aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BuildUnix/Gzip/Makefile.am34
-rw-r--r--BuildUnix/Gzip/Makefile.in325
-rw-r--r--BuildUnix/Makefile.am429
-rw-r--r--BuildUnix/Makefile.in659
-rw-r--r--BuildUnix/aclocal.m4119
-rwxr-xr-xBuildUnix/config.guess951
-rwxr-xr-xBuildUnix/config.sub955
-rwxr-xr-xBuildUnix/configure3974
-rw-r--r--BuildUnix/configure.in394
-rw-r--r--BuildUnix/espws-2.0/Makefile.am33
-rw-r--r--BuildUnix/espws-2.0/Makefile.in348
-rwxr-xr-xBuildUnix/install-sh250
-rw-r--r--BuildUnix/jpeg/Makefile.am84
-rw-r--r--BuildUnix/jpeg/Makefile.in343
-rwxr-xr-xBuildUnix/missing188
-rwxr-xr-xBuildUnix/mkinstalldirs40
-rw-r--r--Docs/12rollin.pdfbin0 -> 67296 bytes
-rw-r--r--Docs/13hewgil.pdfbin0 -> 41372 bytes
-rw-r--r--Docs/Debugger.html854
-rw-r--r--Docs/POSER Profiler.rtf522
-rw-r--r--Docs/UsingPalmOSEmulator.pdfbin0 -> 1543509 bytes
-rw-r--r--Docs/_Bugs.txt116
-rw-r--r--Docs/_Building.txt153
-rw-r--r--Docs/_Contributing.txt176
-rw-r--r--Docs/_Credits.txt219
-rw-r--r--Docs/_GPL.txt340
-rw-r--r--Docs/_News.txt71
-rw-r--r--Docs/_OldNews.txt6094
-rw-r--r--Docs/_ReadMe.txt108
-rw-r--r--Docs/_ToDo.txt16
-rw-r--r--ROMTransfer/Resources/ROM_Transfer.rcp43
-rw-r--r--ROMTransfer/Resources/ROM_Transfer.rsrc0
-rw-r--r--ROMTransfer/Resources/ROM_Transfer.rsrc.c22
-rw-r--r--ROMTransfer/Resources/ROM_Transfer.rsrc.h50
-rw-r--r--ROMTransfer/Resources/ROM_Transfer_icon.pbitm32
-rw-r--r--ROMTransfer/Source/Makefile27
-rwxr-xr-xROMTransfer/Source/ROM_Transferbin0 -> 137999 bytes
-rw-r--r--ROMTransfer/Source/ROM_Transfer.c768
-rw-r--r--ROMTransfer/Source/ROM_Transfer.h55
-rw-r--r--ROMTransfer/Source/ROM_Transfer.prcbin0 -> 4958 bytes
-rw-r--r--ROMTransfer/Source/SerialPortTools.c388
-rw-r--r--ROMTransfer/Source/SerialPortTools.h52
-rw-r--r--Scripting/Perl/EmFunctions.pm1023
-rw-r--r--Scripting/Perl/EmRPC.pm1285
-rw-r--r--Scripting/Perl/EmSysTraps.pm997
-rw-r--r--Scripting/Perl/EmUtils.pm228
-rwxr-xr-xScripting/Perl/FormSpy.pl98
-rw-r--r--Scripting/Perl/HostControl.pm897
-rw-r--r--Scripting/Perl/HostControlTest.pl87
-rwxr-xr-xScripting/Perl/ListDatabases.pl30
-rwxr-xr-xScripting/Perl/ListOpenDatabases.pl53
-rw-r--r--Scripting/Perl/MakeSysTraps.pl88
-rwxr-xr-xScripting/Perl/PoserRPC.pl313
-rwxr-xr-xScripting/Perl/SkipStartup.pl43
-rw-r--r--Scripting/Python/Poser.py471
-rw-r--r--Scripting/Python/SysTraps.py895
-rw-r--r--Scripting/Python/Test.py132
-rw-r--r--SrcShared/ATraps.cpp453
-rw-r--r--SrcShared/ATraps.h58
-rw-r--r--SrcShared/Byteswapping.cpp488
-rw-r--r--SrcShared/Byteswapping.h175
-rw-r--r--SrcShared/CGremlins.cpp2336
-rw-r--r--SrcShared/CGremlins.h94
-rw-r--r--SrcShared/CGremlinsStubs.cpp279
-rw-r--r--SrcShared/CGremlinsStubs.h39
-rw-r--r--SrcShared/ChunkFile.cpp830
-rw-r--r--SrcShared/ChunkFile.h131
-rw-r--r--SrcShared/DebugMgr.cpp2098
-rw-r--r--SrcShared/DebugMgr.h209
-rw-r--r--SrcShared/EcmIf.h388
-rw-r--r--SrcShared/EcmObject.h191
-rw-r--r--SrcShared/EmAction.cpp166
-rw-r--r--SrcShared/EmAction.h73
-rw-r--r--SrcShared/EmApplication.cpp1160
-rw-r--r--SrcShared/EmApplication.h244
-rw-r--r--SrcShared/EmAssert.h45
-rw-r--r--SrcShared/EmCommands.h114
-rw-r--r--SrcShared/EmCommon.cpp14
-rw-r--r--SrcShared/EmCommon.h141
-rw-r--r--SrcShared/EmDevice.cpp1374
-rw-r--r--SrcShared/EmDevice.h84
-rw-r--r--SrcShared/EmDirRef.cpp15
-rw-r--r--SrcShared/EmDirRef.h91
-rw-r--r--SrcShared/EmDlg.cpp6319
-rw-r--r--SrcShared/EmDlg.h922
-rw-r--r--SrcShared/EmDocument.cpp1211
-rw-r--r--SrcShared/EmDocument.h188
-rw-r--r--SrcShared/EmErrCodes.h117
-rw-r--r--SrcShared/EmEventOutput.cpp2012
-rw-r--r--SrcShared/EmEventOutput.h240
-rw-r--r--SrcShared/EmEventPlayback.cpp1443
-rw-r--r--SrcShared/EmEventPlayback.h200
-rw-r--r--SrcShared/EmException.cpp242
-rw-r--r--SrcShared/EmException.h96
-rw-r--r--SrcShared/EmExgMgr.cpp681
-rw-r--r--SrcShared/EmExgMgr.h106
-rw-r--r--SrcShared/EmFileImport.cpp1823
-rw-r--r--SrcShared/EmFileImport.h96
-rw-r--r--SrcShared/EmFileRef.cpp57
-rw-r--r--SrcShared/EmFileRef.h137
-rw-r--r--SrcShared/EmJPEG.cpp902
-rw-r--r--SrcShared/EmJPEG.h167
-rw-r--r--SrcShared/EmLowMem.cpp273
-rw-r--r--SrcShared/EmLowMem.h41
-rw-r--r--SrcShared/EmMapFile.cpp144
-rw-r--r--SrcShared/EmMapFile.h37
-rw-r--r--SrcShared/EmMenus.cpp1274
-rw-r--r--SrcShared/EmMenus.h190
-rw-r--r--SrcShared/EmMinimize.cpp1310
-rw-r--r--SrcShared/EmMinimize.h133
-rw-r--r--SrcShared/EmPalmFunction.cpp2046
-rw-r--r--SrcShared/EmPalmFunction.h188
-rw-r--r--SrcShared/EmPalmHeap.cpp2263
-rw-r--r--SrcShared/EmPalmHeap.h373
-rw-r--r--SrcShared/EmPalmOS.cpp1752
-rw-r--r--SrcShared/EmPalmOS.h110
-rw-r--r--SrcShared/EmPalmStructs.cpp100
-rw-r--r--SrcShared/EmPalmStructs.h1136
-rw-r--r--SrcShared/EmPalmStructs.i3709
-rw-r--r--SrcShared/EmPixMap.cpp2500
-rw-r--r--SrcShared/EmPixMap.h104
-rw-r--r--SrcShared/EmPoint.cpp316
-rw-r--r--SrcShared/EmPoint.h262
-rw-r--r--SrcShared/EmQuantizer.cpp328
-rw-r--r--SrcShared/EmQuantizer.h52
-rw-r--r--SrcShared/EmROMReader.cpp868
-rw-r--r--SrcShared/EmROMReader.h260
-rw-r--r--SrcShared/EmROMTransfer.cpp770
-rw-r--r--SrcShared/EmROMTransfer.h79
-rw-r--r--SrcShared/EmRPC.cpp451
-rw-r--r--SrcShared/EmRPC.h47
-rw-r--r--SrcShared/EmRect.cpp1047
-rw-r--r--SrcShared/EmRect.h389
-rw-r--r--SrcShared/EmRefCounted.cpp15
-rw-r--r--SrcShared/EmRefCounted.h278
-rw-r--r--SrcShared/EmRegion.cpp1500
-rw-r--r--SrcShared/EmRegion.h216
-rw-r--r--SrcShared/EmScreen.cpp281
-rw-r--r--SrcShared/EmScreen.h58
-rw-r--r--SrcShared/EmSession.cpp2443
-rw-r--r--SrcShared/EmSession.h728
-rw-r--r--SrcShared/EmStream.cpp591
-rw-r--r--SrcShared/EmStream.h387
-rw-r--r--SrcShared/EmStreamFile.cpp595
-rw-r--r--SrcShared/EmStreamFile.h98
-rw-r--r--SrcShared/EmStructs.h315
-rw-r--r--SrcShared/EmSubroutine.cpp3113
-rw-r--r--SrcShared/EmSubroutine.h377
-rw-r--r--SrcShared/EmThreadSafeQueue.cpp186
-rw-r--r--SrcShared/EmThreadSafeQueue.h49
-rw-r--r--SrcShared/EmTransport.cpp669
-rw-r--r--SrcShared/EmTransport.h143
-rw-r--r--SrcShared/EmTransportSerial.cpp696
-rw-r--r--SrcShared/EmTransportSerial.h134
-rw-r--r--SrcShared/EmTransportSocket.cpp1220
-rw-r--r--SrcShared/EmTransportSocket.h125
-rw-r--r--SrcShared/EmTransportUSB.cpp571
-rw-r--r--SrcShared/EmTransportUSB.h95
-rw-r--r--SrcShared/EmTypes.h100
-rw-r--r--SrcShared/EmWindow.cpp1388
-rw-r--r--SrcShared/EmWindow.h177
-rw-r--r--SrcShared/ErrorHandling.cpp3388
-rw-r--r--SrcShared/ErrorHandling.h515
-rw-r--r--SrcShared/Gzip/COPYING339
-rw-r--r--SrcShared/Gzip/bits.c207
-rw-r--r--SrcShared/Gzip/crypt.h12
-rw-r--r--SrcShared/Gzip/deflate.c763
-rw-r--r--SrcShared/Gzip/gzip.h323
-rw-r--r--SrcShared/Gzip/inflate.c954
-rw-r--r--SrcShared/Gzip/lzw.h42
-rw-r--r--SrcShared/Gzip/revision.h16
-rw-r--r--SrcShared/Gzip/tailor.h328
-rw-r--r--SrcShared/Gzip/trees.c1076
-rw-r--r--SrcShared/Gzip/util.c484
-rw-r--r--SrcShared/Hardware/EmBankDRAM.cpp686
-rw-r--r--SrcShared/Hardware/EmBankDRAM.h49
-rw-r--r--SrcShared/Hardware/EmBankDummy.cpp326
-rw-r--r--SrcShared/Hardware/EmBankDummy.h47
-rw-r--r--SrcShared/Hardware/EmBankMapped.cpp723
-rw-r--r--SrcShared/Hardware/EmBankMapped.h55
-rw-r--r--SrcShared/Hardware/EmBankROM.cpp1617
-rw-r--r--SrcShared/Hardware/EmBankROM.h81
-rw-r--r--SrcShared/Hardware/EmBankRegs.cpp694
-rw-r--r--SrcShared/Hardware/EmBankRegs.h56
-rw-r--r--SrcShared/Hardware/EmBankSRAM.cpp640
-rw-r--r--SrcShared/Hardware/EmBankSRAM.h58
-rw-r--r--SrcShared/Hardware/EmCPU.cpp68
-rw-r--r--SrcShared/Hardware/EmCPU.h69
-rw-r--r--SrcShared/Hardware/EmCPU68K.cpp1849
-rw-r--r--SrcShared/Hardware/EmCPU68K.h334
-rw-r--r--SrcShared/Hardware/EmCPUARM.cpp398
-rw-r--r--SrcShared/Hardware/EmCPUARM.h731
-rw-r--r--SrcShared/Hardware/EmHAL.cpp939
-rw-r--r--SrcShared/Hardware/EmHAL.h164
-rw-r--r--SrcShared/Hardware/EmMemory.cpp1342
-rw-r--r--SrcShared/Hardware/EmMemory.h457
-rw-r--r--SrcShared/Hardware/EmRegs.cpp499
-rw-r--r--SrcShared/Hardware/EmRegs.h77
-rw-r--r--SrcShared/Hardware/EmRegs328.cpp2803
-rw-r--r--SrcShared/Hardware/EmRegs328.h146
-rw-r--r--SrcShared/Hardware/EmRegs328PalmIII.h21
-rw-r--r--SrcShared/Hardware/EmRegs328PalmPilot.cpp82
-rw-r--r--SrcShared/Hardware/EmRegs328PalmPilot.h30
-rw-r--r--SrcShared/Hardware/EmRegs328PalmVII.h21
-rw-r--r--SrcShared/Hardware/EmRegs328Pilot.h21
-rw-r--r--SrcShared/Hardware/EmRegs328Prv.h45
-rw-r--r--SrcShared/Hardware/EmRegs328Symbol1700.cpp121
-rw-r--r--SrcShared/Hardware/EmRegs328Symbol1700.h26
-rw-r--r--SrcShared/Hardware/EmRegsASICSymbol1700.cpp168
-rw-r--r--SrcShared/Hardware/EmRegsASICSymbol1700.h44
-rw-r--r--SrcShared/Hardware/EmRegsEZ.cpp2655
-rw-r--r--SrcShared/Hardware/EmRegsEZ.h143
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmIIIc.cpp222
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmIIIc.h48
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmIIIe.h21
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmIIIx.h21
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmM100.cpp247
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmM100.h41
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmV.cpp179
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmV.h42
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmVII.cpp41
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmVII.h26
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmVIIx.cpp192
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmVIIx.h41
-rw-r--r--SrcShared/Hardware/EmRegsEZPalmVx.h21
-rw-r--r--SrcShared/Hardware/EmRegsEZPrv.h45
-rw-r--r--SrcShared/Hardware/EmRegsEZTRGpro.cpp251
-rw-r--r--SrcShared/Hardware/EmRegsEZTRGpro.h76
-rw-r--r--SrcShared/Hardware/EmRegsEZTemp.cpp18
-rw-r--r--SrcShared/Hardware/EmRegsEZTemp.h18
-rw-r--r--SrcShared/Hardware/EmRegsEZVisor.cpp243
-rw-r--r--SrcShared/Hardware/EmRegsEZVisor.h131
-rw-r--r--SrcShared/Hardware/EmRegsFrameBuffer.cpp241
-rw-r--r--SrcShared/Hardware/EmRegsFrameBuffer.h52
-rw-r--r--SrcShared/Hardware/EmRegsMediaQ11xx.cpp4791
-rw-r--r--SrcShared/Hardware/EmRegsMediaQ11xx.h351
-rw-r--r--SrcShared/Hardware/EmRegsPLDPalmVIIEZ.cpp210
-rw-r--r--SrcShared/Hardware/EmRegsPLDPalmVIIEZ.h51
-rw-r--r--SrcShared/Hardware/EmRegsPrv.h37
-rw-r--r--SrcShared/Hardware/EmRegsSED1375.cpp506
-rw-r--r--SrcShared/Hardware/EmRegsSED1375.h70
-rw-r--r--SrcShared/Hardware/EmRegsSED1376.cpp860
-rw-r--r--SrcShared/Hardware/EmRegsSED1376.h106
-rw-r--r--SrcShared/Hardware/EmRegsSZ.cpp17
-rw-r--r--SrcShared/Hardware/EmRegsSZ.h18
-rw-r--r--SrcShared/Hardware/EmRegsSZPrv.h19
-rw-r--r--SrcShared/Hardware/EmRegsSZTemp.cpp17
-rw-r--r--SrcShared/Hardware/EmRegsSZTemp.h20
-rw-r--r--SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.cpp154
-rw-r--r--SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.h42
-rw-r--r--SrcShared/Hardware/EmRegsUSBVisor.cpp164
-rw-r--r--SrcShared/Hardware/EmRegsUSBVisor.h44
-rw-r--r--SrcShared/Hardware/EmRegsVZ.cpp3116
-rw-r--r--SrcShared/Hardware/EmRegsVZ.h145
-rw-r--r--SrcShared/Hardware/EmRegsVZHandEra330.cpp608
-rw-r--r--SrcShared/Hardware/EmRegsVZHandEra330.h142
-rw-r--r--SrcShared/Hardware/EmRegsVZPalmM500.cpp259
-rw-r--r--SrcShared/Hardware/EmRegsVZPalmM500.h44
-rw-r--r--SrcShared/Hardware/EmRegsVZPalmM505.cpp151
-rw-r--r--SrcShared/Hardware/EmRegsVZPalmM505.h36
-rw-r--r--SrcShared/Hardware/EmRegsVZPrv.h45
-rw-r--r--SrcShared/Hardware/EmRegsVZTemp.cpp848
-rw-r--r--SrcShared/Hardware/EmRegsVZTemp.h130
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorEdge.cpp166
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorEdge.h30
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorPlatinum.cpp262
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorPlatinum.h43
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorPrism.cpp393
-rw-r--r--SrcShared/Hardware/EmRegsVZVisorPrism.h37
-rw-r--r--SrcShared/Hardware/EmSPISlave.cpp51
-rw-r--r--SrcShared/Hardware/EmSPISlave.h28
-rw-r--r--SrcShared/Hardware/EmSPISlaveADS784x.cpp428
-rw-r--r--SrcShared/Hardware/EmSPISlaveADS784x.h97
-rw-r--r--SrcShared/Hardware/EmUAEGlue.cpp166
-rw-r--r--SrcShared/Hardware/EmUAEGlue.h17
-rw-r--r--SrcShared/Hardware/EmUARTDragonball.cpp936
-rw-r--r--SrcShared/Hardware/EmUARTDragonball.h149
-rw-r--r--SrcShared/Hardware/TRG/EmHandEra330Defs.h40
-rw-r--r--SrcShared/Hardware/TRG/EmHandEraCFBus.h28
-rw-r--r--SrcShared/Hardware/TRG/EmHandEraSDBus.h22
-rw-r--r--SrcShared/Hardware/TRG/EmRegs330CPLD.cpp263
-rw-r--r--SrcShared/Hardware/TRG/EmRegs330CPLD.h144
-rw-r--r--SrcShared/Hardware/TRG/EmSPISlave330Current.cpp189
-rw-r--r--SrcShared/Hardware/TRG/EmSPISlave330Current.h51
-rw-r--r--SrcShared/Hardware/TRG/EmTRG.cpp57
-rw-r--r--SrcShared/Hardware/TRG/EmTRG.h23
-rw-r--r--SrcShared/Hardware/TRG/EmTRGATA.cpp471
-rw-r--r--SrcShared/Hardware/TRG/EmTRGATA.h63
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCF.cpp305
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCF.h58
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCFDefs.h187
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCFIO.cpp236
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCFIO.h90
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCFMem.cpp349
-rw-r--r--SrcShared/Hardware/TRG/EmTRGCFMem.h66
-rw-r--r--SrcShared/Hardware/TRG/EmTRGDiskIO.cpp174
-rw-r--r--SrcShared/Hardware/TRG/EmTRGDiskIO.h53
-rw-r--r--SrcShared/Hardware/TRG/EmTRGDiskType.cpp511
-rw-r--r--SrcShared/Hardware/TRG/EmTRGDiskType.h65
-rw-r--r--SrcShared/Hardware/TRG/EmTRGSD.cpp321
-rw-r--r--SrcShared/Hardware/TRG/EmTRGSD.h64
-rw-r--r--SrcShared/Hordes.cpp2437
-rw-r--r--SrcShared/Hordes.h153
-rw-r--r--SrcShared/HostControl.cpp4989
-rw-r--r--SrcShared/HostControl.h938
-rw-r--r--SrcShared/HostControlPrv.h35
-rw-r--r--SrcShared/LoadApplication.cpp381
-rw-r--r--SrcShared/LoadApplication.h22
-rw-r--r--SrcShared/Logging.cpp1547
-rw-r--r--SrcShared/Logging.h222
-rw-r--r--SrcShared/Marshal.cpp1828
-rw-r--r--SrcShared/Marshal.h755
-rw-r--r--SrcShared/MetaMemory.cpp4096
-rw-r--r--SrcShared/MetaMemory.h668
-rw-r--r--SrcShared/Miscellaneous.cpp2954
-rw-r--r--SrcShared/Miscellaneous.h178
-rw-r--r--SrcShared/Palm.h233
-rw-r--r--SrcShared/Palm/Device/328Jerry/IncsPrv/HardwareTD1.h221
-rw-r--r--SrcShared/Palm/Device/EZAustin/IncsPrv/HardwareAustin.h214
-rw-r--r--SrcShared/Palm/Device/EZAustin/IncsPrv/SED1375Hwr.h240
-rw-r--r--SrcShared/Palm/Device/EZSumo/IncsPrv/HardwareEZ.h239
-rw-r--r--SrcShared/Palm/Device/VZTrn/IncsPrv/HardwareVZ.h285
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/Hardware.h156
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/HwrROMToken.h136
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68328Hwr.h644
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68EZ328Hwr.h708
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68SZ328Hwr.h1078
-rw-r--r--SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68VZ328Hwr.h844
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/DataPrv.h308
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/DebugPrv.h439
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/Globals.h574
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/MemoryPrv.h603
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/SerialLinkPrv.h90
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/SysEvtPrv.h227
-rw-r--r--SrcShared/Palm/Platform/Core/System/IncsPrv/SystemPrv.h474
-rw-r--r--SrcShared/Palm/Platform/Core/System/Src/Crc.c257
-rw-r--r--SrcShared/Palm/Platform/Incs/BuildDefaults.h309
-rw-r--r--SrcShared/Palm/Platform/Incs/BuildDefines.h159
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/CoreTraps.h1505
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/Hardware/HAL.h99
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/Hardware/HwrMiscFlags.h220
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/Hardware/M68KHwr.h113
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Bitmap.h151
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/CharAttr.h129
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Chars.h411
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Crc.h63
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/DLCommon.h2433
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/DLServer.h418
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/DataMgr.h540
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/DateTime.h283
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/ErrorBase.h294
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/FeatureMgr.h89
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Font.h150
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/IntlMgr.h113
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/KeyMgr.h76
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/LocaleMgr.h230
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Localize.h54
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/MemoryMgr.h341
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/NetBitUtils.h135
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/NetMgr.h1515
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/OverlayMgr.h214
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/PalmLocale.h1258
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/PenMgr.h98
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Preferences.h428
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Rect.h83
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SerialLinkMgr.h437
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SerialMgr.h371
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SoundMgr.h317
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SysEvent.h204
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SysEvtMgr.h252
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SystemMgr.h1191
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SystemPkt.h430
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/SystemResources.h346
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/TextMgr.h411
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/System/Window.h559
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/AttentionMgr.h209
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Control.h188
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Event.h347
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/FatalAlert.h43
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Field.h275
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Find.h124
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Form.h510
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/InsPoint.h60
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/List.h134
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/ScrollBar.h77
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/Table.h319
-rw-r--r--SrcShared/Palm/Platform/Incs/Core/UI/UIResources.h322
-rw-r--r--SrcShared/Palm/Platform/Incs/Libraries/LibTraps.h43
-rw-r--r--SrcShared/Palm/Platform/Incs/PalmTypes.h303
-rw-r--r--SrcShared/PalmOptErrorCheckLevel.h28
-rw-r--r--SrcShared/PalmPack.h25
-rw-r--r--SrcShared/PalmPackPop.h24
-rw-r--r--SrcShared/Patches/EmPatchIf.h150
-rw-r--r--SrcShared/Patches/EmPatchLoader.cpp129
-rw-r--r--SrcShared/Patches/EmPatchLoader.h74
-rw-r--r--SrcShared/Patches/EmPatchMgr.cpp1203
-rw-r--r--SrcShared/Patches/EmPatchMgr.h103
-rw-r--r--SrcShared/Patches/EmPatchModule.cpp318
-rw-r--r--SrcShared/Patches/EmPatchModule.h118
-rw-r--r--SrcShared/Patches/EmPatchModuleHtal.cpp89
-rw-r--r--SrcShared/Patches/EmPatchModuleHtal.h30
-rw-r--r--SrcShared/Patches/EmPatchModuleMap.cpp146
-rw-r--r--SrcShared/Patches/EmPatchModuleMap.h100
-rw-r--r--SrcShared/Patches/EmPatchModuleMemMgr.cpp1902
-rw-r--r--SrcShared/Patches/EmPatchModuleNetLib.cpp4100
-rw-r--r--SrcShared/Patches/EmPatchModuleNetLib.h27
-rw-r--r--SrcShared/Patches/EmPatchModuleSys.cpp3217
-rw-r--r--SrcShared/Patches/EmPatchModuleSys.h271
-rw-r--r--SrcShared/Patches/EmPatchModuleTypes.h94
-rw-r--r--SrcShared/Patches/EmPatchState.cpp1034
-rw-r--r--SrcShared/Patches/EmPatchState.h264
-rw-r--r--SrcShared/Platform.h218
-rw-r--r--SrcShared/Platform_NetLib.h100
-rw-r--r--SrcShared/Platform_NetLib_Sck.cpp3436
-rw-r--r--SrcShared/PreferenceMgr.cpp2564
-rw-r--r--SrcShared/PreferenceMgr.h409
-rw-r--r--SrcShared/Profiling.cpp2111
-rw-r--r--SrcShared/Profiling.h333
-rw-r--r--SrcShared/ROMStubs.cpp3220
-rw-r--r--SrcShared/ROMStubs.h191
-rw-r--r--SrcShared/SLP.cpp1074
-rw-r--r--SrcShared/SLP.h74
-rw-r--r--SrcShared/SessionFile.cpp1142
-rw-r--r--SrcShared/SessionFile.h257
-rw-r--r--SrcShared/Skins.cpp1485
-rw-r--r--SrcShared/Skins.h95
-rw-r--r--SrcShared/SocketMessaging.cpp1170
-rw-r--r--SrcShared/SocketMessaging.h95
-rw-r--r--SrcShared/Startup.cpp1642
-rw-r--r--SrcShared/Startup.h88
-rw-r--r--SrcShared/String2193
-rw-r--r--SrcShared/StringConversions.cpp370
-rw-r--r--SrcShared/StringConversions.h78
-rw-r--r--SrcShared/StringData.cpp265
-rw-r--r--SrcShared/StringData.h25
-rw-r--r--SrcShared/Strings.r.h549
-rw-r--r--SrcShared/Strings.txt7302
-rw-r--r--SrcShared/Switches.h267
-rw-r--r--SrcShared/SystemPacket.cpp1282
-rw-r--r--SrcShared/SystemPacket.h52
-rw-r--r--SrcShared/TracerCommon.cpp310
-rw-r--r--SrcShared/TracerCommon.h88
-rw-r--r--SrcShared/TracerPlatform.h57
-rw-r--r--SrcShared/UAE/UAE.h21
-rw-r--r--SrcShared/UAE/build68k.c246
-rw-r--r--SrcShared/UAE/compiler.h106
-rw-r--r--SrcShared/UAE/config.h77
-rw-r--r--SrcShared/UAE/cpudefs.c173
-rw-r--r--SrcShared/UAE/cpuemu.c24243
-rw-r--r--SrcShared/UAE/cpuemu1.c53
-rw-r--r--SrcShared/UAE/cpuemu2.c53
-rw-r--r--SrcShared/UAE/cpuemu3.c53
-rw-r--r--SrcShared/UAE/cpuemu4.c53
-rw-r--r--SrcShared/UAE/cpuemu5.c53
-rw-r--r--SrcShared/UAE/cpuemu6.c53
-rw-r--r--SrcShared/UAE/cpuemu7.c53
-rw-r--r--SrcShared/UAE/cpuemu8.c53
-rw-r--r--SrcShared/UAE/cpustbl.c1590
-rw-r--r--SrcShared/UAE/cputbl.h1584
-rw-r--r--SrcShared/UAE/custom.h30
-rw-r--r--SrcShared/UAE/gencpu.c3346
-rw-r--r--SrcShared/UAE/machdep_m68k.h56
-rw-r--r--SrcShared/UAE/machdep_maccess.h27
-rw-r--r--SrcShared/UAE/memory_cpu.h13
-rw-r--r--SrcShared/UAE/missing.c36
-rw-r--r--SrcShared/UAE/newcpu.h230
-rw-r--r--SrcShared/UAE/options.h30
-rw-r--r--SrcShared/UAE/readcpu.cpp808
-rw-r--r--SrcShared/UAE/readcpu.h113
-rw-r--r--SrcShared/UAE/sysconfig.h33
-rw-r--r--SrcShared/UAE/sysdeps.h348
-rw-r--r--SrcShared/UAE/table68k242
-rw-r--r--SrcShared/UAE/target.h4
-rw-r--r--SrcShared/jpeg/cderror.h132
-rw-r--r--SrcShared/jpeg/jcapimin.c280
-rw-r--r--SrcShared/jpeg/jcapistd.c161
-rw-r--r--SrcShared/jpeg/jccoefct.c449
-rw-r--r--SrcShared/jpeg/jccolor.c459
-rw-r--r--SrcShared/jpeg/jcdctmgr.c387
-rw-r--r--SrcShared/jpeg/jchuff.c909
-rw-r--r--SrcShared/jpeg/jchuff.h47
-rw-r--r--SrcShared/jpeg/jcinit.c72
-rw-r--r--SrcShared/jpeg/jcmainct.c293
-rw-r--r--SrcShared/jpeg/jcmarker.c664
-rw-r--r--SrcShared/jpeg/jcmaster.c590
-rw-r--r--SrcShared/jpeg/jcomapi.c106
-rw-r--r--SrcShared/jpeg/jcparam.c610
-rw-r--r--SrcShared/jpeg/jcphuff.c833
-rw-r--r--SrcShared/jpeg/jcprepct.c354
-rw-r--r--SrcShared/jpeg/jcsample.c519
-rw-r--r--SrcShared/jpeg/jctrans.c388
-rw-r--r--SrcShared/jpeg/jdapimin.c395
-rw-r--r--SrcShared/jpeg/jdapistd.c275
-rw-r--r--SrcShared/jpeg/jdatadst.c151
-rw-r--r--SrcShared/jpeg/jdatasrc.c212
-rw-r--r--SrcShared/jpeg/jdcoefct.c736
-rw-r--r--SrcShared/jpeg/jdcolor.c396
-rw-r--r--SrcShared/jpeg/jdct.h176
-rw-r--r--SrcShared/jpeg/jddctmgr.c269
-rw-r--r--SrcShared/jpeg/jdhuff.c651
-rw-r--r--SrcShared/jpeg/jdhuff.h201
-rw-r--r--SrcShared/jpeg/jdinput.c381
-rw-r--r--SrcShared/jpeg/jdmainct.c512
-rw-r--r--SrcShared/jpeg/jdmarker.c1360
-rw-r--r--SrcShared/jpeg/jdmaster.c557
-rw-r--r--SrcShared/jpeg/jdmerge.c400
-rw-r--r--SrcShared/jpeg/jdphuff.c668
-rw-r--r--SrcShared/jpeg/jdpostct.c290
-rw-r--r--SrcShared/jpeg/jdsample.c478
-rw-r--r--SrcShared/jpeg/jdtrans.c143
-rw-r--r--SrcShared/jpeg/jerror.c252
-rw-r--r--SrcShared/jpeg/jerror.h291
-rw-r--r--SrcShared/jpeg/jfdctflt.c168
-rw-r--r--SrcShared/jpeg/jfdctfst.c224
-rw-r--r--SrcShared/jpeg/jfdctint.c283
-rw-r--r--SrcShared/jpeg/jidctflt.c242
-rw-r--r--SrcShared/jpeg/jidctfst.c368
-rw-r--r--SrcShared/jpeg/jidctint.c389
-rw-r--r--SrcShared/jpeg/jidctred.c398
-rw-r--r--SrcShared/jpeg/jinclude.h91
-rw-r--r--SrcShared/jpeg/jmemmac.c383
-rw-r--r--SrcShared/jpeg/jmemmgr.c1118
-rw-r--r--SrcShared/jpeg/jmemnobs.c109
-rw-r--r--SrcShared/jpeg/jmemsys.h198
-rw-r--r--SrcShared/jpeg/jmorecfg.h363
-rw-r--r--SrcShared/jpeg/jpegint.h392
-rw-r--r--SrcShared/jpeg/jpeglib.h1096
-rw-r--r--SrcShared/jpeg/jquant1.c856
-rw-r--r--SrcShared/jpeg/jquant2.c1310
-rw-r--r--SrcShared/jpeg/jutils.c179
-rw-r--r--SrcShared/jpeg/jversion.h14
-rw-r--r--SrcShared/omnithread/mach.cpp643
-rw-r--r--SrcShared/omnithread/mach.h51
-rw-r--r--SrcShared/omnithread/nt.cpp876
-rw-r--r--SrcShared/omnithread/nt.h65
-rw-r--r--SrcShared/omnithread/null_thread.cpp335
-rw-r--r--SrcShared/omnithread/null_thread.h40
-rw-r--r--SrcShared/omnithread/omnithread.h542
-rw-r--r--SrcShared/omnithread/posix.cpp898
-rw-r--r--SrcShared/omnithread/posix.h57
-rw-r--r--SrcShared/omnithread/solaris.cpp533
-rw-r--r--SrcShared/omnithread/solaris.h47
-rw-r--r--SrcShared/xstring2638
-rw-r--r--SrcUnix/DefaultLarge.xpm732
-rw-r--r--SrcUnix/DefaultSmall.xpm401
-rw-r--r--SrcUnix/EmApplicationFltk.cpp494
-rw-r--r--SrcUnix/EmApplicationFltk.h50
-rw-r--r--SrcUnix/EmCommonUnix.h90
-rw-r--r--SrcUnix/EmDirRefUnix.cpp506
-rw-r--r--SrcUnix/EmDirRefUnix.h19
-rw-r--r--SrcUnix/EmDlgFltk.cpp2497
-rw-r--r--SrcUnix/EmDlgFltk.h62
-rw-r--r--SrcUnix/EmDlgFltkFactory.fl1157
-rw-r--r--SrcUnix/EmDocumentUnix.cpp142
-rw-r--r--SrcUnix/EmDocumentUnix.h40
-rw-r--r--SrcUnix/EmFileRefUnix.cpp547
-rw-r--r--SrcUnix/EmFileRefUnix.h19
-rw-r--r--SrcUnix/EmMenusFltk.cpp94
-rw-r--r--SrcUnix/EmMenusFltk.h25
-rw-r--r--SrcUnix/EmPixMapUnix.cpp48
-rw-r--r--SrcUnix/EmPixMapUnix.h22
-rw-r--r--SrcUnix/EmTransportSerialUnix.cpp1211
-rw-r--r--SrcUnix/EmTransportSerialUnix.h68
-rw-r--r--SrcUnix/EmTransportUSBUnix.cpp394
-rw-r--r--SrcUnix/EmTransportUSBUnix.h36
-rw-r--r--SrcUnix/EmWindowFltk.cpp777
-rw-r--r--SrcUnix/EmWindowFltk.h78
-rw-r--r--SrcUnix/Platform_Unix.cpp850
-rw-r--r--SrcUnix/ResStrings.h19
-rw-r--r--SrcUnix/espws-2.0/CheckButton.cxx113
-rw-r--r--SrcUnix/espws-2.0/CheckButton.h52
-rw-r--r--SrcUnix/espws-2.0/CheckButton.html61
-rw-r--r--SrcUnix/espws-2.0/FileBrowser.cxx518
-rw-r--r--SrcUnix/espws-2.0/FileBrowser.h71
-rw-r--r--SrcUnix/espws-2.0/FileBrowser.html79
-rw-r--r--SrcUnix/espws-2.0/FileChooser.cxx249
-rw-r--r--SrcUnix/espws-2.0/FileChooser.fl189
-rw-r--r--SrcUnix/espws-2.0/FileChooser.gifbin0 -> 10760 bytes
-rw-r--r--SrcUnix/espws-2.0/FileChooser.h82
-rw-r--r--SrcUnix/espws-2.0/FileChooser.html172
-rw-r--r--SrcUnix/espws-2.0/FileChooser2.cxx645
-rw-r--r--SrcUnix/espws-2.0/FileIcon.cxx1217
-rw-r--r--SrcUnix/espws-2.0/FileIcon.h112
-rw-r--r--SrcUnix/espws-2.0/FileIcon.html165
-rw-r--r--SrcUnix/espws-2.0/FileInput.cxx75
-rw-r--r--SrcUnix/espws-2.0/FileInput.h52
-rw-r--r--SrcUnix/espws-2.0/FileInput.html56
-rw-r--r--SrcUnix/espws-2.0/Fl_Wizard.cxx201
-rw-r--r--SrcUnix/espws-2.0/Fl_Wizard.h59
-rw-r--r--SrcUnix/espws-2.0/Fl_Wizard.html75
-rw-r--r--SrcUnix/espws-2.0/HelpApp.cxx470
-rw-r--r--SrcUnix/espws-2.0/HelpApp.fl380
-rw-r--r--SrcUnix/espws-2.0/HelpApp.gifbin0 -> 7556 bytes
-rw-r--r--SrcUnix/espws-2.0/HelpApp.h135
-rw-r--r--SrcUnix/espws-2.0/HelpApp2.cxx546
-rw-r--r--SrcUnix/espws-2.0/HelpDialog.cxx219
-rw-r--r--SrcUnix/espws-2.0/HelpDialog.fl188
-rw-r--r--SrcUnix/espws-2.0/HelpDialog.gifbin0 -> 12984 bytes
-rw-r--r--SrcUnix/espws-2.0/HelpDialog.h53
-rw-r--r--SrcUnix/espws-2.0/HelpDialog.html89
-rw-r--r--SrcUnix/espws-2.0/HelpView.cxx1799
-rw-r--r--SrcUnix/espws-2.0/HelpView.h180
-rw-r--r--SrcUnix/espws-2.0/HelpView.html130
-rw-r--r--SrcUnix/espws-2.0/Makefile.in121
-rw-r--r--SrcUnix/espws-2.0/allfiles.xbm6
-rwxr-xr-xSrcUnix/espws-2.0/configure1865
-rw-r--r--SrcUnix/espws-2.0/configure.in69
-rw-r--r--SrcUnix/espws-2.0/documentation.html73
-rw-r--r--SrcUnix/espws-2.0/download.html54
-rw-r--r--SrcUnix/espws-2.0/espws.book18
-rw-r--r--SrcUnix/espws-2.0/espws.pdf1378
-rw-r--r--SrcUnix/espws-2.0/file.html76
-rw-r--r--SrcUnix/espws-2.0/flsurf.cxx67
-rw-r--r--SrcUnix/espws-2.0/flsurf.gifbin0 -> 4849 bytes
-rw-r--r--SrcUnix/espws-2.0/flsurf.html66
-rw-r--r--SrcUnix/espws-2.0/fltk.css6
-rw-r--r--SrcUnix/espws-2.0/help.html44
-rw-r--r--SrcUnix/espws-2.0/home.xbm6
-rw-r--r--SrcUnix/espws-2.0/index.html57
-rw-r--r--SrcUnix/espws-2.0/intro.html57
-rw-r--r--SrcUnix/espws-2.0/navbar.gifbin0 -> 2367 bytes
-rw-r--r--SrcUnix/espws-2.0/new.xbm6
-rw-r--r--SrcUnix/espws-2.0/next.xbm12
-rw-r--r--SrcUnix/espws-2.0/prev.xbm12
-rw-r--r--SrcUnix/espws-2.0/relnotes.html209
-rw-r--r--SrcUnix/espws-2.0/reload.xbm6
-rw-r--r--SrcUnix/espws-2.0/reset.xbm4
-rw-r--r--SrcUnix/espws-2.0/stop.xbm6
-rw-r--r--SrcUnix/espws-2.0/testfile.cxx141
-rw-r--r--SrcUnix/espws-2.0/testhelp.cxx66
-rw-r--r--SrcUnix/espws-2.0/up.xbm6
-rw-r--r--SrcUnix/espws-2.0/widgets.html61
-rw-r--r--SrcUnix/espws.diff139
-rw-r--r--SrcUnix/jconfig.h46
-rw-r--r--SrcUnix/poser.xpm54
-rw-r--r--Tools/Strings2Resource.pl248
-rwxr-xr-xTools/s2r.sh6
637 files changed, 320876 insertions, 0 deletions
diff --git a/BuildUnix/Gzip/Makefile.am b/BuildUnix/Gzip/Makefile.am
new file mode 100644
index 0000000..ca9c89d
--- /dev/null
+++ b/BuildUnix/Gzip/Makefile.am
@@ -0,0 +1,34 @@
+## ======================================================================================
+## Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+## All rights reserved.
+## ======================================================================================
+
+##
+## makefile.am for poser-specific gzip code
+##
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../../SrcShared/Gzip:
+
+## no subdir specific flags needed -- just go with globals
+LOCAL_CFLAGS =
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS)
+
+INCLUDES = -I$(srcdir)/../../SrcShared/Gzip
+
+noinst_LIBRARIES = libposergzip.a
+
+SRC_GZIP = bits.c \
+ crypt.h \
+ deflate.c \
+ gzip.h \
+ inflate.c \
+ lzw.h \
+ revision.h \
+ tailor.h \
+ trees.c \
+ util.c
+
+libposergzip_a_SOURCES = $(SRC_GZIP)
diff --git a/BuildUnix/Gzip/Makefile.in b/BuildUnix/Gzip/Makefile.in
new file mode 100644
index 0000000..8ea21bb
--- /dev/null
+++ b/BuildUnix/Gzip/Makefile.in
@@ -0,0 +1,325 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+CC = @CC@
+CPP = @CPP@
+CXX = @CXX@
+GLLIB = @GLLIB@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+POSER_CFLAGS = @POSER_CFLAGS@
+POSER_CXXFLAGS = @POSER_CXXFLAGS@
+RANLIB = @RANLIB@
+THREAD_FLAGS = @THREAD_FLAGS@
+THREAD_LIBS = @THREAD_LIBS@
+THREAD_SRC = @THREAD_SRC@
+VERSION = @VERSION@
+
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../../SrcShared/Gzip:
+
+LOCAL_CFLAGS =
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS)
+
+INCLUDES = -I$(srcdir)/../../SrcShared/Gzip
+
+noinst_LIBRARIES = libposergzip.a
+
+SRC_GZIP = bits.c crypt.h deflate.c gzip.h inflate.c lzw.h revision.h tailor.h trees.c util.c
+
+
+libposergzip_a_SOURCES = $(SRC_GZIP)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libposergzip_a_LIBADD =
+libposergzip_a_OBJECTS = bits.o deflate.o inflate.o trees.o util.o
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/bits.P .deps/deflate.P .deps/inflate.P .deps/trees.P \
+.deps/util.P
+SOURCES = $(libposergzip_a_SOURCES)
+OBJECTS = $(libposergzip_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cpp .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign Gzip/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libposergzip.a: $(libposergzip_a_OBJECTS) $(libposergzip_a_DEPENDENCIES)
+ -rm -f libposergzip.a
+ $(AR) cru libposergzip.a $(libposergzip_a_OBJECTS) $(libposergzip_a_LIBADD)
+ $(RANLIB) libposergzip.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = Gzip
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Gzip/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/BuildUnix/Makefile.am b/BuildUnix/Makefile.am
new file mode 100644
index 0000000..6ec3173
--- /dev/null
+++ b/BuildUnix/Makefile.am
@@ -0,0 +1,429 @@
+## -*- mode: Makefile; tab-width: 4; -*-
+## ======================================================================================
+## Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+## All rights reserved.
+## ======================================================================================
+
+SUBDIRS = Gzip jpeg espws-2.0
+
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../SrcUnix: \
+ $(srcdir)/../SrcShared: \
+ $(srcdir)/../SrcShared/Hardware: \
+ $(srcdir)/../SrcShared/Hardware/TRG: \
+ $(srcdir)/../SrcShared/omnithread: \
+ $(srcdir)/../SrcShared/Palm/Platform/Core/System/Src: \
+ $(srcdir)/../SrcShared/Patches: \
+ $(srcdir)/../SrcShared/UAE:
+
+
+## POSER_CFLAGS and POSER_CXXFLAGS defined by configure.in.
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS) $(FLAGS) $(THREAD_FLAGS) $(X_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS) $(FLAGS) $(THREAD_FLAGS) $(X_CFLAGS)
+
+INCLUDES = -I$(srcdir)/../SrcShared
+INCLUDES += -I$(srcdir)/../SrcShared/Hardware
+INCLUDES += -I$(srcdir)/../SrcShared/Hardware/TRG
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Device
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Core/Hardware/IncsPrv
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Core/System/IncsPrv
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/Hardware
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/System
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/UI
+INCLUDES += -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Libraries
+INCLUDES += -I$(srcdir)/../SrcShared/Gzip
+INCLUDES += -I$(srcdir)/../SrcShared/jpeg
+INCLUDES += -I$(srcdir)/../SrcShared/omnithread
+INCLUDES += -I$(srcdir)/../SrcShared/Patches
+INCLUDES += -I$(srcdir)/../SrcShared/UAE
+INCLUDES += -I$(srcdir)/../SrcUnix
+INCLUDES += -I$(srcdir)/../SrcUnix/espws-2.0
+
+SRC_UNIX = EmApplicationFltk.cpp \
+ EmApplicationFltk.h \
+ EmCommonUnix.h \
+ EmDirRefUnix.cpp \
+ EmDirRefUnix.h \
+ EmDlgFltk.cpp \
+ EmDlgFltk.h \
+ EmDocumentUnix.cpp \
+ EmDocumentUnix.h \
+ EmFileRefUnix.cpp \
+ EmFileRefUnix.h \
+ EmMenusFltk.cpp \
+ EmMenusFltk.h \
+ EmPixMapUnix.cpp \
+ EmPixMapUnix.h \
+ EmTransportSerialUnix.cpp \
+ EmTransportSerialUnix.h \
+ EmTransportUSBUnix.cpp \
+ EmTransportUSBUnix.h \
+ EmWindowFltk.cpp \
+ EmWindowFltk.h \
+ Platform_Unix.cpp \
+ jconfig.h
+
+SRC_UNIX_GEN = ResStrings.cpp \
+ EmDlgFltkFactory.h \
+ EmDlgFltkFactory.cpp
+
+SRC_SHARED = ATraps.cpp \
+ ATraps.h \
+ Byteswapping.cpp \
+ Byteswapping.h \
+ CGremlins.cpp \
+ CGremlins.h \
+ CGremlinsStubs.cpp \
+ CGremlinsStubs.h \
+ ChunkFile.cpp \
+ ChunkFile.h \
+ DebugMgr.cpp \
+ DebugMgr.h \
+ EcmIf.h \
+ EcmObject.h \
+ EmAction.cpp \
+ EmAction.h \
+ EmApplication.cpp \
+ EmApplication.h \
+ EmCommands.h \
+ EmCommon.cpp \
+ EmCommon.h \
+ EmDevice.cpp \
+ EmDevice.h \
+ EmDirRef.cpp \
+ EmDirRef.h \
+ EmDlg.cpp \
+ EmDlg.h \
+ EmDocument.cpp \
+ EmDocument.h \
+ EmErrCodes.h \
+ EmEventOutput.cpp \
+ EmEventOutput.h \
+ EmEventPlayback.cpp \
+ EmEventPlayback.h \
+ EmException.cpp \
+ EmException.h \
+ EmExgMgr.cpp \
+ EmExgMgr.h \
+ EmFileImport.cpp \
+ EmFileImport.h \
+ EmFileRef.cpp \
+ EmFileRef.h \
+ EmJPEG.cpp \
+ EmJPEG.h \
+ EmLowMem.cpp \
+ EmLowMem.h \
+ EmMapFile.cpp \
+ EmMapFile.h \
+ EmMenus.cpp \
+ EmMenus.h \
+ EmMinimize.cpp \
+ EmMinimize.h \
+ EmPalmFunction.cpp \
+ EmPalmFunction.h \
+ EmPalmHeap.cpp \
+ EmPalmHeap.h \
+ EmPalmOS.cpp \
+ EmPalmOS.h \
+ EmPalmStructs.cpp \
+ EmPalmStructs.h \
+ EmPalmStructs.i \
+ EmPixMap.cpp \
+ EmPixMap.h \
+ EmPoint.cpp \
+ EmPoint.h \
+ EmQuantizer.cpp \
+ EmQuantizer.h \
+ EmRect.cpp \
+ EmRect.h \
+ EmRefCounted.cpp \
+ EmRefCounted.h \
+ EmRegion.cpp \
+ EmRegion.h \
+ EmROMReader.cpp \
+ EmROMReader.h \
+ EmROMTransfer.cpp \
+ EmROMTransfer.h \
+ EmRPC.cpp \
+ EmRPC.h \
+ EmScreen.cpp \
+ EmScreen.h \
+ EmSession.cpp \
+ EmSession.h \
+ EmStream.cpp \
+ EmStream.h \
+ EmStreamFile.cpp \
+ EmStreamFile.h \
+ EmStructs.h \
+ EmSubroutine.cpp \
+ EmSubroutine.h \
+ EmThreadSafeQueue.cpp \
+ EmThreadSafeQueue.h \
+ EmTransport.cpp \
+ EmTransport.h \
+ EmTransportSerial.cpp \
+ EmTransportSerial.h \
+ EmTransportSocket.cpp \
+ EmTransportSocket.h \
+ EmTransportUSB.cpp \
+ EmTransportUSB.h \
+ EmTypes.h \
+ EmWindow.cpp \
+ EmWindow.h \
+ ErrorHandling.cpp \
+ ErrorHandling.h \
+ Hordes.cpp \
+ Hordes.h \
+ HostControl.cpp \
+ HostControl.h \
+ HostControlPrv.h \
+ LoadApplication.cpp \
+ LoadApplication.h \
+ Logging.cpp \
+ Logging.h \
+ Marshal.cpp \
+ Marshal.h \
+ MetaMemory.cpp \
+ MetaMemory.h \
+ Miscellaneous.cpp \
+ Miscellaneous.h \
+ Palm.h \
+ PalmOptErrorCheckLevel.h \
+ PalmPack.h \
+ PalmPackPop.h \
+ Platform.h \
+ Platform_NetLib.h \
+ Platform_NetLib_Sck.cpp \
+ PreferenceMgr.cpp \
+ PreferenceMgr.h \
+ Profiling.cpp \
+ Profiling.h \
+ ROMStubs.cpp \
+ ROMStubs.h \
+ SLP.cpp \
+ SLP.h \
+ SessionFile.cpp \
+ SessionFile.h \
+ Skins.cpp \
+ Skins.h \
+ SocketMessaging.cpp \
+ SocketMessaging.h \
+ Startup.cpp \
+ Startup.h \
+ StringConversions.cpp \
+ StringConversions.h \
+ StringData.cpp \
+ StringData.h \
+ SystemPacket.cpp \
+ SystemPacket.h
+
+
+SRC_SHARED_HARDWARE = \
+ EmBankDRAM.cpp \
+ EmBankDRAM.h \
+ EmBankDummy.cpp \
+ EmBankDummy.h \
+ EmBankMapped.cpp \
+ EmBankMapped.h \
+ EmBankROM.cpp \
+ EmBankROM.h \
+ EmBankRegs.cpp \
+ EmBankRegs.h \
+ EmBankSRAM.cpp \
+ EmBankSRAM.h \
+ EmCPU.cpp \
+ EmCPU.h \
+ EmCPU68K.cpp \
+ EmCPU68K.h \
+ EmCPUARM.cpp \
+ EmCPUARM.h \
+ EmHAL.cpp \
+ EmHAL.h \
+ EmMemory.cpp \
+ EmMemory.h \
+ EmRegs.cpp \
+ EmRegs.h \
+ EmRegs328.cpp \
+ EmRegs328.h \
+ EmRegs328PalmIII.h \
+ EmRegs328PalmPilot.cpp \
+ EmRegs328PalmPilot.h \
+ EmRegs328PalmVII.h \
+ EmRegs328Pilot.h \
+ EmRegs328Prv.h \
+ EmRegs328Symbol1700.cpp \
+ EmRegs328Symbol1700.h \
+ EmRegsASICSymbol1700.cpp \
+ EmRegsASICSymbol1700.h \
+ EmRegsEZ.cpp \
+ EmRegsEZ.h \
+ EmRegsEZPalmIIIc.cpp \
+ EmRegsEZPalmIIIc.h \
+ EmRegsEZPalmIIIe.h \
+ EmRegsEZPalmIIIx.h \
+ EmRegsEZPalmM100.cpp \
+ EmRegsEZPalmM100.h \
+ EmRegsEZPalmV.cpp \
+ EmRegsEZPalmV.h \
+ EmRegsEZPalmVIIx.cpp \
+ EmRegsEZPalmVIIx.h \
+ EmRegsEZPalmVII.cpp \
+ EmRegsEZPalmVII.h \
+ EmRegsEZPalmVx.h \
+ EmRegsEZPrv.h \
+ EmRegsEZTemp.cpp \
+ EmRegsEZTemp.h \
+ EmRegsEZTRGpro.cpp \
+ EmRegsEZTRGpro.h \
+ EmRegsEZVisor.cpp \
+ EmRegsEZVisor.h \
+ EmRegsFrameBuffer.cpp \
+ EmRegsFrameBuffer.h \
+ EmRegsMediaQ11xx.cpp \
+ EmRegsMediaQ11xx.h \
+ EmRegsPLDPalmVIIEZ.cpp \
+ EmRegsPLDPalmVIIEZ.h \
+ EmRegsPrv.h \
+ EmRegsSED1375.cpp \
+ EmRegsSED1375.h \
+ EmRegsSED1376.cpp \
+ EmRegsSED1376.h \
+ EmRegsSZ.cpp \
+ EmRegsSZ.h \
+ EmRegsSZPrv.h \
+ EmRegsSZTemp.cpp \
+ EmRegsSZTemp.h \
+ EmRegsUSBPhilipsPDIUSBD12.cpp \
+ EmRegsUSBPhilipsPDIUSBD12.h \
+ EmRegsUSBVisor.cpp \
+ EmRegsUSBVisor.h \
+ EmRegsVZ.cpp \
+ EmRegsVZ.h \
+ EmRegsVZHandEra330.cpp \
+ EmRegsVZHandEra330.h \
+ EmRegsVZPalmM500.cpp \
+ EmRegsVZPalmM500.h \
+ EmRegsVZPalmM505.cpp \
+ EmRegsVZPalmM505.h \
+ EmRegsVZPrv.h \
+ EmRegsVZTemp.cpp \
+ EmRegsVZTemp.h \
+ EmRegsVZVisorEdge.cpp \
+ EmRegsVZVisorEdge.h \
+ EmRegsVZVisorPlatinum.cpp \
+ EmRegsVZVisorPlatinum.h \
+ EmRegsVZVisorPrism.cpp \
+ EmRegsVZVisorPrism.h \
+ EmSPISlave.cpp \
+ EmSPISlave.h \
+ EmSPISlaveADS784x.cpp \
+ EmSPISlaveADS784x.h \
+ EmUAEGlue.cpp \
+ EmUAEGlue.h \
+ EmUARTDragonball.cpp \
+ EmUARTDragonball.h
+
+SRC_PATCHES = EmPatchIf.h \
+ EmPatchLoader.cpp \
+ EmPatchLoader.h \
+ EmPatchMgr.cpp \
+ EmPatchMgr.h \
+ EmPatchModule.cpp \
+ EmPatchModule.h \
+ EmPatchModuleHtal.cpp \
+ EmPatchModuleHtal.h \
+ EmPatchModuleMap.cpp \
+ EmPatchModuleMap.h \
+ EmPatchModuleMemMgr.cpp \
+ EmPatchModuleNetLib.cpp \
+ EmPatchModuleNetLib.h \
+ EmPatchModuleSys.cpp \
+ EmPatchModuleSys.h \
+ EmPatchModuleTypes.h \
+ EmPatchState.cpp \
+ EmPatchState.h
+
+SRC_TRG = EmHandEra330Defs.h \
+ EmHandEraCFBus.h \
+ EmHandEraSDBus.h \
+ EmRegs330CPLD.cpp \
+ EmRegs330CPLD.h \
+ EmSPISlave330Current.cpp \
+ EmSPISlave330Current.h \
+ EmTRG.cpp \
+ EmTRG.h \
+ EmTRGATA.cpp \
+ EmTRGATA.h \
+ EmTRGCF.cpp \
+ EmTRGCF.h \
+ EmTRGCFDefs.h \
+ EmTRGCFIO.cpp \
+ EmTRGCFIO.h \
+ EmTRGCFMem.cpp \
+ EmTRGCFMem.h \
+ EmTRGDiskIO.cpp \
+ EmTRGDiskIO.h \
+ EmTRGDiskType.cpp \
+ EmTRGDiskType.h \
+ EmTRGSD.cpp \
+ EmTRGSD.h
+
+SRC_UAE = UAE.h \
+ compiler.h \
+ config.h \
+ cpudefs.c \
+ cpuemu.c \
+ cpustbl.c \
+ cputbl.h \
+ custom.h \
+ machdep_m68k.h \
+ machdep_maccess.h \
+ memory_cpu.h \
+ newcpu.h \
+ options.h \
+ readcpu.cpp \
+ readcpu.h \
+ sysconfig.h \
+ sysdeps.h \
+ target.h
+
+SRC_PALM = Crc.c
+
+if SOLARIS
+SRC_THREAD = solaris.cpp
+else
+SRC_THREAD = posix.cpp
+endif
+
+bin_PROGRAMS = pose
+
+pose_LDADD = $(srcdir)/Gzip/libposergzip.a
+pose_LDADD += $(srcdir)/jpeg/libposerjpeg.a
+pose_LDADD += $(srcdir)/espws-2.0/libposerespws.a
+pose_LDADD += -lfltk
+pose_LDADD += -L/usr/local/lib $(X_LIBS) -lXext -lX11 $(THREAD_LIBS) $(GLLIB) -lm
+
+pose_SOURCES = $(SRC_UNIX) $(SRC_UNIX_GEN) $(SRC_SHARED) $(SRC_SHARED_HARDWARE)
+pose_SOURCES += $(SRC_PATCHES) $(SRC_TRG) $(SRC_UAE) $(SRC_PALM) $(SRC_THREAD)
+
+ResStrings.cpp: $(srcdir)/../SrcShared/Strings.txt
+ perl -x $(srcdir)/../SrcShared/Strings.txt
+
+EmDlgFltkFactory.h EmDlgFltkFactory.cpp : $(srcdir)/../SrcUnix/EmDlgFltkFactory.fl
+ fluid -c $(srcdir)/../SrcUnix/EmDlgFltkFactory.fl
+
+EmDlgFltk.o : EmDlgFltkFactory.h
+
+mytags:
+ etags -R $(srcdir)/../SrcUnix/* $(srcdir)/../SrcShared/*
+
+CLEANFILES = ResStrings.cpp
+CLEANFILES += EmDlgFltkFactory.h
+CLEANFILES += EmDlgFltkFactory.cpp
+CLEANFILES += config.cache
+CLEANFILES += config.log
diff --git a/BuildUnix/Makefile.in b/BuildUnix/Makefile.in
new file mode 100644
index 0000000..874a534
--- /dev/null
+++ b/BuildUnix/Makefile.in
@@ -0,0 +1,659 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+CC = @CC@
+CPP = @CPP@
+CXX = @CXX@
+GLLIB = @GLLIB@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+POSER_CFLAGS = @POSER_CFLAGS@
+POSER_CXXFLAGS = @POSER_CXXFLAGS@
+RANLIB = @RANLIB@
+THREAD_FLAGS = @THREAD_FLAGS@
+THREAD_LIBS = @THREAD_LIBS@
+THREAD_SRC = @THREAD_SRC@
+VERSION = @VERSION@
+
+SUBDIRS = Gzip jpeg espws-2.0
+
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../SrcUnix: $(srcdir)/../SrcShared: $(srcdir)/../SrcShared/Hardware: $(srcdir)/../SrcShared/Hardware/TRG: $(srcdir)/../SrcShared/omnithread: $(srcdir)/../SrcShared/Palm/Platform/Core/System/Src: $(srcdir)/../SrcShared/Patches: $(srcdir)/../SrcShared/UAE:
+
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS) $(FLAGS) $(THREAD_FLAGS) $(X_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS) $(FLAGS) $(THREAD_FLAGS) $(X_CFLAGS)
+INCLUDES = -I$(srcdir)/../SrcShared -I$(srcdir)/../SrcShared/Hardware -I$(srcdir)/../SrcShared/Hardware/TRG -I$(srcdir)/../SrcShared/Palm/Device -I$(srcdir)/../SrcShared/Palm/Platform -I$(srcdir)/../SrcShared/Palm/Platform/Core/Hardware/IncsPrv -I$(srcdir)/../SrcShared/Palm/Platform/Core/System/IncsPrv -I$(srcdir)/../SrcShared/Palm/Platform/Incs -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/Hardware -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/System -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Core/UI -I$(srcdir)/../SrcShared/Palm/Platform/Incs/Libraries -I$(srcdir)/../SrcShared/Gzip -I$(srcdir)/../SrcShared/jpeg -I$(srcdir)/../SrcShared/omnithread -I$(srcdir)/../SrcShared/Patches -I$(srcdir)/../SrcShared/UAE -I$(srcdir)/../SrcUnix -I$(srcdir)/../SrcUnix/espws-2.0
+
+SRC_UNIX = EmApplicationFltk.cpp EmApplicationFltk.h EmCommonUnix.h EmDirRefUnix.cpp EmDirRefUnix.h EmDlgFltk.cpp EmDlgFltk.h EmDocumentUnix.cpp EmDocumentUnix.h EmFileRefUnix.cpp EmFileRefUnix.h EmMenusFltk.cpp EmMenusFltk.h EmPixMapUnix.cpp EmPixMapUnix.h EmTransportSerialUnix.cpp EmTransportSerialUnix.h EmTransportUSBUnix.cpp EmTransportUSBUnix.h EmWindowFltk.cpp EmWindowFltk.h Platform_Unix.cpp jconfig.h
+
+
+SRC_UNIX_GEN = ResStrings.cpp EmDlgFltkFactory.h EmDlgFltkFactory.cpp
+
+
+SRC_SHARED = ATraps.cpp ATraps.h Byteswapping.cpp Byteswapping.h CGremlins.cpp CGremlins.h CGremlinsStubs.cpp CGremlinsStubs.h ChunkFile.cpp ChunkFile.h DebugMgr.cpp DebugMgr.h EcmIf.h EcmObject.h EmAction.cpp EmAction.h EmApplication.cpp EmApplication.h EmCommands.h EmCommon.cpp EmCommon.h EmDevice.cpp EmDevice.h EmDirRef.cpp EmDirRef.h EmDlg.cpp EmDlg.h EmDocument.cpp EmDocument.h EmErrCodes.h EmEventOutput.cpp EmEventOutput.h EmEventPlayback.cpp EmEventPlayback.h EmException.cpp EmException.h EmExgMgr.cpp EmExgMgr.h EmFileImport.cpp EmFileImport.h EmFileRef.cpp EmFileRef.h EmJPEG.cpp EmJPEG.h EmLowMem.cpp EmLowMem.h EmMapFile.cpp EmMapFile.h EmMenus.cpp EmMenus.h EmMinimize.cpp EmMinimize.h EmPalmFunction.cpp EmPalmFunction.h EmPalmHeap.cpp EmPalmHeap.h EmPalmOS.cpp EmPalmOS.h EmPalmStructs.cpp EmPalmStructs.h EmPalmStructs.i EmPixMap.cpp EmPixMap.h EmPoint.cpp EmPoint.h EmQuantizer.cpp EmQuantizer.h EmRect.cpp EmRect.h EmRefCounted.cpp EmRefCounted.h EmRegion.cpp EmRegion.h EmROMReader.cpp EmROMReader.h EmROMTransfer.cpp EmROMTransfer.h EmRPC.cpp EmRPC.h EmScreen.cpp EmScreen.h EmSession.cpp EmSession.h EmStream.cpp EmStream.h EmStreamFile.cpp EmStreamFile.h EmStructs.h EmSubroutine.cpp EmSubroutine.h EmThreadSafeQueue.cpp EmThreadSafeQueue.h EmTransport.cpp EmTransport.h EmTransportSerial.cpp EmTransportSerial.h EmTransportSocket.cpp EmTransportSocket.h EmTransportUSB.cpp EmTransportUSB.h EmTypes.h EmWindow.cpp EmWindow.h ErrorHandling.cpp ErrorHandling.h Hordes.cpp Hordes.h HostControl.cpp HostControl.h HostControlPrv.h LoadApplication.cpp LoadApplication.h Logging.cpp Logging.h Marshal.cpp Marshal.h MetaMemory.cpp MetaMemory.h Miscellaneous.cpp Miscellaneous.h Palm.h PalmOptErrorCheckLevel.h PalmPack.h PalmPackPop.h Platform.h Platform_NetLib.h Platform_NetLib_Sck.cpp PreferenceMgr.cpp PreferenceMgr.h Profiling.cpp Profiling.h ROMStubs.cpp ROMStubs.h SLP.cpp SLP.h SessionFile.cpp SessionFile.h Skins.cpp Skins.h SocketMessaging.cpp SocketMessaging.h Startup.cpp Startup.h StringConversions.cpp StringConversions.h StringData.cpp StringData.h SystemPacket.cpp SystemPacket.h
+
+
+SRC_SHARED_HARDWARE = EmBankDRAM.cpp EmBankDRAM.h EmBankDummy.cpp EmBankDummy.h EmBankMapped.cpp EmBankMapped.h EmBankROM.cpp EmBankROM.h EmBankRegs.cpp EmBankRegs.h EmBankSRAM.cpp EmBankSRAM.h EmCPU.cpp EmCPU.h EmCPU68K.cpp EmCPU68K.h EmCPUARM.cpp EmCPUARM.h EmHAL.cpp EmHAL.h EmMemory.cpp EmMemory.h EmRegs.cpp EmRegs.h EmRegs328.cpp EmRegs328.h EmRegs328PalmIII.h EmRegs328PalmPilot.cpp EmRegs328PalmPilot.h EmRegs328PalmVII.h EmRegs328Pilot.h EmRegs328Prv.h EmRegs328Symbol1700.cpp EmRegs328Symbol1700.h EmRegsASICSymbol1700.cpp EmRegsASICSymbol1700.h EmRegsEZ.cpp EmRegsEZ.h EmRegsEZPalmIIIc.cpp EmRegsEZPalmIIIc.h EmRegsEZPalmIIIe.h EmRegsEZPalmIIIx.h EmRegsEZPalmM100.cpp EmRegsEZPalmM100.h EmRegsEZPalmV.cpp EmRegsEZPalmV.h EmRegsEZPalmVIIx.cpp EmRegsEZPalmVIIx.h EmRegsEZPalmVII.cpp EmRegsEZPalmVII.h EmRegsEZPalmVx.h EmRegsEZPrv.h EmRegsEZTemp.cpp EmRegsEZTemp.h EmRegsEZTRGpro.cpp EmRegsEZTRGpro.h EmRegsEZVisor.cpp EmRegsEZVisor.h EmRegsFrameBuffer.cpp EmRegsFrameBuffer.h EmRegsMediaQ11xx.cpp EmRegsMediaQ11xx.h EmRegsPLDPalmVIIEZ.cpp EmRegsPLDPalmVIIEZ.h EmRegsPrv.h EmRegsSED1375.cpp EmRegsSED1375.h EmRegsSED1376.cpp EmRegsSED1376.h EmRegsSZ.cpp EmRegsSZ.h EmRegsSZPrv.h EmRegsSZTemp.cpp EmRegsSZTemp.h EmRegsUSBPhilipsPDIUSBD12.cpp EmRegsUSBPhilipsPDIUSBD12.h EmRegsUSBVisor.cpp EmRegsUSBVisor.h EmRegsVZ.cpp EmRegsVZ.h EmRegsVZHandEra330.cpp EmRegsVZHandEra330.h EmRegsVZPalmM500.cpp EmRegsVZPalmM500.h EmRegsVZPalmM505.cpp EmRegsVZPalmM505.h EmRegsVZPrv.h EmRegsVZTemp.cpp EmRegsVZTemp.h EmRegsVZVisorEdge.cpp EmRegsVZVisorEdge.h EmRegsVZVisorPlatinum.cpp EmRegsVZVisorPlatinum.h EmRegsVZVisorPrism.cpp EmRegsVZVisorPrism.h EmSPISlave.cpp EmSPISlave.h EmSPISlaveADS784x.cpp EmSPISlaveADS784x.h EmUAEGlue.cpp EmUAEGlue.h EmUARTDragonball.cpp EmUARTDragonball.h
+
+
+SRC_PATCHES = EmPatchIf.h EmPatchLoader.cpp EmPatchLoader.h EmPatchMgr.cpp EmPatchMgr.h EmPatchModule.cpp EmPatchModule.h EmPatchModuleHtal.cpp EmPatchModuleHtal.h EmPatchModuleMap.cpp EmPatchModuleMap.h EmPatchModuleMemMgr.cpp EmPatchModuleNetLib.cpp EmPatchModuleNetLib.h EmPatchModuleSys.cpp EmPatchModuleSys.h EmPatchModuleTypes.h EmPatchState.cpp EmPatchState.h
+
+
+SRC_TRG = EmHandEra330Defs.h EmHandEraCFBus.h EmHandEraSDBus.h EmRegs330CPLD.cpp EmRegs330CPLD.h EmSPISlave330Current.cpp EmSPISlave330Current.h EmTRG.cpp EmTRG.h EmTRGATA.cpp EmTRGATA.h EmTRGCF.cpp EmTRGCF.h EmTRGCFDefs.h EmTRGCFIO.cpp EmTRGCFIO.h EmTRGCFMem.cpp EmTRGCFMem.h EmTRGDiskIO.cpp EmTRGDiskIO.h EmTRGDiskType.cpp EmTRGDiskType.h EmTRGSD.cpp EmTRGSD.h
+
+
+SRC_UAE = UAE.h compiler.h config.h cpudefs.c cpuemu.c cpustbl.c cputbl.h custom.h machdep_m68k.h machdep_maccess.h memory_cpu.h newcpu.h options.h readcpu.cpp readcpu.h sysconfig.h sysdeps.h target.h
+
+
+SRC_PALM = Crc.c
+@SOLARIS_TRUE@SRC_THREAD = solaris.cpp
+@SOLARIS_FALSE@SRC_THREAD = posix.cpp
+
+bin_PROGRAMS = pose
+pose_LDADD = $(srcdir)/Gzip/libposergzip.a $(srcdir)/jpeg/libposerjpeg.a $(srcdir)/espws-2.0/libposerespws.a -lfltk -L/usr/local/lib $(X_LIBS) -lXext -lX11 $(THREAD_LIBS) $(GLLIB) -lm
+pose_SOURCES = $(SRC_UNIX) $(SRC_UNIX_GEN) $(SRC_SHARED) $(SRC_SHARED_HARDWARE) $(SRC_PATCHES) $(SRC_TRG) $(SRC_UAE) $(SRC_PALM) $(SRC_THREAD)
+CLEANFILES = ResStrings.cpp EmDlgFltkFactory.h EmDlgFltkFactory.cpp config.cache config.log
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+@SOLARIS_TRUE@pose_OBJECTS = EmApplicationFltk.o EmDirRefUnix.o \
+@SOLARIS_TRUE@EmDlgFltk.o EmDocumentUnix.o EmFileRefUnix.o \
+@SOLARIS_TRUE@EmMenusFltk.o EmPixMapUnix.o EmTransportSerialUnix.o \
+@SOLARIS_TRUE@EmTransportUSBUnix.o EmWindowFltk.o Platform_Unix.o \
+@SOLARIS_TRUE@ResStrings.o EmDlgFltkFactory.o ATraps.o Byteswapping.o \
+@SOLARIS_TRUE@CGremlins.o CGremlinsStubs.o ChunkFile.o DebugMgr.o \
+@SOLARIS_TRUE@EmAction.o EmApplication.o EmCommon.o EmDevice.o \
+@SOLARIS_TRUE@EmDirRef.o EmDlg.o EmDocument.o EmEventOutput.o \
+@SOLARIS_TRUE@EmEventPlayback.o EmException.o EmExgMgr.o EmFileImport.o \
+@SOLARIS_TRUE@EmFileRef.o EmJPEG.o EmLowMem.o EmMapFile.o EmMenus.o \
+@SOLARIS_TRUE@EmMinimize.o EmPalmFunction.o EmPalmHeap.o EmPalmOS.o \
+@SOLARIS_TRUE@EmPalmStructs.o EmPixMap.o EmPoint.o EmQuantizer.o \
+@SOLARIS_TRUE@EmRect.o EmRefCounted.o EmRegion.o EmROMReader.o \
+@SOLARIS_TRUE@EmROMTransfer.o EmRPC.o EmScreen.o EmSession.o EmStream.o \
+@SOLARIS_TRUE@EmStreamFile.o EmSubroutine.o EmThreadSafeQueue.o \
+@SOLARIS_TRUE@EmTransport.o EmTransportSerial.o EmTransportSocket.o \
+@SOLARIS_TRUE@EmTransportUSB.o EmWindow.o ErrorHandling.o Hordes.o \
+@SOLARIS_TRUE@HostControl.o LoadApplication.o Logging.o Marshal.o \
+@SOLARIS_TRUE@MetaMemory.o Miscellaneous.o Platform_NetLib_Sck.o \
+@SOLARIS_TRUE@PreferenceMgr.o Profiling.o ROMStubs.o SLP.o \
+@SOLARIS_TRUE@SessionFile.o Skins.o SocketMessaging.o Startup.o \
+@SOLARIS_TRUE@StringConversions.o StringData.o SystemPacket.o \
+@SOLARIS_TRUE@EmBankDRAM.o EmBankDummy.o EmBankMapped.o EmBankROM.o \
+@SOLARIS_TRUE@EmBankRegs.o EmBankSRAM.o EmCPU.o EmCPU68K.o EmCPUARM.o \
+@SOLARIS_TRUE@EmHAL.o EmMemory.o EmRegs.o EmRegs328.o \
+@SOLARIS_TRUE@EmRegs328PalmPilot.o EmRegs328Symbol1700.o \
+@SOLARIS_TRUE@EmRegsASICSymbol1700.o EmRegsEZ.o EmRegsEZPalmIIIc.o \
+@SOLARIS_TRUE@EmRegsEZPalmM100.o EmRegsEZPalmV.o EmRegsEZPalmVIIx.o \
+@SOLARIS_TRUE@EmRegsEZPalmVII.o EmRegsEZTemp.o EmRegsEZTRGpro.o \
+@SOLARIS_TRUE@EmRegsEZVisor.o EmRegsFrameBuffer.o EmRegsMediaQ11xx.o \
+@SOLARIS_TRUE@EmRegsPLDPalmVIIEZ.o EmRegsSED1375.o EmRegsSED1376.o \
+@SOLARIS_TRUE@EmRegsSZ.o EmRegsSZTemp.o EmRegsUSBPhilipsPDIUSBD12.o \
+@SOLARIS_TRUE@EmRegsUSBVisor.o EmRegsVZ.o EmRegsVZHandEra330.o \
+@SOLARIS_TRUE@EmRegsVZPalmM500.o EmRegsVZPalmM505.o EmRegsVZTemp.o \
+@SOLARIS_TRUE@EmRegsVZVisorEdge.o EmRegsVZVisorPlatinum.o \
+@SOLARIS_TRUE@EmRegsVZVisorPrism.o EmSPISlave.o EmSPISlaveADS784x.o \
+@SOLARIS_TRUE@EmUAEGlue.o EmUARTDragonball.o EmPatchLoader.o \
+@SOLARIS_TRUE@EmPatchMgr.o EmPatchModule.o EmPatchModuleHtal.o \
+@SOLARIS_TRUE@EmPatchModuleMap.o EmPatchModuleMemMgr.o \
+@SOLARIS_TRUE@EmPatchModuleNetLib.o EmPatchModuleSys.o EmPatchState.o \
+@SOLARIS_TRUE@EmRegs330CPLD.o EmSPISlave330Current.o EmTRG.o EmTRGATA.o \
+@SOLARIS_TRUE@EmTRGCF.o EmTRGCFIO.o EmTRGCFMem.o EmTRGDiskIO.o \
+@SOLARIS_TRUE@EmTRGDiskType.o EmTRGSD.o cpudefs.o cpuemu.o cpustbl.o \
+@SOLARIS_TRUE@readcpu.o Crc.o solaris.o
+@SOLARIS_FALSE@pose_OBJECTS = EmApplicationFltk.o EmDirRefUnix.o \
+@SOLARIS_FALSE@EmDlgFltk.o EmDocumentUnix.o EmFileRefUnix.o \
+@SOLARIS_FALSE@EmMenusFltk.o EmPixMapUnix.o EmTransportSerialUnix.o \
+@SOLARIS_FALSE@EmTransportUSBUnix.o EmWindowFltk.o Platform_Unix.o \
+@SOLARIS_FALSE@ResStrings.o EmDlgFltkFactory.o ATraps.o Byteswapping.o \
+@SOLARIS_FALSE@CGremlins.o CGremlinsStubs.o ChunkFile.o DebugMgr.o \
+@SOLARIS_FALSE@EmAction.o EmApplication.o EmCommon.o EmDevice.o \
+@SOLARIS_FALSE@EmDirRef.o EmDlg.o EmDocument.o EmEventOutput.o \
+@SOLARIS_FALSE@EmEventPlayback.o EmException.o EmExgMgr.o \
+@SOLARIS_FALSE@EmFileImport.o EmFileRef.o EmJPEG.o EmLowMem.o \
+@SOLARIS_FALSE@EmMapFile.o EmMenus.o EmMinimize.o EmPalmFunction.o \
+@SOLARIS_FALSE@EmPalmHeap.o EmPalmOS.o EmPalmStructs.o EmPixMap.o \
+@SOLARIS_FALSE@EmPoint.o EmQuantizer.o EmRect.o EmRefCounted.o \
+@SOLARIS_FALSE@EmRegion.o EmROMReader.o EmROMTransfer.o EmRPC.o \
+@SOLARIS_FALSE@EmScreen.o EmSession.o EmStream.o EmStreamFile.o \
+@SOLARIS_FALSE@EmSubroutine.o EmThreadSafeQueue.o EmTransport.o \
+@SOLARIS_FALSE@EmTransportSerial.o EmTransportSocket.o EmTransportUSB.o \
+@SOLARIS_FALSE@EmWindow.o ErrorHandling.o Hordes.o HostControl.o \
+@SOLARIS_FALSE@LoadApplication.o Logging.o Marshal.o MetaMemory.o \
+@SOLARIS_FALSE@Miscellaneous.o Platform_NetLib_Sck.o PreferenceMgr.o \
+@SOLARIS_FALSE@Profiling.o ROMStubs.o SLP.o SessionFile.o Skins.o \
+@SOLARIS_FALSE@SocketMessaging.o Startup.o StringConversions.o \
+@SOLARIS_FALSE@StringData.o SystemPacket.o EmBankDRAM.o EmBankDummy.o \
+@SOLARIS_FALSE@EmBankMapped.o EmBankROM.o EmBankRegs.o EmBankSRAM.o \
+@SOLARIS_FALSE@EmCPU.o EmCPU68K.o EmCPUARM.o EmHAL.o EmMemory.o \
+@SOLARIS_FALSE@EmRegs.o EmRegs328.o EmRegs328PalmPilot.o \
+@SOLARIS_FALSE@EmRegs328Symbol1700.o EmRegsASICSymbol1700.o EmRegsEZ.o \
+@SOLARIS_FALSE@EmRegsEZPalmIIIc.o EmRegsEZPalmM100.o EmRegsEZPalmV.o \
+@SOLARIS_FALSE@EmRegsEZPalmVIIx.o EmRegsEZPalmVII.o EmRegsEZTemp.o \
+@SOLARIS_FALSE@EmRegsEZTRGpro.o EmRegsEZVisor.o EmRegsFrameBuffer.o \
+@SOLARIS_FALSE@EmRegsMediaQ11xx.o EmRegsPLDPalmVIIEZ.o EmRegsSED1375.o \
+@SOLARIS_FALSE@EmRegsSED1376.o EmRegsSZ.o EmRegsSZTemp.o \
+@SOLARIS_FALSE@EmRegsUSBPhilipsPDIUSBD12.o EmRegsUSBVisor.o EmRegsVZ.o \
+@SOLARIS_FALSE@EmRegsVZHandEra330.o EmRegsVZPalmM500.o \
+@SOLARIS_FALSE@EmRegsVZPalmM505.o EmRegsVZTemp.o EmRegsVZVisorEdge.o \
+@SOLARIS_FALSE@EmRegsVZVisorPlatinum.o EmRegsVZVisorPrism.o \
+@SOLARIS_FALSE@EmSPISlave.o EmSPISlaveADS784x.o EmUAEGlue.o \
+@SOLARIS_FALSE@EmUARTDragonball.o EmPatchLoader.o EmPatchMgr.o \
+@SOLARIS_FALSE@EmPatchModule.o EmPatchModuleHtal.o EmPatchModuleMap.o \
+@SOLARIS_FALSE@EmPatchModuleMemMgr.o EmPatchModuleNetLib.o \
+@SOLARIS_FALSE@EmPatchModuleSys.o EmPatchState.o EmRegs330CPLD.o \
+@SOLARIS_FALSE@EmSPISlave330Current.o EmTRG.o EmTRGATA.o EmTRGCF.o \
+@SOLARIS_FALSE@EmTRGCFIO.o EmTRGCFMem.o EmTRGDiskIO.o EmTRGDiskType.o \
+@SOLARIS_FALSE@EmTRGSD.o cpudefs.o cpuemu.o cpustbl.o readcpu.o Crc.o \
+@SOLARIS_FALSE@posix.o
+pose_DEPENDENCIES = $(srcdir)/Gzip/libposergzip.a \
+$(srcdir)/jpeg/libposerjpeg.a $(srcdir)/espws-2.0/libposerespws.a
+pose_LDFLAGS =
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in aclocal.m4 config.guess \
+config.sub configure configure.in install-sh missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/ATraps.P .deps/Byteswapping.P .deps/CGremlins.P \
+.deps/CGremlinsStubs.P .deps/ChunkFile.P .deps/Crc.P .deps/DebugMgr.P \
+.deps/EmAction.P .deps/EmApplication.P .deps/EmApplicationFltk.P \
+.deps/EmBankDRAM.P .deps/EmBankDummy.P .deps/EmBankMapped.P \
+.deps/EmBankROM.P .deps/EmBankRegs.P .deps/EmBankSRAM.P .deps/EmCPU.P \
+.deps/EmCPU68K.P .deps/EmCPUARM.P .deps/EmCommon.P .deps/EmDevice.P \
+.deps/EmDirRef.P .deps/EmDirRefUnix.P .deps/EmDlg.P .deps/EmDlgFltk.P \
+.deps/EmDlgFltkFactory.P .deps/EmDocument.P .deps/EmDocumentUnix.P \
+.deps/EmEventOutput.P .deps/EmEventPlayback.P .deps/EmException.P \
+.deps/EmExgMgr.P .deps/EmFileImport.P .deps/EmFileRef.P \
+.deps/EmFileRefUnix.P .deps/EmHAL.P .deps/EmJPEG.P .deps/EmLowMem.P \
+.deps/EmMapFile.P .deps/EmMemory.P .deps/EmMenus.P .deps/EmMenusFltk.P \
+.deps/EmMinimize.P .deps/EmPalmFunction.P .deps/EmPalmHeap.P \
+.deps/EmPalmOS.P .deps/EmPalmStructs.P .deps/EmPatchLoader.P \
+.deps/EmPatchMgr.P .deps/EmPatchModule.P .deps/EmPatchModuleHtal.P \
+.deps/EmPatchModuleMap.P .deps/EmPatchModuleMemMgr.P \
+.deps/EmPatchModuleNetLib.P .deps/EmPatchModuleSys.P \
+.deps/EmPatchState.P .deps/EmPixMap.P .deps/EmPixMapUnix.P \
+.deps/EmPoint.P .deps/EmQuantizer.P .deps/EmROMReader.P \
+.deps/EmROMTransfer.P .deps/EmRPC.P .deps/EmRect.P .deps/EmRefCounted.P \
+.deps/EmRegion.P .deps/EmRegs.P .deps/EmRegs328.P \
+.deps/EmRegs328PalmPilot.P .deps/EmRegs328Symbol1700.P \
+.deps/EmRegs330CPLD.P .deps/EmRegsASICSymbol1700.P .deps/EmRegsEZ.P \
+.deps/EmRegsEZPalmIIIc.P .deps/EmRegsEZPalmM100.P .deps/EmRegsEZPalmV.P \
+.deps/EmRegsEZPalmVII.P .deps/EmRegsEZPalmVIIx.P .deps/EmRegsEZTRGpro.P \
+.deps/EmRegsEZTemp.P .deps/EmRegsEZVisor.P .deps/EmRegsFrameBuffer.P \
+.deps/EmRegsMediaQ11xx.P .deps/EmRegsPLDPalmVIIEZ.P \
+.deps/EmRegsSED1375.P .deps/EmRegsSED1376.P .deps/EmRegsSZ.P \
+.deps/EmRegsSZTemp.P .deps/EmRegsUSBPhilipsPDIUSBD12.P \
+.deps/EmRegsUSBVisor.P .deps/EmRegsVZ.P .deps/EmRegsVZHandEra330.P \
+.deps/EmRegsVZPalmM500.P .deps/EmRegsVZPalmM505.P .deps/EmRegsVZTemp.P \
+.deps/EmRegsVZVisorEdge.P .deps/EmRegsVZVisorPlatinum.P \
+.deps/EmRegsVZVisorPrism.P .deps/EmSPISlave.P \
+.deps/EmSPISlave330Current.P .deps/EmSPISlaveADS784x.P .deps/EmScreen.P \
+.deps/EmSession.P .deps/EmStream.P .deps/EmStreamFile.P \
+.deps/EmSubroutine.P .deps/EmTRG.P .deps/EmTRGATA.P .deps/EmTRGCF.P \
+.deps/EmTRGCFIO.P .deps/EmTRGCFMem.P .deps/EmTRGDiskIO.P \
+.deps/EmTRGDiskType.P .deps/EmTRGSD.P .deps/EmThreadSafeQueue.P \
+.deps/EmTransport.P .deps/EmTransportSerial.P \
+.deps/EmTransportSerialUnix.P .deps/EmTransportSocket.P \
+.deps/EmTransportUSB.P .deps/EmTransportUSBUnix.P .deps/EmUAEGlue.P \
+.deps/EmUARTDragonball.P .deps/EmWindow.P .deps/EmWindowFltk.P \
+.deps/ErrorHandling.P .deps/Hordes.P .deps/HostControl.P \
+.deps/LoadApplication.P .deps/Logging.P .deps/Marshal.P \
+.deps/MetaMemory.P .deps/Miscellaneous.P .deps/Platform_NetLib_Sck.P \
+.deps/Platform_Unix.P .deps/PreferenceMgr.P .deps/Profiling.P \
+.deps/ROMStubs.P .deps/ResStrings.P .deps/SLP.P .deps/SessionFile.P \
+.deps/Skins.P .deps/SocketMessaging.P .deps/Startup.P \
+.deps/StringConversions.P .deps/StringData.P .deps/SystemPacket.P \
+.deps/cpudefs.P .deps/cpuemu.P .deps/cpustbl.P .deps/posix.P \
+.deps/readcpu.P .deps/solaris.P
+SOURCES = $(pose_SOURCES)
+OBJECTS = $(pose_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cpp .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): configure.in
+ cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+ cd $(srcdir) && $(AUTOCONF)
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+pose: $(pose_OBJECTS) $(pose_DEPENDENCIES)
+ @rm -f pose
+ $(CXXLINK) $(pose_LDFLAGS) $(pose_OBJECTS) $(pose_LDADD) $(LIBS)
+.cpp.o:
+ $(CXXCOMPILE) -c $<
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+ rev="$$subdir $$rev"; \
+ test "$$subdir" = "." && dot_seen=yes; \
+ done; \
+ test "$$dot_seen" = "no" && rev=". $$rev"; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ -rm -rf $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+ mkdir $(distdir)/=build
+ mkdir $(distdir)/=inst
+ dc_install_base=`cd $(distdir)/=inst && pwd`; \
+ cd $(distdir)/=build \
+ && ../configure --srcdir=.. --prefix=$$dc_install_base \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) dist
+ -rm -rf $(distdir)
+ @banner="$(distdir).tar.gz is ready for distribution"; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"
+dist: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+dist-all: distdir
+ -chmod -R a+r $(distdir)
+ GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+ -rm -rf $(distdir)
+distdir: $(DISTFILES)
+ -rm -rf $(distdir)
+ mkdir $(distdir)
+ -chmod 777 $(distdir)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ for subdir in $(SUBDIRS); do \
+ if test "$$subdir" = .; then :; else \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+ || exit 1; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+
+%.o: %.cpp
+ @echo '$(CXXCOMPILE) -c $<'; \
+ $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.cpp
+ @echo '$(LTCXXCOMPILE) -c $<'; \
+ $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-recursive
+all-am: Makefile $(PROGRAMS)
+all-redirect: all-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am: clean-binPROGRAMS clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \
+ distclean-depend distclean-generic clean-am
+
+distclean: distclean-recursive
+ -rm -f config.status
+
+maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f config.status
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile install-data-recursive \
+uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs-am installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+ResStrings.cpp: $(srcdir)/../SrcShared/Strings.txt
+ perl -x $(srcdir)/../SrcShared/Strings.txt
+
+EmDlgFltkFactory.h EmDlgFltkFactory.cpp : $(srcdir)/../SrcUnix/EmDlgFltkFactory.fl
+ fluid -c $(srcdir)/../SrcUnix/EmDlgFltkFactory.fl
+
+EmDlgFltk.o : EmDlgFltkFactory.h
+
+mytags:
+ etags -R $(srcdir)/../SrcUnix/* $(srcdir)/../SrcShared/*
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/BuildUnix/aclocal.m4 b/BuildUnix/aclocal.m4
new file mode 100644
index 0000000..be5a94a
--- /dev/null
+++ b/BuildUnix/aclocal.m4
@@ -0,0 +1,119 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+dnl We require 2.13 because we rely on SHELL being computed by configure.
+AC_PREREQ([2.13])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi])
+
diff --git a/BuildUnix/config.guess b/BuildUnix/config.guess
new file mode 100755
index 0000000..1ec70cc
--- /dev/null
+++ b/BuildUnix/config.guess
@@ -0,0 +1,951 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+#
+# This file 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.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:NetBSD:*:*)
+ echo powerpc-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
+ sed 's/^ //' << EOF >dummy.c
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (${CC-cc} dummy.c -o dummy 2>/dev/null ) && HP_ARCH=`./dummy`
+ rm -f dummy.c dummy
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin32
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # uname on the ARM produces all sorts of strangeness, and we need to
+ # filter it out.
+ case "$UNAME_MACHINE" in
+ arm* | sa110*) UNAME_MACHINE="arm" ;;
+ esac
+
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
+ i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
+ sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >dummy.c <<EOF
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is gnuoldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+#include <features.h>
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ i?86:UnixWare:*:*)
+ if /bin/uname -X 2>/dev/null >/dev/null ; then
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ fi
+ echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/BuildUnix/config.sub b/BuildUnix/config.sub
new file mode 100755
index 0000000..ba26d74
--- /dev/null
+++ b/BuildUnix/config.sub
@@ -0,0 +1,955 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
+ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \
+ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
+ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
+ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+ | mipstx39 | mipstx39el | armv[34][lb] \
+ | sparc | sparclet | sparclite | sparc64 | v850)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[34567]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \
+ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
+ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
+ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+ | sparc64-* | mips64-* | mipsel-* | armv[34][lb]-*\
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mipstx39-* | mipstx39el-* \
+ | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-cbm
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[34567]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[34567]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[34567]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[34567]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | nexen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | k6 | 6x86)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | nexen-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | k6-* | 6x86-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/BuildUnix/configure b/BuildUnix/configure
new file mode 100755
index 0000000..a537745
--- /dev/null
+++ b/BuildUnix/configure
@@ -0,0 +1,3974 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --with-fltk=DIR use FLTK in DIR"
+ac_help="$ac_help
+ --enable-profile include gprof profiling (default no)"
+ac_help="$ac_help
+ --enable-palm-profile include profiling of Palm applications (default no)"
+ac_help="$ac_help
+ --enable-static-link static link; no shared libraries (default no)"
+ac_help="$ac_help
+ --enable-debug include debugging symbols (default no)"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=../SrcUnix/Platform_Unix.cpp
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:584: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:605: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:623: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:657: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:710: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "$*" != "X $srcdir/configure conftestfile" \
+ && test "$*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+ fi
+
+ test "$2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:767: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+
+PACKAGE=pose
+
+VERSION=0
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:807: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+ ACLOCAL=aclocal
+ echo "$ac_t""found" 1>&6
+else
+ ACLOCAL="$missing_dir/missing aclocal"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:820: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+ AUTOCONF=autoconf
+ echo "$ac_t""found" 1>&6
+else
+ AUTOCONF="$missing_dir/missing autoconf"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:833: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+ AUTOMAKE=automake
+ echo "$ac_t""found" 1>&6
+else
+ AUTOMAKE="$missing_dir/missing automake"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:846: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+ AUTOHEADER=autoheader
+ echo "$ac_t""found" 1>&6
+else
+ AUTOHEADER="$missing_dir/missing autoheader"
+ echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:859: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+ MAKEINFO=makeinfo
+ echo "$ac_t""found" 1>&6
+else
+ MAKEINFO="$missing_dir/missing makeinfo"
+ echo "$ac_t""missing" 1>&6
+fi
+
+
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:874: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:903: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:933: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:984: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1016: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1027 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1058: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1063: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1072: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1091: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1127: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1159: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1170 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:1175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1201: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:1206: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1215: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:1234: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1268: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1299: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1314 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1320: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1331 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1337: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1348 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1354: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:1386: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 1448 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1453: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1522 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:1529: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+if test "$no_x" = yes; then
+ # Not all programs may use this symbol, but it does not hurt to define it.
+ cat >> confdefs.h <<\EOF
+#define X_DISPLAY_MISSING 1
+EOF
+
+ X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+ if test -n "$x_includes"; then
+ X_CFLAGS="$X_CFLAGS -I$x_includes"
+ fi
+
+ # It would also be nice to do this for all -L options, not just this one.
+ if test -n "$x_libraries"; then
+ X_LIBS="$X_LIBS -L$x_libraries"
+ # For Solaris; some versions of Sun CC require a space after -R and
+ # others require no space. Words are not sufficient . . . .
+ case "`(uname -sr) 2>/dev/null`" in
+ "SunOS 5"*)
+ echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
+echo "configure:1635: checking whether -R must be followed by a space" >&5
+ ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 1638 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1645: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_nospace=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_nospace=no
+fi
+rm -f conftest*
+ if test $ac_R_nospace = yes; then
+ echo "$ac_t""no" 1>&6
+ X_LIBS="$X_LIBS -R$x_libraries"
+ else
+ LIBS="$ac_xsave_LIBS -R $x_libraries"
+ cat > conftest.$ac_ext <<EOF
+#line 1661 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_R_space=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_R_space=no
+fi
+rm -f conftest*
+ if test $ac_R_space = yes; then
+ echo "$ac_t""yes" 1>&6
+ X_LIBS="$X_LIBS -R $x_libraries"
+ else
+ echo "$ac_t""neither works" 1>&6
+ fi
+ fi
+ LIBS="$ac_xsave_LIBS"
+ esac
+ fi
+
+ # Check for system-dependent libraries X programs must link with.
+ # Do this before checking for the system-independent R6 libraries
+ # (-lICE), since we may need -lsocket or whatever for X linking.
+
+ if test "$ISC" = yes; then
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+ else
+ # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X
+ # libraries were built with DECnet support. And karl@cs.umb.edu says
+ # the Alpha needs dnet_stub (dnet does not exist).
+ echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
+echo "configure:1700: checking for dnet_ntoa in -ldnet" >&5
+ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1708 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:1719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+ echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
+echo "configure:1741: checking for dnet_ntoa in -ldnet_stub" >&5
+ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldnet_stub $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1749 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dnet_ntoa();
+
+int main() {
+dnet_ntoa()
+; return 0; }
+EOF
+if { (eval echo configure:1760: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+ # to get the SysV transport functions.
+ # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4)
+ # needs -lnsl.
+ # The nsl library prevents programs from opening the X display
+ # on Irix 5.2, according to dickey@clark.net.
+ echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
+echo "configure:1789: checking for gethostbyname" >&5
+if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1794 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gethostbyname(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
+choke me
+#else
+gethostbyname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1817: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_gethostbyname=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_gethostbyname = no; then
+ echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:1838: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1846 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:1857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # lieder@skyler.mavd.honeywell.com says without -lsocket,
+ # socket/setsockopt and other routines are undefined under SCO ODT
+ # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
+ # on later versions), says simon@lia.di.epfl.ch: it contains
+ # gethostby* variants that don't use the nameserver (or something).
+ # -lsocket must be given before -lnsl if both are needed.
+ # We assume that if connect needs -lnsl, so does gethostbyname.
+ echo $ac_n "checking for connect""... $ac_c" 1>&6
+echo "configure:1887: checking for connect" >&5
+if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1892 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char connect(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_connect) || defined (__stub___connect)
+choke me
+#else
+connect();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1915: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_connect=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_connect=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_connect = no; then
+ echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
+echo "configure:1936: checking for connect in -lsocket" >&5
+ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1944 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char connect();
+
+int main() {
+connect()
+; return 0; }
+EOF
+if { (eval echo configure:1955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
+ echo $ac_n "checking for remove""... $ac_c" 1>&6
+echo "configure:1979: checking for remove" >&5
+if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1984 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char remove(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_remove) || defined (__stub___remove)
+choke me
+#else
+remove();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_remove=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_remove=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_remove = no; then
+ echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
+echo "configure:2028: checking for remove in -lposix" >&5
+ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lposix $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2036 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char remove();
+
+int main() {
+remove()
+; return 0; }
+EOF
+if { (eval echo configure:2047: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+ echo $ac_n "checking for shmat""... $ac_c" 1>&6
+echo "configure:2071: checking for shmat" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2076 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shmat(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shmat) || defined (__stub___shmat)
+choke me
+#else
+shmat();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2099: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shmat=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $ac_cv_func_shmat = no; then
+ echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
+echo "configure:2120: checking for shmat in -lipc" >&5
+ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lipc $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2128 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shmat();
+
+int main() {
+shmat()
+; return 0; }
+EOF
+if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ fi
+
+ # Check for libraries that X11R6 Xt/Xaw programs need.
+ ac_save_LDFLAGS="$LDFLAGS"
+ test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+ # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+ # check for ICE first), but we must link in the order -lSM -lICE or
+ # we get undefined symbols. So assume we have SM if we have ICE.
+ # These have to be linked with before -lX11, unlike the other
+ # libraries we check for below, so use a different variable.
+ # --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
+ echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
+echo "configure:2172: checking for IceConnectionNumber in -lICE" >&5
+ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2180 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char IceConnectionNumber();
+
+int main() {
+IceConnectionNumber()
+; return 0; }
+EOF
+if { (eval echo configure:2191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ LDFLAGS="$ac_save_LDFLAGS"
+
+fi
+
+
+# Check whether --with-fltk or --without-fltk was given.
+if test "${with_fltk+set}" = set; then
+ withval="$with_fltk"
+
+ CPPFLAGS="${CPPFLAGS} -I$withval/include"
+ LDFLAGS="${LDFLAGS} -L$withval/lib"
+
+fi
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:2233: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2238 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:2271: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2279 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:2312: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2320 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2354: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2359 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2367: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2384 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2402 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2423 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2434: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in endian.h machine/endian.h sys/isa_defs.h fcntl.h limits.h strings.h sys/time.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2461: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2466 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2471: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2501: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2506 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2555: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2576: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 2583 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2590: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+echo $ac_n "checking for 'sa_len' in 'struct sockaddr'""... $ac_c" 1>&6
+echo "configure:2625: checking for 'sa_len' in 'struct sockaddr'" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_sa_len'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2630 "configure"
+#include "confdefs.h"
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+int main() {
+
+ struct sockaddr sa;
+ sa.sa_len = 0;
+
+; return 0; }
+EOF
+if { (eval echo configure:2643: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_sa_len=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_sa_len=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_sa_len" 1>&6
+ if test "$ac_cv_struct_sa_len" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SA_LEN 1
+EOF
+
+ fi
+echo $ac_n "checking for 'sin_len' in 'struct sockaddr_in'""... $ac_c" 1>&6
+echo "configure:2663: checking for 'sin_len' in 'struct sockaddr_in'" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_sin_len'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2668 "configure"
+#include "confdefs.h"
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+
+int main() {
+
+ struct sockaddr_in sin;
+ sin.sin_len = 0;
+
+; return 0; }
+EOF
+if { (eval echo configure:2682: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_sin_len=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_sin_len=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_sin_len" 1>&6
+ if test "$ac_cv_struct_sin_len" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SIN_LEN 1
+EOF
+
+ fi
+echo $ac_n "checking for 'socklen_t'""... $ac_c" 1>&6
+echo "configure:2702: checking for 'socklen_t'" >&5
+if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2707 "configure"
+#include "confdefs.h"
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+int main() {
+
+ socklen_t var;
+ var = 0;
+
+; return 0; }
+EOF
+if { (eval echo configure:2720: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_socklen_t=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_socklen_t=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_socklen_t" 1>&6
+ if test "$ac_cv_type_socklen_t" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TYPE_SOCKLEN_T 1
+EOF
+
+ fi
+
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:2745: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2750 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:2757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:2778: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2783 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2811: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:2843: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2848 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2873: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2878 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:2928: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2936 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:2955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_func in mkdir
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2979: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2984 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in mkstemp
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3034: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3039 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in tempnam
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3089: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3094 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+
+AR='ar'
+FLAGS_COMMON="-DPLATFORM_UNIX=1 -D__PALMOS_TRAPS__=0 -DEMULATION_LEVEL=EMULATION_UNIX"
+
+
+
+_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -fexceptions -Wall -Wno-multichar -Wno-unknown-pragmas -Wno-conversion"
+_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -fexceptions -Wall -Wno-multichar -Wno-unknown-pragmas -Wno-conversion"
+
+_COMPILER_CFLAGS="${_COMPILER_CFLAGS}"
+_COMPILER_CXXFLAGS="${_COMPILER_CXXFLAGS}"
+
+
+
+THREAD_FLAGS="-D_REENTRANT -DNoNanoSleep -DPthreadDraftVersion=10"
+THREAD_LIBS="-lpthread"
+USE_SOLARIS_CPP="false"
+
+
+
+case "$target" in
+*-aix*)
+ THREAD_FLAGS="-DNoNanoSleep -DPthreadDraftVersion=8"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-hpux*)
+ THREAD_FLAGS="-D_REENTRANT -DPthreadDraftVersion=4"
+ THREAD_LIBS="-lpthread -lmach -lc_r"
+ ;;
+
+*-irix*)
+ THREAD_FLAGS="-DUsePthread -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-linux*)
+ THREAD_FLAGS="-D_REENTRANT -DNoNanoSleep -DPthreadDraftVersion=10"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-nto*)
+ THREAD_FLAGS="-D_REENTRANT -DPthreadDraftVersion=10"
+ THREAD_LIBS=""
+ POSER_CFLAGS="$POSER_CFLAGS -D_QNX_SOURCE -D_POSIX_SOURCE -D__i386__ -D_i386 -DNSCAP_NO_EXPLICIT -DNO_REGEX -DSTRINGS_ALIGNED -D_SEEKPOS_DEFINED_ -I/usr/gcc/lib/gcc-lib/ntox86/2.8.1/include"
+ POSER_CXXFLAGS="$POSER_CFLAGS"
+ _WARNINGS_CFLAGS='-w'
+ _WARNINGS_CXXFLAGS='-w'
+ LIBS="$LIBS -lsocket"
+ poser_optimize="-O2"
+ poser_debug="-gdwarf-2"
+ AR='/usr/local/bin/ar.elf'
+ ;;
+
+*-osf*)
+ THREAD_FLAGS="-D_REENTRANT -pthread -DNoNanoSleep -DPthreadDraftVersion=10"
+ THREAD_LIBS="-lcma"
+ ;;
+
+*-solaris*)
+ # -g somehow helps the assembler understand long symbol names
+ THREAD_FLAGS="-g -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lnsl -lsocket -lthread -lposix4"
+ _COMPILER_CFLAGS="${_COMPILER_CFLAGS} -fpermissive"
+ _COMPILER_CXXFLAGS="${_COMPILER_CXXFLAGS} -fpermissive"
+ USE_SOLARIS_CPP="true"
+ ;;
+
+*-sunos*)
+ # -g somehow helps the assembler understand long symbol names
+ THREAD_FLAGS="-g -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lnsl -lsocket -lthread -lposix4"
+ USE_SOLARIS_CPP="true"
+ ;;
+
+*-freebsd*)
+ THREAD_FLAGS="-pthread -D_THREAD_SAFE -D_REENTRANT -DPthreadDraftVersion=10"
+ THREAD_LIBS=
+ ;;
+
+*-bsdi4*)
+ THREAD_LIBS=
+ ;;
+esac
+
+
+
+# Check whether --enable-profile or --disable-profile was given.
+if test "${enable_profile+set}" = set; then
+ enableval="$enable_profile"
+ FLAGS_PROFILE="-pg"
+else
+ FLAGS_PROFILE=""
+fi
+
+
+
+
+# Check whether --enable-palm_profile or --disable-palm_profile was given.
+if test "${enable_palm_profile+set}" = set; then
+ enableval="$enable_palm_profile"
+ FLAGS_PALM_PROFILE="-DHAS_PROFILING=1"
+else
+ FLAGS_PALM_PROFILE="-DHAS_PROFILING=0"
+fi
+
+
+
+
+# Check whether --enable-static-link or --disable-static-link was given.
+if test "${enable_static_link+set}" = set; then
+ enableval="$enable_static_link"
+ LDFLAGS="${LDFLAGS} -static"
+
+fi
+
+
+
+
+
+FLAGS_OPTIMIZE="-O2"
+
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether virtual function default arguments work""... $ac_c" 1>&6
+echo "configure:3275: checking whether virtual function default arguments work" >&5
+if eval "test \"`echo '$''{'pose_cv_virtual_defarg_ok'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3280 "configure"
+#include "confdefs.h"
+
+ class C
+ {
+ public:
+ virtual int foo ();
+ } *c;
+ void bar (int = c->foo ());
+
+int main() {
+bar ();
+; return 0; }
+EOF
+if { (eval echo configure:3294: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ pose_cv_virtual_defarg_ok=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ pose_cv_virtual_defarg_ok=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$pose_cv_virtual_defarg_ok" 1>&6
+
+if test $pose_cv_virtual_defarg_ok = no; then
+ cat >> confdefs.h <<\EOF
+#define BROKEN_VIRTUAL_DEFAULT_ARGUMENTS 1
+EOF
+
+fi
+
+
+
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ FLAGS_DEBUG="-D_DEBUG -g"
+ FLAGS_PROFILE="-DHAS_PROFILING=1"
+ FLAGS_PALM_PROFILE=""
+ FLAGS_OPTIMIZE=""
+else
+ FLAGS_DEBUG="-DNDEBUG"
+fi
+
+
+
+
+GLLIB=
+
+echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
+echo "configure:3334: checking how to run the C++ preprocessor" >&5
+if test -z "$CXXCPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+ CXXCPP="${CXX-g++} -E"
+ cat > conftest.$ac_ext <<EOF
+#line 3347 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CXXCPP=/lib/cpp
+fi
+rm -f conftest*
+ ac_cv_prog_CXXCPP="$CXXCPP"
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+fi
+fi
+CXXCPP="$ac_cv_prog_CXXCPP"
+echo "$ac_t""$CXXCPP" 1>&6
+
+ac_safe=`echo "GL/gl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for GL/gl.h""... $ac_c" 1>&6
+echo "configure:3378: checking for GL/gl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3383 "configure"
+#include "confdefs.h"
+#include <GL/gl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3388: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for glXMakeCurrent in -lGL""... $ac_c" 1>&6
+echo "configure:3405: checking for glXMakeCurrent in -lGL" >&5
+ac_lib_var=`echo GL'_'glXMakeCurrent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lGL \
+ -L${ac_x_libraries} -lX11 -lXext $X_EXTRA_LIBS -lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3414 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char glXMakeCurrent();
+
+int main() {
+glXMakeCurrent()
+; return 0; }
+EOF
+if { (eval echo configure:3428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_GL 1
+EOF
+ GLLIB="-lGL"
+else
+ echo "$ac_t""no" 1>&6
+\
+ echo $ac_n "checking for glXMakeCurrent in -lMesaGL""... $ac_c" 1>&6
+echo "configure:3451: checking for glXMakeCurrent in -lMesaGL" >&5
+ac_lib_var=`echo MesaGL'_'glXMakeCurrent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lMesaGL \
+ -L${ac_x_libraries} -lX11 -lXext $X_EXTRA_LIBS -lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3460 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char glXMakeCurrent();
+
+int main() {
+glXMakeCurrent()
+; return 0; }
+EOF
+if { (eval echo configure:3474: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_GL 1
+EOF
+ GLLIB=" -lMesaGL"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ac_safe=`echo "GL/glu.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for GL/glu.h""... $ac_c" 1>&6
+echo "configure:3507: checking for GL/glu.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3512 "configure"
+#include "confdefs.h"
+#include <GL/glu.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3517: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_GL_GLU_H 1
+EOF
+
+ if test x$ac_cv_lib_GL_glXMakeCurrent = xyes; then
+ GLLIB="-lGLU $GLLIB"
+ fi
+ if test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes; then
+ GLLIB="-lMesaGLU $GLLIB"
+ fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+
+
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+
+save_LIBS="$LIBS"
+LIBS="-lfltk ${GLLIB} -L${ac_x_libraries} -lXext -lX11 -lm $X_EXTRA_LIBS $LIBS"
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking for 'int fl_height (void)' in -lfltk""... $ac_c" 1>&6
+echo "configure:3612: checking for 'int fl_height (void)' in -lfltk" >&5
+if eval "test \"`echo '$''{'pose_cv_lib_fltk_found'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3617 "configure"
+#include "confdefs.h"
+#include <Fl/fl_draw.H>
+int main() {
+fl_height ();
+; return 0; }
+EOF
+if { (eval echo configure:3624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ pose_cv_lib_fltk_found=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ pose_cv_lib_fltk_found=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$pose_cv_lib_fltk_found" 1>&6
+
+LIBS="$save_LIBS"
+
+if test $pose_cv_lib_fltk_found = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LIBFLTK 1
+EOF
+
+else
+ { echo "configure: error: *** FLTK *must* be installed before running configure. ***" 1>&2; exit 1; }
+fi
+
+
+
+FLAGS="$FLAGS_COMMON $FLAGS_OPTIMIZE $FLAGS_PROFILE $FLAGS_PALM_PROFILE $FLAGS_DEBUG"
+POSER_CFLAGS="$POSER_CFLAGS $FLAGS $_WARNINGS_CFLAGS $_COMPILER_CFLAGS"
+POSER_CXXFLAGS="$POSER_CXXFLAGS $FLAGS $_WARNINGS_CXXFLAGS $_COMPILER_CXXFLAGS"
+
+
+
+
+
+
+
+
+
+
+
+
+if test x$USE_SOLARIS_CPP = xtrue; then
+ SOLARIS_TRUE=
+ SOLARIS_FALSE='#'
+else
+ SOLARIS_TRUE='#'
+ SOLARIS_FALSE=
+fi
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile Gzip/Makefile jpeg/Makefile espws-2.0/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@CXX@%$CXX%g
+s%@RANLIB@%$RANLIB%g
+s%@CPP@%$CPP%g
+s%@X_CFLAGS@%$X_CFLAGS%g
+s%@X_PRE_LIBS@%$X_PRE_LIBS%g
+s%@X_LIBS@%$X_LIBS%g
+s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
+s%@ALLOCA@%$ALLOCA%g
+s%@CXXCPP@%$CXXCPP%g
+s%@GLLIB@%$GLLIB%g
+s%@AR@%$AR%g
+s%@POSER_CFLAGS@%$POSER_CFLAGS%g
+s%@POSER_CXXFLAGS@%$POSER_CXXFLAGS%g
+s%@THREAD_FLAGS@%$THREAD_FLAGS%g
+s%@THREAD_LIBS@%$THREAD_LIBS%g
+s%@THREAD_SRC@%$THREAD_SRC%g
+s%@SOLARIS_TRUE@%$SOLARIS_TRUE%g
+s%@SOLARIS_FALSE@%$SOLARIS_FALSE%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile Gzip/Makefile jpeg/Makefile espws-2.0/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/BuildUnix/configure.in b/BuildUnix/configure.in
new file mode 100644
index 0000000..eda554f
--- /dev/null
+++ b/BuildUnix/configure.in
@@ -0,0 +1,394 @@
+dnl ======================================================================================
+dnl Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+dnl All rights reserved.
+dnl ======================================================================================
+
+dnl ========================================================
+dnl Process this file with autoconf to produce a configure script.
+dnl ========================================================
+
+AC_INIT(../SrcUnix/Platform_Unix.cpp)
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE(pose, 0, no)
+
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_RANLIB
+
+
+dnl ========================================================
+dnl Check for programs.
+dnl ========================================================
+
+AC_PROG_CPP
+
+
+dnl ========================================================
+dnl Check for libraries.
+dnl ========================================================
+
+AC_PATH_XTRA
+
+AC_ARG_WITH(fltk,
+ [ --with-fltk=DIR use FLTK in DIR], [
+ CPPFLAGS="${CPPFLAGS} -I$withval/include"
+ LDFLAGS="${LDFLAGS} -L$withval/lib"
+])
+
+
+dnl ========================================================
+dnl Check for header files.
+dnl ========================================================
+
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(endian.h machine/endian.h sys/isa_defs.h fcntl.h limits.h strings.h sys/time.h unistd.h)
+
+
+dnl ========================================================
+dnl Check for typedefs, structures, and compiler characteristics.
+dnl ========================================================
+
+AC_C_CONST
+AC_C_INLINE
+
+
+dnl ----------------------------
+dnl Check sa_len of sockaddr
+dnl ----------------------------
+
+AC_DEFUN(AC_STRUCT_SA_LEN,
+ [AC_CACHE_CHECK([for 'sa_len' in 'struct sockaddr'], ac_cv_struct_sa_len,
+ [AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ], [
+ struct sockaddr sa;
+ sa.sa_len = 0;
+ ], ac_cv_struct_sa_len=yes, ac_cv_struct_sa_len=no)])
+ if test "$ac_cv_struct_sa_len" = yes; then
+ AC_DEFINE(HAVE_SA_LEN)
+ fi])
+
+AC_DEFUN(AC_STRUCT_SIN_LEN,
+ [AC_CACHE_CHECK([for 'sin_len' in 'struct sockaddr_in'], ac_cv_struct_sin_len,
+ [AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ ], [
+ struct sockaddr_in sin;
+ sin.sin_len = 0;
+ ], ac_cv_struct_sin_len=yes, ac_cv_struct_sin_len=no)])
+ if test "$ac_cv_struct_sin_len" = yes; then
+ AC_DEFINE(HAVE_SIN_LEN)
+ fi])
+
+AC_DEFUN(AC_TYPE_SOCKLEN_T,
+ [AC_CACHE_CHECK([for 'socklen_t'], ac_cv_type_socklen_t,
+ [AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ], [
+ socklen_t var;
+ var = 0;
+ ], ac_cv_type_socklen_t=yes, ac_cv_type_socklen_t=no)])
+ if test "$ac_cv_type_socklen_t" = yes; then
+ AC_DEFINE(HAVE_TYPE_SOCKLEN_T)
+ fi])
+
+AC_STRUCT_SA_LEN
+AC_STRUCT_SIN_LEN
+AC_TYPE_SOCKLEN_T
+
+
+dnl ========================================================
+dnl Check for library functions.
+dnl ========================================================
+
+AC_FUNC_ALLOCA
+AC_CHECK_FUNCS(mkdir)
+AC_CHECK_FUNCS(mkstemp)
+AC_CHECK_FUNCS(tempnam)
+
+
+dnl ========================================================
+dnl Set the defaults first
+dnl ========================================================
+
+AR='ar'
+FLAGS_COMMON="-DPLATFORM_UNIX=1 -D__PALMOS_TRAPS__=0 -DEMULATION_LEVEL=EMULATION_UNIX"
+
+
+dnl ========================================================
+dnl Define some standard warning flags
+dnl ========================================================
+
+_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -fexceptions -Wall -Wno-multichar -Wno-unknown-pragmas -Wno-conversion"
+_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -fexceptions -Wall -Wno-multichar -Wno-unknown-pragmas -Wno-conversion"
+
+_COMPILER_CFLAGS="${_COMPILER_CFLAGS}"
+_COMPILER_CXXFLAGS="${_COMPILER_CXXFLAGS}"
+
+
+dnl ========================================================
+dnl Define the standard OMNITHREAD options
+dnl ========================================================
+
+THREAD_FLAGS="-D_REENTRANT -DNoNanoSleep -DPthreadDraftVersion=10"
+THREAD_LIBS="-lpthread"
+USE_SOLARIS_CPP="false"
+
+
+dnl ========================================================
+dnl System overrides of the defaults
+dnl ========================================================
+
+case "$target" in
+*-aix*)
+ THREAD_FLAGS="-DNoNanoSleep -DPthreadDraftVersion=8"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-hpux*)
+ THREAD_FLAGS="-D_REENTRANT -DPthreadDraftVersion=4"
+ THREAD_LIBS="-lpthread -lmach -lc_r"
+ ;;
+
+*-irix*)
+ THREAD_FLAGS="-DUsePthread -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-linux*)
+ THREAD_FLAGS="-D_REENTRANT -DNoNanoSleep -DPthreadDraftVersion=10"
+ THREAD_LIBS="-lpthread"
+ ;;
+
+*-nto*)
+ THREAD_FLAGS="-D_REENTRANT -DPthreadDraftVersion=10"
+ THREAD_LIBS=""
+ POSER_CFLAGS="$POSER_CFLAGS -D_QNX_SOURCE -D_POSIX_SOURCE -D__i386__ -D_i386 -DNSCAP_NO_EXPLICIT -DNO_REGEX -DSTRINGS_ALIGNED -D_SEEKPOS_DEFINED_ -I/usr/gcc/lib/gcc-lib/ntox86/2.8.1/include"
+ POSER_CXXFLAGS="$POSER_CFLAGS"
+ _WARNINGS_CFLAGS='-w'
+ _WARNINGS_CXXFLAGS='-w'
+ LIBS="$LIBS -lsocket"
+ poser_optimize="-O2"
+ poser_debug="-gdwarf-2"
+ AR='/usr/local/bin/ar.elf'
+ ;;
+
+*-osf*)
+dnl I am not sure how to test for these versions...
+dnl Options for OSF 1.3.2
+dnl THREAD_FLAGS="-D_REENTRANT -DNoNanoSleep -DPthreadDraftVersion=4"
+dnl THREAD_LIBS="-lpthread -lmach -lc_r"
+dnl Options for OSF 1.4
+ THREAD_FLAGS="-D_REENTRANT -pthread -DNoNanoSleep -DPthreadDraftVersion=10"
+ THREAD_LIBS="-lcma"
+ ;;
+
+*-solaris*)
+ # -g somehow helps the assembler understand long symbol names
+ THREAD_FLAGS="-g -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lnsl -lsocket -lthread -lposix4"
+dnl I'd really like to check the compiler directly to see if it supports -fpermissive,
+dnl but I don't know how to get autoconf to do that.
+ _COMPILER_CFLAGS="${_COMPILER_CFLAGS} -fpermissive"
+ _COMPILER_CXXFLAGS="${_COMPILER_CXXFLAGS} -fpermissive"
+ USE_SOLARIS_CPP="true"
+ ;;
+
+*-sunos*)
+ # -g somehow helps the assembler understand long symbol names
+ THREAD_FLAGS="-g -D_REENTRANT -DPthreadDraftVersion=10 -DPthreadSupportThreadPriority"
+ THREAD_LIBS="-lnsl -lsocket -lthread -lposix4"
+ USE_SOLARIS_CPP="true"
+ ;;
+
+*-freebsd*)
+ THREAD_FLAGS="-pthread -D_THREAD_SAFE -D_REENTRANT -DPthreadDraftVersion=10"
+ THREAD_LIBS=
+ ;;
+
+*-bsdi4*)
+ THREAD_LIBS=
+ ;;
+esac
+
+
+dnl ========================================================
+dnl Check for gprof profiling
+dnl ========================================================
+
+AC_ARG_ENABLE(profile,
+ [ --enable-profile include gprof profiling (default no)],
+ FLAGS_PROFILE="-pg",
+ FLAGS_PROFILE="")
+
+
+dnl ========================================================
+dnl Check for built-in profiling
+dnl ========================================================
+
+AC_ARG_ENABLE(palm_profile,
+ [ --enable-palm-profile include profiling of Palm applications (default no)],
+ FLAGS_PALM_PROFILE="-DHAS_PROFILING=1",
+ FLAGS_PALM_PROFILE="-DHAS_PROFILING=0")
+
+
+dnl ========================================================
+dnl Check for static link.
+dnl ========================================================
+
+AC_ARG_ENABLE(static-link,
+ [ --enable-static-link static link; no shared libraries (default no)],
+ LDFLAGS="${LDFLAGS} -static"
+)
+
+
+dnl ========================================================
+dnl Check for Optimize
+dnl
+dnl NOTE: turning on optimizations when using egcs 1.1.2
+dnl runs afoul of a code generation bug on x86's (as
+dnl shipped with RedHat 6.0). The specific cases I know
+dnl about (in SkinScaleDown and SkinScaleUp) are coded
+dnl around, but there may be more lurking...
+dnl
+dnl I haven't checked this, but I hear the bug is fixed
+dnl in gcc 2.95.
+dnl ========================================================
+
+dnl This is now on by default. It gets turned off if the
+dnl user selects --enable-debug.
+dnl
+dnl AC_ARG_ENABLE(optimize,
+dnl [ --enable-optimize optimize code (default no)],
+dnl FLAGS_OPTIMIZE="-O2",
+dnl FLAGS_OPTIMIZE="")
+
+FLAGS_OPTIMIZE="-O2"
+
+
+dnl ========================================================
+dnl Check whether default arguments which call a virtual
+dnl function in another object work -- GCC 2.95.x crashes
+dnl trying to compile something like this.
+dnl ========================================================
+
+AC_LANG_CPLUSPLUS
+AC_CACHE_CHECK([whether virtual function default arguments work],
+ pose_cv_virtual_defarg_ok,
+ AC_TRY_COMPILE([
+ class C
+ {
+ public:
+ virtual int foo ();
+ } *c;
+ void bar (int = c->foo ());
+ ], [bar ();],
+ pose_cv_virtual_defarg_ok=yes, pose_cv_virtual_defarg_ok=no))
+
+if test $pose_cv_virtual_defarg_ok = no; then
+ AC_DEFINE(BROKEN_VIRTUAL_DEFAULT_ARGUMENTS)
+fi
+
+
+dnl ========================================================
+dnl Check for debugging
+dnl ========================================================
+
+AC_ARG_ENABLE(debug,
+ [ --enable-debug include debugging symbols (default no)],
+ FLAGS_DEBUG="-D_DEBUG -g"
+ FLAGS_PROFILE="-DHAS_PROFILING=1"
+ FLAGS_PALM_PROFILE=""
+ FLAGS_OPTIMIZE="",
+ FLAGS_DEBUG="-DNDEBUG")
+
+
+dnl ========================================================
+dnl Check for OpenGL. This is pretty much the same code
+dnl that FLTK uses to check for it. We'll assume that if
+dnl OpenGL is present, FLTK was configured to use it, and
+dnl so we need to link with it.
+dnl ========================================================
+
+GLLIB=
+
+AC_CHECK_HEADER(GL/gl.h,
+ AC_CHECK_LIB(GL, glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB="-lGL", \
+ AC_CHECK_LIB(MesaGL, glXMakeCurrent, AC_DEFINE(HAVE_GL) GLLIB=" -lMesaGL",,\
+ -L${ac_x_libraries} -lX11 -lXext $X_EXTRA_LIBS -lm), \
+ -L${ac_x_libraries} -lX11 -lXext $X_EXTRA_LIBS -lm)
+)
+
+AC_CHECK_HEADER(GL/glu.h,
+ AC_DEFINE(HAVE_GL_GLU_H)
+ if test x$ac_cv_lib_GL_glXMakeCurrent = xyes; then
+ GLLIB="-lGLU $GLLIB"
+ fi
+ if test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes; then
+ GLLIB="-lMesaGLU $GLLIB"
+ fi
+)
+
+AC_SUBST(GLLIB)
+
+
+dnl ========================================================
+dnl Make sure FLTK is available. It must be installed on
+dnl a standard path, or on $x_libraries.
+dnl ========================================================
+
+AC_CACHE_SAVE
+
+dnl Temporarily add -lfltk and OTHER-LIBRARIES (cf AC_CHECK_LIB) to $LIBS
+save_LIBS="$LIBS"
+LIBS="-lfltk ${GLLIB} -L${ac_x_libraries} -lXext -lX11 -lm $X_EXTRA_LIBS $LIBS"
+
+AC_LANG_CPLUSPLUS
+AC_CACHE_CHECK([for 'int fl_height (void)' in -lfltk], pose_cv_lib_fltk_found,
+ AC_TRY_LINK([#include <Fl/fl_draw.H>], [fl_height ();],
+ pose_cv_lib_fltk_found=yes, pose_cv_lib_fltk_found=no))
+
+LIBS="$save_LIBS"
+
+if test $pose_cv_lib_fltk_found = yes; then
+ AC_DEFINE(HAVE_LIBFLTK)
+else
+ AC_MSG_ERROR(*** FLTK *must* be installed before running configure. ***)
+fi
+
+
+dnl ========================================================
+dnl = Append the FLAGS variable that contains options for
+dnl = debug, profiling and optimizing poser.
+dnl ========================================================
+
+FLAGS="$FLAGS_COMMON $FLAGS_OPTIMIZE $FLAGS_PROFILE $FLAGS_PALM_PROFILE $FLAGS_DEBUG"
+POSER_CFLAGS="$POSER_CFLAGS $FLAGS $_WARNINGS_CFLAGS $_COMPILER_CFLAGS"
+POSER_CXXFLAGS="$POSER_CXXFLAGS $FLAGS $_WARNINGS_CXXFLAGS $_COMPILER_CXXFLAGS"
+
+AC_SUBST(AR)
+AC_SUBST(POSER_CFLAGS)
+AC_SUBST(POSER_CXXFLAGS)
+AC_SUBST(THREAD_FLAGS)
+AC_SUBST(THREAD_LIBS)
+AC_SUBST(THREAD_SRC)
+
+
+dnl ========================================================
+dnl Determine which file to use for threading support. NB:
+dnl this may be obvious to most UNIX hacks, but it's very
+dnl important to put spaces around the '='. I didn't do
+dnl that the first time, and I guess "test" needs those
+dnl in order to know that '=' is an operator. Without the
+dnl spaces, I got incorrect results.
+dnl ========================================================
+
+AM_CONDITIONAL(SOLARIS, test x$USE_SOLARIS_CPP = xtrue)
+
+AC_OUTPUT(Makefile Gzip/Makefile jpeg/Makefile espws-2.0/Makefile)
diff --git a/BuildUnix/espws-2.0/Makefile.am b/BuildUnix/espws-2.0/Makefile.am
new file mode 100644
index 0000000..b52a443
--- /dev/null
+++ b/BuildUnix/espws-2.0/Makefile.am
@@ -0,0 +1,33 @@
+## -*- mode: Makefile; tab-width: 4; -*-
+## ======================================================================================
+## Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+## All rights reserved.
+## ======================================================================================
+
+##
+## makefile.am for poser-specific espws code
+##
+SUFFIXES = .cxx
+
+VPATH = $(srcdir)/../../SrcUnix/espws-2.0:
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS) $(X_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS) $(X_CFLAGS)
+
+INCLUDES = -I$(srddir)/../../SrcUnix/espws-2.0
+
+noinst_LIBRARIES = libposerespws.a
+
+SRC_ESPWS = CheckButton.cxx \
+ FileBrowser.cxx \
+ FileChooser.cxx \
+ FileChooser2.cxx \
+ FileIcon.cxx \
+ FileInput.cxx \
+ Fl_Wizard.cxx \
+ HelpApp.cxx \
+ HelpApp2.cxx \
+ HelpDialog.cxx \
+ HelpView.cxx
+
+libposerespws_a_SOURCES = $(SRC_ESPWS)
diff --git a/BuildUnix/espws-2.0/Makefile.in b/BuildUnix/espws-2.0/Makefile.in
new file mode 100644
index 0000000..c148251
--- /dev/null
+++ b/BuildUnix/espws-2.0/Makefile.in
@@ -0,0 +1,348 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+CC = @CC@
+CPP = @CPP@
+CXX = @CXX@
+GLLIB = @GLLIB@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+POSER_CFLAGS = @POSER_CFLAGS@
+POSER_CXXFLAGS = @POSER_CXXFLAGS@
+RANLIB = @RANLIB@
+THREAD_FLAGS = @THREAD_FLAGS@
+THREAD_LIBS = @THREAD_LIBS@
+THREAD_SRC = @THREAD_SRC@
+VERSION = @VERSION@
+
+SUFFIXES = .cxx
+
+VPATH = $(srcdir)/../../SrcUnix/espws-2.0:
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS) $(X_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS) $(X_CFLAGS)
+
+INCLUDES = -I$(srddir)/../../SrcUnix/espws-2.0
+
+noinst_LIBRARIES = libposerespws.a
+
+SRC_ESPWS = CheckButton.cxx FileBrowser.cxx FileChooser.cxx FileChooser2.cxx FileIcon.cxx FileInput.cxx Fl_Wizard.cxx HelpApp.cxx HelpApp2.cxx HelpDialog.cxx HelpView.cxx
+
+
+libposerespws_a_SOURCES = $(SRC_ESPWS)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libposerespws_a_LIBADD =
+libposerespws_a_OBJECTS = CheckButton.o FileBrowser.o FileChooser.o \
+FileChooser2.o FileIcon.o FileInput.o Fl_Wizard.o HelpApp.o HelpApp2.o \
+HelpDialog.o HelpView.o
+CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/CheckButton.P .deps/FileBrowser.P .deps/FileChooser.P \
+.deps/FileChooser2.P .deps/FileIcon.P .deps/FileInput.P \
+.deps/Fl_Wizard.P .deps/HelpApp.P .deps/HelpApp2.P .deps/HelpDialog.P \
+.deps/HelpView.P
+SOURCES = $(libposerespws_a_SOURCES)
+OBJECTS = $(libposerespws_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cxx .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign espws-2.0/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libposerespws.a: $(libposerespws_a_OBJECTS) $(libposerespws_a_DEPENDENCIES)
+ -rm -f libposerespws.a
+ $(AR) cru libposerespws.a $(libposerespws_a_OBJECTS) $(libposerespws_a_LIBADD)
+ $(RANLIB) libposerespws.a
+.cxx.o:
+ $(CXXCOMPILE) -c $<
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = espws-2.0
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign espws-2.0/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+
+%.o: %.cxx
+ @echo '$(CXXCOMPILE) -c $<'; \
+ $(CXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.cxx
+ @echo '$(LTCXXCOMPILE) -c $<'; \
+ $(LTCXXCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/BuildUnix/install-sh b/BuildUnix/install-sh
new file mode 100755
index 0000000..e843669
--- /dev/null
+++ b/BuildUnix/install-sh
@@ -0,0 +1,250 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/BuildUnix/jpeg/Makefile.am b/BuildUnix/jpeg/Makefile.am
new file mode 100644
index 0000000..7f2bec6
--- /dev/null
+++ b/BuildUnix/jpeg/Makefile.am
@@ -0,0 +1,84 @@
+## -*- mode: Makefile; tab-width: 4; -*-
+## ======================================================================================
+## Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+## All rights reserved.
+## ======================================================================================
+
+##
+## makefile.am for poser-specific jpeg code
+##
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../../SrcShared/jpeg:
+
+## no subdir specific flags needed -- just go with globals
+LOCAL_CFLAGS =
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS)
+
+INCLUDES = -I$(srcdir)/../../SrcShared/jpeg \
+ -I$(srcdir)/../../SrcUnix
+
+noinst_LIBRARIES = libposerjpeg.a
+
+SRC_JPEG = cderror.h \
+ jcapimin.c \
+ jcapistd.c \
+ jccoefct.c \
+ jccolor.c \
+ jcdctmgr.c \
+ jchuff.c \
+ jchuff.h \
+ jcinit.c \
+ jcmainct.c \
+ jcmarker.c \
+ jcmaster.c \
+ jcomapi.c \
+ jconfig.h \
+ jcparam.c \
+ jcphuff.c \
+ jcprepct.c \
+ jcsample.c \
+ jctrans.c \
+ jdapimin.c \
+ jdapistd.c \
+ jdatadst.c \
+ jdatasrc.c \
+ jdcoefct.c \
+ jdcolor.c \
+ jdct.h \
+ jddctmgr.c \
+ jdhuff.c \
+ jdhuff.h \
+ jdinput.c \
+ jdmainct.c \
+ jdmarker.c \
+ jdmaster.c \
+ jdmerge.c \
+ jdphuff.c \
+ jdpostct.c \
+ jdsample.c \
+ jdtrans.c \
+ jerror.c \
+ jerror.h \
+ jfdctflt.c \
+ jfdctfst.c \
+ jfdctint.c \
+ jidctflt.c \
+ jidctfst.c \
+ jidctint.c \
+ jidctred.c \
+ jinclude.h \
+ jmemmgr.c \
+ jmemnobs.c \
+ jmemsys.h \
+ jmorecfg.h \
+ jpegint.h \
+ jpeglib.h \
+ jquant1.c \
+ jquant2.c \
+ jutils.c \
+ jversion.h
+
+libposerjpeg_a_SOURCES = $(SRC_JPEG)
diff --git a/BuildUnix/jpeg/Makefile.in b/BuildUnix/jpeg/Makefile.in
new file mode 100644
index 0000000..9b0c1e1
--- /dev/null
+++ b/BuildUnix/jpeg/Makefile.in
@@ -0,0 +1,343 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+CC = @CC@
+CPP = @CPP@
+CXX = @CXX@
+GLLIB = @GLLIB@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+POSER_CFLAGS = @POSER_CFLAGS@
+POSER_CXXFLAGS = @POSER_CXXFLAGS@
+RANLIB = @RANLIB@
+THREAD_FLAGS = @THREAD_FLAGS@
+THREAD_LIBS = @THREAD_LIBS@
+THREAD_SRC = @THREAD_SRC@
+VERSION = @VERSION@
+
+SUFFIXES = .cpp
+
+VPATH = $(srcdir)/../../SrcShared/jpeg:
+
+LOCAL_CFLAGS =
+
+CFLAGS = $(POSER_CFLAGS) $(LOCAL_CFLAGS)
+CXXFLAGS = $(POSER_CXXFLAGS) $(LOCAL_CFLAGS)
+
+INCLUDES = -I$(srcdir)/../../SrcShared/jpeg -I$(srcdir)/../../SrcUnix
+
+
+noinst_LIBRARIES = libposerjpeg.a
+
+SRC_JPEG = cderror.h jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jchuff.h jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jconfig.h jcparam.c jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jdct.h jddctmgr.c jdhuff.c jdhuff.h jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c jdpostct.c jdsample.c jdtrans.c jerror.c jerror.h jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jinclude.h jmemmgr.c jmemnobs.c jmemsys.h jmorecfg.h jpegint.h jpeglib.h jquant1.c jquant2.c jutils.c jversion.h
+
+
+libposerjpeg_a_SOURCES = $(SRC_JPEG)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libposerjpeg_a_LIBADD =
+libposerjpeg_a_OBJECTS = jcapimin.o jcapistd.o jccoefct.o jccolor.o \
+jcdctmgr.o jchuff.o jcinit.o jcmainct.o jcmarker.o jcmaster.o jcomapi.o \
+jcparam.o jcphuff.o jcprepct.o jcsample.o jctrans.o jdapimin.o \
+jdapistd.o jdatadst.o jdatasrc.o jdcoefct.o jdcolor.o jddctmgr.o \
+jdhuff.o jdinput.o jdmainct.o jdmarker.o jdmaster.o jdmerge.o jdphuff.o \
+jdpostct.o jdsample.o jdtrans.o jerror.o jfdctflt.o jfdctfst.o \
+jfdctint.o jidctflt.o jidctfst.o jidctint.o jidctred.o jmemmgr.o \
+jmemnobs.o jquant1.o jquant2.o jutils.o
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/jcapimin.P .deps/jcapistd.P .deps/jccoefct.P \
+.deps/jccolor.P .deps/jcdctmgr.P .deps/jchuff.P .deps/jcinit.P \
+.deps/jcmainct.P .deps/jcmarker.P .deps/jcmaster.P .deps/jcomapi.P \
+.deps/jcparam.P .deps/jcphuff.P .deps/jcprepct.P .deps/jcsample.P \
+.deps/jctrans.P .deps/jdapimin.P .deps/jdapistd.P .deps/jdatadst.P \
+.deps/jdatasrc.P .deps/jdcoefct.P .deps/jdcolor.P .deps/jddctmgr.P \
+.deps/jdhuff.P .deps/jdinput.P .deps/jdmainct.P .deps/jdmarker.P \
+.deps/jdmaster.P .deps/jdmerge.P .deps/jdphuff.P .deps/jdpostct.P \
+.deps/jdsample.P .deps/jdtrans.P .deps/jerror.P .deps/jfdctflt.P \
+.deps/jfdctfst.P .deps/jfdctint.P .deps/jidctflt.P .deps/jidctfst.P \
+.deps/jidctint.P .deps/jidctred.P .deps/jmemmgr.P .deps/jmemnobs.P \
+.deps/jquant1.P .deps/jquant2.P .deps/jutils.P
+SOURCES = $(libposerjpeg_a_SOURCES)
+OBJECTS = $(libposerjpeg_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .cpp .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign jpeg/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libposerjpeg.a: $(libposerjpeg_a_OBJECTS) $(libposerjpeg_a_DEPENDENCIES)
+ -rm -f libposerjpeg.a
+ $(AR) cru libposerjpeg.a $(libposerjpeg_a_OBJECTS) $(libposerjpeg_a_LIBADD)
+ $(RANLIB) libposerjpeg.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = jpeg
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --foreign jpeg/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/BuildUnix/missing b/BuildUnix/missing
new file mode 100755
index 0000000..cbe2b0e
--- /dev/null
+++ b/BuildUnix/missing
@@ -0,0 +1,188 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in`
+ if test -z "$files"; then
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in`
+ test -z "$files" || files="$files.in"
+ else
+ files=`echo "$files" | sed -e 's/:/ /g'`
+ fi
+ test -z "$files" && files="config.h.in"
+ touch $files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print \
+ | sed 's/^\(.*\).am$/touch \1.in/' \
+ | sh
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/BuildUnix/mkinstalldirs b/BuildUnix/mkinstalldirs
new file mode 100755
index 0000000..a01481b
--- /dev/null
+++ b/BuildUnix/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/Docs/12rollin.pdf b/Docs/12rollin.pdf
new file mode 100644
index 0000000..91e45e6
--- /dev/null
+++ b/Docs/12rollin.pdf
Binary files differ
diff --git a/Docs/13hewgil.pdf b/Docs/13hewgil.pdf
new file mode 100644
index 0000000..e71e5c3
--- /dev/null
+++ b/Docs/13hewgil.pdf
Binary files differ
diff --git a/Docs/Debugger.html b/Docs/Debugger.html
new file mode 100644
index 0000000..88669cd
--- /dev/null
+++ b/Docs/Debugger.html
@@ -0,0 +1,854 @@
+<HTML>
+<!--This file created 3:45 AM 8/23/99 by Claris Home Page version 3.0-->
+<HEAD>
+ <TITLE>Debugger</TITLE>
+ <META NAME=GENERATOR CONTENT="Claris Home Page 3.0">
+ <X-CLARIS-WINDOW TOP=23 BOTTOM=859 LEFT=623 RIGHT=1234>
+ <X-CLARIS-TAGVIEW MODE=minimal>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"><META NAME="Author" CONTENT="Keith Rollin">
+</HEAD>
+<BODY>
+<H1><CENTER>Palm Debugger Protocol</CENTER></H1>
+
+<CENTER><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="80%">
+ <TR>
+ <TD>
+ <H3>Document Order</H3>
+ </TD>
+ <TD>
+ <H3>Alphabetical Order</H3>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Overview">Overview</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Continue Command">Continue Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#State Command">State Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Find Command">Find Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Read Memory Command">Read Memory
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Get Breakpoints Command">Get Breakpoints
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Write Memory Command">Write Memory
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Get Routine Name Command">Get Routine Name
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Single Step Command">Single Step
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Get Trap Breaks Command">Get Trap Breaks
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Get Routine Name Command">Get Routine Name
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Get Trap Conditionals Command">Get Trap
+ Conditionals Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Read Registers Command">Read Registers
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Message Command">Message Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Write Registers Command">Write Registers
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Overview">Overview</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Continue Command">Continue Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Read Memory Command">Read Memory
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Get Breakpoints Command">Get Breakpoints
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Read Registers Command">Read Registers
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Set Breakpoints Command">Set Breakpoints
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#RPC Command">RPC Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Toggle Debugger Breaks Command">Toggle Debugger
+ Breaks Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Set Breakpoints Command">Set Breakpoints
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Get Trap Breaks Command">Get Trap Breaks
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Set Trap Breaks Command">Set Trap Breaks
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Set Trap Breaks Command">Set Trap Breaks
+ Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Set Trap Conditionals Command">Set Trap
+ Conditionals Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Find Command">Find Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Single Step Command">Single Step
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Message Command">Message Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#State Command">State Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#RPC Command">RPC Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Toggle Debugger Breaks Command">Toggle Debugger
+ Breaks Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Get Trap Conditionals Command">Get Trap
+ Conditionals Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Write Memory Command">Write Memory
+ Command</A></P>
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ <P><A HREF="#Set Trap Conditionals Command">Set Trap
+ Conditionals Command</A></P>
+ </TD>
+ <TD>
+ <P><A HREF="#Write Registers Command">Write Registers
+ Command</A></P>
+ </TD>
+ </TR>
+</TABLE>
+</CENTER>
+
+<H3><A NAME=Overview></A>Overview</H3>
+
+<P>In this document, "target" refers to the object being debugged.
+This could be the Palm ROM, or Palm OS&nbsp;Emulator. "Host" refers
+to the debugger, which could be either the Metrowerks debugger or the
+Palm Debugger. The target side of the debugger communicates by
+sending command packets to the user interface on the host side.
+Basically, the target side acts as a slave to the host, carrying out
+commands and reporting back results.</P>
+
+<P>The target side must be able to respond to some basic command
+types sent from the host side. These are: get state, display memory,
+set memory, single step, get routine name, display registers, set
+registers, continue, set breakpoint, clear breakpoint, set a-trap,
+clear a-trap, find, and remote procedure call. All high-level
+commands that a user enters from the host side are broken down into
+one or more of these basic target commands, which are then sent to
+the target.</P>
+
+<P>A command packet can be a request packet, response packet, or
+message packet. Request packets are sent from the host to the target
+and must be answered by an appropriate response packet from the
+target. Message packets are sent from either the target or the host
+and merely report status information and do not require a response
+from the recipient.</P>
+
+<P>There is no extensive protocol involved between the host and
+target. Basically, the host sends a request packet and waits for a
+response from the target, or a timeout. If a response is not detected
+by the timeout period, the host does not retry the request but could
+display a message to the user saying that the target is not
+responding. Usually, if the target does not respond, it means either
+that the target is currently executing code and has not encountered a
+breakpoint, or that the target is so messed up that it can't even run
+the debugger.</P>
+
+<P>Figure 1 shows the structure of request, response, and message
+packets. <FONT FACE="Times">Basically, every packet consists of a
+packet header, a variable length packet body, and a packet footer.
+The maximim size of a packet body is 272 bytes. The packet header
+starts with the key 24-bit value $BEEFED and includes packet header
+information and a checksum of just the header itself. The packet
+footer contains a 16-bit CRC of the header and body (not
+footer).</FONT></P>
+
+<P><FONT FACE="Times">Following the 24-bit value $BEEFED at the start
+of the packet header is a destination socket ID byte, a source socket
+ID byte, a packet type byte, a 2 byte body size, a transaction ID
+byte, and an 8 bit checksum of the header. The destination and source
+socket IDs and the packet type bytes are always 0 for debugger
+packets. The bodySize field is the number of bytes that are in the
+body - which will depend on the particular command being sent. The
+transaction ID is an 8 bit value that gets incremented every time a
+command is sent from the host. In order for a response packet from
+the target to be recognized by the host, its transaction ID must
+match the transaction ID of the original request packet.</FONT></P>
+
+<P><FONT FACE="Times">The packet body starts with a command byte
+immediately followed by a filler byte. </FONT>The command byte
+encodes the particular command being sent or acknowledged. Request
+packets always have the upper bit of the command byte clear, response
+packets have the upper bit set. Each command has it's own specific
+structure following the command and filler bytes.&nbsp;</P>
+
+<P>&nbsp;</P>
+
+<P><TT> +--------------------+<BR>
+ | $BE (1) |<BR>
+ | $EF (1) |<BR>
+ | $ED (1) |<BR>
+ | dest ID (1) | Header (10 bytes)<BR>
+ | src ID (1) |<BR>
+ | type (1) |<BR>
+ | bodySize (2) |<BR>
+ | transID (1) |<BR>
+ | checkSum (1) |<BR>
+ +--------------------+<BR>
+ | command (1) |<BR>
+ | filler (1) | Body (2-272 bytes)<BR>
+ | variable size data |<BR>
+ +--------------------+<BR>
+ | CRC (2) | Footer (2 bytes)<BR>
+ +--------------------+<BR>
+</TT></P>
+
+<CENTER><B>Figure 1 - Structure of Packets</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="State Command"></A>State Command</H3>
+
+<P>Figure 2 shows the structure of the request and response bodies
+for the state command. The host sends this command in order to
+determine the current state of the target, including the current
+program counter, the values of all the registers, the reason why the
+target entered the debugger, the current breakpoints, and the name of
+the routine that the program counter is in. The target will also send
+a state response packet to the host whenever it encounters an
+exception and enters the debugger - whether due to a breakpoint, bus
+error, single step, etc. This is the only time a response packet is
+sent to the host without a corresponding request packet from the
+host.</P>
+
+<PRE><TT>#define sysPktStateCmd&nbsp;&nbsp;&nbsp; 0x00
+#define sysPktStateRsp&nbsp;&nbsp;&nbsp; 0x80</TT></PRE>
+
+<BLOCKQUOTE><PRE><I><TT>Max length of a routine name</TT></I></PRE></BLOCKQUOTE>
+
+<PRE><TT>#define sysPktMaxNameLen&nbsp; 32</TT></PRE>
+
+<BLOCKQUOTE><PRE><I><TT>Number of remote code words to send in the 'state response' packet</TT></I></PRE></BLOCKQUOTE>
+
+<PRE><TT>#define sysPktStateRspInstWords&nbsp; 15
+#define dbgNormalBreakpoints&nbsp;&nbsp;&nbsp;&nbsp; 5
+#define dbgTempBPIndex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbgNormalBreakpoints
+#define dbgTotalBreakpoints&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (dbgTempBPIndex+1)
+typedef struct BreakpointType
+{
+&nbsp;&nbsp;&nbsp; Ptr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; addr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // address of breakpoint
+&nbsp;&nbsp;&nbsp; Boolean&nbsp; enabled;&nbsp;&nbsp;&nbsp;&nbsp; // true if enabled
+&nbsp;&nbsp;&nbsp; Boolean&nbsp; installed;&nbsp;&nbsp; // for alignment
+} BreakpointType;
+&nbsp;
+typedef struct SysPktStateCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp;&nbsp; // Common Body header
+} SysPktStateCmdCmdType;</TT></PRE>
+
+<BLOCKQUOTE><PRE><I><TT>Packet Body structure for the state command response packet</TT></I></PRE></BLOCKQUOTE>
+
+<PRE><TT>typedef struct SysPktStateRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; Boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; resetted;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // true if target has just reset
+&nbsp;&nbsp;&nbsp; Word&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exceptionId;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // exception which caused the
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // debugger to be entered.
+&nbsp;&nbsp;&nbsp; M68KregsType&nbsp;&nbsp; reg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // current remote registers.
+&nbsp;&nbsp;&nbsp; Word&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inst&#91;sysPktStateRspInstWords&#93;;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // instruction buffer for
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // code beginning at PC.
+&nbsp;&nbsp;&nbsp; BreakpointType bp&#91;dbgTotalBreakpoints&#93;; // current breakpoints
+&nbsp;&nbsp;&nbsp; void*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // start address of routine
+&nbsp;&nbsp;&nbsp; void*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // end address of routine
+&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name&#91;sysPktMaxNameLen&#93;;&nbsp; // routine name (0 or more chars),
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // immediately follows the address range.
+&nbsp;&nbsp;&nbsp; Byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trapTableRev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // rev of trap table. Used to determine
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when host's trap table cache is invalid
+} SysPktStateRspType;</TT></PRE>
+
+<CENTER><B>Figure 2 - State Command</B></CENTER>
+
+<P>The resetted field is non-zero if the target has reset itself
+since the last time the debugger was entered. The host can use the
+exceptionID field to determine why the debugger on the target was
+entered because it contains the address of the exception vector: $8
+for a bus error, $7C for a non-maskable interrupt, etc. The 8 data
+registers are stored in the packet body starting from D0. The 7
+address registers are stored starting from A0. The instruction buffer
+contains the next 30 bytes of code starting from the current program
+counter. The breakpoint list contains the list of the current
+breakpoints on the device. This is a fixed length list of 6
+breakpoints - unused entries will have 0 in the enabled and installed
+fields. The last breakpoint in the list (breakpoint #5) is used
+exclusively for temporary breakpoints installed by the debugger for
+implementing commands like GoTill (gt).</P>
+
+<P>The routineStart, routineEnd, and routineName fields contain the
+starting and ending address and name of the current routine. The
+target side of the debugger determines this information. A routine
+name is placed at the end of every routine by the compiler and the
+target side of the debugger scans forward and backwards from the
+current program counter to determine this information.</P>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Read Memory Command"></A>Read Memory Command</H3>
+
+<P>Figure 3 shows the structure of the request and response bodies
+for the read command. This command is sent by the host in order to
+read memory on the target. It can return up to 256 bytes of data. The
+size of the response body depends on the number of bytes requested in
+the request packet.</P>
+
+<PRE><TT>#define sysPktReadMemCmd&nbsp;&nbsp; 0x01
+#define sysPktReadMemRsp&nbsp;&nbsp; 0x81
+&nbsp;
+typedef struct SysPktReadMemCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; void*&nbsp; address;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Address to read
+&nbsp;&nbsp;&nbsp; Word&nbsp; numBytes;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // # of bytes to read
+} SysPktReadMemCmdType;
+&nbsp;
+typedef struct SysPktReadMemRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;// Byte&nbsp; data&#91;?&#93;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // variable size
+} SysPktReadMemRspType;</TT></PRE>
+
+<CENTER><B>Figure 3 - Read Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Write Memory Command"></A>Write Memory Command</H3>
+
+<P>Figure 4 shows the structure of the request and response bodies
+for the write command. This command is sent by the host in order to
+write memory on the target. It can write up to 256 bytes of data. The
+size of the request packet depends on the number of bytes that need
+to be written.</P>
+
+<PRE><TT>#define sysPktWriteMemCmd&nbsp;&nbsp; 0x02
+#define sysPktWriteMemRsp&nbsp;&nbsp; 0x82
+&nbsp;
+typedef struct SysPktWriteMemCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; void*&nbsp; address;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Address to write
+&nbsp;&nbsp;&nbsp; Word&nbsp; numBytes;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // # of bytes to write
+&nbsp;// Byte&nbsp; data&#91;?&#93;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // variable size data
+} SysPktWriteMemCmdType;
+&nbsp;
+typedef struct SysPktWriteMemRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktWriteMemRspType;</TT></PRE>
+
+<CENTER><B>Figure 4 - Write Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Single Step Command"></A>Single Step Command</H3>
+
+<P><STRIKE>Figure 5 shows the structure of the request and response
+bodies for the singleStep command. This command is sent by the host
+to tell the target to execute the next instruction. This command and
+the continue command (see below) are unique in that they do not get a
+respective response back from the target. The host relies on the fact
+that when the target re-enters the debugger it will automatically
+send a state response packet. In this case, the target will re-enter
+the debugger immediately after executing the next
+instruction.</STRIKE></P>
+
+<PRE><TT><STRIKE>#define sysPktSingleStepCmd&nbsp;&nbsp; 0x03</STRIKE></TT></PRE>
+
+<CENTER><B><STRIKE>Figure 5 - Single Step
+Command</STRIKE></B></CENTER>
+
+<P>Note: there is no actual single step command implemented in either
+the ROM or the Palm OS Emulator. Instead, this functionality is
+performed by setting the trace bit in the Status Register and
+executing a sysPktContinueCmd.</P>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Get Routine Name Command"></A>Get Routine Name
+Command</H3>
+
+<P>Figure 6 shows the structure of the request and response bodies
+for the getRoutineName command. The host sends this command to
+determine which routine a particular address is in. It will return
+the starting and ending address of the routine and the name. The name
+of each routine is imbedded into the code when it's compiled and the
+target can determine the starting and ending address and name of the
+routine by scanning forwards and backwards in the code for this
+information.</P>
+
+<PRE><TT>#define sysPktGetRtnNameCmd&nbsp;&nbsp; 0x04
+#define sysPktGetRtnNameRsp&nbsp;&nbsp; 0x84
+&nbsp;
+typedef struct SysPktRtnNameCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; void*&nbsp; address;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // -&gt; address to query on
+} SysPktRtnNameCmdType;
+&nbsp;
+typedef struct SysPktRtnNameRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; void*&nbsp; address;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // -&gt; address to query on
+&nbsp;&nbsp;&nbsp; void*&nbsp; startAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // &lt;- start address of routine
+&nbsp;&nbsp;&nbsp; void*&nbsp; endAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // &lt;- end address of routine
+&nbsp;&nbsp;&nbsp; char&nbsp; name&#91;sysPktMaxNameLen&#93;; // &lt;- routine name, if any immediately
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; follows the address range.
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; The balance need not be sent.
+} SysPktRtnNameRspType;</TT></PRE>
+
+<CENTER><B>Figure 6 - Get Routine Name Command</B></CENTER>
+
+<P>The address field in the response body is a copy of the address
+sent in the request. The startAddr and endAddr fields are the
+starting and ending address of the routine that includes address. The
+name field is the 0 terminated name of the routine. If the target can
+not determine which routine address is in, it will return 0 for the
+first byte of the name in the response body and endAddr will contain
+the last address that it scanned in trying to find out the routine
+name. Subsequent getRoutineName calls should use the endAddr from the
+previous call in order to look for more routines.</P>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Read Registers Command"></A>Read Registers Command</H3>
+
+<P>Figure 7 shows the structure of the request and response bodies
+for the readRegisters command. This command is sent by the host to
+get the value of each of the processor registers on the target. The 8
+data registers are stored in the packet body starting from D0. The 7
+address registers are stored starting from A0.</P>
+
+<PRE><TT>#define sysPktReadRegsCmd&nbsp;&nbsp; 0x05
+#define sysPktReadRegsRsp&nbsp;&nbsp; 0x85
+&nbsp;
+typedef struct SysPktReadRegsCmdTyp
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktReadRegsCmdType;
+&nbsp;
+typedef struct SysPktReadRegsRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; M68KRegsType reg;&nbsp;&nbsp; // &lt;- return registers
+} SysPktReadRegsRspType;</TT></PRE>
+
+<CENTER><B>Figure 7 - Read Registers Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Write Registers Command"></A>Write Registers
+Command</H3>
+
+<P>Figure 8 shows the structure of the request and response bodies
+for the writeRegisters command. This command is sent by the host to
+set the value of each of the processor registers on the target. The 8
+data registers are stored in the packet body starting from D0. The 7
+address registers are stored starting from A0.</P>
+
+<PRE><TT>#define sysPktWriteRegsCmd&nbsp;&nbsp; 0x06
+#define sysPktWriteRegsRsp&nbsp;&nbsp; 0x86
+&nbsp;
+typedef struct SysPktWriteRegsCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; M68KRegsType reg;&nbsp;&nbsp;&nbsp; // -&gt; registers to write
+} SysPktWriteRegsCmdType;
+&nbsp;
+typedef struct SysPktWriteRegsRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktWriteRegsRspType;</TT></PRE>
+
+<CENTER><B>Figure 8 - Write Registers Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Continue Command"></A>Continue Command</H3>
+
+<P>Figure 9 shows the structure of the request and response bodies
+for the continue command. This command is sent by the host to tell
+the target to continue execution. This is usually sent as a result of
+the user entering the Go (g) command. The debugger on the target will
+not get re-entered again unless a breakpoint or other exception is
+encountered. The target does not send a response to this command. If
+the target does re-enter the debugger due to a subsequent exception,
+it will send a state response packet to the host.</P>
+
+<PRE><TT>#define sysPktContinueCmd&nbsp;&nbsp; 0x07
+&nbsp;
+typedef struct SysPktContinueCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; M68KregsType regs;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // registers
+&nbsp;&nbsp;&nbsp; Boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stepSpy;&nbsp;&nbsp;&nbsp;&nbsp; // set true to do step spy
+&nbsp;&nbsp;&nbsp; DWord&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssAddr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // step spy address
+&nbsp;&nbsp;&nbsp; DWord&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssCount;&nbsp;&nbsp;&nbsp;&nbsp; // # of bytes
+&nbsp;&nbsp;&nbsp; DWord&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssCheckSum;&nbsp; // checksum
+} SysPktContinueCmdType;</TT></PRE>
+
+<CENTER><B>Figure 9 - Continue Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Get Breakpoints Command"></A>Get Breakpoints
+Command</H3>
+
+<P>Figure 10 shows the structure of the request and response bodies
+for the getBreakpoints command. This command is sent by the host to
+get the current settings of all target breakpoints. The response body
+has an array of 6 breakpoints in it. If the enabled field for a
+particular breakpoint entry is 0, it means that breakpoint is
+disabled. If the address field is 0, it means that breakpoint is not
+used. The installed field is currently never used.</P>
+
+<PRE><TT>#define sysPktGetBreakpointsCmd&nbsp; 0x0B
+#define sysPktGetBreakpointsRsp&nbsp; 0x8B
+&nbsp;
+typedef struct SysPktGetBreakpointsCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktGetBreakpointsCmdType;
+&nbsp;
+typedef struct SysPktGetBreakpointsRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; BreakpointType bp&#91;dbgTotalBreakpoints&#93;;
+} SysPktGetBreakpointsRspType;</TT></PRE>
+
+<CENTER><B>Figure 10 - Get Breakpoints Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Set Breakpoints Command"></A>Set Breakpoints
+Command</H3>
+
+<P>Figure 11 shows the structure of the request and response bodies
+for the setBreakpoints command. This command is sent by the host to
+set the target breakpoints. The request body has an array of 6
+breakpoints in it. If the enabled field for a particular breakpoint
+entry is 0, it means that breakpoint is disabled. If the address
+field is 0, it means that breakpoint is not used.</P>
+
+<PRE><TT>#define sysPktSetBreakpointsCmd&nbsp; 0x0C
+#define sysPktSetBreakpointsRsp&nbsp; 0x8C
+&nbsp;
+typedef struct SysPktSetTrapBreaksCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; Word&nbsp; trapBP&#91;dbgTotalTrapBreaks&#93;;
+} SysPktSetTrapBreaksCmdType;
+&nbsp;
+typedef struct SysPktSetTrapBreaksRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktSetTrapBreaksRspType;</TT></PRE>
+
+<CENTER><B>Figure 11 - Set Breakpoints Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Toggle Debugger Breaks Command"></A>Toggle Debugger
+Breaks Command</H3>
+
+<P>Figure 12 shows the structure of the request and response bodies
+for the toggleDbgBreaks command. This command is sent by the host to
+enable or disable compiled-in breakpoints. A compiled in breakpoint
+is a special TRAP instruction that gets compiled into the code with
+the DbgBreak() and DbgSrcBreak() calls. The host can send this
+command to tell the target whether or not to ignore these
+breakpoints. The request toggles the state and the response returns
+the new state (non-zero for enabled, 0 for disabled).</P>
+
+<PRE><TT>#define sysPktDbgBreakToggleCmd&nbsp; 0x0D
+#define sysPktDbgBreakToggleRsp&nbsp; 0x8D
+&nbsp;
+typedef struct SysPktDbgBreakToggleCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktDbgBreakToggleCmdType;
+&nbsp;
+typedef struct SysPktDbgBreakToggleRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; Boolean&nbsp; newState;
+} SysPktDbgBreakToggleRspType;</TT></PRE>
+
+<CENTER><B>Figure 12 - Toggle Debugger Breaks Command</B></CENTER>
+
+<P>&nbsp;</P>
+
+<H3><A NAME="Get Trap Breaks Command"></A>Get Trap Breaks
+Command</H3>
+
+<P>Figure 13 shows the structure of the request and response bodies
+for the getTrapBreaks command. The host sends this command to get the
+current settings of all target trap breaks. The response body has an
+array of 5 traps in it. If the trap field is 0, it means that trap
+break is not used. Trap breaks are used to force the target to enter
+the debugger when a particular system trap is called. Up to 5 trap
+breaks can be set at any time.</P>
+
+<PRE>#define sysPktGetTrapBreaksCmd&nbsp; 0x10
+#define sysPktGetTrapBreaksRsp&nbsp; 0x90
+&nbsp;
+typedef struct SysPktGetTrapBreaksCmdType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktGetTrapBreaksCmdType;
+&nbsp;
+typedef struct SysPktGetTrapBreaksRspType
+{
+&nbsp;&nbsp;&nbsp; _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+&nbsp;&nbsp;&nbsp; Word&nbsp; trapBP&#91;dbgTotalTrapBreaks&#93;;
+} SysPktGetTrapBreaksRspType;</PRE>
+
+<CENTER><B>Figure 13 - Get Trap Breaks Command</B></CENTER>
+
+<H3><A NAME="Set Trap Breaks Command"></A>Set Trap Breaks
+Command</H3>
+
+<P>Figure 14 shows the structure of the request and response bodies
+for the setTrapBreaks command. The host sends this command to set the
+current settings of all target trap breaks. The request body has an
+array of 5 traps in it. If the trap field is 0, it means that trap
+break is not used. Trap breaks are used to force the target to enter
+the debugger when a particular system trap is called. Up to 5 trap
+breaks can be set at any time.</P>
+
+<PRE>#define sysPktSetTrapBreaksCmd&nbsp; 0x11
+#define sysPktSetTrapBreaksRsp&nbsp; 0x91
+&nbsp;
+typedef struct SysPktSetTrapBreaksCmdType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ Word&nbsp; trapBP&#91;dbgTotalTrapBreaks&#93;;
+} SysPktSetTrapBreaksCmdType;
+&nbsp;
+typedef struct SysPktSetTrapBreaksRspType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktSetTrapBreaksRspType;</PRE>
+
+<CENTER><B>Figure 14 - Set Trap Breaks Command</B></CENTER>
+
+<H3><A NAME="Find Command"></A>Find Command</H3>
+
+<P>Figure 15 shows the structure of the request and response bodies
+for the find command. This command is sent by the host to search for
+data on the target. The firstAddr and lastAddr fields of the request
+set the range of addresses to search through. The numBytes field
+contains the number of bytes in the search string. If the
+caseInsensitive byte is non-zero, a case-insensitive search will be
+made. The variable length search string follows the caseInsensitive
+field.</P>
+
+<P>In the response body, addrFound contains the address of the found
+data. If the data was not found, the found field will be 0.</P>
+
+<PRE>#define sysPktFindCmd&nbsp;&nbsp;&nbsp; 0x13
+#define sysPktFindRsp&nbsp;&nbsp;&nbsp; 0x93
+&nbsp;
+typedef struct SysPktFindCmdType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ DWord&nbsp; firstAddr;&nbsp; // first address to search
+ DWord&nbsp; lastAddr;&nbsp; // last address to begin searching
+ Word&nbsp; numBytes;&nbsp; // number of data bytes to match
+ Boolean caseInsensitive; // if true, perform a case-insensitive search
+} SysPktFindCmdType;
+&nbsp;
+typedef struct SysPktFindRspType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ DWord&nbsp; addr;&nbsp;&nbsp; // address where data was found
+ Boolean&nbsp; found;&nbsp;&nbsp; // true if data was found
+} SysPktFindRspType;</PRE>
+
+<CENTER><B>Figure 15 - Find Command</B></CENTER>
+
+<H3><A NAME="Message Command"></A>Message Command</H3>
+
+<P>Figure 16 shows the structure of the message packet body. This
+packet is sent by the target to display a message on the host.
+Debugger messages can be compiled into the source code through the
+DbgMessage() call. They can be used by applications on Palm devices
+for displaying application specific debugging messages during
+execution. There is no response sent back from the host to the target
+when it receives one of these packets.</P>
+
+<PRE>#define sysPktRemoteMsgCmd&nbsp;&nbsp; 0x7F
+&nbsp;
+typedef struct SysPktRemoteMsgCmdType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ Byte&nbsp; text&#91;1&#93;;&nbsp; // variable length text goes here
+} SysPktRemoteMsgCmdType;</PRE>
+
+<CENTER><B>Figure 16 - Message Command</B></CENTER>
+
+<H3><A NAME="RPC Command"></A>RPC Command</H3>
+
+<PRE>#define sysPktRPCCmd&nbsp;&nbsp;&nbsp; 0x0A
+#define sysPktRPCRsp&nbsp;&nbsp;&nbsp; 0x8A
+&nbsp;
+typedef struct SysPktRPCParamInfo
+{
+ Byte&nbsp;&nbsp; byRef;&nbsp;&nbsp; // true if param is by reference
+ Byte&nbsp; size;&nbsp;&nbsp; // # of Bytes of paramData (must be even)
+ Word&nbsp; data&#91;1&#93;;&nbsp; // variable length array of paramData
+} SysPktRPCParamType;
+&nbsp;
+typedef struct SysPktRPCType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ Word&nbsp; trapWord;&nbsp; // which trap to execute
+ Dword&nbsp; resultD0;&nbsp; // result from D0 placed here
+ Dword&nbsp; resultA0;&nbsp; // result from A0 placed here
+ Word&nbsp; numParams;&nbsp; // how many parameters follow
+&nbsp;
+ // Following is a variable length array of SysPktRPCParamType's
+ SysPktRPCParamType param&#91;1&#93;;
+} SysPktRPCType;</PRE>
+
+<CENTER><B>Figure 17 - RPC Command</B></CENTER>
+
+<H3><A NAME="Get Trap Conditionals Command"></A>Get Trap Conditionals
+Command (new in 3.0)</H3>
+
+<P>These are used to tell the debugger to conditionally break on a
+trap depending on the value of the first word on the stack. They are
+used when setting a-traps on library calls.</P>
+
+<PRE>#define sysPktGetTrapConditionsCmd&nbsp; 0x14
+#define sysPktGetTrapConditionsRsp&nbsp; 0x94
+&nbsp;
+typedef struct SysPktGetTrapConditionsCmdType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktGetTrapConditionsCmdType;
+&nbsp;
+typedef struct SysPktGetTrapConditionsRspType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ Word&nbsp; trapParam&#91;dbgTotalTrapBreaks&#93;;
+} SysPktGetTrapConditionsRspType;</PRE>
+
+<CENTER><B>Figure 18 - Get Trap Conditionals Command</B></CENTER>
+
+<H3><A NAME="Set Trap Conditionals Command"></A>Set Trap Conditionals
+Command (new in 3.0)</H3>
+
+<P>These are used to tell the debugger to conditionally break on a
+trap depending on the value of the first word on the stack. They are
+used when setting a-traps on library calls.</P>
+
+<PRE>#define sysPktSetTrapConditionsCmd&nbsp; 0x15
+#define sysPktSetTrapConditionsRsp&nbsp; 0x95
+&nbsp;
+typedef struct SysPktSetTrapConditionsCmdType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+ Word&nbsp; trapParam&#91;dbgTotalTrapBreaks&#93;;
+} SysPktSetTrapConditionsCmdType;
+&nbsp;
+typedef struct SysPktSetTrapConditionsRspType
+{
+ _sysPktBodyCommon;&nbsp;&nbsp; // Common Body header
+} SysPktSetTrapConditionsRspType;</PRE>
+
+<CENTER><B>Figure 19 - Set Trap Conditionals Command</B></CENTER>
+
+<P>&nbsp;</P>
+</BODY>
+</HTML>
diff --git a/Docs/POSER Profiler.rtf b/Docs/POSER Profiler.rtf
new file mode 100644
index 0000000..e1de7df
--- /dev/null
+++ b/Docs/POSER Profiler.rtf
@@ -0,0 +1,522 @@
+{\rtf1\mac \deff8\deflang1033{\fonttbl{\f1\fnil\fcharset2\fprq2 Symbol;}{\f3\fnil\fcharset77\fprq2 Courier;}{\f8\fnil\fcharset77\fprq2 Times;}{\f9\fnil\fcharset77\fprq2 Helvetica;}{\f48\fnil\fcharset77\fprq2 Monaco;}}
+{\colortbl;\red0\green0\blue0;\red0\green0\blue212;\red2\green171\blue234;\red31\green183\blue20;\red242\green8\blue132;\red221\green8\blue6;\red252\green243\blue5;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green100\blue17;
+\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\widctlpar \f8 \snext0 Normal;}{\s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}
+\b\f8\fs36 \sbasedon0\snext0 heading 1;}{\s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 \sbasedon0\snext0 heading 2;}{\s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8
+\sbasedon0\snext0 heading 3;}{\s4\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl4\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\i\f8 \sbasedon0\snext0 heading 4;}{\s5\sb240\sa60\widctlpar{\*\pn \pnlvl5\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\f9\fs22
+\sbasedon0\snext0 heading 5;}{\s6\sb240\sa60\widctlpar{\*\pn \pnlvl6\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\i\f9\fs22 \sbasedon0\snext0 heading 6;}{\s7\sb240\sa60\widctlpar{\*\pn \pnlvl7\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\f9\fs20
+\sbasedon0\snext0 heading 7;}{\s8\sb240\sa60\widctlpar{\*\pn \pnlvl8\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\i\f9\fs20 \sbasedon0\snext0 heading 8;}{\s9\sb240\sa60\widctlpar{\*\pn \pnlvl9\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\i\f9\fs18
+\sbasedon0\snext0 heading 9;}{\*\cs10 \additive Default Paragraph Font;}{\s15\li1200\widctlpar\tqr\tldot\tx11880 \f8\fs18 \sbasedon0\snext0 toc 8;}{\s16\li1000\widctlpar\tqr\tldot\tx11880 \f8\fs18 \sbasedon0\snext0 toc 7;}{
+\s17\li800\widctlpar\tqr\tldot\tx11880 \f8\fs18 \sbasedon0\snext0 toc 6;}{\s18\li600\widctlpar\tqr\tldot\tx11880 \f8\fs18 \sbasedon0\snext0 toc 5;}{\s19\li400\widctlpar\tqr\tldot\tx11880 \f8\fs18 \sbasedon0\snext0 toc 4;}{
+\s20\li200\widctlpar\tqr\tldot\tx11880 \i\f8 \sbasedon0\snext0 toc 3;}{\s21\widctlpar\tqr\tldot\tx11880 \scaps\f8 \sbasedon0\snext0 toc 2;}{\s22\sb120\sa120\widctlpar\tqr\tldot\tx11880 \b\caps\f8 \sbasedon0\snext0 toc 1;}{
+\s23\fi-240\li1680\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 7;}{\s24\fi-240\li1440\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 6;}{\s25\fi-240\li1200\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 5;}{
+\s26\fi-240\li960\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 4;}{\s27\fi-240\li720\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 3;}{\s28\fi-240\li480\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 2;}{
+\s29\fi-240\li240\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 1;}{\s30\widctlpar\tqc\tx4320\tqr\tx8640 \f8 \sbasedon0\snext30 footer;}{\s31\widctlpar\tqc\tx4320\tqr\tx8640 \f8 \sbasedon0\snext31 header;}{\s32\li1400\widctlpar\tqr\tldot\tx11880
+\f8\fs18 \sbasedon0\snext0 toc 9;}{\s33\sb120\sa120\widctlpar \b\i\f8 \sbasedon0\snext29 index heading;}{\s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\f3\fs20 \sbasedon0\snext34 Code;}{\s35\fi-1710\li1710\widctlpar\box\brdrs\brdrw15\brsp20 \tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx1980\tx2160\tx2340\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f48\fs18 \sbasedon34\snext35
+PsuedoCode;}{\s36\fi-1710\li1710\ri-3680\widctlpar\tx540\tx720\tx980\tx1080\tx1440\tx1800\tx1980\tx2160\tx2420\tx2520\tx2880\tx3240\tx3320\tx3600\tx3780\tx3960\tx4220\tx4680\tx5040\tx5400\tx5760 \f48\fs18 \sbasedon34\snext36 API Summary;}{
+\s37\fi-200\li1600\widctlpar\tqr\tldot\tx8640 \f8 \sbasedon0\snext0 index 8;}{\s38\fi-200\li1800\widctlpar\tqr\tldot\tx8640 \f8 \sbasedon0\snext0 index 9;}{\s39\fi-2700\li3060\widctlpar\tx1440\tx3060 \f8 \sbasedon0\snext39 Prototype;}{
+\s40\fi-240\li1920\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 8;}{\s41\fi-240\li2160\widctlpar\tqr\tx5580 \f8\fs18 \sbasedon0\snext0 index 9;}{\s42\qc\sb240\sa120\widctlpar \b\f8\fs26 \sbasedon0\snext29 index heading;}{\s43\widctlpar \f8
+\sbasedon0\snext43 ading 2;}}{\info{\title Touchdown System Software Spec}{\subject Touchdown System Software}{\author Bob Ebert}{\keywords Touchdown System Software API}{\operator Bob Ebert}{\creatim\yr1998\mo6\dy10\hr15\min43}
+{\revtim\yr1998\mo6\dy10\hr19\min4}{\version128}{\edmins143}{\nofpages0}{\nofwords0}{\nofchars0}{\vern49235}}\paperw14400\paperh18620\margl1440\margr1080 \widowctrl\ftnbj\aenddoc\hyphhotz0\sprstsp\otblrul\brkfrm\sprstsm\truncex\nolead\msmcap\hyphcaps0
+\fet0\sectd \sbknone\linex0\endnhere {\header \pard\plain \s31\nowidctlpar\tqc\tx4320\tqr\tx8640 \f8 {\i\ul Palm Computing Confidential\tab \tab For Internal Use Only
+\par }}{\footer \pard\plain \s30\nowidctlpar\tqc\tx4320\tqr\tx8640 \f8 POSER Profiler\tab Page {\chpgn }\tab Last Revised: 6/10/98
+\par }{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5
+\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\pntext\pard\plain\b\fs36\cchs0 1.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Overview
+
+\par \pard\plain \widctlpar \f8 POSER\rquote s emulator can be used to profile the code that it\rquote
+s executing. It does this by counting cycles while it simulates the opcodes, and watching for JSR/RTS and interrupt/RTE events. It dumps the resulting data to file that is compatible with the Metrowerks Profiler application for Macintosh.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\fs36\cchs0 2.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Profiler Implementation
+\par {\pntext\pard\plain\b\i\fs28\cchs0 2.1\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 UAE Changes
+\par \pard\plain \widctlpar \f8 This section describes the profiling changes to the UAE sources.
+\par
+\par {\pntext\pard\plain\b\cchs0 2.1.1\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Build68K
+\par \pard\plain \widctlpar \f8 UAE is built into POSER in three stages. In the first stage, Build68K takes a text file called \ldblquote table68K\rdblquote containing information about the 68K opcodes and produces \ldblquote cpudefs.c\rdblquote
+, a C source file with a compressed version of UAE specific information for each opcode. There are no profiling changes to this stage. In the third stage, the POSER sour
+ces are combined with the sources produced by GenCPU to build the final executable. The profiling changes for POSER are described in the next section.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.1.2\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 GenCPU
+\par \pard\plain \widctlpar \f8
+In the second stage, GenCPU is built from sources and the cpudefs.c file from state one. When run, GenCPU can produce functions to emulate each 68K Opcode. GenCPU has been modified to produce a table of read cycle, write cycle, and extra CPU cycles for
+each opcode. In addition, some of the opcode functions (e.g. Bcc) include specific code to tell the profiler to increment the clock.
+\par \pard \widctlpar
+\par \pard \widctlpar
+As GenCPU is running, it adds comments to each opcode function to indicate what the profiling numbers are for that opcode. (gen_opcode) The numbers are specific to the MC68000 processor, to match the MC68EC000 used in the Palm devices. The source for t
+he data is the \ldblquote Motorola MC68000 8-/16-/32-Microprocessors User\rquote s Manual\rdblquote section 8. Read and write cycles are tracked seperately, as well as additional CPU-only cycles for each opcode.
+\par \pard \widctlpar
+\par \pard \widctlpar gen_opcode calls genaread and genastore for each opcode to read in arguments and write out results. These functions have been modified to accumulate read, write and extra CPU cycles for each operation.
+\par \pard \widctlpar
+\par \pard \widctlpar After calling gen_opcode, generate_func takes the accumulated read, write, and extra cycle counts for the opcode and produces data for a table that\rquote
+s used by POSER. It also writes a comment after each code block with the expected (per the Motorola manual) and actual (per accumulated numbers) cycle counts for the function. This is hand
+y because the resulting .c file with the opcode functions can be viewed to check the accuracy of the cycle counting.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.1.3\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Inaccuracies
+\par \pard\plain \widctlpar \f8 Here are some known inaccuracies with the current cycle counts.
+\par
+\par \pard \widctlpar JMP, JSR, RTS, RTE, and Bcc fall short by one read each, for 6 or 8 cycles each depending on ROM or RAM. I believe this is because the CPU does instruction prefetch, and so the times in Motorola\rquote
+s tables actually include the time needed to fetch the next instruction, not the current instruction. PC-changing instr
+uctions need to throw away the prefetched instruction and read in the real next instruction, so this takes an extra read cycle. POSER does not prefetch, so there\rquote
+s no good way to account for this. (Since the next instruction may be in ROM or RAM, the actual CPU cycles taken may differ.)
+\par \pard \widctlpar
+\par \pard \widctlpar ANDSR, ORSR, MV2SR and other "SR" instructions are 2 reads short, for 12 or 16 cycles. I\rquote m not sure why this is, some implementation detail with how the CPU references the status register?
+\par \pard \widctlpar
+\par \pard \widctlpar MUL and DIV instructions are c
+ounted as worst case. Both have unusual execution times which depend on the values being multiplied or divided. The DIV instructions is supposedly less than a 10% difference from best to worst case, for a range of 144-158 cycles for signed and 126-140 c
+ycles for unsigned values. These are counted as 158 and 140 cycles (plus wait states and effective address calculation times.) The MUL operations take 38+2n cycles, where n is the number of 1\rquote
+s in the memory value for MULU, and the number of 10 or 01 patterns in the memory value catenated with 0 (as the LSB). 70 is indicated as the max value, and that is what is used.
+\par {\pntext\pard\plain\b\i\fs28\cchs0 2.2\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 POSER changes
+\par \pard\plain \widctlpar \f8 Switches.h has a HAS_PROFILING switch, which must be non-zero to include profiling in an Emulator build.
+\par
+\par {\pntext\pard\plain\b\cchs0 2.2.1\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 CEumlatorApp.cpp
+\par \pard\plain \widctlpar \f8
+CEmulatorApp .cpp contains a little bit of code that hooks the user interface up with the functions in Profiling.cpp. Changes are made in CEmulatorApp::ObeyCommand to responds to menu and key events generated by the user, and in CEmulatorApp::FindCommand
+Status to makes sure the menu state is correct. The profiling menu is defined in Palm OS Emulator.ppob.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.2.2\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 CPU_REG.cpp
+\par \pard\plain \widctlpar \f8 CPU_REG.cpp defines and loads the table of read, write, and extra cycles for each opcode.
+\par
+\par \pard \widctlpar
+Emulator::Execute has been modified to count cycles as the opcode executes. Most of the cycle counting is done by the functions that read and write memory, but the extra CPU-only cycles are counted in Emulator::Execute. Emulator::Execute also sets and cl
+ears a flag to tell the profiler to pay attention to cycles. This is necessary so that the emulator\rquote s internal use of the memory read/write functions (to draw the screen, call ROM traps, etc) are not charged against the running application.
+\par \pard \widctlpar
+\par \pard \widctlpar
+CPU_REG.cpp also has some code controlled by the HAS_PROFILING_DEBUG flag to help debug the profiler. This code compares the actual cycles counted as the opcodes are executed to the ones specified as expected in the table. That is also done in Emulator:
+:Execute.
+\par \pard \widctlpar
+\par Hardware::Initialize loads the table of cycle counts.
+\par
+\par \pard \widctlpar
+Software::ProcessException is hooked in to the emulator opcodes to special case exceptions. It allows POSER to patch out the exception handlers and do its own thing. The profiler counts time spent in exceptions seperately from time spent in regular func
+tions, so Software::ProcessException calls ProfleInterruptEnter to do this. If the emulator patched out the exception, the ProfileInterruptExit is also called here. If not, then the interrupt is not finished until the RTE opcode is executed, and Softwar
+e::ProcessRTE handles this.
+\par \pard \widctlpar
+\par \pard \widctlpar
+Software::ProcessJSR is called by the CPU emulator function for JSR opcodes. It calls ProfileFnEnter to start profiling for the new function. Similarly, Software::ProcessRTS calls ProfileFnExit to stop profiling for the function and return to the enclos
+ing function.
+\par \pard \widctlpar
+\par \pard \widctlpar Software::ProcessTrap14 has been taken over to allow executing code to contol aspects of the emulator. Controlling the profiler is part of this, and there are \ldblquote E-traps\rdblquote to init, start, stop, dump, and cleanup pro
+filing.
+\par \pard \widctlpar
+\par \pard \widctlpar Software::ProcessTrap15 creates a \ldblquote fake\rdblquote function call by calling ProfileFnEnter and ProfileFnExit. By using the trap number for the address, this allows the profiler to count \ldblquote F-traps\rdblquote
+ by trap number, which is handy for finding out which system traps ar
+e used most often. Software::ProcessTrap15 also normally skips the emulated trap dispatcher, preferring instead to get the trap address and do the jump itself. This greatly improves performance when emulating normal code, since about 10% of the ti
+me is spent in the trap dispatcher for common operations. When profiling, native dispatch is skipped, because we actually want to know what overhead the trap dispatcher is requiring.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.2.3\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 RAM_ROM.cpp
+\par \pard\plain \widctlpar \f8 RAM_ROM.cpp implements reading and writing to memory for various memory banks. Because the Palm devices require wait states when accessing memory, it\rquote
+s not enough to simply count reads and writes as 4 cycles each (which is the CPU overhead for them.) Palm devices use different wait states for different memory, a
+nd quite possibly devices will have different wait state characteristics in the future. RAM_ROM.cpp counts this.
+\par \pard \widctlpar
+\par \pard \widctlpar
+Each of the GetLong, GetWord, GetByte, SetLong, SetWord, and SetByte functions for each memory type calls either ProfileIncrementRead or ProfileIncrementWrite, passing in the number of read or write cycles and the number of wait states for that memory typ
+e. (The wait states are #defined in Profiling.h) ProfileIncrementRead and ProfileIncrementWrite are inlined to improve performance in the emulator.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.2.4\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 TrapPatches.cpp
+\par \pard\plain \widctlpar \f8
+TrapPatches.cpp turns off a couple of trap patches if the profiler is built into the emulator. Normally, these are patched out to improve performance by avoiding emulating the ROM routines. Some of the others should probably be turned off with the HAS_P
+ROFILING switch as well, but they are required by the emulator itself.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\i\fs28\cchs0 2.3\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 Profiling Code
+\par \pard\plain \widctlpar \f8 Most of the profiling code is in Profiling.h and Profiling.cpp. This is the chunk that gathers and dumps the profiling data.
+\par
+\par {\pntext\pard\plain\b\cchs0 2.3.1\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Accumulators and Flags
+\par \pard\plain \widctlpar \f8
+gReadCycles, gWriteCycles, and gClockCycles contain the total number of read, write, and clocks that have passed since profiling was started. These globals are accessed from other modules through the inline functions in Profiling.h.
+\par \pard \widctlpar
+\par \pard \widctlpar
+gProfilingEnabled, gProfilingOn, and gProfilingCounted are flags that indicate the current state of profiling affairs. Enabled indicates profiling buffers have been allocated and profiling is happening or could start or stop at any time. On indicates pr
+ofiling data is currently being collected. Counted indicates that the current instructions as well as memory reads and writes should be added to the global read/write/cycle counts.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.3.2\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Data Structures
+\par \pard\plain \widctlpar \f8 The profiler uses two main data structures to accumulate data: a tree of function call records and a stack of currently in progress functions or interrupts.
+\par \pard \widctlpar
+\par \pard \widctlpar The tree is stored in memory using the same format as the Metrowerks profiler file, so dumping the output file is a simple matter of writing a memory block to disk. See A
+ppendix B for the record format. Global variables contain the index of: the root of the tree, the record used for overflow tracking, the record used as the root for interrupt tracking, and the index of the next available record.
+\par \pard \widctlpar
+\par The stack is an array of the following records. Each element tracks a function or interrupt that is currently executing.
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 struct FnStackRecord \{
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab int call;\tab \tab \tab \tab \tab \tab \tab \tab // fn data block for fn being called
+\par \tab uaecptr returnAddress;\tab \tab \tab // return address aka (SP) to calling fn
+\par \tab UInt64 cyclesAtEntry;\tab \tab \tab // cycle count when fn was called
+\par \tab UInt64 cyclesAtInterrupt;\tab \tab // cycle count when fn was interrupted
+\par \tab UInt64 cyclesInKids;\tab \tab \tab \tab // number of cycles spent in subroutines
+\par \tab UInt64 cyclesInInterrupts;\tab \tab // number of cycles spent in interrupts
+\par \};
+\par \pard\plain \widctlpar \f8
+\par A global variable holds the current top of the stack.
+\par
+\par \pard \widctlpar To handle interrupts, a separate stack is used that keeps track of the call stack record that matches the interrupt. A stack is necessary for this because interrupts can be interrupted. We allow up to 8 of these, but I\rquote
+ve never seen more than 2 used.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 2.3.3\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 GetRoutineName
+\par \pard\plain \widctlpar \f8
+GetRoutineName turns an address (or interrupt number or trap number) into a string representation for that function. It attempts to use the ROM.map data to find the function name, and if no match is found it steps through the instructions found at the ad
+dress indicated until it finds the end of the function, then looks for the debug symbol. If the address was to a function in a code resource and the resource was moved, then the name will be i
+ncorrect. GetRoutineName is completely responsible for turning an address into a name, and it will always return some string, even if passed an invalid address.
+\par {\pntext\pard\plain\b\cchs0 2.3.4\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Generating Function Names
+\par \pard\plain \widctlpar \f8
+The functiosn InitStringTable, CleanupStringTable, and FindOrAddString do the work of creating the string table (as described in Appendix B) and then adding strings to it. RecursiveAddressToStrings traverses the tree of functions and changes the address
+stored with each function record into an offset into the string table, which it is generating. That\rquote s a one-time operation, if you tried to do it twice you\rquote d get garbage.
+\par {\pntext\pard\plain\b\cchs0 2.3.5\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 PopCallStackFn
+\par \pard\plain \widctlpar \f8
+PopCallStackFn is used when a function or interrupt is being exited from. It updates the nodes in the tree to properly track call counts and time spent in interrupts and in children. It is called both during normal function or interrupt exit and by clea
+nup code that\rquote s trying to keep the profiler\rquote s call stack in sync with the CPU\rquote s call stack.
+\par {\pntext\pard\plain\b\cchs0 2.3.6\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 FindOrAddCall
+\par \pard\plain \widctlpar \f8 FindOrAddCall is used when a f
+unction or interrupt is being entered. It looks to see if the function has prevously been called from the current function or interrupt, and if so returns the existing record. If not, a new record is allocated, initialized, and plugged into the tree.
+
+\par {\pntext\pard\plain\b\cchs0 2.3.7\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileInit
+\par \pard\plain \widctlpar \f8 ProfileInit allocates the stack and tree with the passed sizes, and initializes a bunch of other data structures.
+\par {\pntext\pard\plain\b\cchs0 2.3.8\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileCleanup
+\par \pard\plain \widctlpar \f8 ProfileCleanup frees the data structures allocated in ProfileInit
+\par {\pntext\pard\plain\b\cchs0 2.3.9\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileStart
+\par \pard\plain \widctlpar \f8 ProfileStart turns on the profiling flags. Currently it assumes that it is not called from within an interrupt, often is not the case. When invoked from the POSER UI, the CPU is often currently processing an interrupt.
+\par {\pntext\pard\plain\b\cchs0 2.3.10\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileStop
+\par \pard\plain \widctlpar \f8 ProfileStop turns off collection of profiling data. If there are functions currently on the profiling stack, they are popped.
+\par {\pntext\pard\plain\b\cchs0 2.3.11\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileDump
+\par \pard\plain \widctlpar \f8 ProfileDump reads in the ROM.map file, turns all the addresses in the call tree into real function names, generating the string table in the process, then dumps out the heade
+r, tree, and stringtable to disk. This operation is destructive to the function tree, and cannot be done more than once. (It should probably call ProfileCleanup to make sure this doesn\rquote t happen.)
+\par {\pntext\pard\plain\b\cchs0 2.3.12\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileFnEnter
+\par \pard\plain \widctlpar \f8 ProfileFnEnter is called by the emulator when a JSR is executed, and at a couple of other places. It creates a record for the function (or reuses an existing record), and updates the profiler\rquote s call stack.
+\par \pard \widctlpar
+\par \pard \widctlpar ProfileFnEnter also supports a special profiling mode. If the profiler is built with PROFILE_ONE_FN on, then it\rquote
+s assumed that whenever profiling has been initialized, you always want to start profiling when a specified function is entered, and stop profiling when that function is exited. That way you get profiling information for a particul
+ar function no matter who it\rquote s called from. In this case, ProfileFnEnter may be called before ProfileStart has been called, and if it detects that the target function has been entered it will start profiling at that point.
+\par {\pntext\pard\plain\b\cchs0 2.3.13\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileFnExit
+\par \pard\plain \widctlpar \f8 ProfileFnExit is called by the emulator when an RTS is executed The Palm OS does some funny things such that there is not always an RTS for every JSR. To handle this, ProfileFnExit has to be smart
+, so it keeps the return address when a function is called and compares it to the destination address for the RTS. Most of the time they match, and everything is fine, but when they don\rquote t one of two things may be happening: either a function
+is being called not by using JSR, but rather by pushing the callee\rquote s address on the stack then executing an RTS, or a RTS has been skipped and the stack has been cleaned up by the executing code (the kernel does this.)
+\par \pard \widctlpar
+\par \pard \widctlpar
+If the return address is not what we expected based on the profiling stack, then the first thing we do is walk up the stack looking to see if the address matches some higher function. If it does, the stack is popped up to the function we expect, and the
+intervening functions are flagged as improperly exited. If no match was found, we assume it\rquote s a long jump disguised as an RTS, and call ProfileFnEnter instead.
+\par \pard \widctlpar
+\par \pard \widctlpar The profiler\rquote s call stack can (commonly) be popped to empty. This happens when the function that was executing when ProfileStart was called exits. If profiling is started from the PO
+SER UI, this happens very often, so we do the best we can: create a new fake \ldblquote root\rdblquote for the call tree, representing the function we\rquote re return
+ing to, and continue on. If profiling was started by the PROFILE_ONE_FN trick, then a pop to empty is considered exiting the target function, and profiling is turned off.
+\par {\pntext\pard\plain\b\cchs0 2.3.14\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileInterruptEnter
+\par \pard\plain \widctlpar \f8 ProfileInterruptEnter does almost the same thing as ProfileFnEnter. The difference is that the current call is added to the \ldblquote interrupt\rdblquote root rather than the currently executing function, and the profile
+\rquote s call stack pointer is pushed onto the profiler\rquote s interrupt stack.
+\par {\pntext\pard\plain\b\cchs0 2.3.15\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileInterruptExit
+\par \pard\plain \widctlpar \f8 ProfileInterruptExit works much like ProfileFnExit, the calls stack\rquote s record for the interrupt \ldblquote function\rdblquote is popped. Unlike with RTS, RTE is reliably matched with an interrupt exit, so it\rquote
+s not necessary to do the funny call stack searching. However, when the RTE executes it\rquote
+s possible that there may still be some unmatched calls (JSRs) that were executed as part of processing the interrupt. (The kernel does this regularly.) So we make sure to pop all the functions off the profiler\rquote
+s call stack until we get to the one indicated by the profiler\rquote s interrupt stack.
+\par \pard \widctlpar
+\par The Palm OS trap handler performs trap calls by pushing stuff on the CPU stack so that the RTE will jump to the real function (and then later be able to do an RTS from that fn to get back to the code that executed the TRAP interrupt.)
+ To handle this, the RTE destination is compared to the PC that was saved when the interrupt happened, and if they addresses don\rquote t match then ProfileFnEnter is called to track the \rdblquote fake\rdblquote function entry.
+\par
+\par {\pntext\pard\plain\b\fs36\cchs0 3.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Using the Profiler
+\par {\pntext\pard\plain\b\i\fs28\cchs0 3.1\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 POSER UI
+\par \pard\plain \widctlpar \f8 You actually don't have to do anything at all to set up your app for profiling. That's the beauty of having the emulator handle profiling--all the work can happen "between cycles" It\rquote
+s a good idea to set the compiler switch so that the debug symbols get embedded in your code, otherwise you won't be able to identify your functions in the output. For the
+ROM, debug symbols are not necessary if a ROM.map file is available. The ROM.map file will be used first, and if the function is not present then the debug symbols will be used.
+\par \pard \widctlpar
+\par To do a profiling run:
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}\pard \fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}Launch the Mac version of the emulator.
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}Load the app or otherwise set up the situation to be profiled
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}Select "Start" from the profiling menu or press cmd-[
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}Do the profiled thing
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}Select "Stop" from the profiling menu, or press cmd-]
+\par {\pntext\pard\plain\f1\cchs0 \'b7\tab}Select "Dump" from the profiling menu, or press cmd-\\
+\par \pard \widctlpar
+\par \pard \widctlpar You can start and stop more than once before dumping the results. The profile data gathered in each start/stop pair will be added into that gathered in previous pairs.
+\par \pard \widctlpar
+\par \pard \widctlpar When you dump the result, you'll find a file in the emulator directory called "POSER Profile Results". At the moment, you have to change the type and creator to 'proF' so the Metrowerks profile will open it. Once that\rquote
+s done, just double-click it, or otherwise convince the "MW Profiler" app to open it. See Reading the Results below.
+\par \pard \widctlpar
+\par \pard \widctlpar When you profile this way, the profiler buffers are predefined in Profiling.h. Currently they\rquote
+re set to 20000 functions with a max stack of 200 functions. That's enough to profile booting a ROM, and plenty for repetetive operations, but it quickly gets used up if you do gremlins.
+ (A few hundred gremlins will generate 20000 unique function calls.)
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\i\fs28\cchs0 3.2\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 From Your App
+\par \pard\plain \widctlpar \f8 You can Init, Start, Stop, Dump, and Cleanup the POSER profiler from application code, much like you can for the Metrowerks profiler for Mac. To do this, #include \ldblquote EmuTraps.h\rdblquote and #include \ldblquote
+EmuProfiling.h\rdblquote in the module that will control the profiler. (You might want to put EmuProfilingNOPs.c in the project for simulator builds only, so that the profiling functions will be stubbed out there.) The APIs are described below.
+\par \pard \widctlpar
+\par {\pntext\pard\plain\b\cchs0 3.2.1\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileInit
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfileInit(int maxCalls, int maxDepth)
+\par \pard\plain \widctlpar \f8 \tab maxCalls - the number of function call buffers to allocate
+\par \tab maxDepth - the number of stack frames to allocate
+\par \pard \widctlpar This allocates the profile buffers within the POSER memory partition. It must be done prior to calling any other profiling function.
+\par {\pntext\pard\plain\b\cchs0 3.2.2\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileStart
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfileStart()
+\par \pard\plain \widctlpar \f8 Begin profiling at that point in the code. The instructions executed within the function that calls ProfileStart will appear in the result in a function body under the label \ldblquote partial\rdblquote
+, as will any code executed by calling functions if ProfileStop is not called when the function that called ProfileStart exits.
+\par {\pntext\pard\plain\b\cchs0 3.2.3\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileStop
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfileStop()
+\par \pard\plain \widctlpar \f8 Stop profiling at that point in the code. In general, it\rquote
+s a good idea to start and stop profiling at the same level, but that is not required. If you stop while nested deeper than where you started, all the functions still on the call stack will be pop
+ped as if they had exited at the point ProfileStop was called.
+\par {\pntext\pard\plain\b\cchs0 3.2.4\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileDump
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfileDump()
+\par \pard\plain \widctlpar \f8 Dumps the accumulated results to a file called \ldblquote POSER Profile Results\rdblquote . (Future versions should allow you to pass the file name as an argument to ProfileDump.)
+\par {\pntext\pard\plain\b\cchs0 3.2.5\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfilePrint
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfilePrint()
+\par \pard\plain \widctlpar \f8 A debugging function. Prints the profile results as text to POSER\rquote s Log file. Can be very slow.
+\par {\pntext\pard\plain\b\cchs0 3.2.6\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 ProfileCleanup
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 void ProfileCleanup()
+\par \pard\plain \widctlpar \f8 Free up the data structures allocated by ProfileInit.
+\par
+\par {\pntext\pard\plain\b\fs36\cchs0 4.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Reading the Results
+\par \pard\plain \widctlpar \f8 The profiler dumps the results in a format compatible with Metrowerks profiler. This format was reverse engineered, and is incompletely described in Appendix B.
+\par \pard \widctlpar
+\par \pard \widctlpar
+Times are all theoretically in millisecond for a 16.580608 MHz clock. The times are written to the output file as 64-bit integers of clocks, and a multiplier is applied to scale the result to milliseconds based on the clock speed. 5661.518 is a bit over
+ 5 1/2 seconds, and 1.255 is a bit over 1 1/4 milliseconds. (In theory at least, I'm still validating the data, if you see anything that strikes you as inaccurate, please tell me about it!)
+\par \pard \widctlpar
+\par \pard \widctlpar The header in the output file can be ignored. The Overhead field actually contains the number of cycles spent in interrupts, which should be identical to the +Children column for the interrupts block.
+\par \pard \widctlpar
+\par The first column contains the function name, with these special cases:
+\par \pard \fi-1440\li2160\widctlpar functions\tab a top-level cover that includes all regular function calls
+\par interrupts\tab a top-level node that includes all interrupts (except the ones POSEr has patched out)
+\par \pard \fi-1440\li2160\widctlpar partial\tab means profiling was started in the middle of the function, so we don't have the address of the fn and consequently don't have a name.
+\par overflow\tab a lump of all functions called when we're out of space to track more unique calls, where unique means called from the same path to the "root" of the call tree.
+\par \pard \fi-1440\li2160\widctlpar unknown\tab a function for which no name could be found. Many functions in .prc files show up as unknown.
+\par \pard \widctlpar
+\par The rest of the names all take the form "Name $address.x" where:
+\par Name- is the name of the function or trap.
+\par address-For regular functions, the 4 byte address.
+\par \tab -For traps, the 2 byte trap number.
+\par \tab -For interrupts, the 1 byte interrupt number.
+\par x- debugging info, indicating where the name information came from:
+\par \tab 't' = trap names table built in POSER,
+\par \tab 'm'= the ROM.Map file found in the same directory as POSER
+\par \tab 'd'=the debug symbol appended to the function\rquote s instructions by the compiler
+\par \tab 'i'=invalid address flag (usually due to POSERs implementation internals)
+\par
+\par The other columns are defined as follows. Note MINIMUM and STACK SPACE are NOT what you expect:
+\par
+\par {\b count} - the number of times the functions was called.
+\par
+\par {\b only} - time spent in the function, not counting child fns or interrupts.
+\par
+\par {\b %} (by only) - percentage of total profiling time spent in this fn/call.
+\par
+\par {\b +Children} - time spent in the function including child fns, but not including interrupts
+\par
+\par {\b %} (by +Children) - percentage of total profiling time spent in the fn and its kids
+\par
+\par {\b Average} - "Only" divided by "count"
+\par
+\par {\b Maximum} - the maximum time (in msec) spent in any 1 call to the fn.
+\par
+\par \pard \widctlpar {\b Minimum} - {\i NOT WHAT YOU EXPECT}. This is actually the time spent handling interrupts for calls to that particlular instance of that fn. Due to the way the "Summary" is calculated, this number won't be correct in summary views.
+
+\par \pard \widctlpar
+\par \pard \widctlpar {\b Stack space} - {\i NOT WHAT YOU EXPECT}
+. More of a trap/interrupt counter plus some debug info. The number in that field for a particular fn entry is incremented by 1 every time the fn is interrupted, by 10000 if the fn call is made by a faked up RTS instead of a JSR, and 1000 if the functio
+n was executing when an RTS occurred that didn't return to it's called but instead returned to some fn farther up the call chain. Again, this will only be useful in the detail view, since the summary does some computation on it.
+\par {\pntext\pard\plain\b\fs36\cchs0 5.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Appendix A - Profiling Includes
+\par {\pntext\pard\plain\b\i\fs28\cchs0 5.1\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 EmuTraps.h
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 /*********************************************************************
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 *
+\par * Copyright (c) 1998
+\par * 3Com/Palm Computing Division. All rights reserved.
+\par *
+\par * Redistribution and use in source and binary forms, with or without
+\par * modification, are permitted provided that the following conditions
+\par * are met:
+\par *
+\par * 1. Redistributions of source code must retain the above copyright
+\par * notice, this list of conditions and the following disclaimer.
+\par *
+\par * 2. Redistributions in binary form must reproduce the above
+\par * copyright notice, this list of conditions and the following
+\par * disclaimer in the documentation and/or other materials provided
+\par * with the distribution.
+\par *
+\par * 3. All advertising materials mentioning features or use of this
+\par * software must display the following acknowledgement:
+\par *
+\par *\tab \tab This product includes software developed by 3Com and its
+\par *\tab \tab contributors.
+\par *
+\par * 4. Neither 3Com nor the names of its contributors may be used to
+\par * endorse or promote products derived from this software
+\par * without specific prior written permission.
+\par *
+\par * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+\par * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+\par * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+\par * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+\par * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+\par * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+\par * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+\par * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+\par * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+\par * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+\par * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+\par * OF SUCH DAMAGE.
+\par *
+\par *******************************************************************/
+\par #pragma once
+\par
+\par #define\tab emuTrapBase\tab \tab \tab 0x0000
+\par
+\par typedef enum \{
+\par \tab emuTrapProfileInit = emuTrapBase,
+\par \tab emuTrapProfileStart,
+\par \tab emuTrapProfileStop,
+\par \tab emuTrapProfileDump,
+\par \tab emuTrapProfileCleanup,
+\par
+\par \tab // WARNING!! LEAVE THIS ONE AT THE END AND ALWAYS ADD NEW TRAPS TO
+\par \tab // THE END OF THE TRAP TABLE BUT RIGHT BEFORE THIS TRAP!!!!!!!!!
+\par \tab emuTrapEmuReserved1,
+\par \tab emuTrapEmuReserved2,
+\par \tab emuTrapEmuReserved3,
+\par \tab emuTrapEmuReserved4,
+\par \tab
+\par \tab emuTrapLastTrapNumber
+\par \tab \} EmuTrapNumber;
+\par
+\par
+\par #define emuTrapNum\tab \tab \tab \tab 0x0E\tab \tab // Emulator trap
+\par
+\par #define EMU_TRAP(trapNum) \\
+\par \tab TWOWORD_INLINE(m68kTrapInstr+emuTrapNum,trapNum)
+\par
+\par #define ASM_EMU_TRAP(trapNum)\tab \\
+\par \tab \tab \tab DC.W\tab m68kTrapInstr+emuTrapNum; \\
+\par \tab \tab \tab DC.W\tab trapNum
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par {\pntext\pard\plain\b\i\fs28\cchs0 5.2\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 EmuProfiling.h
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 /*********************************************************************
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 *
+\par * Copyright (c) 1998
+\par * 3Com/Palm Computing Division. All rights reserved.
+\par *
+\par * Redistribution and use in source and binary forms, with or without
+\par * modification, are permitted provided that the following conditions
+\par * are met:
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 *
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 * 1. Redistributions of source code must retain the above copyright
+\par * notice, this list of conditions and the following disclaimer.
+\par *
+\par * 2. Redistributions in binary form must reproduce the above
+\par * copyright notice, this list of conditions and the following
+\par * disclaimer in the documentation and/or other materials provided
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 * with the distribution.
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 *
+\par * 3. All advertising materials mentioning features or use of this
+\par * software must display the following acknowledgement:
+\par *
+\par *\tab \tab This product includes software developed by 3Com and its
+\par *\tab \tab contributors.
+\par *
+\par * 4. Neither 3Com nor the names of its contributors may be used to
+\par * endorse or promote products derived from this software
+\par * without specific prior written permission.
+\par *
+\par * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+\par * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+\par * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+\par * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+\par * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+\par * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+\par * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+\par * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+\par * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+\par * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+\par * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+\par * OF SUCH DAMAGE.
+\par *
+\par *******************************************************************/
+\par #pragma once
+\par
+\par #include "EmuTraps.h"
+\par
+\par void ProfileInit(int maxCalls, int maxDepth)
+\par \tab \tab \tab EMU_TRAP(emuTrapProfileInit);
+\par
+\par void ProfileStart()
+\par \tab \tab \tab EMU_TRAP(emuTrapProfileStart);
+\par
+\par void ProfileStop()
+\par \tab \tab \tab EMU_TRAP(emuTrapProfileStop);
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 void ProfileDump()
+\par \tab \tab \tab EMU_TRAP(emuTrapProfileDump);
+\par
+\par void ProfileCleanup()
+\par \tab \tab \tab EMU_TRAP(emuTrapProfileCleanup);
+\par
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par {\pntext\pard\plain\b\i\fs28\cchs0 5.3\tab}\pard\plain \s2\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl2\pndec\pnprev1\pnstart1\pnsp144 }\b\i\f8\fs28 EmuProfilingNOPs.c
+\par \pard\plain \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 // stub out the functions for simulator builds only
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par void ProfileInit(int maxCalls, int maxDepth) \{return;\}
+\par void ProfileStart() \{return;\}
+\par void ProfileStop() \{return;\}
+\par void ProfileDump() \{return;\}
+\par void ProfilePrint() \{return;\}
+\par void ProfileCleanup() \{return;\}
+\par {\pntext\pard\plain\b\fs36\cchs0 6.\tab}\pard\plain \s1\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl1\pndec\pnprev1\pnstart1\pnsp144 {\pntxta .}}\b\f8\fs36 Appendix B - Metrowerks Profiler File Format
+\par \pard\plain \widctlpar \f8
+The profile output file is composed of three sections. A header section of 0x200 bytes, then a section of FnCallRecord structures containing an array of function data, followed by a string table containing the names of each function. T
+he functions are represented in a tree, where each node represents a given function when called from a particular path to the root of the tree. That is, if A calls C and B calls C, then there will be at least 2 records in the tree representing calls to C
+, once when called from A and another when called from B. I say at least 2 because A and B themselves may be called from multiple places, and each unique version of A and B will also have a unique child node representing C.
+\par {\pntext\pard\plain\b\cchs0 6.1.1\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Header
+\par \pard\plain \widctlpar \f8 The header section contai
+ns things like the number of functions in the function data array, and offset to the start of the string table, the size of the string table, and the record number (array index) of the root node in the function tree.
+\par \pard \widctlpar
+\par \pard\plain \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 struct ProfFileHeader \{
+\par \pard \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab UInt32\tab proF;\tab \tab \tab \tab \tab // 'proF'
+\par \tab UInt32\tab version;\tab \tab \tab \tab // 0x00040002
+\par \tab UInt32\tab fnCount;\tab \tab \tab \tab // number of unique fns (records) in log
+\par \tab UInt32\tab four;\tab \tab \tab \tab \tab // 0x00000004
+\par
+\par \tab UInt32\tab zeros1;\tab \tab \tab \tab // 0x00000000
+\par \tab UInt32\tab zeros2;\tab \tab \tab \tab // 0x00000000
+\par \tab UInt32\tab unknown;\tab \tab \tab \tab // 0xB141A3A9\tab - maybe timebase data
+\par \tab UInt32\tab recordsSize;\tab \tab // size of header plus size of data (or offset to string table)
+\par \tab
+\par \tab UInt32\tab stringTableSize;\tab // size of string table in bytes
+\par \tab UInt64\tab overhead;\tab \tab \tab // count for overhead
+\par \tab Int32\tab rootRec;\tab \tab \tab \tab \tab // record number of root of tree
+\par \tab
+\par \tab UInt32\tab sixtyfour1;\tab \tab \tab // 0x00000064
+\par \tab UInt32\tab sixtyfour2;\tab \tab \tab // 0x00000064
+\par \tab UInt32\tab countsPerTime; \tab // translation between counts at nodes and integers in column
+\par \tab \tab \tab \tab \tab \tab \tab \tab \tab \tab \tab // 0x00FD0000 = 16.580608 MHz with display in seconds
+\par \tab \tab \tab \tab \tab \tab \tab \tab \tab \tab \tab // 0x000040C4 = 16.580608 MHz with display in milliseconds
+\par \pard \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab UInt32\tab oddstuff0;\tab \tab \tab // seems like it can be 0, set by profiler tool itself
+
+\par \pard \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab
+\par \tab UInt32\tab oddstuff1;\tab \tab \tab // seems like it can be 0, set by profiler tool itself
+\par \tab UInt32\tab oddstuff2;\tab \tab \tab // seems like it can be 0, set by profiler tool itself
+\par \tab UInt32\tab oddstuff3;\tab \tab \tab // seems like it can be 0, set by profiler tool itself
+\par \tab UInt32\tab oddstuff4;\tab \tab \tab // seems like it can be 0, set by profiler tool itself
+\par
+\par \pard \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab Byte\tab unused[0x200 - 0x50];\tab // for 0x200 bytes
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \};
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par {\pntext\pard\plain\b\cchs0 6.1.2\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 Function Array
+\par \pard\plain \widctlpar \f8 Following the header (starting
+ at offset 0x200 in the file) is an array of header.fnCount structs as defined below. Each struct represents a unique node in the tree. Most of these values are straightfoward, and appear in the results view representing what you expect. The sib and ki
+d records determine the relationship to other functions in the tree. Children of a given node are found by looking at the node\rquote s kid field to find the first child, then look at the child\rquote
+s sib field to find the adjacent nodes which are all considered children of the first kid\rquote s parent. If the sib or kid contain -1 then there are no sibling or children nodes.
+\par \pard \widctlpar
+\par \pard\plain \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \f3\fs20 struct FnCallRecord \{
+\par \pard \s34\fi-1714\li1714\keepn\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760 \tab UInt32\tab name;\tab \tab \tab \tab
+// also offset from start of name table to this fn's name
+\par \tab UInt32\tab entries;\tab \tab \tab // times function was called
+\par \tab UInt64\tab cyclesSelf;\tab \tab // profiling data for this fn alone
+\par \tab UInt64\tab cyclesPlusKids;\tab // profiling data for this fn with kids
+\par \tab UInt64\tab cyclesMin;\tab \tab // profiling data for this fn alone, min
+\par \tab UInt64\tab cyclesMax;\tab \tab // profiling data for this fn alone, max
+\par \tab Int32\tab \tab sib;\tab \tab \tab \tab // record number of sib, -1 for no sibs
+\par \tab Int32\tab \tab kid; \tab \tab \tab \tab // record number of kid, -1 for no kids
+\par \tab UInt32\tab stackUsed;\tab \tab // bytes of stack used by fn, we use it to count unmatched returns
+\par \};
+\par \pard \s34\fi-1710\li1710\widctlpar\tx360\tx720\tx1080\tx1440\tx1710\tx1800\tx2160\tx2520\tx2880\tx3240\tx3600\tx3960\tx4320\tx4680\tx5040\tx5400\tx5760
+\par {\pntext\pard\plain\b\cchs0 6.1.3\tab}\pard\plain \s3\sb240\sa60\keepn\widctlpar{\*\pn \pnlvl3\pndec\pnprev1\pnstart1\pnsp144 {\pntxtb .}}\b\f8 String Table
+\par \pard\plain \widctlpar \f8
+After the array of function records is a string table. This table contains the names of all the functions in the profiling output. Each function name appears only once, and all the nodes that represent that function will refer to the same string. Order
+ of strings within the string table is not important.
+\par \pard \widctlpar
+\par \pard \widctlpar T
+he table is stores as adjacent C strings. That is, the first byte of the table is the first byte of the first string, and subsequent bytes contain the rest of the first string until a NULL (0) byte appears. Immediately after the terminator is the first
+byte of the next string.
+\par } \ No newline at end of file
diff --git a/Docs/UsingPalmOSEmulator.pdf b/Docs/UsingPalmOSEmulator.pdf
new file mode 100644
index 0000000..7e0ef9e
--- /dev/null
+++ b/Docs/UsingPalmOSEmulator.pdf
Binary files differ
diff --git a/Docs/_Bugs.txt b/Docs/_Bugs.txt
new file mode 100644
index 0000000..8f31052
--- /dev/null
+++ b/Docs/_Bugs.txt
@@ -0,0 +1,116 @@
+========================================================================
+Bug List for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+This document contains the list of known significant bugs in the Palm
+OS Emulator. This list is not complete -- many insignificant or
+low-runner bugs have been omitted just to keep up the signal to noise
+ratio.
+
+* Neil needs to receive cmdInitDatabase when his app is installed.
+
+* You can't reliably change the time with the Preferences App. The
+ time is generally synched with the host PC time.
+
+* It's not a good idea to load applications while the Launcher (the
+ "Applications" application) is running. If the program you're
+ loading doesn't already exist, it won't show up in the list of
+ installed application until you quit and restart Launcher. If the
+ application you're loading _does_ already exist, the Launcher won't
+ refresh it's list, and will end up with a stale reference to the
+ version you'd just replaced, leading to a Launcher crash.
+
+* We've seen one case where MacEmulator will draw the LCD area with a
+ white background in single-scale mode instead of green. The cause
+ of this problem appears to be with an out-of-date driver for a video
+ acceleration board. Unless this is an issue for you, we probably
+ won't try to figure out a workaround.
+
+* When working with an external debugger, make sure the ROM is awake
+ (and not sleeping with a blank screen). Otherwise, communication
+ between the two applications will not occur.
+
+* Selecting Pilot, PalmPilot, Palm III, or Palm VII as the device to
+ emulate always results in a PalmPilot being emulated. There are
+ very few side effects of this bug (for instance, a Pilot will now
+ indicate that it has backlighting) but fixing this problem will
+ probably cause more problems than it fixes (for instance, the Palm
+ VII OS would then think that it's on Palm VII hardware instead of
+ PalmPilot hardware and start trying to do Palm VII-specific things,
+ and crashing because there is little actual support for Palm VII
+ hardware).
+
+* When using NetLib redirection, NetLibSelect doesn't support the use
+ of sysFileDescStdIn or sysFileDescStdOut.
+
+* There is no IR emulation.
+
+* HotSync doesn't work on Visor devices.
+
+* Many operations will hang the emulator if performed when the
+ emulated power is off. These operations include -- but are not
+ limited to -- typing characters, clicking on the LCD area, running
+ Gremlins, and installing files. To be on the safe side, limit
+ yourself to clicking on the hard buttons and closing/quitting the
+ session.
+
+* Sound emulation doesn't work on the Mac. The facilities previously
+ used don't appear to be available under Carbon, and we haven't yet
+ found any alternatives. If you know about sound on the Mac, we
+ could use your help!
+
+* The English Output created by the minimization process is very
+ preliminary, rough, and incomplete. Some things to know:
+
+ * Pen down-drag-up event sequences are reported as a series of
+ "Tap Pen" messages instead of "Press pen here, move to there,
+ and finally lift up".
+
+ * The English output will likely contain many messages to "Tap
+ at x,y" instead of something more helpful like "Tap on button
+ called 'Foo'". That's because the code that determines what was
+ tapped on is incomplete. For instance, if the tap was on a menu
+ item, you'll get the generic tap message.
+
+ * In the cases where a tap at a specific location can't be
+ related in terms for form objects or menu items, or where the
+ exact location in the form object is critical (for instance, in
+ the case of a scrollbar, where taps on the arrows are different
+ from taps on the main part of the scrollbar but are still
+ reported the same way), we hope to provide screen shots with
+ cross-hairs at the location you should tap.
+
+ To address these shortcomings, you may want to do one of two things:
+
+ * Help the Palm OS Emulator effort by modifying Poser's output
+ to be more accurate and expressive. The schedule for the next
+ release of Poser doesn't include time for Palm to address the
+ issues in-house.
+
+ * Replay the events from the <Original_File>_Min.pev file. This
+ effectively carries out the steps described in the English
+ output. The drawback with this approach is that replaying
+ events also reloads the initial state that existed when the
+ events were generated. That is, you can't, say, start debugging
+ your application under CodeWarrior, replay the events until an
+ error occurs, and then break into the debugger.
+
+ Enabling such a scenario may also be considered a third party
+ opportunity.
+
+* Certain versions of Windows (NT 4.0 and '95 for sure, don't know
+ about '98 or ME, but fixed in 2000 and XP) have a problem where they
+ can truncate the bottom of the Choose File common dialog. The amount
+ of this truncation (and even whether or not it occurs) is based on
+ the size an location of the topmost window when the dialog is
+ opened. If you are seeing this truncation, try moving the
+ underlying window or dialog up on the screen before opening the
+ Choose File dialog.
+
+* Single-stepping in Gremlins when there is no specified upper event
+ limit doesn't work.
diff --git a/Docs/_Building.txt b/Docs/_Building.txt
new file mode 100644
index 0000000..da10bfa
--- /dev/null
+++ b/Docs/_Building.txt
@@ -0,0 +1,153 @@
+========================================================================
+Build Notes for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+========================================================================
+Windows
+========================================================================
+To build the Palm OS Emulator under Windows, you will need Visual C++
+6.0. The Emulator runs under Windows 95, Windows 98, Window ME, Windows
+NT 4.0, Window 2000, and Windows XP, so you should be able to build
+under those environments, too.
+
+To build, simply load the workspace (Emulator.dsw) or project
+(Emulator.dsp) from the BuildWin directory, select the project target
+(you'll mostly likely be interested in building "Win32 Release"), and
+select the the "Build/Build Emulator.exe" menu item. For that target,
+the resulting executable will end up in
+".../BuildWin/Release/Emulator.exe".
+
+If you want to build the ROM Transfer Palm OS application, you will need
+CodeWarrior for Palm OS Release 7.
+
+========================================================================
+Macintosh
+========================================================================
+To build the Palm OS Emulator under Mac OS, you will need CodeWarrior
+Pro 7.0.
+
+To build, simply load the project Emulator.mcp in the BuildMac folder,
+select the project target (you'll mostly likely be interested in
+building "POSER PPC"), and select the the "Make" menu item. For that
+target, the resulting executable will end up in "...:BuildMac:Built:Palm
+OS Emulator".
+
+If you want to build the ROM Transfer Palm OS application, you will need
+CodeWarrior for Palm OS Release 7.
+
+========================================================================
+Unix
+========================================================================
+
+(A cool HOWTO by Jan Schaumann can be found at:
+
+ <http://www.netmeister.org/palm/POSE/POSE-HOWTO.html>)
+
+Palm OS Emulator for Unix has been built on a number of platforms, but
+the one it's developed under is RedHat Linux 6.0 (kernel 2.2.5,
+glibc-devel 2.1.1-6 using XFree86 3.3.3.1-49 running a 16 bit display).
+People have also built it under SuSe Linux, Solaris 2.6 and 2.7,
+FreeBSD, Debian, and QNX Neutrino, so you may have luck under those or
+other environments. Developers using RedHat Linux 7.0 need to make sure
+that they have the gcc compiler patch from RedHat.
+
+ <http://www.redhat.com/support/errata/rh7-errata-bugfixes.html>
+
+We use pthreads, so you need GNU glibc2 (aka Linux libc6) C library and
+a 2.x kernel on a Linux system. Other operating systems need to support
+true threads.
+
+The source makes heavy use of C++ templates and exceptions. On Linux,
+you must have egcs-1.1.1 or better to compile it. egcs-1.1 or any gcc
+below 2.95 may not work. RedHat Linux 6.0 comes with egcs 1.1.2, so you
+should be OK there. If you are running RedHat Linux 5.2, you will need
+to download the latest from <http://egcs.cygnus.com> and build it. For
+other OS'es, either use egcs, or be sure your compiler supports these
+C++ features.
+
+Note that egcs needs to be built with the HANDLE_SYSV_PRAGMA option
+turned on in order to have the support to pack structures correctly. The
+Linux version of egcs has this turned on, but other variants -- such as
+the compiler that comes with FreeBSD -- may not. If you're using gcc
+2.95 or later, make sure it was compiled with the HANDLE_PRAGMA_PACK
+option.
+
+Sparc note: the Sparc assembler doesn't seem able to handle the mangled
+C++ names emitted by GCC. You may have to follow the instructions in
+the GCC FAQ "How to work around too long C++ symbol names?"
+
+Some versions of Linux are included with a version of gcc that cannot
+correctly compile the emulator. It has a code generation bug that
+causes the emulator to crash on startup. If you have gcc 2.96 or 2.97,
+you probably have a version with the bug. Our configure script
+attempts to detect compilers with the bug and invokes some workarounds
+if it finds one. If those workarounds don't appear to be working for
+you, you may want to revert to gcc 2.95.x or upgrade to gcc 3.0.x. Here
+are instructions from one developer:
+
+ What I did was compile gcc 2.95.3 --prefix=/usr/local/gcc2953 (ie, I
+ didn't destroy the 2.96 conpiler). Using that compiler (export
+ CC=/usr/local/gcc2953/bin/gcc, CXX=/usr/local/gcc2953/bin/g++), I
+ built glibc-2.2.2 and installed that in /usr/local. After that
+ completed, I put /usr/local/lib at the head of the search list in
+ /etc/ld.so.conf and rebooted. Then I compiled fltk and the emulator.
+ This time it worked. It may not be necessary to build the libraries
+ -- All I know is that it worked!
+
+We use the FLTK X toolkit. I'm not going to get into an X GUI Toolkit
+religious war, so don't ask why not some other toolkit. You are
+encouraged to add support for other toolkits, like Qt or GTK+ or even
+Xt. I have tried to keep all of the FLTK code in the Em*Fltk.cpp files.
+If you add support for another toolkit, please follow that pattern.
+Don't pollute the UNIX-generic code with toolkit specific code. FLTK is
+available from <http://www.fltk.org>, is a quick download, and is easy
+to build on a variety of OS'es. We've tested with the binary install
+RPMs for 1.0.3 and 1.0.4, as well as the source install of 1.0.5 and
+1.0.7. "fluid" (the FLTK User Interface Design tool) is part of the
+build, so make sure it gets installed, too.
+
+ NOTE: Not all FLTK's install the same way. Some install their
+ includes in an "Fl" directory, some install their includes in
+ an "FL" directory. The emulator is written to look for them
+ in "FL". If you don't have that directory, you may need to
+ create a symbolic link with that name to "Fl".
+
+ Additionally, the Emulator's build script expects libfltk.a to
+ be installed in /usr/lib or /usr/local/lib. If you've
+ installed it elsewhere, use the --with-fltk=DIR configure
+ flag. The directory you specify will be used as the prefix
+ for additional "include" and "lib" dirs to search.
+
+ NOTE: Many users have compiled against FLTK 1.0.11 with no
+ apparent problems, so using that version instead of 1.0.7
+ should be OK. FLTK 1.1.0 (in beta at the time of this
+ writing) is only minimally supported. Emulator 3.5 includes
+ initial support for this version of FLTK, but little testing
+ has been performed. Our confidence is high that there are no
+ problems, but your mileage may vary.
+
+To build the Emulator, first build and/or install FLTK. Doing this
+first is very important. Otherwise, the Emulator's build script won't
+find it. After that, switch to the BuildUnix directory and execute
+the following commands:
+
+ ./configure
+ make
+
+You will end up with an application called "pose" that you can run.
+
+If you want, the "configure" script understands the following command-
+line switches:
+
+ --enable-palm-profile Include support for profiling Palm applications
+ --enable-profile Include support for profiling Poser itself
+ --enable-debug Include debugging symbols. This option also
+ turns on palm-profile, turns off profile, and
+ compiles the source code without optimizations.
+ --enable-static-link static link; no shared libraries (default no).
+ --with-fltk=DIR Use the fltk which is installed on DIR.
diff --git a/Docs/_Contributing.txt b/Docs/_Contributing.txt
new file mode 100644
index 0000000..89873f6
--- /dev/null
+++ b/Docs/_Contributing.txt
@@ -0,0 +1,176 @@
+========================================================================
+Contributing guidelines for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+The Palm OS Emulator is distributed under and protected by the GNU
+GENERAL PUBLIC LICENSE (the full copy of which is found in _GPL.txt).
+We make the source code available so that others can alter it for their
+own needs. We do request you submit your changes back to us so that we
+can merge them into the main version of the product, but there is no
+requirement that you do so. Changes can be submitted to the current
+maintainer (<mailto:keith.rollin@corp.palm.com>) or Palm Developer
+Support (<mailto:bug.reports@corp.palm.com>).
+
+If you make changes and submit them back to us, all I ask is that you
+follow a few guidelines. The general theme of these guidelines is to
+follow the programming conventions you already find in the source code.
+I don't want this thing to look like a patchwork quilt; it should look
+like it was written by just one person.
+
+* Naming conventions: I use MacApp's naming conventions:
+
+ Function names begin with upper case letters (e.g., SomeFunction).
+
+ Private function names begin with "Prv" (e.g. PrvHelperFunction).
+ This includes static functions (local to a single file) and
+ private member functions.
+
+ Local variables begin with lower case letters (e.g., myVariable).
+
+ Global variables begin with a "g" (e.g., gCachedData).
+
+ Data members begin with an "f" (e.g., fFieldOfDreams). However,
+ I'm flexible on this one. I think the UNIX guys are using
+ "_" for the UNIX-specific portions, and there are probably
+ still some Mac sections that use "m".
+
+ Static data members begin with "fg" (e.g., fgDebuggerData).
+
+ Constants start with a "k" (e.g., kTicksPerSecond).
+
+ To help clean up the namespace a little bit, data types (classes,
+ structs, typedefs, etc.) and file names start with the "Em"
+ prefix. You may see a mix of this now in the sources, because
+ I'm slowly moving over to that convention. Using the "Em"
+ prefix for types is more "primitive" that using actual namespaces,
+ but it's simpler (easier to type).
+
+ File guards are based on the name of the file, with the '.' replaced
+ with an underscore. Thus, the fileguard for EmWhizzyHeader.h is
+ EmWhizzyHeader_h. File guards are placed only in the header; they
+ are not used to control the inclusion of the header from another
+ file.
+
+* Use classes and objects only where it makes sense. There's no need
+ to go overboard.
+
+* You'll see some places where I use classes with all-static members
+ to emulate namespaces. This approach was used before CodeWarrior
+ supported namespaces. Now that it does, I've started using
+ namespaces. However, neither CodeWarrior Pro 5 nor VC++ 6.0
+ support namespaces in their browsers, so choose which method you
+ like if you introduce a new namespace.
+
+* By convention, I use pointer types (e.g., "void*") for referencing
+ data in the host computer's space, and the UAE type "emuptr" to
+ reference data residing in the emulated Palm OS space. (This
+ comment may not make much sense now, but come back to it later
+ once you've looked over the sources and learned how Palm OS
+ memory is emulated.)
+
+* Braces go like this:
+
+ if (...)
+ {
+ ...
+ }
+
+ I use this approach because it is consistant with the bracing rules
+ for function bodies, it's easy to match up the begin and end of
+ a block, and because it's easy to comment out the "if" statement
+ in order to make the block unconditional. People trying to comment
+ out the "if" statement when it also includes the left brace at the
+ end have to deal with finding and commenting out the right brace
+ as well.
+
+ The contents always move to the right. None of this in-and-out,
+ back-and-forth GNU stuff.
+
+ I generally like to use braces even if there is only one line
+ in between them, but I'm not adamant about that.
+
+* One statement per line. None of this stuff:
+
+ if (...) DoSomething();
+
+ I don't like the DoSomething() being on the same line, since that
+ makes it impossible to put a breakpoint on it.
+
+* Comment all functions using the following template:
+
+ /***********************************************************************
+ *
+ * FUNCTION:
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+ Not all functions are currently like this, but I'm working on that.
+
+* Call global functions using "::". E.g.:
+
+ ::SomeGlobalFunction ();
+
+ Again, not all of Poser sources follow this convention, but I'd
+ like to stick to it.
+
+* When calling non-static member functions from another function of the same
+ class or subclass, use "this->". When calling static member functions,
+ you may use "EmMyClass::" to prefix the function call. However, I'm not
+ really sure I like this latter convention, so use the prefix or not, as
+ you choice.
+
+* When referencing a data member, you may want to also use the "this->"
+ prefix. I currently don't use this much in Poser, preferring to use
+ the "f" prefix in the data member's name to indicate that it is a data
+ member. However, by using "this->", you can take advantage of VC++'s
+ type-completion features, which I'm finding to be really handy.
+
+* No platform-specific calls in the cross-platform files. If you find any
+ counter-examples to this rule, it's a bug.
+
+* Let's not go overboard with STL. Yes, I know you can write a MasterMind
+ program in one line with it (true!), but let's keen this sane.
+
+* Whitespace. Use lots of it! Vertically and horizontally! It's possible
+ to go overboard -- I knew one programmer who put spaces around every token
+ in his code, leading to stuff like:
+
+ if ( myPtr -> mySubStruct . myField )
+ {
+ for (ii = 0 ; ii < max ; ++ ii)
+ {
+ myObject -> CallSomeFunction ( ii * 2 ) ;
+ }
+ }
+
+ But this is a bit extreme for me. I like putting braces on their own lines
+ for the vertical spacing, spaces in mathematical expressions, and spaces
+ between the function name and following parameter list, as well as the
+ places most other programmers put them.
+
+ if (myPtr->mySubStruct.myField)
+ {
+ for (ii = 0; ii < max; ++ii)
+ {
+ myObject->CallSomeFunction (ii * 2);
+ }
+ }
+
+Anyway, I'm flexible on most of this stuff. These are merely guidelines. I'm
+just asking that you keep them in mind if possible.
+
+Thanks,
+
+-- Keith Rollin
+-- Palm OS Emulator engineer
diff --git a/Docs/_Credits.txt b/Docs/_Credits.txt
new file mode 100644
index 0000000..d42f661
--- /dev/null
+++ b/Docs/_Credits.txt
@@ -0,0 +1,219 @@
+========================================================================
+Credits for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+The Palm OS Emulator is currently a Palm Computing product. However, it
+was not originally written by Palm Computing. Rather, it was developed
+by outside developers, on their own time and without help from Palm
+Computing. This product is a tribute to them, their perseverance,
+their creativity and their ingenuity. We just stepped in after the hard
+parts were done.
+
+------------------------------------------------------------------------
+* Greg Hewgill
+ <http://www.hewgill.com/>
+
+ Original Copilot, the basis for the Windows version of the Palm OS
+ Emulator. See the article "13hewgil.pdf" on how he developed
+ Copilot.
+
+------------------------------------------------------------------------
+* Craig Schofield
+ <http://members.aol.com/illumesoft/illume.html>
+
+ Macintosh port of Copilot, the basis for the Macintosh version of
+ the Palm OS Emulator.
+
+------------------------------------------------------------------------
+* Bernd Schmidt
+ <http://www.freiburg.linux.de/~uae/>
+
+ UAE (UAE Amiga Emulator), which provides the 68000 CPU emulator
+ used at the core of Copilot.
+
+------------------------------------------------------------------------
+* Bruce Ashley Photography
+ Santa Cruz, Ca 831-429-8300
+ email: ba@phot.com
+
+ For the amazing skins.
+
+------------------------------------------------------------------------
+* Bill Spitzak and others
+ <http://www.fltk.org/>
+
+ FLTK - Fast Light Tool Kit for Unix (and Windows and soon Mac).
+
+------------------------------------------------------------------------
+* Matthias Ulrich Neeracher
+ <http://www.sourceforge.net/projects/gusi>
+ <http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html>
+
+ GUSI -- the Grand Unified Sockets Interface for Macintosh.
+
+------------------------------------------------------------------------
+* John C. Daub
+
+ CURLPushButton, used in the Mac emulator's About Box.
+
+------------------------------------------------------------------------
+* Quinn "The Eskimo" and Peter N Lewis, et al
+ <ftp://ftp.interarchy.com/>
+
+ Internet Config, the brains behind the hyperlinks in the Mac emulator's
+ stunning About Box.
+
+------------------------------------------------------------------------
+* Neil Rhodes
+
+ Communications Toolbox support in Mac serial code.
+
+------------------------------------------------------------------------
+* Ron Marianetti
+
+ Fixes and speedups to the TCP/debugger handling code.
+
+------------------------------------------------------------------------
+* Adam Dingle
+
+ Conditional breakpoints.
+ Profiling output enhancements.
+ Display address of corruption in errors reporting corrupted heaps.
+
+------------------------------------------------------------------------
+* Jean-loup Gailly
+ <http://www.gzip.org/>
+
+ gzip.
+
+------------------------------------------------------------------------
+* The Independent JPEG Group
+ <http://www.ijg.org/>
+
+ JPEG decompression routines.
+
+------------------------------------------------------------------------
+* Jeff Prosise
+
+ The CQuantize class for collecting palette colors from a 24-bit image.
+
+ Algorithm from the August 1996 issue of Microsoft Systems Journal.
+ <http://msdn.microsoft.com/library/periodic/period96/msj/S3F1.htm>
+
+ Source code from the October 1997 issue of Microsoft Systems Journal.
+ <http://msdn.microsoft.com/library/periodic/period97/wicked1097.htm>
+
+------------------------------------------------------------------------
+* Catherine White, Stuart Malone
+ <http://www.llamagraphics.com/>
+
+ Profiling code clean-ups.
+ Many excellent bug reports and analyses.
+
+------------------------------------------------------------------------
+* Jerry Kirk, Michael Kedl
+
+ QNX Neutrino port.
+ Added serial port emulation code.
+ Added additional keyboard support.
+ Fixed massive memory leak.
+
+------------------------------------------------------------------------
+* Jon Fo
+
+ Solaris 2.6/7 modifications.
+
+------------------------------------------------------------------------
+* Frank Yellin
+
+ Solaris 2.6/7 modifications.
+ Many bug fixes to the NetLib redirection code.
+
+------------------------------------------------------------------------
+* Akhil Arora, Sun Microsystems
+
+ For the long-term loan of an Ultra 2 Sparc system for Solaris
+ development.
+
+------------------------------------------------------------------------
+* Stefan Hoffmeister
+
+ Borland C++ Builder port.
+
+------------------------------------------------------------------------
+* The traitor formerly known as the intern known as Jerry Lin
+
+ Boggle sample program.
+ Gremlins Hordes.
+ Palm OS Emulator Binder.
+ Assorted other fit-only-for-an-intern tasks.
+
+------------------------------------------------------------------------
+* The intern known as Toshi Clark
+
+ Eights sample program (cut down version of the 15 puzzle).
+ IR redirection.
+ Session Info dialog.
+ Horde stats.
+ SuperVZ emulation.
+ Initial MediaQ emulation.
+ Gremlin step/resume bug fixes.
+ Support for new (unreleased) Palm device.
+ Unique profile output file names.
+ International Strict Checks.
+ Initial Gremlin Minimization implementation.
+
+------------------------------------------------------------------------
+* Red Dutta
+
+ "Export Database..." menu item.
+
+------------------------------------------------------------------------
+* Ben Darnell
+
+ Debian port.
+
+------------------------------------------------------------------------
+* John Ludwig
+
+ FreeBSD port.
+
+------------------------------------------------------------------------
+* Easy Software
+ <http://www.easysw.com/~mike/espws/>
+
+ FLTK Widget Set.
+
+------------------------------------------------------------------------
+* Scott Gruby
+ <http://www.gruby.org/>
+
+ Carbon port.
+
+------------------------------------------------------------------------
+* Alexandre Parenteau
+ <http://www.cvsgui.org/>
+
+ Carbonized GUSI 2.1.5.
+
+------------------------------------------------------------------------
+* Anthony Fishbeck
+ <http://www.pocketpyro.com/>
+
+ Design of plug-in architecture, and re-implementation of the
+ Emulator's system function patch system to make use of it.
+
+------------------------------------------------------------------------
+* Cooperative Computers, Inc. (Stuart Eichert, Justin Clark)
+ <http://www.coopcomp.com/>
+
+ Gremlin Minimization enhancements.
+
+------------------------------------------------------------------------
+And thanks to the many users of the Palm OS Emulator who have made
+suggestions on how to make it even better!
diff --git a/Docs/_GPL.txt b/Docs/_GPL.txt
new file mode 100644
index 0000000..32d0e60
--- /dev/null
+++ b/Docs/_GPL.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Docs/_News.txt b/Docs/_News.txt
new file mode 100644
index 0000000..d478f8e
--- /dev/null
+++ b/Docs/_News.txt
@@ -0,0 +1,71 @@
+========================================================================
+News (latest changes) for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+========================================================================
+ REVISION HISTORY
+
+ Starting in 2.1d25 (and backdated to 2.1d24) I'm giving credit
+ to the person or people responsible for convincing me to fix a
+ bug or add a feature, in some cases even providing the source code
+ for the bug or feature. These people's names appear in []'s.
+
+ See the file Credits.txt for a list of people who have submitted
+ actual changes to the project.
+========================================================================
+
+
+Changes for 3.5 (2001-03-29)
+----------------------------
+* Added m125, m130, m515, and i705 support. NOTE: at the time of
+ this writing, skins for these devices are not available. There is
+ no estimated date for when they will be available.
+
+* Enabled TRGpro and HandEra330 support for Mac. [Scott Gruby]
+
+* Allow access to the following UI data structures in support of
+ PalmOSGlue that comes with SDK 4.0 Update 1 (DR1):
+
+ read/write access to ControlType.attr for CtlGlueNewSliderControl
+ and CtlGlueSetLeftAnchor
+
+ read access to ListType.itemsText for LstGlueGetItemsText
+
+ read access to TableType.numColumns for TblGlueGetColumnMasked
+
+ read access to GraphicControlType.bitmapID and selectedBitmapID for
+ CtlGlueGetGraphics
+
+* Re-allow read/write access to the text returned by CtlGetLabel,
+ etc. It's OK to read the text, and we'll allow writing to the text
+ until we come up with a better API for altering it. [many]
+
+* Fixed HostImportFileWithID to return a non-zero ID. [Scott Johnson]
+
+* Fixed timeout calculations when using redirected send/recieve
+ calls. [many]
+
+* (Windows) Poser 3.4 de-asserted DTR when opening the host serial
+ port. Poser 3.5 reverts this change (DTR is asserted when the host
+ serial port is opened). [many]
+
+* Fixed problem with inability to set/change socket address/port in
+ serial port emulation redirection. [Mahendra Tailor]
+
+* (Mac) Better Mac OS X support (Quit menu item now respects
+ preferences regarding save-on-quit, and an idle Poser now gives more
+ time to other running processes). [Scott Gruby, Christopher Hunt]
+
+* (Unix) Fix the crawling dialogs (where dialogs appearing quickly in
+ succession march down the screen). [John Marshall]
+
+* When hostErrProfilingNotReady was added in Pose 3.1, it was done in
+ such a way as to change the value of hostErrUnknownError. Re-order
+ those two symbols so that hostErrUnknownError retains its original
+ value (at the expense of changing hostErrProfilingNotReady). [Scott
+ Johnson]
diff --git a/Docs/_OldNews.txt b/Docs/_OldNews.txt
new file mode 100644
index 0000000..3eca435
--- /dev/null
+++ b/Docs/_OldNews.txt
@@ -0,0 +1,6094 @@
+========================================================================
+News (latest changes) archive for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+
+Changes for 3.4 (2001-02-01)
+----------------------------
+* Interim internal release dates:
+ 3.4a1 - 2001-10-18
+ 3.4a2 - 2001-11-01
+ 3.4a3 - 2001-11-09
+ 3.4a4 - 2001-11-13
+ 3.4a5 - 2001-11-15
+ 3.4b1 - 2001-11-20
+ 3.4b2 - 2001-11-27
+ 3.4b3 - 2001-11-29
+ 3.4b4 - 2001-12-03
+ 3.4b5 - 2001-12-05
+ 3.4b6 - 2001-12-06
+ 3.4b7 - 2001-12-10
+ 3.4b8 - 2001-12-18
+ 3.4b9 - 2002-01-21
+
+
+# Documentation: I don't think it's ever been documented what Poser
+ means by "Error" and "Warning" (as listed in the Logging Options
+ dialog). Now, with the Error Handling dialog (see below), it's more
+ important to know what those mean. Errors and Warnings are very
+ similar. The only difference between them is that an Error is
+ generally fatal (the Continue button is disabled in the dialog box
+ displaying the message) and a Warning is not (the Continue button is
+ enabled). Examples of Errors are Address Errors, Divide By Zero
+ Errors, or calls to SysFatalAlert. Examples of Warnings are Low
+ Memory accesses, Direct Screen accesses, and Hardware Register
+ accesses. Since Warnings are not fatal, they can generally be
+ turned off at the developer's option in the Debugging Options
+ dialog.
+
+* Documentation: The release notes for 2.1d16 refer to the "Autoload"
+ facility being added, but it doesn't describe the Autoload facility.
+ What it means is that you can create a directory in the same
+ directory as the Poser executable called Autoload. All installable
+ files in this directory (.prcs, .pdbs, and .pqas) will be installed
+ any time a new session is created or old session is loaded.
+
+ This facility is superceded on Windows and Unix by the -load_apps
+ command line option.
+
+* Added support for cross-platform modeless dialogs. Not only does
+ this finally enable the Gremlin Control Window on Unix, but it paves
+ the way for enabling other features (such as importing files via the
+ Exchange Manager, which needs the progress window to be modeless).
+
+* Added Memory Leak detection, controlled by a new option in the
+ Debugging Options dialog. On SysAppExit, the Emulator looks for
+ memory leaks (much in the same way Palm OS 3.5 and later do). If it
+ finds any, it writes information about the leaks (including memory
+ location, memory contents, and a stack crawl of the context that
+ allocated the leaked block) to a log file. In either case, the Palm
+ OS-generated "you have leaks" dialog is suppressed.
+
+* Added Overlay Errors to the Debugging Options dialog. This option
+ controls a facility of the Overlay Manager in Debug ROMs. When
+ enabled, it sets the omFtrShowErrorsFlag bit of the omFtrCreator
+ Feature. When this bit is set, the Overlay Manager reports errors
+ with overlay databases that it can't validate (name of the overlay,
+ plus the reason why it didn't validate properly).
+
+* When a Gremlin is running, all generated events are now saved to a
+ Palm Event (.pev) file. This event file contains a snapshot of the
+ initial session state along with a list of all the events that
+ Gremlins generated. The event file can be used for event playback
+ or event minimization (see below).
+
+* Added a Replay menu item that re-opens a Palm Event file and
+ replays all the events recorded in it. This is handy if the events
+ in the file lead to an error condition you'd like to create. It is
+ similar to running the same Gremlin on the same application over
+ again, except that instead of regenerating the same random events to
+ post to the application, the events are read from a file.
+
+* Added Minimization menu item. This feature also re-opens a Palm
+ Event file and replays the events in it. Additionally, it goes
+ through an iterative process of removing ranges of events and seeing
+ if the resulting subset of events still leads to a crash. If a
+ crash still occurs, then those events are permanetly removed from
+ the set of events and another range of events is similarly tested.
+ If a crash does NOT occur, then the removed events are put back and
+ again the iterative process tries again by removing another range of
+ events. The end result is a minimal set of events that reproduce a
+ crash. This set of events is saved to a new Palm Event file
+ (suitable for execution using the Replay menu item). As a final
+ step, the set of events is translated into a sequence of English
+ instructions suitable for a human to follow.
+
+ The amount of time it takes to complete the minimization process can
+ vary wildly, depending on the speed of your application, how many of
+ the events in the initial set are required in the final set, where
+ those events are located in the initial set, etc. In the lab, one
+ particular 265 event set minimized to 9 events in 50 seconds, and a
+ 1200 event set minimized to 18 in 11 1/2 minutes. I've heard
+ reports that starting with an initial set of 2000 to 3000 events
+ takes a couple of hours.
+
+ See _Bugs.txt for comments on the English output.
+
+* Added -minimize command-line option. This option takes a path to
+ a .pev file with an event set to minimize. After the minimization
+ has completed, the files are written out as normal and the
+ emulator exits.
+
+* Cleaned up methods for specifying how serial, IR, and and NetLib
+ data are redirected.
+
+* Support setting Trap break from PalmDebugger when executing 'atb
+ A###'. Poser had a bug leading it to support only 'atb
+ "FredFunction"'
+
+* Further restricted direct access to data structures. Poser allows
+ NO access if the OS supports an "accessor" function that provides
+ access to the remaining fields Palm wants to support.
+
+* Allow read access to "attr" fields of Control, List, Bitmap, Label,
+ and Scrollbar objects if the "accessor" function is not available --
+ FrmGlueGetObjectUsable accesses those fields. FrmGlueGetObjectUsable
+ also accesses Gadget and Table objects, but Poser already allows
+ read access to "attr" for those objects. [Catherine White]
+
+* Cleaned up New Session dialog behavior in the face of missing or
+ unusable ROM files.
+
+* Converted dates in _OldNews.txt to John Marshall-approved ISO 8601
+ format.
+
+* (Mac) Fixed bug leading to crash while displaying the "invalid ROM
+ checksum" error message.
+
+* Better UART support: all FIFO interrupts supported, all FIFO sizes
+ correct.
+
+* Tweaks to configure.in to better find GL and FLTK libraries. Look
+ in $ac_x_libraries when searching for GL libraries, and look in
+ $ac_x_libraries (instead of $x_libraries) and GLLIB when looking for
+ FLTK and making sure it has fl_height(). [wart@kobold.org]
+
+* (Unix) Additional gcc 3.0 compatibility. [John Marshall]
+
+* (Unix) Work around gcc 2.95.x and 2.96.x bugs, where they had
+ problems compiling an inline function taking a parameter with a
+ default value that involved calling a virtual function. [John
+ Marshall]
+
+* Removed uses of ## operator with a token only on the right-hand
+ side. This usage is unnecessary and its effect is undefined. [John
+ Marshall]
+
+* (Mac) Updated to CodeWarrior 7.
+
+ * Updated projects.
+
+ * Added LTimerTask.cp and LTimerTaskFunctor.cp to PowerPlant
+ project.
+
+ * Added CarbonFrameworkLib to Poser targets.
+
+ * Removed CustomTextColorCDEF.cp from PowerPlant project.
+
+ * Removed LAMTabsControlImp.cp from PowerPlant project. Register
+ LAMControlImp instead of LAMTabsControlImp.
+
+ * Because LTableView has fixed its problems with setting its
+ background to white, removed custom CWhiteTextColumn class,
+ reverting back to using LTextColumn. Also Removed
+ LColorEraseAttachments from ppobs.
+
+ * Because LAMControlImp now supports > 255 characters, removed
+ LFixedAMStaticTextImp.
+
+ * Because LDialogBox now handles default buttons better, removed
+ LFixedDialogBox. Instead, use custom LNotifierDialogBox so that
+ we can catch when the dialog box is being closed and notify our
+ dialog handling routines.
+
+ * Undeffed EAGAIN and EDEADLK in GUSI's errno.h (defined in
+ <cerrno>) so that it can get redefined in GUSI's sys/errno.h.
+
+ * In GUSI's inttypes.h, include stdint.h instead of defining the
+ C99 standard integer types itself.
+
+ * In GUSI's in.h, comment out IP_OPTIONS...IP_RCVIFADDR, since
+ they're now also defined in OpenTransportProviders.h
+
+ * In GUSI's fcntl.h, make fdopen() match that in MSL's stdio.h
+ (actually stdio.posix.h) again.
+
+ * Added back S64Mod macro removed from <Math64.h>, needed in
+ GUSITimer.cp.
+
+ * In GUSIOTNetDB.cp, don't #undef AF_INET. The idea in this file
+ was to undef it before including <OpenTptInternet.h>, which
+ defines it again. However, before undeffing that symbol,
+ GUSIOTNetDB.cp includes, which includes GUSIOTNetDB.h, which
+ includes GUSIOpenTransport.h, which includes
+ <OpenTptInternet.h>. Which means that <OpenTptInternet.h>
+ defines AF_INET before GUSIOTNetDB has a chance to undef it.
+ They both evaluate to 2 anyway, so duplicate #defines are OK.
+
+ * Added PP_Suppress_Notes_22 to prefix files.
+
+ * Specify LCleanupTask_Terminator as CFM Termination function.
+
+ * CURLPushButton::AdjustCursorSelf -> AdjustMouseSelf.
+
+ * Re-added definition of CRMRec, which is now surrounded by a
+ CALL_NOT_IN_CARBON flag in <CommResources.h>.
+
+ * Re-added definitions of crmSerialDevice and CRMSerialRecord,
+ which are now surrounded by a CALL_NOT_IN_CARBON flag in
+ <CRMSerialDevices.h>.
+
+ * Changed EmAddressBank::check to checkaddr; <Debugging.h> now
+ defines "check".
+
+ * Renamed some private functions in HostControl.cpp so that they
+ no longer started with "__" (thus conflicting with some system
+ functions now defined in MSL).
+
+ * NewPPCCompProc -> NewPPCCompUPP. The former used to be a macro
+ in PPCToolbox.h that was defined to the latter. It's now
+ surrounded by a CALL_NOT_IN_CARBON, so we call NewPPCCompUPP
+ directly, which is defined in EmClassic.cpp.
+
+ * ampCmd -> volumeCmd; freqDurationCmd -> rateMultiplierCmd;
+ squareWaveSynth -> ? (zero, for now).
+
+ * Got rid of EmCustomWindow, making use of the new facilities for
+ creating an LWindow from an existing Mac window.
+
+* (Windows) Change the way Poser remembers and resets its location
+ when changing skins. Poser can be embedded in another application
+ (such as an IDE), and needs to be cognizant that its location is not
+ necessarily in screen coordinates. [Christian Falch]
+
+* (Unix) Added support for --enable-static-link (forces static
+ linking with libraries -- no shared libraries). [Harry Dolan]
+
+* Added preferences for controlling skin appearance (dimming when
+ inactive, red when in debug mode, green when in Gremlin mode).
+
+* Fixed some places where error codes caused by file operations got
+ mangled before they could be used to generate error messages. [John
+ Marshall]
+
+* (Unix) Protect against the window trying to fit itself to the size
+ of a skin when their's no skin being used. [John Marshall]
+
+* Fixed byteswapping bug in NetLibGetServByName when running on a
+ Little Endian platform and NetLib Redirection is on -- the returned
+ port would be byteswapped. [Maurizio Moretti]
+
+* Re-allow calls to the following functions (previously proscribed in
+ 3.3): SysReserved10Trap1, SysReserved30Trap1, SysReserved30Trap2,
+ SysReserved31Trap1, OEMDispatch, OEMDispatch2. It's possible for
+ OEMs to have implemented these traps, or for some version of the OS
+ or extension to have implemented them, in ways that Poser doesn't
+ know about. So allow access to them. If they are in fact not
+ implemented, then Poser's "you just called an unimplemented trap"
+ mechanism will kick in. SysReserved40Trap1, SysReserved40Trap2,
+ SysReserved40Trap3, and SysReserved40Trap4 should also be given the
+ same treatment, but they weren't on the proscribed list in the first
+ place.
+
+* The following functions are now also officially allowed:
+ IntlGetRoutineAddress, SerPrimeWakeupHandler, SerReceiveWindowClose,
+ SerReceiveWindowOpen, SerSetWakeupHandler, SrmOpenBackground,
+ SrmPrimeWakeupHandler, SrmReceiveWindowClose, SrmReceiveWindowOpen,
+ SrmSetWakeupHandler, SysNotifyBroadcast, SyNotifyBroadcastDeferred.
+
+* (Unix) Protect against Poser hanging when performing a "paste the
+ host selection to the Palm OS's clipboard" operation and there is no
+ host selection. [John Marshall]
+
+* Expanded on the ContinueOnWarnings and ExitOnErrors preferences
+ from Poser 3.3. These have now been replace with the preferences
+ WarningOn, WarningOff, ErrorOn, ErrorOff. These control what
+ happens with Warnings and Errors with Gremlins On and Off. Each
+ preference can be set to one of ShowDialog (which will show the
+ message in the familiar error dialog with the Continue, Debug, and
+ Reset buttons), Continue (which will make Poser act as if the user
+ had seen the dialog and pressed the Continue button, but will not
+ actually show the dialog), Quit (which will cause Poser to quit with
+ an error code of 1 if an error occurred or an error code of 2 if a
+ warning occurred), or NextGremlin (which will cause Poser to no
+ longer generate events for the current Gremlin and switch to the
+ next Gremlin in a Horde). Note that these actions take place ONLY
+ if logging is enabled for warnings and errors. If logging is not
+ enabled, then Poser enable them for you (asking you first if it's OK
+ to do so).
+
+* Added a new preferences dialog to support the setting of the
+ WarningOn, WarningOff, ErrorOn, and ErrorOff preferences.
+
+* ContinueOnWarnings and ExitOnErrors can no longer be set from the
+ UI, and their settings will not be saved to the preferences file.
+ However, they CAN be set from the Windows command line or via the
+ HostSetPreference function, and Poser will heed them. SilentRunning
+ was never setable from the UI, but its handling is also the same as
+ the ContinueOnWarnings and ExitOnErrors preferences (you can set it
+ via the command line or HostControl, and Poser will heed it).
+
+* Fixed crasher that could occur if the list of Palm applications in
+ the preferences used to limit what applications a Gremlin could run
+ included an application that no longer existed on the device. [John
+ Marshall]
+
+* Added DmNextOpenDatabase and DmOpenDatabaseInfo Perl wrappers.
+ Added ListOpenDatabases.pl. Added "#!/usr/bin/perl -w" to
+ FormSpy.pl, PoserRPC.pl, and SkipStartup.pl and made them executable
+ types. Fixed up warnings to due adding -w. Updated SkipStartup.pl
+ to skip the language selection form on EFIGS ROMs. [John Marshall]
+
+* (Internal) Massive rewrite of application model, document model,
+ and window model code. Created EmAction and EmActionHandler
+ classes, supporting the manipulation of actions/commands as objects,
+ thus allowing them to be queued up and/or deferred. These changes
+ allow for much sharing of cross-platform code, bring to parity many
+ features (such as command line options on Unix and Mac OS X).
+
+* Implied by the above, command line options are now supported on
+ Unix. They are not supported on the Mac as (a) Mac OS 9 doesn't
+ have a way to specify command line options, and (b) Mac OS X won't
+ launch Poser from the command line in a terminal.
+
+* Fixed problem that could lead to Poser hanging. Poser would from
+ time to time need to suspend emulation at a very safe, stable spot
+ in order to carry out some of its operations. This spot was when
+ EvtGetEvent was called and there were no pending events. However,
+ it was possible that an emulated process would be wedged or in an
+ infinite loop and wasn't calling EvtGetEvent. Poser would hang in
+ the process of waiting for that infinite loop to end. There was
+ another problem similar to this involving background processes, but
+ it's too complicated to get into here. Suffice to say that both
+ problems were solved by using a mechanism different from having
+ Poser wait for EvtGetEvent. [Vitaly Kruglikov, James Phillips, and
+ possibly some other engineers from Handspring]
+
+* (Mac) Added check for minimal Carbon version number. If Carbon is
+ not at least version 1.2.5, display an error message and exit.
+
+* (Mac) Added a top-level exception handler that displays a "Fatal
+ Internal Error" message and quits.
+
+* (Unix) Enabled most HandEra 330 support (code in
+ EmTRGDiskIO::GetFilePath is still not enabled). [Michael Glickman]
+
+* Added HostImportFileWithID. This is the same as HostImportFile,
+ but it returns the LocalID of the installed database. [Ben Combee]
+
+* Changed any references from "Cards" to "HostFS". The Card Options
+ dialog never did anything with emulating SD or any other sorts of
+ cards. It just allowed you to enter parameters for the HostFS
+ extension. Having it say "Cards" just confused people who expected
+ that the options specified there would have some effect on the Card
+ Info application in the Palm OS.
+
+* (Windows) Sped up startup time by assuming that the only files in
+ the Skins directory that can contain link information are those
+ ending in .lnk.
+
+* Recognize databases of type 'htal' as containing system code, and
+ don't complain if they do system-like things. This will allow
+ Network HotSync (when NetSync.prc is installed in RAM) to work
+ again.
+
+* Automatically create directories specified in command line options
+ as containers for Poser-generated files (such as Gremlin and logging
+ output) if they don't already exist.
+
+* Allow multiple file selection in the Install Application/Database
+ dialog. [Michael Nordstrom]
+
+* The directory created by Gremlins to hold the files it also creates
+ is now named with the current date/time instead of the number of
+ milliseconds since the host system was booted.
+
+* Bound Posers not longer care if the Skins directory exists. [Kelly
+ Maher]
+
+* Fixed bug in NetLibGetHostByName when NetLib Redirection is turned
+ on: attempting to return netDNSMaxAddresses addresses would result
+ in memory after "addressList" to get NULLed (that is, the first
+ element of the "address" array). The solution is to do the same
+ this as NetLib, which is to only return netDNSMaxAddresses-1
+ address pointers. Note that Poser still differs from the on-device
+ NetLib, in that it will return only first netDNSMaxAddresses-1
+ addresses in addition to the pointers to them, while the on-device
+ NetLib will return netDNSMaxAddresses addresses (with no pointer
+ to the last one).
+
+* Fixed bug with restarting a Gremlin from an intermediate Gremlin
+ state file (Gremlin_XXX_Event_XXXXXXXX.psf). Poser would silently
+ reset when the newly started Gremlin would attempt to generate an
+ event to switch to another application. [Rick Wagner]
+
+* Fixed bug where running a Gremlin Horde would not switch to the
+ next Gremlin when an error occurred.
+
+* Emulate DragonballVZ requirement for having the entire LCD frame
+ buffer in a 128K segment. [Scott Johnson]
+
+
+Changes for 3.3 (2001-08-27)
+----------------------------
+* Interim internal release dates:
+ 3.3a1 - 2001-06-15
+ 3.3a2 - 2001-06-18
+ 3.3a3 - 2001-07-10
+ 3.3a4 - 2001-07-12
+ 3.3a5 - 2001-07-13
+ 3.3a6 - 2001-07-27
+ 3.3b1 - 2001-08-02
+ 3.3b2 - 2001-08-07
+ 3.3b3 - 2001-08-13
+ 3.3b4 - 2001-08-14
+ 3.3b5 - 2001-08-20
+ 3.3b6 - 2001-08-22
+
+* Added Visor Edge support. [James Phillips]
+
+* Added HandEra 330 support. [Dan Fahrion]
+
+* Better checking for invalid database names as .prc, .pdb, and .pqa
+ files are installed. Error message now also includes more text
+ describing why the name is invalid.
+
+* When reporting invalid database dates when installing a file, now
+ include the name of the file containing the database. [David A.
+ Desrosiers]
+
+* Better error message when reporting that a .prc, .pdb, and .pqa
+ file cannot be installed because one of its resources or records is
+ too large.
+
+* Removed feature of Gremlins which would turn the device off and on
+ every once and a while. The mechanism used to perform this could
+ alter the emulated hardware timers and clocks, such that two runs of
+ the same Gremlin number would result in different outcomes.
+
+* NOTE: the following new feature was added to this release and then
+ disabled. "Beaming" over TCP or serial worked only intermittently.
+ We'll try to get this working in a future release. Until then, Mac
+ and Windows users will see a disabled IR option in the Preferences
+ dialog. Original release note was as follows: Limited IR emulation.
+ The user can choose to redirect IR data out the serial port or to
+ another instance of Poser running on the same computer. Note that
+ although TCP is used to exchange data between the to instances of
+ Poser, exchanging data between Posers running on different computers
+ is not supported. The network latency and transmission times is
+ greater than the timeout values used in IR communications, leading
+ to broken connections.
+
+* Include preliminary plug-in support. Current support extends to
+ letting external plug-ins patch traps and access memory. [Anthony
+ Fishbeck]
+
+* Internal change: continuing work to remove Dragonball-specific
+ assumptions from the source code in preparation for adding ARM
+ support.
+
+* Added support for downloading ROMs over USB on Mac and Windows.
+
+ On Windows, you must have Palm Desktop 4.0.1 installed in order to
+ get the USB driver. You must then make the library for the driver
+ ("USBPort.dll") available to Poser. Either copy this library from
+ Palm Desktop's directory to Poser's directory, or move it into the
+ Windows system directory (thus making it available to all
+ applications).
+
+ On the Mac, you must have Palm Desktop 2.6.3 installed in order to
+ get the USB driver.
+
+ Note that the ROM Transfer application fails to work on Handspring
+ devices, so unless someone figures out why, you can't download those
+ ROMs. And though you can download Sony CLIE ROMs, Palm's version of
+ Poser doesn't emulate those devices, so performing that exercise is
+ not very useful. Which means that the addition of this feature is
+ of most benefit to those with Palm m500s and m505s.
+
+* Support backlighting (two levels of brightness) for m505.
+
+* Report direct access to BitmapType data structures.
+
+* Report calls to functions that will no longer be available on
+ future versions of Palm OS. This list appears at the end of this
+ note.
+
+* Corrected minimum RAM sizes for Palm m500 and m505 (was 2MB, now
+ 8MB).
+
+* (Mac) Added better support for transliterating characters exchanged
+ between the host and Palm OS emulated clipboard.
+
+* (Windows) The popup menu would always appear on the primary monitor
+ on a multi-monitor system. [David Vaportrails]
+
+* Palm m500/m505 alarm LED is green, not red.
+
+* (Unix) GCC 3.0 support: added <ctype.h> where needed; no longer
+ assume vector<T>::iterator is a pointer type; add exception
+ specifications where needed; recognize that "map" is in the std
+ namespace. [John Marshall]
+
+* (Windows) Added "Stay On Top" checkbox to Skins dialog. [Jonathan
+ Cox]
+
+* (Unix) Re-established X Windows window class (missing from Poser
+ 3.2). [Chris Ridd]
+
+* (Unix) Link with OpenGL if it is installed (required by FLTK).
+ [Holger Klawitter]
+
+* (Unix) SuSE 7.1 is rather pedantic and refuses to compile source
+ code containing calls to tmpnam in it. Therefore, on Unix, if
+ mkstemp is available, use that instead. Note that this mean that if
+ you call HostTmpNam to get a temp file name, be warned that the file
+ will already exist (but will still need to be opened). [Holger
+ Klawitter]
+
+* In Poser's implementations of NetLibSend, NetLibSendPB,
+ NetLibReceive, NetLibReceivePB, and NetLibDmReceive (used when
+ NetLib redirection is turned on), no longer try to be clever about
+ when to call send vs. sendto or recv vs recvfrom. Instead, always
+ call sendto and recvfrom. That should provide the same
+ characteristics as the Palm OS NetLib calls. [Gary Gorsline]
+
+* In order to support the various options in the Reset dialog, Poser
+ emulates the pressing of the appropriate hard keys. Pressing the
+ key down worked fine, but Poser's determination of when to release
+ the key wasn't always correct, and the Palm OS would sometimes fail
+ to notice that the key was ever down. Poser now tries a different
+ approach that should be more definitive. [Mike McCollister]
+
+* Fixed profiling bug. The memory cycles incurred fetching the
+ opcodes were not being counted.
+
+* Fixed profiling bug. Poser performs a lot of processing when
+ system functions are called. Some of this processing would access
+ emulated memory, causing the cycles to do so to be counted against
+ the running application. This was incorrect. Poser's operations
+ should as transparent as possible and not show up on profiling data.
+
+* Added two HostControl functions:
+
+ HostErr HostDbgSetDataBreak (UInt32 addr, UInt32 size)
+
+ Configure Poser to enter an external debugger or display a
+ message if the bytes starting at the given address and
+ continuing for the given number of bytes are accessed in any
+ way (either written two or read from). The functionality
+ here is the same that is provided in the Data Breakpoint
+ section of the Breakpoints dialog.
+
+ HostErr HostDbgClearDataBreak (void)
+
+ Configure Poser to no longer enter an external debugger or
+ display a message when the memory range specified in
+ HostDbgDataBreak is accessed.
+
+* Added Gremlin Horde logging information: ROM version, ROM file
+ name, RAM size, device name; statistics regarding the number of
+ events each Gremlin was run for before generating an error; and
+ error frequency and type statistics.
+
+* Rearranged New Horde dialog, and added Select All / Deselect
+ capability for the Applications list, and a menu from which the
+ application to be launched first can be selected.
+
+* Changed behavior of application switching -- SysUIAppSwitch is
+ called on a random application from the list of applications
+ selected in the New Horde dialog, rather than having a random button
+ pressed.
+
+* Resuming a Horde run from a .psf file now terminates correctly, at
+ the maximum depth originally specified, rather than at the next
+ switching boundary, as before.
+
+* International Strict Checks (for checking multi-byte character
+ display routines) is now a debugging option.
+
+* Stepping a halted Gremlin now behaves identically when running a
+ single Gremlin or a Horde.
+
+* Files generated during Profiling now have unique names.
+
+* New warning displayed if comm port could not be opened on the host.
+
+* Added -pref command line option (-preference or -d can by used as
+ synonyms). This option changes preferences as stored in the
+ preference file. Its parameter has the form "key=value", and is
+ treated the same way as the "key=value" lines found in the
+ preference file.
+
+* Enabled the long-stillborn Logging Options for Warnings and Errors.
+ Checking these options will log the text of message dialogs just
+ before they are displayed. You can then use this text in bug
+ reports (or you can just use Ctrl-C or your platform's equivalent to
+ copy the text from the dialog to the clipboard, as mentioned in a
+ previous release note).
+
+* Added "ContinueOnWarnings" and "ExitOnErrors" preferences (along
+ with UI for them in the Debug Options dialog). If logging for
+ warnings is enabled and ContinueOnWarnings is true, warning dialogs
+ will be dismissed as if the user had pressed the Continue button. If
+ logging for errors is enabled and ExitOnErrors is true, fatal error
+ dialogs result in Poser exiting.
+
+* Added "SilentRunning" preference. Setting this value to non-zero
+ has the same effect as enabling the following separately controlled
+ preferences: LogErrorMessages, LogWarningMessages,
+ ContinueOnWarnings, and ExitOnErrors.
+
+ Since it is not a good idea to set this option and forget it, Poser
+ resets this preference to zero every time it starts up. It resets
+ the value *before* parsing the command line options, so using the
+ -pref option to set it will work.
+
+* Added "DialogBeep" preference (along with UI for it in the Debug
+ Options dialog). Setting this value to non-zero causes Poser to
+ beep every 2 seconds that a message dialog is displayed. So as to
+ not annoy your co-workers if you're not around to hear it, Poser
+ will stop the beeping after 1 minute.
+
+* (Windows) If ExitOnErrors or SilentRunning is turned on, Poser
+ exits with a status code of 2 if a fatal error had occurred at any
+ time during execution, a status code of 1 if a warning had occurred
+ any time during execution, and a status code of 0 if no errors or
+ warnings occurred.
+
+* Changed the behavior of error handling when running a single
+ Gremlin vs. running a Horde. Originally, when there was only the
+ ability to run a single Gremlin, Poser would display all warnings
+ and errors as they occurred. Later, when Hordes was added, it was
+ felt that running multiple Gremlins was more of a "batch" operation,
+ and so the user should not be bothered with error messages. Instead,
+ if a Gremlin range was specified in the New Horde dialog, warnings
+ and errors were logged to a file, the Gremlin resulting in the
+ message was terminated, and Poser would switch to the next Gremlin.
+ But if the user specified to run only a single Gremlin in the New
+ Horde dialog, they'd get the original behavior of seeing error
+ dialogs as they occurred. Now, that behavior has been made
+ consistent with the original behavior: by default, the user will see
+ warnings and errors in dialogs as they occur. If this is not
+ desired, they can use the "ContinueOnWarnings" and "ExitOnErrors"
+ preferences to log the messages instead.
+
+* Gremlins used to implicitly log error and warning messages. Now
+ that there is a UI for specifying whether or not to log messages,
+ Gremlins no long automatically does that. To support the change,
+ Poser 3.3 will automatically turns on error and warning message
+ logging for Gremlins the first time you run it.
+
+* (Mac, Windows) When loading or saving preferences, Poser now first
+ looks for a preferences file in the same directory as itself. If it
+ finds that, it uses that as the preferences file. Otherwise, it
+ uses the old behavior of using the system's designated location for
+ preference files.
+
+* Profiling fix: when converting cycle counts into time, make use of
+ the actual CPU speed instead of assuming 16MHz.
+
+* (Windows) Fixed problem where a user could click on the Logging
+ Options of the New Gremlin dialog multiple times, bringing up
+ multiple Logging dialog boxes.
+
+* Indicate the active/inactive state of the Emulator's window by
+ lightening it if it's inactive.
+
+* (Mac) Fixed many problems with calling HostGetFile, HostPutFile,
+ etc. Calling these functions would crash, and even if they worked,
+ they wouldn't display any files, just folders. [Hal Mueller]
+
+* Check for screen access in the storage heap. The screen is not
+ normally stored in the storage heap, but the hardware supports it
+ and SuperWaba 2.0b3 puts it there. [Guilherme C. Hazan]
+
+* Fixed memory leak that could occur if an application running under
+ Gremlins attempted to call SysUIAppSwitch in order to launch another
+ application, that application took a command parameter block, and
+ that application was not on the list of applications that could be
+ run under Gremlins. The command parameter block was leaked.
+
+* Added two new UI-less preferences: LogFileSize and LogDefaultDir.
+ The former specifies the number of bytes that can be written to the
+ log file before old bytes are discarded. HostSetLogFileSize is
+ still supported, but calling HostSetPreference will now do the same
+ thing. LogDefaultDir specifies where you want log files stored. If
+ a Gremlin is running, log files will be stored in the Gremlin output
+ file, as before. But you can use LogDefaultDir to specify a
+ directory for log files generated while not running Gremlins. If
+ this preference is not specified, log files are written to the
+ Emulator directory, as before. The existence of this preference and
+ the -pref command-line option makes the old never-implemented
+ -log_save_dir command-line option obsolete.
+
+========================================================================
+
+The following is a list of Palm OS traps that are not supported on future
+OSes. The list is broken into a number of different groups (which more or
+less explains why the trap was not implemented).
+
+Documented 'System Use Only' Traps
+----------------------------------
+AlmAlarmCallback
+AlmCancelAll
+AlmDisplayAlarm
+AlmEnableNotification
+AlmInit
+AlmTimeChange
+DmInit
+EvtDequeueKeyEvent
+EvtGetSysEvent
+EvtInitialize
+EvtSetKeyQueuePtr
+EvtSetPenQueuePtr
+EvtSysInit
+ExgInit
+FrmAddSpaceForObject
+FtrInit
+GrfFree
+GrfInit
+InsPtCheckBlink
+InsPtInitialize
+MemCardFormat
+MemHandleFlags
+MemHandleOwner
+MemHandleResetLock
+MemHeapFreeByOwnerID
+MemHeapInit
+MemInit
+MemInitHeapTable
+MemKernelInit
+MemPtrFlags
+MemPtrOwner
+MemPtrResetLock
+MemStoreInit
+MemStoreSetInfo
+PenClose
+PenGetRawPen
+PenOpen
+PenRawToScreen
+PenScreenToRaw
+ScrCompressScanLine
+ScrCopyRectangle
+ScrDeCompressScanLine
+ScrDrawChars
+ScrDrawNotify
+ScrLineRoutine
+ScrRectangleRoutine
+ScrScreenInfo
+ScrSendUpdateArea
+SlkProcessRPC
+SlkSysPktDefaultResponse
+SndInit
+SysBatteryDialog
+SysColdBoot
+SysDoze
+SysInit
+SysLaunchConsole
+SysNewOwnerID
+SysReserved10Trap1
+SysReserved31Trap1
+SysSemaphoreSet
+SysUILaunch
+SysWantEvent
+TimInit
+UIInitialize
+UIReset
+WinAddWindow
+WinRemoveWindow
+
+Undocumented 'System Use Only' or 'HAL Use Only' Traps
+------------------------------------------------------
+These traps are routines in the HAL, documented in headers to be called by
+Palm OS only, or I have spoken with the authors of those traps who
+identified them as internal traps.
+
+AttnAllowClose
+AttnDoEmergencySpecialEffects
+AttnEffectOfEvent
+AttnEnableNotification
+AttnHandleEvent
+AttnIndicatorAllow
+AttnIndicatorAllowed
+AttnIndicatorCheckBlink
+AttnIndicatorGetBlinkPattern
+AttnIndicatorSetBlinkPattern
+AttnIndicatorTicksTillNextBlink
+AttnInitialize
+BltCopyRectangle
+BltDrawChars
+BltFindIndexes
+BltGetPixel
+BltLineRoutine
+BltPaintPixel
+BltPaintPixels
+BltRectangleRoutine
+BltRoundedRectangle
+BltRoundedRectangleFill
+DayHandleEvent
+DbgControl
+DbgSerDrvClose
+DbgSerDrvControl
+DbgSerDrvOpen
+DbgSerDrvReadChar
+DbgSerDrvStatus
+DbgSerDrvWriteChar
+FlashInit
+FntPrvGetFontList
+HwrBacklightV33
+HwrBattery
+HwrBatteryLevel
+HwrCalcDynamicHeapSize
+HwrCursorV33
+HwrCustom
+HwrDebuggerEnter
+HwrDebuggerExit
+HwrDebugSelect
+HwrDisplayDoze
+HwrDisplayDrawBootScreen
+HwrDisplayInit
+HwrDisplayPalette
+HwrDisplaySleep
+HwrDisplayWake
+HwrDockSignals
+HwrDockStatus
+HwrDoze
+HwrFlashWrite
+HwrGetRAMMapping
+HwrGetSilkscreenID
+HwrIdentifyFeatures
+HwrInterruptsInit
+HwrIRQ1Handler
+HwrIRQ2Handler
+HwrIRQ3Handler
+HwrIRQ4Handler
+HwrIRQ5Handler
+HwrIRQ6Handler
+HwrLCDBaseAddrV33
+HwrLCDContrastV33
+HwrLCDGetDepthV33
+HwrModelInitStage2
+HwrModelInitStage3
+HwrModelSpecificInit
+HwrNVPrefGet
+HwrNVPrefSet
+HwrPluggedIn
+HwrPostDebugInit
+HwrPreDebugInit
+HwrResetNMI
+HwrResetPWM
+HwrSetCPUDutyCycle
+HwrSetSystemClock
+HwrSleep
+HwrSoundOff
+HwrSoundOn
+HwrTimerInit
+HwrWake
+KeyBootKeys
+KeyHandleInterrupt
+KeyInit
+MemHeapPtr
+MemStoreSearch
+OEMDispatch2
+PalmPrivate3
+ScrCompress
+ScrDecompress
+ScrGetColortable
+ScrGetGrayPat
+ScrPalette
+ScrScreenInit
+ScrScreenLock
+ScrScreenUnlock
+ScrUpdateScreenBitmap
+SndInterruptSmfIrregardless
+SndPlaySmfIrregardless
+SndPlaySmfResourceIrregardless
+SysFatalAlertInit
+SysKernelClockTick
+SysNotifyBroadcastFromInterrupt
+SysNotifyInit
+SysReserved30Trap1
+SysReserved30Trap2
+SysUnimplemented
+TimGetAlarm
+TimSetAlarm
+UIColorInit
+WinGetFirstWindow
+WinMoveWindowAddr
+WinPrvInitCanvas
+WinScreenInit
+
+Kernel Traps
+------------
+These traps are not implemented because 68K applications do not have access
+to the kernel APIs.
+
+SysEvGroupCreate
+SysEvGroupRead
+SysEvGroupSignal
+SysEvGroupWait
+SysKernelInfo
+SysMailboxCreate
+SysMailboxDelete
+SysMailboxFlush
+SysMailboxSend
+SysMailboxWait
+SysResSemaphoreCreate
+SysResSemaphoreDelete
+SysResSemaphoreRelease
+SysResSemaphoreReserve
+SysSemaphoreCreate
+SysSemaphoreDelete
+SysSemaphoreSignal
+SysSemaphoreWait
+SysTaskCreate
+SysTaskDelete
+SysTaskID
+SysTaskResume
+SysTaskSetTermProc
+SysTaskSuspend
+SysTaskSwitching
+SysTaskTrigger
+SysTaskUserInfoPtr
+SysTaskWait
+SysTaskWaitClr
+SysTaskWake
+SysTimerCreate
+SysTimerDelete
+SysTimerRead
+SysTimerWrite
+SysTranslateKernelErr
+
+Obsolete Traps
+--------------
+These traps are not implemented because they are obsolete Palm OS 1.0 traps
+(or an esoteric obsolete trap such as WiCmdV32).
+
+FplAdd
+FplAToF
+FplBase10Info
+FplDiv
+FplFloatToLong
+FplFloatToULong
+FplFToA
+FplLongToFloat
+FplMul
+FplSub
+WiCmdV32
+
+Ghost Traps
+-----------
+These traps were never implemented in Palm OS (although they appear in
+CoreTraps.h), but they are listed for completeness.
+
+ClipboardCheckIfItemExist
+CtlValidatePointer
+FrmSetCategoryTrigger
+FrmSetLabel
+MenuEraseMenu
+SysUICleanup
+WinDrawArc
+WinDrawPolygon
+WinEraseArc
+WinErasePolygon
+WinFillArc
+WinFillPolygon
+WinInvertArc
+WinInvertPolygon
+WinPaintArc
+WinPaintPolygon
+
+Unimplemented NOP Traps
+-----------------------
+These traps should not be called by applications. Some third-party
+applications call these traps and it is safer to treat them as NOPs for
+backwards compatibility.
+
+FplFree
+FplInit
+HwrTimerSleep
+HwrTimerWake
+PenSleep
+PenWake
+SerReceiveISP
+SrmSleep
+SrmWake
+SysDisableInts
+SysRestoreStatus
+TimHandleInterrupt
+TimSleep
+TimWake
+WinDisableWindow
+WinEnableWindow
+WinInitializeWindow
+
+Unimplemented Rare Traps
+------------------------
+These traps all seem like traps that are only used internally by Palm OS or
+by serial drivers or by OEM extensions, etc. In other words, these are
+traps that an application would not use.
+
+ConGetS
+ConPutS
+DayDrawDays
+DayDrawDaySelector
+DbgCommSettings
+DbgGetMessage
+DlkControl
+DlkDispatchRequest
+DlkStartServer
+DmMoveOpenDBContext
+DmOpenDBWithLocale
+FlashCompress
+FlashErase
+FlashProgram
+IntlGetRoutineAddress
+MemGetRomNVParams
+MemNVParams
+OEMDispatch
+ResLoadForm
+SerPrimeWakeupHandler
+SerReceiveWindowClose
+SerReceiveWindowOpen
+SerSetWakeupHandler
+SlkSetSocketListener
+SrmOpenBackground
+SrmPrimeWakeupHandler
+SrmReceiveWindowClose
+SrmReceiveWindowOpen
+SrmSetWakeupHandler
+SysNotifyBroadcast
+SysNotifyBroadcastDeferred
+SysNotifyDatabaseAdded
+SysNotifyDatabaseRemoved
+SysSetTrapAddress
+
+
+Changes for 3.2 (2001-06-03)
+----------------------------
+* Interim internal release dates:
+ 3.2a1 - 2001-03-30
+ 3.2b1 - 2001-05-06
+ 3.2b2 - 2001-05-14
+ 3.2b3 - 2001-05-29
+
+* (Unix) Support psf, ram, rom, device, load_apps, and run_app
+ command line options. [David A. Jablonski]
+
+* Rewrote LCD-handling code to share a lot of cross-platform code.
+ The major user visible effect of this is that the Unix version now
+ has the white 2-pixel border around it when emulating a device with
+ an SED 1375 or 1376 display, and that the updating on Unix will be
+ faster (especially over a network).
+
+* Rewrote a lot of the EmDevice routines in order to be more table-
+ driven. Also added ability to configure the CPU object created, and
+ the minimum RAM size that can be configured.
+
+* Added Visor Edge support. [James Phillips]
+
+* Rewrote the menu-handling code to share a lot of cross-platform
+ code. Along the way, cleaned up some host-specific aspects of menu
+ handling. Over all:
+
+ * Mac
+
+ o Now has a popup menu that looks like the Windows version
+ (use Ctrl-click to display it).
+
+ * Unix
+
+ o The popup menu on Unix now is laid out the same way as the
+ Windows version. This includes finally having the MRU menus
+ for recent sessions and installable files.
+
+ o Can press Shift-F10 to display the popup menu.
+
+ * Windows
+
+ o Menu items now have Alt shortcut keys. I would have used
+ the more-standard Ctrl, but that's currently used for
+ entering commands into the emulated environment. I would
+ have used the less-standard Ctrl+Shift, but felt that
+ requiring three fingers for a shortcut command was
+ excessive.
+
+ o The menu is popped-up in response to a WM_CONTEXTMENU
+ message now instead of manually looking for F10 presses and
+ right button clicks. This means that (a) the menu is popped
+ up at the *end* of a right-button click instead of the
+ beginning, (b) you need to use Shift-F10 instead of just F10
+ to popup the menu item, and (c) you can also use the "menu"
+ key on some PC keyboards (the "VK_APPS" key).
+
+ * All
+
+ o Paves the way for dynamically updating menus for different
+ circumstances (for instance, if emulating a particular
+ device requires a menu special for it, that can be added).
+
+ o Hmmm...HostAddMenuCommand, anyone? :-)
+
+* Sped up the checking for direct access to UI Mgr data structures.
+ The overhead for this option should now be imperceptible.
+
+* Allow read/write access to font fields in ControlType, ListType,
+ and FormLabelType. [Many]
+
+* Allow read access to FormType::menuRscId field. [Markus Schmid]
+
+* Allow complete access to gadgets (since gadget callback functions
+ are given just a pointer to the gadget, but not the Form through
+ which they could make access calls). [Ben Combee]
+
+* Allow read/write access to "attr" for FormBitmapType before Palm OS
+ 3.2 -- FrmHideObject didn't change the usable bit before then.
+ [Steve Achelis]
+
+* Fix access to WindowType::frame field. This was allowed, but a bug
+ in the calculation of the field's offset invalidated the access.
+ [Stephen Best]
+
+* For Poser 3.1, access to WindowType fields displayWidthV20,
+ displayHeightV20, displayAddrV20, and bitmapP was documented as
+ "read only". This is now enforced; write access is no longer
+ allowed.
+
+* For Poser 3.1, access to the FieldType field attr was documented as
+ "read/write" before Palm OS 3.3. This is now enforced.
+
+* Allow access to WindowType fields even when the WindowType is part
+ of a FormType. It used to be that you could not access those fields
+ if the windowFlags.dialog bit was set.
+
+* Fixed bug where Poser itself would cause an access violation to
+ parts of a FormType when preparing the error message for a user
+ access violation to the FormType.
+
+* Poser used to read and cache the size of the system function
+ dispatch table. However, some versions of Palm OS now resize the
+ table, thus invalidating Poser's cached size value. The result is
+ that Poser would sometimes report that system functions are not
+ implemented when they really are. [Mike McCollister]
+
+* Squelch display of message saying that someone called DbgMessage
+ ("c") and DbgMessage ("Transaction finished"). [Catherine White,
+ Andreas Linke, Mark Peters]
+
+* (Mac) Carbonized. [Scott Gruby]
+
+* Be more robust in HostControl calls that take printf-style var-args
+ parameters.
+
+* Fix potential bug in code that tries to find the beginning of a
+ function given an address in that function. [Adam Liss]
+
+* Support Soft, Hard, Debug, and No Extension resets. The Reset menu
+ item now brings up a dialog allowing you to set various
+ reset-related options. The "Reset" button in the "Continue / Debug
+ / Reset" dialog is now "Reset...", and brings up the same dialog. By
+ default, the settings are set to a Soft Reset with Extensions.
+
+* Fixed problem where device could get into a "flashing" state while
+ running Gremlins, where the device is continually turning on and
+ off. [Stephen Best]
+
+* Added 4 more slots in Card Options dialog.
+
+* If the user brings up the Card Options dialog, Poser checks for the
+ existance of the HostFS shared library when exitting the dialog. If
+ the library is not installed, Poser displays a message dialog
+ suggesting that the user download and install it.
+
+* Make sure the user can't accidentally attempt to install a HotSync
+ User Name from the preferences dialog that's too long. [Steve
+ Achelis]
+
+* (Unix) Extended "Choose File" dialog to support the choosing of
+ directories. This "Choose Directory" dialog is used when clicking
+ on the "Browse" button in the "Card Options" dialog. Navigate via
+ the file/directory name list, or type the path into the edit box.
+ You can use TAB for name completion, '/' to indicate that you want
+ to enter the directory currently entered in the edit box, and RETURN
+ (or click on the OK button) to select the directory in the edit box.
+
+* (Unix) Implemented clipboard support. This support has uses in two
+ areas: copying the text from error message boxes (see the next
+ item), and clipboard interchange. Clipboard interchange is where
+ the Palm OS clipboard is kept in sync with the host clipboard. On
+ Unix, this is tricky because of the paradigm Unix uses for the
+ clipboard. But, in short, to copy from the Palm OS to a Unix
+ application, select the text in the Palm OS application, select the
+ Copy menu item in the Palm OS application, go to the Unix
+ application, and middle-click to paste the selection. To copy from
+ a Unix application to a Palm OS application, select the text in the
+ Unix application, go to the Palm OS application, set the insertion
+ point, and select the Paste menu item.
+
+* (Unix) The error dialog that reports runtime errors in Palm OS
+ applications (e.g., "Bus error", "Low-memory accessed", etc.) now
+ displays the text in a selectable pane. That is, the user can
+ select the text with the mouse. Once this is done, it acts like a
+ selection in any other Unix program, and can be pasted by
+ middle-clicking in the target Unix application.
+
+* (Unix) All dialogs are now centered on the main screen.
+
+* Show applications in the "New Gremlin" dialog even if they have the
+ dmHdrAttrHidden bit set. [Scott Johnson]
+
+* Fixed problem with profiling where any system function that Poser
+ completely implemented (including all HostControl functions) would
+ cause the profiling system to push a record onto an internal stack
+ but not pop it off later, leading to an internal stack overflow.
+
+* Using a debugger to single-step over a line of source code that
+ performed a "soft" invalid memory access (that is, one that is
+ proscribed by convention, and not, say, one that causes an address
+ error) would queue up the error and not show it until regular
+ execution was resumed. [Adam Dingle]
+
+* Support -horde_save_dir. This option has been around for a couple
+ of years, but never did anything. It now works as documented. Use
+ it to specify the location for "GremlinStates_*" directories. This
+ parent directory must already exist. If the directory does not
+ exist or is not specified, the "GremlinStates_*" directories will be
+ created in the Emulator directory as before.
+
+* When resetting a session or creating a new one, reset the Gremlin
+ state so that the Suspend and Resume menu items are no longer
+ enabled.
+
+
+Changes for 3.1 (2001-03-16)
+----------------------------
+* Interim internal release dates:
+ 3.0a9e1 - 2001-01-07
+ 3.0a9e2 - 2001-01-09
+ 3.0a9e3 - 2001-01-17
+ 3.0a9e4 - 2001-01-23
+ 3.0a9e5 - 2001-01-24
+ 3.0a9e6 - 2001-02-07
+ 3.0a9e7 - 2001-02-19
+ 3.1b1 - 2001-02-22
+ 3.1b2 - 2001-02-27
+ 3.1b3 - 2001-02-28
+ 3.1b4 - 2001-03-02
+ 3.1b5 - 2001-03-08
+ 3.1b6 - 2001-03-08
+ 3.1b7 - 2001-03-14
+ 3.1b8 - 2001-03-15
+
+* Changed Skin file searching rules. Now, when starting up, Poser
+ looks for a directory called "Skins". On Mac and Windows, it looks
+ for this directory in the same directory as Poser itself. On Unix,
+ it looks in $POSER_DIR, $HOME, /usr/local/share/pose, and
+ /usr/share/pose, stopping at the first one that has a directory
+ named "Skins" or "skins". Once a Skins directory has been found,
+ that directory is recursively searched for *.skin files.
+
+ Because the rule change may confuse users, Poser displays a warning
+ message on startup if it can't find a "Skins" directory. This
+ warning is displayed only once, so as to not disturb developers
+ who don't care a whole lot about skins.
+
+* If the Skins directory could not be found, display an error message
+ at startup. This will tell users that they either need to rename
+ their skins directory to "Skins", or to download the skins archive
+ from the Poser Web page.
+
+* Allow the setting of breakpoints in the prologue code of Palm OS
+ Manager's that are sub-dispatched. That is, the managers that take a
+ selector number and then use a secondary dispatch table to further
+ dispatch to the final function. Poser would originally skip over
+ this prologue code and jump directly to the final function
+ destination. However, one could not set breakpoints on the prologue
+ code and have them trigger in that case. Now if any breakpoint is
+ installed, Poser jumps to the prologue code. Otherwise, it jumps to
+ the final function address like it used to. This modification allows
+ people to use the 's' command in PalmDebugger to Step into Palm OS
+ functions that are sub-dispatched.
+
+* (Mac) Updated to CodeWarrior Pro 6.
+
+* (Mac) Updated to GUSI 2.13 (needed under CWP6).
+
+* (Mac) Worked around problem in PowerPlant 2.1 that caused the
+ highlighting to not always work in text lists in dialogs like the
+ New Gremlin dialog.
+
+* Recalibrated the Palm OS tick-counter to my 500MHz PC. The tick
+ counter now runs 3 times slower than before, resulting in 97 ticks
+ per second as opposed to the 297 ticks per second I was seeing
+ before. The upshot of all this is that repeating tasks (like
+ scrolling and holding down the hard buttons) don't zoom by as
+ quickly as before.
+
+* Cleaned up the handling of Poser-detected errors and their
+ messages. Before now, if you got an error message for a "soft" error
+ (that is, one that is not a hardware exception), Poser would display
+ a dialog box containing Continue, Debug, and Reset buttons. If you
+ clicked on Debug and there were no debugger, it would be the same as
+ clicking on Continue. Now, Poser will merely redisplay the same
+ dialog until you click on a different button or a debugger can be
+ found.
+
+* Switched to native "long long" operations in Profiling.cpp (this
+ issue was finally forced because someone forgot S64Compare in CWP6).
+
+* Adjusted the calculated heights for cells in LTextColumnView in
+ order to account for the 2 pixel inset LTextColumnView::DrawCell
+ uses. Ken noticed that descenders were getting chopped off.
+
+* Fixed problem in Hordes where specifying a switch depth but not
+ specifying a maximum depth (that is, not checking the third check
+ box in the dialog) would cause the Hordes mechanism to not actually
+ switch between different Gremlin numbers.
+
+* Implemented support for the timeout values passed to NetLibReceive
+ and NetLibSend. Previously, these values were ignored, leading to
+ hangs or overly-long timeouts on the desktop that wouldn't appear on
+ the device. [Hiroyuki Okamoto]
+
+* Fixed problems where entering a debugger could cause Poser to
+ complain that the PC is being set to an invalid value (mostly seen
+ when executing "att" in PalmDebugger). Fixing this problem also had
+ the benefit of speeding up emulation by 6%.
+
+* Would you believe that changing the following in the core emulation
+ loop from:
+
+ uint16 opcode;
+ opcode = get_iword (0);
+ fCycleCount += (cpufunctbl[opcode]) (opcode);
+
+ to:
+
+ uint32 opcode;
+ opcode = get_iword (0);
+ fCycleCount += (cpufunctbl[opcode]) (opcode);
+
+ sped up emulation by 4%?
+
+* Poser was relying on a lot of UAE types and routines for basic
+ facilities. For instance, Poser had standardized on uae_u8, uae_u16,
+ etc., for basic integral types, and get_byte, get_word, put_byte,
+ etc., for basic memory emulation. However, all of those are
+ UAE-specific. When implementing ARM support, those facilities may
+ not be available. Therefore, move those basic types and facilities
+ into Poser, give them Poser-ish names, and recast UAE to use those
+ genericized facilities.
+
+* When the SED1376 LCD is turned off, emulate the fact that the bus
+ to it is disabled. While disabled, any access to the SED registers
+ or VRAM will cause a bus error.
+
+* Add support for the interrupts caused by the additional sources on
+ the DragonBall VZ (UART2, TMR2, PWM2, etc.), and support the
+ configurable interrupt levels for those sources.
+
+* Keep the Palm OS clipbard in sync with the host platform's
+ clipboard. After a Palm OS application calls ClipboardAddItem or
+ ClipboardAppendItem, the Palm OS clipboard is copied to the host
+ clipboard. Before calls to ClipboardGetItem, the host clipboard is
+ copied to the Palm OS clipboard. Note that this synchronization is
+ not performed if a Gremlin is running so that any data on the host
+ clipboard doesn't alter the Gremlin outcome.
+
+ With this change, it should be fairly painless to exchange data
+ between the emulated Palm device and the host computer. To copy data
+ into the emulated device:
+
+ * Copy the text data with Ctrl-C (or as appropriate on Mac or Unix)
+ * Switch to the emulated device
+ * Make sure you have a field active that can accept text data
+ * Press Ctrl-C, then P. Ctrl-C enters the "/" stroke to invoke
+ the "Command" mode, and "P" invokes the Paste command.
+
+ To copy data from the emulated device to the host:
+
+ * Select the text on the emulated device
+ * Press Ctrl-C, then C to copy the data.
+ * Switch to the host computer application to receive the text
+ * Press Ctrl-V (or as appropriate on Mac or Unix).
+
+ Note that data copied to the Palm's clipboard is silently truncated
+ to cbdMaxTextLength characters if necessary.
+
+* Fixed problem where some stack overflows weren't being detected. On
+ a LINK instruction, when the stack pointer is decremented to hold
+ the old A6 value, we check the stack. However, when the stack is
+ decremented again by the value specified by the LINK statement, that
+ wasn't being checked.
+
+* Completely rewrote the error messages generated when an emulated
+ application causes (either directly or indirectly) an error. This
+ includes both hardware exceptions (bus error, address error, divide
+ by zero, etc.) and emulator-detected errors (write to low-memory,
+ write to screen buffer, stack overflow, etc.). The new messages are
+ intended to be more useful (more detailed information) and clearer
+ (more explanatory text).
+
+* Added new error message to explain cases where it looks like an
+ invalid DrawWindow is being used. On Debug 3.5 ROMs, when there is
+ no valid DrawWindow, the Palm OS sets the value of the stored
+ DrawWindow to 0x80000000. This value causes a bus error. Poser
+ detects this kind of bus error and puts up a message saying what it
+ really thinks is going on.
+
+* Added new error message saying that the application is attempting
+ to write to the storage heap. Previously, the user would just see a
+ "bus error" message.
+
+* Previously when reporting a hardware exception, Poser would attempt
+ to contact a debugger before displaying an error message. Now Poser
+ displays an error message first. This mirrors the way other error
+ messages are handled. The exceptions to this rule are with Trace,
+ TRAP 0, and TRAP 8 exceptions. Those will still attempt to silently
+ enter the debugger first. If no debugger is connected, *then* an
+ error dialog is posted.
+
+* Poser used to report certain errors only once per application run.
+ The intention was to not pelt users constantly when running an
+ application that, say, draws directly to the screen. In an effort to
+ get more applications to be more compliant, this one-time-only
+ feature has been removed. If you need to turn off those error
+ messages, you can still use the Debug Options dialog.
+
+* After the previously-mentioned changed, an "it's always been there"
+ bug cropped up. After reporting a warning like "Application just
+ read from low-memory", the developer could click on the Debug button
+ and break into an external debugger. From the debugger, they could
+ examine the error, and then optionally continue the application's
+ execution. However, doing so would re-execute the instruction that
+ caused the error. We never saw this before because of Poser's
+ feature of reporting such errors only once per application run. But
+ with that feature removed, the application keeps breaking at the
+ same place. Even with the feature in place, there could be problems
+ if the instruction were some sort of pre/post-increment/decrement
+ instruction. The first time it was executed, the affected base
+ register would get modified. And it would get modified again the
+ second time it was executed, even if no error were reported. Anyway,
+ that's all fixed now. Now Poser waits for the instruction to
+ completely execute before reporting an error so that the PC is
+ properly incremented and the instruction doesn't get executed twice.
+ The only negative side effect of this change is that the PC will now
+ always point to the instruction *after* the one causing the error.
+ Most of the time, this will be confusing only if you're debugging at
+ the assembly level instead of the source level. However, if the
+ opcode executed was last opcode of a source-level statement, the
+ source line indicated by the debugger could be the one *after*
+ causing the error.
+
+* The last part of that last paragraph bears repeating: errors are
+ now flagged *after* the instruction causing it has finished, rather
+ than in the middle of the instruction. This means that the PC
+ reported to the debugger will be pointing to the *next* opcode. You
+ may need to mentally adjust for this difference in the debugger.
+ That is, you may need to look at the previous instruction or source
+ code line.
+
+* Poser keeps a list of Palm OS function names and error code names.
+ Updated this list for Palm OS 4.0.
+
+* Fixed some problems resuming a Gremlin from a saved file when no
+ upper event bound has been selected. [Catherine White,
+ Llamagraphics, Inc.]
+
+* (Windows) Work around the fact that connect may return WSAEINVAL or
+ WSAEWOULDBLOCK when it really means WSAEALREADY. [Mark Baysinger]
+
+* (Windows) Provide a default extension when asking to save a file.
+ [Mike McCollister]
+
+* (Windows) Fixed color problems when saving the LCD to a disk file
+ when it's in 16-bit mode. [Mike McCollister]
+
+* Added new command line option: -horde_quit_when_done. Specifying
+ this option on the command line will cause the emulator to exit
+ after completing a Horde.
+
+* Fixed problem with the Step Spy feature in PalmDebugger where
+ attempting to set a Step Spy address would cause Poser to raise an
+ invalid access error message.
+
+* Additional documentation: HostProfileInit takes two parameters:
+ maxCalls and maxDepth. These parameters determine the sizes of
+ arrays used to keep track of function calls and call depth. A
+ typical value for maxCalls is 65536, and for maxDepth is 200. In
+ future versions of Poser, the need for specifying these values may
+ be removed.
+
+* (Mac) Fixed application list in the New Horde dialog. There used to
+ be a feature whereby application names would be shown in Japanese if
+ running a Japanese ROM on a JLK-enabled Mac. Somewhere along the
+ way, this got broken. It should be fixed now.
+
+* (Mac) Messages strings used to be stored in a 'STRA' (string array)
+ resource. However, if an error occurred while handling a packet from
+ a debugger, Poser would be unable to access this resource when
+ forming an error message. This is because Poser would be operating
+ in the context of the debugger. Thus, the debugger's resources would
+ be available, but not Poser's. The result of this would be error
+ messages with the words "missing string #xxxx" in them. Now, the
+ strings are embedded in the application as string constants, the
+ same way as is done on Unix.
+
+* (Mac) Some messages would display missing character symbols (those
+ hollow boxes) instead of performing a linefeed/carriage return.
+ Fixed.
+
+* Corrected the spelling in some messages (ran the whole lot through
+ a spell checker, I did...).
+
+* Poser makes calls into ROM functions from time to time in order to
+ get information or perform some operation. Poser has known for a
+ long time to skip breakpoints in those functions when they're
+ executed in this fashion. Now Poser also skips DbgBreaks (TRAP 8s)
+ and Trap Breaks (from PalmDebugger's ATB command) as well.
+
+* (Mac) Translate high-ASCII characters when exchanging the Mac
+ clipboard with the Palm OS clipboard.
+
+* (Mac) Fixed problem where certain high-ASCII characters (CENT SIGN,
+ POUND SIGN, COPYRIGHT SIGN, PLUS-MINUS-SIGN, and MICRO SIGN) weren't
+ getting translated correctly into the PalmLatin code page.
+
+* Added checks for accesses to form, form object, and window data
+ structures from applications. In general, all access is prohibited.
+ The following exceptions are allowed:
+
+ ======================= =========== ==========================
+ struct/field access type When direct access allowed
+ ======================= =========== ==========================
+
+ WindowType
+ displayWidthV20 read only before Palm OS 2.0
+ displayHeightV20 read only before Palm OS 2.0
+ displayAddrV20 read only before Palm OS 3.5
+ bitmapP read only before Palm OS 3.5
+ frameType read/write always
+
+ FormType
+ handler read only always
+ helpRscID read/write always
+ defaultButton read/write always
+
+ FieldType
+ lines read only if AccessorDispatch not present
+ attr read/write before Palm OS 3.3
+
+ ControlType
+ attr read only if AccessorDispatch not present
+ style read only if AccessorDispatch not present
+
+ ListType
+ attr read/write always
+ topItem read only before Palm OS 4.0
+
+ TableType
+ numRows read only before Palm OS 4.0
+ numColumns read only before Palm OS 4.0
+ topRow read only before Palm OS 4.0
+ rowAttrs read only always
+ columnAttrs read only always
+ items real only always
+ attr read/write always
+ currentRow read/write before Palm OS 4.0
+ currentColumn read/write before Palm OS 4.0
+
+ FormBitmapType
+ attr read only if AccessorDispatch not present
+
+ FormLabelType
+ attr read only if AccessorDispatch not present
+
+ FormGadgetType
+ attr read only if AccessorDispatch not present
+ attr read/write before Palm OS 3.5
+
+ ScrollBarType
+ attr read only if AccessorDispatch not present
+ attr read/write before Palm OS 3.5
+
+ WARNING: use of this option may dramatically slow down your
+ application's performance. You may want to make use of this
+ feature on a limited basis until the next relesae of Poser,
+ which will speed things back up again.
+
+* Added check for accesses to the unused portion of the stack.
+
+* Removed unused checkboxes from Debug Options dialog, and added or
+ enabled checkboxes for the new features.
+
+* Calling DbgMessage when no debugger was around to receive the
+ message could crash Poser. Now, if no debugger is attached, the
+ message is displayed in a dialog box.
+
+* When presented with an error dialog box, you can press Cmd-C (Mac),
+ Alt-C (Unix), or Ctrl-C (Windows) to copy the error message to the
+ clipboard. Note that on Unix, the cursor needs to be over the error
+ dialog box in order for the keystroke to be sent to the dialog box.
+
+* Rewrote the Breakpoints dialog as a cross-platform dialog, thus
+ making it available on Mac and Unix as well.
+
+* When a StepSpy condition (as established by PalmDebugger or any
+ other debugger using the relevent fields of the Continue debugger
+ packet) is triggered, or a Watchpoint condition (as established by
+ the Breakpoints dialog) is triggered, display a dialog box
+ describing what just happened, much like what happens on other
+ memory access error dialogs.
+
+* In checking the stack pointer against the low end of the stack or
+ when checking for memory accesses between the low end of the stack
+ and the stack pointer, Poser needs to know where the low end of the
+ stack is. Previously, it would just assume that the entire Memory
+ Manager chunk containing the stack pointer was used for the stack
+ and so the start of the chunk was the low end of the the stack. This
+ assumption was incorrect for some applications (particularly
+ background applications in the Palm OS) that would allocate a memory
+ block for use as "instance data" that also included an embedded
+ array for use as a private stack. In order to account for those
+ applications, Poser now also monitors calls to SysTaskCreate, which
+ is passed a stack starting address and size as parameters.
+
+* (Unix) Mapped ESCAPE to most dialog Cancel buttons.
+
+* (Unix) Made clicking on the dialog's Close box in the title bar the
+ same as pressing ESCAPE. If a button with an ESCAPE shortcut could
+ not be found, then pretend the user clicked on the Cancel button.
+
+* Re-implemented the Export Database dialog as a cross-platform
+ dialog. Added code to check for .pqa databases and tack on ".pqa"
+ instead of ".pdb" when forming the default filename.
+
+* (Mac) Poser implements the LEventDispatcher::UpdateMenus method to
+ update the session and database MRU sub-menus. However, this method
+ is called all the time, and since building those menus can be time
+ consuming, UI responsiveness is impacted. Now Poser just rebuilds
+ those menus when the MRU lists actually change. The drawback to this
+ approach is that the sub-menus could be incorrect if the files they
+ correspond to are deleted from the file system.
+
+* Extended -horde_apps command line parameter to take an "exclusion
+ modifier". If the list of application names is preceded with a dash
+ (e.g., "-Prefs,HotSync"), then all applications are available to
+ Gremlins *except* those applications.
+
+* Loading a session file used to involved installing the HotSync User
+ Name that's specified in the Properties/Preferences dialog. That
+ direction is now reversed. When a session is loaded, the HotSync
+ User Name is extracted from the session and installed as the
+ emulator preference. This allows you to specify different users in
+ saved sessions and have those restored when you reload those
+ session, as opposed to all sessions -- new and reloaded -- having
+ the same user name. [Scott Maxwell]
+
+* Fixed long-standing bug where reloading session files created on
+ previous days did not get their system date updated. The time would
+ be correct, but the date would the the date on which the session was
+ created (or whatever was established by the last use of the Date
+ preference panel). [Scott Johnson, Paul Nevai]
+
+* Better hard key emulation. On an actual device, pressing a key on a
+ sleeping device would trigger an edge-sensitive INT[3:0] interrupt.
+ Normally, this by itself won't wake up a device. However, a KB
+ interrupt can also be generated, and this interrupt will wake up a
+ device. Poser, on the other hand, ignored the fact that
+ edge-sensitve INT[3:0] interrupts weren't supposed to wake the
+ device, and it also failed to support the KB interrupt. Thus, on a
+ device, pressing a key to wake up the device would succeed because
+ of the KB interrupt, while on Poser it would succeed because of
+ Poser's incorrectly waking the device on an edge-sensitive INT[3:0]
+ interrupt. In Palm OS 4.0, INT[3:0] interrupts are actually maked
+ off when the device is asleep, and so pressing keys to wake the
+ device would utterly fail. Poser now supports the KB interrupt, and
+ devices wake up again under Palm OS 4.0.
+
+* Added serial port -> TCP socket mapping. You can now redirect
+ emulated serial communications to a socket connected to another
+ application running on the same or different host computer. On Mac
+ and Windows, in the Properties/Preferences dialog, select the TCP
+ menu item. This will enable the Target edit text item, wherein you
+ can enter an IP address:port (e.g. localhost:7777). On Unix, there
+ is no menu item for selecting a serial port; there's just an edit
+ text item. Normally, you'd have something like /dev/ttyS0 there. But
+ you can replace this with an IP-looking address (e.g.,
+ localhost:7777), and Poser will recognize the difference and act
+ accordingly.
+
+ When opening the emulated Palm serial port, Poser will open a
+ corresponding socket. It will first try to connect to another socket
+ at the given address. If that fails, it will revert to "server"
+ mode, and listen for connections on the given port.
+
+* Re-implemented the Preferences/Properties and Tracer Options
+ dialogs as cross-platform dialogs.
+
+* Added HostSessionSave.
+
+ HostBoolType HostSessionSave(const char* saveFileName);
+
+ The session will be saved to a file with the given name. Regardless
+ of whether or not the save attempt succeeds, the function returns
+ false. When the session file is reloaded, execution resumes at the
+ point where HostSessionSave is returning. In this case, the function
+ returns true. This can be handy if have debugging code that can
+ detect an invalid condition, and you want your debugging harness to
+ save a session file for a later post-mortem. When you reload that
+ snapshot later, you can break into a debugger. For example:
+
+ void MyFunc (void)
+ {
+ // Check to see if our application's data is internally
+ // consistant. If not, save the state for later analysis.
+
+ if (ASSERT_VALID () == false)
+ if (HostSessionSave ("c:\\temp\foo.psf"))
+ DbgBreak ();
+ }
+
+* Changed the type of the second parameter to HostTraceOutputB from
+ "const unsigned char*" to "const void*". [Ben Combee]
+
+* When a Gremlin is running and -- for whatever reason -- the device
+ goes to sleep, wake it up by pretending the user pressed the Power
+ button.
+
+* Give the Gremlin fake event generation mechanism a 1% chance of
+ generating a vchrAutoOff event. This is the same chance given to it
+ generating a vchrKeyboard event. [Mike McCollister]
+
+* Added facilities for resolving aliases (Mac), links (Unix), and
+ shortcuts (Windows).
+
+* Added profiling support for BSR opcodes. [B. CAMERON LESIUK]
+
+* (Windows) Provided better error message when trying to create bound
+ emulators on Windows 95, 98, and ME. [Gregory Allen Gaub]
+
+* Added support for system extensions that reside in RAM. Normally,
+ Poser treats code executing in RAM as "application" code, and
+ prohibits it from accessing areas of memory reserved for the
+ operating system. However, this approach prevented user-installed OS
+ components that reside in RAM (such as OS patches and updates).
+ Poser now recognizes those components and allows them access to
+ memory in the same way it allow the OS in ROM to access memory.
+ Components that Poser recognizes are system patches, system
+ extensions, and libraries with Palm creator IDs.
+
+* Updated copyright messages to include 2001.
+
+* Updated ROM Transfer to print slightly better messages on errors.
+ For instance, instead of displaying #773, it will display "timeout".
+ Similarly for all other serial manager error codes.
+
+* Updated ROM Transfer to use the Serial Manager instead of the
+ Serial Driver Library when available. Will also use Palm OS 4.0
+ SrmExtOpen call if available.
+
+* Fixed problem where Poser could read off the end of the ROM image
+ when trying to determine what type of device it's for (when building
+ the Device menu in the New Session dialog). [John Ludwig]
+
+* (Unix) Set the default device in the ROM Transfer dialog to
+ "/dev/ttyS0" in order to impart to users what type of data should be
+ entered here. Because different Unixes have different device names
+ for their serial ports, the default may not be correct. But it
+ should get the idea across, preventing users from entering just "0",
+ for example. [Bob Marcum]
+
+* Added Prism and Platinum support. [James Phillips, Handspring]
+
+* Updated Profiling operation rules.
+
+ When using the menu commands, the following rules are used:
+
+ * System starts with only Start enabled.
+
+ * Selecting Start starts profiling executed code, initializing
+ the profiling system first if necessary. After selecting Start,
+ Stop and Dump are enabled.
+
+ * Selecting Stop suspends the profiling of executed code. After
+ selecting Stop, the Start and Dump menu items are enabled.
+
+ * The user can select Start and Stop as many times has he wants.
+ Always, the other menu item will end up being enabled, as well
+ as Dump.
+
+ * Selecting Dump first Stops any profiling (if necessary) and then
+ writes data collected while profiling to files on disk. After
+ selecting Dump, only the Start menu item is enabled.
+
+ When using the HostControl calls, an analogous set of calls can take
+ place. The only difference is that HostProfileInit can be called
+ before the first call to HostProfileStart or after HostProfileDump
+ in order to specify any custom parameters. If any HostProfile* calls
+ are made out of sequence, the error code hostErrProfilingNotReady is
+ returned. [Michael Nordstrom]
+
+* Updated HostProfile* functions along the same lines. If a
+ HostProfile* call is made out of sequence, it will return
+ hostErrProfilingNotReady.
+
+* Enable/disable Gremlins menu items correctly.
+
+* (Windows) Added platform-specific support for HostSaveScreen. [Bill
+ Kirby]
+
+* (Windows) Added multiple monitor support. Mostly this means that
+ the device window won't always reposition itself on the primary
+ monitor. [Thomas Hagen Johansen]
+
+* (Unix) Added $X_CFLAGS to espws build flags. [John Ludwig]
+
+* (Unix) Removed -L/usr/lib from link path (leaving just
+ /usr/local/lib). Both of these were added on Jan. 8, 2000,
+ apparently in response to Ralf Zimmerman's comments on
+ emulator-forum ("Re: Problem while compiling POSE 3.0a3 on Linux",
+ posted Dec 28, 1999). However, adding /usr/lib may have been
+ overkill, since doing that hides any custom tools in /usr/local/lib.
+ [John Ludwig]
+
+* When checking the validity of databases before installing them, now
+ also check the database's creation and modification dates. Poser
+ doesn't care about these and neither does the Palm OS, but some
+ versions of HotSync complain if the creation date is more recent
+ than the modification date or if the creation date is zero, so
+ display a warning if either of those cases is true.
+
+* In 3.0a8, code was added to automatically change use of
+ 207.240.80.136 (the old proxy address) to 209.247.202.106 (the new
+ proxy address). Well, those addresses are changing again. Instead of
+ hardcoding the address this time, Poser now looks up the address,
+ using the name "content-dev.palm.net" (or "content-dev2.palm.net" if
+ that one's not available).
+
+* Made the ROM transfer process more robust. Modifying the ROM
+ Transfer application and the Emulator to randomly corrupt data and
+ drop characters at a higher-than-normal rate showed problems with
+ the transfer process's ability to recover from transmission errors.
+ Those should all be fixed now.
+
+* With NetLib Redirection on, recv() is called as the underlying
+ implementation of NetLibReceive. If recv() returns EGAIN, map it to
+ netErrWouldBlock. [Chad House]
+
+* A bug in an internal ROM function in Palm OS 3.5 and 4.0 causes the
+ message "Background must be at least half as wide as slider." to be
+ displayed under the opposite conditions that it should be.
+
+* Plugged a hole that could cause Poser to hang. Occassionally,
+ Poser needs to suspend emulation so that it can make it's own
+ calls to Palm OS functions (it does this, for example, when building
+ the list of applications that appears in the New Gremlins window).
+ Because suspending emulation between any two opcodes and inserting
+ a call to a Palm OS function can be disruptive (for instance, the
+ Palm OS function may change the state of the heap in a way that
+ would never happen on a real device), Poser tries to first halt
+ emulation at a safe stopping point. This stopping point use to be
+ at the next call to a Palm OS function. However, even that's not
+ safe enough. If, for example, the Memory Manager semaphore were
+ acquired when emulation was suspended, and the call Poser was making
+ tried to acquire the semaphore, then Poser's call could block, waiting
+ for the semaphore to be released. Because emulation is suspended,
+ that will never happen, and Poser hangs. So now, in addition to
+ suspending emulation on a system call, Poser also makes sure that
+ the Memory Manager semaphore is available. This change should fix
+ a number of mysterious Poser hangs, including some that occur when
+ downloading a file for debugging in CodeWarrior.
+
+
+Changes for 3.0a8 (2000-11-17)
+------------------------------
+* Interim internal release dates:
+ 3.0a8e1 - not released
+ 3.0a8e2 - 2000-09-05
+ 3.0a8e3 - 2000-09-13
+ 3.0a8e4 - 2000-09-14
+ 3.0a8e5 - not released
+ 3.0a8e6 - not released
+ 3.0a8e7 - 2000-10-13
+ 3.0a8e8 - 2000-10-19
+ 3.0a8e9 - not released
+ 3.0a8e10 - 2000-11-06
+ 3.0a8e11 - 2000-11-13
+ 3.0a8e12 - 2000-11-16
+ 3.0a8e13 - not released
+ 3.0a8e14 - 2000-11-17
+ 3.0a8e15 - 2000-11-20
+ 3.0a8e16 - 2000-11-26
+
+* Added Dragonball VZ support.
+
+* Added SED1376 support.
+
+* Fixed (again) the problem with the Palm IIIc screen not getting
+ redrawn after turning the power off then on.
+
+* Palm devices since the Palm III have an A-to-D converter (ADC)
+ called the Burr-Brown ADS7843. Until now, Poser did no emulate this
+ hardware, and so patched the OS routines that tried accessing it,
+ causing them to return sensible values anyway. Poser now emulates
+ the ADC, and so no longer needs to patch certain traps.
+
+* Removed spaces from ROM Transfer file names.
+
+* In 3.0a7, added ability to pass-through keyboard modifiers to the
+ Palm OS. However, I forgot to implement this on non-Windows
+ platforms. Fixed that oversight. [Dave Johnson]
+
+* (Unix) Fixed problem where you could save a screen shot only if the
+ target file already existed. [Michael Nordstom]
+
+* (Unix) Allow multiple .prc (et al) files to be loaded at the same
+ time from the "Get File" dialog. [Michael Nordstrom]
+
+* (Unix) Updated Gremlins menu items after a Gremlin has been
+ started. [Michael Nordstrom]
+
+* (Unix) Remember last-accessed directory when the File dialog is
+ presented, and re-show that directory the next time the dialog is
+ displayed. [Michael Nordstrom]
+
+* Fixed inability to use serial port when emulating the EZ-based Palm
+ VII or the Palm VIIx. [Jason Simpkins]
+
+* Added support for RTS_CONT bit in the Dragonball UART register.
+ This gives better support for applications doing hardware
+ handshaking.
+
+* Before closing the host serial port in response to the emulated
+ UART being shutdown, make sure that all locally buffered data is
+ transmitted.
+
+* Worked around that d*** bug in Palm OS 3.3 that would cause it to
+ overflow the kernel stack on a reset. Now, if Poser detects a stack
+ overflow and it's the kernel stack, Poser lets it overflow into the
+ interrupt stack (which appears right below it in RAM); Poser just
+ holds off interrupts for as long as the stack has overflowed.
+
+* Map Ctrl-P to vchrPrevField, to match Ctrl-N mapping to
+ vchrNextField. [Ben Combee, David Slotter]
+
+* (Mac) Worked around problem with items in progress dialogs not
+ showing up immediately (or, sometimes, at all). For instance, in
+ the dialog tracking the progress of the installation of databases,
+ the Cancel button and "Files remaining" text didn't appear until
+ after the first file was completely installed. I now manually
+ activate and update the dialog after making it visible.
+
+* Hide a Palm OS 1.0 bug that would access memory location 0xC2 in
+ HwrSleep.
+
+* (Windows) Support double-clicking on a .rom file in order to launch
+ Poser. Before, doing this would crash Poser, as it thought the file
+ was a session file. Note that you need to run Poser once by itself
+ first in order to update the appropriate Registry entries.
+
+* Fixed problems with Poser allowing access to certain system globals
+ from certain RAM-based functions (such access is usually
+ disallowed). The affected globals were tsmFepLibStatusP and
+ tsmFepLibRefNum, which can be accessed by the glue function
+ TsmGlueGetFepGlobals.
+
+* Secure Web-based transactions would result in Poser displaying an
+ error message about memory accesses to "unallocated memory",
+ "unlocked memory", "memory manager data structures", etc. These
+ messages are now no longer displayed.
+
+* Fixed Palm Debugger fb, fw, fl and ft commands. Poser's response
+ to the Find debugger packet was incorrect. [Bob Petersen]
+
+* Fixed removal of breakpoints. Poser was disabling them instead of
+ out-and-out removing them. The effect that old breakpoints would
+ re-appear, albeit disabled, in PalmDebugger. [Bob Petersen]
+
+* Reimplemented HostFSetPos and HostFGetPos in terms of fseek and
+ ftell. Previously, they were implemented in terms of fsetpos and
+ fgetpos, but those functions aren't portable, in that the definition
+ of fpos_t changes from platform to platform.
+
+* Merged in TRGpro support from TRGnet. [Dan Smith]
+
+* (Internal) Massive rewrite of the core emulation/session handler.
+
+ Previously, a single sub-system was responsible for creating,
+ loading, saving, resetting, and freeing sessions; emulating the
+ Dragonball core instruction set; and taking care of "Palm OS
+ smarts", where checking based knowledge of how the Palm OS and Palm
+ OS applications was used to enforce correct behavior. Additionally,
+ the interface to this massive, heterogeneous sub- system was
+ different depending on whether Poser was being built for a platform
+ that supported multi-threaded applications or not.
+
+ Now that's all been changed. There's an EmSession sub-system that
+ takes care of processor- and platform-independent session creation,
+ deletion, etc. There's an abstract EmCPU class and a concrete
+ EmCPU68K subclass responsible for emulating the 68xxx instruction
+ set. And there's an EmPalmOS sub-system responsible for knowing how
+ the Palm OS works and enforcing correct behavior.
+
+ With these changes, Poser should be in a better position to support
+ different processors (like ARM) and operating systems (like Linux,
+ or even future versions of Palm OS that operate significantly
+ different from the current one). And with a more unified interface
+ to these new sub-systems, the higher levels of Poser can now also be
+ rewritten to be more cross-platform.
+
+* (Unix) Fixed (finally?) problem with LCD not appearing to turn off
+ when the power button is clicked to turn off the emulated device.
+
+* (Unix) Resize and relayout the generic error message dialog box,
+ instead of putting the (could be long, could be short) error text in
+ a scrollable field.
+
+* If INetLib tries creating its default preferences with a proxy
+ server address of 207.240.80.136 (an old, obsolete address), replace
+ it with 209.247.202.106 (the current address).
+
+* Fixed support for loading Palm VIIx ROM images downloaded from an
+ actual device (as opposed to the ROM images on the www.palmos.com
+ site). The problem was that the code used to determine what device
+ a ROM image is intended for was tripping up on that image's format,
+ and so misidentified the ROM.
+
+* (Windows) Fixed crash that could occur when clicking on some
+ Logging Options dialog buttons.
+
+* Let the Palm OS function dns_decode_name read off the end of a
+ buffer. I'm not sure yet why this happens, but until I do, let it
+ happen. Otherwise, developers will be presented with an error
+ dialog they can't do anything about. [Doitchinov Ivan]
+
+* Cleaned up, simplified, and robustified the mechanism used to
+ implement the AutoRunAndQuit directory feature. Poser used to have
+ a complex and (apparently) fragile mechanism for tracking calls to
+ SysUIAppSwitch, SysAppLaunch, SysAppStartup, and SysAppExit in order
+ to make sure that when the desired application exitted that Poser
+ quit. That's all been thrown out. Now, when an application quits,
+ Poser merely checks (in SysAppExit) to see if its cardNo and dbID
+ match that of the target application.
+
+* Fixed problem with logging posted/received events with Japanese
+ ROMs on Little-Endian host computers. Poser wasn't byteswapping the
+ event data, and so was trying to fetch some data at the wrong memory
+ location.
+
+* Address two of the three cases where calling a Palm OS function
+ which causes an exception can crash the emulator:
+
+ 1. When handling an RPC call (e.g., try "hd 3" from
+ PalmDebugger).
+ 2. When calling a Palm OS function in a trap patch.
+
+ We still don't handle the third case:
+
+ 3. When calling a Palm OS function in the UI thread (e.g., when
+ building the Gremlin application list).
+
+* When a hardware exception (such as a bus error) occurs, Poser first
+ tries to contact any attached debugger. If it can't find one, it
+ displays an error message containing Debug and Reset buttons.
+ Pressing Reset will reset the device. Pressing Debug will try again
+ to contact a debugger. If it continues to fail, it continues to
+ display the same dialog, until either the user presses Reset or a
+ debugger is finally found.
+
+* (Mac) Added two new HostControl functions:
+
+ HostProfileGetCycles()
+ Returns the current running CPU cycle count. As with all
+ profiling-related HostControl functions, this one is available
+ only in the profiling version of the emulator.
+
+ HostSaveScreen(const char*)
+ Saves the LCD frame buffer to the given file name.
+
+* For its own purposes, Poser tracks memory allocations and de-
+ allocations in the Palm OS dynamic heap. In general, except when
+ the Palm OS dynamic heap is in flux (because an allocation or
+ deallocation is in process), Poser's notion of the heap state should
+ match Palm OS's. However, Poser was failing to keep its notion in
+ sync with Palm OS's in the case where a memory allocation was
+ requested and failed. It was possible for the heap to be compacted
+ and for Poser to not notice and sync up with that compaction. This
+ error could lead to Poser reporting errors when it shouldn't or not
+ reporting errors when it should.
+
+* Fixed problem where Poser could crash if the emulated application
+ tried accessing memory location 0xFFFFFFFF.
+
+* Fixed problem with the appInfo block not getting installed if the
+ .pdb file being installed didn't have any records in it.
+
+
+Changes for 3.0a7 (2000-08-07)
+------------------------------
+* Interim internal release dates:
+ 3.0a7e1 - 2000-04-19
+ 3.0a7e2 - 2000-04-25
+ 3.0a7e3 - 2000-04-28
+ 3.0a7e4 - 2000-05-31
+ 3.0a7e5 - 2000-07-07
+ 3.0a7e6 - 2000-07-17
+ 3.0a7e7 - 2000-07-18
+ 3.0a7e8 - 2000-07-31
+ 3.0a7e9 - 2000-08-04
+ 3.0a7e10 - 2000-08-09
+
+* Added m100 support.
+
+* Added Palm VIIx support.
+
+* Implemented the following previously defined but unimplemenated
+ HostControl functions: HostMalloc, HostRealloc, HostFree,
+ HostRename, HostRemove, and HostTmpNam.
+
+* Added the following HostControl functions: HostStat, HostTruncate,
+ HostMkDir, HostRmDir, HostOpenDir, HostReadDir, HostCloseDir,
+ HostAscTime, HostClock, HostCTime, HostGMTime, HostLocalTime,
+ HostStrFPrint, HostTime, and HostUTime.
+
+* Added the following HostControl functions: HostSlotMax,
+ HostSlotRoot, and HostSlotHasCard.
+
+* Added Card Options dialog.
+
+* Renamed a bunch of HostControl types to follow Palm's naming
+ convention of having types end in "Type". Added typedefs for
+ backward compatibility with applications using the old type names.
+
+* When a session is reset, all HostControl resources are reclaimed.
+ That is, any blocks allocated with HostMalloc are freed, any files
+ opened with HostFOpen are closed, any directories opened with
+ HostOpenDir are closed, and any pointers to returned string buffers
+ (as with HostGetEnv) are now invalid and the buffers are
+ inaccessible.
+
+* After creating a handle with MemHandleNew, locking it, remembering
+ the pointer, and then freeing the handle with MemHandleFree, the
+ application could write to the freed block using the now-stale
+ pointer. Fixed. [Neil Rhodes]
+
+* Support TsmGlueGetFepGlobals accessing system globals.
+
+* Updated URLs to point to www.palmos.com.
+
+* Fixed double-dispose bug when handing the getting or setting of a
+ linger-related socket option. The symptom of this bug is that Poser
+ would crash when calling NetLibSocketOptionGet(...netSocketOptSock-
+ Linger...). [Peter Burka]
+
+* Fixed problem in NetLibSendPB when NetLib redirection is turned on;
+ the various parameters weren't converted correctly into something
+ the host TCP stack could use. [Rob Leslie]
+
+* (Unix) Added dynamic check for socklen_t in configure.in. [Radu
+ Cornea]
+
+* Internal change: added new support classes: EmPoint, EmRect,
+ EmRegion, EmRefCounted, EmRefCounter, and EmPixMap.
+
+* Used the preceding classes in rewriting the pipeline that converts
+ the LCD framebuffer into something that can be displayed on the host
+ screen. These changes (a) better insulate much of Poser from the
+ specifics of the LCD framebuffer format, (b) reduce the amount of
+ platform-specific code needed to create a bitmap that can be blitted
+ to the host screen, and (c) result in slightly faster emulation.
+
+* Poser makes use of the following as a compile-time assert:
+
+ char _dummy[expr ? 1 : 0];
+
+ If (expr) is true, then the compiler evaluates the stuff inside the
+ brackets as 1. Otherwise, the compiler evaluates it to zero,
+ resulting in the invalid definition of a zero-sized array. However,
+ unbeknownst to this poor programmer, gcc allows the definition of
+ zero-sized arrays as an extension. Therefore, all instances of the
+ above technique have been changed to COMPILE_TIME_ASSERT(expr),
+ where COMPILE_TIME_ASSERT is a macro that expands to something like:
+
+ char _dummy[expr ? 1 : -1];
+
+ Even gcc complains about that one. [Frank Yellin]
+
+* Now that we have a working compile-time assert, a number of errors
+ popped up. Part of the NetLib redirection facility involves
+ translating between NetLib data structures and host TCP (sockets)
+ data structures. The process of translating back and forth assumed
+ that various structs and constants between the two systems were the
+ same and could be copied back and forth without any interpretation.
+ This assumption was backed up by compile-time asserts. But those
+ asserts were broken. Now that they're working, it was found that
+ many assumptions were bad and/or wrong. Therefore, much of the
+ translation code was rewritten to remove those assumptions. [Frank
+ Yellin]
+
+* (Unix) Turn on -fexceptions unconditionally. While this is on by
+ default for C++, we now turn it on for C, too. Poser seems to need
+ this on Solaris/Sparc systems. [Frank Yellin]
+
+* (Unix) Implemented Save Screen... menu item. Files are saved to
+ .ppm format.
+
+* (Internal) Implemented EmDlg::DoGetFile, DoGetFileList, DoPutFile,
+ and DoGetDirectory on all platforms, and use them universally.
+
+* Added HostGetFile, HostPutFile, and HostGetDirectory.
+
+* (Unix) Use new "FileChooser" widget from Easy Software. This one
+ will probably get incorporated into FLTK 2.0, and it just plain
+ looks and works nicer anyway. [Easy Software]
+
+* Patched TblHandleEvent to fix a Palm OS 3.5 bug where the drawing
+ state would eventually become invalid, resulting in incorrect
+ drawing and possible ErrDisplays from the OS. [Tom Bulatewicz]
+
+* Inhibit error checking in NetLibBitMove. This function sometimes
+ accesses bytes past the end of an allocate block of memory,
+ resulting in a Poser error message, usually while using PQAs. As it
+ turns out, it does this in a fairly safe fashion, so prevent the
+ error message from appearing.
+
+* (Internal) Use new method to access low-memory Palm OS System
+ globals -- one based on the EmPalmStructs mechanism.
+
+* The progress dialog that's displayed when installing files has
+ changed. The progress indicator is now modelled after the Macintosh
+ file copy progress dialog; instead of having two indicators -- one
+ for files and one for the current file -- the single progress
+ indicator now indicates overall progress for all files being
+ installed. Also, the Stop button now works. Finally, the progress
+ dialog is now also implemented on Unix.
+
+* Enabled logging of Exchange Manager actions (just calls to ExgSend
+ and ExgReceive).
+
+* (Internal) New Session dialog is now implemented using cross-
+ platform techniques that Poser is slowly moving towards. This
+ change results in consistant behavior of the dialog across
+ platforms.
+
+* (Unix) "configure" script now supports "--with-fltk=DIR" command
+ line option. [Arturo Tena]
+
+* Poser contains facilities for extracting the "Macsbug" symbols that
+ can be appended to compiled functions for debugging purposes. It
+ finds these symbols using heuristic methods that don't always
+ succeed. If they fail, fail gracefully. [Adam Dingle]
+
+* Fixed problem where turning off the "power" to a Palm IIIc would
+ blank the LCD, but turning the "power" back on would not redraw the
+ LCD. [Bob Petersen]
+
+* Fixed implementation of Perl wrapper for HostImportFile and
+ HostExportFile. [Derek Johnson, Andy Ihlenfeldt, John Ludwig]
+
+* Poser would crash if you passed a full path to HostProfileDump
+ instead of just the name of a file.
+
+* Ensure that the binary file produced by profiling an application
+ ends with .mwp.
+
+* Include keyboard modifiers when posting key events from the host
+ computer's keyboard. [Ken Krugler]
+
+* Changed "New Session" dialog to use MRU list for ROM Files, and not
+ present devices for selection that cannot possibly run the chosen
+ ROM File.
+
+* Updated CodeWarrior projects to CodeWarrior 5.3 (IDE 4.0.4).
+
+* Fixed problem with lack of responsiveness in mouse-click handling.
+ The problem was that there was only a 1-element queue, as it were,
+ for handling mouse-clicks. It was too easy for the user to click
+ the mouse and let up on the button before the emulated Palm OS had a
+ chance to even recognize that the mouse button was down. Now there
+ is an n-element queue to handle mouse ups/downs. I had originally
+ stayed away from that because I thought that it would be too easy
+ for the user to overrun the event queue, zooming the mouse around
+ faster than the Palm OS could keep up. But we'll see how this works
+ out. Note that the hard buttons across the bottom of the the
+ emulated device can still be unresponsive. That's because there's
+ no queuing involved; the mechanism for handling them is different
+ from that used to handle events in the LCD area, and can't easily be
+ converted to do so.
+
+* (Unix) Fixed problem with specifying desktop serial port to use for
+ ROM Transfer. [Rick Richardson]
+
+* Catch a whole class of problems where Poser didn't detect when the
+ emulated program counter went bad. [Eugene Chin]
+
+* Fixed byteswapping problems with creating the binary output file
+ for profiling. Such a file created on Windows couldn't be read into
+ MW Profiler on a Mac. [Greg Simon]
+
+* (Internal) Rewrote all of the emulation code that deals with
+ hardware registers (such as the Dragonball registers). There were
+ many subsystems that had to deal with memory in this way (the
+ Dragonball (328, EZ) register handlers, the SED register handlers,
+ the Visor USB register handlers, the Palm VII EZ PLD register
+ handlers, the Sybol ASIC register handlers, etc.). All of these
+ subsystems originally were just cloned from each other and tweaked.
+ This lead to a lot of duplicated code. All that's now been changed
+ so that the common code is in EmBankRegs, and the hardware-specific
+ code is in subclasses of EmRegs.
+
+* (Mac) Fixed crash that would happen when clicking on the mailto URL
+ in the Palm section of the About box.
+
+* The Field Manager in Palm OS 1.0 - 3.2 has a bug that causes the
+ message "Invalid insertion point location" to be erroneously
+ displayed. Added a patch to ErrDisplayFileLineMsg to squelch this
+ message if it looks incorrect. [Stephen P. Hill, David Kendall]
+
+* (Mac) Updated to GUSI 2.1.1, fixing a bug in HostFOpen, where
+ creating the file ":x:y" would create a file called "x" if the
+ directory didn't exist.
+
+* (Unix) Re-arranged checks at bottom of EmulatorTypes.h to allow
+ for definition of INADDR_LOOPBACK. [Jon Fo]
+
+* (Unix) Specify -fpermissive to gcc to support broken X11 headers.
+ [Jon Fo]
+
+
+Changes for 3.0a6 (2000-04-19)
+------------------------------
+* Interim internal release dates:
+ 3.0a6e1 - 2000-03-06
+ 3.0a6e2 - 2000-03-13
+ 3.0a6e3 - not released
+ 3.0a6e4 - 2000-03-24
+ 3.0a6e5 - 2000-03-31
+ 3.0a6e6 - 2000-04-10
+ 3.0a6e7 - 2000-04-12
+ 3.0a6e8 - 2000-04-17
+
+* (Unix) Support POSER_DIR environment variable. If this variable
+ exists, Poser uses it as the root for all files it uses (including
+ preferences, Gremlin States, log files, and skin files). Otherwise,
+ it uses HOME.
+
+* External skin support. A "skin" is something that defines the
+ appearance of an application. Palm OS Emulator uses skins for each
+ device that it emulates. Until this release, skins were built into
+ Poser and couldn't be changed without recompiling the application.
+ Now, skins are stored in external files that Poser locates and uses.
+
+ When starting up, Poser looks for a directory starting with the text
+ "Skins" (that is, it may be "Skins", "Skins.Palm", "Skins.Personal",
+ etc.). Poser looks for all such directories in its own directory
+ (that is, the directory in which it resides on Mac or Windows, or
+ POSER_DIR on Unix), as well as that directory's parent and
+ grandparent directories.
+
+ For each such directory it finds, it scans the contents for files
+ ending with ".skin". These files are text files that describe the
+ skin. Associated with each .skin file are two graphics files that
+ define the appearance of the skin (in single and double size mode).
+
+ All of Poser's previously built-in images are now provided
+ seperately in a Skin archive available on Poser's Web pages. This
+ archive includes a ReadMe.txt file that describes how to create your
+ own skins.
+
+* Internal change: as part of the skin implementation, a number of
+ file handling and streaming classes were replaced with a new, more
+ consistant set. The following classes:
+
+ FileReference
+ StreamHandle
+ BufferHandle
+ FileHandle
+ PPStream
+ ChunkStream
+
+ Have been replaced with:
+
+ EmDirRef
+ EmFileRef
+ EmStream
+ EmStreamBlock
+ EmStreamChunk
+ EmStreamFile
+
+ Testing note:
+
+ All File I/O is affected by this change. The following places
+ need to be tested to make sure they're not broken:
+
+ Reading
+ AutoLoad, AutoRun, AutoRunAndQuit directories
+ Files specified to be loaded via cmd line.
+ Loading PDB, PRC, and PQA files.
+ Loading skin files (.skin and .jpg files).
+ Loading Preference file
+ Loading PSF files
+ Loading ROM files
+
+ Writing/Creating
+ Exporting PRC, PDB, and PQA files (both via the menu
+ item and via HostExportFile).
+ Saving screen shots.
+ Saving PSF files
+ Saving preferences
+ Saving downloaded ROM file.
+ Saving Logging files
+ Saving Profile files.
+
+* Our patch to SndDoCmd now initializes the return value. [David
+ Slotter]
+
+* (Unix) AutoLoad, AutoRun, and AutoRunAndQuit directories now
+ supported.
+
+* (Windows) Binder utility now merged into Poser directly (see the
+ "Save Bound Emulator..." menu item).
+
+ "Binding" Poser means to create a new version of Poser based on the
+ settings in the currently running Poser. A new executable is
+ created that includes a ROM image, configuration settings, skins,
+ and optionally a RAM image (the stuff that goes into a .psf file).
+ All of this information is taken from the current settings in the
+ running Poser. The result is a new Poser that is self-contained and
+ runs stand-alone.
+
+ When binding Poser, you'll be presented with two options:
+
+ * Create a version that always creates a new session based on
+ the current emulator settings
+
+ * Create a version that restores the current session
+
+ Selecting the first option creates a version of Poser bound with a
+ ROM image, configuration settings, and appropriate skins. When
+ launched, this version of Poser will always create a new session
+ based on those settings.
+
+ Selecting the second option creates a version of Poser that is also
+ bound with a RAM image. When launched, this version of Poser will
+ always restore the state that is stored in that image. This is
+ effectively the same as reloading a .psf file.
+
+ In both cases, Poser functionality is abbreviated. Because much
+ information is now specified by the bound items, menu items used to
+ create, save, and load sessions and session files are removed. And
+ since bound Posers are intended to be used in demo, kiosk, or other
+ closely controlled environments, most developer-related menu items
+ are also removed.
+
+* Fixed a problem where NetLibReceivePB could return netErrParamErr
+ instead of a more informative error code. [Frank Yellin]
+
+* Fixed a problem where NetLibReceivePB where an in/out parameter
+ passed to recvfrom was not initialized first. [Frank Yellin]
+
+* When emulating NetLib calls by turning them into host TCP calls,
+ and an error occurs, add a log message (if NetLib logging is turned
+ on) that describes how the host error code is translated into a
+ NetLib error code.
+
+* Implement the documented -skin and -silkscreen command-line
+ options.
+
+* Got rid of problem that prevented Poser from running on Macs with
+ more than 256 Meg of RAM (and which could have lead to problems on
+ other platforms as well).
+
+ Details:
+
+ (First, some terminology. In the discussion below, "host address
+ space" refers to the memory that any Windows, Mac OS, or Unix
+ application sees and manipulates. "Emulated address space" refers
+ to the memory that the Palm OS or a Palm OS application sees. It is
+ up to Poser to make the host address space look like emulated
+ address space.)
+
+ Poser emulates memory by allocating some buffers in the host's heap
+ to "back" the various memory ranges utilized by the Palm OS. For
+ instance, it creates buffers to represent RAM, ROM, and the
+ Dragonball registers. Whenever a memory access is performed, Poser
+ determines which of these buffers is required, calculates the
+ correct offset into that buffer, and fetches or stores as
+ appropriate. These buffers are used to create the illusion of the
+ emulated address space.
+
+ On occassion, it is necessary for Poser to magically make more
+ memory "appear" to the emulated process. That is, the emulated
+ process needs to be granted access to memory other than that
+ normally needed to emulate a true Palm OS environment. A chief
+ example of this is when loading a .prc file. Poser performs the
+ install process by creating the database, creating the records in
+ the database, and then copying the record contents from the .prc
+ file to the records in the database it created. This copying is
+ done by calling DmWrite. But the source of the DmWrite is a buffer
+ that Poser allocated to hold the contents of the .prc file. This
+ buffer is not one of the standard buffers Poser uses to emulate the
+ any of the standard memory ranges that a Palm OS process can access.
+
+ In order -- in this example -- for DmWrite to access the bytes in
+ the file buffer Poser allocated, Poser temporarily "maps" arbitrary
+ ranges into the emulated address space. Ranges that are mapped in
+ can be accessed by Palm OS processes. However, this mapping did not
+ undergo any address translation. That is, if the buffer holding the
+ .prc file happened to have been allocated at memory location
+ 0x01234560 by Windows, the Mac OS, Unix, or whatever, then Poser
+ would map that buffer into memory location 0x01234560 in the Palm
+ address space.
+
+ This was OK, except when memory ranges mapped into the emulated
+ space overlapped with standard memory ranges in the emulated space.
+ For instance, on Macs with lots of RAM (greater than 256 Meg, at
+ least), Poser could easily make a memory allocation that return an
+ address > 0x10000000. If the buffer that was allocated were actually
+ in the range 0x10C00000 - 0x10E00000 (or whatever the ROM range
+ was), then when Poser attempted to "map in" that buffer, it would
+ fail because of the overlap.
+
+ Now, finally, this problem is fixed. Poser now performs memory
+ address translation. Segments of memory mapped into the emulated
+ address space are now mapped in so that they appear at 0x60000000 -
+ 0x6FFFFFFF.
+
+* When checking for the validity of calls to shared library
+ functions, don't allow a refnum of zero. Also, display a specific
+ error message when an invalid library refnum is detected. [Frank
+ Yellin]
+
+* (Unix) Fixed problem with crashing on Sparc systems when loading
+ .prc files. [Frank Yellin]
+
+* Silently ignore a bug in an internal Palm OS 3.3 function
+ (PrvConvertDepth1To2BW) that causes it to walk off the end of an
+ allocated memory chunk by a single byte when reading from it.
+
+* Slightly more rigorous PC validation. Previously, I'd just check
+ to see if the PC were in a valid address space (RAM, ROM, Dragonball
+ register, etc.). Now only RAM or ROM addresses are allowed. [Frank
+ Yellin]
+
+* HostFFlush (HostLogFile()) now writes the log file to disk.
+
+* Re-hooked up the "Logging Options..." button in the New Gremlin
+ dialog box. In order to do this, utilized some cross-platform
+ dialog handling routines that are slowly being phased in. As a
+ result of these new routines, the dialog box has been changed from a
+ multi-panel dialog on Mac and Windows to a non-panel dialog box (as
+ was on Unix).
+
+* (Unix) No longer hide and reshow the main window when establishing
+ a new skin (either as part of the Skins dialog, or as part of
+ loading/creating a session). This process was an attemp to work-
+ around an FLTK problem where the X frame window didn't properly
+ resize itself. This workaround didn't work, and another one has
+ been put in place, so the old one's taken out.
+
+* (Unix) Change the filter button to use only lower-case suffixes.
+ With both upper and lowercase, the text in the filter button would
+ overflow its bounds. [Jon Aslund]
+
+* (Unix) When opening a saved session file while a current session is
+ already running, Poser would attempt to close the first session's
+ thread twice, and then attempt to start the second session's thread
+ twice. This would often lead Poser to hang. Now each of those is
+ done just once. [Jon Aslund]
+
+* (Unix) Instead of crashing, report errors that occur while creating
+ a new session or loading an old one. [Jon Aslund]
+
+* (Unix) Added BSD/OS 4.1 support. [Bert Driehuis]
+
+* Allow TsmGlueGetFepMode and TsmGlueSetFepMode access to system
+ globals.
+
+* (Windows) Fixed bug where creating a new session in Poser, quitting
+ without saving, and then starting Poser using the -psf command line
+ option would result in a new session being created again instead of
+ loading the specified session file.
+
+* ROM Transfer project updated to use SDK 3.5.
+
+* Internal change: previously, when Poser had to manipulate data in
+ Palm OS format, it used the structs in the Palm OS headers directly.
+ However, that assumed that we could convince all the compilers used
+ to build Poser to lay out those structs correctly (that is, with the
+ same size and alignment as the 68K compiler used to build the Palm
+ OS ROM and Palm OS applications). This assumption is almost true,
+ but not quite. Therefore, with this release, a new mechanism for
+ manipulating Palm OS structs is used. This mechanism (see the
+ EmPalmStructs.xxx files) allows Poser to access structs in a
+ platform-, compiler-, and endian-independent fashion.
+
+ Currently, this new mechanism is used only in the area of sending
+ and receiving packets from external clients (debuggers and scripts).
+ Eventually, it will be used in all aspects of Poser operation. Once
+ this switchover is complete, we'll be mostly independent of the Palm
+ header files, and will probably be able to get rid of most of
+ contents of the the Byteswapping.xxx files.
+
+* Fixed problem with our patch to NetLibReceive. The exact problem
+ being solved was one where NetLibReceive was called, received some
+ data, the application modified that data in the buffer that received
+ the data, and then call NetLibReceive again. No bytes were
+ available, but the contents of the buffer were updated with the
+ contents of the previous receive, thus wiping out the modified
+ buffer contents. The application was relying on the buffer not
+ changing, and so failed when it actually did.
+
+* Fixed problems with ROM Transfer not running on Palm OS 1.0.
+ [Vladimir Amarante]
+
+* Fixed problem with trying to boot a ROM from a Palm V device that
+ had originally been installed with Palm OS 3.1 but was lateer
+ upgraded to Palm OS 3.3. [Douglas R. Shefsky]
+
+* (Windows) Fixed a problem with not reading the entire preferences
+ file.
+
+* (Unix) Fixed problem with clicking in a non-active area of the
+ window (that is, outside of any button or LCD area).
+
+* (Unix) Added ROM Transfer project (with prc-tools 2.0 compatible
+ Makefile) and pre-built ROM Transfer.prc application that can
+ be installed with something like pilot-xfer.
+
+* (Unix) Fixed problem that could lead to unexpected results when
+ running certain dialogs after other certain dialogs (FLTK wasn't
+ clearing out a reference to a widget in the first dialog,
+ causing the second to crash).
+
+* (Unix) Remapped EINPROGRESS (as returned by sockets functions)
+ to netErrWouldBlock instead of netErrSocketBusy (as NetMgr.h
+ would suggest). This change allows Network HotSync to work
+ between a Unix box and a Windows box.
+
+
+Changes for 3.0a5 (2000-03-06)
+------------------------------
+* Interim internal release dates:
+ 3.0a5e1 - 2000-02-25
+ 3.0a5e2 - 2000-02-25
+ 3.0a5e3 - 2000-03-01
+ 3.0a5e4 - 2000-03-03
+
+* Internal change: major change in the way the Dragonball and
+ DragonballEZ registers are handled for different devices.
+ Previously, there were two sub-systems: one that handled Dragonball
+ registers, and one that handled DragonballEZ registers. Any device
+ differences withing those two categories were handled with a set of
+ conditional statements. That mechanism started breaking down (the
+ conditionals were getting too twisty), so now device support is
+ broken down with a set of classes having the following hierarchy:
+
+ EmRegs - fairly abstract base class
+ EmRegs328 - mildly abstract base class implementing Dragonball emulation common to all 328 devices
+ EmRegs328Pilot, EmRegs328PalmPilot, etc. - concrete base class filling in the missing, custom pieces for a specific device
+ EmRegsEZ - mildly abstract base class implementing Dragonball emulation common to all EZ devices
+ EmRegsEZPalmIIIx, EmRegsPalmV, etc. - concrete base class filling in the missing, custom pieces for a specific device
+
+* Added Symbol 1700 support. Note that Symbol-specific hardware is
+ not yet emulated. Attempting to use scanner or Spectrum facilities
+ will hang the device. [Ron Kupke, Darren Kropp, John Duhart, Harini
+ Bharadvaj]
+
+* Changed the way serial emulation is performed a little bit.
+ Before, I'd look at the UART-enable bit to determine whether or not
+ to open or close the host's serial port. However, that would lead
+ to problems on Unix when using pseudo-devices. While opening the
+ serial port, the Palm OS would enable and disable the UART several
+ times as it was configuring the communications. This would lead to
+ the host serial port being opened and closed several times. But
+ Unix pseudo-devices don't react to that usage very well. So now,
+ Poser looks at the serial line driver enable bit. This bit is
+ toggled just once at the beginning and end of a serial port session,
+ just like we want. [Eskil Heyn Olsen]
+
+* Fixed problem with serial emulation not working on Palm VII EZ.
+
+* Fixed problem where reloading a .psf file that had a Gremlin
+ running would not correctly install the Gremlin-specific logging
+ options.
+
+* Fixed problem affecting Gremlin reproducability. There was a patch
+ on KeyCurrentState to randomly set key bits when a Gremlin was
+ running. However, the RNG used to set the bits was in no way
+ synchronized with the RNG used to generate Gremlin events, nor was
+ it ever reset in any way when a Gremlin was started or restarted.
+ The effect was that any application that was sensitive to the
+ results of KeyCurrentState would react randomly. One example of
+ this was the Address Book, which looked to see if the Address Book
+ hard key was pressed in order to see if the user wanted to beam
+ his/her business card.
+
+* Fixed problem affecting Gremlin reproducability. Some applications
+ are sensitive to time and timing issues. Gremlins now tries to make
+ sure that all forms of time (including the DragonBall cycle counter,
+ the kernel's tick counter, the Palm OS tick counter, and the
+ Dragonball real-time clock) are all set to consistant values when a
+ Gremlin is started and restored when a Gremlin-active .psf file is
+ reloaded (the cycle and tick counters are set to zero, and the RTC
+ is set to 3:00pm). Also, when a Gremlin is running, the real-time
+ clock is unhooked from the host's clock (normally, the values read
+ from the Dragonball real-time clock are generated from the host's
+ clock functions). Instead, the RTC is incremented assuming that the
+ average instruction takes 12 cycles, and where the cycle time is
+ based on the Dragonball's PLL registers.
+
+* Set the chip and mask IDs. This is set to the 1H58B part for the
+ 328, and 1J83G for the EZ.
+
+* (Unix) Fixed problem with Logging Options dialog hanging.
+
+* Check PC and stack pointer when doing a TRAP #$F dispatch.
+
+* More up-to-date instructions for Network HotSyncing with Poser.
+ [Brian Mathis]
+
+ These instructions are intended for developers or other POSE users
+ who want to synchronize the Palm OS Emulator with the same PC they
+ are running POSE on. Modifications to these directions may be
+ needed if a user wishes to synchronize with a PC on an attached
+ network. They were written on a Windows machine, and probably have
+ Windows specific instructions in them. It should be pretty painless
+ to adapt them to other platforms that support hotsyncing.
+
+ These are current for version 30a3 and 30a4 of POSE emulating a Palm
+ V, OS 3.1, and Hotsync version 3.0.1/3.0.4, Windows 98 & NT.
+
+ ----Configure Hotsync on your Desktop PC
+
+ 1. Right-Click the hotsync icon in the system tray
+
+ 2. Enable "Network". A check mark will appear next to it if it's
+ already enabled.
+
+ ----Configure POSE:
+
+ 1. Right-Click on the POSE window to bring up the Menu. Choose
+ "Settings/Properties".
+
+ 2. Check the box next to "Redirect NetLib Calls to TCP/IP".
+
+ 3. Click "OK"
+
+ ----Configure Hotsync on the Palm
+
+ 1. Open the "HotSync App".
+
+ 2. "Menu/Options/Modem Sync Preferences" - set to "Network"
+
+ 3. "Menu/Options/LANSync Preferences" - set to "LANSync"
+
+ 4. "Menu/Options/Primary PC Setup" - enter "127.0.0.1" under
+ "Primary PC Address" (the middle one)
+
+ 5. Under the "Modem Sync" icon on the main Hotsync screen, tap
+ "Select Service". Then tap "Done". You don't need to change any
+ info, you just need to have something selected. You can create a
+ new profile if you like.
+
+ 6. Tap the "Modem Sync" button. Your PC should now kick into
+ action, and will probably ask you to choose an account, or create a
+ new one. It is highly recommended that you create a new account
+ just for POSE.
+
+ See also the following KnowledgeBase article:
+
+ <http://oasis.palm.com/devzone/knowledgebasearticle.cfm?article_id=1674>
+
+* Information from TRGnet on TRGpro support. [Mike Walter]
+
+ TRGpro support for POSE
+
+ Version 3.0a4 includes limited support for TRGpro emulation. This
+ version emulates the FAT file system API provided on the TRGpro. It
+ does not support the lower level CompactFlash API or the enhanced
+ audio API on the TRGpro.
+
+ In order to emulate the TRGpro Fat file system, do the following:
+
+ 1. Obtain a PalmOS 3.3 image from any device. (PalmIIIx, PalmV,
+ etc)
+
+ 2. Modify file "Palm OS Emulator.ini" in your Windows
+ subdirectory. Change to line FfsHome to point to a subdirectory on
+ your drive.
+
+ Example "FfsHome=C:\POSE\
+
+ 3. Put desired Palm programs and databases into subdirectory
+ specified above.
+
+ 4. Run Emulator.exe.
+
+ 5. Install the programs ffs_pose.prc and CFPro.prc onto emulator.
+
+ 6. Run CFPro to move files back and forth between Emulator and
+ PC's subdirectory.
+
+ Developers writing code for the FAT file system can now debug using
+ POSE.
+
+ More documentation will be provided later, specifying exactly what
+ is and is not supported with the emulator. For example, card
+ insert/remove messages are not supported with this version.
+
+ For those of you interested, the files modified/added to the POSE
+ software base were, Platform_FfsLibWin.cpp and
+ TrapPatches_FfsLib.cpp.
+
+ Keep in mind that this is a first beta release, if you have any
+ questions or problems, email TRGnet directly.
+
+ Zip file containing ffs_pose.prc and CFPro.prc can be downloaded
+ from:
+
+ http://www.trgnet.com/download/pose/fat.zip
+
+ POSE version 3.0a4 or greater can be downloaded from:
+
+ http://www.palmos.com/dev/tech/tools/emulator/>
+
+* "Pen" events are essentially created as needed and inserted into
+ the Palm OS on demand from mouse events by way of a patch on the
+ SysEventGet function. However, until now, there was no
+ corresponding patch to EvtSysEventAvail to make that function return
+ true if the host mouse was down. Now there is. [Michael Nordstrom]
+
+* Added back long paths for MRU menus. [Chris Antos]
+
+* (Windows) Made F11 minimize the window. [Chris Antos]
+
+* (Windows) Swapped positions of About and Exit menu items. [Carlton
+ Craighead]
+
+* Simplified Skins dialog.
+
+* Simplified Gremlins dialog. Instead of entering magic numbers like
+ zero and -1, use checkboxes to enable desired features.
+
+* Added Palm IIIc skins. Renamed "Color Device" to Palm IIIc.
+
+* Added UsingPOSE.pdf.
+
+* (Unix) Implemented "File/Save" menu item. [Dan Poirier]
+
+* (Unix) Fixed problem where UART::Initialize would get called twice
+ when reloading a .psf file, triggering an assert. [Dan Poirier]
+
+* (Windows) Fixed problem with not setting the skin palette when
+ using the generic skin on 8-bit monitors. [Andreas Linke]
+
+* Removed SndInit patch that would set the system volume level to
+ zero, mirroring what happens in the simulator. However, this
+ caused problems with people not hearing sounds when they expected
+ to. So, removed the patch. If you don't want sound, turn it off
+ in the Preferences/Properties dialog. [Frederic Paolucci]
+
+* (Unix) Building under Solaris 2.6 (with gcc installed) is now
+ possible. It's probable that building under other SunOS environments
+ won't work.
+
+* (Unix) The window resizes to match skin selections.
+
+* Export Database dialog now primarily lists the actual database name,
+ with the application icon name in parentheses if it differs.
+
+
+Changes for 3.0a4 (2000-01-28)
+------------------------------
+* Interim internal release dates:
+ 3.0a4e1 - 1999-12-02
+ 3.0a4e2 - 1999-12-30
+ 3.0a4e3 - 2000-01-07
+ 3.0a4e4 - 2000-01-23
+ 3.0a4e5 - 2000-01-26
+ 3.0a4e6 - 2000-01-27
+
+* Yow...time to start updating those copyright statements...again...
+ and this time there's a lot more files!
+
+* When installing a .prc file, check for duplicate resources.
+
+* Provide better error messages when something goes awry while
+ installing an application or database.
+
+* Added support for Palm IIIe and Palm Vx:
+
+ - Added as items to Device menu.
+ - Added code to save those devices as preferences.
+ - Added as -device parameters on command line ("PalmIIIe" and "PalmVx").
+ - Added and mapped in appropriate skins.
+ - Added new internal type IDs.
+ - Corresponding tweaks to Binder application.
+ - Made Palm IIIe return same device ID as Palm IIIx.
+ - Made Palm Vx return same device ID as Palm V.
+
+* (Mac) Updated to GUSI 2.0.1. This has the following benefits:
+
+ - Adds support for socket options.
+ - Based on Open Transport instead of Mac TCP.
+ - Fixes problem with menus sometimes getting disabled (the
+ old GUSI would eat up "resume" events, so PowerPlant didn't
+ know to re-enable the UI).
+
+* Fixed problem where Poser's heap walking routines were vulnerable
+ to odd master pointers. [Mike Chen]
+
+* Gremlins wasn't generating and posting hard button events properly.
+ [Steve Lemke]
+
+* (Unix) Fixed problem with trying to delete a skin with a stale
+ pointer. [Ben Darnell]
+
+* Updated ROM Transfer.mcp to CodeWarrior for Palm OS R6.
+
+* Support for the gdb debugger has been built-in for quite some time
+ (since 2.1d22 or so). Here, finally, are some instructions for
+ interacting with it. Note that you no longer need to use gdbpanel
+ or gdbplug if you were using those with earlier versions of Poser,
+ Copilot, or xcopilot. [Ben Thomas]
+
+ - Build your app. Be sure to _both_ compile and link with -g
+ (e.g., "gcc -g ..."). On the compile pass, this generates the
+ necessary symbol information; on the link pass it forces the
+ inclusion of a debug runtime code that results in a breakpoint
+ being installed in PilotMain when the app starts.
+
+ - Start Poser.
+
+ - Load your app into Poser.
+
+ - Start gdb, loading your application's symbol table (e.g., "gdb
+ myApp"). Note that the file to be loaded is the "myApp" file
+ created by the GCC link pass, not "myApp.prc" created by
+ buildprc.
+
+ - Type "target pilot localhost:2000" to gdb. It should respond
+ with a message along the lines of "Remote debugging under PalmOS
+ using localhost:2000. Waiting... (Press Ctrl-C to connect to
+ halted machine)".
+
+ - Start your app on Poser.
+
+ - Wait for gdb to see the initial breakpoint and prompt you.
+
+ - Start debugging.
+
+* Tweaks to the scripting samples: [Flash Sheridan, Steve Haneman]
+
+ - Wait() no long automatically resumes.
+ - Added seperate Resume function
+ - Since wait no longer resumes, added TapPenSync, and TapButtonSync
+ which automatically call Wait and Resume at the beginning and end.
+ - Fixed some warnings that showed up when running Perl -w.
+ - Added MemPtrSetOwner, WinDisplayToWindowPt, WinWindowToDisplayPt.
+ - In TapButton, call WinWindowToDisplayPt.
+ - In EmRPC, added support for Coord type.
+
+* Internal change: encapsulated all device-specific information in an
+ EmDevice class. This should make it easier to add new devices,
+ since all the information is now in one place.
+
+* Stack overflow checking is back (cf 2.1d27)! Whenever it looks
+ like something is assigning a value to the stack pointer register,
+ Poser marks the memory block that pointer is in as a stack. Then,
+ when the stack pointer is decremented for any reason, it is compared
+ to the low end of the memory chunk. If it falls below, Poser
+ displays a fatal error dialog. If the stack pointer is just getting
+ close without actually going over, Poser will display a warning.
+
+* Fixed another case of Gremlins going to sleep on the job. Gremlins
+ normally posts new random events when the system calls EvtGetEvent
+ and there's nothing to return, resulting in SysDoze being called.
+ Most of the times, Gremlins will post an event and return from
+ EvtGetEvent. In the cases it doesn't, it forces EvtGetEvent to
+ return a nil event. However, if Gremlins was posting a Shakespeare
+ quote to a form field, and the form field was full, and there was a
+ non-empty selection, there was a 33% chance that neither an event
+ would be posted nor a nil event returned. This resulted in the
+ application having nothing to do (and so SysDoze was called) and
+ Gremlins thinking its job was done for the moment and putting itself
+ into a "do nothing" state. [Scott Maxwell]
+
+* (Windows) When reloading a .psf file, fixed a bug that prevent the
+ Gremlin Control Window from being reshown if the session file had
+ been saved while a Gremlin was running. [Scott Maxwell]
+
+* (Windows) Fixed a problem with relocating the ROM file that a .psf
+ file reference when that ROM file wasn't where it was supposed to
+ be, but it *was* in the same directory as the .psf file.
+
+* (Unix) Rolled in modifications for FreeBSD. [John Ludwig]
+
+* (Unix) Properly recognise X options such as -display and -geometry.
+ [Eric House, John Marshall]
+
+* Reset the Dragonball timer registers to a consistant state before
+ starting a Gremlin. This gives more consistant results. HOWEVER,
+ any application that is dependent on the time in any fashion may
+ still have consistancy problems when running Gremlins (that is,
+ starting Gremlin #0 at 3:00pm may give different results than when
+ it is started at 5:00pm). This is an issue that we'll try to
+ address in a future release.
+
+* Switch from obsolete xxxChr names to new vchrXXX names in logging
+ output. Also, if a winExit/EnterEvent is associated with a form,
+ print the name of that form in the logging output if event logging
+ is turned on.
+
+* (Mac, Windows) Added Tracer support. This is a facility for
+ sending logging information to an external logging application. Palm
+ applications use the following API for doing this:
+
+ (All HostTraceOutput functions take a module identifier as their
+ first parameter. This parameter allows filtering out traces
+ according to their origin. Recognized modules are listed as error
+ classes in SystemMgr.h. Application should specify appErrorClass.)
+
+ void HostTraceInit(void);
+ Call once at the beginning of your application to
+ initialize the logging facility. Initiates a connection
+ to the "tracing port" (specified in Poser's Tracing
+ Options dialog box).
+
+ void HostTraceClose(void);
+ Call once at the exit of your application to release
+ any host logging resources.
+
+ void HostTraceOutputT(unsigned short, const char*, ...);
+ Log a string of text to the tracing port via a
+ "printf-like" facility.
+
+ void HostTraceOutputTL(unsigned short, const char*, ...);
+ Same as HostTraceOutputT with an additional line break.
+
+ void HostTraceOutputVT(unsigned short, const char*, char* /*va_list*/);
+ vprintf-like variant of HostTraceOutputT.
+
+ void HostTraceOutputVTL(unsigned short, const char*, char* /*va_list*/);
+ vprintf-like variant of HostTraceOutputTL.
+
+ void HostTraceOutputB(unsigned short, const unsigned char*, unsigned long/*size_t*/);
+ Send binary data to the tracing port.
+
+ The functionality for sending the logging information to the
+ external application is provided by a shared library (e.g.,
+ "PalmTrace.dll" on Windows). The external application can be any
+ application that supports the open packet convention. The one we
+ provide is "Reporter". At the time of this writing, the shared
+ library and external reporting application will be provided in a
+ seperate archive. [Patrick Porlan, Regis Nicolas]
+
+* Internal changes: massive movement to make more source code cross
+ platform. New classes include:
+
+ EmTransport: abstract base class representing a "pipe" between two
+ entities.
+
+ EmTransportSerial: a pipe based on serial communications. Serial
+ port emulation (the facility that allows Palm OS Serial Manager
+ calls to pass thru to and from the host serial port) rewritten to
+ use EmTransportSerial.
+
+ EmHostTransportSerial: class with different implementations on
+ different platforms in order to provide platform specific
+ functionality.
+
+ EmDlg: class to manage dialogs in a cross-platform fashion.
+
+ EmROMTransfer: class that implements a rewritten ROM download
+ facility, based on the new EmTransport and EmDlg classes. Because
+ the new ROM transfer code is based on EmTransport and not
+ EmTransportSerial, this means that it may be possible to transfer a
+ ROM using something other than the serial port in the future.
+
+* With the help of the previous changes, the ROM Download facility is
+ now available on Unix.
+
+* Internal change: rewrote JPEG decompression routines to better
+ modularize the source of compressed data and the destination of
+ decompressed data. This was done to better support JPEG images on
+ disk in addition to those in embedded resources.
+
+* Added back the old generic case graphics. These graphics are now
+ used when the user selects "Default" in the Skins menu and dialog.
+ The nicer graphics are now identified with names like "Standard -
+ English" and "Standard - Japanese". Eventually, those nicer
+ graphics will be moved to external files, reducing the size of Poser
+ drastically and reducing download times.
+
+* Internal change: synced up with the latest shared Palm OS files.
+ This change also included switching over to the new standardized
+ types (UInt32, Int16, etc.) from the old hodgepodge of types (DWord,
+ Long, Int, Byte, etc.).
+
+* ROM Transfer now downloads the entire ROM instead of just the "Big
+ ROM". It now is also a little more robust in light of some invalid
+ fields in Visor ROMs.
+
+* (Windows) Added support for TRGpro devices. This support comes in
+ the form of supporting TRGnet's FAT File System library. There is
+ no TRGpro menu item in the device menu. Instead, you can
+ effectively turn any Palm Computing device into the equivalent of a
+ TRGnet device by installing their FFS library -- which is what
+ manages access to the CompactFlash slot -- onto the device.
+ (Actually, all it needs is a stub library that you can get from
+ TRGnet.) Poser will redirect calls from that library to the host
+ file system. The root of the emulated FFS directory hierarchy is
+ specified by the FfsHome preference in Poser's preference file. It
+ can be a path relative to Poser's directory (e.g., "foo") or an
+ absolute path (e.g., "c:\temp\foo"). The directory will be created
+ if needed. If no preference is specified, or the value is empty, or
+ the specified directory could not be created, the root path defaults
+ to Poser's directory. There is currently no UI for setting the root
+ of the hierarchy; you have to edit the preference file by hand.
+ [Mike Walter]
+
+* Added Visor support. Note that no USB support is provided in this
+ release. This means that Poser will not download a ROM from a
+ device in a USB-connected cradle, nor will USB operations on the
+ emulated Visor be redirected to any host facility.
+
+* Fixed problem with a too-small name buffer in profiling routines.
+ Removed absolute address from generated function names, as that
+ annotation interferes with the CodeWarrior Profiler's ability to
+ unmangle C++ names. [Catherine White]
+
+* (Windows) Removed "Close" menu item from "bound" versions of Poser
+ (functionality duplicates "Exit"), and added "Save Screen". [Scott
+ Johnson]
+
+* (Unix) Added temporary hack to get Unix menus working (many would
+ result in the message that the system was not responding). The
+ solution implemented, however, is not optimal, and may lead to other
+ problems. Expect this area to receive more attention in the near
+ future. [Eric House]
+
+* Added sound emulation. Be sure to enable this in the preferences
+ if you want it. [William F. Weiher III]
+
+* Fixed a couple of minor problems in the NetLib redirection code,
+ one with accept() and another with the way select() timeouts were
+ set up. [bill pitore]
+
+* Fixed a problem with determining the baud rate established by the
+ UART, with the result that serial communications on 20MHz devices
+ (like the Palm Vx) didn't work. [Alan Finke]
+
+
+Changes for 3.0a3 (1999-11-13)
+------------------------------
+* Added Q&D PC checking. On JSR, BSR, RTS, and RTE, I check what
+ we're attempting to set the PC to. Originally, I had a pretty beefy
+ check that made sure the PC was in things like allocated, locked
+ chunks. However, that's expensive for now, so I backed off to
+ checking that the PC was (a) even, (b) in RAM or ROM, and (c) not in
+ low-memory.
+
+* The new UAE 0.8.10 code includes a new way to emulate ROR and ROL
+ instructions. Unfortunately, this new way runs afoul of a code
+ generation bug in CWCPPC 2.3.1 (from CW 5.2) on the Mac. Reverted
+ to the old way of emulating those instructions until Metrowerks
+ comes out with a compiler patch. [Catherine White]
+
+* (Unix) Added tweaks for Debian systems. [Ben Darnell]
+
+* (Mac) Changed the way Poser determines whether or not to translate
+ extended ASCII characters (those >= 0x80) into standard ASCII
+ equivalents. The new method should be more consistant and robust,
+ based on whether or not the user is running a Japanese Palm OS and a
+ Mac OS with the Japanese Language Kit installed.
+
+* The device could actually go to sleep while running Gremlins!
+ Sometimes, Gremlins will input a long series of key events.
+ However, key events don't reset the auto-off counter. Normally, the
+ Palm doesn't care, since key events are a side-effect of pen events,
+ which *do* reset the auto-off counter. But Poser doesn't enter key
+ events that way -- it inserts them directly with EvtEnqueueKey. Now
+ Poser calls EvtResetAutoOffTimer when it enters key events. [Steve
+ Lemke]
+
+* (Windows) Sped up Gremlin Hordes a little. There were some long
+ delays while switching from one Gremlin to another due to trying to
+ access the Gremlin Control Window from the wrong thread. There's
+ still a mysterious 2 second delay while switching Gremlins, but at
+ least one cause of the slow-down is fixed.
+
+* Fixed problem with Gremlins and Palm OS 3.5 systems. Gremlins
+ calls WinGetWindowBounds to get the bounds of a window in which to
+ generate pen taps. WinGetWindowBounds returns the bounds of the
+ window returned by WinGetDrawWindow. On older systems, if the draw
+ window were NULL, WinGetDrawWindow would return the display window.
+ On 3.5, this has been changed in debug ROMs; WinGetDrawWindow can
+ return NULL so as to force applications to make sure there is an
+ established draw window. Gremlins ran afoul of that change, and so
+ now calls WinSetDrawWindow(WinGetActiveWindow()) before calling
+ WinGetWindowBounds(). [Roger Flores, Steve Lemke]
+
+* In the event posting/receiving logging code, support the new Palm
+ OS 3.5 events.
+
+* In HostFPrintF, support + and space as flags, and * as a minimum
+ width field character. [Patrick Porlan]
+
+* Added Symbol 1700/1740 skin as an option for Palm III's. This is
+ *not* to say that Poser emulates symbol devices. It only means that
+ you can make a Palm III look like a Symbol device. [Ron Kupke]
+
+* Reformatted Gremlin Hordes log file to make it a little easier to
+ find the error messages. [Flash Sheridan, Catherine White]
+
+* Make a stronger effort to get the pen calibrated perfectly. The
+ original attempt (cf, 2.1d11) would occassionally only get us very
+ close, which could lead to inconsistent Gremlin runs.
+
+* Fixed a bug in the UAE 0.8.10 code where a corrupt status register
+ could get pushed onto the stack during an exception/interrupt and
+ the previous instruction that had affected the Z CPU flag was a BCHG
+ instruction that flipped the highmost bit from off to on (gee, how
+ could we have missed *that*). [Catherine White, Stuart Malone]
+
+
+Changes for 3.0a2 (1999-11-05)
+------------------------------
+* Updated to UAE 0.8.10. We were previously based on 0.8.3. The new
+ version fixes a few minor bugs (I never noticed them), perhaps
+ speeds things up a little, but most importantly cleans up those 2000
+ "unreferenced label" warnings you get when compiling with gcc! OK,
+ so now there are some "unused variable" warnings, but there are a
+ lot fewer of them...
+
+* (Windows) The sequence of events involving saving a session when
+ creating or opening a new one was completely broken.
+
+* (Windows) Added support from Palm Europe for their tracing tool.
+ This tracing tool is a seperate application that receives tracing
+ information sent via HostControl functions. The documentation for
+ these functions is not yet available. Neither is the external
+ application. But they soon will be. I just wanted to at least
+ mention them so that people don't ask me about them if they see the
+ new functions in HostControl.h.
+
+* (Unix) Modified Perl script that creates ResStrings.cpp. It used
+ to add the strings to a map object (so that they can be looked up by
+ an ID number) by calling a function with about 2000 calls that
+ looked like "map[id] = str;". However, gcc would choke on this with
+ optimizations turned on. Now, that map addition is performed in a
+ seperate function, and that function is called 2000 times instead.
+ [Ben Darnell, Jon Fo]
+
+
+Changes for 3.0a1 (1999-11-04)
+------------------------------
+* Interim internal release dates:
+ 2.1d29.1 - 1999-08-26
+ 3.0a1e2 - 1999-09-14
+ 3.0a1e3 - 1999-09-15
+ 3.0a1e4 - 1999-09-16
+ 3.0a1e5 - 1999-09-21
+ 3.0a1e6 - 1999-09-24
+ 3.0a1e7 - 1999-09-30
+ 3.0a1e8 - 1999-10-08
+ 3.0a1e9 - 1999-10-14
+ 3.0a1e10 - 1999-10-19
+ 3.0a1e11 - 1999-10-27
+
+* Rolled in Llamagraphics's profiling changes [Catherine White]:
+
+ The motivation for these changes was to fix the crashing problem we
+ reported earlier. Here's what we changed:
+
+ - We rewrote RecursiveAddressToStrings without recursion, and
+ named the new function LinearAddressToStrings. The old function
+ was recursing over both kids and siblings, which was blowing the
+ stack on the Macintosh. Since it doesn't matter what order the
+ addresses are converted in, a linear loop is faster and simpler.
+
+ - Called ProfilerCleanup at the end of ProfilerDump. Since
+ calls[i].address is modified during the dump, the calls array
+ can't be reused after the dump since it no longer contains valid
+ addresses. It seems safer to dispose of it so that it isn't used
+ accidentally.
+
+ - Replaced the two Debugger() calls in ProfilerInit with calls to
+ DisposeMemory(). We were encountering these Debugger calls
+ while testing our own code, probably because ProfilerInit was
+ being called twice somehow. Calling ProfilerInit twice should
+ now be harmless, and should no longer leak memory.
+
+ - Changed the handling of function names so that they are no
+ longer limited to 31 characters. The new limit is 255
+ characters. This means that most mangled C++ names can now be
+ parsed properly by the MW Profiler, which makes interpreting the
+ profiles easier.
+
+ In order to accomplish this, we needed to add extra arguments to
+ two routines in Miscellaneous.cpp for the buffer capacity. This
+ capacity defaults to 32, which means that callers who don't pass
+ in the extra argument will get the same behavior as before.
+
+ We also added code in the profiler so that the stringTable could
+ grow dynamically. This means that it isn't so important to
+ allocate enough memory for the stringTable initially. However,
+ the initial size is currently the same as the old size was, so
+ reallocation shouldn't occur very often.
+
+* (Mac) Updated to CodeWarrior Pro 5.
+
+* Overhauled handling of preferences/properties/settings/options...
+ These settings were previously stored as resource-based binary data
+ on the Mac, System Registry entries on Window, and an RC text file
+ on Unix. Now the information is saved out as a text file on all
+ platforms. And -- with a common source code base -- all information
+ is saved out consistantly (some platforms previously skipped saving
+ some information). Finally, with all information in an accessible
+ text file format, it should be easier for users to tweak or fix
+ settings (or even specify settings for which there is no UI).
+
+ Note that NO attempt has been made to migrate forward settings from
+ the previous formats.
+
+* In line with that, if the InterceptSysFatalAlert is true (default),
+ Poser will intercept calls to SysFatalAlert and display the message
+ in its own dialog box. If this setting is false, Poser will let the
+ standard Palm OS function display the message. [Ken Krugler, Scott
+ Johnson]
+
+* If a SysFatalAlert dialog is displayed while a Gremlin is running,
+ the Gremlin will no longer be halted if the user clicks on Continue
+ (it used to be that the Gremlin was *always* halted). [Roger Flores]
+
+* (Windows) Ask user if they'd like to have a shortcut to Poser added
+ to the Start Menu. [Phil Shoemaker]
+
+* Better validation of .prc files. [Daniel McCarthy]
+
+* (Windows) Cancel button in file download progress dialog now works.
+
+* (Windows) Fixed byteswapping bug in PSF writing code. Poser should
+ now have a better chance of reading Mac-created PSF files on Windows
+ and vice-versa.
+
+* Fixed memory leak bug that would occur when closing a session. The
+ buffers holding the ROM image and auxilliary information weren't
+ being deleted. [bullshark (a real person with a real email
+ address)].
+
+* (Windows) Added the Palm OS Emulator Binding tool, an NT-only
+ wizard which can bind a Windows Poser executable with (1) a ROM file
+ and a device configuration, or (2) a ROM file and a session file.
+ This will create a self-contained executable suitable for "kiosk"
+ run.
+
+ Poser detects when it is bound, and modifies its behavior in the
+ following manner:
+
+ (1) ROM + device configuration. Poser always starts by booting
+ into a new session with the selected device configuration and
+ ROM. If the user closes the session and creates a new one, he or
+ she will not be prompted for a device configuration.
+
+ (2) ROM + PSF file. Poser always starts right into the state
+ saved in the PSF file. The user interface is abbreviated to
+ include only pertinent functionality (no debugging or logging,
+ for example) that is appropriate to a "kiosk" run. IF the user
+ closes the session, he or she only has the option to restart it
+ in the state saved in the PSF file. Posers bound this way share
+ a separate set of preferences then unbound Posers.
+
+* Made the socket port that an external debugger can connect to
+ configurable. The old hard-coded port of 2000 is still support for
+ backward compatibility, but clients should move away from that.
+ Instead, they should use the port specified in the
+ "DebuggerSocketPort" preference. (There is currently no UI for
+ changing this preference. But it can be changed by hand by editting
+ the Poser preferences file, which is in text format.)
+
+* Added the following functions to HostControl.h:
+
+ HostErr HostProfileDetailFn (void* addr, HostBool logDetails)
+
+ Profiles the function containing the given address. If
+ logDetails is true, profiling is performed at a machine-
+ language instruction level (each opcode is treated as
+ its own function).
+
+ HostErr HostGremlinNew (const HostGremlinInfo*);
+
+ Start a new Gremlin using the given specifications.
+
+ HostBool HostGetPreference (const char*, char*);
+ void HostSetPreference (const char*, const char*);
+
+ Get or set the specified preference. Preferences are
+ identified by name, the set of which can be seen in the Palm
+ OS Emulator Preferences file for your platform ("Palm OS
+ Emulator Preferences" in the Preferences folder on the Mac,
+ "Palm OS Emulator Preferences.ini" in the Windows System
+ directory on Windows, and ".poserrc" in your home directory
+ on Unix). The values are also specified as strings,
+ examples of which can be seen in the preferences file.
+
+ HostErr HostSessionCreate (const char* device, long ramSize, const char* romPath);
+
+ Create a new session based on the given parameters.
+ Fails if a session is already running.
+
+ * NOTE: Not yet implemented.
+
+ HostErr HostSessionOpen (const char* psfFileName);
+
+ Open the given session. Fails if a session is already
+ running.
+
+ * NOTE: Not yet implemented.
+
+ HostErr HostSessionClose (const char* saveFileName);
+
+ Close the current session, saving it to the given file.
+ The session is not saved if no file name is specified.
+ This function fails if no session is running.
+
+ HostErr HostSessionQuit (void);
+
+ Ask Poser to quit. Fails if a session is already
+ running.
+
+ HostErr HostSignalSend (HostSignal signalNumber)
+
+ Send a signal (identified by an integer) to any scripts
+ with HostSignalWait calls pending. If there are such
+ pending calls, Poser then halts waiting to be restarted
+ with HostSignalResume. If no one was waiting for any
+ signals, then Poser doesn't halt.
+
+ HostErr HostSignalWait (long timeout, HostSignal* signalNumber)
+
+ Wait for a signal from Poser. Signals can be predefined
+ (hostSignalIdle, hostSignalQuit) or user-defined.
+ HostSignalWait returns the signalled value.
+
+ hostSignalIdle is issued by Poser when it detects that it's
+ going into an idle state.
+
+ hostSignalQuit is issued by Poser when it's about to quit.
+
+ HostErr HostSignalResume (void)
+
+ Restarts Poser after it has issued a signal. By waiting
+ to be restarted, Poser allows external scripts to perform
+ any other operations first.
+
+
+ While the following functions are in the HostControl API,
+ they exist for external RPC clients to call and will return
+ errors if called by Palm OS applications:
+
+ HostSessionCreate
+ HostSessionOpen
+ HostSessionClose
+ HostSessionQuit
+ HostSignalWait
+ HostSignalResume
+
+* Opened a socket (on the port specified in "RPCSocketPort"
+ preference) for external applications to make RPC calls. By sending
+ RPC packets, external applications can invoke any function in the
+ Palm OS dispatch table. This set of functions includes the
+ HostControl functions, which can be called even when no session is
+ running (which normally would mean that there isn't really a
+ dispatch table containing functions that can be called).
+
+ Packets sent to the RPC sub-system use the same format as packets
+ sent to the debugger sub-system, that is, the Serial Link Protocol
+ packet format (also used by HotSync). This format is described in
+ Debugging.html.
+
+ When sending command packets to the RPC sub-system, you need to set
+ the "dest" field of the packet header to:
+
+ #define slkSocketRPC (slkSocketFirstDynamic + 10)
+
+ as opposed to slkSocketDebugger or slkSocketConsole, as you would
+ when talking with the debugger sub-system.
+
+ The RPC sub-system can accept one of 4 kinds of command pacets:
+ ReadMem, WriteMem, RPC, and RPC2. The first three packets are the
+ same as those sent to the debugger sub-system and are defined in
+ Debugging.html. RPC2 is an extension of the RPC packet in order to
+ support a wider range of facilities.
+
+ RPC2 packets are defined as follows:
+
+ #define sysPktRPC2Cmd 0x20
+ #define sysPktRPC2Rsp 0xA0
+
+ struct SysPktRPCParamInfo
+ {
+ UInt8 byRef; // true if param is by reference
+ UInt8 size; // # of Bytes of paramData (must be even)
+ UInt16 data[1]; // variable length array of paramData
+ };
+
+ struct SysPktRPC2Type
+ {
+ _sysPktBodyCommon; // Common Body header
+ UInt16 trapWord; // which trap to execute
+ UInt32 resultD0; // result from D0 placed here
+ UInt32 resultA0; // result from A0 placed here
+ UInt16 resultException; // If an exception occurred, it's ID is here
+ UInt8 DRegMask; // Bitmasks indicating what registers need...
+ UInt8 ARegMask; // ...to be set on this call.
+ UInt32 Regs[1]; // Variable-length array holding register...
+ // ...values to be set on this call.
+ UInt16 numParams; // how many parameters follow
+
+ // Following is a variable length array of SlkRPCParamInfo's
+ SysPktRPCParamType param[1];
+ };
+
+ Most of this is the same as the RPC packet. It differs with the
+ addition of the following fields:
+
+ resultException: if the function call failed because a hardware
+ exception occurred, the exception ID will be stored here. Otherwise,
+ this field contains zero.
+
+ DRegMask: a bitmask indicating what D registers need to be set in
+ order to make this call. In particular, some functions require that
+ a "selector" value be placed in register D2. In this case, bit 2 of
+ DRegMask (the 3rd bit from the right) would be set.
+
+ ARegMask: same comments.
+
+ Regs[1]: a variable length array containing the values to be placed
+ in the registers to be set. Only the registers that are being
+ changed need to be supplied. Most of the time, DRegMask and ARegMask
+ will be zero and Regs would not appear in the packet. In the example
+ where D2 needs to be set, DRegMask would be 0x04, ARegMask would be
+ 0x00, and ARegMask would be followed by a single 32-bit value to be
+ placed in D2. If more than one register needs to be set, then the
+ register values should appear in the following order: D0, D1, ...,
+ D6, D7, A0, A1, ..., A6, A7. Again, only values for the registers
+ specified in DRegMask and ARegMask need to be provided.
+
+* Fixed crasher that could occur if "Received Events" logging was
+ turned on and one of three KeyDown events was popped off the stack.
+ [Ken Krugler, Jeff Yasuda]
+
+* (Unix) Added serial port emulation, as well as better support for
+ other OS and compiler flavors. [Jerry Kirk, Michael Kedl]
+
+* (Unix) Added support for cursor, page up/down keys. [Michael Kedl]
+
+* (Unix) Fixed massive memory leak when sessions ended. [Michael Kedl]
+
+* More evolution of skin support. Skins are now set on a device-by-
+ device basis from a new "Skins..." dialog box. Other aspects of the
+ device's appearance are also set from this dialog box, such as the
+ scaling factor and the LCD background color.
+
+* Look at the chip selects when determining what range of RAM should
+ be protected or not instead of just assuming 128K. [Steve Lemke]
+
+* Fixed problems with reloading .psf files what were saved when a
+ Gremlin was running.
+
+* Fixed problem with white border in 2x mode.
+
+* Fixed problem with setting some color table entries. [Bob Ebert]
+
+* Fixed problem with HwrDisplayWake hanging on power-up. [David Fedor]
+
+* Setting "DebuggerSocketPort" or "RPCSocketPort" preferences to zero
+ will disable their respective facilities. This should be handy in
+ cases where merely opening a TCP socket fires up any sort of
+ unwanted Remote Access facilites. [Ken Krugler]
+
+* (Mac) Fixed bug in new preferences saving mechanism where the
+ preferences would not get saved if the file didn't already exist.
+ [Mike Puckett]
+
+* Allow LCD window to be placed in negative coordinates. [Mike Puckett]
+
+* Addition of Gremlin Hordes. A Horde is basically a range of
+ Gremlins to run. You specify the range: the first Gremlin and the
+ last Gremlin in the Horde. Poser will start with the first Gremlin,
+ and generate that Gremlins event stream until one of four things
+ happens:
+
+ - An error occurs (hardware exception, illegal memory access, etc.),
+ - The maximum number of events have been generated,
+ - A "switch" event occurs. A switch event is when a specified number
+ of the maximum number of events have been generated.
+
+ When any of these conditions occur, the current Gremlin is either
+ halted or suspended and the next Gremlin in the Horde is selected.
+ When Poser has cycled through all the Gremlins in the range, it
+ cycles back and restarts any suspended Gremlins one at a time. When
+ all Gremlins have been halted (either because they've encountered an
+ error or they've reached the maximum number of events), the Hordes
+ session is completed.
+
+* (Windows) Added the following command-line options [Brian Estes]:
+
+ -skin <name>:
+ Synonyn for -silkscreen.
+
+ -ram_size <size in K>:
+ Synonym for -ram.
+
+ -load_apps <file name list>:
+ A comma-seperated list of files (.prc's, etc.) to load after
+ startup.
+
+ -run_app <app name>:
+ Application to run after startup. Note that this is the
+ name of the *application*, not the file.
+
+ -quit_on_exit:
+ If -run_app was specified, quit when that application exits.
+
+ -log_save_dir <path>:
+ Location for standard log file. Default = Poser's directory.
+
+ -horde <num>:
+ Gremlin number to run after session is created or loaded.
+ Equivalent to setting -horde_first and -horde_last to the
+ same number.
+
+ -horde_first <num>:
+ First Gremlin in a Gremlin Horde to run.
+
+ -horde_last <num>:
+ Last Gremlin in a Gremlin Horde to run.
+
+ -horde_apps <app name list>:
+ A comma-seperated list of applications Gremlins is allowed
+ to switch to. Default == entire device (no restrictions).
+
+ -horde_save_dir <path>:
+ Location for directory that keeps saved session files and
+ logs. Default = Poser's directory.
+
+ -horde_save_freq <num>:
+ Gremlin snapshot save frequency. Default = don't save
+ snapshots.
+
+ -horde_depth_max <num>:
+ Total number of Gremlin events to generate for each Gremlin.
+ Default == no upper limit.
+
+ -horde_depth_switch <num>:
+ Number of Gremlin events to generate before switching to
+ another Gremlin in a Horde. Default == the same number
+ specified for -horde_depth_max.
+
+* (Windows) Added support for Alt-F4; made it act like the Exit menu
+ item. [Ryan Robertson]
+
+* Fixed a problem with profiling calls to Palm OS function made via
+ the SYSTRAP_FASTER macro. The function entry would be recorded once
+ because it was a system call, and then again because it was made via
+ a JSR. Because the subsequent RTS would pop only one of those off of
+ the profiler's stack, the stack would get out of sync and overflow.
+ [Jameson Quinn]
+
+* (Windows, Unix) Now stop the CPU thread on almost any UI action.
+ Previously, the CPU thread would be stopped only in targeted
+ situations. Now, it's stopped whenever the user executed a menu
+ command. This change was made when I found out that the profiling
+ menu items could mess up the CPU thread if it weren't stopped first.
+
+* Updated ROM Transfer project to CodeWarrior for Palm OS 5.2 (that
+ is, CodeWarrior for Palm OS Release 5 with Metrowerks' two updates
+ applied).
+
+* Fixed the way time spent in the trap dispatcher was recorded when
+ profiling; entries for the same function weren't necessarily being
+ collapsed into a single entry. [Bob Ebert]
+
+* (Unix) Added JPEG case graphics.
+
+* (Windows) Added taskbar menu with Minimize/Move/Close menu items.
+ Note that there may still be problems with minimizing/maximizing
+ Poser. For instance, Windows NT does not minimize windows without
+ caption bars when you select "Minimize All Windows". Windows 98
+ will hide Poser when selection "Show Desktop", but will restore
+ Poser when restoring another application window. These problems
+ appear to be shortcomings of Windows, but if anyone knows how to
+ accomodate these foibles, please let me know. [Scott Johnson]
+
+* More accurate emulation of ROM space. Now the chip-selects are
+ used in conjuction with the ROM image file size. [Steve Lemke,
+ Jesse Donaldson]
+
+ In general:
+
+ The size of the ROM image is always rounded up to the next power of
+ two.
+
+ On Dragonball devices, I assume that the chip-selects are always set
+ to specify a 2 Meg ROM (this appropriate for all ROMs so far). On
+ DragonballEZ devices, I look at csASelect, bits 1-3 (BTW, the reset
+ value for this register is 0x00E0, so there don't seem to be any
+ boot-up issues).
+
+ If the rounded ROM image size is larger than the size specified by
+ the chip-selects, then it gets truncated; the CPU won't be able to
+ access the far end of it.
+
+ If the rounded ROM image size is the same as the size specified by
+ the chip-selects, then everything is fine. No truncating, no
+ mirroring.
+
+ If the rounded ROM image size is smaller than the size specified by
+ the chip-selects, then the ROM image is mirrored for as many times
+ as is necessary to cover the range.
+
+* (Mac) Added Power Manager code to keep PowerBooks awake when Poser
+ is doing something and when the PowerBook is plugged in. [Mike
+ Puckett]
+
+* Ensure that windows (LCD, Gremlin Control) are onscreen when
+ they're created. Right now, this means that they are brought
+ onscreen if any part of them is offscreen. If this is too strict,
+ we can revisit the algorithm later.
+
+* The code to validate the objects on a form has been moved from
+ Gremlins-specific code into a patch on FrmDrawFrom. Now people will
+ get bugged about invalid objects even when not running Gremlins. :-)
+
+ By the way, some people have reported that they get told about
+ invalid or offscreen form objects, and that they think these reports
+ are in error, as the objects reported have ludicrous positions and
+ sizes and have object IDs that don't exist in the resource
+ description file. If you get such a message, *strongly* suspect
+ that your object list has been trashed, possibly due to the changing
+ of a label or title. Eventually, Poser will be able to detect when
+ form object lists get trashed at the moment it occurs, and not later
+ on down the stream (such as when the form gets drawn).
+
+* When dragging files onto the LCD screen, the rules are: you can
+ drag any number and assortment of .prc, .pdb, and .pqa files; you
+ can drag only one .rom file, you can drag only one .psf file; you
+ can't mix files from any of the three just-mentioned categories
+ together. If you broke any of these rules, you'd get an error
+ message. However, this error message was broken in different way on
+ Mac and Windows (the Unix version doesn't support D&D yet -- any
+ takers?). This was fixed by making the majority of the relevent
+ code cross-platform, and then fixing *that*. [Roger Flores, Mike
+ Turcotte]
+
+* (Mac) Fixed problem with Japanese text showing up as "Jinglish" on
+ systems with the Japanese Language Kit installed. This was always
+ supposed to be a feature in the New Gremlin dialog (so that you
+ could see the application names correctly), but appears to have been
+ broken for some time. That should be fixed, and the same facility
+ has now been extended to the dialog containing error messages
+ generated by the Palm OS. [Ken Krugler]
+
+* Fixed bug in NetLibGetHostByAddr where the address was assumed to be
+ a NetSocketAddrType instead of anything that could be "len" bytes
+ long. [Bill Pittore]
+
+* Turned on checking of writes to ROM. This was off for a reason
+ (there's a comment next to the relevent part saying "HACK: We really
+ want it to be true!"), but I don't remember what it is. I was able
+ to run Gremlins on some apps for quite a while without error, so
+ hopefully we can get away with turning this back on. [Scott Johnson]
+
+* Take another stab at fixing the problem with FntDefineFont, as first
+ described in the release notes for 2.1d20. FntDefineFont can read
+ off the end of a source buffer, causing Poser to report an invalid
+ read access to memory manager data structures. This bug -- fixed in
+ Palm OS 3.2 -- doesn't need to be alerted by Poser. [Scott Johnson]
+
+* If an application executes DbgBreak and no debugger is attached,
+ display a friendly message in a dialog box that includes Continue
+ and Reset buttons. [Ken Krugler]
+
+* Added Red Dutta's "Export Database" menu item. This command takes
+ the place of the "posedbexport" Palm OS application, allowing you
+ to export databases and applications from the emulator to your
+ desktop computer as a .pdb or .prc file. [Red Dutta]
+
+* Patch SysReset so that Poser no longer complains about normally
+ proscribed actions (like mucking with low-memory) during a reboot.
+
+* Bring us in-sync with the Simulator with regards to entering
+ control-chars that map to Palm OS command-chars. The list is:
+
+ control-A menuChr
+ control-B lowBatteryChr
+ control-C commandChr
+ control-D confirmChr
+ control-E launchChr
+ control-F keyboardChr
+ control-M linefeedChr
+ control-N nextFieldChr
+ control-S autoOffChr
+ control-T hardContrastChr
+ control-U backlightChr
+
+ B, S, T, and U are new in this release.
+
+
+Changes for 2.1d29 (1999-07-08)
+-------------------------------
+* Interim internal release dates:
+ 2.1d28.1 - 1999-06-04
+ 2.1d28.2 - 1999-06-04
+ 2.1d28.3 - 1999-06-11
+ 2.1d28.4 - 1999-06-11
+ 2.1d28.5 - 1999-06-11
+ 2.1d28.6 - 1999-06-15
+ 2.1d28.7 - 1999-06-16
+ 2.1d28.8 - 1999-06-23
+ 2.1d28.9 - 1999-06-25
+ 2.1d28.10 - 1999-06-30
+
+* For temporary backward compatibility, "bare" file names on the
+ command lineare treated as paths to .psf files. [Andreas Linke, Mike
+ McCollister]
+
+* (Mac) Fixed problem with receiving Error #18 when trying to download
+ ROMs from actual devices over the serial port. [Mark Ordal]
+
+* In debugger/sockets communications, allow for recv() returning
+ zero, indicating a closed connection.
+
+* Fixed multi-threading bugs. [Andrew Ball, Daniel McCarty, Scott
+ Johnson, Keith Wolcott, Art Dahm, Mark Lussier, Alex Robinson,
+ Patrick Porlan]
+
+* (Unix) Fixed some makefile problems. [many]
+
+* (Mac, Windows): new case graphics. Note that the edges of the new
+ graphics are a little rough; we'll be working on that for the next
+ release. Also, the Mac version doesn't set up a custom palette in
+ 8-bit mode, yet, so for best results, you might want to put your
+ monitor in 16- or 24-bit modes. Finally, the Unix version will get
+ the new graphics in the next release.
+
+* Print some logging information using signed instead of unsigned
+ value. [Oliver King-Smith]
+
+* Don't go into infinite recursion when the emulated PC is set to an
+ odd memory address. [John Marshall]
+
+* Fixed problem in the "NetLib redirected" version of
+ NetLibSocketAccept where the address and address length were not
+ returned. [Bill Pitore]
+
+* (Windows) As outlined in the notes for 2.1d28, Poser will look for
+ the last-saved .psf file when starting up. It used to save the
+ reference to this file as a full pathname. Now, if the attempt
+ to locate the file with the full pathname fails, Poser will look
+ for a .psf file with the same name in the same directory as
+ Poser itself. This approach is similar to the way in which
+ Poser looks for .ROM files that are no longer at their last known
+ location. [Michael Hado]
+
+* Worked around VC++ 6.0 bug where tabbed dialogs in applications
+ built by it won't show up on systems without IE 4.x installed.
+ [Michael S. Davis]
+
+* (Unix) Fixed a minor bug in skin loading code which causes Emulator
+ to crash when it tries to load a skin file from current directory.
+ [Vlad]
+
+* Set the command key bit when Gremlins posts an up or down arrow.
+
+
+Changes for 2.1d28 (1999-05-21)
+-------------------------------
+* Interim internal release dates:
+ 2.1d27.1 - 1999-05-17
+
+* (Windows) Added command line options:
+
+ -psf <filename>: emulator loads the specified .psf file on startup.
+
+ -rom <filename>: specifies the ROM image file to use.
+ -ram <size>: specifies the amount of RAM to emulate (in K). Valid sizes
+ are 128, 256, 512, 1024, 2048, 4096, and 8192.
+ -device <type>: specifies the device to emulate. Valid types are pilot,
+ palmpilot, palmiii, palmiiix, palmv, palmvii, and palmiiic.
+ -silkscreen <type>: specifies the silkscreen to use. Valid types are
+ english and japanese.
+
+ Case is NOT significant.
+
+ Examples:
+
+ Emulator -psf C:\Data\Session.psf
+
+ Emulator -ROM C:\ROMs\3.0\debug.rom -RAM 1024 -Device PalmIII
+ -Silkscreen English
+
+ Startup rules are now as follows:
+
+ 1 If the Caps Lock key is toggled in the ON position, always bring
+ up the New/Open/... dialog.
+ 2 Scan the command line for startup parameters. If an error occurs
+ trying to scan the command line, the error is reported and the user
+ is presented with the New/Open/... dialog.
+ 3 Use the .psf file if one is specified. If an error occurs trying
+ to load the file, the error is reported and the user is presented
+ with the New/Open/... dialog.
+ 4 If any of -rom, -ram, -device, or -silkscreen are specified, try
+ to start a new session based on those values. If all are specified,
+ the new session is automatically created. If any of those four
+ values are missing, the "New Configuration" dialog is displayed.
+ If the user cancels the dialog, or if there is an error creating
+ the new session, any error is reported and the user is presented
+ with the New/Open/... dialog.
+ 5 If no command line options are specified, try re-opening the last
+ saved .psf file (this step is skipped if the user last created a
+ new session, but did NOT save that session to a file). If an error
+ occurs trying to load the file, the error is reported and the user
+ is presented with the New/Open/... dialog.
+ 6 Try creating a new session based on the settings the user last
+ specified when creating a session. If there is an error creating
+ the new session, the error is reported and the user is presented
+ with the New/Open/... dialog.
+ 7 Finally, if all else fails, present the user with the New/Open/...
+ dialog.
+
+ Steps 1, 5, 6, and 7 describe the old startup rules. Steps 2, 3,
+ and 4 are new. [Steve Haneman]
+
+* See that problem where I said that saving a session file could take
+ up to 15 seconds or even longer? And see where I said I didn't know
+ why? Well, it's because I'm an idiot. Under certain circumstances,
+ Poser could get into a state where it would save the same session
+ file several times in a row. Normally it would take a 1/2 second to
+ save a file. But if it decided to save the same file 30 times in a
+ row, that would take 15 seconds...
+
+* Fixed some more synchronization problems on SMP machines.
+
+* Force the Log####.txt files to be stored in the Poser directory
+ instead of whatever directory happens to be the current one.
+
+
+Changes for 2.1d27 (1999-05-07)
+-------------------------------
+* Interim internal release dates:
+ 2.1d26.1 - ???
+ 2.1d26.2 - ???
+ 2.1d26.3 - ???
+ 2.1d26.4 - 1999-03-25
+ 2.1d26.5 - 1999-04-01
+ 2.1d26.6 - ???
+ 2.1d26.7 - ???
+ 2.1d26.8 - 1999-04-27
+ 2.1d26.9 - 1999-04-29
+ 2.1d26.10 - 1999-05-05
+
+* Added special messages for accessing NULL and for trying to access
+ the A5 register (in order to access global variables or make inter-
+ segment jumps) when A5 is not set up for the application trying to
+ use it. [Roger Flores, Ken Krugler]
+
+* Better tracking of the current application. Now, if errors occur
+ during an "action code" sequence, the application executing is
+ reported, not the "main", "real" application that has the stack, A5,
+ etc. [Roger Flores]
+
+* Fixed problem with installed Palm OS files and .psf files not
+ getting added to the MRU lists if the list was empty. [Scott
+ Johnson]
+
+* Fixed problem with MRU lists getting too long. [John Kinast]
+
+* In our SysUIAppSwitch patch, release any leftover command parameter
+ blocks (if any). [Catherine White]
+
+* Fixed problem with the Escape key used to wake up a sleeping device
+ also showing up in the event queue. [Daniel McCarty]
+
+* (Mac) Added support for Escape, F1-F4, page up/down.
+
+* Added special checks and error messages for SANE Math calling
+ sequences. [Steve Lemke]
+
+* Rolled in Adam's fixes to conditional breakpoints. [Adam Dingle]
+
+* Fixed problems with NetLibSocketAddr. [Adam Dingle]
+
+* Converted to VC++ 6.0.
+
+* Fixed problem with getting names of library routines in the
+ profiling system. [Adam Dingle]
+
+* Made Profile/Initialize implicit. [Adam Dingle]
+
+* Added explicit parent node information to profiling output text
+ file. [Adam Dingle]
+
+* Fixed problem with recursive routines recursing too deep in the
+ profile output functions.
+
+* The workaround for the old FindSaveFindStr bug didn't always work;
+ it would sometimes still let the bug emerge. Made a small tweak to
+ keep it suppressed.
+
+* Turned off stack overflow checking facility. It would occasionally
+ cause the emulator to walk the dynamic heap when the heap was in an
+ inconsistent state, resulting in spurious "...regular checkup..."
+ error messages. [The IBM guys: Paul Silagi, Chunk Bazil, Mike Nagy]
+
+* Added support for the contrast button on Palm Vs. The button is on
+ the right-hand side of the display graphic, opposite from the power
+ button. You can't see it, but clicking on it brings up the contrast
+ dialog. The dialog itself has no visual effect yet. [Ron Flax]
+
+* Breakpoints are now preserved across reboots. [Steve Lemke]
+
+* Totally rewrote the way (a) tailpatches and (b) soft breakpoints
+ are handled. Previously, Poser would get control by handling
+ special opcodes written into emulated memory: TRAP $D for
+ tailpatches and TRAP $0 for soft breakpoints. However, there were
+ problems with this approach. For one thing, what would happen if we
+ needed to write a TRAP $D and TRAP $0 to the same memory location.
+ You couldn't do it. There was no way, for example, to use
+ PalmDebugger to set a breakpoint just after a call to a system
+ function that Poser tailpatched. Also, Adam Dingle pointed out a
+ problem with the actual routines involved: on very rare occasions,
+ if an interrupt occurred just after one of those TRAP $Ds or TRAP $0s
+ were executed, then the next opcode executed would be the one that
+ originally resided at that location, an NOT the first opcode in the
+ interrupt routine. Anyway, this whole mess has been replaced with a
+ new mechanism that doesn't alter the emulated RAM or ROM. [Steve
+ Lemke, Adam Dingle and the IBM guys: Paul Silagi, Chunk Bazil, Mike
+ Nagy]
+
+* Sped up performance by 20%. But since the previous change slowed
+ things down by 13%, that's not as great as it first sounds.
+
+* Poser now ignores soft breakpoints (those installed by
+ PalmDebugger) it encounters when it calls into the ROM for it own,
+ nefarious, "between the cycles" purposes. [Steve Lemke]
+
+* Fixed problems trying to re-establish a sockets connection after
+ it's been broken when the external debugger quit. [Ron Marianetti]
+
+* When asked for a ROM, .psf, .prc, etc., file, set the initial
+ directory to the last directory used for that file type.
+
+* (Windows) Allow multiple .prc file selection in the Open File dialog.
+
+* ROMs with invalid header checksums now generate a non-fatal warning
+ instead of a fatal error. [Paul Dugas]
+
+* Allow for zero-length objects appearing at the end of .pdb files.
+ [Christopher Hunt]
+
+* Massive spring cleaning of sources. Now all major sub-systems have
+ a consistant interface for creating new sessions, resetting
+ sessions, saving sessions, loading sessions, and disposing of
+ sessions. Also, a lot of naming and scoping inconsistancies were
+ taken care of. Also, namespaces were forsaken in favor of classes
+ with static member functions; the CodeWarrior and VC++ browsers
+ didn't handle namespaces too well.
+
+* In line with the above, .psf files are now compressed, taking as
+ little as 15K for one that was normally 1 Meg. Note: the time it
+ takes to compress an image can vary wildly, sometimes being nearly
+ instantaneous, and sometimes taking upwards of 15 seconds. I'm not
+ sure why the difference occurs...
+
+* Also in line with the source code spring cleaning, the entire
+ emulator state is now saved to the session files. When loaded from
+ the session files, the entire emulator state is restored. This means
+ that you are returned right back to where you were when you created
+ the session file; you do not have to go through the process of
+ rebooting the "device".
+
+* Only heed the "Continue Past Warnings" option if a Gremlin is
+ actually running. [Scott Johnson]
+
+* Added support for the "dead battery" pin on Port D on EZ devices.
+ This should cut down the number of low-battery warnings on those
+ devices. [Jesse Donaldson]
+
+* Don't insert keyboard or mouse events if stopped in the debugger or
+ if the main emulator window is not active.
+
+* Added support for 4-bit LCD mode on EZ's. Found and fixed a long-
+ standing bug where the emulated copy of the LCD display might not
+ get updated if the lcdPageWidth register was updated.
+
+* If the emulated serial port was open and a reset occurred, close the
+ host serial port.
+
+* On the Mac, session files contain references to their associated
+ ROM files via aliases. On Windows, the references are stored as
+ full pathnames. This is old news. What's new is that if either of
+ these mechanisms fails to find the ROM file, Poser now looks first
+ in the same directory as the session file for a ROM file with the
+ same name, and if that fails looks in Poser's own directory for a
+ ROM file with the same name.
+
+* When reporting a corrupted heap, display also the address of the
+ chunk header. [Adam Dingle]
+
+* Implemented Part I of Gremlin Hordes: You can now periodically have
+ the complete emulator state saved while a Gremlin is running. This
+ state can be reloaded, and the Gremlin restarted.
+
+ This feature is controlled via a new setting in the New Gremlin
+ dialog. There is now an editable item called Snapshot Frequency.
+ The number entered here is the number of events that should occur
+ between the time snapshots are taken. The default value is 10,000
+ events. By setting this value to zero, you turn off the snapshot
+ feature.
+
+ Snapshots are saved in a single directory in the Poser directory.
+ The name of the directory is "GremlinStates_####", where #### is a
+ value ensuring the directory name's uniqueness.
+
+ Snapshots are saved in this directory with the name Event##########,
+ where ########## is the event number at which the snapshot was
+ taken. Snapshots are merely session files, so they can be reloaded
+ at any time, just like regular session files.
+
+ Since snapshots are taken while a Gremlin is running, the Gremlin is
+ automatically turned off when the snapshot is reloaded. However,
+ Poser displays the Gremlin Control window when the snapshot is
+ loaded, allowing you to resume the Gremlin if you want. [Roger
+ Flores]
+
+* Fixed a bug in the Gremlins facility that validates forms and form
+ objects before trying to manipulate any of them. A call to
+ FrmGetObjectType would occassionally return garbage, leading the
+ rest of the function astray. [Scott Maxwell]
+
+* Added Unix release. [Ben Williamson, David Creemer]
+
+* Fixed serial port not working on EZ devices (a pin moved from port
+ F to port D during hardware development, and I missed it). [Florent
+ Pillet]
+
+* Don't validate form objects and their sizes on Palm OS 1.0 devices.
+ The built-in applications don't appear to follow the rules. [Andrew
+ Ball]
+
+* Rolled in Adam's conditional breakpoint enhancements. [Adam Dingle]
+
+ "A register reference in a conditional breakpoint expression can
+ use either a direct (i.e. "d5") or indirect (e.g. "12(a6)")
+ addressing mode. Furthermore, a register expression can be
+ suffixed with either ".b", ".w" or ".l" to indicate that the
+ expression to be compared is either a byte, a word or a long. An
+ an example, "12(a6).w == 1000" compares the two bytes at memory
+ location (a6 + 12) to the value 1000. "d4.b == 100" compares the
+ low byte of the d4 register to the value 100.
+
+ "I have found this enhancement to be extremely useful for breaking
+ into the debugger when a local variable (typically referenced off
+ the a6 register in code built by CodeWarrior) has a certain value."
+
+* (Windows) Fixed problem with running on dual-processor boxes. [TBD]
+
+* There is now a "white paper" on Poser usage at the following URL:
+
+ <http://www.palm.com/devzone/docs/pose.htm>
+
+
+Changes for 2.1d26 (1999-02-26)
+-------------------------------
+* On the Mac, we were saving the device type to the .psf file twice.
+ On Windows, we weren't saving the country type at all. [Waddah
+ Kudaimi]
+
+* System call logging now also gets the names of library functions,
+ and attempts to make a better stab at "dispatch" system functions
+ (where a single dispatch code sub-dispatches to a suite of other
+ functions, as with the Floating Point Manager). [Ken Krugler]
+
+* Sped up debugger communications via sockets by 20x. [Ron Marianetti,
+ Mark Corry]
+
+* (Windows) Added conditional breakpoints. This is bolted on for now,
+ but should eventually be merged more seamlessly. Changes provided
+ by Adam Dingle of AvantGo. From Adam's release notes:
+
+ New debugging features
+
+ I've posted several messages recently to the palm-dev-forum mailing
+ list in which I've pointed out several limitations of the debugger
+ in CodeWarrior for PalmOS: it doesn't support data breakpoints
+ ("watchpoints") and its conditional breakpoint implementation is
+ very slow. To work around these limitations, I've added both data
+ breakpoints and fast conditional breakpoints to the 2.0b3 emulator.
+
+ A data breakpoint allows you to monitor a range of memory addresses
+ for writes. When any code tries to write to the addresses you've
+ monitored, execution will immediately break into the debugger. This
+ can be extremely useful when you know that a certain data structure
+ is being corrupted somewhere in your program, but you don't know
+ where it is happening.
+
+ To set a data breakpoint in the modified emulator, first launch the
+ emulator, then start the debugger in CodeWarrior. In the emulator,
+ choose the "Breakpoints" menu item. A dialog window will pop up;
+ select the "Enabled" check box, then enter a start address and a
+ number of bytes to monitor. The address and number of bytes may be
+ either hex ("0x89abc") or decimal ("12345"). As an example, if the
+ start address is 0x10000 and the number of bytes is 8, then any
+ write to addresses 0x10000 through 0x10007 will break into the
+ CodeWarrior debugger.
+
+ Conditional breakpoints allow you to break when execution reaches a
+ given address, but only when a certain condition is true.
+ CodeWarrior for PalmOS supports conditional breakpoints, but its
+ implementation is so slow as to be practically useless. As I
+ pointed out in an earlier post to the palm-dev-forum list, in the
+ CodeWarrior debugger, each iteration past a conditional breakpoint
+ takes about 0.3 second, so you have to wait for an eternity if you
+ have to iterate hundreds or thousands of times until the break
+ condition is true (as is often the case in debugging).
+
+ The modified emulator allows you to set conditional breakpoints with
+ virtually zero overhead. To set conditional breakpoints, first
+ launch the emulator, then start the CodeWarrior debugger. When you
+ are stopped in the debugger, choose the "Breakpoints" menu item in
+ the emulator. A dialog window will pop up which will allow you to
+ set up to 6 conditional breakpoints. To set a breakpoint, choose a
+ breakpoint slot and press the "Edit" button. A window will pop up
+ where you can enter an address and a condition. The address can be
+ either hex ("0x2468ace2") or decimal. Typically, you will determine
+ the address where you want to break by selecting the "mixed" view in
+ CodeWarrior to see a mix of source and assembly code. The condition
+ you specify must be of the form "<register> <condition> <constant>",
+ where
+
+ <register> is one of the 68000 registers D0...D7 or A0...A7
+ <condition> is ==, !=, <, >, <=, or >=. (Important: for now,
+ all comparisons are UNSIGNED. This means that you can't use
+ a condition such as "D0 < 0", which will always be false).
+ <constant> is a hex or decimal constant
+
+ By choosing the "mixed" view in CodeWarrior, you can see which 68000
+ registers represent which local variables in your program, and so
+ you can construct an appropriate break condition involving a
+ register.
+
+* Exposed Palm IIIx and Palm V support.
+
+* Fixed problem with ROM Transfer on EZ devices. [Yoshiyuki Kubo]
+
+* Relaxed form-object-validation rules to allow for zero-sized
+ gadgets and tables. [Roger Flores]
+
+* Fixed bug in AutoRunAndQuit mechanism where Poser would quit when
+ a sub-launched application would quit, not when the application-of-
+ interest would quit. [Steve Haneman]
+
+* NetLibDmReceive should really work this time. [Doug Morrison]
+
+
+Changes for 2.1d25 (1999-02-16)
+-------------------------------
+* Different method for checking whether or not a library function is
+ implemented. Poser still only checks known (i.e., Palm Computing)
+ libraries, but now instead of using a hardcoded table, it takes
+ advantage of the fact that the "open library" function appears right
+ after the dispatch table. [Tim Wiegman, Adam Hampson]
+
+* (Mac) Added WDEF project to Poser project. Changed the way the
+ outline region is calculated (should be more accurate now).
+
+* Added support for internal faster trap dispatching mechanism. The
+ major effect of this is that Poser can now support non-debug Palm
+ VII ROMs again. [Bob Ebert]
+
+* Added support for Autorun and AutorunAndQuit directories. These
+ directories are like the Autoload directory. Applications in
+ Autorun are loaded, and then one is chosen to be executed (by
+ convention chosen to be the last file in the directory).
+ Applications in AutorunAndQuit are loaded, and then one is chosen to
+ be executed in the same way. When that application quits, Poser
+ quits. If there are files in both Autorun and AutorunAndQuit, the
+ last file in AutorunAndQuit is chosen for execution. The files in
+ those directories can also contain launchable documents such as
+ .PQAs. [Steve Haneman]
+
+* (Windows) Centered the LCD. [Scott Johnson]
+
+* Better logging facilities. Here's what we've got so far:
+
+ - Error Messages: undefined and unimplemented.
+
+ - Warning Messages: If a dialog comes up that can be dismissed by
+ clicking on the Continue button, this option causes the message
+ to be logged. - Misc Gremlin Info: undefined.
+
+ - Assembly Opcodes: unimplemented. Will eventually log assembly-
+ level trace information (registers, PC, opcodes, etc.)
+
+ - Posted events: events entered into the system by calls to
+ EvtAddEventToQueue, EvtAddUniqueEventToQueue,
+ EvtEnqueuePenPoint, and EvtEnqueueKey.
+
+ - Received events: events returned by EvtGetEvent, EvtGetPen, and
+ EvtGetSysEvent,
+
+ - System calls: calls to Palm OS functions.
+
+ - Application calls: unimplemented. Calls to functions in your own
+ application. In order for this to work, the name of the function
+ needs to be stored in memory following the function itself.
+ CodeWarrior supports this convention, gcc currently does not.
+
+ - Serial Activity: serial port being opened and closed, changes in
+ serial port settings.
+
+ - Serial Data: data being transmitted and sent.
+
+ - NetLib Activity: calls to NetLib functions, parameter values and
+ return values.
+
+ - NetLib Data: data being transmitted and sent.
+
+ - ExgMgr Activity: unimplemented. You get the idea...
+
+ - ExgMgr Data: You get the idea...
+
+ - High-level Debugger Activity: messages received from an
+ external debugger and the replies sent back.
+
+ - High-level Debugger data: details of the messages sent back and
+ forth. Not all packets currently display all their data when
+ this mode is turned on.
+
+ - Low-Level Debugger Activity: trace of the low-level mechanisms
+ that receive raw data from external debuggers and the raw data
+ being sent back.
+
+ - Low-Level Debugger Data: dumps of the raw data being sent back and
+ forth.
+
+ These options are presented in a dialog box with two tabs: Normal
+ and Gremlins. The first tab contains options which are active
+ during normal emulator use. The second tab contains options which
+ are active when using Gremlins.
+
+ Along with this new dialog, the Debug Options and New Gremlins
+ dialogs have also been changed. The logging checkboxes have been
+ removed from Debug Options (along with some currently unused
+ checkboxes). The logging checkboxes in the New Gremlins dialog have
+ been replaced with a "Logging Options..." button that brings up the
+ Logging Options dialog. A new checkbox ("Continue Past Warnings")
+ has been added to the New Gremlins dialog that controls what happens
+ when a non-fatal error dialog is displayed; if possible, these error
+ dialogs will automatically be dismissed if this option is checked.
+
+ For performance reasons, all logged information is stored in an
+ internal memory buffer. Additionally, only the most recent
+ information is kept. After a certain threshhold, old information is
+ discarded. The amount of information kept is initially 1Meg, but
+ that can be changed by calling HostSetLogFileSize.
+
+ The in-memory buffer is flushed on the following occassions:
+
+ - The application quits.
+ - An error is displayed.
+ - A new Gremlin is started.
+ - An exception occurs.
+
+ Logged data is written to a file named "Log####.txt", where #### is
+ a number ensuring the file name's uniqueness.
+
+ Contents of the log file are of the form:
+
+ <Time> <Gremlin Event> <Text>
+
+ <Time> is the zero-based time in seconds, where the base is the time
+ of the first event logged.
+
+ <Gremlin Event> is the event sequence number if Gremlins is running.
+ This field is omitted if Gremlins is not running.
+
+ <Text> is the log text. Output is generally one line long, with the
+ major exception being hex dump information.
+
+* Allow more concurrent tailpatches. Previously, there was a fixed
+ number of traps that could be tailpatched at once. Exceeding this
+ limit would cause Poser to abort().
+
+* Allow one particular SecurityLib function to access low-memory.
+ [Gavin Peacock]
+
+* Implemented HostSetLogFileSize. Increased default log size from
+ 128K to 1Meg. [Dan Rowley]
+
+* Support netSocketOptSockNonBlocking in NetLib redirection. Also
+ support the UDP calls (NetLib[Send|Receive](PB) with non-NULL
+ address specifications). With these changes, Windows users can now
+ Network HotSync. [Tilo Christ]
+
+ Here's now (this is for Palm III):
+
+ - Get the Network HotSync files from:
+
+ <http://www.palm.com/support/downloads/netsync.html>
+
+ - Run "nhssetup.exe" to extract "setupex.exe".
+
+ - Run "setupex.exe" to install Network HotSync.
+
+ - Fire up Poser.
+
+ - Install "netsync.prc". There will be one in your ...\Palm
+ Desktop\ <UserName>\Install\ directory or your ...\Palm
+ Desktop\add-on\ directory.
+
+ - Go to the HotSync application.
+
+ - Select the "LANSync Prefs..." menu item.
+
+ - Select the "LANSync" option. Click on "OK".
+
+ - Select the "Primary PC Setup..." menu item.
+
+ - Enter your Primay PC's IP address. You can get this from the
+ HotSync Manager (click on the HotSync icon in the TaskBar,
+ select the "Setup..." menu item, click on the "Network" tab, and
+ click on the "TCP/IP Settings..." button). Click on "OK".
+
+ - Click on the "Select Service" button under the "Modem Sync" icon.
+
+ - Create a new service or modify an existing one. Either way, the
+ result should be a service with the phone number set to "00".
+ Exit that screen.
+
+ - Click on the "Modem Sync" icon and sync as usual.
+
+* (Mac) Additional note on NetLib redirection: currently, support
+ is implemented with the help of the GUSI library. This library is
+ built on top of MacTCP, which doesn't support the settting or
+ getting of socket options. Any call to NetLibSocketOptionGet or Set
+ will result in an error on the Mac. Eventually, emulation will be
+ performed with direct Open Transport calls, and this limitation will
+ go away.
+
+ In the meantime, this limitation affects the ability to Network
+ HotSync from Poser runningon the Mac to HotSync running on a PC.
+
+* Fixed a long-standing 2.1dx bug where the screen would not always
+ reflect the state of the LCD buffer. One way this could happen is
+ if the screen were modified in a strictly high-memory to low-memory
+ order (as happens when a document is scrolled down).
+
+* (Windows) Fixed byteswapping problem in the addresses returned by
+ NetLibGetHostByName. [Pedro Alves]
+
+* The text file dumped by the profiler always used to be named
+ "Profile Results.txt" and would be written to the current default
+ directory. Now the file name is based on the file name used for the
+ binary output and is stored in the same directory as it. This is
+ mostly useful if the output file name is specified by
+ HostProfileDump (). [Steve Haneman]
+
+* While running Gremlins, validate the sizes of various form objects.
+ [Chris Antos] The rules are:
+
+ * frmBitmapObj, frmLineObj, frmFrameObj, frmRectangleObj,
+ frmLabelObj, frmTitleObj, frmPopupObj: Don't care. We don't
+ touch them or look at them.
+ * frmControlObj: if the style is popupTriggerCtl, allow a
+ zero-width object.
+ * frmListObj: if the number of items is zero, allow a zero-height
+ object.
+ * In all other cases, disallow zero-height or zero-width objects,
+ as well as objects completely offscreen.
+
+* (Windows) Added mnemonic keys to the menus and dialogs. [Scott
+ Johnson]
+
+* Adjusted the internal rectangle indicating the bounds of the hard
+ buttons on the case graphics, now that the case graphics have
+ changed. [Horace Ho]
+
+* Enable storage heap write access in our NetLib-redirected version
+ of NetLibDmReceive. [Neil Rhodes]
+
+* Turned back on the checks to see if someone accesses the area from
+ 0x00018000 to 0x00020000. [Adam Dingle]
+
+* Added Japanese color silkscreens (no B&W yet).
+
+
+Changes for 2.1d24 (1999-01-25)
+-------------------------------
+* Yow...time to start updating those copyright statements...
+
+* Fixed performance problems with logging (this really affected
+ Gremlins performance). [Andrew Ball]
+
+* Made small change to heap tracking routines; this change really
+ speeds up overall performance. A lot of performance tuning still
+ needs to be done here. [Scott Johnson]
+
+* NetLib redirection. [Phil Shoemaker, Ron Marianetti]
+
+ Here's the current list of what doesn't yet work:
+
+ Raw sockets (not on the Mac at all, works on Windows only if
+ your version of WinSock supports it).
+
+ PalmOS-specified options:
+ netSocketOptSockNonBlocking
+ netSocketOptSockRequireErrClear
+ netSocketOptSockMultiPktAddr
+
+ BSD sockets options that are not supported by "NetLib redirection"
+ because the underlying WinSock library doesn't support them:
+ netSocketOptTCPMaxSeg
+ netSocketOptIPOptions
+ netSocketOptSockSndLowWater
+ netSocketOptSockRcvLowWater
+ netSocketOptSockSndTimeout
+ netSocketOptSockRcvTimeout
+
+ Timeouts
+
+ NetLibGetMailExchangeByName
+
+ UDP stuff
+
+ Turning NetLib redirection on and off on the fly. It might be
+ safer to change the setting, then quit and restart Poser (or at
+ least reset the ROM).
+
+ MacTCP doesn't appear to timeout if it can't make a connection
+ to a socket on a remote machine that isn't listening on that
+ socket. There may be other cases where MacTCP doesn't timeout
+ or return some other error. In those cases, the PalmOS application
+ will hang. You should be able to press Cmd-. to get out of those
+ situations, causing the patched NetLib to return a user-cancelled
+ error number.
+
+ Comments on how NetLib redirection works: Poser has the ability
+ to intercept process execution at the points where an OS function
+ is called and where the OS function returns. Poser can then
+ execute additional code at these points, and can even skip
+ calling the ROM version at all if it wants. That's what happens
+ with NetLib redirection. The following calls are intercepted
+ and replaced with versions that make the corresponding host-
+ specific Ethernet calls:
+
+ NetLibClose NetLibConnectionRefresh
+ NetLibDmReceive NetLibFinishCloseWait
+ NetLibGetHostByAddr NetLibGetHostByName
+ NetLibGetMailExchangeByName NetLibGetServByName
+ NetLibHandlePowerOff NetLibOpen
+ NetLibOpenConfig NetLibOpenCount
+ NetLibOpenIfCloseWait NetLibReceive
+ NetLibReceivePB NetLibSelect
+ NetLibSend NetLibSendPB
+ NetLibSleep NetLibSocketAccept
+ NetLibSocketAddr NetLibSocketBind
+ NetLibSocketClose NetLibSocketConnect
+ NetLibSocketListen NetLibSocketOpen
+ NetLibSocketOptionGet NetLibSocketOptionSet
+ NetLibSocketShutdown NetLibWake
+
+ Because NetLibOpen (and its cousins) is entirely patched out, the
+ Palm OS version of NetLib never actually gets opened. This means
+ that the remaining, unpatched NetLib calls are made in the context
+ of a closed NetLib. I don't know if this differenc will affect
+ anyone, but it might be good for you to know.
+
+ Comments on Palm VII supprt: Palm VII files are not yet externally
+ available. But Poser is preparing for that day, so when they *are*
+ available:
+
+ Download the prerelease Palm VII rom and the required Debug
+ wireless panel which will configure the emulated OS so that
+ it knows you're not on a wireless device.
+
+ To configure: open the ROM with the Palm OS Emulator, wait
+ until it has completed the boot process, and install the debug
+ wireless panel by dragging the prc onto the running emulator
+ window. Now open the Prefs application and go to the "Wireless"
+ panel. You'll see a box there entitled "wireline ip". Tap on
+ it, clear the existing selection, and enter "207.240.80.136".
+ Finally, open the preferences for the Palm OS Emulator itself
+ (right-mouse click under Windows), and turn on the "Redirect
+ Netlib calls to host TCP/IP" option.
+
+ Now when you use a PQA, it will connect to the web site with
+ your PC's internet connectivity instead of a wireless radio.
+ (Warning: it is much faster that way! Pages will load much
+ more slowly when transmitted over the air.) Also, there may
+ be warnings where the Emulator notices possible bugs in the ROM.
+ Usually these are benign (but indicate the prerelease status of
+ the ROM) - pressing "continue" will usually get you by them.
+
+ You can install PQAs by dragging them onto the Emulator window,
+ or using the Emulator's menu commands. Just make sure you're
+ neither in the Launcher when installing an application, nor
+ running the app you're upgrading. (Installing software while
+ the device is booting is also a bad idea.) The Calculator is
+ a convenient, safe app to be in when installing software.
+
+ Note that if your PC is behind a firewall, you might not be able
+ to connect to our proxy server. Ask your system administrator to
+ enable port 5002 for you.
+
+ If you get an error message along the lines of "no interfaces
+ found: net - 12", that's an indication that you didn't select
+ "Redirect NetLib" in the preferences panel. Getting the error
+ message "wrong socket type" is an indication that you didn't
+ install the DgbWirelessPnl application.
+
+
+* More fixing of semaphore warnings: duh, changing the text of the
+ warning message doesn't change the test itself! [many...]
+
+* Made .prc/.pdb file loading more robust: the contents are now
+ validated before accessing them. This helps against problems
+ like 0x0A's turning into 0x0D's because of network downloading.
+
+* (Windows) Fixed byteswapping problem that would occur when gdb
+ tried to set a breakpoint [Ben Thomas].
+
+* (Mac) Fixed problem with getting 'Could not save the file ""
+ because the file wasn't found' when trying to save a session.
+ [???]
+
+* Palm OS 1.0 support: Gremlins and pen events weren't being
+ inserted into the system because EvtGetSysEvent blocked on
+ SysSemaphoreWait instead of SysEvGroupWait in that version
+ of the OS (we were only patching the later to detect when
+ to insert events into the system). Now I patch both functions.
+ [Andrew Ball, Ken Hancock]
+
+* Set HotSync user name at boot-up. Name specified in preferences.
+ [Richard Ziegelmaier, et al]
+
+* Check for and report for out-of-range access to library functions.
+
+* The workaround for SysAppExit in d22 was hiding the workaround for
+ FindSaveFindStr from d20. Adjusted the tests so that one no
+ longer hides the other. [Matt Disher]
+
+* Exposed Palm VII and Web Clipping support in external release.
+
+* (Windows) Fixed a problem in the mechanism for exchanging debugger
+ information with the Metrowerks debugger. This problem could
+ potentially cause debugger packets to be ignored. However, there's
+ no evidence that this is the cause of the "Failed to connect to
+ remote" problem that some people are still reporting with R5.
+ [Ben Sessoms]
+
+* When handling SysPktRtnNameCmdType packets, force the given address
+ to be even. Otherwise, we'll generate an internal error as we try
+ to walk the function starting at an odd address. [Ben Sessoms]
+
+* Fixed long-standing bug that would crash the New Gremlin dialog if
+ the last item in the list had a ROM-based version and a RAM-based
+ version.
+
+* Sort the items in the New Gremlin dialog case-insensitively.
+
+* Added support for launching applications with documents. [Gavin
+ Peacock]
+
+* Updated bitmaps. [Ken Krugler, Stephen Best]
+
+* Fixed problem with getting a "yadda accessed memory manager data
+ structure" while dumping the results of profiling. [Adam Dingle]
+
+* Removed most (hopefully all) influences of Poser's memory
+ accessing and ROM function calling from the profiling output.
+
+* Fixed the profiler to handle TRAP $F / <dispatch number> sequences
+ where <dispatch number> is not in the range 0xA000-0xAFFF (some
+ development systems leave off the leading "A"). [Adam Dingle]
+
+* Bumped the default number of profiled functions from 20000 to 48K.
+ [Steve Haneman]
+
+
+Changes for 2.1d23 (1998-12-16)
+-------------------------------
+* (Windows) fixed some byteswapping problems with debugger packets.
+ (Actually, put *back* some bugs that I fixed...)
+
+* Re-organized sources.
+
+* Added ability to patch libraries. Started patching out NetLib.
+ Note that there is no actual NetLib redirection in this release.
+
+* Fixed some serial port emulation problems: mirrored UART settings
+ into the host serial port just after the port has been opened, not
+ after the first call to SerSetSettings (there may *not* be a call
+ to SerSetSettings!).
+
+* Generating a profiling report now also produces a text file for
+ use on platforms that can't read the Metrowerks Profile tool
+ file format.
+
+* (Windows) Added profiling configuration.
+
+
+Changes for 2.1d22 (1998-12-07)
+-------------------------------
+* Only warn about MemSemaphore usage on ROMs that themselves hold the
+ memory semaphore correctly. This time for sure! Also only warn
+ when the semaphore has been held for 1 minute (previously, the
+ timeout was 10 milliseconds).
+
+* Completely overhauled serial port emulation. More of the UART is
+ emulated more faithfully.
+
+* If no serial port is selected for emulation pass through and we're
+ not in loopback mode, drop transmitted bytes on the floor.
+
+* If IrDA is using the serial port, drop transmitted bytes on the
+ floor (for now).
+
+* Re: SysAppExit accessing a deleted stack: SysTaskDelete and a whole
+ host of other functions also access the deleted stack until the
+ kernel has a chance to switch to another stack. Much gnashing of
+ teeth was performed until an appropriate alternate heuristic could
+ be found.
+
+* Let PrvCompressedInnerBitBlt access bits outside the allocated
+ buffer.
+
+* (Windows) Fixed problems with Cancelling a ROM download.
+
+* Another attempt at fixing -192 errors at startup.
+
+* (Mac) Fixed problem with opening two windows when starting a session
+ by double-clicking on a ROM file.
+
+* (Mac) Goosed debugger messaging. Previously, an asynchronous
+ callback function would get called when Poser received a packet from
+ the debugger. The callback function would set a boolean and then
+ call a Toolbox function to wake up the application. The next time
+ the application's main-event-loop was entered, the packet would be
+ handled. However, the overhead of waking up the app and waiting for
+ the main-event-loop to be entered was way too high. I now handle
+ the debugger packet immediately in the asynchronous callback
+ function. This means that the debugger packet is handled in the
+ context of the calling application (the external debugger). If
+ Poser were to crash at this point, it would crash the debugger, not
+ Poser. Additionally, we have to be very careful not to allocate any
+ memory from within the callback, as such memory would be allocated
+ from the debugger's heap, not Poser's.
+
+* Changed some of the rules for interacting with an external
+ debugger.
+
+ In order for an external debugger (PalmDebugger, MWDebug, or gdb) to
+ talk with a hardware device, the hardware device has to be
+ listening. There are two things a debugger can talk to: the Debugger
+ socket and the Console socket. These two sockets correspond to the
+ two windows in the PalmDebugger.
+
+ To get the ROM to listen on the Console socket, the developer has to
+ execute shortcut-.2. To get the ROM to listen on the Debugger
+ socket, the device has to cause an exception somehow. Doing
+ something wrong (e.g., access invalid memory, divide by zero, etc.)
+ does this. Executing a DbgBreak also does this, which is what
+ happens when the user executes shortcut-.1. After the exception
+ occurs, the ROM goes into a loop where it listens for and responds
+ to debugger commands.
+
+ Because external debuggers talk directly with Poser and not the ROM
+ when debugging with Poser, there's no need to execute shortcuts or
+ cause exceptions in order to start debugging. Poser is perfectly
+ capable of handling debugger requests, letting the emulated process
+ continue on its merry way.
+
+ However, when dealing with commands sent to the debugger socket,
+ it's very important that the state of the emulated CPU not change.
+ Often several commands are issued, ultimately ending with some
+ command that restarts the emulated CPU. During these exchanges, the
+ debuggers assume that the state of the CPU has not changed since
+ "debug mode" was entered. For this reason, when commands are sent
+ to the Debugger socket:
+
+ - Poser needs to be in "debug mode". That means that it has
+ halted any emulation and is just idling. If commands for
+ the Debugger socket come in and Poser is not in debug mode,
+ the commands are ignored.
+ - The exception to this rule is the "get state" Debugger
+ command. This command is issued when the user types "att"
+ in the Debug window. It indicates that the user wants to
+ enter debug mode for the purpose of setting breakpoints,
+ examine memory, etc. As a courtesey, Poser will enter
+ debug mode when it sees this command.
+
+* Install a 'pose' feature so that applications can tell if they are
+ running under Poser or not.
+
+* Install a 'gdbS' feature when connected via a socket to an external
+ debugger. The existance of this feature causes programs written
+ with prc tools to enter the debugger when they are launched.
+
+* (Windows) Removed a minimum version check that was preventing us
+ from using sockets on Windows '95.
+
+
+Changes for 2.1d21 (1998-11-12)
+-------------------------------
+* Allow for NULL access bug in FldDelete.
+
+* (Windows) Allow for launching of Emulator by double clicking on
+ .psf or .rom files.
+
+* Added back a whole slew of strings accidentally deleted in d20.
+
+
+Changes for 2.1d20 (1998-11-10)
+-------------------------------
+* Support full debugger protocol for latest PalmDebugger (with
+ integrated Poser support).
+
+* Fixed button mapping problems with EZ hardware.
+
+* Added Greg's Ymodem code for downloading ROMs. This includes his
+ fix for high-baud rate downloads.
+
+* Support for higher baud rates.
+
+* Re-establish serial port after Preferences/Properties dialog.
+
+* Allow for access to deleted stack in SysAppExit.
+
+* Allow for bug in NetPrvTaskMain that accesses low-memory.
+
+* Allow for bug in NetPrvSettingSet that reads from a random memory
+ location.
+
+* Tighten up on some inappropriate memory checks (only let some
+ functions get away with murder in older ROMs).
+
+* Removed check for bug in PrvGetBatteryPercent (it's been fixed).
+
+* Changed formatting of time displayed in Gremlins window. Was in
+ seconds, now in hh:mm:ss.
+
+* Revoked Memory Manager privileges for MemCmp, MemMove, and MemSet;
+ they no longer have free run of RAM like other MemMgr functions.
+
+* Allow for bug in FindSaveFindStr which reads off the end of the
+ handle passed to it.
+
+* Similar comments for FntDefineFont. When copying the contents of
+ an old, smaller buffer into a new, larger buffer, it copies the
+ size of the new buffer, causing MemMove to walk off the end of the
+ old buffer.
+
+* Let ScrInit access unallocate memory for when it copies the splash
+ screen from its temporary location to the real LCD buffer.
+
+* Re-enabled code that reports a bug in BackspaceChar, but only for
+ newer ROMs.
+
+* Internal change: Better encapsulation of what Palm OS bugs are
+ fixed in what version.
+
+* Only warn about MemSemaphore usage on ROMs that themselves hold
+ the memory semaphore correctly.
+
+
+Changes for 2.1d19 (1998-10-30)
+-------------------------------
+* (Windows) Fixed problem with trying to auto-reload the previously
+ used .psf file on startup.
+
+* (Windows) Allow the user to click on the close box of the Startup
+ dialog (the one saying New/Open/Download/Exit).
+
+* Fixed two problems with heap management on 2.0 ROMs. First, I was
+ failing to recognize the fact that zero in the size field of a heap
+ header means that the heap is 64K bytes long. Second, I was
+ attempting to access *all* fields of the terminating sentry chunk.
+ This chunk only has a size field; attempts to access subsequent
+ fields may fail if the sentry is at the end of RAM.
+
+
+Changes for 2.1d18 (1998-10-29)
+-------------------------------
+* Disabled Profiling menu items and Transfer ROM menu item until
+ the functionality behind those items can be implemented.
+
+* Added "Dragonball EZ" menu item to device list.
+
+* (Windows) Fixed problem with stale reference to the LCD window after
+ its been closed.
+
+* Fixed problem in MC68EZ328Bank::GetLCDDepth where it would return 4
+ for grayscale mode instead of 2.
+
+* (Mac) Fixed problem getting -192 error on startup with a fresh
+ set of preferences.
+
+
+Changes for 2.1d17 (1998-10-28)
+-------------------------------
+* Fixed bug in Gremlins when logging information; an internal counter
+ would wrap to be negative after a large number of events have been
+ posted.
+
+* Re-laid out Debug Options dialog and hooked up the checkboxes.
+ Disabled the ones that aren't supported yet.
+
+* (Windows) Fixed another "Unhandled exception caught in main" bug:
+ this one would occur when the Poser would try to open a .psf file
+ that no longer existed (the previous cause of this bug occurred
+ when Poser would try loading a .rom file that no longer existed).
+
+* (Windows) Remove old registry entries when found.
+
+* When an error occurs accessing a file, consistantly set the
+ %filename parameter for error messages.
+
+* Added "Log error messages" checkbox to New Gremlin dialog.
+
+* Save Gremlins settings to preferences.
+
+* Fixed bug in meta-memory tracking stuff that would trash the
+ emulator's heap if it was emulating a device with 256K of RAM
+ or less.
+
+* Clear the serial FIFO queues on reset. Fixes a problem with their
+ overflowing and serial port emulation is not turned on (that is,
+ "None" is selected in the Preferences/Properties dialog).
+
+* Fixed problems with trying to use "&string_object[0]" on empty
+ strings. Apparently, there is not necessarily any memory
+ allocated for empty string objects, so attempting to take the
+ address of the string fails.
+
+
+Changes for 2.1d16 (1998-10-22)
+-------------------------------
+* Allow the opening of locked .rom, .psf, .prc, .pdb, and .pqa files.
+
+* Updated TextMgr calls to reflect new (long) parameters.
+
+* Added Autoload facility.
+
+* Fixed problem with trying to wakeup the device (by calling
+ EvtWakeup) when the interrupt level mask was too high.
+
+ (Backed this modification out temporarily. Seems that the ROM can
+ spend a large percentage of its time at this interrupt level if
+ it's not doing anything else useful, preventing the user from
+ clicking on the LCD screen.)
+
+* Conditionalized the code so that Palm VII, Palm V, and Palm IIIx
+ could be included or excluded separately.
+
+* Conditionalized *this* file so that secret stuff can be stripped for
+ external releases.
+
+* Fixed the "Save Screen" functions (I'd commented them out while
+ adding support for lcdPageWidth and lcdPanningOffset registers and
+ forgot to go back and clean up).
+
+
+Changes for 2.1d15 (1998-10-15)
+-------------------------------
+* Bug fix: my wrapper function for TxtGetCharBounds was accidentally
+ calling TxtGetNextChar (copy & paste error).
+
+* Bug fix: the routine that maps a range of "host" memory into
+ "emulated" memory would round the base address down to the nearest
+ multiple of four, but the routine that would reverse the process
+ didn't do the same rounding. This meant that the routine that
+ unmapped would be unable to find the address recorded by the routine
+ that did the mapping, and entries would never get unmapped.
+
+* Bug fix: if Poser reads in a preference setting for a Japanese
+ silkscreen and that version of Poser doesn't support Japanese
+ silkscreens, change the setting. Otherwise we'd get a -192
+ (resource not found) error.
+
+* Relaxed MemSemaphoreReserve/Release testing. Now only track time
+ when "write" parameter is true.
+
+* Bug fix: allow debuggers access to reserved parts of Dragonball
+ memory.
+
+* (Mac) Show errors in a movable modal dialog, allowing the user
+ to switch to the Finder, possibly for the purpose of launching a
+ debugger.
+
+* Allow selection of multiple items in New Gremlins dialog. These
+ items are also reselected when the dialog is re-opened.
+
+* Added HostGremlinNumber, HostGremlinCounter, HostGremlinLimit.
+
+ "The reason I'm asking is that I'd like to log info to figure out
+ what's going wrong with a specific gremlin test case, but since
+ it's pretty far along (e.g. 100000 steps) I only want to start
+ logging when I'm getting close to where I think the problem will
+ occur. The problem occurs after a different number of steps
+ depending on the gremlin seed value, thus I'd like to set my
+ 'start recording' value based on which gremlin is running."
+
+* Added HostLogFile. This function returns a special HostFILE* that
+ can be used by Palm OS applications that want to write to the same
+ file that any Poser facility is writing to. This HostFILE* is
+ special in that it is only open when Poser wants it to be, and is
+ write-only; any HostFxxx functions that attempt to read from
+ HostFILE's will fail when fed this HostFILE*.
+
+ Output occurs only when Poser has turned on logging. If the
+ Palm OS application calls something like HostFPrintF(hostLogFile,
+ "...", ...) and logging is not turned on, the output is discarded.
+
+* Added HostSetLogFileSize. This function sets the maximum amount of
+ text written to the file created by Poser's logging facilities.
+
+* If Gremlins is running and a message needs to be displayed that can
+ be handled by clicking on a Continue button, write that message to
+ a log file instead and implicitly click on the Continue button.
+
+* If Gremlins is running, turn off the facility that causes the user
+ to be warned only once of certain kinds of errors (that is, the
+ error will be logged to the file every time).
+
+* In the logging output file, add a comment that only the last xxxK
+ of information is recorded.
+
+
+Changes for 2.1d14 (1998-10-01)
+-------------------------------
+* Added Japanese silkscreens, and support for selecting them.
+
+* (Mac) Added "None" menu item to serial port menu.
+
+* Added support for lcdPageWidth and lcdPanningOffset registers.
+
+* Fixed bug with power-off (I wasn't allowing HwrSleep to change some
+ low-memory vectors, resulting in a warning dialog).
+
+* Check for and report heap corruptions. Poser walks the heap
+ regularly, usually to sync up its notion of where things are with
+ the Palm OS Memory Manager's. These walks used to be vulnerable to
+ corrupted heaps. Now they should be more robust.
+
+* (Mac) Updated to CodeWarrior Pro 4.
+
+* Instead of patching ErrDisplayFileLineMsg and showing its text in
+ our own dialog, let the ROM version execute. It will eventually
+ call SysFatalAlert, which we patch for the same reason (to show the
+ text in our own dialog with our own buttons).
+
+* Added stack overflow checking. On all opcodes changing the stack
+ pointer (PEA, MOVE, MOVEM, JSR, and any opcode operating on a
+ register with pre-decrement mode), I check the stack pointer to see
+ if it's (a) close to the end of the stack or (b) past the end of the
+ stack. The former gets a warning, the latter gets an error.
+
+* Initialize new RAM to 0xFF (make it look like new flash RAM).
+
+* (Windows) Fixed "Unhandled exception caught in main()" error message.
+ This would show up when the previously-used ROM file could not be
+ found. Now, the (slightly) less enigmatic message "Could not start
+ a new session because the file could not be found" is displayed.
+ More importantly, Poser no longer quits after displaying the message.
+
+* Added check for how long the Memory Manager semaphore was held.
+ Show a warning if held for more than 10 milliseconds.
+
+* Fixed problem with multiple Gremlin Control windows appearing in
+ the windows version. Doh!
+
+* Made the "Release" target an "External Release" target, and added
+ an "Internal Release" target.
+
+* Added support for loading clippings.
+
+* Made a change that should take care of accesses to invalid memory
+ from an external debugger.
+
+
+Changes for 2.1d13 (1998-09-15)
+-------------------------------
+* Fixed bug in heap validation functions; when I extract the *signed*
+ hOffset value, I have to sign extend it from 24-bits to 32-bits.
+
+* Mark more parts of memory as memory manager data structures.
+
+* Support hardware sub-ID for EZ devices.
+
+* Support HwrIdentifyFeatures for 68328 devices.
+
+* Enable flash for Palm V and Palm IIIx.
+
+* Fixed long-standing Gremlins bug that would cause event pushing to
+ stop after a while (the Gremlin mechanism would enqueue and event
+ and then wait for it to be handled; however, in some cases, the
+ event would fail to be enqueued, and the Gremlin mechanism would
+ wait forever for that event to be handled).
+
+* Allow for a bug in SysBinarySearch in pre-3.0 systems that would
+ cause it to pass an invalid pointer to the search callback.
+
+* Added Gremlins Control window (displays gremlin number, current
+ event number, and elapsed time; also contains Stop, Resume, and Step
+ buttons).
+
+* Tweaked Gremlins engine so that doing a Step doesn't reset the
+ "until" value.
+
+* Performance enhancements:
+
+ - Changing some functions to return "int" instead of "bool"
+ resulted in better code generation, leading to a 7% performance
+ boost in my canonical Gremlins test (Gremlin #0, 10000 events
+ on the Memo Pad). (Actually, this was only a win in VC++;
+ CodeWarrior worked better with "bool". Therefore, all of the
+ sources were changed to use "Bool", which is typedeffed to
+ "bool" or "int" depending on the compiler being used.)
+
+ - Putting back an enhancement from Craig's Mac Copilot lead to a
+ 27% performance boost. The idea is to update only the scanlines
+ that are changed since the last screen refresh. Craig did it by
+ carefully comparing the current LCD buffer with a saved version
+ of it. I now do it instead by noting when the LCD buffer is
+ being written to (this is done fairly efficiently via the
+ MetaMemory tracking routines) and remembering the first and last
+ bytes in the LCD buffer that were written to.
+
+* Fixed trap number used in HostControl.h.
+
+* Updated to latest CharEncodingType values from TextMgr.h.
+
+
+Changes for 2.1d12 (1998-09-02)
+-------------------------------
+* EmuTraps -> HostControl.
+
+* Let PrvFindMemoryLeaks walk the heap.
+
+* Added HostGetEnv.
+
+
+Changes for 2.1d11 (1998-08-31)
+-------------------------------
+* Added support for AMD flash RAM.
+
+* (Windows) Fixed support for external debugging.
+
+* (Windows) Display dialog if an exception is caught in WinMain.
+
+* (Windows) Fixed the way the Dragonball(EZ) registers were
+ initialized. After things got going, the registers were OK, but the
+ initial values on little-endian machines was completely bogus.
+
+* (Mac) Updated creator resource text.
+
+* Totally revamped the way memory access checking is performed. In
+ addition to detecting access to low-memory, system globals, the
+ screen buffer and Dragonball(EZ) registers, I validate access to the
+ dynamic heap. Now, only the Memory Manager can fiddle with chunk
+ headers and trailers, free chunks, and unlocked chunks. For the time
+ being, low-stack access is no longer detected, though this feature
+ will return. Eventually, we should also be able to detect access to
+ uninitialized memory.
+
+* Updated to latest sysFtrNumXXX values.
+
+* Fixed test for Intl Mgr in gremlins.
+
+* Test for NULL in stub Intl Mgr functions.
+
+* I now calibrate the pen before running a gremlin. This is
+ necessary for consistant results between different runs across
+ boots.
+
+* Fixed error reporting problem where previous messages reported in
+ dialogs would inhibit other messages from appearing (that is, the
+ attempt to display a second message would end up showing the first
+ error message again).
+
+* Handle errant accesses to Dragonball space past the end of the last
+ defined register.
+
+* Check for and report unimplemented traps. This check detects
+ attempts to call functions that are off the end of the trap table as
+ well as calls to SysUnimplemented.
+
+* Internal change: consolidated more error handling in the Errors
+ class. Cleaned up the Errors interface a little bit.
+
+* Added temp hack to let PrvGetBatteryPercent read off the end of an
+ allocated chunk of memory.
+
+
+Changes for 2.1d10 (1998-08-18)
+-------------------------------
+* Display correct error message if a low-stack access is performed (I
+ was previously re-using the "screen buffer access" message).
+
+* Low-memory access by the ROM was previously allowed up until
+ UIInitialize was called. That's been changed to TimInit.
+
+* Consolidated some "device" menu items in the New Session dialog,
+ and added a new device.
+
+* Per Steve and Roger, changed some function names in EmuTraps.h.
+
+* Added Control Panels to the list of applications in the New Gremlin
+ dialog box.
+
+* Added support for DbgMessage.
+
+* Internal change: Roger Flores Memorial Constant Eradication. Got
+ rid of a lot of constants in EmuTraps.cpp and TrapPatches.cpp. These
+ constants were used to fetch parameters from the emulated stack
+ pushed on there by emulated code. I now define structs that
+ describe the stack contents and use those (with the offsetof macro)
+ to get the values. In addition to the obvious one, another
+ advantage is that the macros can now determine the _size_ of the
+ parameters and call get_long, get_word, or get_byte accordingly.
+
+* Rolled in more IK/Gremlin changes for Ken.
+
+* Double-clicking on an app in the New Gremlin dialog will implicitly
+ click on the OK button.
+
+* (Mac) Support Cmd-D in the "Save this file?" dialog (you guys owe
+ me!)
+
+* Mapped some internal error numbers to error strings.
+
+* Re-establish the interrupt state of any pressed buttons after a
+ reset. This allows you to press the Power key and Cmd/Ctrl-R,
+ resulting in a Hard Reset.
+
+* Asking for the 'irda' ROM token will now always fail (at least,
+ until we can get some IrDA support implemented). NOTE: the ROM
+ calls HwrGetROMToken directly, which means that it will not see the
+ effect of this patch.
+
+* Internal change: Platform::DisposeMemory now takes a reference to a
+ pointer so that it can set that pointer to NULL.
+
+* Use Platform::AllocateMemory and Platform::DisposeMemory in the
+ profiling code, so that it can use temp memory on the Mac.
+
+* EmuProfileDump now uses the name passed in to it. If NULL is
+ passed in, a default name ("Profile Results") is used.
+
+* Started on checking memory accesses to the dynamic heap that are
+ outside of allocated memory chunks. Not activated yet because (a)
+ it's too slow and (b) the hueristics aren't quite right.
+
+* (Windows) Fixed bug with not reporting errors that occurred
+ while initializing the emulator. Now you're notified if the serial
+ port you've specified in the Properties dialog is busy.
+
+* (Windows) Made the example in the previous bullet a warning,
+ not a fatal error.
+
+
+Changes for 2.1d9 (1998-08-04)
+------------------------------
+* (Mac) Fixed problem where the emulator would attempt to save the RAM
+ file with no name if "Save Always" were selected, the user chose
+ Quit from the File menu, and the RAM file was new (i.e., had never
+ been saved before).
+
+* Prevent the system from _reading_ low-memory if it's (a) not
+ sleeping or dozing, (b) fully booted, and (c) not handling an
+ interrupt.
+
+* Hooked up "Fill New Blocks" and "Fill Disposed Blocks".
+
+* Minor optimizations to DRAM_Bank accessors.
+
+* Rolled in Ron's changes for finding a function's name.
+
+* Detect and report accesses to the space below the stack pointer and
+ above the low-end of the stack. Note that there is no checkbox in
+ "Debug Options" for this, but performance timing shows that there is
+ very low overhead for this check (less than .1%).
+
+ IMPLEMENTATION NOTE: detecting accesses to the unused parts of the
+ stack obviously entail knowing where the stack is. This information
+ is gleaned from the SysAppInfoType block when the application is
+ launched. However, there's no really good way to hook into the
+ launch process. There are advantages and disadvantages to every
+ approach, but the one used here is to hook into SysAppStartup and
+ SysAppExit. This works for applications that use the standard
+ runtime startup code, but applications are not guaranteed to use
+ that standard code. Hopefully, the percentage of such applications
+ is low.
+
+ Additionally, SysAppStartup and SysAppExit are called under
+ circumstances other than starting up the application. For instance,
+ they are called when action codes are sent to each application. To
+ differentiate the two, we ignore all calls to SysAppStartup that
+ don't contain sysAppLaunchCmdNormalLaunch in the cmd field of the
+ SysAppInfoType block.
+
+* Hooked up "Clean Stack" check box. This option was originally
+ defined to overwrite the parts of the stack that were freed up by an
+ UNLK or RTS opcode in an attempt to detect accesses to those ranges
+ of memory. Since that's now handled by the previous "*", "Clean
+ Stack" now means that we initialize the part of the stack reserved
+ by LINK opcodes, thus initializing local variables to well-defined
+ bad values.
+
+* Fixed bug that occurred when setting a breakpoint on an opcode just
+ after a call to a system function that was tailpatched by the
+ emulator.
+
+
+Changes for 2.1d8 (1998-07-29)
+------------------------------
+* EmuGrmIsRunning (and SysGremlins) FINALLY returns a correct value
+ instead of just returning "true" all the time.
+
+* Implemented EmuDmLoadFile and EmuDmSaveFile.
+
+* EmuDmSaveFile now takes a card number as the second parameter.
+
+* Added parameter checking to all EmuXXX functions. Functions that
+ return EmuErrs will return emuErrInvalidParameter. StdIO functions
+ return error values according to the ANSI/ISO standard, and will set
+ errno to emuErrInvalidParameter (note that functions that alter the
+ return values of ferror and/or feof will NOT affect those value,
+ which is DIFFERENT from the standard).
+
+* Fixed bug when setting the current time on startup. This bug would
+ cause a crash on new Palm V ROMs.
+
+* Fixed bug with new Palm V ROMs when they tried to identify how much
+ memory was on the "device".
+
+* (Windows) Fixed problem where clicking OK in the Properties dialog
+ would crash the emulator under Windows 95 (and could possibly crash
+ Windows 95, too!).
+
+* (Mac) Fixed problem where the serial port name would get lost,
+ prohibiting the emulator from being able to open the serial port.
+
+
+Changes for 2.1d7 (1998-07-27)
+------------------------------
+* (Mac) Don't feed the ROM mouse/pen events if we've turned off
+ emulator execution at idle time. This prevents problems if a dialog
+ comes up while tracking the mouse/pen.
+
+* Fixed long-standing bug from Mac Copilot 1.3 days. The functions
+ GetRegisters and SetRegisters can be used to save and restore the
+ CPU registers. The emulator used those functions for just that
+ purpose when it would call ROM functions as subroutines. However,
+ the status register was not faithfully saved, which meant that it
+ was not always put back the way it was found. Since status bits
+ would then occassionally change spontaneously out from under the
+ emulated process, things would occassionally go "haywire" (that's a
+ technical term).
+
+* Value returned by EmuHostGetVersion is now based on the
+ application's version resource instead of being hard-coded.
+
+* (Mac) Save window position.
+
+* Implemented EmuHostIsSelectorImplemented.
+
+* Holding down the Ctrl key while booting/resetting will stop the ROM
+ at the start of the Big ROM by using a temporary breakpoint.
+
+
+Changes for 2.1d6 (1998-07-23)
+------------------------------
+* Changed way emulated apps called host functions. Those functions
+ used to be called by invoking TRAP $E. Now we latch onto the
+ SysGremlins trap number.
+
+* Extended set of host functions.
+
+* Zap some card header fields to say that we don't emulate flash RAM.
+
+* Fixed problem with profiling.
+
+* (Mac) Fixed an execution path where an untyped ROM file wasn't
+ getting its type set.
+
+* Fixed problem with stopping on A-Trap breaks.
+
+
+Changes for 2.1d5 (1998-07-21)
+------------------------------
+* (Mac) added version that does profiling.
+
+* Fixed loading of "whole" ROMs (those with Big ROMs and Small ROMs).
+
+* Fixed loading of .pdb files that have an AppInfo block but no
+ records.
+
+
+Changes for 2.1d4 (1998-07-20)
+------------------------------
+* (Mac) turned Open and Install menu items into hierarchical menus.
+
+* Fixed bugs with saving and loading session files.
+
+* (Mac) turned Appearance Manager classes back on when running on a
+ sufficient machine (I'd accidentally left the application using the
+ GA classes even when AM was available).
+
+* (Mac) create the Debug Options window invisibly; reduces flickering
+ when opened.
+
+* Converted over to using the cross-platform classes FileReference
+ (reference to and unopened file) and FileHandle (reference to an
+ opened file). These classes allow more platform-independent code
+ (such as the preferences code, which used to deal with Aliases on
+ the Mac and file paths on Windows).
+
+* Overhauled error/exception handling/reporting. I now use a
+ consistant approach to detecting, handling, and reporting errors.
+
+* Rewrote the ROM image loading function. ROM images consist of two
+ parts: a Big ROM and a Small ROM. The ROM image file always
+ contains a Big ROM part, but not always a Small ROM part. However,
+ the Small ROM part is optional and can be dummied up if necessary.
+ The original version of the ROM image loader needed to load in the
+ ROM image file once, determine if the Small ROM was included, and
+ start over if it wasn't. The new ROM image loader is smarter,
+ reading in just the parts it needs to determine if the Small ROM is
+ there or not. Only after that does read in the full ROM file.
+
+* Put more strings in resources. Most, but not all, are now done.
+
+* Added StdIO wrappers (see EmuTraps.h).
+
+
+Changes for 2.1d3 (1998-07-07)
+------------------------------
+* Added progress bars when loading .prc and .pdb files.
+
+* Added support for drag and drop.
+
+* Now close previous session before opening the next.
+
+* (Mac) Added StandardGetFile file filter to allow files that start
+ with "rom." or end with ".rom" or " rom", but that don't have the
+ right file type.
+
+* Updated to latest EZ ROM header files (as of 7/6/98).
+
+* Update the low-memory checksum if low-memory is altered by an
+ external debugger.
+
+* Fixed long-standing bug that would corrupt ROMs when switching from
+ one to another. Since you couldn't do this on Windows in 2.0, you'd
+ only see it in the Mac 2.0 version.
+
+* When creating the preferences for the first time, set the amount of
+ RAM displayed in the New Configuration dialog to 1Meg.
+
+* (Mac) Allocate large chunks of memory from temp mem.
+
+
+Changes for 2.1d2 (1998-07-02)
+------------------------------
+* Revamped startup sequence. From the ERS:
+
+ If the application is started by double-clicking on its icon, it
+ will attempt to perform some appropriate startup action.
+
+ * If the user had saved a session document the previous time the
+ emulator had been run, the emulator will attempt to reload that
+ document.
+
+ * If the user created a new session document during the previous
+ session but didn't save that document, the emulator will create
+ a document with the same settings.
+
+ * If either of those attempts fails (for instance, the previously
+ used session document or ROM file cannot be found), or this is the
+ first time the user has used the emulator, or the user holds down
+ the Caps Lock key while starting the emulator, the user is
+ presented with a "New Configuration" dialog box. The user uses
+ this dialog box to specify a new hardware/RAM/ROM configuration
+ from which a new document is created.
+
+ If the user double-clicks on an emulator document icon, the emulator
+ attempts to restore the session recorded in that file. This attempt
+ may fail if the ROM image for the session can no longer be found. In
+ that case, the session document can no longer be used; session
+ documents can only be used in conjunction with the exact same ROM
+ image that created them.
+
+ If the user double-clicks on a ROM image icon, the emulator
+ presents the user with the "New Configuration" dialog box with the
+ selected ROM file entered into the ROM File text slot.
+
+* Brought Mac and Windows versions in sync with each other.
+
+* IMPORTANT NOTE: "RAM" files created by previous versions of the
+ emulator are no longer supported. There are two reasons for this.
+ First, they didn't contain enough information that today's session
+ files need (such as the associated ROM file name, or the device type
+ to emulate). Second, ".ram" is the extension for Real Audio Media
+ files. Therefore, the emulator now reads and writes ".psf" (Palm
+ Session File) files.
+
+* Added Registry information so that Emulator files have the right
+ description next to their names.
+
+
+Changes for 2.1d1 (1998-06-22)
+------------------------------
+* Updated to latest UAE.
+
+* (Mac) Updated to CodeWarrior Pro 3. (Requires "MW C/C++ PPC"
+ from May 19th or later.)
+
+* Removed 68K and FAT versions.
+
+* New menu organization.
+
+* More emphasis on documents, rather than ROM image files.
+
+* Lots of internal changes:
+
+ - RAM_ROM broken out into many smaller files.
+
+ - Lots of small performance tweaks.
+
+ - More strings moved to resources.
+
+ - Names of system functions are fetched directly from the ROM
+ instead of being hardcoded in StringData.cpp.
+
+* Added DragonballEZ support.
+
+* (Mac) Added white screen.
+
+* New Preferences/Properties... and Debug Options... dialogs.
+
+* New startup dialog for Windows (for when it needs help starting
+ up).
+
+* Fixed the bug where you couldn't enter typed characters if there
+ wasn't a blinking insertion point.
+
+
+Changes for 2.0b3 (1998-06-02)
+------------------------------
+* Windows only: Added Greg's nifty Hyperlink controls to the About box.
+
+* Added Keith's Palm OS Emulator article from HHSJ.
+
+* Windows only: Added Greg's fixes to the serial emulation routines.
+
+* Fixed Headpatch::SysGremlins bug where it would read garbage from
+ the stack when trying to get the selector parameter.
+
+* Got A-Trap breaks working ("atb" from the PalmDebugger).
+
+* Windows only: bumped number of recently loaded application from
+ five to nine.
+
+* Fixed 1.0 ROM compatibility problem: the emulator was trying to call
+ a function introduced in Palm OS 2.0 (PrefSetPreference).
+
+
+Changes for 2.0b2 (1998-05-25)
+------------------------------
+* Windows only: Fixed bug that would zap the version number in the
+ system preferences when attempting to set the timeout value to be
+ infinite.
+
+* Fixed bug that would cause the emulator try to access invalid memory
+ if the emulated app tries to access invalid memory.
+
+* If an exception occurs that an external debugger should handle and
+ there is no external debugger, instead show a dialog that reports
+ the problem and forces the user to reset.
+
+* When getting application version string, look for ID's 1 and 1000.
+
+* Windows only: Fixed bug that would leave a debugger-related messaging
+ event object signalled if there were no external debugger.
+
+
+Changes for 2.0b1 (1998-05-20)
+------------------------------
+* Prevent the device from ever going to sleep. Letting it go to sleep
+ is only annoying, and doesn't accomplish anything. You can make the
+ device go to sleep by setting the timeout value in the General
+ Preference panel, but that setting will get reset back to "never" on
+ any reset.
+
+* Mac only: Fixed problem that would cause the emulator to hang if
+ you tried to open a console window from within MWDebug.
+
+* Got alarms working.
+
+* Mac only: Wasn't doing a "weak import" of AppearanceLib in non-debug
+ version.
+
+* With regards to a change in 2.0d8, it's OK to load an application that
+ already exists in ROM. The RAM-based version will override the one
+ that's in ROM.
+
+
+Changes for 2.0d9 (1998-05-13)
+------------------------------
+* The handling of DbgBreak was broken.
+
+* Allow application to resume after ErrDisplayFileLineMessage. This
+ is handy in cases where you're using ErrNonFatalDisplayIf to display
+ warning messages and it's OK for the application to continue
+ execution.
+
+* Accidentally turned off checksumming of post-2.0 ROMs; turned it
+ back on.
+
+* Windows only: there was supposed to be a feature whereby holding
+ down the caps-lock key when starting the emulator would cause it to
+ bring up a Download/Browse/Quit dialog box. However, the dialog box
+ would actually come up if the caps-lock key had ever been toggled
+ since the last time the emulator had been executed. Fixed.
+
+* Selecting "Gremlin/New..." while a gremlin is currently running
+ will now switch to the new gremlin.
+
+* Fixed error message to say RAM instead of ROM when saving a RAM
+ image file, and added an exception handler to deal with the ensuing
+ thrown exception.
+
+
+Changes for 2.0d8 (1998-05-07)
+------------------------------
+* Added Greg's Copilot article from HHSJ.
+
+* Added updates to Guide.html from Roger.
+
+* Removed support for the 2.0 Debug ROM that offset the low-memory
+ globals byte four bytes. There were problems with that ROM that
+ would cause it to crash.
+
+* Gremlins now latches into KeyCurrentState in order to randomly set
+ the bits so that applications can respond to them.
+
+* The patched versions of SysFatalAlert and ErrDisplayFileLineMsg now
+ display dialogs containing "Debug" and "Reset" buttons. Clicking on
+ "Debug" will simulate a bus error, which an external debugger will
+ catch. Clicking on "Reset" is the same as selecting the Reset menu
+ item.
+
+ NOTE: currently, clicking on the "Debug" button when there's no external
+ debugger running will result in the ROM attempting to handle the
+ simulated bus error. If the ROM is a Debug ROM, it will attempt to
+ contact a debugger over the seial port. Since there is probably no
+ such debugger listening on the serial port, the emulator will appear
+ to hang with a blank screen. Selecting the Reset menu item will
+ restart the ROM.
+
+* Failures reported via SysFatalAlert and ErrDisplayFileLineMsg
+ during application execution have more info for users to report.
+ The dialog has text along the lines of:
+
+ SubHunt 2.0 has failed while running Gremlin 2 at 20,000 events.
+ SubHunt complains "SubHunt.c: Line 100: Score too good." If
+ this is the latest version of SubHunt, please report this to the
+ application author.
+
+ or:
+
+ SubHunt 2.0 has failed. PalmOS complains "Window.c: Line 100:
+ Invalid Window." If this is the latest version of SubHunt,
+ please report this to the application author.
+
+ NOTE: currently no effort is made to determine if the application or
+ the PalmOS is generating the message. This shortcoming will be
+ addressed in a future version.
+
+* Use application name from 'tAIN' resource when generating the list
+ of applications for the New Gremlin dialog box.
+
+* Reduced the 10% random pen tap chance in Gremlins to 2% (per
+ Roger's recommendation).
+
+* Internal change: added "TrapIndex" inline function for converting a
+ trap number (0xA000) to an index that can be used with the trap
+ table. Standardized on its use all over. This function converts by
+ merely masking off the upper byte (which mirrors what the ROM does)
+ instead of subtracting "sysTrapBase" from trap numbers (which fails
+ because some applications appear to use trap numbers that don't have
+ "A" in their upper nybble).
+
+* Internal change: we patch ROM system functions. We also call ROM
+ system functions. Now, whenever we call a ROM system function, any
+ trap patches made to that function are called (they didn't used to
+ be).
+
+* Fixed emulator/debugger communications bug that occurred when one
+ would quit and then restart (needed to refresh -- not just flush --
+ the handle to the other guy's window). (Windows only)
+
+* After the UI has been initialized, prevent even the ROM from
+ writing to low-memory (except from HwrSleep, which patches out the
+ exception vectors).
+
+* When trying to load an application that's already in ROM, warn with
+ a specific error message instead of a generic one.
+
+
+Changes for 2.0d7 (1998-04-27)
+------------------------------
+* Gremlins now works better with "ill-formed" forms (forms with no
+ "live" objects in them). Gremlins will also now generate random
+ taps 10% of the time instead of always trying to target form
+ objects.
+
+* Turn off Gremlins on a reset or fatal system error.
+
+* Only the last 128K of Gremlins logging text will now be written to
+ the logging file.
+
+* Added "Debug" button to the "Application so-and-so just made an
+ invalid memory access" dialog. Clicking on this button emulates a
+ bus error. If an external debugger is running, it will be notified
+ of this bus error. If not, the emulated ROM will take over,
+ displaying a Fatal Error dialog.
+
+* Fixed a bug where the emulator itself would cause a "The current
+ application just accessed Palm OS Globals ..." to appear after
+ downloading an application via MWDebug.
+
+
+Changes for 2.0d6 (1998-04-22)
+------------------------------
+* Added ROM Transfer project (for Mac).
+
+* Added Docs folder.
+
+* Added Plugins folder containing MWDebug plugins.
+
+* Tweaks to PCH file generation for CW Pro 3.
+
+* Added HotSync to Mac side.
+
+ IMPORTANT: For both versions of the Emulator, HotSyncing has only
+ been tested between two machines (in both cases, between a Mac and a
+ PC). I don't know what performance is like when both the emulator
+ and HotSync are running on the same machine.
+
+* Now enable and disable Gremlins menu items in WinEmulator.
+
+* Fixed bug in ROM Transfer.prc which would cause it to crash on Palm
+ III's.
+
+* Fixed some bugs in RAM file management in Mac version.
+
+
+Changes for 2.0d5 (1998-04-17)
+------------------------------
+* Checksum the ROMs when they're loaded. This checksum is used to (a)
+ validate the ROM contents (for pre-3.0 ROMs, the checksum is checked
+ against a hard-coded list of ROM checksums, for 3.0 ROMs and later,
+ the checksum is checked against the checksum in the ROM header) and
+ (b) determine if we're running the 2.0 debug ROM, which needs
+ special hacks activated in order to run.
+
+* Allow *.* patterns when loading ROM and application files.
+
+* Support serial port emulation in WinEmulator (not in Mac, yet).
+
+* Added method for applications to call the emulator (see
+ EmuTraps.h). Note that there currently is no method to see at
+ runtime if an application is running under the emulator or not.
+
+* Tweaks to get Mac version to build under CWP R2 with CW4POS R4
+ installed in it.
+
+* Backed out checksumming of pre-3.0 ROMs until I get get an accurate
+ set of checksum numbers.
+
+
+Changes for 2.0d4 (1998-04-09)
+------------------------------
+* Reset auto-off timer when processing debugger packets.
+
+* Changed way tailpatches are implemented. I used to set the return
+ address of a system function I was tailpatching to point to a TRAP
+ $E opcode (saving the original return address in an array in the
+ emulator). This approach has the advantage of not modifying any
+ opcodes in memory, and handles recursive system functions very well.
+ Sadly, the critical flaw in this approach is that some operations
+ need the real return address to be on the stack. For instance, the
+ TRAP $F handler (TrapDispatcher) in the ROM looks at the return
+ address so that it can look up the $Axxx function selector.
+ Therefore, the approach I now take is to write a TRAP $E into memory
+ after the TRAP $F / $Axxx sequence, saving the overwritten opcode in
+ a table. Recursive functions are handled by incrementing and
+ decrementing a counter associated with that memory location. When
+ the counter gets back down to zero, the opcode is restored.
+
+* Added preliminary profiling stuff. Still disabled at this point.
+
+* Don't let the user enter pen and keyboard events if the CPU is
+ stopped (for example, when it's in the debugger).
+
+* Don't run RPC commands from the debugger in TRACE mode (that is,
+ run the commands, but turn trace mode off, first).
+
+* Respond better to a SysReset message from the debugger.
+
+* Remove tailpatch opcode when the CPU is reset.
+
+* In WinEmulator, restart the CPU after a screenshot only if it was
+ running before we took the screenshot.
+
+* Fixed problems with synchronization between the UI thread and the
+ CPU thread. One way to trip up over the bug was to run Gremlins and
+ at the same time click like crazy on the screen or hardware buttons.
+ After a while, you'd get the dreaded "ATrap::DoCall returned and
+ exception" dialog box.
+
+* Fixed Gremlins bug that would put it into an infinite loop if the
+ top form had only frmBitmapObj, frmLineObj, frmFrameObj,
+ frmRectangleObj, frmLabelObj, frmTitleObj, and/or frmPopupObj
+ objects in it. Games like SubHunt, HardBall, and Reptoids are
+ examples of programs with such forms.
+
+* Changed the low-level mechanism for handling exceptions and
+ entering the debugger. With the old way, an exception would cause
+ the main CPU loop to exit before the debugger was notified about the
+ exception. But if there were no external debugger to notify, there
+ was no way to cleanly restart the CPU loop in order to have the
+ emulated ROM handle the exception (either by trying to connect to a
+ serial debugger, or by showing a fatal error dialog). Now, the
+ attempt to contact an external debugger is made before exiting the
+ CPU loop. If the attempt succeeds, the CPU loop is exited. If the
+ attempt fails, the normal exception handling process takes over
+ (i.e., the appropriate vector from the low- memory exception table
+ is loaded into the PC and execution continues).
+
+* Added support for 2.0.2 Debug ROMs (added minimal support for 68681
+ serial access and account for different low-memory variable
+ locations).
+
+* Removed support for ROM files with the pattern "ROM *". This
+ pattern also matches the "ROM Transfer.prc" application, causing the
+ emulator to try loading it if there are no other candicates.
+
+* For MacEmulator, save RAM files with the type '(Pi)RAM' and ROM
+ files with the type '(Pi)ROM'. Also, if untyped files are accessed
+ as RAM or ROM files, they are changed to have the appropriate type.
+
+* Restarting and stepping of Gremlins in WinEmulator more reliable.
+
+* Better warning messages for applications that:
+
+ - Access low-memory directly
+ - Access system global variables directly
+ - Access the screen directly
+ - Access Dragonball registers directly
+
+
+Changes for 2.0d3 (1998-03-30)
+------------------------------
+* Lots of internal changes:
+
+ - Names changed from Foo_Bar format to Foo::Bar format (where Bar
+ is a static member function of the Foo class). This change
+ makes it easier to look things up in a class browser.
+
+ - Handling of memory access errors codified. All accesses are
+ checked; any errors are reported through bottleneck functions;
+ all accesses can be turned on/off with compile-time and/or
+ runtime switches; added CEnableFullAccess class that allows
+ internal functions full access to memory (i.e., turns off memory
+ access checking) so that we can do things like set breakpoints
+ in ROM.
+
+ - Added Palm copyrights to all files.
+
+ - Standardized on PowerPlant-style function header comments.
+
+ - Removed all mention of Pilot and Pilot-derivatives.
+
+ - Untemplatized some functions in UAE_Utils that didn't need to
+ be templates.
+
+ - Sped up uae_memset by using long-word access.
+
+ - Changed way tail patches are implemented. Previously, I'd write
+ a TRAP $E opcode into memory after the TRAP $F/Axxx instruction
+ sequence that would invoke the trap. The problems with this
+ approach is that (a) this wouldn't break on all returns from the
+ function if it called itself recursively, and (b) it modified
+ memory in a way that would need to be reversed on selected
+ occassions (e.g., when we entered the debugger, or when RAM was
+ saved to disk). Instead, when a trap function is called that I
+ wish to tail patch, I modify the return address from the
+ function in such a way that I get control when the function
+ exits (I save the old return address and replace it with a
+ pointer to a TRAP $E opcode, which leads to a CPU exception
+ which I catch in Software::ProcessException).
+
+ - Patched calls to SysDoze and SysSleep so we better know the
+ state of the ROM/CPU. We don't actually use this information,
+ yet.
+
+ - Centralized all compile-time pre-processor symbols into
+ Switches.h.
+
+ - Centralized all byteswapping into Byteswapping.h/.cpp. Used a
+ templatized Canonical() function on the Mac so that Canonical is
+ zero-overhead no matter what type it's called with.
+
+ - Added internal diagnostic logging functions.
+
+ - Lots of timing tests to optimize memory access and core CPU
+ emulation loop.
+
+ - Committed to "word-swapped" memory layout in x86-compatible
+ systems. Removed experimental alternative memory layout code.
+ Look for WORDSWAP_MEMORY symbol for areas that are byte-order
+ sensitive.
+
+* Fixed some bugs with external debugger hooks.
+
+ - Now support the same notion of "sockets" as the SerialLinkMgr.
+
+ - On some entries into the debugger, the PC would incorrectly be
+ adjusted to point 2 bytes before the instruction causing the
+ debugger entry instead of pointing right at the instruction.
+
+ - Finally added debugger hooks to WinEmulator (missing
+ functionality's considered a "bug", right?).
+
+* Fixed bug where UAE would allocate a significant chunk of memory and
+ then try using it without first checking that the allocation attempt
+ succeeded. This would result in the Mac emulator freezing on startup
+ when emulator a 4Meg device.
+
+* Fixed ROM Transfer.prc to download Palm III ROMs. Updated Mac
+ "Download ROM" command to work with larger ROMs. Added "Download
+ ROM" to Windows emulator.
+
+* On startup, if WinEmulator can't find a ROM, it will ask you to
+ find one or download one.
+
+* On startup, if the capslock key is down, WinEmulator will _always_
+ bring up the dialog asking you to find a ROM file or download one.
+
+* Removed "Backlight" and "Enter debugger on startup" properties from
+ WinEmulator.
+
+* When looking for a ROM file, Emulator use the following search
+ order:
+
+ - The file you've explicitly specified in Properties (WinEmulator only).
+ - The first file in the Emulator directory ending with ".ROM"
+ - The first file in the Emulator directory ending with " ROM"
+ - The first file in the Emulator directory starting with "ROM."
+ - The first file in the Emulator directory starting with "ROM "
+
+* Fixed problem where mouse clicking wasn't working with 1.0 ROMs. I'm
+ still not sure what the root of the problem is, but I've added a
+ check for 1.0 ROMs and implemented a workaround.
+
+* In WinEmulator, RAM image is automatically saved to and read from a
+ file based on the name of the ROM being used and the RAM size
+ requested. The name of the RAM file is "<ROM file>.<RAM size>.RAM".
+ In other words, the old Windows Copilot functionality is back (it
+ was temporarily removed during the Grand Code Unification).
+
+ The format of this RAM image file is a little different, however.
+ There are chunks of data in this file, each tagged with an ID and a
+ chunk size. For now, the only defined chunk is 'ram '. In the
+ future, there will be chunks for register state, associated ROM
+ version, etc.
+
+ In MacEmulator, the file saving operation remains the same as in Mac
+ Copilot, but the file format is the same as in WinEmulator.
+
+* Switched to new case graphics.
+
+
+Changes for 2.0d2 (1998-03-04)
+------------------------------
+* Fixed MacEmulator bug when switching between 1x and 2x screen
+ sizes.
+
+* Fixed bug where loading an application would smash 4 random bytes
+ of memory.
+
+* Sped up emulation on the Mac by 20% by streamlining some
+ Mac-specific operations.
+
+* Sped up core emulation loop on both platforms by moving some
+ not-oft-used functionality into some subroutines, thus simplifying
+ the core loop.
+
+* Added hooks for external debugger.
+
+* Made Gremlins deterministic.
+
+* Ensured Gremlins did the same thing on both Mac and Windows.
+
+
+Changes for 2.0d1
+-----------------
+* Support for Palm OS 3.0:
+
+ - memChunk headers changed, so reliance on their format when
+ loading applications has been removed.
+
+ - More complete support for Dragonball registers.
+
+ - Allow for 96K and 128K dynamic heaps.
+
+* Common source code base.
+
+* Refitted with latest UAE sources.
+
+* Can load .prc files larger than 64K.
+
+* Windows version is much smaller.
+
+* Mac version is much bigger (it's a FAT binary).
+
+* Removed built-in debugger.
+
+* Support grayscale mode.
+
+* Now emulates hardware method for turning on backlighting (holding
+ down the power key). Properties option is no longer needed.
+
+* Added screen shot command.
+
+* Added Gremlins. (Note that user input (typing, mousing) is disabled
+ while Gremlins is running due to the incompatible ways in which they
+ enter their events.)
+
+* Set the Palm OS date on startup.
+
+* Trap dispatcher is now run as native code instead of being
+ emulated. This results in about a 10 - 12% speedup.
+
+* Auto-calibrate the pen on startup; no more digitizer screen.
+
+* InternetConfig-savvy About box on the Mac. Panel-savvy About box on
+ Windows.
+
+* Gremlins can now confine itself to a single application.
+
+* Emulate MemSet, MemMove, and RctPtInRectangle with native code for
+ 15% performance increase.
+
+* While Gremlins is running, can optionally log to a text file:
+
+ - posted events
+ - received events
+ - system functions called
+ - time of execution.
diff --git a/Docs/_ReadMe.txt b/Docs/_ReadMe.txt
new file mode 100644
index 0000000..d96261d
--- /dev/null
+++ b/Docs/_ReadMe.txt
@@ -0,0 +1,108 @@
+========================================================================
+Read Me for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+This document is the Read Me for the Palm OS Emulator (formerly known as
+Copilot).
+
+Palm OS Emulator is an application that emulates the hardware for most
+Palm Computing Platform Hardware devices (e.g., Pilot, PalmPilot, Palm
+III, Palm V, Palm VII, etc.). The Emulator runs on most standard
+desktop computers, includes those running Windows 95, Windows 98,
+Windows NT 4.0, Windows 2000, Mac OS 8.6, Mac OS 9.x, Mac OS X, and
+several flavors of Unix. On the Mac, you need CarbonLib 1.2.5 or later.
+You can find CarbonLib at:
+
+ <http://developer.apple.com/carbon/>
+or:
+ <http://developer.apple.com/sdk/>
+
+With the Palm OS Emulator, you can emulate the functions of a Palm
+hardware device, including running the built-in application, as well as
+installing and running 3rd party applications.
+
+Palm OS Emulator is an Open Source project. That means that the source
+code is available for you to peruse and modify. If you make any changes
+that you think might benefit others, we urge you to consider sending
+them back to Palm, Inc., for inclusion in the main source code base.
+
+You can find the Palm OS Emulator at:
+
+ <http://www.palmos.com/dev/tech/tools/emulator/>
+
+You will also find this URL in the About Box for the Emulator. The URL
+is an active hyperlink; you can usually just click on it to launch your
+Web browser and have it automatically access the Emulator home page.
+
+
+Guide to the documentation files:
+---------------------------------
+UserGuide.pdf
+ The official Poser documentation. The current version documents
+ features up to Palm OS Emulator 3.0a8. See the _News.txt or
+ _OldNews.txt files for changes since that version.
+
+Bugs.txt
+ A small set of bugs that we think you need to know about. Not
+ all known bugs are listed here -- just fairly relevent ones.
+
+Building.txt
+ Instructions on how to build (compile) the Palm OS Emulator on
+ the various supported platforms.
+
+Contributing.txt
+ Guidelines to follow (or at least consider) if you are thinking
+ of contributing to this Open Source project.
+
+Credits.txt
+ List of people who have contributed to the Emulator project.
+
+GPL.txt
+ Palm OS Emulator is an Open Source project distributed under and
+ protected by the GNU GENERAL PUBLIC LICENSE. The text of the
+ license is included in this file.
+
+News.txt
+ Blow-by-blow descriptions of changes made to the emulator as it
+ evolves over time.
+
+OldNews.txt
+ News.txt was getting too big, so older entries have been archived
+ to this file.
+
+ReadMe.txt
+ The document you're currently reading.
+
+ToDo.txt
+ A short list of To Do items, for people wondering what features
+ are planned or for people wondering how they can contribute to
+ the project.
+
+12rollin.pdf
+ Handheld Systems Journal article written by the current Palm OS
+ Emulator engineer. Covers the differences between the Palm OS
+ Emulator and Copilot, the program from which it was derived.
+
+13hewgil.pdf
+ Handheld Systems Journal article written by the original author
+ of Copilot.
+
+
+Notes on the Profile version:
+-----------------------------
+Some Palm OS Emulator releases include a profiling version (indicated by
+its having "Profile" appended to its name). This version of the
+emulator allows users to turn profiling on and off, and to save the
+results to disk in a format compatible with the CodeWarrior Profile
+application, or in a tab-delimited text file suitable for spreadsheets.
+
+Because the extra code involved with profiling an application slows down
+all program execution (even when profiling isn't currently being used),
+profiling support is provided only in this special version. If you
+don't intend to profile your application, you should use the normal
+version of the emulator.
diff --git a/Docs/_ToDo.txt b/Docs/_ToDo.txt
new file mode 100644
index 0000000..418076d
--- /dev/null
+++ b/Docs/_ToDo.txt
@@ -0,0 +1,16 @@
+========================================================================
+Abridged To Do List for the Palm OS Emulator
+Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+All rights reserved.
+
+Please send bug reports, comments, suggestions, etc. to
+<mailto:bug.reports@corp.palm.com>
+========================================================================
+
+This document contains an overview of some of the major features and
+components of the Palm OS Emulator that still need to be added or worked
+on. The are listed here not only to let people know what's to come, but
+also to give them a starting point if they wish to contribute to the
+development of the project.
+
+* TBD
diff --git a/ROMTransfer/Resources/ROM_Transfer.rcp b/ROMTransfer/Resources/ROM_Transfer.rcp
new file mode 100644
index 0000000..2b7e2a4
--- /dev/null
+++ b/ROMTransfer/Resources/ROM_Transfer.rcp
@@ -0,0 +1,43 @@
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "ROM_Transfer.rsrc.h"
+
+/* pbitm is a fairly brutal image format! But it's good enough for icons,
+ and you can be sure that everyone will have software capable of editing
+ it. PilRC does support other image formats too. */
+
+icon "ROM_Transfer_icon.pbitm"
+
+applicationiconname id 1000 "ROM Transfer"
+
+version id 1 "2.0"
+
+/* Unfortunately, pilrc doesn't allow you to write a very long label as a
+ multiple line string. */
+
+form id MainForm at (0 0 160 160)
+begin
+ title "ROM Transfer"
+ button "Begin Transfer" id MainBeginTransferButton at (79 138 74 16)
+ label "ROM Transfer is provided as a\rcompanion utility to the Palm OS\rEmulator. To use this utility, select\r\"Download ROM...\" from the File\rmenu in the emulator and follow the\rinstructions provided."
+ autoid at (7 21)
+ label "Transfer Speed:" autoid at (7 98) font 1
+ popuptrigger "" id MainSpeedPopTrigger at (90 97 0 13) leftanchor
+ list
+ "115,200 bps" "57,600 bps" "38,400 bps" "28,800 bps"
+ "19,200 bps" "14,400 bps" "9,600 bps"
+ id MainSpeedList at (94 98 65 auto) visibleitems 7 nonusable disabled
+ popuplist MainSpeedPopTrigger MainSpeedList
+ label "Status:" autoid at (49 114) font 1
+ label "Idle " MainStatusTextLabel at (93 114)
+end
diff --git a/ROMTransfer/Resources/ROM_Transfer.rsrc b/ROMTransfer/Resources/ROM_Transfer.rsrc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ROMTransfer/Resources/ROM_Transfer.rsrc
diff --git a/ROMTransfer/Resources/ROM_Transfer.rsrc.c b/ROMTransfer/Resources/ROM_Transfer.rsrc.c
new file mode 100644
index 0000000..207ccf5
--- /dev/null
+++ b/ROMTransfer/Resources/ROM_Transfer.rsrc.c
@@ -0,0 +1,22 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include <BuildRules.h>
+
+
+char* AppResourceList[] =
+{
+ ":Resources:Rom Transfer.rsrc",
+ ""
+};
+
diff --git a/ROMTransfer/Resources/ROM_Transfer.rsrc.h b/ROMTransfer/Resources/ROM_Transfer.rsrc.h
new file mode 100644
index 0000000..f88371f
--- /dev/null
+++ b/ROMTransfer/Resources/ROM_Transfer.rsrc.h
@@ -0,0 +1,50 @@
+// Header generated by Constructor for Pilot 1.0.2
+
+//
+
+// Generated at 2:42:07 PM on Wednesday, November 4, 1998
+
+//
+
+// Generated for file: Phantom:Projects:Emulator:main:ROM_Transfer:Resources:ROM Transfer.rsrc
+
+//
+
+// THIS IS AN AUTOMATICALLY GENERATED HEADER FILE FROM CONSTRUCTOR FOR PALMPILOT;
+
+// - DO NOT EDIT - CHANGES MADE TO THIS FILE WILL BE LOST
+
+//
+
+// Pilot App Name: "ROM Transfer"
+
+//
+
+// Pilot App Version: "2.0"
+
+
+
+
+
+
+
+// Resource: tFRM 1000
+
+#define MainForm 1000 //(Left Origin = 0, Top Origin = 0, Width = 160, Height = 160, Usable = 1, Modal = 0, Save Behind = 0, Help ID = 0, Menu Bar ID = 0, Default Button ID = 0)
+
+#define MainBeginTransferButton 1000 //(Left Origin = 79, Top Origin = 138, Width = 74, Height = 16, Usable = 1, Anchor Left = 1, Frame = 1, Non-bold Frame = 1, Font = Standard)
+
+#define MainInstructionsLabel 1001 //(Left Origin = 7, Top Origin = 21, Usable = 1, Font = Standard)
+
+#define MainSpeedLabel 1002 //(Left Origin = 7, Top Origin = 98, Usable = 1, Font = Bold)
+
+#define MainStatusLabel 1005 //(Left Origin = 49, Top Origin = 114, Usable = 1, Font = Bold)
+
+#define MainStatusTextLabel 1006 //(Left Origin = 93, Top Origin = 114, Usable = 1, Font = Standard)
+
+#define MainSpeedList 1004 //(Left Origin = 94, Top Origin = 98, Width = 65, Usable = 0, Font = Standard, Visible Items = 0)
+
+#define MainSpeedPopTrigger 1003 //(Left Origin = 90, Top Origin = 97, Width = 0, Height = 13, Usable = 1, Anchor Left = 1, Font = Standard, List ID = 1004)
+
+
+
diff --git a/ROMTransfer/Resources/ROM_Transfer_icon.pbitm b/ROMTransfer/Resources/ROM_Transfer_icon.pbitm
new file mode 100644
index 0000000..3fca0bf
--- /dev/null
+++ b/ROMTransfer/Resources/ROM_Transfer_icon.pbitm
@@ -0,0 +1,32 @@
+------------#######-------------
+----------###########-----------
+---------######-######----------
+--------######-#-######---------
+-------######-###-######--------
+------######-#####-######-------
+------#####-######--#####-------
+-----#####-######--#######------
+-----####-######--#-######------
+-----###-######--#########------
+-----##-######--#-########------
+-----###-####--###########------
+-----####-##--#-##-##-####------
+-----#####---####---#-####------
+------#####-#-####----###-------
+------#############---###-------
+-------##########-----##--------
+--------###############---------
+---------#############----------
+----------###########-----------
+------------#######-------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
+--------------------------------
diff --git a/ROMTransfer/Source/Makefile b/ROMTransfer/Source/Makefile
new file mode 100644
index 0000000..efb76d1
--- /dev/null
+++ b/ROMTransfer/Source/Makefile
@@ -0,0 +1,27 @@
+## -*- mode: Makefile; tab-width: 4; -*-
+## ======================================================================================
+## Copyright (c) 2000 Palm Computing, Inc. or its subsidiaries. All rights reserved.
+## ======================================================================================
+
+R = ../Resources
+
+CC = m68k-palmos-gcc
+CFLAGS = -O2 -Wall -I$(R) -g -Wno-unknown-pragmas
+
+ROM_Transfer.prc: ROM_Transfer tver0001.bin
+ build-prc ROM_Transfer.prc "ROM Transfer" ROMX ROM_Transfer *.bin
+
+ROM_Transfer: ROM_Transfer.o SerialPortTools.o
+ $(CC) -v -g -o ROM_Transfer ROM_Transfer.o SerialPortTools.o
+
+ROM_Transfer.o: ROM_Transfer.c ROM_Transfer.h SerialPortTools.h $(R)/ROM_Transfer.rsrc.h
+ $(CC) $(CFLAGS) -c ROM_Transfer.c
+
+SerialPortTools.o: SerialPortTools.c SerialPortTools.h $(R)/ROM_Transfer.rsrc.h
+ $(CC) $(CFLAGS) -c SerialPortTools.c
+
+tver0001.bin: $(R)/ROM_Transfer.rcp $(R)/ROM_Transfer_icon.pbitm $(R)/ROM_Transfer.rsrc.h
+ pilrc -I $(R) $(R)/ROM_Transfer.rcp
+
+clean:
+ -rm -f ROM_Transfer *.o *.bin
diff --git a/ROMTransfer/Source/ROM_Transfer b/ROMTransfer/Source/ROM_Transfer
new file mode 100755
index 0000000..8e9d15c
--- /dev/null
+++ b/ROMTransfer/Source/ROM_Transfer
Binary files differ
diff --git a/ROMTransfer/Source/ROM_Transfer.c b/ROMTransfer/Source/ROM_Transfer.c
new file mode 100644
index 0000000..2126ce9
--- /dev/null
+++ b/ROMTransfer/Source/ROM_Transfer.c
@@ -0,0 +1,768 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#define PILOT_PRECOMPILED_HEADERS_OFF
+
+#include <PalmOS.h>
+
+#include "ROM_Transfer.h"
+#include "ROM_Transfer.rsrc.h"
+
+UInt32 HwrMemReadable(void *addr)
+ HAL_CALL(sysTrapHwrMemReadable);
+
+static void SendXModem (FormType* form, UInt8* romStart, Int32 romSize);
+static void SendRaw (FormType* form, UInt8* romStart, Int32 romSize);
+static void UpdatePercentComplete (FormType* form, Int32 offset, Int32 romSize);
+static void GetROMStartSize (UInt8** romStart, Int32* romSize);
+static void PrvUpdateStatus (FormType* form, const char*);
+static void PrvStrPrintF (char* dest, const char* fmt, Int32 num);
+static void PrvStrIToX (char* dest, UInt32 val);
+
+static UInt32 gROMVersion;
+
+const char* kSerialErrors[] =
+{
+ "Bad Param",
+ "Bad Port",
+ "No Memory",
+ "Bad ConnID",
+ "Timeout",
+ "Line Error",
+ "Already Open",
+ "Still Open",
+ "Not Open",
+ "Not Supported",
+ "No Devices"
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ PilotMain
+// ---------------------------------------------------------------------------
+// The main entry point for ROM Transfer.
+
+UInt32 PilotMain ( UInt16 iCommand,
+ void* iCommandParams,
+ UInt16 iLaunchFlags)
+{
+ if (iCommand != sysAppLaunchCmdNormalLaunch)
+ return 0;
+
+ ErrTry
+ {
+ InitializeApplication ();
+ ExecuteApplication ();
+ }
+
+ // Catch any unhandled exceptions.
+
+ ErrCatch (iError)
+ {
+ }
+ ErrEndCatch
+
+ // Clean up.
+
+ DisposeApplication ();
+
+ return 0;
+}
+
+
+#pragma mark -
+
+
+// ---------------------------------------------------------------------------
+// ¥ InitializeApplication
+// ---------------------------------------------------------------------------
+// Initializes the application globals and prepares to execute the event loop.
+
+void InitializeApplication (void)
+{
+ Char* aLabel;
+ ListPtr aList;
+ UInt16 aListItem;
+ ControlPtr aControl;
+ FormPtr aMainForm;
+
+ FtrGet (sysFtrCreator, sysFtrNumROMVersion, &gROMVersion);
+
+ // Initialize and draw the main form.
+
+ aMainForm = FrmInitForm (MainForm);
+ Throw_IfNil (aMainForm, 0);
+
+ FrmSetActiveForm (aMainForm);
+ FrmDrawForm (aMainForm);
+
+ // Set up the speed popup.
+
+ aListItem = kItem_115200;
+ aList = FrmGetObjectPtr (aMainForm, FrmGetObjectIndex (aMainForm, MainSpeedList));
+ aLabel = LstGetSelectionText (aList, aListItem);
+ aControl = FrmGetObjectPtr (aMainForm, FrmGetObjectIndex (aMainForm, MainSpeedPopTrigger));
+ CtlSetLabel (aControl, aLabel);
+ LstSetSelection (aList, aListItem);
+
+#if 0
+{
+ #define sysFtrNewSerialVersion 2
+ int fred;
+
+#define gSerialManagerVersion fred
+
+ Err err;
+ char buffer[20];
+ UInt32 systemVersion;
+ UInt32 ftrValue;
+
+ // Determine what version Serial Manager we have:
+ //
+ // 0 = undetermined
+ // 1 = Original driver in Pilot 1000/5000
+ // 2 = Updated driver in PalmPilot (new Send/Receive calls)
+ // 3 = New Serial Manager (Srm calls)
+ // 4 = Updated Serial Manager (includes SrmExtOpen call)
+
+ err = FtrGet (sysFileCSystem, sysFtrNumROMVersion, &systemVersion);
+
+ ErrFatalDisplayIf (err, "Unable to determine System version");
+
+ if (sysGetROMVerMajor(systemVersion) < 2)
+ {
+ gSerialManagerVersion = 1;
+ }
+ else
+ {
+ err = FtrGet (sysFileCSerialMgr, sysFtrNewSerialPresent, &ftrValue);
+
+ if (err || ftrValue == 0)
+ {
+ gSerialManagerVersion = 2;
+ }
+ else
+ {
+ err = FtrGet (sysFileCSerialMgr, sysFtrNewSerialVersion, &ftrValue);
+
+ if (err)
+ {
+ gSerialManagerVersion = 3;
+ }
+ else if (ftrValue <= 2)
+ {
+ gSerialManagerVersion = 3;
+
+ // Palm OS 3.5.2 for Handspring implements
+ // sysFtrNewSerialVersion and returns a feature value of 2.
+ // Palm OS 4.0 also implements sysFtrNewSerialVersion and
+ // returns a value of 2. However, the two serial managers
+ // are different: the latter implements SrmExtOpen. In
+ // order to differentiate between the two, we have to check
+ // the OS version.
+
+ if (ftrValue == 2 &&
+ sysGetROMVerMajor (systemVersion) == 4 &&
+ sysGetROMVerMinor (systemVersion) == 0)
+ {
+ gSerialManagerVersion = 4;
+ }
+ }
+ else
+ {
+ // ftrValue should be at least 3 for versions of the
+ // Serial Manager that implement SrmExtOpen.
+
+ gSerialManagerVersion = ftrValue + 1;
+ }
+ }
+ }
+
+ StrPrintF (buffer, "%d %d", (int) err, (int) gSerialManagerVersion);
+
+ PrvUpdateStatus (aMainForm, buffer);
+}
+#endif
+
+#if 0
+{
+ char buffer1[20];
+ char buffer2[20];
+ char buffer3[20];
+ UInt8* romStart;
+ Int32 romSize;
+
+ GetROMStartSize (&romStart, &romSize);
+
+ PrvStrIToX (buffer1, (UInt32) romStart);
+ PrvStrIToX (buffer2, (UInt32) romSize);
+
+ StrCopy (buffer3, buffer1);
+ StrCat (buffer3, " ");
+ StrCat (buffer3, buffer2);
+
+ PrvUpdateStatus (aMainForm, buffer3);
+}
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DisposeApplication
+// ---------------------------------------------------------------------------
+// Disposes the application globals and prepares to exit.
+
+void DisposeApplication (void)
+{
+ FrmCloseAllForms ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ExecuteApplication
+// ---------------------------------------------------------------------------
+// Executes an event loop until the application quits.
+
+void ExecuteApplication (void)
+{
+ EventType aEvent;
+
+ aEvent.eType = nilEvent;
+
+ // Repeat until the application quits.
+
+ while (aEvent.eType != appStopEvent)
+ {
+ // Get the next available event.
+
+ EvtGetEvent (&aEvent, evtWaitForever);
+
+ // Give the system a chance to handle the event.
+
+ if (!SysHandleEvent (&aEvent))
+
+ // Try to handle the event ourselves.
+
+ if (!ProcessEvent (&aEvent))
+
+ // Let the form provide default handling of the event.
+
+ FrmHandleEvent (FrmGetActiveForm (), &aEvent);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProcessEvent
+// ---------------------------------------------------------------------------
+// Attempts to process the specified event.
+
+Boolean ProcessEvent (EventPtr iEvent)
+{
+ Boolean aWasHandled = false;
+
+ if (iEvent->eType == ctlSelectEvent)
+ {
+ switch (iEvent->data.ctlEnter.controlID)
+ {
+ case MainBeginTransferButton:
+ {
+ TransferROM ();
+
+ aWasHandled = true;
+ break;
+ }
+ }
+ }
+
+ return aWasHandled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TransferROM
+// ---------------------------------------------------------------------------
+// Downloads the ROM via the serial connection.
+
+static UInt32 MySysTicksPerSecond ()
+{
+ if (sysGetROMVerMajor(gROMVersion) < 2)
+ return sysTicksPerSecond;
+
+ return SysTicksPerSecond ();
+}
+
+void TransferROM (void)
+{
+ Int16 err;
+ UInt8* romStart;
+ Int32 romSize;
+
+ Int16 speedChoice;
+ UInt32 speed;
+ FormPtr form;
+
+ form = FrmGetActiveForm ();
+
+ ErrTry
+ {
+ ErrFatalDisplayIf (!form, "Unable to get form");
+
+ speedChoice = LstGetSelection (FrmGetObjectPtr (form, FrmGetObjectIndex (form, MainSpeedList)));
+ switch (speedChoice)
+ {
+ case kItem_1200: speed = kBaud_1200; break;
+ case kItem_2400: speed = kBaud_2400; break;
+ case kItem_4800: speed = kBaud_4800; break;
+ case kItem_9600: speed = kBaud_9600; break;
+ case kItem_14400: speed = kBaud_14400; break;
+ case kItem_19200: speed = kBaud_19200; break;
+ case kItem_28800: speed = kBaud_28800; break;
+ case kItem_38400: speed = kBaud_38400; break;
+ case kItem_57600: speed = kBaud_57600; break;
+ case kItem_115200: speed = kBaud_115200; break;
+ default: speed = kBaud_14400; break;
+ }
+
+ err = Comm_Initialize (speed);
+ Throw_IfError (err, err);
+
+ // Get the size and location of the ROM.
+
+ GetROMStartSize (&romStart, &romSize);
+
+ // Send the data using a protocol appropriate for the connection.
+
+#if 0
+ if (using_USB)
+ {
+ SendRaw (form, romStart, romSize);
+ }
+ else
+#endif
+ {
+ SendXModem (form, romStart, romSize);
+ }
+
+ // Change the status text.
+
+ PrvUpdateStatus (form, "Finished");
+ }
+
+ // Catch any exceptions.
+
+ ErrCatch (iError)
+ {
+ // Change the status text.
+
+ if (form != NULL)
+ {
+ char buffer[20];
+
+ if (iError >= serErrBadParam &&
+ iError <= serErrNoDevicesAvail)
+ {
+ StrCopy (buffer, kSerialErrors[iError - serErrBadParam]);
+ }
+ else
+ {
+ PrvStrPrintF (buffer, "Error #%d", iError);
+ }
+
+ PrvUpdateStatus (form, buffer);
+ }
+ }
+ ErrEndCatch
+
+ Comm_Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvSendChar
+// ---------------------------------------------------------------------------
+
+static void PrvSendChar (UInt8 ch)
+{
+ Err err = Comm_Send (&ch, 1);
+ Throw_IfError (err, err);
+
+ EvtResetAutoOffTimer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReceiveChar
+// ---------------------------------------------------------------------------
+
+static void PrvReceiveChar (UInt8* ch)
+{
+ Err err = Comm_Receive (ch, 1, 30 * MySysTicksPerSecond ());
+ Throw_IfError (err, err);
+
+ EvtResetAutoOffTimer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SendXModem
+// ---------------------------------------------------------------------------
+
+void SendXModem (FormType* form, UInt8* romStart, Int32 romSize)
+{
+ const int kXModemBodySize = 1024; // 1k-XModem variant
+ const int kXModemSohOffset = 0;
+ const int kXModemBlkOffset = kXModemSohOffset + 1;
+ const int kXModemNBlkOffset = kXModemBlkOffset + 1;
+ const int kXModemBodyOffset = kXModemNBlkOffset + 1;
+ const int kXModemChk1Offset = kXModemBodyOffset + kXModemBodySize;
+ const int kXModemChk2Offset = kXModemChk1Offset + 1;
+ const int kXModemBlockSize = kXModemChk2Offset + 1;
+
+ const char kXModemSoh = 1; // start of block header
+ const char kXModemEof = 4; // end of file signal
+ const char kXModemAck = 6; // acknowledge
+ const char kXModemNak = 21; // negative acknowledge (resend packet)
+ const char kXModemCan = 24; // cancel
+ const char kXModemNakCrc = 'C'; // used instead of NAK for initial block
+
+ Err err;
+ UInt8 c;
+ UInt8 blockNum;
+ UInt32 i;
+ Boolean bXModemCrc;
+ char block[kXModemBlockSize];
+ Boolean bXModemHeaderBlock;
+ Int32 offset;
+ UInt16 crc;
+ char* body = &block[kXModemBodyOffset];
+
+ // Change the status text.
+
+ PrvUpdateStatus (form, "Waiting...");
+
+ // First, wait for the receiver to send us a nak. If it's
+ // a real nak, then we'll send in checksum mode. If it's
+ // a 'C', we'll send in CRC mode.
+
+ Comm_ClearError ();
+
+ while (true)
+ {
+ PrvReceiveChar (&c);
+
+ if (c == kXModemNakCrc)
+ {
+ bXModemCrc = true;
+ break;
+ }
+ else if (c == kXModemNak)
+ {
+ bXModemCrc = false;
+ break;
+ }
+ else if (c == kXModemCan)
+ {
+ ErrThrow (c);
+ }
+ }
+
+ // Send the ROM one block at a time until it's done.
+
+ offset = 0;
+ blockNum = 0;
+ bXModemHeaderBlock = true;
+
+ while (offset < romSize)
+ {
+ // Change the status text.
+
+ UpdatePercentComplete (form, offset, romSize);
+
+ // Build up the block.
+
+ block[kXModemSohOffset] = kXModemSoh;
+ block[kXModemBlkOffset] = blockNum;
+ block[kXModemNBlkOffset] = ~blockNum;
+
+ if (bXModemHeaderBlock)
+ {
+ // The very first block sends over a "file name"
+ // and "file size".
+
+ MemSet (body, kXModemBodySize, 0);
+ StrCopy (body, "PalmOS.ROM"); // What's in a name?
+ StrIToA (&body[StrLen (body) + 1], romSize);
+ }
+ else
+ {
+ // All subseqent blocks contain 1K of the ROM.
+
+ MemMove (body, romStart + offset, kXModemBodySize);
+ }
+
+ // Figure out and add the checksum.
+
+ if (bXModemCrc)
+ {
+ // Calculate the checksum of the body data, as
+ // well as the two empty spots that will get filled
+ // in with the checksum bytes in a moment.
+
+ block[kXModemChk1Offset] = 0;
+ block[kXModemChk2Offset] = 0;
+
+ crc = Crc16CalcBlock (body, kXModemBodySize + 2, 0);
+
+ block[kXModemChk1Offset] = crc >> 8;
+ block[kXModemChk2Offset] = crc;
+
+ err = Comm_Send (block, kXModemBlockSize);
+ }
+ else
+ {
+ c = 0;
+
+ for (i = 0; i < kXModemBodySize; i++)
+ {
+ c += (romStart + offset)[i];
+ }
+
+ body[kXModemChk1Offset] = c;
+
+ err = Comm_Send (block, kXModemBlockSize - 1);
+ }
+
+ Throw_IfError (err, err);
+
+ EvtResetAutoOffTimer ();
+
+ // Wait for the other end to ack or nak us. Leave
+ // plenty of timeout so the receiver has time to
+ // decide whether it got a partial block.
+
+ do
+ {
+ PrvReceiveChar (&c);
+ } while (c != kXModemAck && c != kXModemNak && c != kXModemNakCrc);
+
+ if (c == kXModemAck)
+ {
+ if (!bXModemHeaderBlock)
+ {
+ // Only do this if we're into sending the file
+ // (don't increment on the file header block).
+
+ offset += kXModemBodySize;
+ }
+
+ blockNum++;
+ bXModemHeaderBlock = false;
+ }
+ }
+
+ // Send an EOF and wait for an acknowledgement.
+
+ do
+ {
+ PrvSendChar (kXModemEof);
+ PrvReceiveChar (&c);
+ } while (c != kXModemAck);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SendRaw
+// ---------------------------------------------------------------------------
+
+void SendRaw (FormType* form, UInt8* romStart, Int32 romSize)
+{
+#define kRawBlockSize 1024
+
+ Err err;
+ Int32 offset = 0;
+
+ // Start by sending the size.
+
+ err = Comm_Send (&romSize, sizeof (romSize));
+ Throw_IfError (err, err);
+
+ // Now send the ROM.
+
+ while (offset < romSize)
+ {
+ // Change the status text.
+
+ UpdatePercentComplete (form, offset, romSize);
+
+ err = Comm_Send (romStart + offset, kRawBlockSize);
+ Throw_IfError (err, err);
+
+ offset += kRawBlockSize;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ UpdatePercentComplete
+// ---------------------------------------------------------------------------
+
+void UpdatePercentComplete (FormType* form, Int32 offset, Int32 romSize)
+{
+ Int32 percentComplete = (offset * 100) / romSize;
+ char buffer[20];
+
+ PrvStrPrintF (buffer, "Sending...%d%%", percentComplete);
+
+ PrvUpdateStatus (form, buffer);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetROMStartSize
+// ---------------------------------------------------------------------------
+
+void * MemHeapPtr(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapPtr);
+
+#define memHeapFlagReadOnly 0x0001 // heap is read-only (ROM based)
+
+void GetROMStartSize (UInt8** romStartP, Int32* romSizeP)
+{
+#if 0
+ void* romStart = (void*) HwrMemReadable ((void*) 0xFFFFFFFF);
+ UInt32 romSize = HwrMemReadable (romStart);
+
+ *romStartP = romStart;
+ *romSizeP = romSize;
+#else
+ UInt16 numHeaps = MemNumHeaps (0);
+ UInt16 heapID;
+ UInt16 heapFlags;
+ UInt8* heapBegin;
+ UInt8* heapEnd;
+ UInt32 heapSize;
+
+ UInt8* romLow = (UInt8*) 0xFFFFFFFF;
+ UInt8* romHigh = (UInt8*) NULL;
+
+ for (heapID = 0; heapID < numHeaps; ++heapID)
+ {
+ heapFlags = MemHeapFlags (heapID);
+
+ if (heapFlags & memHeapFlagReadOnly)
+ {
+ heapBegin = (UInt8*) MemHeapPtr (heapID);
+ heapSize = MemHeapSize (heapID);
+ heapEnd = heapBegin + heapSize;
+
+ if (romLow > heapBegin)
+ {
+ romLow = heapBegin;
+ }
+
+ if (romHigh < heapEnd)
+ {
+ romHigh = heapEnd;
+ }
+ }
+ }
+
+ // Round up/down to 512K boundaries. (512K is the size
+ // of the Pilot 1000/5000 ROM).
+
+ #define MASK (512L * 1024 - 1)
+
+ romLow = (UInt8*) ((UInt32) romLow & ~MASK);
+ romHigh = (UInt8*) (((UInt32) romHigh + MASK) & ~MASK);
+
+ *romStartP = romLow;
+ *romSizeP = romHigh - romLow;
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvUpdateStatus
+// ---------------------------------------------------------------------------
+
+void PrvUpdateStatus (FormType* form, const char* txt)
+{
+ char buffer[100];
+ StrCopy (buffer, txt);
+ StrCat (buffer, " ");
+
+ FrmCopyLabel (form, MainStatusTextLabel, buffer);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvStrPrintF
+// ---------------------------------------------------------------------------
+// Roll our own StrPrintF, since it doesn't exist in 1.0.
+
+void PrvStrPrintF (char* dest, const char* fmt, Int32 num)
+{
+ char ch;
+ const char* s = fmt;
+ char* d = dest;
+ char numBuff[12]; // -2 xxx xxx xxx \0 = 12 bytes
+
+ while ((ch = *s++) != 0)
+ {
+ if (ch != '%')
+ {
+ *d++ = ch;
+ }
+ else
+ {
+ ch = *s++;
+
+ if (ch == 'd')
+ {
+ StrIToA (numBuff, num);
+ StrCopy (d, numBuff);
+ d += StrLen (numBuff);
+ }
+ else if (ch == 'c')
+ {
+ *d++ = (char) num;
+ }
+ else if (ch == '%')
+ {
+ *d++ = '%';
+ }
+ }
+ }
+
+ *d = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvStrIToX
+// ---------------------------------------------------------------------------
+
+void PrvStrIToX (char* dest, UInt32 val)
+{
+ const char* kDigits = "0123456789ABCDEF";
+ int ii;
+
+ for (ii = 0; ii < 8; ++ii)
+ {
+ unsigned nybble = (val >> (28 - ii * 4)) & 0x0F;
+ dest[ii] = kDigits[nybble];
+ }
+
+ dest[8] = 0;
+}
diff --git a/ROMTransfer/Source/ROM_Transfer.h b/ROMTransfer/Source/ROM_Transfer.h
new file mode 100644
index 0000000..3bc9b2a
--- /dev/null
+++ b/ROMTransfer/Source/ROM_Transfer.h
@@ -0,0 +1,55 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef ROM_TRANSFER_H
+#define ROM_TRANSFER_H
+
+
+#include "SerialPortTools.h"
+
+
+// Constants.
+
+#define kItem_1200 9
+#define kItem_2400 8
+#define kItem_4800 7
+#define kItem_9600 6
+#define kItem_14400 5
+#define kItem_19200 4
+#define kItem_28800 3
+#define kItem_38400 2
+#define kItem_57600 1
+#define kItem_115200 0
+
+// Error macros.
+
+#define Throw_IfNil(iHandle,iError) { if ((iHandle) == NULL) ErrThrow (iError); }
+#define Throw_IfError(iCode,iError) { if ((iCode) != 0) ErrThrow (iError); }
+
+// Function prototypes.
+
+UInt32 PilotMain (UInt16 iCommand,
+ void* iCommandParams,
+ UInt16 iLaunchFlags);
+
+void InitializeApplication (void);
+
+void DisposeApplication (void);
+
+void ExecuteApplication (void);
+
+Boolean ProcessEvent (EventPtr iEvent);
+
+void TransferROM (void);
+
+#endif
diff --git a/ROMTransfer/Source/ROM_Transfer.prc b/ROMTransfer/Source/ROM_Transfer.prc
new file mode 100644
index 0000000..1227cdb
--- /dev/null
+++ b/ROMTransfer/Source/ROM_Transfer.prc
Binary files differ
diff --git a/ROMTransfer/Source/SerialPortTools.c b/ROMTransfer/Source/SerialPortTools.c
new file mode 100644
index 0000000..0428a43
--- /dev/null
+++ b/ROMTransfer/Source/SerialPortTools.c
@@ -0,0 +1,388 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#define PILOT_PRECOMPILED_HEADERS_OFF
+
+#include <PalmOS.h>
+#include <SerialMgrOld.h> // SerSettingsType
+
+#include "SerialPortTools.h"
+
+// for Handspring API access
+#define sysTrapHsSelector sysTrapOEMDispatch
+#define hsSelExtKeyboardEnable 5
+#define SYS_SEL_TRAP(trapNum, selector) \
+ _SYSTEM_API(_CALL_WITH_16BIT_SELECTOR)(_SYSTEM_TABLE, trapNum, selector)
+
+Err HsExtKeyboardEnable (Boolean enable)
+ SYS_SEL_TRAP (sysTrapHsSelector, hsSelExtKeyboardEnable);
+
+#ifndef serMgrVersion
+
+ // Bits of the Palm OS 4.0 Serial Manager we need until
+ // the SDK is available
+
+ #define sysFtrNewSerialVersion 2
+
+ #define sysSerialOpenV4 24
+ #define sysSerialOpenBkgndV4 25
+ #define sysSerialCustomControl 26
+
+ //
+ // Open Configuration Structure
+ //
+ typedef struct SrmOpenConfigType {
+ UInt32 baud; // Baud rate that the connection is to be opened at.
+ // Applications that use drivers that do not require
+ // baud rates can set this to zero or any other value.
+ // Drivers that do not require a baud rate should
+ // ignore this field
+ UInt32 function; // Designates the function of the connection. A value
+ // of zero indictates default behavior for the protocol.
+ // Drivers that do not support multiple functions should
+ // ignore this field.
+ MemPtr drvrDataP; // Pointer to driver specific data.
+ UInt16 drvrDataSize; // Size of the driver specific data block.
+ UInt32 sysReserved1; // System Reserved
+ UInt32 sysReserved2; // System Reserved
+ } SrmOpenConfigType;
+
+ typedef SrmOpenConfigType* SrmOpenConfigPtr;
+
+ Err SrmExtOpen(UInt32 port, SrmOpenConfigType* configP, UInt16 configSize, UInt16 *newPortIdP)
+ SERIAL_TRAP(sysSerialOpenV4);
+
+#endif
+
+
+// Globals.
+
+UInt16 gPortID;
+int gSerialManagerVersion;
+
+
+// ---------------------------------------------------------------------------
+// ¥ Comm_Initialize
+// ---------------------------------------------------------------------------
+// Opens the communications port.
+
+Int16 Comm_Initialize (UInt32 iBaud)
+{
+ Err err = errNone;
+ SrmOpenConfigType config;
+ SerSettingsType serSettings;
+ UInt32 srmSettings;
+ UInt16 srmSettingsSize;
+ UInt32 systemVersion;
+ UInt32 ftrValue;
+
+ // Exit if communications have already been established.
+
+ if (gPortID)
+ return (serErrAlreadyOpen);
+
+ // Clear the globals.
+
+ gPortID = 0;
+ gSerialManagerVersion = 0;
+
+ // Determine what version Serial Manager we have:
+ //
+ // 0 = undetermined
+ // 1 = Original driver in Pilot 1000/5000
+ // 2 = Updated driver in PalmPilot (new Send/Receive calls)
+ // 3 = New Serial Manager (Srm calls)
+ // 4 = Updated Serial Manager (includes SrmExtOpen call)
+
+ err = FtrGet (sysFileCSystem, sysFtrNumROMVersion, &systemVersion);
+
+ ErrFatalDisplayIf (err, "Unable to determine System version");
+
+ if (sysGetROMVerMajor(systemVersion) < 2)
+ {
+ gSerialManagerVersion = 1;
+ }
+ else
+ {
+ err = FtrGet (sysFileCSerialMgr, sysFtrNewSerialPresent, &ftrValue);
+
+ if (err || ftrValue == 0)
+ {
+ gSerialManagerVersion = 2;
+ }
+ else
+ {
+ err = FtrGet (sysFileCSerialMgr, sysFtrNewSerialVersion, &ftrValue);
+
+ if (err)
+ {
+ gSerialManagerVersion = 3;
+ }
+ else if (ftrValue <= 2)
+ {
+ gSerialManagerVersion = 3;
+
+ // Palm OS 3.5.2 for Handspring implements
+ // sysFtrNewSerialVersion and returns a feature value of 2.
+ // Palm OS 4.0 also implements sysFtrNewSerialVersion and
+ // returns a value of 2. However, the two serial managers
+ // are different: the latter implements SrmExtOpen. In
+ // order to differentiate between the two, we have to check
+ // the OS version.
+
+ if (ftrValue == 2 && sysGetROMVerMajor (systemVersion) >= 4)
+ {
+ gSerialManagerVersion = 4;
+ }
+ }
+ else
+ {
+ // ftrValue should be at least 3 for versions of the
+ // Serial Manager that implement SrmExtOpen.
+
+ gSerialManagerVersion = ftrValue + 1;
+ }
+ }
+ }
+
+ // <chg 02-01-2000 BP> If on Handspring device, disable the keyboard
+ // thread before opening the serial library.
+
+ if (FtrGet ('hsEx', 0, &ftrValue) == errNone)
+ {
+ HsExtKeyboardEnable (false);
+ }
+
+ // Open the serial port in a manner appropriate for this platform.
+
+ if (gSerialManagerVersion <= 2)
+ {
+ // Find the serial library.
+
+ err = SysLibFind ("Serial Library", &gPortID);
+ if (err != errNone)
+ return (err);
+
+ // Open the serial port.
+
+ err = SerOpen (gPortID, kPort_Pilot, iBaud);
+ if (err != errNone)
+ goto Exit;
+
+ // Set the serial attributes.
+
+ serSettings.baudRate = iBaud;
+ serSettings.flags = serSettingsFlagBitsPerChar8 | serSettingsFlagStopBits1;
+ serSettings.ctsTimeout = serDefaultCTSTimeout;
+
+ err = SerSetSettings (gPortID, &serSettings);
+ if (err != errNone)
+ goto Exit;
+ }
+ else // if (gSerialManagerVersion >= 3)
+ {
+ // Open the serial port.
+
+ if (gSerialManagerVersion == 3)
+ {
+ err = SrmOpen (serPortLocalHotSync, iBaud, &gPortID);
+ }
+ else
+ {
+ MemSet (&config, sizeof (config), 0);
+
+ config.baud = iBaud;
+ config.function = 'ROMX';
+
+ err = SrmExtOpen ( serPortLocalHotSync,
+ &config, sizeof (config),
+ &gPortID);
+ }
+
+ if (err != errNone)
+ goto Exit;
+
+ // Set the serial attributes.
+
+ srmSettings = srmSettingsFlagBitsPerChar8 | srmSettingsFlagStopBits1;
+ srmSettingsSize = sizeof (srmSettings);
+ err = SrmControl (gPortID, srmCtlSetFlags,
+ &srmSettings, &srmSettingsSize);
+ if (err != errNone)
+ goto Exit;
+ }
+
+Exit:
+ if (err != errNone)
+ {
+ if (gPortID)
+ {
+ SrmClose (gPortID);
+ gPortID = 0;
+ }
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Comm_Receive
+// ---------------------------------------------------------------------------
+
+Err Comm_Receive (void* bufP, UInt32 count, UInt32 timeout)
+{
+ Err err;
+
+ if (gSerialManagerVersion == 1)
+ {
+ err = SerReceive10 (gPortID, bufP, count, timeout);
+ }
+ else if (gSerialManagerVersion == 2)
+ {
+ (void) SerReceive (gPortID, bufP, count, timeout, &err);
+ }
+ else // if (gSerialManagerVersion >= 3)
+ {
+ (void) SrmReceive (gPortID, bufP, count, timeout, &err);
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Comm_Send
+// ---------------------------------------------------------------------------
+
+#define CORRUPT_SENDS 0
+
+#if CORRUPT_SENDS
+static UInt32 PrvRange (UInt32 maxValue)
+{
+ static int initialized;
+ if (!initialized)
+ {
+ initialized = true;
+ SysRandom (1);
+ }
+
+ return (SysRandom (0) * maxValue) / (1UL + sysRandomMax);
+}
+#endif
+
+
+Err Comm_Send (void* bufP, UInt32 count)
+{
+ Err err;
+
+#if CORRUPT_SENDS
+ void* buf2 = MemPtrNew (count);
+
+ MemMove (buf2, bufP, count);
+
+ bufP = buf2;
+
+ if (PrvRange (100) <= (count / 100))
+ {
+ // Corrupt a character
+
+ ((char*) bufP)[PrvRange (count)]++;
+ }
+ else if (PrvRange (100) <= (count / 100))
+ {
+ // Drop a character
+
+ UInt32 index = PrvRange (count);
+
+ if (count - index - 1 > 0)
+ {
+ MemMove ((char*) bufP + index,
+ (char*) bufP + index + 1,
+ count - index - 1);
+ }
+ count--;
+ }
+#endif
+
+ if (gSerialManagerVersion == 1)
+ {
+ err = SerSend10 (gPortID, bufP, count);
+ }
+ else if (gSerialManagerVersion == 2)
+ {
+ (void) SerSend (gPortID, bufP, count, &err);
+ }
+ else // if (gSerialManagerVersion >= 3)
+ {
+ (void) SrmSend (gPortID, bufP, count, &err);
+ }
+
+#if CORRUPT_SENDS
+ MemPtrFree (bufP);
+#endif
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Comm_Dispose
+// ---------------------------------------------------------------------------
+// Closes the communications port.
+
+void Comm_Dispose (void)
+{
+ // Exit if communications have not been established.
+
+ if (!gPortID)
+ return;
+
+ // Close the serial port.
+
+ if (gSerialManagerVersion <= 2)
+ {
+ SerClose (gPortID);
+ }
+ else // if (gSerialManagerVersion >= 3)
+ {
+ SrmClose (gPortID);
+ }
+
+ // Clear the globals.
+
+ gPortID = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Comm_ClearError
+// ---------------------------------------------------------------------------
+// Clears the current serial errors.
+
+void Comm_ClearError (void)
+{
+ // Exit if communications have not been established.
+
+ if (!gPortID)
+ return;
+
+ if (gSerialManagerVersion <= 2)
+ {
+ SerClearErr (gPortID);
+ }
+ else // if (gSerialManagerVersion >= 3)
+ {
+ SrmClearErr (gPortID);
+ }
+}
diff --git a/ROMTransfer/Source/SerialPortTools.h b/ROMTransfer/Source/SerialPortTools.h
new file mode 100644
index 0000000..bf25cde
--- /dev/null
+++ b/ROMTransfer/Source/SerialPortTools.h
@@ -0,0 +1,52 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef SERIAL_PORT_TOOLS_H
+#define SERIAL_PORT_TOOLS_H
+
+// Globals.
+
+#define kPort_Pilot 0
+
+#define kBaud_1200 1200
+#define kBaud_2400 2400
+#define kBaud_4800 4800
+#define kBaud_9600 9600
+#define kBaud_14400 14400
+#define kBaud_19200 19200
+#define kBaud_28800 28800
+#define kBaud_38400 38400
+#define kBaud_57600 57600
+#define kBaud_57600 57600
+#define kBaud_115200 115200
+
+
+// Prototypes.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+Int16 Comm_Initialize (UInt32 iBaud);
+Err Comm_Receive (void* bufP, UInt32 count, UInt32 timeout);
+Err Comm_Send (void* bufP, UInt32 count);
+void Comm_Dispose (void);
+void Comm_ClearError (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Scripting/Perl/EmFunctions.pm b/Scripting/Perl/EmFunctions.pm
new file mode 100644
index 0000000..4454ff7
--- /dev/null
+++ b/Scripting/Perl/EmFunctions.pm
@@ -0,0 +1,1023 @@
+########################################################################
+#
+# File: EmFunctions.pm
+#
+# Purpose: Perl wrappers for Palm OS functions
+#
+# Description: This file contains Perl equivalents of Palm OS
+# functions like DmNumDatabases, FrmGetActiveForm,
+# etc. Currently, the functions here are generated
+# by hand, and so only a small subset of Palm OS
+# functions are wrapped. In the future, this file
+# (or files) may be automatically generated by
+# a script that converts the SDK headers.
+#
+# In general, functions follow the calling
+# conventions in the SDK headers. However, there
+# are exceptions. See the comments before each
+# subroutine for details.
+#
+########################################################################
+
+package EmFunctions;
+
+use EmRPC;
+use EmSysTraps;
+
+use strict;
+use vars qw(@ISA @EXPORT);
+
+use Exporter;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ CtlGetLabel
+
+ DmNumDatabases DmFindDatabase DmGetDatabase DmDatabaseInfo
+ DmNextOpenDatabase DmOpenDatabaseInfo
+
+ EvtEnqueuePenPoint EvtEnqueueKey
+
+ FrmGetActiveForm FrmGetLabel FrmGetNumberOfObjects FrmGetObjectBounds
+ FrmGetObjectId FrmGetObjectIndex FrmGetObjectPtr FrmGetObjectType FrmGetTitle
+
+ FtrGet
+
+ HwrDisplayAttributes
+
+ MemChunkFree MemPtrFree MemPtrNew MemPtrSetOwner MemStoreInfo MemCardInfo
+ MemNumCards MemNumHeaps MemNumRAMHeaps
+ MemHeapID MemHeapDynamic MemHeapFlags MemHeapSize
+
+ SysUIAppSwitch SysCurAppDatabase
+
+ WinDisplayToWindowPt WinWindowToDisplayPt
+
+ dmModeReadOnly dmModeWrite dmModeReadWrite
+ dmModeLeaveOpen dmModeExclusive dmModeShowSecret
+
+ frmFieldObj frmControlObj frmListObj frmTableObj frmBitmapObj frmLineObj
+ frmFrameObj frmRectangleObj frmLabelObj frmTitleObj frmPopupObj
+ frmGraffitiStateObj frmGadgetObj frmScrollBarObj
+
+ hwrDispType hwrDispRev hwrDispVers hwrDispAllDepths hwrDispMaxDepth
+ hwrDispBootDepth hwrDispMaxGrays hwrDispHorizontal hwrDispVertical hwrDispVRAMBaseAddr
+ hwrDispVRAMSize hwrDispColor hwrDispName hwrDispBaseAddr hwrDispDepth
+ hwrDispWidth hwrDispHeight hwrDispRowBytes hwrDispBacklight hwrDispBrightness
+ hwrDispContrast hwrDispDbgIndicator hwrDispEndAddr hwrDispBufferMask hwrDispResolutionX
+ hwrDispResolutionY hwrDispMemAccessOK
+);
+
+use constant dmModeReadOnly => 0x01;
+use constant dmModeWrite => 0x02;
+use constant dmModeReadWrite => 0x03;
+use constant dmModeLeaveOpen => 0x04;
+use constant dmModeExclusive => 0x08;
+use constant dmModeShowSecret => 0x10;
+
+use constant frmFieldObj => 0;
+use constant frmControlObj => 1;
+use constant frmListObj => 2;
+use constant frmTableObj => 3;
+use constant frmBitmapObj => 4;
+use constant frmLineObj => 5;
+use constant frmFrameObj => 6;
+use constant frmRectangleObj => 7;
+use constant frmLabelObj => 8;
+use constant frmTitleObj => 9;
+use constant frmPopupObj => 10;
+use constant frmGraffitiStateObj => 11;
+use constant frmGadgetObj => 12;
+use constant frmScrollBarObj => 13;
+
+use constant hwrDispType => 0; # (4) Get 4-char code for controller/display combination.
+use constant hwrDispRev => 1; # (2) Get Hardware Revision
+use constant hwrDispVers => 2; # (2) Get Display driver HAL version.
+use constant hwrDispAllDepths => 3; # (2) Get All display depths in bitmap format.
+use constant hwrDispMaxDepth => 4; # (2) Get Maximum supported bit depth.
+use constant hwrDispBootDepth => 5; # (2) The preset boot depth of the device.
+use constant hwrDispMaxGrays => 6; # (2) Get Maximum number of grays supported by HW.
+use constant hwrDispHorizontal => 7; # (2) Get Maximum hortizontal pixels supported by Display.
+use constant hwrDispVertical => 8; # (2) Get Maximum vertical pixels supported by Display.
+use constant hwrDispVRAMBaseAddr => 9; # (4) Get Base address of video memory if any (if 0, no VRAM)
+use constant hwrDispVRAMSize => 10; # (4) Get Size of VRAM (if 0, no VRAM)
+use constant hwrDispColor => 11; # (2) Get True if controller AND display supprt color.
+use constant hwrDispName => 12; #(32) Get 32 character string for controller and Hardware.
+
+use constant hwrDispBaseAddr => 13; # (4) Get/Set Base Address for current screen memory (somewhere in VRAM or main RAM)
+use constant hwrDispDepth => 14; # (2) Get/Set Depth of display
+use constant hwrDispWidth => 15; # (2) Get/Set current display width
+use constant hwrDispHeight => 16; # (2) Get/Set current display height
+use constant hwrDispRowBytes => 17; # (2) Get/Set bytes in a row of display (changed when depth or width change)
+use constant hwrDispBacklight => 18; # (1) Get/Set Backlight status: 0 = off, 1 = on (returns 0 on Austin)
+use constant hwrDispBrightness => 19; # (1) Get/Set Brightness level: 0(min/off)...255(max)
+use constant hwrDispContrast => 20; # (1) Get/Set Contrast Level: 0(min)...255(max)
+use constant hwrDispDbgIndicator => 21; # (2) Turn Debug Indicator on/off
+use constant hwrDispEndAddr => 22; # (4) Get last byte of screen memory
+use constant hwrDispBufferMask => 23; # (4) Mask for determining required display address alignment
+use constant hwrDispResolutionX => 24; # (?) Screen resolution
+use constant hwrDispResolutionY => 25; # (?) Screen resolution
+use constant hwrDispMemAccessOK => 26; # (1) true if controller can be accessed when bus clock disabled
+
+
+########################################################################
+#
+# FUNCTION: CtlGetLabel
+#
+# DESCRIPTION: Return a string pointer to the control's text label.
+#
+# PARAMETERS: Memory address on the remote device of the control
+# object. Usually the result of something like
+# FrmGetObjectPtr on a control object.
+#
+# RETURNED: A list containing the memory address on the remote
+# device of the label, and the label string itself.
+#
+########################################################################
+
+sub CtlGetLabel
+{
+ # const Char* CtlGetLabel (const ControlType * ctlP)
+
+ my ($return, $format) = ("string", "rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapCtlGetLabel, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmNumDatabases
+#
+# DESCRIPTION: Returns the number of databases on a card
+#
+# PARAMETERS: card number
+#
+# RETURNS: Number of databases found
+#
+########################################################################
+
+sub DmNumDatabases
+{
+ # UInt DmNumDatabases (UInt cardNo)
+
+ my ($return, $format) = ("int16", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmNumDatabases, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmDatabaseInfo
+#
+# DESCRIPTION: Retrieves database information
+#
+# PARAMETERS: Card number, database LocalID
+#
+# RETURNS: Result code from function, as well as the components
+# of a hash. To get the result, assign the result
+# of this function to ($err, %results). You can
+# then extract individual values from %results using
+# hash operators and the following keys: name
+# attributes, version, crDate, modDate, bckUpDate,
+# modNum, appInfoID, sortInfoID, type, and creator.
+# Example: $name = $results{name}.
+#
+########################################################################
+
+sub DmDatabaseInfo
+{
+ # Err DmDatabaseInfo (UInt cardNo, LocalID dbID, const CharPtr nameP,
+ # UIntPtr attributesP, UIntPtr versionP, ULongPtr crDateP,
+ # ULongPtr modDateP, ULongPtr bckUpDateP,
+ # ULongPtr modNumP, LocalID* appInfoIDP,
+ # LocalID* sortInfoIDP, ULongPtr typeP,
+ # ULongPtr creatorP)
+
+ my ($cardNo, $dbID) = @_;
+
+ my ($format) = "int16 LocalID string32 int16* int16* int32* int32* " .
+ "int32* int32* LocalID* LocalID* int32* int32*";
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmDatabaseInfo, $format,
+ $cardNo, $dbID, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ ($D0, name => $params[2],
+ attributes => $params[3],
+ version => $params[4],
+ crDate => $params[5],
+ modDate => $params[6],
+ bckUpDate => $params[7],
+ modNum => $params[8],
+ appInfoID => $params[9],
+ sortInfoID => $params[10],
+ type => $params[11],
+ creator => $params[12]);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmFindDatabase
+#
+# DESCRIPTION: Searches for a database by name
+#
+# PARAMETERS: card number, database name
+#
+# RETURNS: LocalID of database header
+#
+########################################################################
+
+sub DmFindDatabase
+{
+ # LocalID DmFindDatabase (UInt cardNo, const CharPtr nameP)
+
+ my ($return, $format) = ("LocalID", "int16 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmFindDatabase, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmGetDatabase
+#
+# DESCRIPTION: Finds the nth database on the card
+#
+# PARAMETERS: card number, database index
+#
+# RETURNS: LocalID of database header
+#
+########################################################################
+
+sub DmGetDatabase
+{
+ # LocalID DmGetDatabase (UInt16 cardNo, Uint16 index)
+
+ my ($return, $format) = ("LocalID", "int16 int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmGetDatabase, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmNextOpenDatabase
+#
+# DESCRIPTION: Returns the next open database
+#
+# PARAMETERS: A DmOpenRef (or 0 the first time)
+#
+# RETURNS: The next DmOpenRef, or 0 at the end of the chain
+#
+########################################################################
+
+sub DmNextOpenDatabase
+{
+ # DmOpenRef DmNextOpenDatabase (DmOpenRef currentP)
+
+ my ($return, $format) = ("rptr", "rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmNextOpenDatabase, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: DmOpenDatabaseInfo
+#
+# DESCRIPTION: Retrieves database information
+#
+# PARAMETERS: DmOpenRef
+#
+# RETURNS: Result code from function, as well as the components
+# of a hash. To get the result, assign the result
+# of this function to ($err, %results). You can
+# then extract individual values from %results using
+# hash operators and the following keys: cardNo, dbID,
+# openCount, mode, resDB.
+# Example: $name = $results{name}.
+#
+########################################################################
+
+sub DmOpenDatabaseInfo
+{
+ # Err DmOpenDatabaseInfo (DmOpenRef dbP, LocalID *dbIDP,
+ # UInt16 *openCountP, UInt16 *modeP, UInt16 *cardNoP,
+ # Boolean *resDBP)
+
+ my ($format) = "rptr LocalID* int16* int16* int16* int16*";
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapDmOpenDatabaseInfo, $format, @_, 0, 0, 0, 0, 0);
+
+ ($D0, dbID => $params[1],
+ openCount => $params[2],
+ mode => $params[3],
+ cardNo => $params[4],
+ resDB => $params[5]);
+}
+
+
+########################################################################
+#
+# FUNCTION: EvtEnqueuePenPoint
+#
+# DESCRIPTION: Called by the digitizer interrupt routine to enqueue
+# a pen coordinate into the pen queue.
+#
+# PARAMETERS: x and y coordinates, subtracted from 256.
+# Example: EvtEnqueuePoint (256 - 100, 256 - 80)
+# Pass in (-1, -1) to enqueue a Pen Up.
+#
+# RETURNS: size of queue in bytes
+#
+########################################################################
+
+sub EvtEnqueuePenPoint
+{
+ # Err EvtEnqueuePenPoint (PointType* ptP)
+
+ my ($return, $format) = ("Err", "point");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapEvtEnqueuePenPoint, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: EvtEnqueueKey
+#
+# DESCRIPTION: Called by the digitizer interrupt routine to enqueue
+# a key into the key queue.
+#
+# PARAMETERS: WChar ascii, UInt16 keycode, UInt16 modifiers
+#
+# RETURNS: size of queue in bytes
+#
+########################################################################
+
+sub EvtEnqueueKey
+{
+ # Err EvtEnqueueKey (WChar ascii, UInt16 keycode, UInt16 modifiers)
+
+ my ($return, $format) = ("Err", "int16 int16 int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapEvtEnqueueKey, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetActiveForm
+#
+# DESCRIPTION: This routine returns the currently active form.
+#
+# PARAMETERS: nothing
+#
+# RETURNED: Memory address on the remote device of the form.
+#
+########################################################################
+
+sub FrmGetActiveForm
+{
+ # FormPtr FrmGetActiveForm (void)
+
+ my ($return, $format) = ("rptr", "");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetActiveForm, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetLabel
+#
+# DESCRIPTION: This routine return the text of the specified label object
+# in the specified form.
+#
+# PARAMETERS: formP - memory block that contains the form.
+# labelID - id of the label object.
+#
+# RETURNED: A list containing the memory address on the remote
+# device of the label, and the label string itself.
+#
+########################################################################
+
+sub FrmGetLabel
+{
+ # CharPtr FrmGetLabel (const FormPtr frm, const Word lableID)
+
+ my ($return, $format) = ("string", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetLabel, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetNumberOfObjects
+#
+# DESCRIPTION: This routine returns the number of objects in a form.
+#
+# PARAMETERS: formP memory block that contains the form.
+#
+# RETURNED: number of object in the form specified
+#
+########################################################################
+
+sub FrmGetNumberOfObjects
+{
+ # Word FrmGetNumberOfObjects (const FormPtr frm)
+
+ my ($return, $format) = ("int16", "rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetNumberOfObjects, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetObjectBounds
+#
+# DESCRIPTION: This routine returns the bounds of the specified form object
+#
+# PARAMETERS: formP memory block that contains the form.
+# objIndex index of the object
+#
+# RETURNS: The components of a hash. To get the result, assign
+# the result of this function to %results. You can
+# then extract individual values from %results using
+# hash operators and the following keys: top, left
+# bottom, right, width, height.
+# Example: $top = $results{top}.
+#
+########################################################################
+
+sub FrmGetObjectBounds
+{
+ # void FrmGetObjectBounds (const FormPtr frm, const Word pObjIndex, const RectanglePtr r)
+
+ my ($form, $obj_index) = @_;
+
+ my ($return, $format) = ("", "rptr int16 rect");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetObjectBounds, $format,
+ $form, $obj_index, {});
+
+ my ($foo) = $params[2];
+ %$foo;
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetObjectId
+#
+# DESCRIPTION: This routine returns the id of the object specified.
+# An id is a value specified by the application developer
+# that uniquely identifies an object.
+#
+# PARAMETERS: formP memory block that contains the form.
+# objIndex item number of the object
+#
+# RETURNED: Object ID.
+#
+########################################################################
+
+sub FrmGetObjectId
+{
+ # UInt16 FrmGetObjectId (const FormType * formP, UInt16 objIndex)
+
+ my ($return, $format) = ("int16", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetObjectId, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetObjectIndex
+#
+# DESCRIPTION: This routine returns the item number of an object, the
+# item number is the position of the object in the objects
+# list.
+#
+# PARAMETERS: formP memory block that contains the form.
+# objId id of an object in the form.
+#
+# RETURNED: item number of an object (the first item number is 0).
+#
+########################################################################
+
+sub FrmGetObjectIndex
+{
+ # UInt16 FrmGetObjectIndex (const FormType * formP, UInt16 objId)
+
+ my ($return, $format) = ("int16", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetObjectIndex, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetObjectPtr
+#
+# DESCRIPTION: This routine returns a pointer to the data structure of an
+# object in a form.
+#
+# PARAMETERS: formP memory block that contains the form.
+# objIndex item number of the object
+#
+# RETURNED: Memory address on the remote device of the object.
+# The contents of the object depend on the object type.
+#
+########################################################################
+
+sub FrmGetObjectPtr
+{
+ # VoidPtr FrmGetObjectPtr (const FormPtr frm, const Word objIndex)
+
+ my ($return, $format) = ("rptr", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetObjectPtr, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetObjectType
+#
+# DESCRIPTION: This routine returns the type of an object.
+#
+# PARAMETERS: formP memory block that contains the form.
+# objIndex item number of the object
+#
+# RETURNED: FormObjectType of the item specified
+#
+########################################################################
+
+sub FrmGetObjectType
+{
+ # FormObjectKind FrmGetObjectType (const FormPtr frm, const Word objIndex)
+
+ my ($return, $format) = ("int16", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetObjectType, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FrmGetTitle
+#
+# DESCRIPTION: This routine returns a pointer to the title string of a
+# form.
+#
+# PARAMETERS: formP - memory block that contains the form.
+#
+# RETURNED: A list containing the memory address on the remote
+# device of the title, and the title string itself.
+#
+########################################################################
+
+sub FrmGetTitle
+{
+ # const Char * FrmGetTitle (const FormType * formP)
+
+ my ($return, $format) = ("string", "rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFrmGetTitle, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: FtrGet
+#
+# DESCRIPTION: Get a PalmOS feature setting
+#
+# PARAMETERS: creator - creator id
+# featureNum - number of feature requested
+#
+# RETURNS: Result code and value of feature
+#
+########################################################################
+
+sub FtrGet
+{
+ # Err FtrGet(UInt32 creator, UInt16 featureNum, UInt32 *valueP)
+
+ my ($creator, $featureNum) = @_;
+
+ my ($return, $format) = ("Err", "int32 int16 int32*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapFtrGet, $format, $creator, $featureNum, 0);
+ ($D0, $params[2]);
+}
+
+
+########################################################################
+#
+# FUNCTION: HwrDisplayAttributes
+#
+# DESCRIPTION: Get or set Info about the Hwr display and controller
+#
+# PARAMETERS: set - true to set, false to get. Ignored for read-only attributes
+# attr - HwrDisplayAttrType
+# dataP - data to get or set. Must be non-NULL, as read-only
+# attributes are always read, regardless of 'set' param.
+#
+# RETURNS:
+#
+########################################################################
+
+sub HwrDisplayAttributes
+{
+ # Err HwrDisplayAttributes(Boolean set, HwrDisplayAttrType attr, void* dataP)
+
+ my ($set, $attr, $data) = @_;
+
+ my ($return, $format) = ("Err", "int8 int8 block");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHwrDisplayAttributes, $format, $set, $attr, $data);
+ ($D0, $params[2]);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemChunkFree
+#
+# DESCRIPTION: Disposes of a chunk
+#
+# PARAMETERS: Pointer to chunk
+#
+# RETURNS: 0 if no error
+#
+########################################################################
+
+sub MemChunkFree
+{
+ my ($return, $format) = ("Err", "rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemChunkFree, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemPtrFree
+#
+# DESCRIPTION: Disposes of a chunk
+#
+# PARAMETERS: Pointer to chunk
+#
+# RETURNS: 0 if no error
+#
+########################################################################
+
+sub MemPtrFree
+{
+ MemChunkFree (@_);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemPtrNew
+#
+# DESCRIPTION: Allocates a non-movable chunk in the dynamic heap
+#
+# PARAMETERS: requested size of chunk
+#
+# RETURNS: Ptr to chunk, or 0 if error
+#
+########################################################################
+
+sub MemPtrNew
+{
+ my ($return, $format) = ("rptr", "int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemPtrNew, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemPtrSetOwner
+#
+# DESCRIPTION: Sets the owner ID of a chunk
+#
+# PARAMETERS: chunk data pointer
+#
+# RETURNS: 0 if no error
+#
+########################################################################
+
+sub MemPtrSetOwner
+{
+ # Err MemPtrSetOwner (void* p, UInt16 owner)
+
+ my ($return, $format) = ("Err", "rptr int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemPtrSetOwner, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/*******************************************************************
+#
+# FUNCTION: MemStoreInfo
+#
+# DESCRIPTION: Returns information on either the RAM store or
+# the ROM store for a memory card.
+#
+# PARAMETERS: 1) cardNo - either 0 or 1
+# 2) storeNumber - 0 for ROM, 1 for RAM
+# 3) versionP - Pointer to version variable, or 0.
+# 4) flagsP - Pointer to flags variable, or 0.
+# 5) nameP - Pointer to character array (32 bytes), or 0.
+# 6) crDateP - Pointer to creation date variable, or 0.
+# 7) bckUpDateP - Pointer to backup date variable, or 0.
+# 8) heapListOffsetP - Pointer to heapListOffset variable, or 0.
+# 9) initCodeOffset1P - Pointer to initCodeOffset1 variable, or 0.
+# 10) initCodeOffset2P - Pointer to initCodeOffset2 variable, or 0.
+# 11) databaseDirIDP - Pointer to database directory chunk ID variable, or 0.
+#
+# RETURNS: 0 if no error, error number otherwise
+#
+#*******************************************************************/
+sub MemStoreInfo
+{
+ my ($cardNo, $storeNumber) = @_;
+ my ($return, $format) = ("Err", "int16 int16 int16* int16* string int32* int32* int32* int32* int32* LocalID*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemStoreInfo, $format, $cardNo, $storeNumber, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ ($D0, version => $params[2],
+ flags => $params[3],
+ name => $params[4],
+ crDate => $params[5],
+ bckUpDate => $params[6],
+ heapListOffset => $params[7],
+ initCodeOffset1 => $params[8],
+ initCodeOffset2 => $params[9],
+ databaseDirID => $params[10]);
+}
+
+
+#/*******************************************************************
+#
+# FUNCTION: MemCardInfo
+#
+# DESCRIPTION: Returns information on either the RAM store or
+# the ROM store for a memory card.
+#
+# PARAMETERS:
+#
+# RETURNS: 0 if no error, error number otherwise
+#
+#*******************************************************************/
+sub MemCardInfo
+{
+ my ($cardNo) = @_;
+ my ($return, $format) = ("Err", "int16 string32 string32 int16* int32* int32* int32* int32*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC(EmSysTraps::sysTrapMemCardInfo, $format, $cardNo, 0, 0, 0, 0, 0, 0, 0);
+
+ ($D0, cardName => $params[1],
+ manufName => $params[2],
+ version => $params[3],
+ crDate => $params[4],
+ romSize => $params[5],
+ ramSize => $params[6],
+ freeBytes => $params[7]);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemNumCards
+#
+# DESCRIPTION: Counts the cards on the device.
+#
+# PARAMETERS: none
+#
+# RETURNS: Usually 1. :-)
+#
+########################################################################
+sub MemNumCards
+{
+ my ($return, $format) = ("int16", "");
+ my ($D0, $A0) = EmRPC::DoRPC (EmSysTraps::sysTrapMemNumCards, $format);
+ EmRPC::ReturnValue ($return, $D0, $A0);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemNumHeaps
+#
+# DESCRIPTION: Counts the heaps on the given card.
+#
+# PARAMETERS: Card number
+#
+# RETURNS: How many
+#
+########################################################################
+sub MemNumHeaps
+{
+ my ($return, $format) = ("int16", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemNumHeaps, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemNumRAMHeaps
+#
+# DESCRIPTION: Counts the RAM heaps on the given card.
+#
+# PARAMETERS: Card number
+#
+# RETURNS: How many
+#
+########################################################################
+sub MemNumRAMHeaps
+{
+ my ($return, $format) = ("int16", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemNumRAMHeaps, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemHeapID
+#
+# DESCRIPTION: Returns the heap ID of the j'th heap on the i'th card.
+#
+# PARAMETERS: Card number, heap index
+#
+# RETURNS: A heap ID
+#
+########################################################################
+sub MemHeapID
+{
+ my ($return, $format) = ("int16", "int16 int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemHeapID, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemHeapDynamic
+#
+# DESCRIPTION: Returns whether the given heap is dynamic.
+#
+# PARAMETERS: A heap ID
+#
+# RETURNS: Boolean
+#
+########################################################################
+sub MemHeapDynamic
+{
+ my ($return, $format) = ("int16", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemHeapDynamic, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemHeapFlags
+#
+# DESCRIPTION: Returns the given heap's flags.
+#
+# PARAMETERS: A heap ID
+#
+# RETURNS: The flags
+#
+########################################################################
+sub MemHeapFlags
+{
+ my ($return, $format) = ("int16", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemHeapFlags, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: MemHeapSize
+#
+# DESCRIPTION: Returns the size of the given heap.
+#
+# PARAMETERS: A heap ID
+#
+# RETURNS: The size
+#
+########################################################################
+sub MemHeapSize
+{
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapMemHeapSize, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: SysUIAppSwitch
+#
+# DESCRIPTION: Tries to make the current UI application quit and
+# then launches the given UI application by card
+# number and database ID.
+#
+# PARAMETERS: cardNo, dbID, launchCmd, cmdPBP
+#
+# Note that in order to utilize the cmdPBP, you need
+# to first create a buffer on the remote side with
+# MemPtrNew and fill in its contents with
+# EmRPC::WriteBlock. If you want to pass NULL for
+# cmdPBP, specify zero for the last parameter.
+#
+# RETURNS: errNone if no err
+#
+########################################################################
+
+sub SysUIAppSwitch
+{
+ # Err SysUIAppSwitch(UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP)
+
+ my ($return, $format) = ("Err", "int16 LocalID int16 rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapSysUIAppSwitch, $format, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/*******************************************************************
+#
+# FUNCTION: SysCurAppDatabase
+#
+# DESCRIPTION:
+#
+# PARAMETERS:
+#
+# RETURNS:
+#
+#*******************************************************************/
+sub SysCurAppDatabase {
+ my ($return, $format) = ("Err", "int16* LocalID*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC(EmSysTraps::sysTrapSysCurAppDatabase, $format, 0, 0);
+
+ ($D0, cardNum => $params[0],
+ databaseID => $params[1]);
+}
+
+
+########################################################################
+#
+# FUNCTION: WinDisplayToWindowPt
+#
+# DESCRIPTION: This routine converts a display-relative coordinate to
+# a window-relative coordinate. The coordinate returned is
+# relative to the draw window.
+#
+# PARAMETERS: xP <-> x coordinate to convert
+# yP <-> y coordinate to convert
+#
+# RETURNED: nothing
+#
+########################################################################
+
+sub WinDisplayToWindowPt
+{
+ # void WinDisplayToWindowPt (Coord * xP, Coord * yP)
+
+ my ($return, $format) = ("void", "Coord* Coord*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapWinDisplayToWindowPt, $format, @_);
+ ($params[0], $params[1]);
+}
+
+
+########################################################################
+#
+# FUNCTION: WinWindowToDisplayPt
+#
+# DESCRIPTION: This routine converts a window-relative coordinate to
+# a display-relative coordinate. The coordinate passed is
+# assumed to be relative to the draw window.
+#
+# PARAMETERS: xP <-> x coordinate to convert
+# yP <-> y coordinate to convert
+#
+# RETURNED: nothing
+#
+########################################################################
+
+sub WinWindowToDisplayPt
+{
+ # void WinWindowToDisplayPt (Coord * xP, Coord * yP)
+
+ my ($return, $format) = ("void", "Coord* Coord*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapWinWindowToDisplayPt, $format, @_);
+ ($params[0], $params[1]);
+}
+
+1;
diff --git a/Scripting/Perl/EmRPC.pm b/Scripting/Perl/EmRPC.pm
new file mode 100644
index 0000000..d02433d
--- /dev/null
+++ b/Scripting/Perl/EmRPC.pm
@@ -0,0 +1,1285 @@
+########################################################################
+#
+# File: EmRPC.pm
+#
+# Purpose: Low-level functions for using RPC with the Palm OS
+# Emulator.
+#
+# Description: This file contains base functions for using RPC:
+#
+# OpenConnection
+# Opens a socket to the Emulator
+#
+# CloseConnection
+# Closes the socket
+#
+# DoRPC
+# Full-service RPC packet sending and receiving,
+# including marshalling and unmarshalling of
+# parameters.
+#
+# ReadBlock
+# Read up to 256 bytes from the remote device's
+# memory.
+#
+# WriteBlock
+# Write up to 256 bytes to the remote device's
+# memory.
+#
+# ReadString
+# Read a C string from the remote device's memory.
+#
+# PrintString
+# Debugging utility. Prints a Perl string
+# (block of arbitrary data) as a hex dump.
+#
+########################################################################
+
+package EmRPC;
+
+use vars qw(@ISA @EXPORT);
+
+use Exporter;
+$VERSION = 1.00;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+ OpenConnection CloseConnection
+ DoRPC
+ ReadBlock WriteBlock
+ ReadString PrintString
+);
+
+use IO::Socket;
+use IO::File;
+
+use constant slkSocketDebugger => 0; # Debugger Socket
+use constant slkSocketConsole => 1; # Console Socket
+use constant slkSocketRemoteUI => 2; # Remote UI Socket
+use constant slkSocketDLP => 3; # Desktop Link Socket
+use constant slkSocketFirstDynamic => 4; # first dynamic socket ID
+use constant slkSocketPoserRPC => 14;
+
+use constant slkPktTypeSystem => 0; # System packets
+use constant slkPktTypeUnused1 => 1; # used to be: Connection Manager packets
+use constant slkPktTypePAD => 2; # PAD Protocol packets
+use constant slkPktTypeLoopBackTest => 3; # Loop-back test packets
+
+
+########################################################################
+#
+# FUNCTION: OpenConnection
+#
+# DESCRIPTION: Open a socket-based connection to Poser.
+#
+# PARAMETERS: Either "[<host>][:[<port>]]" (defaults are localhost and
+# 6415) to connect to an IPv4 socket, or a filename (with
+# at least one "/") to open a file (eg a device file), or
+# "@<fd>" to reopen an existing fd.
+#
+# "#<socket>" can be added to any of these, and causes the
+# given SLK socket to be used instead of slkSocketPoserRPC.
+#
+# The older form with two parameters, (<port> <host>), is
+# equivalent to "<host>:<port>".
+#
+# RETURNED: Nothing. Dies if fail to connect.
+#
+########################################################################
+
+sub OpenConnection
+{
+ # Are we already connected?
+ return if defined $sock;
+
+ # Rewrite the old two parameter (<port> <host>) form as <host>:<port>
+ local ($_) = join ":", reverse @_;
+ $_ = ":$_" unless /\D/; # Handle two parameters with <host> omitted
+
+ my $sname = (s/#(.*)//)? $1 : "PoserRPC";
+ $sname = "slkSocket\u$sname" unless $sname =~ /slkSocket/;
+ $sock_slkSocket = eval $sname;
+ die "invalid SLK socket '$sname'\n" if $sock_slkSocket =~ /\D/;
+
+ if (/^@(\d+)/)
+ {
+ my $fd = $1;
+ $sock = new_from_fd IO::Handle ($fd, "r+")
+ or die "cannot reopen fd $fd: $!\n";
+ }
+ elsif (m"/")
+ {
+ $sock = new IO::File ($_, O_RDWR)
+ or die "cannot open $_: $!\n";
+ }
+ else
+ {
+ my ($remote, $port) = split /:/, $_;
+ $remote = "localhost" unless $remote;
+ $port = 6415 unless $port;
+
+ $sock = new IO::Socket::INET( PeerAddr => $remote,
+ PeerPort => $port,
+ Proto => 'tcp')
+ or die "cannot connect to $_: $@\n";
+ }
+
+ $sock->autoflush (1);
+}
+
+
+########################################################################
+#
+# FUNCTION: CloseConnection
+#
+# DESCRIPTION: Close the socket connection to Poser.
+#
+# PARAMETERS: None.
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub CloseConnection
+{
+ close ($sock);
+ undef $sock;
+}
+
+
+########################################################################
+#
+# FUNCTION: DoRPC
+#
+# DESCRIPTION: Performs full, round-trip RPC service.
+#
+# PARAMETERS: Trap word of function to call.
+# Format string describing parameters.
+# Parameters to pass in the RPC call.
+#
+# The format string contains a series of format
+# descriptors. Descriptors must be seperated by
+# some sort of delimiter, which can be a space, a
+# common, a colon, or any combination of those. Each
+# descriptor has the following format:
+#
+# <type><optional size><optional "*">
+#
+# The "type" describes the parameter in the format
+# expected by the Palm OS. The RPC routines will
+# convert the Perl variable corresponding to the
+# parameter into the described type. The following
+# types are supported:
+#
+# int: integer
+# Err: 2 byte integer
+# Coord: 2 byte integer;
+# LocalID: 4 byte integer
+# HostErr: 4 byte integer
+# string: C string
+# rptr: Pointer to something back on
+# the emulated device
+# point: Palm OS PointType
+# rect: Palm OS RectangleType
+# block: Block of arbitrary data
+#
+# Some format types can accept a size specifier
+# after them. This size specifier is used when
+# a default parameter size cannot be implied, or
+# when you want to override the default parameter
+# size. The following describes how the size
+# specifier is handled for each parameter type:
+#
+# int:
+# Length specifier must be supplied, and
+# must be one of 8, 16, or 32.
+#
+# string:
+# Default length is the value as returned
+# by Perl's "length" function plus one.
+# You can override this value by including
+# your own length specifier.
+#
+# block:
+# Default length is the value as returned
+# by Perl's "length" function. You can
+# override this value by including your
+# own length specifier.
+#
+# all others:
+# Any specified size is ignored.
+#
+# In general, integer types are passed by value, and
+# all other types are passed by reference. That is
+# after all the parameters are marhsalled, sent to
+# the emulator, and unmarshalled, the "pass by value"
+# parameters are pushed directly onto the emulated
+# stack, and "pass by reference" parameters have
+# their addresses pushed onto the stack. You can
+# can change this behavior in one way: if you way
+# an integer to be passed by reference, then you
+# can append a "*" to its format specifier.
+#
+# Examples:
+#
+# "int16"
+# Pass a 2 byte integer
+#
+# "int32 string"
+# Pass a 4 byte integer, followed by
+# a C-string
+#
+# "block32"
+# Pass a 32 byte buffer, filling in
+# its contents as much as possible
+# with the given data
+#
+# "int16 in32 int32*"
+# Pass a 2 byte integer, followed by
+# a 4 byte integer, followed by a
+# 4 byte integer passed by reference.
+#
+# RETURNED: List containing:
+# Register D0
+# Register A0
+# Full parameter list. If any parameters were
+# "pass by reference", you'll receive the
+# updated parameters. If parameters are
+# "pass by value", you'll get them back just
+# the same way you provided them.
+#
+########################################################################
+
+sub DoRPC
+{
+ my ($trap_word, $format, @parameters) = @_;
+
+ my ($slkSocket) = $sock_slkSocket;
+ my ($slkPktType) = slkPktTypeSystem;
+ my ($send_body) = EmRPC::MakeRPCBody ($trap_word, $format, @parameters);
+
+ my ($packet) = MakePacket($slkSocket, $slkSocket, $slkPktType, $send_body);
+
+ SendPacket($packet);
+
+ my ($header, $body, $footer) = ReceivePacket();
+
+ EmRPC::UnmakeRPCBody ($body, $format);
+}
+
+
+########################################################################
+#
+# FUNCTION: ReturnValue
+#
+# DESCRIPTION: .
+#
+# PARAMETERS: .
+#
+# RETURNED: .
+#
+########################################################################
+
+sub ReturnValue
+{
+ my ($format, $D0, $A0, @parameters) = @_;
+
+ my ($type, $size, $by_ref) = GetFormat ($format, 0);
+
+ my ($result);
+
+ if ($type eq "int")
+ {
+ return $D0;
+ }
+ elsif ($type eq "string")
+ {
+ return ($A0, ReadString ($A0));
+ }
+ elsif ($type eq "rptr")
+ {
+ return $A0;
+ }
+
+ die "Unexpected type \"$type\" in EmRPC::ReturnValue, stopped";
+}
+
+
+########################################################################
+#
+# FUNCTION: ReadBlock
+#
+# DESCRIPTION: Read a range of memory from the remote device.
+#
+# PARAMETERS: address of remote device to start reading from.
+# number of bytes to read (256 max).
+#
+# RETURNED: A Perl string containing the result.
+#
+########################################################################
+
+$sysPktReadMemCmd = 0x01;
+$sysPktReadMemRsp = 0x81;
+
+ # typedef struct SysPktReadMemCmdType {
+ # _sysPktBodyCommon; // Common Body header
+ # void* address; // Address to read
+ # Word numBytes; // # of bytes to read
+ # } SysPktReadMemCmdType;
+ # typedef SysPktReadMemCmdType* SysPktReadMemCmdPtr;
+ #
+ # typedef struct SysPktReadMemRspType {
+ # _sysPktBodyCommon; // Common Body header
+ # // Byte data[?]; // variable size
+ # } SysPktReadMemRspType;
+ # typedef SysPktReadMemRspType* SysPktReadMemRspPtr;
+
+sub ReadBlock
+{
+ my ($address, $num_bytes) = @_;
+
+ my ($slkSocket) = $sock_slkSocket;
+ my ($slkPktType) = slkPktTypeSystem;
+ my ($send_body) = pack ("cxNn", $sysPktReadMemCmd, $address, $num_bytes);
+
+ my ($packet) = MakePacket($slkSocket, $slkSocket, $slkPktType, $send_body);
+
+ SendPacket($packet);
+
+ my ($header, $body, $footer) = ReceivePacket();
+
+ unpack ("xx a$num_bytes", $body);
+}
+
+
+########################################################################
+#
+# FUNCTION: WriteBlock
+#
+# DESCRIPTION: Write a range of bytes to the remote device.
+#
+# PARAMETERS: address to start writing to.
+# a Perl string containing the stuff to write.
+#
+# RETURNED: nothing
+#
+########################################################################
+
+$sysPktWriteMemCmd = 0x02;
+$sysPktWriteMemRsp = 0x82;
+
+ # typedef struct SysPktWriteMemCmdType {
+ # _sysPktBodyCommon; // Common Body header
+ # void* address; // Address to write
+ # Word numBytes; // # of bytes to write
+ # // Byte data[?]; // variable size data
+ # } SysPktWriteMemCmdType;
+ # typedef SysPktWriteMemCmdType* SysPktWriteMemCmdPtr;
+ #
+ # typedef struct SysPktWriteMemRspType {
+ # _sysPktBodyCommon; // Common Body header
+ # } SysPktWriteMemRspType;
+ # typedef SysPktWriteMemRspType* SysPktWriteMemRspPtr;
+
+sub WriteBlock
+{
+ my ($address, $data) = @_;
+
+ my ($slkSocket) = $sock_slkSocket;
+ my ($slkPktType) = slkPktTypeSystem;
+ my ($send_body) = pack ("cxNn", $sysPktWriteMemCmd, $address, length ($data)) . $data;
+
+ my ($packet) = MakePacket($slkSocket, $slkSocket, $slkPktType, $send_body);
+
+ SendPacket($packet);
+
+ ReceivePacket(); # receive the results, but we don't need to do anything with them
+}
+
+
+########################################################################
+#
+# FUNCTION: SendPacket
+#
+# DESCRIPTION: Send a fully-built packet to Poser. The socket
+# connection to Poser should already have been
+# established
+#
+# PARAMETERS: The packet to be sent.
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub SendPacket
+{
+ my ($packet) = @_;
+
+ print $sock $packet;
+}
+
+
+########################################################################
+#
+# FUNCTION: ReceivePacket
+#
+# DESCRIPTION: Receive a packet from Poser.
+#
+# PARAMETERS: None.
+#
+# RETURNED: The packet header, body, and footer as an array.
+#
+########################################################################
+
+sub ReceivePacket
+{
+ my ($header, $body, $footer);
+
+ my ($header_length) = 10;
+ sysread($sock, $header, $header_length);
+
+ my ($body_length) = GetBodySize($header);
+ sysread($sock, $body, $body_length);
+
+ my ($footer_length) = 2;
+ sysread($sock, $footer, $footer_length);
+
+ ($header, $body, $footer);
+}
+
+
+########################################################################
+#
+# FUNCTION: MakePacket
+#
+# DESCRIPTION: Builds up a complete packet for sending to Poser
+# including the header, body, and footer.
+#
+# PARAMETERS: $src - the source SLP socket. Generally something
+# like slkSocketDebugger or slkSocketConsole.
+#
+# $dest - the destination SLP socket.
+#
+# $type - the type of packet. Generally something
+# like slkPktTypeSystem or slkPktTypePAD.
+#
+# $body - the body of the packet.
+#
+# RETURNED: The built packet as a Perl string. The header and
+# footer checksums will be calculated and filled in.
+#
+########################################################################
+
+ # struct SlkPktHeaderType
+ # {
+ # Word signature1; // X first 2 bytes of signature
+ # Byte signature2; // X 3 and final byte of signature
+ # Byte dest; // -> destination socket Id
+ # Byte src; // -> src socket Id
+ # Byte type; // -> packet type
+ # Word bodySize; // X size of body
+ # Byte transID; // -> transaction Id
+ # // if 0 specified, it will be replaced
+ # SlkPktHeaderChecksum checksum; // X check sum of header
+ # };
+ #
+ # struct SlkPktFooterType
+ # {
+ # Word crc16; // header and body crc
+ # };
+
+$header_template = "H6CCCnCC"; # 6 Hex digits, 3 unsigned chars, a B.E. short, 2 unsigned chars
+$footer_template = "n"; # a B.E. short
+
+$signature = "BEEFED";
+
+sub MakePacket
+{
+ my ($src, $dest, $type, $body) = @_;
+
+ if (not defined($transID))
+ {
+ $transID = 0;
+ }
+
+ ++$transID;
+
+ my ($bodySize) = length ($body);
+ my ($header_checksum) = CalcHeaderChecksum ($signature, $dest, $src, $type, $bodySize, $transID);
+
+ my ($header) = pack ($header_template, $signature, $dest, $src, $type, $bodySize, $transID, $header_checksum);
+
+# my ($footer_checksum) = CalcFooterChecksum ($header, &body);
+ my ($footer_checksum) = 0;
+ my ($footer) = pack ($footer_template, $footer_checksum);
+
+ $header . $body . $footer;
+}
+
+
+########################################################################
+#
+# FUNCTION: CalcHeaderChecksum
+#
+# DESCRIPTION: Calculate that checksum value for the packet header.
+#
+# PARAMETERS: The components of the header.
+#
+# RETURNED: The checksum that should be placed in the SLP
+# packet header.
+#
+########################################################################
+
+sub CalcHeaderChecksum
+{
+ my ($signature, $dest, $src, $type, $bodySize, $transID) = @_;
+
+ my ($checksum, $temp_buffer);
+
+ $checksum = 0;
+
+ $temp_buffer = pack ($header_template, $signature, $dest, $src, $type, $bodySize, $transID, 0);
+ @bytes = unpack("C8", $temp_buffer);
+ $checksum = $bytes[0] + $bytes[1] + $bytes[2] + $bytes[3] + $bytes[4] +
+ $bytes[5] + $bytes[6] + $bytes[7];
+
+ $checksum % 256;
+}
+
+
+########################################################################
+#
+# FUNCTION: CalcFooterChecksum
+#
+# DESCRIPTION: Calculate the checksum value for the packet footer.
+#
+# PARAMETERS: The header and body.
+#
+# RETURNED: The checksum that should be placed in the SLP
+# packet footer.
+#
+########################################################################
+
+sub CalcFooterChecksum
+{
+ my ($header, $body) = @_;
+
+ my ($checksum, $temp_buffer);
+
+ $temp_buffer = $header . $body;
+
+ $checksum = unpack("%16c*", $temp_buffer); # Wrong kind of checksum!
+}
+
+
+########################################################################
+#
+# FUNCTION: MakeRPCBody
+#
+# DESCRIPTION: Create the body of an RPC packet, suitable for
+# being passed off to MakePacket.
+#
+# PARAMETERS: The "trap word" of the trap that needs to be called
+# (as defined by the constants in SysTraps.pm) and
+# the parameters of the RPC call, as created by the
+# MakeParam function.
+#
+# RETURNED: The body of the packet as a string.
+#
+########################################################################
+
+ # struct SysPktRPCType
+ # {
+ # _sysPktBodyCommon; // Common Body header
+ # Word trapWord; // which trap to execute
+ # DWord resultD0; // result from D0 placed here
+ # DWord resultA0; // result from A0 placed here
+ # Word numParams; // how many parameters follow
+ # // Following is a variable length array ofSlkRPCParamInfo's
+ # SysPktRPCParamType param[1];
+ # };
+
+$rpc_header_template = "CxH4NNn"; # unsigned byte, filler, 4 hex digits, 2 B.E. longs, B.E. short
+$sysPktRPCCmd = 0x0A;
+$sysPktRPCRsp = 0x8A;
+
+sub MakeRPCBody
+{
+ my ($trapword, $format, @param_list) = @_;
+
+ my ($rpc_header) = pack ($rpc_header_template, $sysPktRPCCmd, $trapword, 0, 0, $#param_list + 1);
+ my ($rpc_body) = join ("", $rpc_header, Marshal($format, @param_list));
+
+ $rpc_body;
+}
+
+sub UnmakeRPCBody
+{
+ my ($body, $format) = @_;
+
+ my ($cmd, $trap_word, $D0, $A0, $num_params, $packed_parms) = unpack ("$rpc_header_template a*", $body);
+ my (@parms) = Unmarshal($packed_parms, $format);
+
+ return ($D0, $A0, @parms);
+}
+
+
+$rpc2_header_template = "CxH4NNN"; # unsigned byte, filler, 4 hex digits, 3 B.E. longs
+$sysPktRPC2Cmd = 0x20;
+$sysPktRPC2Rsp = 0xA0;
+
+sub MakeRPC2Body
+{
+ my ($trapword, $reg_list, @param_list) = @_;
+
+ my ($rpc_header) = pack ($rpc_header_template, $sysPktRPCCmd, $trapword, 0, 0, 0);
+ my ($param_count) = pack ("n", $#param_list + 1);
+ my ($rpc_body) = join ("", $rpc_header, $reg_list, $param_count, reverse @param_list);
+
+ $rpc_body;
+}
+
+
+########################################################################
+#
+# FUNCTION: PackRegList
+#
+# DESCRIPTION: Pack a list of register values into the format
+# needed by an RPC2 packet.
+#
+# PARAMETERS: An associative array, where each key contains Ax
+# or Dx, and the value contains the register value.
+#
+# RETURNED: The packed registers as a string.
+#
+########################################################################
+
+sub PackRegList
+{
+ my (%reg_list) = @_;
+
+ my ($dreg_bits, $areg_bits, $dregs, $aregs);
+
+ $dreg_bits = 0;
+ $areg_bits = 0;
+ $dregs = "";
+ $aregs = "";
+
+ foreach $key (sort keys %reg_list)
+ {
+ my($reg_space) = substr($key, 0, 1);
+ my($bit_to_set) = (1 << (ord(substr($key, 1, 1)) - ord("0")));
+ my($value) = $reg_list{$key};
+
+ if ($reg_space eq "D")
+ {
+ $dreg_bits |= $bit_to_set;
+ $dregs .= pack ("N", $value);
+ }
+ else
+ {
+ $areg_bits |= $bit_to_set;
+ $aregs .= pack ("N", $value);
+ }
+ }
+
+ my ($result) = join ("", pack("CC", $dreg_bits, $areg_bits), $dregs, $aregs);
+}
+
+
+########################################################################
+#
+# FUNCTION: MakeParam
+#
+# DESCRIPTION: Create a parameter array element, suitable for being
+# added to other parameter array elements and --
+# eventually -- to an RPC packet body.
+#
+# PARAMETERS: $data - the data to be added.
+# $data_len - the length of the data to be added. If
+# greater than zero, then we assume $data to be
+# an integer. If equal to zero, then we assume
+# data to be a string where the length of the
+# string is determined by the length () function.
+# If less than zero, then data is assumed to be
+# a buffer with a length of -$data.
+# $by_ref - zero if the parameter is to be treated as
+# pass-by-value. Non-zero if it's pass-by-ref.
+#
+# RETURNED: A parameter string that can be appended to a longer
+# string of parameters. If the length of the string
+# would otherwise be odd, a padding byte is added.
+#
+########################################################################
+
+ # struct SysPktRPCParamInfo
+ # {
+ # Byte byRef; // true if param is by reference
+ # Byte size; // # of Bytes of paramData (must be even)
+ # Word data[1]; // variable length array of paramData
+ # };
+
+sub ToParamBlock
+{
+ my ($data, $data_len) = @_;
+
+ die "Undefined \$data, stopped" unless defined($data);
+ die "\$data_len is negative, stopped" if ($data_len < 0);
+
+ ## If data_len == 0, determine the length using the length () function.
+ ## Else, use the given length.
+
+ if ($data_len == 0)
+ {
+ $data_len = length ($data);
+ }
+ else
+ {
+ $data = pack ("a$data_len", $data);
+ }
+
+ ## Pack up the data.
+
+ my ($param) = pack ("CC", 1, $data_len) . $data;
+
+ ## Make sure the packed data is an even number of bytes long.
+
+ if (($data_len % 2) != 0)
+ {
+ $param .= "\0";
+ }
+
+ $param;
+}
+
+
+sub FromParamBlock
+{
+ my ($param, $data_len) = @_;
+
+ die "Undefined \$param, stopped" unless defined($param);
+ die "\$data_len is negative, stopped" if ($data_len < 0);
+
+ ## Just ignore the $data_len and use what's in the parameter block.
+
+ $data_len = unpack ("xC", $param);
+
+ unpack ("xxa$data_len", $param);
+}
+
+
+sub ToParamInt
+{
+ my ($data, $data_len, $by_ref) = @_;
+
+ die "Undefined \$data, stopped" unless defined($data);
+
+ my ($format);
+
+ if ($data_len == 8)
+ {
+ $format = ("CCCx");
+ $data_len = 1;
+ }
+ elsif ($data_len == 16 || $data_len == 0)
+ {
+ $format = ("CCn");
+ $data_len = 2;
+ }
+ elsif ($data_len == 32)
+ {
+ $format = ("CCN");
+ $data_len = 4;
+ }
+ else
+ {
+ die "\$data_len not 8, 16, or 32, stopped";
+ }
+
+ ## Pack up the data.
+
+ pack ($format, $by_ref, $data_len, $data);
+}
+
+
+sub FromParamInt
+{
+ my ($param, $data_len) = @_;
+
+ die "Undefined \$param, stopped" unless defined($param);
+
+ my ($format);
+
+ if ($data_len == 8)
+ {
+ $format = ("xxCx");
+ }
+ elsif ($data_len == 16 || $data_len == 0)
+ {
+ $format = ("xxn");
+ }
+ elsif ($data_len == 32)
+ {
+ $format = ("xxN");
+ }
+ else
+ {
+ die "\$data_len not 8, 16, or 32, stopped";
+ }
+
+ unpack ($format, $param);
+}
+
+
+sub ToParamPoint
+{
+ my ($point) = @_;
+ my ($param);
+
+ if (defined $point->{x})
+ {
+ $param = pack ("CCnn", 1, 4, $point->{x}, $point->{y});
+ }
+ else
+ {
+ $param = pack ("CCxxxx", 1, 4);
+ }
+
+ $param;
+}
+
+
+sub FromParamPoint
+{
+ my ($param) = @_;
+
+ die "Undefined \$param, stopped" unless defined($param);
+
+ my (@coords) = unpack ("xxnn", $param);
+
+ {x => $coords[0],
+ y => $coords[1]};
+}
+
+
+sub ToParamRect
+{
+ my ($rect) = @_;
+ my ($param);
+
+ if (defined $rect->{height})
+ {
+ $param = pack ("CCnnnn", 1, 8, $rect->{left}, $rect->{top}, $rect->{width}, $rect->{height});
+ }
+ elsif (defined $rect->{bottom})
+ {
+ $param = pack ("CCnnnn", 1, 8, $rect->{left}, $rect->{top}, $rect->{right} - $rect->{left}, $rect->{bottom} - $rect->{top});
+ }
+ else
+ {
+ $param = pack ("CCxxxxxxxx", 1, 8);
+ }
+
+ $param;
+}
+
+
+sub FromParamRect
+{
+ my ($param) = @_;
+
+ die "Undefined \$param, stopped" unless defined($param);
+
+ my (@coords) = unpack ("xxnnnn", $param);
+
+ {left => $coords[0],
+ top => $coords[1],
+ width => $coords[2],
+ height => $coords[3],
+ right => $coords[0] + $coords[2],
+ bottom => $coords[1] + $coords[3]};
+}
+
+
+sub ToParamString
+{
+ my ($data, $data_len) = @_;
+
+ die "Undefined \$data, stopped" unless defined($data);
+ die "\$data_len is negative, stopped" if ($data_len < 0);
+
+ ## If $data_len == 0, determine the length using the length () function.
+
+ if ($data_len == 0)
+ {
+ $data_len = length ($data) + 1; # Add 1 to get 1 byte of NULL padding
+ }
+
+ ## Pack up the data.
+
+ my ($param) = pack ("CCa$data_len", 1, $data_len, $data);
+
+ ## Make sure the packed data is an even number of bytes long.
+
+ if (($data_len % 2) != 0)
+ {
+ $param .= "\0";
+ }
+
+ $param;
+}
+
+
+sub FromParamString
+{
+ my ($param) = @_;
+
+ unpack ("xxA*", $param);
+}
+
+
+########################################################################
+#
+# FUNCTION: UnpackHeader
+#
+# DESCRIPTION: Disassemble a packet header into its consituent
+# parts.
+#
+# PARAMETERS: The packet header as received from Poser
+#
+# RETURNED: The signature, destination port, source port,
+# packet type, body size, transaction ID, and
+# checksum as an array.
+#
+########################################################################
+
+sub UnpackHeader
+{
+ my($header) = @_;
+
+ my ($signature, $dest, $src, $type, $bodySize, $transID, $checksum)
+ = unpack ($header_template, $header);
+
+ ($signature, $dest, $src, $type, $bodySize, $transID, $checksum);
+}
+
+
+########################################################################
+#
+# FUNCTION: GetBodySize
+#
+# DESCRIPTION: Utility function to extract the packet body size
+# field from the packet header.
+#
+# PARAMETERS: The packet header as received from Poser.
+#
+# RETURNED: The size of the body following the header.
+#
+########################################################################
+
+sub GetBodySize
+{
+ my($header) = @_;
+
+ my ($signature, $dest, $srs, $type, $bodySize, $transID, $checksum)
+ = UnpackHeader ($header);
+
+ $bodySize;
+}
+
+
+sub SkipWhite
+{
+ my ($format, $format_index) = @_;
+
+ while ()
+ {
+ last if ($format_index >= length ($format));
+
+ my ($char) = substr ($format, $format_index, 1);
+ last unless ($char eq " " || $char eq "," || $char eq ":");
+
+ $format_index += 1;
+ }
+
+ $format_index
+}
+
+
+sub GetType
+{
+ my ($format, $format_index) = @_;
+ my ($type) = "";
+
+ $format_index = SkipWhite ($format, $format_index);
+
+ while ()
+ {
+ last if ($format_index >= length ($format));
+
+ my ($char) = substr ($format, $format_index, 1);
+ last if (($char lt "a" || $char gt "z") && ($char lt "A" || $char gt "Z"));
+
+ $type .= $char;
+ $format_index += 1;
+ }
+
+ die "Unknown type (\"$type\" @ $format_index), stopped"
+ unless ($type eq "int" ||
+ $type eq "Err" ||
+ $type eq "Coord" ||
+ $type eq "LocalID" ||
+ $type eq "HostErr" ||
+ $type eq "string" ||
+ $type eq "rptr" ||
+ $type eq "point" ||
+ $type eq "rect" ||
+ $type eq "block");
+
+ return ($type, $format_index);
+}
+
+
+sub GetSize
+{
+ my ($format, $format_index) = @_;
+ my ($size) = 0;
+
+ while ()
+ {
+ last if ($format_index >= length ($format));
+
+ my ($char) = substr ($format, $format_index, 1);
+ last if ($char lt "0" || $char gt "9");
+
+ $size = $size * 10 + $char;
+ $format_index += 1;
+ }
+
+ return ($size, $format_index);
+}
+
+
+sub GetByRef
+{
+ my ($format, $format_index) = @_;
+ my ($by_ref) = 0;
+
+ if (substr ($format, $format_index, 1) eq "*")
+ {
+ $by_ref = 1;
+ }
+
+ if ($by_ref)
+ {
+ $format_index += 1;
+ }
+
+ return ($by_ref, $format_index);
+}
+
+
+sub GetFormat
+{
+ my ($format, $format_index) = @_;
+ my ($type, $size, $by_ref) = (" ", 0, 0);
+
+ ($type, $format_index) = GetType ($format, $format_index);
+ ($size, $format_index) = GetSize ($format, $format_index);
+ ($by_ref, $format_index) = GetByRef ($format, $format_index);
+
+ ## Deal with aliases
+
+ if ($type eq "LocalID" or $type eq "HostErr")
+ {
+ $type = "int";
+ $size = 32;
+ }
+ elsif ($type eq "Err" or $type eq "Coord")
+ {
+ $type = "int";
+ $size = 16;
+ }
+
+ return ($type, $size, $by_ref, $format_index);
+}
+
+
+sub Marshal
+{
+ my ($format, @parameters) = @_;
+ my (@result);
+
+ my ($format_index) = 0;
+ my ($parameter_index) = 0;
+
+ while ($format_index < length ($format))
+ {
+ my ($parm);
+
+ my ($type, $size);
+ ($type, $size, $by_ref, $format_index) = GetFormat ($format, $format_index);
+
+ if ($type eq "int")
+ {
+ $parm = EmRPC::ToParamInt($parameters[$parameter_index], $size, $by_ref);
+ }
+ elsif ($type eq "rptr")
+ {
+ $parm = EmRPC::ToParamInt($parameters[$parameter_index], 32, 0);
+ }
+ elsif ($type eq "point")
+ {
+ $parm = EmRPC::ToParamPoint($parameters[$parameter_index], $size);
+ }
+ elsif ($type eq "rect")
+ {
+ $parm = EmRPC::ToParamRect($parameters[$parameter_index], $size);
+ }
+ elsif ($type eq "string")
+ {
+ $parm = EmRPC::ToParamString($parameters[$parameter_index], $size);
+ }
+ elsif ($type eq "block")
+ {
+ $parm = EmRPC::ToParamBlock($parameters[$parameter_index], $size);
+ }
+ else
+ {
+ die "Unexpected type \"$type\" in EmRPC::Marshal, stopped";
+ }
+
+ push (@result, $parm);
+
+ $parameter_index += 1;
+ }
+
+ return join ("", reverse @result);
+}
+
+
+sub BreakApartParameters
+{
+ my ($packed_parms) = @_;
+ my (@result) = 0;
+
+ my ($offset) = 0;
+
+ while ($offset < length ($packed_parms))
+ {
+ # Get the size field.
+
+ my ($size) = unpack ("x$offset" . "xC", $packed_parms);
+
+ # Add in the lengths of the byRef and size fields.
+
+ $size += 2;
+
+ # Make sure the field is word-aligned.
+
+ if (($size % 2) != 0)
+ {
+ $size += 1;
+ }
+
+ # Get the SysPktRPCParamInfo.
+
+ my ($parm) = unpack ("x$offset a$size", $packed_parms);
+
+ push (@result, $parm);
+
+ $offset += $size;
+ }
+
+ return @result;
+}
+
+
+sub Unmarshal
+{
+ my ($packed_parms, $format) = @_;
+ my (@result);
+
+ my ($format_index) = 0;
+ my ($parameter_index) = 0;
+
+ my (@parameters) = reverse BreakApartParameters($packed_parms);
+
+ while ($format_index < length ($format))
+ {
+ my ($parm);
+
+ my ($type, $size);
+ ($type, $size, $by_ref, $format_index) = GetFormat ($format, $format_index);
+
+ if ($type eq "int")
+ {
+ $parm = EmRPC::FromParamInt($parameters[$parameter_index], $size);
+ }
+ elsif ($type eq "rptr")
+ {
+ $parm = EmRPC::FromParamInt($parameters[$parameter_index], 32);
+ }
+ elsif ($type eq "point")
+ {
+ $parm = EmRPC::FromParamPoint($parameters[$parameter_index]);
+ }
+ elsif ($type eq "rect")
+ {
+ $parm = EmRPC::FromParamRect($parameters[$parameter_index]);
+ }
+ elsif ($type eq "string")
+ {
+ $parm = EmRPC::FromParamString($parameters[$parameter_index]);
+ }
+ elsif ($type eq "block")
+ {
+ $parm = EmRPC::FromParamBlock($parameters[$parameter_index], $size);
+ }
+ else
+ {
+ die "Unexpected type \"$type\" in EmRPC::Unmarshal, stopped";
+ }
+
+ push (@result, $parm);
+
+ $parameter_index += 1;
+ }
+
+ return @result;
+}
+
+
+sub ReadString
+{
+ my ($address) = @_;
+
+ my ($block) = EmRPC::ReadBlock($address, 128);
+
+ $block =~ /^([^\000]*)/;
+ return $1;
+}
+
+
+sub PrintString
+{
+ my($string) = @_;
+
+ foreach $ii (0..length ($string) - 1)
+ {
+ my($ch) = substr($string, $ii, 1);
+
+ printf "0x%02X, ", ord($ch);
+
+ if ($ii % 8 == 7)
+ {
+ print "\n";
+ }
+ }
+
+ printf "\n";
+
+ $string;
+}
+
+1;
diff --git a/Scripting/Perl/EmSysTraps.pm b/Scripting/Perl/EmSysTraps.pm
new file mode 100644
index 0000000..38ae497
--- /dev/null
+++ b/Scripting/Perl/EmSysTraps.pm
@@ -0,0 +1,997 @@
+# DO NOT EDIT! This section was automatically produced by D:\Projects\Emulator\Main\Scripting\Perl\MakeSysTraps.pl
+# from D:\Projects\Emulator\Main\SrcShared\Palm\Incs\System\SysTraps.h
+
+package EmSysTraps;
+
+use constant sysTrapMemInit => "A000";
+use constant sysTrapMemInitHeapTable => "A001";
+use constant sysTrapMemStoreInit => "A002";
+use constant sysTrapMemCardFormat => "A003";
+use constant sysTrapMemCardInfo => "A004";
+use constant sysTrapMemStoreInfo => "A005";
+use constant sysTrapMemStoreSetInfo => "A006";
+use constant sysTrapMemNumHeaps => "A007";
+use constant sysTrapMemNumRAMHeaps => "A008";
+use constant sysTrapMemHeapID => "A009";
+use constant sysTrapMemHeapPtr => "A00A";
+use constant sysTrapMemHeapFreeBytes => "A00B";
+use constant sysTrapMemHeapSize => "A00C";
+use constant sysTrapMemHeapFlags => "A00D";
+use constant sysTrapMemHeapCompact => "A00E";
+use constant sysTrapMemHeapInit => "A00F";
+use constant sysTrapMemHeapFreeByOwnerID => "A010";
+use constant sysTrapMemChunkNew => "A011";
+use constant sysTrapMemChunkFree => "A012";
+use constant sysTrapMemPtrNew => "A013";
+use constant sysTrapMemPtrRecoverHandle => "A014";
+use constant sysTrapMemPtrFlags => "A015";
+use constant sysTrapMemPtrSize => "A016";
+use constant sysTrapMemPtrOwner => "A017";
+use constant sysTrapMemPtrHeapID => "A018";
+use constant sysTrapMemPtrCardNo => "A019";
+use constant sysTrapMemPtrToLocalID => "A01A";
+use constant sysTrapMemPtrSetOwner => "A01B";
+use constant sysTrapMemPtrResize => "A01C";
+use constant sysTrapMemPtrResetLock => "A01D";
+use constant sysTrapMemHandleNew => "A01E";
+use constant sysTrapMemHandleLockCount => "A01F";
+use constant sysTrapMemHandleToLocalID => "A020";
+use constant sysTrapMemHandleLock => "A021";
+use constant sysTrapMemHandleUnlock => "A022";
+use constant sysTrapMemLocalIDToGlobal => "A023";
+use constant sysTrapMemLocalIDKind => "A024";
+use constant sysTrapMemLocalIDToPtr => "A025";
+use constant sysTrapMemMove => "A026";
+use constant sysTrapMemSet => "A027";
+use constant sysTrapMemStoreSearch => "A028";
+use constant sysTrapReserved6 => "A029";
+use constant sysTrapMemKernelInit => "A02A";
+use constant sysTrapMemHandleFree => "A02B";
+use constant sysTrapMemHandleFlags => "A02C";
+use constant sysTrapMemHandleSize => "A02D";
+use constant sysTrapMemHandleOwner => "A02E";
+use constant sysTrapMemHandleHeapID => "A02F";
+use constant sysTrapMemHandleDataStorage => "A030";
+use constant sysTrapMemHandleCardNo => "A031";
+use constant sysTrapMemHandleSetOwner => "A032";
+use constant sysTrapMemHandleResize => "A033";
+use constant sysTrapMemHandleResetLock => "A034";
+use constant sysTrapMemPtrUnlock => "A035";
+use constant sysTrapMemLocalIDToLockedPtr => "A036";
+use constant sysTrapMemSetDebugMode => "A037";
+use constant sysTrapMemHeapScramble => "A038";
+use constant sysTrapMemHeapCheck => "A039";
+use constant sysTrapMemNumCards => "A03A";
+use constant sysTrapMemDebugMode => "A03B";
+use constant sysTrapMemSemaphoreReserve => "A03C";
+use constant sysTrapMemSemaphoreRelease => "A03D";
+use constant sysTrapMemHeapDynamic => "A03E";
+use constant sysTrapMemNVParams => "A03F";
+use constant sysTrapDmInit => "A040";
+use constant sysTrapDmCreateDatabase => "A041";
+use constant sysTrapDmDeleteDatabase => "A042";
+use constant sysTrapDmNumDatabases => "A043";
+use constant sysTrapDmGetDatabase => "A044";
+use constant sysTrapDmFindDatabase => "A045";
+use constant sysTrapDmDatabaseInfo => "A046";
+use constant sysTrapDmSetDatabaseInfo => "A047";
+use constant sysTrapDmDatabaseSize => "A048";
+use constant sysTrapDmOpenDatabase => "A049";
+use constant sysTrapDmCloseDatabase => "A04A";
+use constant sysTrapDmNextOpenDatabase => "A04B";
+use constant sysTrapDmOpenDatabaseInfo => "A04C";
+use constant sysTrapDmResetRecordStates => "A04D";
+use constant sysTrapDmGetLastErr => "A04E";
+use constant sysTrapDmNumRecords => "A04F";
+use constant sysTrapDmRecordInfo => "A050";
+use constant sysTrapDmSetRecordInfo => "A051";
+use constant sysTrapDmAttachRecord => "A052";
+use constant sysTrapDmDetachRecord => "A053";
+use constant sysTrapDmMoveRecord => "A054";
+use constant sysTrapDmNewRecord => "A055";
+use constant sysTrapDmRemoveRecord => "A056";
+use constant sysTrapDmDeleteRecord => "A057";
+use constant sysTrapDmArchiveRecord => "A058";
+use constant sysTrapDmNewHandle => "A059";
+use constant sysTrapDmRemoveSecretRecords => "A05A";
+use constant sysTrapDmQueryRecord => "A05B";
+use constant sysTrapDmGetRecord => "A05C";
+use constant sysTrapDmResizeRecord => "A05D";
+use constant sysTrapDmReleaseRecord => "A05E";
+use constant sysTrapDmGetResource => "A05F";
+use constant sysTrapDmGet1Resource => "A060";
+use constant sysTrapDmReleaseResource => "A061";
+use constant sysTrapDmResizeResource => "A062";
+use constant sysTrapDmNextOpenResDatabase => "A063";
+use constant sysTrapDmFindResourceType => "A064";
+use constant sysTrapDmFindResource => "A065";
+use constant sysTrapDmSearchResource => "A066";
+use constant sysTrapDmNumResources => "A067";
+use constant sysTrapDmResourceInfo => "A068";
+use constant sysTrapDmSetResourceInfo => "A069";
+use constant sysTrapDmAttachResource => "A06A";
+use constant sysTrapDmDetachResource => "A06B";
+use constant sysTrapDmNewResource => "A06C";
+use constant sysTrapDmRemoveResource => "A06D";
+use constant sysTrapDmGetResourceIndex => "A06E";
+use constant sysTrapDmQuickSort => "A06F";
+use constant sysTrapDmQueryNextInCategory => "A070";
+use constant sysTrapDmNumRecordsInCategory => "A071";
+use constant sysTrapDmPositionInCategory => "A072";
+use constant sysTrapDmSeekRecordInCategory => "A073";
+use constant sysTrapDmMoveCategory => "A074";
+use constant sysTrapDmOpenDatabaseByTypeCreator => "A075";
+use constant sysTrapDmWrite => "A076";
+use constant sysTrapDmStrCopy => "A077";
+use constant sysTrapDmGetNextDatabaseByTypeCreator => "A078";
+use constant sysTrapDmWriteCheck => "A079";
+use constant sysTrapDmMoveOpenDBContext => "A07A";
+use constant sysTrapDmFindRecordByID => "A07B";
+use constant sysTrapDmGetAppInfoID => "A07C";
+use constant sysTrapDmFindSortPositionV10 => "A07D";
+use constant sysTrapDmSet => "A07E";
+use constant sysTrapDmCreateDatabaseFromImage => "A07F";
+use constant sysTrapDbgSrcMessage => "A080";
+use constant sysTrapDbgMessage => "A081";
+use constant sysTrapDbgGetMessage => "A082";
+use constant sysTrapDbgCommSettings => "A083";
+use constant sysTrapErrDisplayFileLineMsg => "A084";
+use constant sysTrapErrSetJump => "A085";
+use constant sysTrapErrLongJump => "A086";
+use constant sysTrapErrThrow => "A087";
+use constant sysTrapErrExceptionList => "A088";
+use constant sysTrapSysBroadcastActionCode => "A089";
+use constant sysTrapSysUnimplemented => "A08A";
+use constant sysTrapSysColdBoot => "A08B";
+use constant sysTrapSysReset => "A08C";
+use constant sysTrapSysDoze => "A08D";
+use constant sysTrapSysAppLaunch => "A08E";
+use constant sysTrapSysAppStartup => "A08F";
+use constant sysTrapSysAppExit => "A090";
+use constant sysTrapSysSetA5 => "A091";
+use constant sysTrapSysSetTrapAddress => "A092";
+use constant sysTrapSysGetTrapAddress => "A093";
+use constant sysTrapSysTranslateKernelErr => "A094";
+use constant sysTrapSysSemaphoreCreate => "A095";
+use constant sysTrapSysSemaphoreDelete => "A096";
+use constant sysTrapSysSemaphoreWait => "A097";
+use constant sysTrapSysSemaphoreSignal => "A098";
+use constant sysTrapSysTimerCreate => "A099";
+use constant sysTrapSysTimerWrite => "A09A";
+use constant sysTrapSysTaskCreate => "A09B";
+use constant sysTrapSysTaskDelete => "A09C";
+use constant sysTrapSysTaskTrigger => "A09D";
+use constant sysTrapSysTaskID => "A09E";
+use constant sysTrapSysTaskUserInfoPtr => "A09F";
+use constant sysTrapSysTaskDelay => "A0A0";
+use constant sysTrapSysTaskSetTermProc => "A0A1";
+use constant sysTrapSysUILaunch => "A0A2";
+use constant sysTrapSysNewOwnerID => "A0A3";
+use constant sysTrapSysSemaphoreSet => "A0A4";
+use constant sysTrapSysDisableInts => "A0A5";
+use constant sysTrapSysRestoreStatus => "A0A6";
+use constant sysTrapSysUIAppSwitch => "A0A7";
+use constant sysTrapSysCurAppInfoPV20 => "A0A8";
+use constant sysTrapSysHandleEvent => "A0A9";
+use constant sysTrapSysInit => "A0AA";
+use constant sysTrapSysQSort => "A0AB";
+use constant sysTrapSysCurAppDatabase => "A0AC";
+use constant sysTrapSysFatalAlert => "A0AD";
+use constant sysTrapSysResSemaphoreCreate => "A0AE";
+use constant sysTrapSysResSemaphoreDelete => "A0AF";
+use constant sysTrapSysResSemaphoreReserve => "A0B0";
+use constant sysTrapSysResSemaphoreRelease => "A0B1";
+use constant sysTrapSysSleep => "A0B2";
+use constant sysTrapSysKeyboardDialogV10 => "A0B3";
+use constant sysTrapSysAppLauncherDialog => "A0B4";
+use constant sysTrapSysSetPerformance => "A0B5";
+use constant sysTrapSysBatteryInfoV20 => "A0B6";
+use constant sysTrapSysLibInstall => "A0B7";
+use constant sysTrapSysLibRemove => "A0B8";
+use constant sysTrapSysLibTblEntry => "A0B9";
+use constant sysTrapSysLibFind => "A0BA";
+use constant sysTrapSysBatteryDialog => "A0BB";
+use constant sysTrapSysCopyStringResource => "A0BC";
+use constant sysTrapSysKernelInfo => "A0BD";
+use constant sysTrapSysLaunchConsole => "A0BE";
+use constant sysTrapSysTimerDelete => "A0BF";
+use constant sysTrapSysSetAutoOffTime => "A0C0";
+use constant sysTrapSysFormPointerArrayToStrings => "A0C1";
+use constant sysTrapSysRandom => "A0C2";
+use constant sysTrapSysTaskSwitching => "A0C3";
+use constant sysTrapSysTimerRead => "A0C4";
+use constant sysTrapStrCopy => "A0C5";
+use constant sysTrapStrCat => "A0C6";
+use constant sysTrapStrLen => "A0C7";
+use constant sysTrapStrCompare => "A0C8";
+use constant sysTrapStrIToA => "A0C9";
+use constant sysTrapStrCaselessCompare => "A0CA";
+use constant sysTrapStrIToH => "A0CB";
+use constant sysTrapStrChr => "A0CC";
+use constant sysTrapStrStr => "A0CD";
+use constant sysTrapStrAToI => "A0CE";
+use constant sysTrapStrToLower => "A0CF";
+use constant sysTrapSerReceiveISP => "A0D0";
+use constant sysTrapSlkOpen => "A0D1";
+use constant sysTrapSlkClose => "A0D2";
+use constant sysTrapSlkOpenSocket => "A0D3";
+use constant sysTrapSlkCloseSocket => "A0D4";
+use constant sysTrapSlkSocketRefNum => "A0D5";
+use constant sysTrapSlkSocketSetTimeout => "A0D6";
+use constant sysTrapSlkFlushSocket => "A0D7";
+use constant sysTrapSlkSetSocketListener => "A0D8";
+use constant sysTrapSlkSendPacket => "A0D9";
+use constant sysTrapSlkReceivePacket => "A0DA";
+use constant sysTrapSlkSysPktDefaultResponse => "A0DB";
+use constant sysTrapSlkProcessRPC => "A0DC";
+use constant sysTrapConPutS => "A0DD";
+use constant sysTrapConGetS => "A0DE";
+use constant sysTrapFplInit => "A0DF";
+use constant sysTrapFplFree => "A0E0";
+use constant sysTrapFplFToA => "A0E1";
+use constant sysTrapFplAToF => "A0E2";
+use constant sysTrapFplBase10Info => "A0E3";
+use constant sysTrapFplLongToFloat => "A0E4";
+use constant sysTrapFplFloatToLong => "A0E5";
+use constant sysTrapFplFloatToULong => "A0E6";
+use constant sysTrapFplMul => "A0E7";
+use constant sysTrapFplAdd => "A0E8";
+use constant sysTrapFplSub => "A0E9";
+use constant sysTrapFplDiv => "A0EA";
+use constant sysTrapWinScreenInit => "A0EB";
+use constant sysTrapScrCopyRectangle => "A0EC";
+use constant sysTrapScrDrawChars => "A0ED";
+use constant sysTrapScrLineRoutine => "A0EE";
+use constant sysTrapScrRectangleRoutine => "A0EF";
+use constant sysTrapScrScreenInfo => "A0F0";
+use constant sysTrapScrDrawNotify => "A0F1";
+use constant sysTrapScrSendUpdateArea => "A0F2";
+use constant sysTrapScrCompressScanLine => "A0F3";
+use constant sysTrapScrDeCompressScanLine => "A0F4";
+use constant sysTrapTimGetSeconds => "A0F5";
+use constant sysTrapTimSetSeconds => "A0F6";
+use constant sysTrapTimGetTicks => "A0F7";
+use constant sysTrapTimInit => "A0F8";
+use constant sysTrapTimSetAlarm => "A0F9";
+use constant sysTrapTimGetAlarm => "A0FA";
+use constant sysTrapTimHandleInterrupt => "A0FB";
+use constant sysTrapTimSecondsToDateTime => "A0FC";
+use constant sysTrapTimDateTimeToSeconds => "A0FD";
+use constant sysTrapTimAdjust => "A0FE";
+use constant sysTrapTimSleep => "A0FF";
+use constant sysTrapTimWake => "A100";
+use constant sysTrapCategoryCreateListV10 => "A101";
+use constant sysTrapCategoryFreeListV10 => "A102";
+use constant sysTrapCategoryFind => "A103";
+use constant sysTrapCategoryGetName => "A104";
+use constant sysTrapCategoryEditV10 => "A105";
+use constant sysTrapCategorySelectV10 => "A106";
+use constant sysTrapCategoryGetNext => "A107";
+use constant sysTrapCategorySetTriggerLabel => "A108";
+use constant sysTrapCategoryTruncateName => "A109";
+use constant sysTrapClipboardAddItem => "A10A";
+use constant sysTrapClipboardCheckIfItemExist => "A10B";
+use constant sysTrapClipboardGetItem => "A10C";
+use constant sysTrapCtlDrawControl => "A10D";
+use constant sysTrapCtlEraseControl => "A10E";
+use constant sysTrapCtlHideControl => "A10F";
+use constant sysTrapCtlShowControl => "A110";
+use constant sysTrapCtlGetValue => "A111";
+use constant sysTrapCtlSetValue => "A112";
+use constant sysTrapCtlGetLabel => "A113";
+use constant sysTrapCtlSetLabel => "A114";
+use constant sysTrapCtlHandleEvent => "A115";
+use constant sysTrapCtlHitControl => "A116";
+use constant sysTrapCtlSetEnabled => "A117";
+use constant sysTrapCtlSetUsable => "A118";
+use constant sysTrapCtlEnabled => "A119";
+use constant sysTrapEvtInitialize => "A11A";
+use constant sysTrapEvtAddEventToQueue => "A11B";
+use constant sysTrapEvtCopyEvent => "A11C";
+use constant sysTrapEvtGetEvent => "A11D";
+use constant sysTrapEvtGetPen => "A11E";
+use constant sysTrapEvtSysInit => "A11F";
+use constant sysTrapEvtGetSysEvent => "A120";
+use constant sysTrapEvtProcessSoftKeyStroke => "A121";
+use constant sysTrapEvtGetPenBtnList => "A122";
+use constant sysTrapEvtSetPenQueuePtr => "A123";
+use constant sysTrapEvtPenQueueSize => "A124";
+use constant sysTrapEvtFlushPenQueue => "A125";
+use constant sysTrapEvtEnqueuePenPoint => "A126";
+use constant sysTrapEvtDequeuePenStrokeInfo => "A127";
+use constant sysTrapEvtDequeuePenPoint => "A128";
+use constant sysTrapEvtFlushNextPenStroke => "A129";
+use constant sysTrapEvtSetKeyQueuePtr => "A12A";
+use constant sysTrapEvtKeyQueueSize => "A12B";
+use constant sysTrapEvtFlushKeyQueue => "A12C";
+use constant sysTrapEvtEnqueueKey => "A12D";
+use constant sysTrapEvtDequeueKeyEvent => "A12E";
+use constant sysTrapEvtWakeup => "A12F";
+use constant sysTrapEvtResetAutoOffTimer => "A130";
+use constant sysTrapEvtKeyQueueEmpty => "A131";
+use constant sysTrapEvtEnableGraffiti => "A132";
+use constant sysTrapFldCopy => "A133";
+use constant sysTrapFldCut => "A134";
+use constant sysTrapFldDrawField => "A135";
+use constant sysTrapFldEraseField => "A136";
+use constant sysTrapFldFreeMemory => "A137";
+use constant sysTrapFldGetBounds => "A138";
+use constant sysTrapFldGetTextPtr => "A139";
+use constant sysTrapFldGetSelection => "A13A";
+use constant sysTrapFldHandleEvent => "A13B";
+use constant sysTrapFldPaste => "A13C";
+use constant sysTrapFldRecalculateField => "A13D";
+use constant sysTrapFldSetBounds => "A13E";
+use constant sysTrapFldSetText => "A13F";
+use constant sysTrapFldGetFont => "A140";
+use constant sysTrapFldSetFont => "A141";
+use constant sysTrapFldSetSelection => "A142";
+use constant sysTrapFldGrabFocus => "A143";
+use constant sysTrapFldReleaseFocus => "A144";
+use constant sysTrapFldGetInsPtPosition => "A145";
+use constant sysTrapFldSetInsPtPosition => "A146";
+use constant sysTrapFldSetScrollPosition => "A147";
+use constant sysTrapFldGetScrollPosition => "A148";
+use constant sysTrapFldGetTextHeight => "A149";
+use constant sysTrapFldGetTextAllocatedSize => "A14A";
+use constant sysTrapFldGetTextLength => "A14B";
+use constant sysTrapFldScrollField => "A14C";
+use constant sysTrapFldScrollable => "A14D";
+use constant sysTrapFldGetVisibleLines => "A14E";
+use constant sysTrapFldGetAttributes => "A14F";
+use constant sysTrapFldSetAttributes => "A150";
+use constant sysTrapFldSendChangeNotification => "A151";
+use constant sysTrapFldCalcFieldHeight => "A152";
+use constant sysTrapFldGetTextHandle => "A153";
+use constant sysTrapFldCompactText => "A154";
+use constant sysTrapFldDirty => "A155";
+use constant sysTrapFldWordWrap => "A156";
+use constant sysTrapFldSetTextAllocatedSize => "A157";
+use constant sysTrapFldSetTextHandle => "A158";
+use constant sysTrapFldSetTextPtr => "A159";
+use constant sysTrapFldGetMaxChars => "A15A";
+use constant sysTrapFldSetMaxChars => "A15B";
+use constant sysTrapFldSetUsable => "A15C";
+use constant sysTrapFldInsert => "A15D";
+use constant sysTrapFldDelete => "A15E";
+use constant sysTrapFldUndo => "A15F";
+use constant sysTrapFldSetDirty => "A160";
+use constant sysTrapFldSendHeightChangeNotification => "A161";
+use constant sysTrapFldMakeFullyVisible => "A162";
+use constant sysTrapFntGetFont => "A163";
+use constant sysTrapFntSetFont => "A164";
+use constant sysTrapFntGetFontPtr => "A165";
+use constant sysTrapFntBaseLine => "A166";
+use constant sysTrapFntCharHeight => "A167";
+use constant sysTrapFntLineHeight => "A168";
+use constant sysTrapFntAverageCharWidth => "A169";
+use constant sysTrapFntCharWidth => "A16A";
+use constant sysTrapFntCharsWidth => "A16B";
+use constant sysTrapFntDescenderHeight => "A16C";
+use constant sysTrapFntCharsInWidth => "A16D";
+use constant sysTrapFntLineWidth => "A16E";
+use constant sysTrapFrmInitForm => "A16F";
+use constant sysTrapFrmDeleteForm => "A170";
+use constant sysTrapFrmDrawForm => "A171";
+use constant sysTrapFrmEraseForm => "A172";
+use constant sysTrapFrmGetActiveForm => "A173";
+use constant sysTrapFrmSetActiveForm => "A174";
+use constant sysTrapFrmGetActiveFormID => "A175";
+use constant sysTrapFrmGetUserModifiedState => "A176";
+use constant sysTrapFrmSetNotUserModified => "A177";
+use constant sysTrapFrmGetFocus => "A178";
+use constant sysTrapFrmSetFocus => "A179";
+use constant sysTrapFrmHandleEvent => "A17A";
+use constant sysTrapFrmGetFormBounds => "A17B";
+use constant sysTrapFrmGetWindowHandle => "A17C";
+use constant sysTrapFrmGetFormId => "A17D";
+use constant sysTrapFrmGetFormPtr => "A17E";
+use constant sysTrapFrmGetNumberOfObjects => "A17F";
+use constant sysTrapFrmGetObjectIndex => "A180";
+use constant sysTrapFrmGetObjectId => "A181";
+use constant sysTrapFrmGetObjectType => "A182";
+use constant sysTrapFrmGetObjectPtr => "A183";
+use constant sysTrapFrmHideObject => "A184";
+use constant sysTrapFrmShowObject => "A185";
+use constant sysTrapFrmGetObjectPosition => "A186";
+use constant sysTrapFrmSetObjectPosition => "A187";
+use constant sysTrapFrmGetControlValue => "A188";
+use constant sysTrapFrmSetControlValue => "A189";
+use constant sysTrapFrmGetControlGroupSelection => "A18A";
+use constant sysTrapFrmSetControlGroupSelection => "A18B";
+use constant sysTrapFrmCopyLabel => "A18C";
+use constant sysTrapFrmSetLabel => "A18D";
+use constant sysTrapFrmGetLabel => "A18E";
+use constant sysTrapFrmSetCategoryLabel => "A18F";
+use constant sysTrapFrmGetTitle => "A190";
+use constant sysTrapFrmSetTitle => "A191";
+use constant sysTrapFrmAlert => "A192";
+use constant sysTrapFrmDoDialog => "A193";
+use constant sysTrapFrmCustomAlert => "A194";
+use constant sysTrapFrmHelp => "A195";
+use constant sysTrapFrmUpdateScrollers => "A196";
+use constant sysTrapFrmGetFirstForm => "A197";
+use constant sysTrapFrmVisible => "A198";
+use constant sysTrapFrmGetObjectBounds => "A199";
+use constant sysTrapFrmCopyTitle => "A19A";
+use constant sysTrapFrmGotoForm => "A19B";
+use constant sysTrapFrmPopupForm => "A19C";
+use constant sysTrapFrmUpdateForm => "A19D";
+use constant sysTrapFrmReturnToForm => "A19E";
+use constant sysTrapFrmSetEventHandler => "A19F";
+use constant sysTrapFrmDispatchEvent => "A1A0";
+use constant sysTrapFrmCloseAllForms => "A1A1";
+use constant sysTrapFrmSaveAllForms => "A1A2";
+use constant sysTrapFrmGetGadgetData => "A1A3";
+use constant sysTrapFrmSetGadgetData => "A1A4";
+use constant sysTrapFrmSetCategoryTrigger => "A1A5";
+use constant sysTrapUIInitialize => "A1A6";
+use constant sysTrapUIReset => "A1A7";
+use constant sysTrapInsPtInitialize => "A1A8";
+use constant sysTrapInsPtSetLocation => "A1A9";
+use constant sysTrapInsPtGetLocation => "A1AA";
+use constant sysTrapInsPtEnable => "A1AB";
+use constant sysTrapInsPtEnabled => "A1AC";
+use constant sysTrapInsPtSetHeight => "A1AD";
+use constant sysTrapInsPtGetHeight => "A1AE";
+use constant sysTrapInsPtCheckBlink => "A1AF";
+use constant sysTrapLstSetDrawFunction => "A1B0";
+use constant sysTrapLstDrawList => "A1B1";
+use constant sysTrapLstEraseList => "A1B2";
+use constant sysTrapLstGetSelection => "A1B3";
+use constant sysTrapLstGetSelectionText => "A1B4";
+use constant sysTrapLstHandleEvent => "A1B5";
+use constant sysTrapLstSetHeight => "A1B6";
+use constant sysTrapLstSetSelection => "A1B7";
+use constant sysTrapLstSetListChoices => "A1B8";
+use constant sysTrapLstMakeItemVisible => "A1B9";
+use constant sysTrapLstGetNumberOfItems => "A1BA";
+use constant sysTrapLstPopupList => "A1BB";
+use constant sysTrapLstSetPosition => "A1BC";
+use constant sysTrapMenuInit => "A1BD";
+use constant sysTrapMenuDispose => "A1BE";
+use constant sysTrapMenuHandleEvent => "A1BF";
+use constant sysTrapMenuDrawMenu => "A1C0";
+use constant sysTrapMenuEraseStatus => "A1C1";
+use constant sysTrapMenuGetActiveMenu => "A1C2";
+use constant sysTrapMenuSetActiveMenu => "A1C3";
+use constant sysTrapRctSetRectangle => "A1C4";
+use constant sysTrapRctCopyRectangle => "A1C5";
+use constant sysTrapRctInsetRectangle => "A1C6";
+use constant sysTrapRctOffsetRectangle => "A1C7";
+use constant sysTrapRctPtInRectangle => "A1C8";
+use constant sysTrapRctGetIntersection => "A1C9";
+use constant sysTrapTblDrawTable => "A1CA";
+use constant sysTrapTblEraseTable => "A1CB";
+use constant sysTrapTblHandleEvent => "A1CC";
+use constant sysTrapTblGetItemBounds => "A1CD";
+use constant sysTrapTblSelectItem => "A1CE";
+use constant sysTrapTblGetItemInt => "A1CF";
+use constant sysTrapTblSetItemInt => "A1D0";
+use constant sysTrapTblSetItemStyle => "A1D1";
+use constant sysTrapTblUnhighlightSelection => "A1D2";
+use constant sysTrapTblSetRowUsable => "A1D3";
+use constant sysTrapTblGetNumberOfRows => "A1D4";
+use constant sysTrapTblSetCustomDrawProcedure => "A1D5";
+use constant sysTrapTblSetRowSelectable => "A1D6";
+use constant sysTrapTblRowSelectable => "A1D7";
+use constant sysTrapTblSetLoadDataProcedure => "A1D8";
+use constant sysTrapTblSetSaveDataProcedure => "A1D9";
+use constant sysTrapTblGetBounds => "A1DA";
+use constant sysTrapTblSetRowHeight => "A1DB";
+use constant sysTrapTblGetColumnWidth => "A1DC";
+use constant sysTrapTblGetRowID => "A1DD";
+use constant sysTrapTblSetRowID => "A1DE";
+use constant sysTrapTblMarkRowInvalid => "A1DF";
+use constant sysTrapTblMarkTableInvalid => "A1E0";
+use constant sysTrapTblGetSelection => "A1E1";
+use constant sysTrapTblInsertRow => "A1E2";
+use constant sysTrapTblRemoveRow => "A1E3";
+use constant sysTrapTblRowInvalid => "A1E4";
+use constant sysTrapTblRedrawTable => "A1E5";
+use constant sysTrapTblRowUsable => "A1E6";
+use constant sysTrapTblReleaseFocus => "A1E7";
+use constant sysTrapTblEditing => "A1E8";
+use constant sysTrapTblGetCurrentField => "A1E9";
+use constant sysTrapTblSetColumnUsable => "A1EA";
+use constant sysTrapTblGetRowHeight => "A1EB";
+use constant sysTrapTblSetColumnWidth => "A1EC";
+use constant sysTrapTblGrabFocus => "A1ED";
+use constant sysTrapTblSetItemPtr => "A1EE";
+use constant sysTrapTblFindRowID => "A1EF";
+use constant sysTrapTblGetLastUsableRow => "A1F0";
+use constant sysTrapTblGetColumnSpacing => "A1F1";
+use constant sysTrapTblFindRowData => "A1F2";
+use constant sysTrapTblGetRowData => "A1F3";
+use constant sysTrapTblSetRowData => "A1F4";
+use constant sysTrapTblSetColumnSpacing => "A1F5";
+use constant sysTrapWinCreateWindow => "A1F6";
+use constant sysTrapWinCreateOffscreenWindow => "A1F7";
+use constant sysTrapWinDeleteWindow => "A1F8";
+use constant sysTrapWinInitializeWindow => "A1F9";
+use constant sysTrapWinAddWindow => "A1FA";
+use constant sysTrapWinRemoveWindow => "A1FB";
+use constant sysTrapWinSetActiveWindow => "A1FC";
+use constant sysTrapWinSetDrawWindow => "A1FD";
+use constant sysTrapWinGetDrawWindow => "A1FE";
+use constant sysTrapWinGetActiveWindow => "A1FF";
+use constant sysTrapWinGetDisplayWindow => "A200";
+use constant sysTrapWinGetFirstWindow => "A201";
+use constant sysTrapWinEnableWindow => "A202";
+use constant sysTrapWinDisableWindow => "A203";
+use constant sysTrapWinGetWindowFrameRect => "A204";
+use constant sysTrapWinDrawWindowFrame => "A205";
+use constant sysTrapWinEraseWindow => "A206";
+use constant sysTrapWinSaveBits => "A207";
+use constant sysTrapWinRestoreBits => "A208";
+use constant sysTrapWinCopyRectangle => "A209";
+use constant sysTrapWinScrollRectangle => "A20A";
+use constant sysTrapWinGetDisplayExtent => "A20B";
+use constant sysTrapWinGetWindowExtent => "A20C";
+use constant sysTrapWinDisplayToWindowPt => "A20D";
+use constant sysTrapWinWindowToDisplayPt => "A20E";
+use constant sysTrapWinGetClip => "A20F";
+use constant sysTrapWinSetClip => "A210";
+use constant sysTrapWinResetClip => "A211";
+use constant sysTrapWinClipRectangle => "A212";
+use constant sysTrapWinDrawLine => "A213";
+use constant sysTrapWinDrawGrayLine => "A214";
+use constant sysTrapWinEraseLine => "A215";
+use constant sysTrapWinInvertLine => "A216";
+use constant sysTrapWinFillLine => "A217";
+use constant sysTrapWinDrawRectangle => "A218";
+use constant sysTrapWinEraseRectangle => "A219";
+use constant sysTrapWinInvertRectangle => "A21A";
+use constant sysTrapWinDrawRectangleFrame => "A21B";
+use constant sysTrapWinDrawGrayRectangleFrame => "A21C";
+use constant sysTrapWinEraseRectangleFrame => "A21D";
+use constant sysTrapWinInvertRectangleFrame => "A21E";
+use constant sysTrapWinGetFramesRectangle => "A21F";
+use constant sysTrapWinDrawChars => "A220";
+use constant sysTrapWinEraseChars => "A221";
+use constant sysTrapWinInvertChars => "A222";
+use constant sysTrapWinGetPattern => "A223";
+use constant sysTrapWinSetPattern => "A224";
+use constant sysTrapWinSetUnderlineMode => "A225";
+use constant sysTrapWinDrawBitmap => "A226";
+use constant sysTrapWinModal => "A227";
+use constant sysTrapWinGetWindowBounds => "A228";
+use constant sysTrapWinFillRectangle => "A229";
+use constant sysTrapWinDrawInvertedChars => "A22A";
+use constant sysTrapPrefOpenPreferenceDBV10 => "A22B";
+use constant sysTrapPrefGetPreferences => "A22C";
+use constant sysTrapPrefSetPreferences => "A22D";
+use constant sysTrapPrefGetAppPreferencesV10 => "A22E";
+use constant sysTrapPrefSetAppPreferencesV10 => "A22F";
+use constant sysTrapSndInit => "A230";
+use constant sysTrapSndSetDefaultVolume => "A231";
+use constant sysTrapSndGetDefaultVolume => "A232";
+use constant sysTrapSndDoCmd => "A233";
+use constant sysTrapSndPlaySystemSound => "A234";
+use constant sysTrapAlmInit => "A235";
+use constant sysTrapAlmCancelAll => "A236";
+use constant sysTrapAlmAlarmCallback => "A237";
+use constant sysTrapAlmSetAlarm => "A238";
+use constant sysTrapAlmGetAlarm => "A239";
+use constant sysTrapAlmDisplayAlarm => "A23A";
+use constant sysTrapAlmEnableNotification => "A23B";
+use constant sysTrapHwrGetRAMMapping => "A23C";
+use constant sysTrapHwrMemWritable => "A23D";
+use constant sysTrapHwrMemReadable => "A23E";
+use constant sysTrapHwrDoze => "A23F";
+use constant sysTrapHwrSleep => "A240";
+use constant sysTrapHwrWake => "A241";
+use constant sysTrapHwrSetSystemClock => "A242";
+use constant sysTrapHwrSetCPUDutyCycle => "A243";
+use constant sysTrapHwrDisplayInit => "A244";
+use constant sysTrapHwrDisplaySleep => "A245";
+use constant sysTrapHwrTimerInit => "A246";
+use constant sysTrapHwrCursorV33 => "A247";
+use constant sysTrapHwrBatteryLevel => "A248";
+use constant sysTrapHwrDelay => "A249";
+use constant sysTrapHwrEnableDataWrites => "A24A";
+use constant sysTrapHwrDisableDataWrites => "A24B";
+use constant sysTrapHwrLCDBaseAddrV33 => "A24C";
+use constant sysTrapHwrDisplayDrawBootScreen => "A24D";
+use constant sysTrapHwrTimerSleep => "A24E";
+use constant sysTrapHwrTimerWake => "A24F";
+use constant sysTrapHwrDisplayWake => "A250";
+use constant sysTrapHwrIRQ1Handler => "A251";
+use constant sysTrapHwrIRQ2Handler => "A252";
+use constant sysTrapHwrIRQ3Handler => "A253";
+use constant sysTrapHwrIRQ4Handler => "A254";
+use constant sysTrapHwrIRQ5Handler => "A255";
+use constant sysTrapHwrIRQ6Handler => "A256";
+use constant sysTrapHwrDockSignals => "A257";
+use constant sysTrapHwrPluggedIn => "A258";
+use constant sysTrapCrc16CalcBlock => "A259";
+use constant sysTrapSelectDayV10 => "A25A";
+use constant sysTrapSelectTimeV33 => "A25B";
+use constant sysTrapDayDrawDaySelector => "A25C";
+use constant sysTrapDayHandleEvent => "A25D";
+use constant sysTrapDayDrawDays => "A25E";
+use constant sysTrapDayOfWeek => "A25F";
+use constant sysTrapDaysInMonth => "A260";
+use constant sysTrapDayOfMonth => "A261";
+use constant sysTrapDateDaysToDate => "A262";
+use constant sysTrapDateToDays => "A263";
+use constant sysTrapDateAdjust => "A264";
+use constant sysTrapDateSecondsToDate => "A265";
+use constant sysTrapDateToAscii => "A266";
+use constant sysTrapDateToDOWDMFormat => "A267";
+use constant sysTrapTimeToAscii => "A268";
+use constant sysTrapFind => "A269";
+use constant sysTrapFindStrInStr => "A26A";
+use constant sysTrapFindSaveMatch => "A26B";
+use constant sysTrapFindGetLineBounds => "A26C";
+use constant sysTrapFindDrawHeader => "A26D";
+use constant sysTrapPenOpen => "A26E";
+use constant sysTrapPenClose => "A26F";
+use constant sysTrapPenGetRawPen => "A270";
+use constant sysTrapPenCalibrate => "A271";
+use constant sysTrapPenRawToScreen => "A272";
+use constant sysTrapPenScreenToRaw => "A273";
+use constant sysTrapPenResetCalibration => "A274";
+use constant sysTrapPenSleep => "A275";
+use constant sysTrapPenWake => "A276";
+use constant sysTrapResLoadForm => "A277";
+use constant sysTrapResLoadMenu => "A278";
+use constant sysTrapFtrInit => "A279";
+use constant sysTrapFtrUnregister => "A27A";
+use constant sysTrapFtrGet => "A27B";
+use constant sysTrapFtrSet => "A27C";
+use constant sysTrapFtrGetByIndex => "A27D";
+use constant sysTrapGrfInit => "A27E";
+use constant sysTrapGrfFree => "A27F";
+use constant sysTrapGrfGetState => "A280";
+use constant sysTrapGrfSetState => "A281";
+use constant sysTrapGrfFlushPoints => "A282";
+use constant sysTrapGrfAddPoint => "A283";
+use constant sysTrapGrfInitState => "A284";
+use constant sysTrapGrfCleanState => "A285";
+use constant sysTrapGrfMatch => "A286";
+use constant sysTrapGrfGetMacro => "A287";
+use constant sysTrapGrfFilterPoints => "A288";
+use constant sysTrapGrfGetNumPoints => "A289";
+use constant sysTrapGrfGetPoint => "A28A";
+use constant sysTrapGrfFindBranch => "A28B";
+use constant sysTrapGrfMatchGlyph => "A28C";
+use constant sysTrapGrfGetGlyphMapping => "A28D";
+use constant sysTrapGrfGetMacroName => "A28E";
+use constant sysTrapGrfDeleteMacro => "A28F";
+use constant sysTrapGrfAddMacro => "A290";
+use constant sysTrapGrfGetAndExpandMacro => "A291";
+use constant sysTrapGrfProcessStroke => "A292";
+use constant sysTrapGrfFieldChange => "A293";
+use constant sysTrapGetCharSortValue => "A294";
+use constant sysTrapGetCharAttr => "A295";
+use constant sysTrapGetCharCaselessValue => "A296";
+use constant sysTrapPwdExists => "A297";
+use constant sysTrapPwdVerify => "A298";
+use constant sysTrapPwdSet => "A299";
+use constant sysTrapPwdRemove => "A29A";
+use constant sysTrapGsiInitialize => "A29B";
+use constant sysTrapGsiSetLocation => "A29C";
+use constant sysTrapGsiEnable => "A29D";
+use constant sysTrapGsiEnabled => "A29E";
+use constant sysTrapGsiSetShiftState => "A29F";
+use constant sysTrapKeyInit => "A2A0";
+use constant sysTrapKeyHandleInterrupt => "A2A1";
+use constant sysTrapKeyCurrentState => "A2A2";
+use constant sysTrapKeyResetDoubleTap => "A2A3";
+use constant sysTrapKeyRates => "A2A4";
+use constant sysTrapKeySleep => "A2A5";
+use constant sysTrapKeyWake => "A2A6";
+use constant sysTrapDlkControl => "A2A7";
+use constant sysTrapDlkStartServer => "A2A8";
+use constant sysTrapDlkGetSyncInfo => "A2A9";
+use constant sysTrapDlkSetLogEntry => "A2AA";
+use constant sysTrapIntlDispatch => "A2AB";
+use constant sysTrapSysLibLoad => "A2AC";
+use constant sysTrapSndPlaySmf => "A2AD";
+use constant sysTrapSndCreateMidiList => "A2AE";
+use constant sysTrapAbtShowAbout => "A2AF";
+use constant sysTrapMdmDial => "A2B0";
+use constant sysTrapMdmHangUp => "A2B1";
+use constant sysTrapDmSearchRecord => "A2B2";
+use constant sysTrapSysInsertionSort => "A2B3";
+use constant sysTrapDmInsertionSort => "A2B4";
+use constant sysTrapLstSetTopItem => "A2B5";
+use constant sysTrapSclSetScrollBar => "A2B6";
+use constant sysTrapSclDrawScrollBar => "A2B7";
+use constant sysTrapSclHandleEvent => "A2B8";
+use constant sysTrapSysMailboxCreate => "A2B9";
+use constant sysTrapSysMailboxDelete => "A2BA";
+use constant sysTrapSysMailboxFlush => "A2BB";
+use constant sysTrapSysMailboxSend => "A2BC";
+use constant sysTrapSysMailboxWait => "A2BD";
+use constant sysTrapSysTaskWait => "A2BE";
+use constant sysTrapSysTaskWake => "A2BF";
+use constant sysTrapSysTaskWaitClr => "A2C0";
+use constant sysTrapSysTaskSuspend => "A2C1";
+use constant sysTrapSysTaskResume => "A2C2";
+use constant sysTrapCategoryCreateList => "A2C3";
+use constant sysTrapCategoryFreeList => "A2C4";
+use constant sysTrapCategoryEditV20 => "A2C5";
+use constant sysTrapCategorySelect => "A2C6";
+use constant sysTrapDmDeleteCategory => "A2C7";
+use constant sysTrapSysEvGroupCreate => "A2C8";
+use constant sysTrapSysEvGroupSignal => "A2C9";
+use constant sysTrapSysEvGroupRead => "A2CA";
+use constant sysTrapSysEvGroupWait => "A2CB";
+use constant sysTrapEvtEventAvail => "A2CC";
+use constant sysTrapEvtSysEventAvail => "A2CD";
+use constant sysTrapStrNCopy => "A2CE";
+use constant sysTrapKeySetMask => "A2CF";
+use constant sysTrapSelectDay => "A2D0";
+use constant sysTrapPrefGetPreference => "A2D1";
+use constant sysTrapPrefSetPreference => "A2D2";
+use constant sysTrapPrefGetAppPreferences => "A2D3";
+use constant sysTrapPrefSetAppPreferences => "A2D4";
+use constant sysTrapFrmPointInTitle => "A2D5";
+use constant sysTrapStrNCat => "A2D6";
+use constant sysTrapMemCmp => "A2D7";
+use constant sysTrapTblSetColumnEditIndicator => "A2D8";
+use constant sysTrapFntWordWrap => "A2D9";
+use constant sysTrapFldGetScrollValues => "A2DA";
+use constant sysTrapSysCreateDataBaseList => "A2DB";
+use constant sysTrapSysCreatePanelList => "A2DC";
+use constant sysTrapDlkDispatchRequest => "A2DD";
+use constant sysTrapStrPrintF => "A2DE";
+use constant sysTrapStrVPrintF => "A2DF";
+use constant sysTrapPrefOpenPreferenceDB => "A2E0";
+use constant sysTrapSysGraffitiReferenceDialog => "A2E1";
+use constant sysTrapSysKeyboardDialog => "A2E2";
+use constant sysTrapFntWordWrapReverseNLines => "A2E3";
+use constant sysTrapFntGetScrollValues => "A2E4";
+use constant sysTrapTblSetRowStaticHeight => "A2E5";
+use constant sysTrapTblHasScrollBar => "A2E6";
+use constant sysTrapSclGetScrollBar => "A2E7";
+use constant sysTrapFldGetNumberOfBlankLines => "A2E8";
+use constant sysTrapSysTicksPerSecond => "A2E9";
+use constant sysTrapHwrBacklightV33 => "A2EA";
+use constant sysTrapDmDatabaseProtect => "A2EB";
+use constant sysTrapTblSetBounds => "A2EC";
+use constant sysTrapStrNCompare => "A2ED";
+use constant sysTrapStrNCaselessCompare => "A2EE";
+use constant sysTrapPhoneNumberLookup => "A2EF";
+use constant sysTrapFrmSetMenu => "A2F0";
+use constant sysTrapEncDigestMD5 => "A2F1";
+use constant sysTrapDmFindSortPosition => "A2F2";
+use constant sysTrapSysBinarySearch => "A2F3";
+use constant sysTrapSysErrString => "A2F4";
+use constant sysTrapSysStringByIndex => "A2F5";
+use constant sysTrapEvtAddUniqueEventToQueue => "A2F6";
+use constant sysTrapStrLocalizeNumber => "A2F7";
+use constant sysTrapStrDelocalizeNumber => "A2F8";
+use constant sysTrapLocGetNumberSeparators => "A2F9";
+use constant sysTrapMenuSetActiveMenuRscID => "A2FA";
+use constant sysTrapLstScrollList => "A2FB";
+use constant sysTrapCategoryInitialize => "A2FC";
+use constant sysTrapEncDigestMD4 => "A2FD";
+use constant sysTrapEncDES => "A2FE";
+use constant sysTrapLstGetVisibleItems => "A2FF";
+use constant sysTrapWinSetWindowBounds => "A300";
+use constant sysTrapCategorySetName => "A301";
+use constant sysTrapFldSetInsertionPoint => "A302";
+use constant sysTrapFrmSetObjectBounds => "A303";
+use constant sysTrapWinSetColors => "A304";
+use constant sysTrapFlpDispatch => "A305";
+use constant sysTrapFlpEmDispatch => "A306";
+use constant sysTrapExgInit => "A307";
+use constant sysTrapExgConnect => "A308";
+use constant sysTrapExgPut => "A309";
+use constant sysTrapExgGet => "A30A";
+use constant sysTrapExgAccept => "A30B";
+use constant sysTrapExgDisconnect => "A30C";
+use constant sysTrapExgSend => "A30D";
+use constant sysTrapExgReceive => "A30E";
+use constant sysTrapExgRegisterData => "A30F";
+use constant sysTrapExgNotifyReceive => "A310";
+use constant sysTrapExgControl => "A311";
+use constant sysTrapPrgStartDialogV31 => "A312";
+use constant sysTrapPrgStopDialog => "A313";
+use constant sysTrapPrgUpdateDialog => "A314";
+use constant sysTrapPrgHandleEvent => "A315";
+use constant sysTrapImcReadFieldNoSemicolon => "A316";
+use constant sysTrapImcReadFieldQuotablePrintable => "A317";
+use constant sysTrapImcReadPropertyParameter => "A318";
+use constant sysTrapImcSkipAllPropertyParameters => "A319";
+use constant sysTrapImcReadWhiteSpace => "A31A";
+use constant sysTrapImcWriteQuotedPrintable => "A31B";
+use constant sysTrapImcWriteNoSemicolon => "A31C";
+use constant sysTrapImcStringIsAscii => "A31D";
+use constant sysTrapTblGetItemFont => "A31E";
+use constant sysTrapTblSetItemFont => "A31F";
+use constant sysTrapFontSelect => "A320";
+use constant sysTrapFntDefineFont => "A321";
+use constant sysTrapCategoryEdit => "A322";
+use constant sysTrapSysGetOSVersionString => "A323";
+use constant sysTrapSysBatteryInfo => "A324";
+use constant sysTrapSysUIBusy => "A325";
+use constant sysTrapWinValidateHandle => "A326";
+use constant sysTrapFrmValidatePtr => "A327";
+use constant sysTrapCtlValidatePointer => "A328";
+use constant sysTrapWinMoveWindowAddr => "A329";
+use constant sysTrapFrmAddSpaceForObject => "A32A";
+use constant sysTrapFrmNewForm => "A32B";
+use constant sysTrapCtlNewControl => "A32C";
+use constant sysTrapFldNewField => "A32D";
+use constant sysTrapLstNewList => "A32E";
+use constant sysTrapFrmNewLabel => "A32F";
+use constant sysTrapFrmNewBitmap => "A330";
+use constant sysTrapFrmNewGadget => "A331";
+use constant sysTrapFileOpen => "A332";
+use constant sysTrapFileClose => "A333";
+use constant sysTrapFileDelete => "A334";
+use constant sysTrapFileReadLow => "A335";
+use constant sysTrapFileWrite => "A336";
+use constant sysTrapFileSeek => "A337";
+use constant sysTrapFileTell => "A338";
+use constant sysTrapFileTruncate => "A339";
+use constant sysTrapFileControl => "A33A";
+use constant sysTrapFrmActiveState => "A33B";
+use constant sysTrapSysGetAppInfo => "A33C";
+use constant sysTrapSysGetStackInfo => "A33D";
+use constant sysTrapWinScreenMode => "A33E";
+use constant sysTrapHwrLCDGetDepthV33 => "A33F";
+use constant sysTrapHwrGetROMToken => "A340";
+use constant sysTrapDbgControl => "A341";
+use constant sysTrapExgDBRead => "A342";
+use constant sysTrapExgDBWrite => "A343";
+use constant sysTrapHostControl => "A344";
+use constant sysTrapFrmRemoveObject => "A345";
+use constant sysTrapSysReserved1 => "A346";
+use constant sysTrapSysReserved2 => "A347";
+use constant sysTrapSysReserved3 => "A348";
+use constant sysTrapOEMDispatch => "A349";
+use constant sysTrapHwrLCDContrastV33 => "A34A";
+use constant sysTrapSysLCDContrast => "A34B";
+use constant sysTrapUIContrastAdjust => "A34C";
+use constant sysTrapHwrDockStatus => "A34D";
+use constant sysTrapFntWidthToOffset => "A34E";
+use constant sysTrapSelectOneTime => "A34F";
+use constant sysTrapWinDrawChar => "A350";
+use constant sysTrapWinDrawTruncChars => "A351";
+use constant sysTrapSysNotifyInit => "A352";
+use constant sysTrapSysNotifyRegister => "A353";
+use constant sysTrapSysNotifyUnregister => "A354";
+use constant sysTrapSysNotifyBroadcast => "A355";
+use constant sysTrapSysNotifyBroadcastDeferred => "A356";
+use constant sysTrapSysNotifyDatabaseAdded => "A357";
+use constant sysTrapSysNotifyDatabaseRemoved => "A358";
+use constant sysTrapSysWantEvent => "A359";
+use constant sysTrapFtrPtrNew => "A35A";
+use constant sysTrapFtrPtrFree => "A35B";
+use constant sysTrapFtrPtrResize => "A35C";
+use constant sysTrapSysReserved5 => "A35D";
+use constant sysTrapHwrNVPrefSet => "A35E";
+use constant sysTrapHwrNVPrefGet => "A35F";
+use constant sysTrapFlashInit => "A360";
+use constant sysTrapFlashCompress => "A361";
+use constant sysTrapFlashErase => "A362";
+use constant sysTrapFlashProgram => "A363";
+use constant sysTrapAlmTimeChange => "A364";
+use constant sysTrapErrAlertCustom => "A365";
+use constant sysTrapPrgStartDialog => "A366";
+use constant sysTrapSerialDispatch => "A367";
+use constant sysTrapHwrBattery => "A368";
+use constant sysTrapDmGetDatabaseLockState => "A369";
+use constant sysTrapCncGetProfileList => "A36A";
+use constant sysTrapCncGetProfileInfo => "A36B";
+use constant sysTrapCncAddProfile => "A36C";
+use constant sysTrapCncDeleteProfile => "A36D";
+use constant sysTrapSndPlaySmfResource => "A36E";
+use constant sysTrapMemPtrDataStorage => "A36F";
+use constant sysTrapClipboardAppendItem => "A370";
+use constant sysTrapWiCmdV32 => "A371";
+use constant sysTrapHwrDisplayAttributes => "A372";
+use constant sysTrapHwrDisplayDoze => "A373";
+use constant sysTrapHwrDisplayPalette => "A374";
+use constant sysTrapBltFindIndexes => "A375";
+use constant sysTrapBltGetBitsAddr => "A376";
+use constant sysTrapBltCopyRectangle => "A377";
+use constant sysTrapBltDrawChars => "A378";
+use constant sysTrapBltLineRoutine => "A379";
+use constant sysTrapBltRectangleRoutine => "A37A";
+use constant sysTrapScrCompress => "A37B";
+use constant sysTrapScrDecompress => "A37C";
+use constant sysTrapSysLCDBrightness => "A37D";
+use constant sysTrapWinPaintChar => "A37E";
+use constant sysTrapWinPaintChars => "A37F";
+use constant sysTrapWinPaintBitmap => "A380";
+use constant sysTrapWinGetPixel => "A381";
+use constant sysTrapWinPaintPixel => "A382";
+use constant sysTrapWinDrawPixel => "A383";
+use constant sysTrapWinErasePixel => "A384";
+use constant sysTrapWinInvertPixel => "A385";
+use constant sysTrapWinPaintPixels => "A386";
+use constant sysTrapWinPaintLines => "A387";
+use constant sysTrapWinPaintLine => "A388";
+use constant sysTrapWinPaintRectangle => "A389";
+use constant sysTrapWinPaintRectangleFrame => "A38A";
+use constant sysTrapWinPaintPolygon => "A38B";
+use constant sysTrapWinDrawPolygon => "A38C";
+use constant sysTrapWinErasePolygon => "A38D";
+use constant sysTrapWinInvertPolygon => "A38E";
+use constant sysTrapWinFillPolygon => "A38F";
+use constant sysTrapWinPaintArc => "A390";
+use constant sysTrapWinDrawArc => "A391";
+use constant sysTrapWinEraseArc => "A392";
+use constant sysTrapWinInvertArc => "A393";
+use constant sysTrapWinFillArc => "A394";
+use constant sysTrapWinPushDrawState => "A395";
+use constant sysTrapWinPopDrawState => "A396";
+use constant sysTrapWinSetDrawMode => "A397";
+use constant sysTrapWinSetForeColor => "A398";
+use constant sysTrapWinSetBackColor => "A399";
+use constant sysTrapWinSetTextColor => "A39A";
+use constant sysTrapWinGetPatternType => "A39B";
+use constant sysTrapWinSetPatternType => "A39C";
+use constant sysTrapWinPalette => "A39D";
+use constant sysTrapWinRGBToIndex => "A39E";
+use constant sysTrapWinIndexToRGB => "A39F";
+use constant sysTrapWinScreenLock => "A3A0";
+use constant sysTrapWinScreenUnlock => "A3A1";
+use constant sysTrapWinGetBitmap => "A3A2";
+use constant sysTrapUIColorInit => "A3A3";
+use constant sysTrapUIColorGetTableEntryIndex => "A3A4";
+use constant sysTrapUIColorGetTableEntryRGB => "A3A5";
+use constant sysTrapUIColorSetTableEntry => "A3A6";
+use constant sysTrapUIColorPushTable => "A3A7";
+use constant sysTrapUIColorPopTable => "A3A8";
+use constant sysTrapCtlNewGraphicControl => "A3A9";
+use constant sysTrapTblGetItemPtr => "A3AA";
+use constant sysTrapUIBrightnessAdjust => "A3AB";
+use constant sysTrapUIPickColor => "A3AC";
+use constant sysTrapEvtSetAutoOffTimer => "A3AD";
+use constant sysTrapTsmDispatch => "A3AE";
+use constant sysTrapOmDispatch => "A3AF";
+use constant sysTrapDmOpenDBNoOverlay => "A3B0";
+use constant sysTrapDmOpenDBWithLocale => "A3B1";
+use constant sysTrapResLoadConstant => "A3B2";
+use constant sysTrapHwrPreDebugInit => "A3B3";
+use constant sysTrapHwrResetNMI => "A3B4";
+use constant sysTrapHwrResetPWM => "A3B5";
+use constant sysTrapKeyBootKeys => "A3B6";
+use constant sysTrapDbgSerDrvOpen => "A3B7";
+use constant sysTrapDbgSerDrvClose => "A3B8";
+use constant sysTrapDbgSerDrvControl => "A3B9";
+use constant sysTrapDbgSerDrvStatus => "A3BA";
+use constant sysTrapDbgSerDrvWriteChar => "A3BB";
+use constant sysTrapDbgSerDrvReadChar => "A3BC";
+use constant sysTrapHwrPostDebugInit => "A3BD";
+use constant sysTrapHwrIdentifyFeatures => "A3BE";
+use constant sysTrapHwrModelSpecificInit => "A3BF";
+use constant sysTrapHwrModelInitStage2 => "A3C0";
+use constant sysTrapHwrInterruptsInit => "A3C1";
+use constant sysTrapHwrSoundOn => "A3C2";
+use constant sysTrapHwrSoundOff => "A3C3";
+use constant sysTrapSysKernelClockTick => "A3C4";
+use constant sysTrapMenuEraseMenu => "A3C5";
+use constant sysTrapSelectTime => "A3C6";
+use constant sysTrapMenuCmdBarAddButton => "A3C7";
+use constant sysTrapMenuCmdBarGetButtonData => "A3C8";
+use constant sysTrapMenuCmdBarDisplay => "A3C9";
+use constant sysTrapHwrGetSilkscreenID => "A3CA";
+use constant sysTrapEvtGetSilkscreenAreaList => "A3CB";
+use constant sysTrapSysFatalAlertInit => "A3CC";
+use constant sysTrapDateTemplateToAscii => "A3CD";
+use constant sysTrapSecVerifyPW => "A3CE";
+use constant sysTrapSecSelectViewStatus => "A3CF";
+use constant sysTrapTblSetColumnMasked => "A3D0";
+use constant sysTrapTblSetRowMasked => "A3D1";
+use constant sysTrapTblRowMasked => "A3D2";
+use constant sysTrapFrmCustomResponseAlert => "A3D3";
+use constant sysTrapFrmNewGsi => "A3D4";
+use constant sysTrapMenuShowItem => "A3D5";
+use constant sysTrapMenuHideItem => "A3D6";
+use constant sysTrapMenuAddItem => "A3D7";
+use constant sysTrapFrmSetGadgetHandler => "A3D8";
+use constant sysTrapCtlSetGraphics => "A3D9";
+use constant sysTrapCtlGetSliderValues => "A3DA";
+use constant sysTrapCtlSetSliderValues => "A3DB";
+use constant sysTrapCtlNewSliderControl => "A3DC";
+use constant sysTrapLastTrapNumber => "A3DD";
+
+1;
diff --git a/Scripting/Perl/EmUtils.pm b/Scripting/Perl/EmUtils.pm
new file mode 100644
index 0000000..625da89
--- /dev/null
+++ b/Scripting/Perl/EmUtils.pm
@@ -0,0 +1,228 @@
+########################################################################
+#
+# File: EmUtils.pm
+#
+# Purpose: High-level utilities for scripting the Palm OS
+# Emulator
+#
+# Description: This file contains the following useful utilities:
+#
+# Wait
+# Wait for a signal from the Emulator.
+#
+# TapPen
+# Tap the pen at the given x,y location.
+#
+# TapButton
+# Tap the pen on the button with the given name.
+#
+# ClipperGoToURL
+# Launches the web clipping application with a given URL.
+#
+########################################################################
+
+package EmUtils;
+
+use strict;
+use vars qw(@ISA @EXPORT);
+
+use EmFunctions; # EvtEnqueuePenPoint, etc.
+use HostControl; # HostSignalWait, HostSignalResume, etc.
+
+use Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+ Wait
+ Resume
+ TapPen TapPenSync
+ TapButton TapButtonSync
+ EnterKey EnterKeySync
+ ClipperGoToURL
+
+);
+
+
+########################################################################
+#
+# FUNCTION: Wait
+#
+# DESCRIPTION: Wait for a signal from the Palm OS Emulator.
+#
+# PARAMETERS: timeout in milliseconds.
+#
+# RETURNED: List containing the HostSignalResume error code
+# and the number of the signalled event.
+#
+########################################################################
+
+sub Wait
+{
+ my $timeout = $_[0];
+ if (not defined $timeout)
+ {
+ $timeout = 0x7fffffff;
+ }
+
+ my ($err, $signal) = HostSignalWait ($timeout);
+ die "Didn't hear back from Poser, stopped" if ($err != 0);
+
+ ($err, $signal);
+}
+
+
+########################################################################
+#
+# FUNCTION: Resume
+#
+# DESCRIPTION: Resume the Palm OS Emulator after it paused itself
+# after sending a signal.
+#
+# PARAMETERS: none.
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub Resume
+{
+ HostSignalResume ();
+}
+
+
+########################################################################
+#
+# FUNCTION: TapPen
+#
+# DESCRIPTION: Simulate a tap at the given location, then wait for
+# the next null event.
+#
+# PARAMETERS: x, y coordinates.
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub TapPen
+{
+ EvtEnqueuePenPoint ({x => 256 - $_[0], y => 256 - $_[1]});
+ EvtEnqueuePenPoint ({x => -1, y => -1});
+}
+
+sub TapPenSync
+{
+ Wait ();
+ TapPen (@_);
+ Resume ();
+}
+
+
+########################################################################
+#
+# FUNCTION: TapButton
+#
+# DESCRIPTION: Simulate a tap on the named button, then wait for
+# the next null event.
+#
+# PARAMETERS: Name of the button to tap on.
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub TapButton
+{
+ my ($button_name) = @_;
+ my($ii);
+
+ my ($form) = FrmGetActiveForm();
+ my ($num_objects) = FrmGetNumberOfObjects($form);
+
+ for $ii (0..$num_objects - 1)
+ {
+ my ($object_type) = FrmGetObjectType($form, $ii);
+
+ if ($object_type == EmFunctions::frmControlObj)
+ {
+ my ($obj_ptr) = FrmGetObjectPtr ($form, $ii);
+ my ($address, $label) = CtlGetLabel($obj_ptr);
+
+ if ($label eq $button_name)
+ {
+ my (%bounds) = FrmGetObjectBounds($form, $ii);
+
+ my ($x, $y) = ( $bounds{left} + $bounds{width} / 2,
+ $bounds{top} + $bounds{height} / 2);
+
+ ($x, $y) = WinWindowToDisplayPt ($x, $y);
+
+ TapPen ($x, $y);
+
+ last; # break out of the for loop.
+ }
+ }
+ }
+}
+
+sub TapButtonSync
+{
+ Wait ();
+ TapButton (@_);
+ Resume ();
+}
+
+########################################################################
+#
+# FUNCTION: EnterKey
+#
+# DESCRIPTION: Enter a key, then wait for the next null event.
+#
+# PARAMETERS: WChar asciiChar, UInt16 keycode, UInt16 modifiers
+#
+# RETURNED: Nothing.
+#
+########################################################################
+
+sub EnterKey
+{
+ EvtEnqueueKey($_[0], $_[1], $_[2]);
+}
+
+sub EnterKeySync
+{
+ Wait ();
+ EnterKey (@_);
+ Resume ();
+}
+
+########################################################################
+#
+# FUNCTION: ClipperGoToURL
+#
+# AUTHOR: Flash Sheridan, based on C code by David Fedor
+#
+# DESCRIPTION: Launches Clipper to view the given URL.
+#
+# PARAMETERS: URL string
+#
+# RETURNS: An OS error code; zero means no error.
+#
+########################################################################
+
+sub ClipperGoToURL
+{
+ my $url = $_[0] . "\0";
+ my $sysAppLaunchCmdGoToURL = 54;
+ my($ClipperID);
+#ifndef PUBLIC_STUFF_STRIPPED
+ $ClipperID = (DmFindDatabase (0, "Web Browser"));
+#endif // PUBLIC_STUFF_STRIPPED
+ $ClipperID = DmFindDatabase (0, "Clipper") if not $ClipperID;
+ die "Clipper not found" unless $ClipperID;
+
+ my $cmdPB = MemPtrNew (length ($url));
+ EmRPC::WriteBlock ($cmdPB, $url);
+ MemPtrSetOwner($cmdPB, 0);
+ SysUIAppSwitch (0, $ClipperID, $sysAppLaunchCmdGoToURL, $cmdPB);
+}
+
+1;
diff --git a/Scripting/Perl/FormSpy.pl b/Scripting/Perl/FormSpy.pl
new file mode 100755
index 0000000..f4d2a19
--- /dev/null
+++ b/Scripting/Perl/FormSpy.pl
@@ -0,0 +1,98 @@
+#!/usr/bin/perl -w
+########################################################################
+#
+# File: FormSpy.pl
+#
+# Purpose: Examine the current active form.
+#
+# Description: This script gets the current active form, iterates
+# over its contents, and prints out information on
+# all of the form objects. For each object, it prints
+#
+# * The object's index number (starting from zero)
+# * The object's type (frmTitleObj, etc.)
+# * Text associated with the object (only for title,
+# label, and control objects)
+# * The object's bounds
+#
+########################################################################
+
+use EmRPC; # EmRPC::OpenConnection, CloseConnection
+use EmFunctions;
+
+EmRPC::OpenConnection(6415, "localhost");
+
+ #=====================================================================
+ # Get the current form and the number objects on that form.
+ #=====================================================================
+
+ my ($form) = FrmGetActiveForm();
+ my ($num_objects) = FrmGetNumberOfObjects($form);
+
+ #=====================================================================
+ # Iterate over all the objects on the form.
+ #=====================================================================
+
+ for $ii (0..$num_objects - 1)
+ {
+ #=====================================================================
+ # Start generating the line to print. Start with the object's index.
+ #=====================================================================
+
+ my ($line) = "$ii. ";
+
+ #=====================================================================
+ # Add the object's type (frmTitleObj, etc.) to the line.
+ #=====================================================================
+
+ my ($object_type) = FrmGetObjectType($form, $ii);
+
+ my ($type) = ("frmFieldObj", "frmControlObj", "frmListObj", "frmTableObj",
+ "frmBitmapObj", "frmLineObj", "frmFrameObj", "frmRectangleObj",
+ "frmLabelObj", "frmTitleObj", "frmPopupObj", "frmGraffitiStateObj",
+ "frmGadgetObj", "frmScrollBarObj")[$object_type];
+
+ $line .= " $type";
+
+ #=====================================================================
+ # If the object is a frmControlObj, frmLabelObj, or frmTitleObj,
+ # get the text associated with the object and add it to our line.
+ #=====================================================================
+
+ if ($object_type == frmControlObj)
+ {
+ my ($obj_ptr) = FrmGetObjectPtr ($form, $ii);
+ my ($address, $label) = CtlGetLabel($obj_ptr);
+ $line .= " \"$label\"";
+ }
+ elsif ($object_type == frmLabelObj)
+ {
+ my ($label_id) = FrmGetObjectId ($form, $ii);
+ my ($address, $label) = FrmGetLabel($form, $label_id);
+ $line .= " \"$label\"";
+ }
+ elsif ($object_type == frmTitleObj)
+ {
+ my ($address, $title) = FrmGetTitle($form,);
+ $line .= " \"$title\"";
+ }
+ else
+ {
+ $line .= " <no label>";
+ }
+
+ #=====================================================================
+ # Add the object's bounds to the line.
+ #=====================================================================
+
+ my (%bounds) = FrmGetObjectBounds($form, $ii);
+ $line .= " ($bounds{left}, $bounds{top}, $bounds{right}, $bounds{bottom})";
+
+ #=====================================================================
+ # Print out the result.
+ #=====================================================================
+
+ print "$line\n";
+ }
+
+EmRPC::CloseConnection();
diff --git a/Scripting/Perl/HostControl.pm b/Scripting/Perl/HostControl.pm
new file mode 100644
index 0000000..4d481c8
--- /dev/null
+++ b/Scripting/Perl/HostControl.pm
@@ -0,0 +1,897 @@
+########################################################################
+#
+# File: HostControl.pm
+#
+# Purpose: Perl wrappers for Palm OS Emulator HostControl
+# functions.
+#
+# Description: This file contains Perl equivalents of Palm OS
+# Emulator Host Control functions, like HostGetHostID,
+# HostGetHostVersion, HostProfileStart etc...
+#
+# In general, functions follow the calling
+# conventions in the SDK headers. However, there
+# are exceptions. See the comments before each
+# subroutine for details.
+#
+########################################################################
+
+package HostControl;
+
+use EmRPC qw(DoRPC);
+use EmSysTraps;
+
+use strict;
+use vars qw(@ISA @EXPORT);
+
+use Exporter;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+
+ HostGetHostVersion HostGetHostID HostGetHostPlatform
+ HostIsSelectorImplemented HostGestalt HostIsCallingTrap
+
+ HostProfileInit HostProfileStart HostProfileStop HostProfileDump
+ HostProfileCleanup HostProfileDetailFn
+
+ HostErrNo HostFClose HostFEOF HostFError HostFFlush HostFGetC
+ HostFGetPos HostFGetS HostFOpen HostFPrintF HostFPutC HostFPutS
+ HostFRead HostRemove HostRename HostFReopen HostFScanF HostFSeek
+ HostFSetPos HostFTell HostFWrite HostTmpFile HostTmpNam HostGetEnv
+
+ HostMalloc HostRealloc HostFree
+
+ HostGremlinIsRunning HostGremlinNumber HostGremlinCounter
+ HostGremlinLimit HostGremlinNew
+
+ HostImportFile HostExportFile
+
+ HostGetPreference HostSetPreference
+
+ HostLogFile HostSetLogFileSize
+
+ HostSessionCreate HostSessionOpen HostSessionClose HostSessionQuit
+ HostSignalSend HostSignalWait HostSignalResume
+
+ HostTraceInit HostTraceClose HostTraceOutputT HostTraceOutputTL
+ HostTraceOutputVT HostTraceOutputVTL HostTraceOutputB
+
+);
+
+#// HostControl.h functions.
+
+# Host information selectors
+use constant hostSelectorGetHostVersion => 0x0100;
+use constant hostSelectorGetHostID => 0x0101;
+use constant hostSelectorGetHostPlatform => 0x0102;
+use constant hostSelectorIsSelectorImplemented => 0x0103;
+use constant hostSelectorGestalt => 0x0104;
+use constant hostSelectorIsCallingTrap => 0x0105;
+
+# Profiler Selectors
+use constant hostSelectorProfileInit => 0x0200;
+use constant hostSelectorProfileStart => 0x0201;
+use constant hostSelectorProfileStop => 0x0202;
+use constant hostSelectorProfileDump => 0x0203;
+use constant hostSelectorProfileCleanup => 0x0204;
+use constant hostSelectorProfileDetailFn => 0x0205;
+
+# Std C Library wrapper selectors
+
+use constant hostSelectorErrNo => 0x0300;
+
+use constant hostSelectorFClose => 0x0301;
+use constant hostSelectorFEOF => 0x0302;
+use constant hostSelectorFError => 0x0303;
+use constant hostSelectorFFlush => 0x0304;
+use constant hostSelectorFGetC => 0x0305;
+use constant hostSelectorFGetPos => 0x0306;
+use constant hostSelectorFGetS => 0x0307;
+use constant hostSelectorFOpen => 0x0308;
+use constant hostSelectorFPrintF => 0x0309; # Floating point not yet supported in Poser
+use constant hostSelectorFPutC => 0x030A;
+use constant hostSelectorFPutS => 0x030B;
+use constant hostSelectorFRead => 0x030C;
+use constant hostSelectorRemove => 0x030D; # Not yet implemented in Poser
+use constant hostSelectorRename => 0x030E; # Not yet implemented in Poser
+use constant hostSelectorFReopen => 0x030F; # Not yet implemented in Poser
+use constant hostSelectorFScanF => 0x0310; # Not yet implemented in Poser
+use constant hostSelectorFSeek => 0x0311;
+use constant hostSelectorFSetPos => 0x0312;
+use constant hostSelectorFTell => 0x0313;
+use constant hostSelectorFWrite => 0x0314;
+use constant hostSelectorTmpFile => 0x0315;
+use constant hostSelectorTmpNam => 0x0316; # Not yet implemented in Poser
+use constant hostSelectorGetEnv => 0x0317;
+
+use constant hostSelectorMalloc => 0x0318; # Not yet implemented in Poser
+use constant hostSelectorRealloc => 0x0319; # Not yet implemented in Poser
+use constant hostSelectorFree => 0x031A; # Not yet implemented in Poser
+
+# Gremlin Selectors
+use constant hostSelectorGremlinIsRunning => 0x0400;
+use constant hostSelectorGremlinNumber => 0x0401;
+use constant hostSelectorGremlinCounter => 0x0402;
+use constant hostSelectorGremlinLimit => 0x0403;
+use constant hostSelectorGremlinNew => 0x0404;
+
+# Database Selectors
+use constant hostSelectorImportFile => 0x0500;
+use constant hostSelectorExportFile => 0x0501;
+
+# Preference Selectors
+use constant hostSelectorGetPreference => 0x0600;
+use constant hostSelectorSetPreference => 0x0601;
+
+# Logging Selectors
+use constant hostSelectorLogFile => 0x0700;
+use constant hostSelectorSetLogFileSize => 0x0701;
+
+# RPC Selectors
+use constant hostSelectorSessionCreate => 0x0800; # Not yet implemented in Poser
+use constant hostSelectorSessionOpen => 0x0801; # Not yet implemented in Poser
+use constant hostSelectorSessionClose => 0x0802;
+use constant hostSelectorSessionQuit => 0x0803;
+use constant hostSelectorSignalSend => 0x0804;
+use constant hostSelectorSignalWait => 0x0805;
+use constant hostSelectorSignalResume => 0x0806;
+
+# External tracing tool support
+use constant hostSelectorTraceInit => 0x0900;
+use constant hostSelectorTraceClose => 0x0901;
+use constant hostSelectorTraceOutputT => 0x0902;
+use constant hostSelectorTraceOutputTL => 0x0903;
+use constant hostSelectorTraceOutputVT => 0x0904;
+use constant hostSelectorTraceOutputVTL => 0x0905;
+use constant hostSelectorTraceOutputB => 0x0906;
+
+use constant hostSelectorLastTrapNumber => 0x0907;
+
+
+#/* ==================================================================== */
+#/* Host environment-related calls */
+#/* ==================================================================== */
+
+########################################################################
+#
+# FUNCTION: HostGetHostVersion
+#
+# DESCRIPTION: Get the version number of the host (Palm OS Emulator).
+#
+# PARAMETERS: None
+#
+# RETURNS: Version number of Poser in Palm OS version format.
+#
+########################################################################
+
+sub HostGetHostVersion
+{
+ # long HostGetHostVersion(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGetHostVersion, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGetHostID
+#
+# DESCRIPTION: Get the ID of the debugging host.
+#
+# PARAMETERS: None
+#
+# RETURNS: hostIDPalmOS, hostIDPalmOSEmulator, hostIDPalmOSSimulator
+# etc...
+#
+########################################################################
+
+sub HostGetHostID
+{
+ # HostID HostGetHostID(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGetHostID, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGetHostPlatform
+#
+# DESCRIPTION: Get the host platform ID.
+# hostPlatformPalmOS, hostPlatformWindows,
+# hostPlatformMacintosh, hostPlatformUnix etc...
+#
+# PARAMETERS: None
+#
+# RETURNS: hostPlatformPalmOS, hostPlatformWindows,
+# hostPlatformMacintosh, hostPlatformUnix etc...
+#
+########################################################################
+
+sub HostGetHostPlatform
+{
+ # HostPlatform HostGetHostPlatform(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGetHostPlatform, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostIsSelectorImplemented
+#
+# DESCRIPTION: Determines if the particular selector is implemented.
+#
+# PARAMETERS: None
+#
+# RETURNS: True or False.
+#
+########################################################################
+
+sub HostIsSelectorImplemented
+{
+ # HostBool HostIsSelectorImplemented(long selector)
+
+ my ($return, $format) = ("int32", "int16 int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorIsSelectorImplemented, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGestalt
+#
+# DESCRIPTION: Return queries about the Runtime environment.
+#
+# PARAMETERS: None
+#
+# RETURNS: Runtime environment info.
+#
+########################################################################
+
+sub HostGestalt
+{
+ # HostErr HostGestalt(long gestSel, long* response)
+
+ my ($return, $format) = ("HostErr", "int16 int32 rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGestalt, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostIsCallingTrap
+#
+# DESCRIPTION: Determines if the Palm OS Emulator is currently
+# calling a trap. True if so, false if not.
+#
+# PARAMETERS: None
+#
+# RETURNS: True if trap is being called, false if not.
+#
+########################################################################
+
+sub HostIsCallingTrap
+{
+ # HostBool HostIsCallingTrap(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorIsCallingTrap, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/* ==================================================================== */
+#/* Profiling-related calls */
+#/* ==================================================================== */
+
+
+########################################################################
+#
+# FUNCTION: HostProfileInit
+#
+# DESCRIPTION: Initializes and enables profiling in debugging host.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileInit
+{
+ # HostErr HostProfileInit(long maxCalls, long maxDepth)
+
+ my ($return, $format) = ("HostErr", "int16 int32 int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileInit, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostProfileDetailFn
+#
+# DESCRIPTION: Profiles the function that contains the specified
+# address.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileDetailFn
+{
+ # HostErr HostProfileDetailFn(void* addr, HostBool logDetails)
+
+ my ($return, $format) = ("HostErr", "int16 rptr int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileDetailFn, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostProfileStart
+#
+# DESCRIPTION: Turns Profiling on.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileStart
+{
+ # HostErr HostProfileStart(void)
+
+ my ($return, $format) = ("HostErr", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileStart, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostProfileStop
+#
+# DESCRIPTION: Initializes and enables profiling in debugging host.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileStop
+{
+ # HostErr HostProfileStop(void)
+
+ my ($return, $format) = ("HostErr", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileStop, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostProfileDump
+#
+# DESCRIPTION: Writes the current profiling information to the
+# named file.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileDump
+{
+ # HostErr HostProfileDump(const char* filename)
+
+ my ($return, $format) = ("HostErr", "int16 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileDump, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostProfileCleanup
+#
+# DESCRIPTION: Initializes and enables profiling in debugging host.
+#
+# PARAMETERS: None
+#
+# RETURNS: Returns zero if successful, non-zero otherwise.
+#
+########################################################################
+
+sub HostProfileCleanup
+{
+ # HostErr HostProfileCleanup(void)
+
+ my ($return, $format) = ("HostErr", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorProfileCleanup, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/* ==================================================================== */
+#/* Std C Library-related calls */
+#/* ADD LATER!!! */
+#/* ==================================================================== */
+
+
+#/* ==================================================================== */
+#/* Gremlin-related calls */
+#/* ==================================================================== */
+
+
+########################################################################
+#
+# FUNCTION: HostGremlinIsRunning
+#
+# DESCRIPTION: Determines if Gremlin is currently running.
+#
+# PARAMETERS: None
+#
+# RETURNS: True if a gremlin is currently running, False otherwise.
+#
+########################################################################
+
+sub HostGremlinIsRunning
+{
+ # HostBool HostGremlinIsRunning(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGremlinIsRunning, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGremlinNumber
+#
+# DESCRIPTION: Retrieves the number of the currently running gremlin.
+#
+# PARAMETERS: None
+#
+# RETURNS: The number of the current gremlin.
+# Only valid if a gremlin is currently executing.
+#
+########################################################################
+
+sub HostGremlinNumber
+{
+ # long HostGremlinNumber(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGremlinNumber, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGremlinCounter
+#
+# DESCRIPTION: Returns the current event counter of the currently
+# running gremlin.
+#
+# PARAMETERS: None
+#
+# RETURNS: Current event counter.
+# Only valid if a gremlin is currently executing.
+#
+########################################################################
+
+sub HostGremlinCounter
+{
+ # long HostGremlinCounter(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGremlinCounter, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGremlinLimit
+#
+# DESCRIPTION: Retrieves the limit value of the currently running gremlin.
+#
+# PARAMETERS: None
+#
+# RETURNS: Limit value of the currently running gremlin.
+# Only valid if a gremlin is currently executing.
+#
+########################################################################
+
+sub HostGremlinLimit
+{
+ # long HostGremlinLimit(void)
+
+ my ($return, $format) = ("int32", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGremlinLimit, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGremlinNew
+#
+# DESCRIPTION: Start a new Gremlin Horde.
+#
+# PARAMETERS: Starting Gremlin number.
+# Ending Gremlin number.
+# Frequency (in terms of Gremlin events) at which
+# states are automatically saved.
+# Switching depth (number of events generated before
+# switching to a different Gremlin).
+# Max depth (maximum number of events generated
+# for each Gremlin).
+# List of application names on which to run Gremlins.
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostGremlinNew
+{
+ # HostErr HostGremlinNew(const HostGremlinInfo*)
+
+ my($start, $stop, $save_freq, $switch_depth, $max_depth, @apps) = @_;
+
+ my ($app_string) = join (",", @apps);
+
+ my ($struct) = pack("NNNNN", $start, $stop, $save_freq, $switch_depth, $max_depth) . $app_string;
+
+ my ($return, $format) = ("HostErr", "int16 block");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGremlinNew, $struct);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/* ==================================================================== */
+#/* Import/export-related calls */
+#/* ==================================================================== */
+
+
+########################################################################
+#
+# FUNCTION: HostImportFile
+#
+# DESCRIPTION: Path to file on desktop
+# Card to import file to.
+#
+# PARAMETERS: None
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostImportFile
+{
+ # HostErr HostImportFile(const char* fileName, long cardNum)
+
+ my ($return, $format) = ("HostErr", "int16 string int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorImportFile, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostExportFile
+#
+# DESCRIPTION: Export a db from Emulator to the host.
+#
+# PARAMETERS: None
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostExportFile
+{
+ # HostErr HostExportFile(const char* fileName, long cardNum, const char* dbName)
+
+ my ($return, $format) = ("HostErr", "int16 string int32 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorExportFile, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/* ==================================================================== */
+#/* Logging-related calls */
+#/* ==================================================================== */
+
+
+########################################################################
+#
+# FUNCTION: HostSetPreference
+#
+# DESCRIPTION: Set a preference.
+#
+# PARAMETERS: prefName, The name of the preference whose value you
+# are setting.
+# prefValue, The new value of the preference.
+#
+# RETURNS: Nothing.
+#
+########################################################################
+
+sub HostSetPreference
+{
+ # void HostSetPreference(const char*, const char*)
+
+ my ($return, $format) = ("void", "int16 string string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSetPreference, @_);
+ #//EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostGetPreference
+#
+# DESCRIPTION: Export a db from Emulator to the host.
+#
+# PARAMETERS: prefName, The name of the preference whose value you
+# want to retrieve.
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostGetPreference
+{
+ # HostBool HostGetPreference(const char*, char*)
+
+ my ($return, $format) = ("int32", "int16 string string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorGetPreference, $_[0], "");
+ ($D0, prefName => $params[1],
+ prefValue => $params[2]);
+}
+
+
+
+
+########################################################################
+#
+# FUNCTION: HostSetLogFileSize
+#
+# DESCRIPTION: Determines the size of the log file the Palm OS
+# Emulator is using. By default the Palm OS Emulator
+# Uses a 1 MB log file to record the last 1 MB of
+# Log Data information.
+#
+# PARAMETERS: Size, The new size for the logging file in bytes.
+#
+# RETURNS: None.
+#
+#
+########################################################################
+
+sub HostSetLogFileSize
+{
+ # void HostSetLogFileSize(long)
+
+ my ($return, $format) = ("int16", "int16 int32");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSetLogFileSize, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+#/* ==================================================================== */
+#/* RPC-related calls */
+#/* ==================================================================== */
+
+
+########################################################################
+#
+# FUNCTION: HostSessionCreate
+#
+# DESCRIPTION: Create a new session.
+#
+# PARAMETERS: Name of device to emulate. Choices are: "Pilot",
+# "PalmPilot", "Palm III", "Palm IIIx",
+# "Palm V", "Palm VII".
+# RAM size (in K) to emulate.
+# Path to ROM to use.
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostSessionCreate
+{
+ # HostErr HostSessionCreate(const char* device, long ramSize, const char* romPath)
+
+ my ($return, $format) = ("HostErr", "int16 string int32 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSessionCreate, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSessionOpen
+#
+# DESCRIPTION: Open a previously create session file.
+#
+# PARAMETERS: Path to session file to open.
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostSessionOpen
+{
+ # HostErr HostSessionOpen(const char* psfFileName)
+
+ my ($return, $format) = ("HostErr", "int16 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSessionOpen, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSessionClose
+#
+# DESCRIPTION: Close the current session, optionally saving it.
+#
+# PARAMETERS: Name of session file to create. Can be null.
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostSessionClose
+{
+ # HostErr HostSessionClose(const char* saveFileName)
+
+ my ($return, $format) = ("HostErr", "int16 string");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSessionClose, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSessionQuit
+#
+# DESCRIPTION: Ask Palm OS Emulator to quit.
+#
+# PARAMETERS: None
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostSessionQuit
+{
+ # HostErr HostSessionQuit(void)
+
+ my ($return, $format) = ("HostErr", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSessionQuit, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSignalSend
+#
+# DESCRIPTION: Sends a signal to any script that has host signal
+# wait calls pending.
+#
+# PARAMETERS: signalNumber, The signal you want to wait for.
+#
+# RETURNS: List containing the error code and the numeric
+# signal value returned from the Emulator.
+#
+########################################################################
+
+sub HostSignalSend
+{
+ # HostErr HostSignalSend(HostSignal signalNumber)
+
+ my ($return, $format) = ("HostErr", "int16 int32*");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSignalSend, $_[0], 0);
+
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSignalWait
+#
+# DESCRIPTION: Wait for a signal from the Palm OS Emulator.
+#
+# PARAMETERS: timeout (in milliseconds)
+#
+# RETURNS: List containing the error code and the numeric
+# signal value returned from the Emulator.
+#
+########################################################################
+
+sub HostSignalWait
+{
+ # HostErr HostSignalWait(long timeout, HostSignal* signalNumber)
+
+ my ($return, $format) = ("HostErr", "int16 int32 rptr");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSignalWait, $_[0], 0);
+
+ ($D0, $params[2]); # 0 = selector, 1 = timeout, 2 = signal number
+}
+
+
+########################################################################
+#
+# FUNCTION: HostSignalResume
+#
+# DESCRIPTION: Tell the Emulator to resume after it has sent us
+# a signal.
+#
+# PARAMETERS: None
+#
+# RETURNS: Error code.
+#
+########################################################################
+
+sub HostSignalResume
+{
+ # HostErr HostSignalResume(void)
+
+ my ($return, $format) = ("HostErr", "int16");
+ my ($D0, $A0, @params) = EmRPC::DoRPC (EmSysTraps::sysTrapHostControl, $format,
+ hostSelectorSignalResume, @_);
+ EmRPC::ReturnValue ($return, $D0, $A0, @params);
+}
diff --git a/Scripting/Perl/HostControlTest.pl b/Scripting/Perl/HostControlTest.pl
new file mode 100644
index 0000000..ab751e3
--- /dev/null
+++ b/Scripting/Perl/HostControlTest.pl
@@ -0,0 +1,87 @@
+#@INC = push (@INC, "D:/Emulator");
+#@INC = push (@INC, "D:/Emulator/Scripting/Perl");
+#print $INC;
+
+use EmRPC; # EmRPC::OpenConnection, CloseConnection
+use HostControl;
+use EmFunctions;
+use EmUtils; # TapPenSync, TapButtonSync
+
+print "Start HostControlTest.pl\n";
+
+
+
+EmRPC::OpenConnection(6415, "localhost");
+
+
+my ($hostVers) = HostGetHostVersion();
+print "HostGetHostVersion = $hostVers\n";
+
+my ($hostID) = HostGetHostID();
+print "HostGetHostID = $hostID\n";
+
+my ($hostPlatform) = HostGetHostPlatform();
+print "HostGetHostPlatform = $hostPlatform\n";
+
+my ($hostSelector1) = HostIsSelectorImplemented(hostSelectorGetHostVersion);
+print "HostIsSelectorImplemented (hostSelectorGetHostVersion) = $hostSelector1\n";
+
+my ($hostSelector2) = HostIsSelectorImplemented(hostSelectorGetHostID);
+print "HostIsSelectorImplemented (hostSelectorGetHostID) = $hostSelector2\n";
+
+my ($hostSelector3) = HostIsSelectorImplemented(hostSelectorProfileInit);
+print "HostIsSelectorImplemented (hostSelectorProfileInit) = $hostSelector3\n";
+
+my ($hostGestalt) = HostGestalt(1000);
+print ("HostGestalt 1000 = $hostGestalt\n");
+
+my ($hostIsCallingTrap) = HostIsCallingTrap();
+print ("HostIsCallingTrap = $hostIsCallingTrap\n");
+
+
+#// Profiling Calls
+my ($profileInit) = HostProfileInit(1000, 1000);
+print ("HostProfileInit = $profileInit\n");
+
+#my ($profileDetailFn) = HostProfileDetailFn();
+#print ("HostProfileDetailFn = $profileDetailFn\n");
+
+#// profileStart crashed the Emulator Profiler 3.0a5e3.
+my ($profileStart) = HostProfileStart();
+print ("HostProfileStart = $profileStart\n");
+
+ my ($gremlinResponse) = HostGremlinNew(0, 0, 10000, 1000, 10000, "Address");
+ print ("HostGremlinNew = $gremlinResponse\n");
+
+ my ($gremlinResponse) = HostGremlinLimit();
+ print ("HostGremlinLimit = $gremlinResponse\n");
+
+ my ($gremlinResponse) = HostGremlinNumber();
+ print ("HostGremlinNumber = $gremlinResponse\n");
+
+ my ($gremlinResponse) = HostGremlinLimit();
+ print ("HostGremlinLimit = $gremlinResponse\n");
+
+ my ($gremlinResponse) = HostGremlinIsRunning();
+ print ("HostGremlinIsRunning = $gremlinResponse\n");
+
+ my ($gremlinResponse) = HostGremlinCounter();
+ print ("HostGremlinCounter = $gremlinResponse\n");
+
+
+#// profileStart crashed the Emulator Profiler 3.0a5e3.
+#// x outside of string at d:\Emulator\Scripting\Perl/EmRPC.pm line 594
+my ($profileResponse) = HostProfileStop();
+print ("HostProfileStop = $profileResponse\n");
+
+my ($profileResponse) = HostProfileDump("D:\Emulator\Dump.txt");
+print ("HostProfileDump = $profileResponse\n");
+
+my ($profileResponse) = HostProfileCleanup();
+print ("HostProfileCleanup = $profileResponse\n");
+
+
+
+
+
+EmRPC::CloseConnection();
diff --git a/Scripting/Perl/ListDatabases.pl b/Scripting/Perl/ListDatabases.pl
new file mode 100755
index 0000000..97914ae
--- /dev/null
+++ b/Scripting/Perl/ListDatabases.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/perl -w
+#
+# 2001-11-08 John Marshall <jmarshall@acm.org>
+
+use strict;
+use Getopt::Std;
+
+use EmRPC;
+use EmFunctions;
+
+my %opt;
+getopt ('', \%opt);
+
+EmRPC::OpenConnection (@ARGV);
+
+my ($cardNo, $i, $lid);
+
+print "card/LocalID\ttype\tcrid\tname\n" unless defined $opt{q};
+
+for $cardNo (0 .. MemNumCards () - 1) {
+ for $i (0 .. DmNumDatabases ($cardNo) - 1) {
+ my $localID = DmGetDatabase ($cardNo, $i);
+ my ($err, %r) = DmDatabaseInfo ($cardNo, $localID);
+ printf "%d 0x%08x\t%s\t%s\t%s\n",
+ $cardNo, $localID,
+ pack ("N", $r{type}), pack ("N", $r{creator}), $r{name};
+ }
+ }
+
+EmRPC::CloseConnection ();
diff --git a/Scripting/Perl/ListOpenDatabases.pl b/Scripting/Perl/ListOpenDatabases.pl
new file mode 100755
index 0000000..dec547e
--- /dev/null
+++ b/Scripting/Perl/ListOpenDatabases.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+# Lists all databases open in the current thread, topmost first. Obscure
+# fields are open count (#) and the mode with which the db was opened (see
+# &openflags below).
+#
+# 2001-10-25 John Marshall <jmarshall@acm.org>
+
+use strict;
+
+use EmRPC;
+use EmFunctions;
+
+EmRPC::OpenConnection (@ARGV);
+
+sub openflags {
+ my ($f) = @_;
+ local $_ = "";
+ $_ .= "R" if $f & dmModeReadOnly;
+ $_ .= "W" if $f & dmModeWrite;
+ $_ .= "L" if $f & dmModeLeaveOpen;
+ $_ .= "E" if $f & dmModeExclusive;
+ $_ .= "S" if $f & dmModeShowSecret;
+ return $_;
+ }
+
+print "DmOpenRef card/LocalID # mode r/type/crid name\n";
+
+my $db = 0;
+while (($db = DmNextOpenDatabase ($db)) != 0) {
+ printf "0x%08x ", $db;
+
+ my ($err, %r) = DmOpenDatabaseInfo ($db);
+
+ if ($err == 0) {
+ printf "%d 0x%08x%3d %-5s %s ",
+ $r{cardNo}, $r{dbID}, $r{openCount}, openflags($r{mode}),
+ $r{resDB}? "R" : "D";
+
+ my ($err, %r) = DmDatabaseInfo ($r{cardNo}, $r{dbID});
+
+ if ($err == 0) {
+ $_ = pack "NcN", $r{type}, ord " ", $r{creator};
+ s/[[:^print:]]/./g;
+ print "$_ $r{name}";
+ }
+ else { printf "[DmDatabaseInfo failed: 0x%x]", $err; }
+ }
+ else { printf "[DmOpenDatabaseInfo failed: 0x%x]", $err; }
+
+ print "\n";
+ }
+
+EmRPC::CloseConnection ();
diff --git a/Scripting/Perl/MakeSysTraps.pl b/Scripting/Perl/MakeSysTraps.pl
new file mode 100644
index 0000000..a70029f
--- /dev/null
+++ b/Scripting/Perl/MakeSysTraps.pl
@@ -0,0 +1,88 @@
+#Usage for #define format is `perl MakeSysTraps.pl -d /path/to/systrap.h'.
+
+use strict;
+
+if (@ARGV == 0)
+{
+ print <<EOF;
+Usage: $0 [-cds] file...
+Generates an annotated list of systraps from the named files.
+ <default> Produces output suitable for the build-prc data file.
+ -s Produces an asm include file.
+ -d Produces a bunch of #defines.
+ -c Produces a list of Perl constants.
+EOF
+ exit;
+}
+
+my ($format, $forConst);
+$forConst = 0;
+
+if ($ARGV[0] eq "-s")
+{
+ shift;
+ $format = "\t.equ %s,%s\n";
+ print <<EOF;
+/* DO NOT EDIT! This file was automatically produced by $0
+ from @ARGV */
+
+ .macro systrap trapname
+ trap #15
+ .word \\trapname
+ .endm
+
+EOF
+ }
+elsif ($ARGV[0] eq "-d")
+{
+ shift;
+ $format = "#define _P_sysTrap%s\t%s\n";
+ print <<EOF;
+/* DO NOT EDIT! This section was automatically produced by $0
+ from @ARGV */
+
+EOF
+}
+elsif ($ARGV[0] eq "-c")
+{
+ shift;
+ $format = "use constant sysTrap%s\t=> %s;\n";
+ $forConst = 1;
+ print <<EOF;
+# DO NOT EDIT! This section was automatically produced by $0
+# from @ARGV
+
+EOF
+}
+else
+{
+ $format = "<%s>\t%s\n";
+ print <<EOF;
+DO NOT EDIT! This file was automatically produced by $0
+from @ARGV
+
+EOF
+}
+
+my $num = 0;
+
+while (<>)
+{
+ s"//.*$""; # eat C++-style comments
+ s"/\*[^/]*\*/""g; # eat simple C-style comments (just in case)
+
+ if (/define\W+sysTrapBase\W+((0[xX][\da-fA-F]+)|(\d+))/)
+ {
+ $num = $1;
+ $num = oct $num if $num =~ /^0/;
+ }
+
+ next unless /=.*sysTrapBase.*,/ .. /}.*SysTrapNumber.*;/;
+
+ printf $format, $1, sprintf("\"%lX\"", $num++) if /sysTrap(\w+)\b/;
+}
+
+if ($forConst != 0)
+{
+ print "\n", "1;", "\n";
+}
diff --git a/Scripting/Perl/PoserRPC.pl b/Scripting/Perl/PoserRPC.pl
new file mode 100755
index 0000000..6141667
--- /dev/null
+++ b/Scripting/Perl/PoserRPC.pl
@@ -0,0 +1,313 @@
+#!/usr/bin/perl
+########################################################################
+#
+# File: PoserRPC.pl
+#
+# Purpose: Scrap file for testing Poser's RPC mechanism
+#
+# Description: This file contains a hodgepodge of scripts and
+# commands used to test out parts of Poser's RPC.
+# Don't take anything in this file too seriously;
+# it's provided only for completeness' sake.
+#
+########################################################################
+
+use EmRPC; # EmRPC::OpenConnection, CloseConnection
+use EmFunctions;
+use EmUtils; # Wait, TapPen, TapButton
+
+use constant hostSignalReserved => 0;
+use constant hostSignalIdle => 1;
+use constant hostSignalQuit => 2;
+use constant hostSignalSessionStarted => 3;
+use constant hostSignalSessionStopped => 4;
+
+EmRPC::OpenConnection(6415, "localhost");
+
+if (1)
+{
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispType, "xxxx");
+ print "hwrDispType", ($err ? ": err = $err" : (" = ", $result)), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispRev, "xx");
+ print "hwrDispRev", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispVers, "xx");
+ print "hwrDispVers", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispAllDepths, "xx");
+ print "hwrDispAllDepths", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispMaxDepth, "xx");
+ print "hwrDispMaxDepth", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispBootDepth, "xx");
+ print "hwrDispBootDepth", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispMaxGrays, "xx");
+ print "hwrDispMaxGrays", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispHorizontal, "xx");
+ print "hwrDispHorizontal", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispVertical, "xx");
+ print "hwrDispVertical", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispVRAMBaseAddr, "xxxx");
+ print "hwrDispVRAMBaseAddr", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispVRAMSize, "xxxx");
+ print "hwrDispVRAMSize", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispColor, "xx");
+ print "hwrDispColor", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispName, pack ("x32"));
+ print "hwrDispName", ($err ? ": err = $err" : (" = ", $result)), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispBaseAddr, "xxxx");
+ print "hwrDispBaseAddr", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispDepth, "xx");
+ print "hwrDispDepth", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispWidth, "xx");
+ print "hwrDispWidth", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispHeight, "xx");
+ print "hwrDispHeight", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispRowBytes, "xx");
+ print "hwrDispRowBytes", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispBacklight, "x");
+ print "hwrDispBacklight", ($err ? ": err = $err" : (" = ", unpack ("c", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispBrightness, "x");
+ print "hwrDispBrightness", ($err ? ": err = $err" : (" = ", unpack ("c", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispContrast, "x");
+ print "hwrDispContrast", ($err ? ": err = $err" : (" = ", unpack ("c", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispDbgIndicator, "xx");
+ print "hwrDispDbgIndicator", ($err ? ": err = $err" : (" = ", unpack ("n", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispEndAddr, "xxxx");
+ print "hwrDispEndAddr", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispBufferMask, "xxxx");
+ print "hwrDispBufferMask", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispResolutionX, "xxxx");
+ print "hwrDispResolutionX", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispResolutionY, "xxxx");
+ print "hwrDispResolutionY", ($err ? ": err = $err" : (" = ", unpack ("N", $result))), "\n";
+
+ my ($err, $result) = HwrDisplayAttributes (0, hwrDispMemAccessOK, "x");
+ print "hwrDispMemAccessOK", ($err ? ": err = $err" : (" = ", unpack ("c", $result))), "\n";
+}
+
+if (0)
+{
+ TapButtonSync("OK");
+}
+
+if (0)
+{
+ Wait();
+ $err = HostSessionClose (""); # Don't save
+ die "$err" if $err;
+ $err = HostSessionQuit ();
+ die "$err" if $err;
+}
+
+
+if (0)
+{
+ my ($err, $signal);
+
+ ########################################################################
+ print "Waiting for idle\n";
+
+ do {
+ ($err, $signal) = HostSignalWait (0x7fffffff);
+ if ($err)
+ {
+ HostSignalResume ();
+ die "Error $err while waiting for hostSignalIdle";
+ }
+ } while ($signal != hostSignalIdle);
+
+ ########################################################################
+ print "Closing session\n";
+
+ $err = HostSessionClose (""); # Don't save
+
+ ########################################################################
+ print "Waiting for session to close\n";
+
+ do {
+ ($err, $signal) = HostSignalWait (0x7fffffff);
+ if ($err)
+ {
+ HostSignalResume ();
+ die "Error $err while waiting for hostSignalSessionStopped";
+ }
+ } while ($signal != hostSignalSessionStopped);
+
+ ########################################################################
+ print "Creating session\n";
+
+ $err = HostSessionCreate ("PalmIII", 1024, "C:\\ROMs\\spp\\rom30dbg.rom");
+
+ ########################################################################
+ print "Waiting for session to start\n";
+
+ do {
+ ($err, $signal) = HostSignalWait (0x7fffffff);
+ if ($err)
+ {
+ HostSignalResume ();
+ die "Error $err while waiting for hostSignalSessionStarted";
+ }
+ } while ($signal != hostSignalSessionStarted);
+
+ ########################################################################
+ print "Closing session\n";
+
+ $err = HostSessionClose (""); # Don't save
+
+ ########################################################################
+ print "Waiting for session to close\n";
+
+ do {
+ ($err, $signal) = HostSignalWait (0x7fffffff);
+ if ($err)
+ {
+ HostSignalResume ();
+ die "Error $err while waiting for hostSignalSessionStopped";
+ }
+ } while ($signal != hostSignalSessionStopped);
+
+ ########################################################################
+
+ HostSignalResume ();
+ print "Done!\n";
+}
+
+if (0)
+{
+ $addr = MemPtrNew (100);
+ printf ("0x%08X\n", $addr);
+ EmRPC::WriteBlock ($addr, "1234567890");
+ $str = EmRPC::ReadBlock ($addr, 10);
+ print $str, "\n";
+ MemPtrFree ($addr);
+}
+
+if (0)
+{
+ TapPen (100, 100);
+}
+
+if (0)
+{
+ $vers = HostGetHostVersion ();
+ printf ("HostGetHostVersion() = 0x%08X\n", $vers);
+}
+
+if (0)
+{
+ $num = DmNumDatabases (0);
+ print "DmNumDatabases(0) = ", $num, "\n";
+
+ $localID = DmFindDatabase (0, "MemoDB");
+ printf ("DmFindDatabase(0, \"MemoDB\") = 0x%08X\n", $localID);
+
+ ($err, %results) = DmDatabaseInfo (0, $localID);
+ printf ("DmDatabaseInfo(0, 0x%08X) = 0x%08X\n", $localID, $err);
+ print ("results: \n");
+ print ("\tname = ", $results{name}, "\n");
+ print ("\tattributes = ", $results{attributes}, "\n");
+ print ("\tversion = ", $results{version}, "\n");
+ print ("\tcrDate = ", $results{crDate}, "\n");
+ print ("\tmodDate = ", $results{modDate}, "\n");
+ print ("\tbckUpDate = ", $results{bckUpDate}, "\n");
+ print ("\tmodNum = ", $results{modNum}, "\n");
+ print ("\tappInfoID = ", $results{appInfoID}, "\n");
+ print ("\tsortInfoID = ", $results{sortInfoID}, "\n");
+ print ("\ttype = ", $results{type}, "\n");
+ print ("\tcreator = ", $results{creator}, "\n");
+}
+
+if (0)
+{
+ $block = EmRPC::ReadBlock (0, 256);
+ EmRPC::PrintString ($block);
+}
+
+if (0)
+{
+ my ($form) = FrmGetActiveForm();
+ my ($num_objects) = FrmGetNumberOfObjects($form);
+
+ for $ii (0..$num_objects - 1)
+ {
+ my ($line) = "$ii. ";
+ my ($object_type) = FrmGetObjectType($form, $ii);
+
+ my ($type) = ("frmFieldObj", "frmControlObj", "frmListObj", "frmTableObj",
+ "frmBitmapObj", "frmLineObj", "frmFrameObj", "frmRectangleObj",
+ "frmLabelObj", "frmTitleObj", "frmPopupObj", "frmGraffitiStateObj",
+ "frmGadgetObj", "frmScrollBarObj")[$object_type];
+
+ $line .= " $type";
+
+ if ($object_type == frmControlObj)
+ {
+ my ($obj_ptr) = FrmGetObjectPtr ($form, $ii);
+ my ($address, $label) = CtlGetLabel($obj_ptr);
+ $line .= " \"$label\"";
+ }
+ elsif ($object_type == frmLabelObj)
+ {
+ my ($label_id) = FrmGetObjectId ($form, $ii);
+ my ($address, $label) = FrmGetLabel($form, $label_id);
+ $line .= " \"$label\"";
+ }
+ elsif ($object_type == frmTitleObj)
+ {
+ my ($address, $title) = FrmGetTitle($form,);
+ $line .= " \"$title\"";
+ }
+ else
+ {
+ $line .= " <no label>";
+ }
+
+ my (%bounds) = FrmGetObjectBounds($form, $ii);
+ $line .= " ($bounds{left}, $bounds{top}, $bounds{right}, $bounds{bottom})";
+
+ print "$line\n";
+ }
+}
+
+if (0)
+{
+ $err = HostSessionClose ("");
+ printf ("HostSessionClose() = 0x%08X\n", $err);
+
+ $err = HostSessionQuit ();
+ printf ("HostSessionQuit() = 0x%08X\n", $err);
+}
+
+if (0)
+{
+ HostGremlinNew (0, 3, 0, -1, 10000, "Memo Pad") == 0 || die "HostGremlinNew failed, stopped";
+}
+
+EmRPC::CloseConnection();
+
+
+
diff --git a/Scripting/Perl/SkipStartup.pl b/Scripting/Perl/SkipStartup.pl
new file mode 100755
index 0000000..2844c51
--- /dev/null
+++ b/Scripting/Perl/SkipStartup.pl
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+########################################################################
+#
+# File: SkipStartup.pl
+#
+# Purpose: Skip the Palm V startup application.
+#
+# Description: Run this script to skip past the application that
+# automatically starts when cold-booting a Palm V
+# (or Palm IIIx). It generates the appropriate
+# pen events to "tap past" the initial forms.
+#
+########################################################################
+
+use EmRPC; # EmRPC::OpenConnection, CloseConnection
+use EmFunctions;
+use EmUtils; # TapPenSync, TapButtonSync
+
+
+EmRPC::OpenConnection(6415, "localhost");
+
+ TapPenSync (100, 100); # Tap past first setup screen
+ TapPenSync (100, 100); # Tap past second setup screen
+
+ TapPenSync (10, 10); # First tap in pen calibration screen
+ TapPenSync (160-10, 160-10); # Second tap in pen calibration screen
+ TapPenSync (80, 60); # Confirmation tap in pen calibration screen
+
+ Wait();
+ Resume();
+ my ($titleptr, $title) = FrmGetTitle (FrmGetActiveForm ());
+
+ if ($title eq "Select Language")
+ {
+ # Tap past the extra screens in a 4.0 EFIGS ROM
+ TapButtonSync ("OK");
+ TapButtonSync ("Yes");
+ }
+
+ TapButtonSync ("Next"); # Tap Next button
+ TapButtonSync ("Done"); # Tap Done button
+
+EmRPC::CloseConnection();
diff --git a/Scripting/Python/Poser.py b/Scripting/Python/Poser.py
new file mode 100644
index 0000000..0febf45
--- /dev/null
+++ b/Scripting/Python/Poser.py
@@ -0,0 +1,471 @@
+# ======================================================================================
+# Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+# All rights reserved.
+# ======================================================================================
+#
+# File: Poser.py
+# Author: David Creemer
+# Created: Thu Jul 29 17:05:33 PDT 1999
+
+""" This module implements a connection to the PalmOS Emulator
+POSER. It provides a socket for client - poser communications, and an
+hierarchy of classes for formatting poser RPC and other SysPackets
+calls. """
+
+import sys
+import socket
+from struct import pack, unpack
+from string import upper,atoi
+
+# -----------------------------------------------------------------------------
+# Utility functions
+
+def _memdump( baseaddr, len, data ):
+ """return a string that is a nicely formatted hex and ascii dump of a range of bytes"""
+
+ base = "Addr=0x%08X " % (baseaddr)
+ base = base + "Len=0x%04X (%d) " % (len, len)
+ for i in range(len):
+ if (i % 8) == 0:
+ base = base + "\n %08X " % (baseaddr + i)
+ base = base + " %02X" % ( ord(data[i]) )
+ return base
+
+# -----------------------------------------------------------------------------
+class ProtocolException:
+
+ def __init__( self, msg ):
+ self._message = msg
+
+# -----------------------------------------------------------------------------
+
+class Socket:
+ """defines the interface by which an application talks with a running poser"""
+
+ # packet header signatures
+ _HeaderSignature1 = 0xBEEF
+ _HeaderSignature2 = 0xED
+
+ def __init__( self ):
+ self._sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
+ self._transid = 1
+ self._src = 1
+ self._type = 0
+
+ # ----------------------------------------------------------------
+ # public API
+ # ----------------------------------------------------------------
+
+ def connect( self, addr="localhost", port=6414 ):
+ """connect to the running poser at the given host and port"""
+ self._sock.connect( addr, port )
+
+ def close( self ):
+ """terminate communication with the connected poser"""
+ self._sock.close()
+
+ def call( self, pkt ):
+ """call the connected poser with the given sysCall packet"""
+ # get the raw packet data
+ pkt._marshal()
+ # prepare the header
+ shdr = pack( ">HBBBBHB", Socket._HeaderSignature1, Socket._HeaderSignature2,
+ pkt._dest, self._src, self._type, len( pkt._data ), self._transid );
+ shdr = shdr + pack( ">B", self._calcHeaderChecksum( shdr ) )
+ # send the packet pieces
+ spkt = shdr + pkt._data + pack( ">H", self._calcFooterChecksum( pkt._data ) )
+ self._sock.send( spkt )
+ # read the header
+ rhdr = self._sock.recv( 10 )
+ ( h1, b1, rsrc, rdest, rtype, rlen, rtid, rhcs ) = unpack( ">HBBBBHBB", rhdr )
+ # read in the body
+ pkt._data = self._sock.recv( rlen )
+ # read in the footer
+ rftr = self._sock.recv( 2 )
+ (rbcs) = unpack( ">H", rftr )
+ # bump the transaction id
+ self._transid = self._transid + 1
+ pkt._unmarshal()
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _calcHeaderChecksum( self, bytes ):
+ """calculate the checksum for the packet header"""
+ cs = 0
+ for c in bytes:
+ cs = cs + ord( c )
+ if ( cs > 255 ):
+ cs = cs - 256
+ return cs
+
+ def _calcFooterChecksum( self, body ):
+ """calculate the checksum for the packet body"""
+ # TBD
+ return 0
+
+ def __repr__( self ):
+ return "<poser socket, tid=" + str( self._transid ) + ", sock=" + \
+ str( self._sock ) + ">"
+
+#-----------------------------------------------------------------------------
+# Abstract base class for all SysPackets
+#-----------------------------------------------------------------------------
+
+class SysPacket:
+ """abstract base class for all poser SysPacket messages"""
+
+ def __init__( self ):
+ self._data = None
+ self._command = 0x00
+ self._dest = 0
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _marshal( self ):
+ """pack the packet data into a binary stream"""
+ return pack( ">BB", self._command, 0 )
+
+ def _unmarshal( self ):
+ """pull the packet data from the binary stream"""
+ ( self._command, dummy ) = unpack( ">BB", self._data[0:2] )
+ self._data = self._data[2:]
+
+ def __repr__( self ):
+ return "cmd=0x%02X" % ( self._command )
+
+
+
+#-----------------------------------------------------------------------------
+# Memory Reading and Writing SysPackets
+#-----------------------------------------------------------------------------
+
+class SysPacketMem( SysPacket ):
+ """ abstract parent class of mem read/write packet classes"""
+
+ def __init__( self, addr, length ):
+ """instantiate generic memory sys packet"""
+ SysPacket.__init__( self )
+ self._dest = 1
+ self._memAddr = addr
+ self._memLength = length
+ self._memory = None
+
+ # ----------------------------------------------------------------
+ # public API
+ # ----------------------------------------------------------------
+
+ def getMemory( self ):
+ """return the memory read"""
+ return self._memory
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def __repr__( self ):
+ return SysPacket.__repr__( self ) + ", " + _memdump( self._memAddr, self._memLength, self._memory )
+
+#-----------------------------------------------------------------------------
+
+class SysPacketReadMem( SysPacketMem ):
+ """A poser sysPacket which reads PalmOS memory"""
+
+ def __init__( self, addr, length ):
+ """instantiate read memory packet"""
+ SysPacketMem.__init__( self, addr, length )
+ self._command = 0x01
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _marshal( self ):
+ """marshal the RPC information & parameters into a flat byte stream"""
+ self._data = SysPacket._marshal( self ) + pack( ">LH",
+ self._memAddr,
+ self._memLength )
+
+ def _unmarshal( self ):
+ """unmarshal the RPC information & parameters from the flat byte stream"""
+ SysPacket._unmarshal( self )
+ self._memory = self._data[0:self._memLength]
+
+#-----------------------------------------------------------------------------
+
+class SysPacketWriteMem( SysPacketMem ):
+ """A poser sysPacket which writes PalmOS memory"""
+
+ def __init__( self, addr, data, length ):
+ """instantiate write memory"""
+ SysPacketMem.__init__( self, addr, length )
+ self._command = 0x02
+ self._memory = data
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _marshal( self ):
+ """marshal the RPC information & parameters into a flat byte stream"""
+ fmt = ">LH" + str(self._memLength) + "s"
+ self._data = SysPacket._marshal( self ) + pack( fmt,
+ self._memAddr,
+ self._memLength,
+ self._memory )
+
+#-----------------------------------------------------------------------------
+# OS Trap RPC SysPackets
+#-----------------------------------------------------------------------------
+
+class SysPacketRPC( SysPacket ):
+ """A poser sysPacket which implements a RPC call/respone PalmOS Trap call"""
+
+ def __init__( self, trap ):
+ """instantiate new RPC call with the trap word to be called"""
+ SysPacket.__init__( self )
+ self._dest = 1
+ self._command = 0x0A
+ self._trap = trap
+ self._params = {}
+ self._paramnames = [] # used to preserver order
+ self._a0 = 0
+ self._d0 = 0
+
+ # ----------------------------------------------------------------
+ # public API
+ # ----------------------------------------------------------------
+
+ def __len__( self ):
+ # return # of params + A0 and D0 registers
+ return len( self._paramnames ) + 2
+
+ def keys( self ):
+ return self._paramnames + [ 'A0' , 'D0' ]
+
+ def __setitem__( self, key, param ):
+ if upper( key ) == 'A0':
+ self._a0 = param
+ elif upper( key ) == 'D0':
+ self._d0 = param
+ else:
+ self._params[ key ] = param
+ self._paramnames.insert( 0, key )
+
+ def __getitem__( self, key ):
+ if upper( key ) == 'A0':
+ return self._a0
+ elif upper( key ) == 'D0':
+ return self._d0
+ else:
+ return self._params[ key ]._getvalue()
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _marshal( self ):
+ """marshal the RPC information & parameters into a flat byte stream"""
+ self._data = SysPacket._marshal( self ) + pack( ">HLLH",
+ self._trap,
+ self._d0,
+ self._a0,
+ len( self._params ) )
+ for pname in self._paramnames:
+ self._data = self._data + self._params[ pname ]._data
+
+ def _unmarshal( self ):
+ """unmarshal the RPC information & parameters from the flat byte stream"""
+ SysPacket._unmarshal( self )
+
+ ( self._trap, self._d0, self._a0, pcount ) = unpack( ">HLLH", self._data[0:12] )
+ self._data = self._data[12:]
+
+ if pcount != len( self._paramnames ):
+ raise ProtocolException, "Unexpected number of return parameters"
+
+ for i in range( pcount ):
+ pname = self._paramnames[i]
+ ( dummy, size ) = unpack( ">BB", self._data[0:2] )
+ self._params[ pname ]._data = self._data[0:size+2]
+ self._data = self._data[size+2:]
+ self._params[ pname ]._unmarshal()
+
+ def __repr__( self ):
+ base = "<sysPacketRPC, " + SysPacket.__repr__( self )
+ base = base + ", trap=0x%04X, " % ( self._trap )
+ base = base + "a0=0x%08X, " % (self._a0)
+ base = base + "d0=0x%08X(%d), " % (self._d0, self._d0)
+ base = base + "Params("
+ for pname in self._paramnames:
+ base = base + " " + pname + "=" + str( self._params[ pname ] )
+ return base + " ) >"
+
+#-----------------------------------------------------------------------------
+
+class SysPacketRPC2( SysPacketRPC ):
+
+ def __init__( self, trap ):
+ """instantiate a new RPC2 call with the trap word to be called"""
+ SysPacketRPC.__init__( self, trap )
+ self._dest = 14
+ self._command = 0x70
+ self._registers = {} # for A0,A1...,D0,D1...
+ self._exception = 0
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ # register list. order is important: don't change it
+ _reglist = [ 'D7','D6','D5','D4','D3','D2','D1','D0','A7','A6','A5','A4','A3','A2','A1','A0' ]
+ _reglistrev = [ 'A0','A1','A2','A3','A4','A5','A6','A7','D0','D1','D2','D3','D4','D5','D6','D7' ]
+
+ def _isRegister( self, key ):
+ return upper( key ) in SysPacketRPC2._reglist
+
+ def _makeRegMask( self ):
+ mask = 0
+ for r in SysPacketRPC2._reglist:
+ mask = mask << 1
+ if self._registers.has_key( r ):
+ mask = mask | 1
+ return mask
+
+ def __setitem__( self, key, param ):
+ if self._isRegister( key ):
+ self._registers[ upper( key ) ] = param
+ else:
+ self._params[ key ] = param
+ self._paramnames.insert( 0, key )
+
+ def __getitem__( self, key ):
+ if upper( key ) == 'A0':
+ return self._a0
+ elif upper( key ) == 'D0':
+ return self._d0
+ elif self._isRegister( key ):
+ # this may throw an exception. That's ok.
+ return self._registers[ upper( key ) ]
+ elif upper( key ) == 'exception':
+ return self._exception
+ else:
+ return self._params[ key ]._getvalue()
+
+ def _marshal( self ):
+ """marshal the RPC information & parameters into a flat byte stream"""
+ self._data = SysPacket._marshal( self ) + pack( ">HLLHH",
+ self._trap,
+ self._d0,
+ self._a0,
+ self._exception,
+ self._makeRegMask() )
+ # add registers
+ for r in self._registers.keys():
+ self._data = self._data + pack( ">L", self._registers[ r ] )
+
+ # add parameters
+ self._data = self._data + pack( ">H", len( self._params ) )
+ for pname in self._paramnames:
+ self._data = self._data + self._params[ pname ]._data
+
+ def _unmarshal( self ):
+ """unmarshal the RPC information & parameters from the flat byte stream"""
+ SysPacket._unmarshal( self )
+ ( self._trap, self._d0, self._a0, self._exception, regmask ) = unpack( ">HLLHH",
+ self._data[0:14] )
+ self._data = self._data[14:]
+
+ # extract the registers ( if any )
+ for r in SysPacketRPC2._reglistrev:
+ # if the mask bit is set
+ if regmask & 0x0001:
+ # extract register value & trim unmarshalled data
+ ( self._registers[ r ], ) = unpack( ">L", self._data )
+ self._data = self._data[4:]
+ # go onto next bit in mask
+ regmask = regmask >> 1
+
+ # extract parameter count
+ ( pcount, ) = unpack( ">H", self._data[0:2] )
+ self._data = self._data[2:]
+
+ # extract paramters
+ if pcount != len( self._paramnames ):
+ raise ProtocolException, "Unexpected number of return parameters"
+
+ for i in range( pcount ):
+ pname = self._paramnames[i]
+ ( dummy, size ) = unpack( ">BB", self._data[0:2] )
+ self._params[ pname ]._data = self._data[0:size+2]
+ self._data = self._data[size+2:]
+ self._params[ pname ]._unmarshal()
+
+ def __repr__( self ):
+ base = "<sysPacketRPC2, " + SysPacket.__repr__( self )
+ base = base + ", trap=0x%04X, " % ( self._trap )
+ base = base + "a0=0x%08X, " % (self._a0)
+ base = base + "d0=0x%08X(%d), " % (self._d0, self._d0)
+ base = base + "exception=0x%04X, " % (self._exception)
+ base = base + "registers=" + str(self._registers)
+ base = base + "Params("
+ for pname in self._paramnames:
+ base = base + " " + pname + "=" + str( self._params[ pname ] )
+ return base + " ) >"
+
+#-----------------------------------------------------------------------------
+
+class RPCParam:
+ """a parameter to a poser SysPacketRPC(2) call"""
+
+ def __init__( self, byref, type, value ):
+ """instantiate new RPC parameter of a given type and value"""
+ self._type = type
+ self._value = value
+ if byref:
+ self._byref = 1
+ else:
+ self._byref = 0
+ self._data = None
+ self._calcSize()
+ self._marshal()
+
+ # ----------------------------------------------------------------
+ # implementation methods
+ # ----------------------------------------------------------------
+
+ def _getvalue( self ):
+ """return the value of the param as received from the wire"""
+ self._unmarshal()
+ return self._value
+
+ def _calcSize( self ):
+ """calculate the size of the parameter based on its type"""
+ t = upper( self._type[ -1 ] )
+ if t == 'B':
+ self._size = 1
+ elif t == 'H':
+ self._size = 2
+ elif t == 'L':
+ self._size = 4
+ elif t == 'S':
+ # string with specified size ('32s')
+ self._size = atoi( self._type[:-1] )
+
+ def _marshal( self ):
+ """flatten the RPC param into a binary stream"""
+ self._data = pack( ">BB" + self._type,
+ self._byref, self._size, self._value )
+
+ def _unmarshal( self ):
+ """pull the RPC param data from the binary stream"""
+ ( self._byref, self._size ) = unpack( ">BB", self._data[0:2] )
+ ( self._value, ) = unpack( ">" + self._type, self._data[2:] )
+
+ def __repr__( self ):
+ return "<sysPacketRPC param, byref=" + str( self._byref ) + ", type=" + \
+ str( self._type ) + ", size=" + str( self._size ) + ", value=" + \
+ str( self._value ) + ">"
diff --git a/Scripting/Python/SysTraps.py b/Scripting/Python/SysTraps.py
new file mode 100644
index 0000000..fa8f238
--- /dev/null
+++ b/Scripting/Python/SysTraps.py
@@ -0,0 +1,895 @@
+# ======================================================================================
+# Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+# All rights reserved.
+# ======================================================================================
+#
+# File: SysTraps.py
+# Author: David Creemer
+# Created: Thu Jul 29 17:05:33 PDT 1999
+
+# PalmOS Trap table (not complete)
+
+sysTraps = {}
+sysTraps['sysTrapMemInit'] = 0xA000
+sysTraps['sysTrapMemInitHeapTable'] = 0xA001
+sysTraps['sysTrapMemStoreInit'] = 0xA002
+sysTraps['sysTrapMemCardFormat'] = 0xA003
+sysTraps['sysTrapMemCardInfo'] = 0xA004
+sysTraps['sysTrapMemStoreInfo'] = 0xA005
+sysTraps['sysTrapMemStoreSetInfo'] = 0xA006
+sysTraps['sysTrapMemNumHeaps'] = 0xA007
+sysTraps['sysTrapMemNumRAMHeaps'] = 0xA008
+sysTraps['sysTrapMemHeapID'] = 0xA009
+sysTraps['sysTrapMemHeapPtr'] = 0xA00A
+sysTraps['sysTrapMemHeapFreeBytes'] = 0xA00B
+sysTraps['sysTrapMemHeapSize'] = 0xA00C
+sysTraps['sysTrapMemHeapFlags'] = 0xA00D
+sysTraps['sysTrapMemHeapCompact'] = 0xA00E
+sysTraps['sysTrapMemHeapInit'] = 0xA00F
+sysTraps['sysTrapMemHeapFreeByOwnerID'] = 0xA010
+sysTraps['sysTrapMemChunkNew'] = 0xA011
+sysTraps['sysTrapMemChunkFree'] = 0xA012
+sysTraps['sysTrapMemPtrNew'] = 0xA013
+sysTraps['sysTrapMemPtrRecoverHandle'] = 0xA014
+sysTraps['sysTrapMemPtrFlags'] = 0xA015
+sysTraps['sysTrapMemPtrSize'] = 0xA016
+sysTraps['sysTrapMemPtrOwner'] = 0xA017
+sysTraps['sysTrapMemPtrHeapID'] = 0xA018
+sysTraps['sysTrapMemPtrCardNo'] = 0xA019
+sysTraps['sysTrapMemPtrToLocalID'] = 0xA01A
+sysTraps['sysTrapMemPtrSetOwner'] = 0xA01B
+sysTraps['sysTrapMemPtrResize'] = 0xA01C
+sysTraps['sysTrapMemPtrResetLock'] = 0xA01D
+sysTraps['sysTrapMemHandleNew'] = 0xA01E
+sysTraps['sysTrapMemHandleLockCount'] = 0xA01F
+sysTraps['sysTrapMemHandleToLocalID'] = 0xA020
+sysTraps['sysTrapMemHandleLock'] = 0xA021
+sysTraps['sysTrapMemHandleUnlock'] = 0xA022
+sysTraps['sysTrapMemLocalIDToGlobal'] = 0xA023
+sysTraps['sysTrapMemLocalIDKind'] = 0xA024
+sysTraps['sysTrapMemLocalIDToPtr'] = 0xA025
+sysTraps['sysTrapMemMove'] = 0xA026
+sysTraps['sysTrapMemSet'] = 0xA027
+sysTraps['sysTrapMemStoreSearch'] = 0xA028
+sysTraps['sysTrapReserved6'] = 0xA029
+sysTraps['sysTrapMemKernelInit'] = 0xA02A
+sysTraps['sysTrapMemHandleFree'] = 0xA02B
+sysTraps['sysTrapMemHandleFlags'] = 0xA02C
+sysTraps['sysTrapMemHandleSize'] = 0xA02D
+sysTraps['sysTrapMemHandleOwner'] = 0xA02E
+sysTraps['sysTrapMemHandleHeapID'] = 0xA02F
+sysTraps['sysTrapMemHandleDataStorage'] = 0xA030
+sysTraps['sysTrapMemHandleCardNo'] = 0xA031
+sysTraps['sysTrapMemHandleSetOwner'] = 0xA032
+sysTraps['sysTrapMemHandleResize'] = 0xA033
+sysTraps['sysTrapMemHandleResetLock'] = 0xA034
+sysTraps['sysTrapMemPtrUnlock'] = 0xA035
+sysTraps['sysTrapMemLocalIDToLockedPtr'] = 0xA036
+sysTraps['sysTrapMemSetDebugMode'] = 0xA037
+sysTraps['sysTrapMemHeapScramble'] = 0xA038
+sysTraps['sysTrapMemHeapCheck'] = 0xA039
+sysTraps['sysTrapMemNumCards'] = 0xA03A
+sysTraps['sysTrapMemDebugMode'] = 0xA03B
+sysTraps['sysTrapMemSemaphoreReserve'] = 0xA03C
+sysTraps['sysTrapMemSemaphoreRelease'] = 0xA03D
+sysTraps['sysTrapMemHeapDynamic'] = 0xA03E
+sysTraps['sysTrapMemNVParams'] = 0xA03F
+sysTraps['sysTrapDmInit'] = 0xA040
+sysTraps['sysTrapDmCreateDatabase'] = 0xA041
+sysTraps['sysTrapDmDeleteDatabase'] = 0xA042
+sysTraps['sysTrapDmNumDatabases'] = 0xA043
+sysTraps['sysTrapDmGetDatabase'] = 0xA044
+sysTraps['sysTrapDmFindDatabase'] = 0xA045
+sysTraps['sysTrapDmDatabaseInfo'] = 0xA046
+sysTraps['sysTrapDmSetDatabaseInfo'] = 0xA047
+sysTraps['sysTrapDmDatabaseSize'] = 0xA048
+sysTraps['sysTrapDmOpenDatabase'] = 0xA049
+sysTraps['sysTrapDmCloseDatabase'] = 0xA04A
+sysTraps['sysTrapDmNextOpenDatabase'] = 0xA04B
+sysTraps['sysTrapDmOpenDatabaseInfo'] = 0xA04C
+sysTraps['sysTrapDmResetRecordStates'] = 0xA04D
+sysTraps['sysTrapDmGetLastErr'] = 0xA04E
+sysTraps['sysTrapDmNumRecords'] = 0xA04F
+sysTraps['sysTrapDmRecordInfo'] = 0xA050
+sysTraps['sysTrapDmSetRecordInfo'] = 0xA051
+sysTraps['sysTrapDmAttachRecord'] = 0xA052
+sysTraps['sysTrapDmDetachRecord'] = 0xA053
+sysTraps['sysTrapDmMoveRecord'] = 0xA054
+sysTraps['sysTrapDmNewRecord'] = 0xA055
+sysTraps['sysTrapDmRemoveRecord'] = 0xA056
+sysTraps['sysTrapDmDeleteRecord'] = 0xA057
+sysTraps['sysTrapDmArchiveRecord'] = 0xA058
+sysTraps['sysTrapDmNewHandle'] = 0xA059
+sysTraps['sysTrapDmRemoveSecretRecords'] = 0xA05A
+sysTraps['sysTrapDmQueryRecord'] = 0xA05B
+sysTraps['sysTrapDmGetRecord'] = 0xA05C
+sysTraps['sysTrapDmResizeRecord'] = 0xA05D
+sysTraps['sysTrapDmReleaseRecord'] = 0xA05E
+sysTraps['sysTrapDmGetResource'] = 0xA05F
+sysTraps['sysTrapDmGet1Resource'] = 0xA060
+sysTraps['sysTrapDmReleaseResource'] = 0xA061
+sysTraps['sysTrapDmResizeResource'] = 0xA062
+sysTraps['sysTrapDmNextOpenResDatabase'] = 0xA063
+sysTraps['sysTrapDmFindResourceType'] = 0xA064
+sysTraps['sysTrapDmFindResource'] = 0xA065
+sysTraps['sysTrapDmSearchResource'] = 0xA066
+sysTraps['sysTrapDmNumResources'] = 0xA067
+sysTraps['sysTrapDmResourceInfo'] = 0xA068
+sysTraps['sysTrapDmSetResourceInfo'] = 0xA069
+sysTraps['sysTrapDmAttachResource'] = 0xA06A
+sysTraps['sysTrapDmDetachResource'] = 0xA06B
+sysTraps['sysTrapDmNewResource'] = 0xA06C
+sysTraps['sysTrapDmRemoveResource'] = 0xA06D
+sysTraps['sysTrapDmGetResourceIndex'] = 0xA06E
+sysTraps['sysTrapDmQuickSort'] = 0xA06F
+sysTraps['sysTrapDmQueryNextInCategory'] = 0xA070
+sysTraps['sysTrapDmNumRecordsInCategory'] = 0xA071
+sysTraps['sysTrapDmPositionInCategory'] = 0xA072
+sysTraps['sysTrapDmSeekRecordInCategory'] = 0xA073
+sysTraps['sysTrapDmMoveCategory'] = 0xA074
+sysTraps['sysTrapDmOpenDatabaseByTypeCreator'] = 0xA075
+sysTraps['sysTrapDmWrite'] = 0xA076
+sysTraps['sysTrapDmStrCopy'] = 0xA077
+sysTraps['sysTrapDmGetNextDatabaseByTypeCreator'] = 0xA078
+sysTraps['sysTrapDmWriteCheck'] = 0xA079
+sysTraps['sysTrapDmMoveOpenDBContext'] = 0xA07A
+sysTraps['sysTrapDmFindRecordByID'] = 0xA07B
+sysTraps['sysTrapDmGetAppInfoID'] = 0xA07C
+sysTraps['sysTrapDmFindSortPositionV10'] = 0xA07D
+sysTraps['sysTrapDmSet'] = 0xA07E
+sysTraps['sysTrapDmCreateDatabaseFromImage'] = 0xA07F
+sysTraps['sysTrapDbgSrcMessage'] = 0xA080
+sysTraps['sysTrapDbgMessage'] = 0xA081
+sysTraps['sysTrapDbgGetMessage'] = 0xA082
+sysTraps['sysTrapDbgCommSettings'] = 0xA083
+sysTraps['sysTrapErrDisplayFileLineMsg'] = 0xA084
+sysTraps['sysTrapErrSetJump'] = 0xA085
+sysTraps['sysTrapErrLongJump'] = 0xA086
+sysTraps['sysTrapErrThrow'] = 0xA087
+sysTraps['sysTrapErrExceptionList'] = 0xA088
+sysTraps['sysTrapSysBroadcastActionCode'] = 0xA089
+sysTraps['sysTrapSysUnimplemented'] = 0xA08A
+sysTraps['sysTrapSysColdBoot'] = 0xA08B
+sysTraps['sysTrapSysReset'] = 0xA08C
+sysTraps['sysTrapSysDoze'] = 0xA08D
+sysTraps['sysTrapSysAppLaunch'] = 0xA08E
+sysTraps['sysTrapSysAppStartup'] = 0xA08F
+sysTraps['sysTrapSysAppExit'] = 0xA090
+sysTraps['sysTrapSysSetA5'] = 0xA091
+sysTraps['sysTrapSysSetTrapAddress'] = 0xA092
+sysTraps['sysTrapSysGetTrapAddress'] = 0xA093
+sysTraps['sysTrapSysTranslateKernelErr'] = 0xA094
+sysTraps['sysTrapSysSemaphoreCreate'] = 0xA095
+sysTraps['sysTrapSysSemaphoreDelete'] = 0xA096
+sysTraps['sysTrapSysSemaphoreWait'] = 0xA097
+sysTraps['sysTrapSysSemaphoreSignal'] = 0xA098
+sysTraps['sysTrapSysTimerCreate'] = 0xA099
+sysTraps['sysTrapSysTimerWrite'] = 0xA09A
+sysTraps['sysTrapSysTaskCreate'] = 0xA09B
+sysTraps['sysTrapSysTaskDelete'] = 0xA09C
+sysTraps['sysTrapSysTaskTrigger'] = 0xA09D
+sysTraps['sysTrapSysTaskID'] = 0xA09E
+sysTraps['sysTrapSysTaskUserInfoPtr'] = 0xA09F
+sysTraps['sysTrapSysTaskDelay'] = 0xA0A0
+sysTraps['sysTrapSysTaskSetTermProc'] = 0xA0A1
+sysTraps['sysTrapSysUILaunch'] = 0xA0A2
+sysTraps['sysTrapSysNewOwnerID'] = 0xA0A3
+sysTraps['sysTrapSysSemaphoreSet'] = 0xA0A4
+sysTraps['sysTrapSysDisableInts'] = 0xA0A5
+sysTraps['sysTrapSysRestoreStatus'] = 0xA0A6
+sysTraps['sysTrapSysUIAppSwitch'] = 0xA0A7
+sysTraps['sysTrapSysCurAppInfoPV20'] = 0xA0A8
+sysTraps['sysTrapSysHandleEvent'] = 0xA0A9
+sysTraps['sysTrapSysInit'] = 0xA0AA
+sysTraps['sysTrapSysQSort'] = 0xA0AB
+sysTraps['sysTrapSysCurAppDatabase'] = 0xA0AC
+sysTraps['sysTrapSysFatalAlert'] = 0xA0AD
+sysTraps['sysTrapSysResSemaphoreCreate'] = 0xA0AE
+sysTraps['sysTrapSysResSemaphoreDelete'] = 0xA0AF
+sysTraps['sysTrapSysResSemaphoreReserve'] = 0xA0B0
+sysTraps['sysTrapSysResSemaphoreRelease'] = 0xA0B1
+sysTraps['sysTrapSysSleep'] = 0xA0B2
+sysTraps['sysTrapSysKeyboardDialogV10'] = 0xA0B3
+sysTraps['sysTrapSysAppLauncherDialog'] = 0xA0B4
+sysTraps['sysTrapSysSetPerformance'] = 0xA0B5
+sysTraps['sysTrapSysBatteryInfoV20'] = 0xA0B6
+sysTraps['sysTrapSysLibInstall'] = 0xA0B7
+sysTraps['sysTrapSysLibRemove'] = 0xA0B8
+sysTraps['sysTrapSysLibTblEntry'] = 0xA0B9
+sysTraps['sysTrapSysLibFind'] = 0xA0BA
+sysTraps['sysTrapSysBatteryDialog'] = 0xA0BB
+sysTraps['sysTrapSysCopyStringResource'] = 0xA0BC
+sysTraps['sysTrapSysKernelInfo'] = 0xA0BD
+sysTraps['sysTrapSysLaunchConsole'] = 0xA0BE
+sysTraps['sysTrapSysTimerDelete'] = 0xA0BF
+sysTraps['sysTrapSysSetAutoOffTime'] = 0xA0C0
+sysTraps['sysTrapSysFormPointerArrayToStrings'] = 0xA0C1
+sysTraps['sysTrapSysRandom'] = 0xA0C2
+sysTraps['sysTrapSysTaskSwitching'] = 0xA0C3
+sysTraps['sysTrapSysTimerRead'] = 0xA0C4
+sysTraps['sysTrapStrCopy'] = 0xA0C5
+sysTraps['sysTrapStrCat'] = 0xA0C6
+sysTraps['sysTrapStrLen'] = 0xA0C7
+sysTraps['sysTrapStrCompare'] = 0xA0C8
+sysTraps['sysTrapStrIToA'] = 0xA0C9
+sysTraps['sysTrapStrCaselessCompare'] = 0xA0CA
+sysTraps['sysTrapStrIToH'] = 0xA0CB
+sysTraps['sysTrapStrChr'] = 0xA0CC
+sysTraps['sysTrapStrStr'] = 0xA0CD
+sysTraps['sysTrapStrAToI'] = 0xA0CE
+sysTraps['sysTrapStrToLower'] = 0xA0CF
+sysTraps['sysTrapSerReceiveISP'] = 0xA0D0
+sysTraps['sysTrapSlkOpen'] = 0xA0D1
+sysTraps['sysTrapSlkClose'] = 0xA0D2
+sysTraps['sysTrapSlkOpenSocket'] = 0xA0D3
+sysTraps['sysTrapSlkCloseSocket'] = 0xA0D4
+sysTraps['sysTrapSlkSocketRefNum'] = 0xA0D5
+sysTraps['sysTrapSlkSocketSetTimeout'] = 0xA0D6
+sysTraps['sysTrapSlkFlushSocket'] = 0xA0D7
+sysTraps['sysTrapSlkSetSocketListener'] = 0xA0D8
+sysTraps['sysTrapSlkSendPacket'] = 0xA0D9
+sysTraps['sysTrapSlkReceivePacket'] = 0xA0DA
+sysTraps['sysTrapSlkSysPktDefaultResponse'] = 0xA0DB
+sysTraps['sysTrapSlkProcessRPC'] = 0xA0DC
+sysTraps['sysTrapConPutS'] = 0xA0DD
+sysTraps['sysTrapConGetS'] = 0xA0DE
+sysTraps['sysTrapFplInit'] = 0xA0DF
+sysTraps['sysTrapFplFree'] = 0xA0E0
+sysTraps['sysTrapFplFToA'] = 0xA0E1
+sysTraps['sysTrapFplAToF'] = 0xA0E2
+sysTraps['sysTrapFplBase10Info'] = 0xA0E3
+sysTraps['sysTrapFplLongToFloat'] = 0xA0E4
+sysTraps['sysTrapFplFloatToLong'] = 0xA0E5
+sysTraps['sysTrapFplFloatToULong'] = 0xA0E6
+sysTraps['sysTrapFplMul'] = 0xA0E7
+sysTraps['sysTrapFplAdd'] = 0xA0E8
+sysTraps['sysTrapFplSub'] = 0xA0E9
+sysTraps['sysTrapFplDiv'] = 0xA0EA
+sysTraps['sysTrapScrInit'] = 0xA0EB
+sysTraps['sysTrapScrCopyRectangle'] = 0xA0EC
+sysTraps['sysTrapScrDrawChars'] = 0xA0ED
+sysTraps['sysTrapScrLineRoutine'] = 0xA0EE
+sysTraps['sysTrapScrRectangleRoutine'] = 0xA0EF
+sysTraps['sysTrapScrScreenInfo'] = 0xA0F0
+sysTraps['sysTrapScrDrawNotify'] = 0xA0F1
+sysTraps['sysTrapScrSendUpdateArea'] = 0xA0F2
+sysTraps['sysTrapScrCompressScanLine'] = 0xA0F3
+sysTraps['sysTrapScrDeCompressScanLine'] = 0xA0F4
+sysTraps['sysTrapTimGetSeconds'] = 0xA0F5
+sysTraps['sysTrapTimSetSeconds'] = 0xA0F6
+sysTraps['sysTrapTimGetTicks'] = 0xA0F7
+sysTraps['sysTrapTimInit'] = 0xA0F8
+sysTraps['sysTrapTimSetAlarm'] = 0xA0F9
+sysTraps['sysTrapTimGetAlarm'] = 0xA0FA
+sysTraps['sysTrapTimHandleInterrupt'] = 0xA0FB
+sysTraps['sysTrapTimSecondsToDateTime'] = 0xA0FC
+sysTraps['sysTrapTimDateTimeToSeconds'] = 0xA0FD
+sysTraps['sysTrapTimAdjust'] = 0xA0FE
+sysTraps['sysTrapTimSleep'] = 0xA0FF
+sysTraps['sysTrapTimWake'] = 0xA100
+sysTraps['sysTrapCategoryCreateListV10'] = 0xA101
+sysTraps['sysTrapCategoryFreeListV10'] = 0xA102
+sysTraps['sysTrapCategoryFind'] = 0xA103
+sysTraps['sysTrapCategoryGetName'] = 0xA104
+sysTraps['sysTrapCategoryEditV10'] = 0xA105
+sysTraps['sysTrapCategorySelectV10'] = 0xA106
+sysTraps['sysTrapCategoryGetNext'] = 0xA107
+sysTraps['sysTrapCategorySetTriggerLabel'] = 0xA108
+sysTraps['sysTrapCategoryTruncateName'] = 0xA109
+sysTraps['sysTrapClipboardAddItem'] = 0xA10A
+sysTraps['sysTrapClipboardCheckIfItemExist'] = 0xA10B
+sysTraps['sysTrapClipboardGetItem'] = 0xA10C
+sysTraps['sysTrapCtlDrawControl'] = 0xA10D
+sysTraps['sysTrapCtlEraseControl'] = 0xA10E
+sysTraps['sysTrapCtlHideControl'] = 0xA10F
+sysTraps['sysTrapCtlShowControl'] = 0xA110
+sysTraps['sysTrapCtlGetValue'] = 0xA111
+sysTraps['sysTrapCtlSetValue'] = 0xA112
+sysTraps['sysTrapCtlGetLabel'] = 0xA113
+sysTraps['sysTrapCtlSetLabel'] = 0xA114
+sysTraps['sysTrapCtlHandleEvent'] = 0xA115
+sysTraps['sysTrapCtlHitControl'] = 0xA116
+sysTraps['sysTrapCtlSetEnabled'] = 0xA117
+sysTraps['sysTrapCtlSetUsable'] = 0xA118
+sysTraps['sysTrapCtlEnabled'] = 0xA119
+sysTraps['sysTrapEvtInitialize'] = 0xA11A
+sysTraps['sysTrapEvtAddEventToQueue'] = 0xA11B
+sysTraps['sysTrapEvtCopyEvent'] = 0xA11C
+sysTraps['sysTrapEvtGetEvent'] = 0xA11D
+sysTraps['sysTrapEvtGetPen'] = 0xA11E
+sysTraps['sysTrapEvtSysInit'] = 0xA11F
+sysTraps['sysTrapEvtGetSysEvent'] = 0xA120
+sysTraps['sysTrapEvtProcessSoftKeyStroke'] = 0xA121
+sysTraps['sysTrapEvtGetPenBtnList'] = 0xA122
+sysTraps['sysTrapEvtSetPenQueuePtr'] = 0xA123
+sysTraps['sysTrapEvtPenQueueSize'] = 0xA124
+sysTraps['sysTrapEvtFlushPenQueue'] = 0xA125
+sysTraps['sysTrapEvtEnqueuePenPoint'] = 0xA126
+sysTraps['sysTrapEvtDequeuePenStrokeInfo'] = 0xA127
+sysTraps['sysTrapEvtDequeuePenPoint'] = 0xA128
+sysTraps['sysTrapEvtFlushNextPenStroke'] = 0xA129
+sysTraps['sysTrapEvtSetKeyQueuePtr'] = 0xA12A
+sysTraps['sysTrapEvtKeyQueueSize'] = 0xA12B
+sysTraps['sysTrapEvtFlushKeyQueue'] = 0xA12C
+sysTraps['sysTrapEvtEnqueueKey'] = 0xA12D
+sysTraps['sysTrapEvtDequeueKeyEvent'] = 0xA12E
+sysTraps['sysTrapEvtWakeup'] = 0xA12F
+sysTraps['sysTrapEvtResetAutoOffTimer'] = 0xA130
+sysTraps['sysTrapEvtKeyQueueEmpty'] = 0xA131
+sysTraps['sysTrapEvtEnableGraffiti'] = 0xA132
+sysTraps['sysTrapFldCopy'] = 0xA133
+sysTraps['sysTrapFldCut'] = 0xA134
+sysTraps['sysTrapFldDrawField'] = 0xA135
+sysTraps['sysTrapFldEraseField'] = 0xA136
+sysTraps['sysTrapFldFreeMemory'] = 0xA137
+sysTraps['sysTrapFldGetBounds'] = 0xA138
+sysTraps['sysTrapFldGetTextPtr'] = 0xA139
+sysTraps['sysTrapFldGetSelection'] = 0xA13A
+sysTraps['sysTrapFldHandleEvent'] = 0xA13B
+sysTraps['sysTrapFldPaste'] = 0xA13C
+sysTraps['sysTrapFldRecalculateField'] = 0xA13D
+sysTraps['sysTrapFldSetBounds'] = 0xA13E
+sysTraps['sysTrapFldSetText'] = 0xA13F
+sysTraps['sysTrapFldGetFont'] = 0xA140
+sysTraps['sysTrapFldSetFont'] = 0xA141
+sysTraps['sysTrapFldSetSelection'] = 0xA142
+sysTraps['sysTrapFldGrabFocus'] = 0xA143
+sysTraps['sysTrapFldReleaseFocus'] = 0xA144
+sysTraps['sysTrapFldGetInsPtPosition'] = 0xA145
+sysTraps['sysTrapFldSetInsPtPosition'] = 0xA146
+sysTraps['sysTrapFldSetScrollPosition'] = 0xA147
+sysTraps['sysTrapFldGetScrollPosition'] = 0xA148
+sysTraps['sysTrapFldGetTextHeight'] = 0xA149
+sysTraps['sysTrapFldGetTextAllocatedSize'] = 0xA14A
+sysTraps['sysTrapFldGetTextLength'] = 0xA14B
+sysTraps['sysTrapFldScrollField'] = 0xA14C
+sysTraps['sysTrapFldScrollable'] = 0xA14D
+sysTraps['sysTrapFldGetVisibleLines'] = 0xA14E
+sysTraps['sysTrapFldGetAttributes'] = 0xA14F
+sysTraps['sysTrapFldSetAttributes'] = 0xA150
+sysTraps['sysTrapFldSendChangeNotification'] = 0xA151
+sysTraps['sysTrapFldCalcFieldHeight'] = 0xA152
+sysTraps['sysTrapFldGetTextHandle'] = 0xA153
+sysTraps['sysTrapFldCompactText'] = 0xA154
+sysTraps['sysTrapFldDirty'] = 0xA155
+sysTraps['sysTrapFldWordWrap'] = 0xA156
+sysTraps['sysTrapFldSetTextAllocatedSize'] = 0xA157
+sysTraps['sysTrapFldSetTextHandle'] = 0xA158
+sysTraps['sysTrapFldSetTextPtr'] = 0xA159
+sysTraps['sysTrapFldGetMaxChars'] = 0xA15A
+sysTraps['sysTrapFldSetMaxChars'] = 0xA15B
+sysTraps['sysTrapFldSetUsable'] = 0xA15C
+sysTraps['sysTrapFldInsert'] = 0xA15D
+sysTraps['sysTrapFldDelete'] = 0xA15E
+sysTraps['sysTrapFldUndo'] = 0xA15F
+sysTraps['sysTrapFldSetDirty'] = 0xA160
+sysTraps['sysTrapFldSendHeightChangeNotification'] = 0xA161
+sysTraps['sysTrapFldMakeFullyVisible'] = 0xA162
+sysTraps['sysTrapFntGetFont'] = 0xA163
+sysTraps['sysTrapFntSetFont'] = 0xA164
+sysTraps['sysTrapFntGetFontPtr'] = 0xA165
+sysTraps['sysTrapFntBaseLine'] = 0xA166
+sysTraps['sysTrapFntCharHeight'] = 0xA167
+sysTraps['sysTrapFntLineHeight'] = 0xA168
+sysTraps['sysTrapFntAverageCharWidth'] = 0xA169
+sysTraps['sysTrapFntCharWidth'] = 0xA16A
+sysTraps['sysTrapFntCharsWidth'] = 0xA16B
+sysTraps['sysTrapFntDescenderHeight'] = 0xA16C
+sysTraps['sysTrapFntCharsInWidth'] = 0xA16D
+sysTraps['sysTrapFntLineWidth'] = 0xA16E
+sysTraps['sysTrapFrmInitForm'] = 0xA16F
+sysTraps['sysTrapFrmDeleteForm'] = 0xA170
+sysTraps['sysTrapFrmDrawForm'] = 0xA171
+sysTraps['sysTrapFrmEraseForm'] = 0xA172
+sysTraps['sysTrapFrmGetActiveForm'] = 0xA173
+sysTraps['sysTrapFrmSetActiveForm'] = 0xA174
+sysTraps['sysTrapFrmGetActiveFormID'] = 0xA175
+sysTraps['sysTrapFrmGetUserModifiedState'] = 0xA176
+sysTraps['sysTrapFrmSetNotUserModified'] = 0xA177
+sysTraps['sysTrapFrmGetFocus'] = 0xA178
+sysTraps['sysTrapFrmSetFocus'] = 0xA179
+sysTraps['sysTrapFrmHandleEvent'] = 0xA17A
+sysTraps['sysTrapFrmGetFormBounds'] = 0xA17B
+sysTraps['sysTrapFrmGetWindowHandle'] = 0xA17C
+sysTraps['sysTrapFrmGetFormId'] = 0xA17D
+sysTraps['sysTrapFrmGetFormPtr'] = 0xA17E
+sysTraps['sysTrapFrmGetNumberOfObjects'] = 0xA17F
+sysTraps['sysTrapFrmGetObjectIndex'] = 0xA180
+sysTraps['sysTrapFrmGetObjectId'] = 0xA181
+sysTraps['sysTrapFrmGetObjectType'] = 0xA182
+sysTraps['sysTrapFrmGetObjectPtr'] = 0xA183
+sysTraps['sysTrapFrmHideObject'] = 0xA184
+sysTraps['sysTrapFrmShowObject'] = 0xA185
+sysTraps['sysTrapFrmGetObjectPosition'] = 0xA186
+sysTraps['sysTrapFrmSetObjectPosition'] = 0xA187
+sysTraps['sysTrapFrmGetControlValue'] = 0xA188
+sysTraps['sysTrapFrmSetControlValue'] = 0xA189
+sysTraps['sysTrapFrmGetControlGroupSelection'] = 0xA18A
+sysTraps['sysTrapFrmSetControlGroupSelection'] = 0xA18B
+sysTraps['sysTrapFrmCopyLabel'] = 0xA18C
+sysTraps['sysTrapFrmSetLabel'] = 0xA18D
+sysTraps['sysTrapFrmGetLabel'] = 0xA18E
+sysTraps['sysTrapFrmSetCategoryLabel'] = 0xA18F
+sysTraps['sysTrapFrmGetTitle'] = 0xA190
+sysTraps['sysTrapFrmSetTitle'] = 0xA191
+sysTraps['sysTrapFrmAlert'] = 0xA192
+sysTraps['sysTrapFrmDoDialog'] = 0xA193
+sysTraps['sysTrapFrmCustomAlert'] = 0xA194
+sysTraps['sysTrapFrmHelp'] = 0xA195
+sysTraps['sysTrapFrmUpdateScrollers'] = 0xA196
+sysTraps['sysTrapFrmGetFirstForm'] = 0xA197
+sysTraps['sysTrapFrmVisible'] = 0xA198
+sysTraps['sysTrapFrmGetObjectBounds'] = 0xA199
+sysTraps['sysTrapFrmCopyTitle'] = 0xA19A
+sysTraps['sysTrapFrmGotoForm'] = 0xA19B
+sysTraps['sysTrapFrmPopupForm'] = 0xA19C
+sysTraps['sysTrapFrmUpdateForm'] = 0xA19D
+sysTraps['sysTrapFrmReturnToForm'] = 0xA19E
+sysTraps['sysTrapFrmSetEventHandler'] = 0xA19F
+sysTraps['sysTrapFrmDispatchEvent'] = 0xA1A0
+sysTraps['sysTrapFrmCloseAllForms'] = 0xA1A1
+sysTraps['sysTrapFrmSaveAllForms'] = 0xA1A2
+sysTraps['sysTrapFrmGetGadgetData'] = 0xA1A3
+sysTraps['sysTrapFrmSetGadgetData'] = 0xA1A4
+sysTraps['sysTrapFrmSetCategoryTrigger'] = 0xA1A5
+sysTraps['sysTrapUIInitialize'] = 0xA1A6
+sysTraps['sysTrapUIReset'] = 0xA1A7
+sysTraps['sysTrapInsPtInitialize'] = 0xA1A8
+sysTraps['sysTrapInsPtSetLocation'] = 0xA1A9
+sysTraps['sysTrapInsPtGetLocation'] = 0xA1AA
+sysTraps['sysTrapInsPtEnable'] = 0xA1AB
+sysTraps['sysTrapInsPtEnabled'] = 0xA1AC
+sysTraps['sysTrapInsPtSetHeight'] = 0xA1AD
+sysTraps['sysTrapInsPtGetHeight'] = 0xA1AE
+sysTraps['sysTrapInsPtCheckBlink'] = 0xA1AF
+sysTraps['sysTrapLstSetDrawFunction'] = 0xA1B0
+sysTraps['sysTrapLstDrawList'] = 0xA1B1
+sysTraps['sysTrapLstEraseList'] = 0xA1B2
+sysTraps['sysTrapLstGetSelection'] = 0xA1B3
+sysTraps['sysTrapLstGetSelectionText'] = 0xA1B4
+sysTraps['sysTrapLstHandleEvent'] = 0xA1B5
+sysTraps['sysTrapLstSetHeight'] = 0xA1B6
+sysTraps['sysTrapLstSetSelection'] = 0xA1B7
+sysTraps['sysTrapLstSetListChoices'] = 0xA1B8
+sysTraps['sysTrapLstMakeItemVisible'] = 0xA1B9
+sysTraps['sysTrapLstGetNumberOfItems'] = 0xA1BA
+sysTraps['sysTrapLstPopupList'] = 0xA1BB
+sysTraps['sysTrapLstSetPosition'] = 0xA1BC
+sysTraps['sysTrapMenuInit'] = 0xA1BD
+sysTraps['sysTrapMenuDispose'] = 0xA1BE
+sysTraps['sysTrapMenuHandleEvent'] = 0xA1BF
+sysTraps['sysTrapMenuDrawMenu'] = 0xA1C0
+sysTraps['sysTrapMenuEraseStatus'] = 0xA1C1
+sysTraps['sysTrapMenuGetActiveMenu'] = 0xA1C2
+sysTraps['sysTrapMenuSetActiveMenu'] = 0xA1C3
+sysTraps['sysTrapRctSetRectangle'] = 0xA1C4
+sysTraps['sysTrapRctCopyRectangle'] = 0xA1C5
+sysTraps['sysTrapRctInsetRectangle'] = 0xA1C6
+sysTraps['sysTrapRctOffsetRectangle'] = 0xA1C7
+sysTraps['sysTrapRctPtInRectangle'] = 0xA1C8
+sysTraps['sysTrapRctGetIntersection'] = 0xA1C9
+sysTraps['sysTrapTblDrawTable'] = 0xA1CA
+sysTraps['sysTrapTblEraseTable'] = 0xA1CB
+sysTraps['sysTrapTblHandleEvent'] = 0xA1CC
+sysTraps['sysTrapTblGetItemBounds'] = 0xA1CD
+sysTraps['sysTrapTblSelectItem'] = 0xA1CE
+sysTraps['sysTrapTblGetItemInt'] = 0xA1CF
+sysTraps['sysTrapTblSetItemInt'] = 0xA1D0
+sysTraps['sysTrapTblSetItemStyle'] = 0xA1D1
+sysTraps['sysTrapTblUnhighlightSelection'] = 0xA1D2
+sysTraps['sysTrapTblSetRowUsable'] = 0xA1D3
+sysTraps['sysTrapTblGetNumberOfRows'] = 0xA1D4
+sysTraps['sysTrapTblSetCustomDrawProcedure'] = 0xA1D5
+sysTraps['sysTrapTblSetRowSelectable'] = 0xA1D6
+sysTraps['sysTrapTblRowSelectable'] = 0xA1D7
+sysTraps['sysTrapTblSetLoadDataProcedure'] = 0xA1D8
+sysTraps['sysTrapTblSetSaveDataProcedure'] = 0xA1D9
+sysTraps['sysTrapTblGetBounds'] = 0xA1DA
+sysTraps['sysTrapTblSetRowHeight'] = 0xA1DB
+sysTraps['sysTrapTblGetColumnWidth'] = 0xA1DC
+sysTraps['sysTrapTblGetRowID'] = 0xA1DD
+sysTraps['sysTrapTblSetRowID'] = 0xA1DE
+sysTraps['sysTrapTblMarkRowInvalid'] = 0xA1DF
+sysTraps['sysTrapTblMarkTableInvalid'] = 0xA1E0
+sysTraps['sysTrapTblGetSelection'] = 0xA1E1
+sysTraps['sysTrapTblInsertRow'] = 0xA1E2
+sysTraps['sysTrapTblRemoveRow'] = 0xA1E3
+sysTraps['sysTrapTblRowInvalid'] = 0xA1E4
+sysTraps['sysTrapTblRedrawTable'] = 0xA1E5
+sysTraps['sysTrapTblRowUsable'] = 0xA1E6
+sysTraps['sysTrapTblReleaseFocus'] = 0xA1E7
+sysTraps['sysTrapTblEditing'] = 0xA1E8
+sysTraps['sysTrapTblGetCurrentField'] = 0xA1E9
+sysTraps['sysTrapTblSetColumnUsable'] = 0xA1EA
+sysTraps['sysTrapTblGetRowHeight'] = 0xA1EB
+sysTraps['sysTrapTblSetColumnWidth'] = 0xA1EC
+sysTraps['sysTrapTblGrabFocus'] = 0xA1ED
+sysTraps['sysTrapTblSetItemPtr'] = 0xA1EE
+sysTraps['sysTrapTblFindRowID'] = 0xA1EF
+sysTraps['sysTrapTblGetLastUsableRow'] = 0xA1F0
+sysTraps['sysTrapTblGetColumnSpacing'] = 0xA1F1
+sysTraps['sysTrapTblFindRowData'] = 0xA1F2
+sysTraps['sysTrapTblGetRowData'] = 0xA1F3
+sysTraps['sysTrapTblSetRowData'] = 0xA1F4
+sysTraps['sysTrapTblSetColumnSpacing'] = 0xA1F5
+sysTraps['sysTrapWinCreateWindow'] = 0xA1F6
+sysTraps['sysTrapWinCreateOffscreenWindow'] = 0xA1F7
+sysTraps['sysTrapWinDeleteWindow'] = 0xA1F8
+sysTraps['sysTrapWinInitializeWindow'] = 0xA1F9
+sysTraps['sysTrapWinAddWindow'] = 0xA1FA
+sysTraps['sysTrapWinRemoveWindow'] = 0xA1FB
+sysTraps['sysTrapWinSetActiveWindow'] = 0xA1FC
+sysTraps['sysTrapWinSetDrawWindow'] = 0xA1FD
+sysTraps['sysTrapWinGetDrawWindow'] = 0xA1FE
+sysTraps['sysTrapWinGetActiveWindow'] = 0xA1FF
+sysTraps['sysTrapWinGetDisplayWindow'] = 0xA200
+sysTraps['sysTrapWinGetFirstWindow'] = 0xA201
+sysTraps['sysTrapWinEnableWindow'] = 0xA202
+sysTraps['sysTrapWinDisableWindow'] = 0xA203
+sysTraps['sysTrapWinGetWindowFrameRect'] = 0xA204
+sysTraps['sysTrapWinDrawWindowFrame'] = 0xA205
+sysTraps['sysTrapWinEraseWindow'] = 0xA206
+sysTraps['sysTrapWinSaveBits'] = 0xA207
+sysTraps['sysTrapWinRestoreBits'] = 0xA208
+sysTraps['sysTrapWinCopyRectangle'] = 0xA209
+sysTraps['sysTrapWinScrollRectangle'] = 0xA20A
+sysTraps['sysTrapWinGetDisplayExtent'] = 0xA20B
+sysTraps['sysTrapWinGetWindowExtent'] = 0xA20C
+sysTraps['sysTrapWinDisplayToWindowPt'] = 0xA20D
+sysTraps['sysTrapWinWindowToDisplayPt'] = 0xA20E
+sysTraps['sysTrapWinGetClip'] = 0xA20F
+sysTraps['sysTrapWinSetClip'] = 0xA210
+sysTraps['sysTrapWinResetClip'] = 0xA211
+sysTraps['sysTrapWinClipRectangle'] = 0xA212
+sysTraps['sysTrapWinDrawLine'] = 0xA213
+sysTraps['sysTrapWinDrawGrayLine'] = 0xA214
+sysTraps['sysTrapWinEraseLine'] = 0xA215
+sysTraps['sysTrapWinInvertLine'] = 0xA216
+sysTraps['sysTrapWinFillLine'] = 0xA217
+sysTraps['sysTrapWinDrawRectangle'] = 0xA218
+sysTraps['sysTrapWinEraseRectangle'] = 0xA219
+sysTraps['sysTrapWinInvertRectangle'] = 0xA21A
+sysTraps['sysTrapWinDrawRectangleFrame'] = 0xA21B
+sysTraps['sysTrapWinDrawGrayRectangleFrame'] = 0xA21C
+sysTraps['sysTrapWinEraseRectangleFrame'] = 0xA21D
+sysTraps['sysTrapWinInvertRectangleFrame'] = 0xA21E
+sysTraps['sysTrapWinGetFramesRectangle'] = 0xA21F
+sysTraps['sysTrapWinDrawChars'] = 0xA220
+sysTraps['sysTrapWinEraseChars'] = 0xA221
+sysTraps['sysTrapWinInvertChars'] = 0xA222
+sysTraps['sysTrapWinGetPattern'] = 0xA223
+sysTraps['sysTrapWinSetPattern'] = 0xA224
+sysTraps['sysTrapWinSetUnderlineMode'] = 0xA225
+sysTraps['sysTrapWinDrawBitmap'] = 0xA226
+sysTraps['sysTrapWinModal'] = 0xA227
+sysTraps['sysTrapWinGetWindowBounds'] = 0xA228
+sysTraps['sysTrapWinFillRectangle'] = 0xA229
+sysTraps['sysTrapWinDrawInvertedChars'] = 0xA22A
+sysTraps['sysTrapPrefOpenPreferenceDBV10'] = 0xA22B
+sysTraps['sysTrapPrefGetPreferences'] = 0xA22C
+sysTraps['sysTrapPrefSetPreferences'] = 0xA22D
+sysTraps['sysTrapPrefGetAppPreferencesV10'] = 0xA22E
+sysTraps['sysTrapPrefSetAppPreferencesV10'] = 0xA22F
+sysTraps['sysTrapSndInit'] = 0xA230
+sysTraps['sysTrapSndSetDefaultVolume'] = 0xA231
+sysTraps['sysTrapSndGetDefaultVolume'] = 0xA232
+sysTraps['sysTrapSndDoCmd'] = 0xA233
+sysTraps['sysTrapSndPlaySystemSound'] = 0xA234
+sysTraps['sysTrapAlmInit'] = 0xA235
+sysTraps['sysTrapAlmCancelAll'] = 0xA236
+sysTraps['sysTrapAlmAlarmCallback'] = 0xA237
+sysTraps['sysTrapAlmSetAlarm'] = 0xA238
+sysTraps['sysTrapAlmGetAlarm'] = 0xA239
+sysTraps['sysTrapAlmDisplayAlarm'] = 0xA23A
+sysTraps['sysTrapAlmEnableNotification'] = 0xA23B
+sysTraps['sysTrapHwrGetRAMMapping'] = 0xA23C
+sysTraps['sysTrapHwrMemWritable'] = 0xA23D
+sysTraps['sysTrapHwrMemReadable'] = 0xA23E
+sysTraps['sysTrapHwrDoze'] = 0xA23F
+sysTraps['sysTrapHwrSleep'] = 0xA240
+sysTraps['sysTrapHwrWake'] = 0xA241
+sysTraps['sysTrapHwrSetSystemClock'] = 0xA242
+sysTraps['sysTrapHwrSetCPUDutyCycle'] = 0xA243
+sysTraps['sysTrapHwrLCDInit'] = 0xA244
+sysTraps['sysTrapHwrLCDSleep'] = 0xA245
+sysTraps['sysTrapHwrTimerInit'] = 0xA246
+sysTraps['sysTrapHwrCursor'] = 0xA247
+sysTraps['sysTrapHwrBatteryLevel'] = 0xA248
+sysTraps['sysTrapHwrDelay'] = 0xA249
+sysTraps['sysTrapHwrEnableDataWrites'] = 0xA24A
+sysTraps['sysTrapHwrDisableDataWrites'] = 0xA24B
+sysTraps['sysTrapHwrLCDBaseAddr'] = 0xA24C
+sysTraps['sysTrapHwrLCDDrawBitmap'] = 0xA24D
+sysTraps['sysTrapHwrTimerSleep'] = 0xA24E
+sysTraps['sysTrapHwrTimerWake'] = 0xA24F
+sysTraps['sysTrapHwrLCDWake'] = 0xA250
+sysTraps['sysTrapHwrIRQ1Handler'] = 0xA251
+sysTraps['sysTrapHwrIRQ2Handler'] = 0xA252
+sysTraps['sysTrapHwrIRQ3Handler'] = 0xA253
+sysTraps['sysTrapHwrIRQ4Handler'] = 0xA254
+sysTraps['sysTrapHwrIRQ5Handler'] = 0xA255
+sysTraps['sysTrapHwrIRQ6Handler'] = 0xA256
+sysTraps['sysTrapHwrDockSignals'] = 0xA257
+sysTraps['sysTrapHwrPluggedIn'] = 0xA258
+sysTraps['sysTrapCrc16CalcBlock'] = 0xA259
+sysTraps['sysTrapSelectDayV10'] = 0xA25A
+sysTraps['sysTrapSelectTime'] = 0xA25B
+sysTraps['sysTrapDayDrawDaySelector'] = 0xA25C
+sysTraps['sysTrapDayHandleEvent'] = 0xA25D
+sysTraps['sysTrapDayDrawDays'] = 0xA25E
+sysTraps['sysTrapDayOfWeek'] = 0xA25F
+sysTraps['sysTrapDaysInMonth'] = 0xA260
+sysTraps['sysTrapDayOfMonth'] = 0xA261
+sysTraps['sysTrapDateDaysToDate'] = 0xA262
+sysTraps['sysTrapDateToDays'] = 0xA263
+sysTraps['sysTrapDateAdjust'] = 0xA264
+sysTraps['sysTrapDateSecondsToDate'] = 0xA265
+sysTraps['sysTrapDateToAscii'] = 0xA266
+sysTraps['sysTrapDateToDOWDMFormat'] = 0xA267
+sysTraps['sysTrapTimeToAscii'] = 0xA268
+sysTraps['sysTrapFind'] = 0xA269
+sysTraps['sysTrapFindStrInStr'] = 0xA26A
+sysTraps['sysTrapFindSaveMatch'] = 0xA26B
+sysTraps['sysTrapFindGetLineBounds'] = 0xA26C
+sysTraps['sysTrapFindDrawHeader'] = 0xA26D
+sysTraps['sysTrapPenOpen'] = 0xA26E
+sysTraps['sysTrapPenClose'] = 0xA26F
+sysTraps['sysTrapPenGetRawPen'] = 0xA270
+sysTraps['sysTrapPenCalibrate'] = 0xA271
+sysTraps['sysTrapPenRawToScreen'] = 0xA272
+sysTraps['sysTrapPenScreenToRaw'] = 0xA273
+sysTraps['sysTrapPenResetCalibration'] = 0xA274
+sysTraps['sysTrapPenSleep'] = 0xA275
+sysTraps['sysTrapPenWake'] = 0xA276
+sysTraps['sysTrapResLoadForm'] = 0xA277
+sysTraps['sysTrapResLoadMenu'] = 0xA278
+sysTraps['sysTrapFtrInit'] = 0xA279
+sysTraps['sysTrapFtrUnregister'] = 0xA27A
+sysTraps['sysTrapFtrGet'] = 0xA27B
+sysTraps['sysTrapFtrSet'] = 0xA27C
+sysTraps['sysTrapFtrGetByIndex'] = 0xA27D
+sysTraps['sysTrapGrfInit'] = 0xA27E
+sysTraps['sysTrapGrfFree'] = 0xA27F
+sysTraps['sysTrapGrfGetState'] = 0xA280
+sysTraps['sysTrapGrfSetState'] = 0xA281
+sysTraps['sysTrapGrfFlushPoints'] = 0xA282
+sysTraps['sysTrapGrfAddPoint'] = 0xA283
+sysTraps['sysTrapGrfInitState'] = 0xA284
+sysTraps['sysTrapGrfCleanState'] = 0xA285
+sysTraps['sysTrapGrfMatch'] = 0xA286
+sysTraps['sysTrapGrfGetMacro'] = 0xA287
+sysTraps['sysTrapGrfFilterPoints'] = 0xA288
+sysTraps['sysTrapGrfGetNumPoints'] = 0xA289
+sysTraps['sysTrapGrfGetPoint'] = 0xA28A
+sysTraps['sysTrapGrfFindBranch'] = 0xA28B
+sysTraps['sysTrapGrfMatchGlyph'] = 0xA28C
+sysTraps['sysTrapGrfGetGlyphMapping'] = 0xA28D
+sysTraps['sysTrapGrfGetMacroName'] = 0xA28E
+sysTraps['sysTrapGrfDeleteMacro'] = 0xA28F
+sysTraps['sysTrapGrfAddMacro'] = 0xA290
+sysTraps['sysTrapGrfGetAndExpandMacro'] = 0xA291
+sysTraps['sysTrapGrfProcessStroke'] = 0xA292
+sysTraps['sysTrapGrfFieldChange'] = 0xA293
+sysTraps['sysTrapGetCharSortValue'] = 0xA294
+sysTraps['sysTrapGetCharAttr'] = 0xA295
+sysTraps['sysTrapGetCharCaselessValue'] = 0xA296
+sysTraps['sysTrapPwdExists'] = 0xA297
+sysTraps['sysTrapPwdVerify'] = 0xA298
+sysTraps['sysTrapPwdSet'] = 0xA299
+sysTraps['sysTrapPwdRemove'] = 0xA29A
+sysTraps['sysTrapGsiInitialize'] = 0xA29B
+sysTraps['sysTrapGsiSetLocation'] = 0xA29C
+sysTraps['sysTrapGsiEnable'] = 0xA29D
+sysTraps['sysTrapGsiEnabled'] = 0xA29E
+sysTraps['sysTrapGsiSetShiftState'] = 0xA29F
+sysTraps['sysTrapKeyInit'] = 0xA2A0
+sysTraps['sysTrapKeyHandleInterrupt'] = 0xA2A1
+sysTraps['sysTrapKeyCurrentState'] = 0xA2A2
+sysTraps['sysTrapKeyResetDoubleTap'] = 0xA2A3
+sysTraps['sysTrapKeyRates'] = 0xA2A4
+sysTraps['sysTrapKeySleep'] = 0xA2A5
+sysTraps['sysTrapKeyWake'] = 0xA2A6
+sysTraps['sysTrapDlkControl'] = 0xA2A7
+sysTraps['sysTrapDlkStartServer'] = 0xA2A8
+sysTraps['sysTrapDlkGetSyncInfo'] = 0xA2A9
+sysTraps['sysTrapDlkSetLogEntry'] = 0xA2AA
+sysTraps['sysTrapIntlDispatch'] = 0xA2AB
+sysTraps['sysTrapSysLibLoad'] = 0xA2AC
+sysTraps['sysTrapSndPlaySmf'] = 0xA2AD
+sysTraps['sysTrapSndCreateMidiList'] = 0xA2AE
+sysTraps['sysTrapAbtShowAbout'] = 0xA2AF
+sysTraps['sysTrapMdmDial'] = 0xA2B0
+sysTraps['sysTrapMdmHangUp'] = 0xA2B1
+sysTraps['sysTrapDmSearchRecord'] = 0xA2B2
+sysTraps['sysTrapSysInsertionSort'] = 0xA2B3
+sysTraps['sysTrapDmInsertionSort'] = 0xA2B4
+sysTraps['sysTrapLstSetTopItem'] = 0xA2B5
+sysTraps['sysTrapSclSetScrollBar'] = 0xA2B6
+sysTraps['sysTrapSclDrawScrollBar'] = 0xA2B7
+sysTraps['sysTrapSclHandleEvent'] = 0xA2B8
+sysTraps['sysTrapSysMailboxCreate'] = 0xA2B9
+sysTraps['sysTrapSysMailboxDelete'] = 0xA2BA
+sysTraps['sysTrapSysMailboxFlush'] = 0xA2BB
+sysTraps['sysTrapSysMailboxSend'] = 0xA2BC
+sysTraps['sysTrapSysMailboxWait'] = 0xA2BD
+sysTraps['sysTrapSysTaskWait'] = 0xA2BE
+sysTraps['sysTrapSysTaskWake'] = 0xA2BF
+sysTraps['sysTrapSysTaskWaitClr'] = 0xA2C0
+sysTraps['sysTrapSysTaskSuspend'] = 0xA2C1
+sysTraps['sysTrapSysTaskResume'] = 0xA2C2
+sysTraps['sysTrapCategoryCreateList'] = 0xA2C3
+sysTraps['sysTrapCategoryFreeList'] = 0xA2C4
+sysTraps['sysTrapCategoryEditV20'] = 0xA2C5
+sysTraps['sysTrapCategorySelect'] = 0xA2C6
+sysTraps['sysTrapDmDeleteCategory'] = 0xA2C7
+sysTraps['sysTrapSysEvGroupCreate'] = 0xA2C8
+sysTraps['sysTrapSysEvGroupSignal'] = 0xA2C9
+sysTraps['sysTrapSysEvGroupRead'] = 0xA2CA
+sysTraps['sysTrapSysEvGroupWait'] = 0xA2CB
+sysTraps['sysTrapEvtEventAvail'] = 0xA2CC
+sysTraps['sysTrapEvtSysEventAvail'] = 0xA2CD
+sysTraps['sysTrapStrNCopy'] = 0xA2CE
+sysTraps['sysTrapKeySetMask'] = 0xA2CF
+sysTraps['sysTrapSelectDay'] = 0xA2D0
+sysTraps['sysTrapPrefGetPreference'] = 0xA2D1
+sysTraps['sysTrapPrefSetPreference'] = 0xA2D2
+sysTraps['sysTrapPrefGetAppPreferences'] = 0xA2D3
+sysTraps['sysTrapPrefSetAppPreferences'] = 0xA2D4
+sysTraps['sysTrapFrmPointInTitle'] = 0xA2D5
+sysTraps['sysTrapStrNCat'] = 0xA2D6
+sysTraps['sysTrapMemCmp'] = 0xA2D7
+sysTraps['sysTrapTblSetColumnEditIndicator'] = 0xA2D8
+sysTraps['sysTrapFntWordWrap'] = 0xA2D9
+sysTraps['sysTrapFldGetScrollValues'] = 0xA2DA
+sysTraps['sysTrapSysCreateDataBaseList'] = 0xA2DB
+sysTraps['sysTrapSysCreatePanelList'] = 0xA2DC
+sysTraps['sysTrapDlkDispatchRequest'] = 0xA2DD
+sysTraps['sysTrapStrPrintF'] = 0xA2DE
+sysTraps['sysTrapStrVPrintF'] = 0xA2DF
+sysTraps['sysTrapPrefOpenPreferenceDB'] = 0xA2E0
+sysTraps['sysTrapSysGraffitiReferenceDialog'] = 0xA2E1
+sysTraps['sysTrapSysKeyboardDialog'] = 0xA2E2
+sysTraps['sysTrapFntWordWrapReverseNLines'] = 0xA2E3
+sysTraps['sysTrapFntGetScrollValues'] = 0xA2E4
+sysTraps['sysTrapTblSetRowStaticHeight'] = 0xA2E5
+sysTraps['sysTrapTblHasScrollBar'] = 0xA2E6
+sysTraps['sysTrapSclGetScrollBar'] = 0xA2E7
+sysTraps['sysTrapFldGetNumberOfBlankLines'] = 0xA2E8
+sysTraps['sysTrapSysTicksPerSecond'] = 0xA2E9
+sysTraps['sysTrapHwrBacklight'] = 0xA2EA
+sysTraps['sysTrapDmDatabaseProtect'] = 0xA2EB
+sysTraps['sysTrapTblSetBounds'] = 0xA2EC
+sysTraps['sysTrapStrNCompare'] = 0xA2ED
+sysTraps['sysTrapStrNCaselessCompare'] = 0xA2EE
+sysTraps['sysTrapPhoneNumberLookup'] = 0xA2EF
+sysTraps['sysTrapFrmSetMenu'] = 0xA2F0
+sysTraps['sysTrapEncDigestMD5'] = 0xA2F1
+sysTraps['sysTrapDmFindSortPosition'] = 0xA2F2
+sysTraps['sysTrapSysBinarySearch'] = 0xA2F3
+sysTraps['sysTrapSysErrString'] = 0xA2F4
+sysTraps['sysTrapSysStringByIndex'] = 0xA2F5
+sysTraps['sysTrapEvtAddUniqueEventToQueue'] = 0xA2F6
+sysTraps['sysTrapStrLocalizeNumber'] = 0xA2F7
+sysTraps['sysTrapStrDelocalizeNumber'] = 0xA2F8
+sysTraps['sysTrapLocGetNumberSeparators'] = 0xA2F9
+sysTraps['sysTrapMenuSetActiveMenuRscID'] = 0xA2FA
+sysTraps['sysTrapLstScrollList'] = 0xA2FB
+sysTraps['sysTrapCategoryInitialize'] = 0xA2FC
+sysTraps['sysTrapEncDigestMD4'] = 0xA2FD
+sysTraps['sysTrapEncDES'] = 0xA2FE
+sysTraps['sysTrapLstGetVisibleItems'] = 0xA2FF
+sysTraps['sysTrapWinSetWindowBounds'] = 0xA300
+sysTraps['sysTrapCategorySetName'] = 0xA301
+sysTraps['sysTrapFldSetInsertionPoint'] = 0xA302
+sysTraps['sysTrapFrmSetObjectBounds'] = 0xA303
+sysTraps['sysTrapWinSetColors'] = 0xA304
+sysTraps['sysTrapFlpDispatch'] = 0xA305
+sysTraps['sysTrapFlpEmDispatch'] = 0xA306
+sysTraps['sysTrapExgInit'] = 0xA307
+sysTraps['sysTrapExgConnect'] = 0xA308
+sysTraps['sysTrapExgPut'] = 0xA309
+sysTraps['sysTrapExgGet'] = 0xA30A
+sysTraps['sysTrapExgAccept'] = 0xA30B
+sysTraps['sysTrapExgDisconnect'] = 0xA30C
+sysTraps['sysTrapExgSend'] = 0xA30D
+sysTraps['sysTrapExgReceive'] = 0xA30E
+sysTraps['sysTrapExgRegisterData'] = 0xA30F
+sysTraps['sysTrapExgNotifyReceive'] = 0xA310
+sysTraps['sysTrapExgControl'] = 0xA311
+sysTraps['sysTrapPrgStartDialogV31'] = 0xA312
+sysTraps['sysTrapPrgStopDialog'] = 0xA313
+sysTraps['sysTrapPrgUpdateDialog'] = 0xA314
+sysTraps['sysTrapPrgHandleEvent'] = 0xA315
+sysTraps['sysTrapImcReadFieldNoSemicolon'] = 0xA316
+sysTraps['sysTrapImcReadFieldQuotablePrintable'] = 0xA317
+sysTraps['sysTrapImcReadPropertyParameter'] = 0xA318
+sysTraps['sysTrapImcSkipAllPropertyParameters'] = 0xA319
+sysTraps['sysTrapImcReadWhiteSpace'] = 0xA31A
+sysTraps['sysTrapImcWriteQuotedPrintable'] = 0xA31B
+sysTraps['sysTrapImcWriteNoSemicolon'] = 0xA31C
+sysTraps['sysTrapImcStringIsAscii'] = 0xA31D
+sysTraps['sysTrapTblGetItemFont'] = 0xA31E
+sysTraps['sysTrapTblSetItemFont'] = 0xA31F
+sysTraps['sysTrapFontSelect'] = 0xA320
+sysTraps['sysTrapFntDefineFont'] = 0xA321
+sysTraps['sysTrapCategoryEdit'] = 0xA322
+sysTraps['sysTrapSysGetOSVersionString'] = 0xA323
+sysTraps['sysTrapSysBatteryInfo'] = 0xA324
+sysTraps['sysTrapSysUIBusy'] = 0xA325
+sysTraps['sysTrapWinValidateHandle'] = 0xA326
+sysTraps['sysTrapFrmValidatePtr'] = 0xA327
+sysTraps['sysTrapCtlValidatePointer'] = 0xA328
+sysTraps['sysTrapWinMoveWindowAddr'] = 0xA329
+sysTraps['sysTrapFrmAddSpaceForObject'] = 0xA32A
+sysTraps['sysTrapFrmNewForm'] = 0xA32B
+sysTraps['sysTrapCtlNewControl'] = 0xA32C
+sysTraps['sysTrapFldNewField'] = 0xA32D
+sysTraps['sysTrapLstNewList'] = 0xA32E
+sysTraps['sysTrapFrmNewLabel'] = 0xA32F
+sysTraps['sysTrapFrmNewBitmap'] = 0xA330
+sysTraps['sysTrapFrmNewGadget'] = 0xA331
+sysTraps['sysTrapFileOpen'] = 0xA332
+sysTraps['sysTrapFileClose'] = 0xA333
+sysTraps['sysTrapFileDelete'] = 0xA334
+sysTraps['sysTrapFileReadLow'] = 0xA335
+sysTraps['sysTrapFileWrite'] = 0xA336
+sysTraps['sysTrapFileSeek'] = 0xA337
+sysTraps['sysTrapFileTell'] = 0xA338
+sysTraps['sysTrapFileTruncate'] = 0xA339
+sysTraps['sysTrapFileControl'] = 0xA33A
+sysTraps['sysTrapFrmActiveState'] = 0xA33B
+sysTraps['sysTrapSysGetAppInfo'] = 0xA33C
+sysTraps['sysTrapSysGetStackInfo'] = 0xA33D
+sysTraps['sysTrapScrDisplayMode'] = 0xA33E
+sysTraps['sysTrapHwrLCDGetDepth'] = 0xA33F
+sysTraps['sysTrapHwrGetROMToken'] = 0xA340
+sysTraps['sysTrapDbgControl'] = 0xA341
+sysTraps['sysTrapExgDBRead'] = 0xA342
+sysTraps['sysTrapExgDBWrite'] = 0xA343
+sysTraps['sysTrapHostControl'] = 0xA344
+sysTraps['sysTrapFrmRemoveObject'] = 0xA345
+sysTraps['sysTrapSysReserved1'] = 0xA346
+sysTraps['sysTrapSysReserved2'] = 0xA347
+sysTraps['sysTrapSysReserved3'] = 0xA348
+sysTraps['sysTrapSysReserved4'] = 0xA349
+sysTraps['sysTrapHwrLCDContrast'] = 0xA34A
+sysTraps['sysTrapSysLCDContrast'] = 0xA34B
+sysTraps['sysTrapContrastAdjust'] = 0xA34C
+sysTraps['sysTrapHwrDockStatus'] = 0xA34D
+sysTraps['sysTrapFntWidthToOffset'] = 0xA34E
+sysTraps['sysTrapSelectOneTime'] = 0xA34F
+sysTraps['sysTrapWinDrawChar'] = 0xA350
+sysTraps['sysTrapWinDrawTruncChars'] = 0xA351
+sysTraps['sysTrapNotifyInit'] = 0xA352
+sysTraps['sysTrapNotifyRegister'] = 0xA353
+sysTraps['sysTrapNotifyUnregister'] = 0xA354
+sysTraps['sysTrapNotifyBroadcast'] = 0xA355
+sysTraps['sysTrapNotifyBroadcastDeferred'] = 0xA356
+sysTraps['sysTrapNotifyDatabaseAdded'] = 0xA357
+sysTraps['sysTrapNotifyDatabaseRemoved'] = 0xA358
+sysTraps['sysTrapSysWantEvent'] = 0xA359
+sysTraps['sysTrapFtrPtrNew'] = 0xA35A
+sysTraps['sysTrapFtrPtrFree'] = 0xA35B
+sysTraps['sysTrapFtrPtrResize'] = 0xA35C
+sysTraps['sysTrapSysReserved5'] = 0xA35D
+sysTraps['sysTrapHwrNVPrefSet'] = 0xA35E
+sysTraps['sysTrapHwrNVPrefGet'] = 0xA35F
+sysTraps['sysTrapFlashInit'] = 0xA360
+sysTraps['sysTrapFlashCompress'] = 0xA361
+sysTraps['sysTrapFlashErase'] = 0xA362
+sysTraps['sysTrapFlashProgram'] = 0xA363
+sysTraps['sysTrapAlmTimeChange'] = 0xA364
+sysTraps['sysTrapErrAlertCustom'] = 0xA365
+sysTraps['sysTrapPrgStartDialog'] = 0xA366
+sysTraps['sysTrapSerialDispatch'] = 0xA367
+sysTraps['sysTrapHwrBattery'] = 0xA368
+sysTraps['sysTrapDmGetDatabaseLockState'] = 0xA369
+sysTraps['sysTrapCncGetProfileList'] = 0xA36A
+sysTraps['sysTrapCncGetProfileInfo'] = 0xA36B
+sysTraps['sysTrapCncAddProfile'] = 0xA36C
+sysTraps['sysTrapCncDeleteProfile'] = 0xA36D
+sysTraps['sysTrapSndPlaySmfResource'] = 0xA36E
+sysTraps['sysTrapMemPtrDataStorage'] = 0xA36F
+sysTraps['sysTrapClipboardAppendItem'] = 0xA370
+sysTraps['sysTrapWiCmd'] = 0xA371
+sysTraps['sysTrapLastTrapNumber'] = 0xA372
diff --git a/Scripting/Python/Test.py b/Scripting/Python/Test.py
new file mode 100644
index 0000000..4213b21
--- /dev/null
+++ b/Scripting/Python/Test.py
@@ -0,0 +1,132 @@
+# ======================================================================================
+# Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+# All rights reserved.
+# ======================================================================================
+#
+# File: Test.py
+# Author: David Creemer
+# Created: Thu Jul 29 17:05:33 PDT 1999
+
+# Test of the Python Poser RPC mechanism
+#
+# This file includes a number of PalmOS sample function wrappers. Each
+# wraps a PalmOS trap or hostcontrol function, and calls the lower
+# level Poser RPC layer. Each function takes 1 or more parameters. The
+# first parameter is a required Poser Socket (an object representing a
+# connection to a running Poser). All other parameters are optional
+# and specific to each function.
+#
+
+import sys
+import Poser
+from SysTraps import *
+
+def MemReadMemory( poserSocket, addr, len ):
+ msg = Poser.SysPacketReadMem( addr, len )
+ poserSocket.call( msg )
+ return msg.getMemory()
+
+def MemWriteMemory( poserSocket, addr, data, len ):
+ msg = Poser.SysPacketWriteMem( addr, data, len )
+ poserSocket.call( msg )
+
+def MemPtrNew( poserSocket, size ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapMemPtrNew'] )
+ msg[ 'size' ] = Poser.RPCParam( 0, 'L', size )
+ poserSocket.call( msg )
+ return msg[ 'A0' ]
+
+def SysTicksPerSecond( poserSocket ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapSysTicksPerSecond'] )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def DmNumDatabases( poserSocket, cardNo ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapDmNumDatabases'] )
+ msg[ 'cardNo' ] = Poser.RPCParam( 0, 'H', cardNo )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def DmGetDatabase( poserSocket, cardNo, index ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapDmGetDatabase'] )
+ msg[ 'cardNo' ] = Poser.RPCParam( 0, 'H', cardNo )
+ msg[ 'index' ] = Poser.RPCParam( 1, 'H', index )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def DmFindDatabase( poserSocket, cardNo, name ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapDmFindDatabase'] )
+ msg[ 'cardNo' ] = Poser.RPCParam( 0, 'H', cardNo )
+ msg[ 'name' ] = Poser.RPCParam( 1, '32s', name )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def DmDatabaseInfo( poserSocket, cardNo, dbId ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapDmDatabaseInfo'] )
+ msg[ 'cardNo' ] = Poser.RPCParam( 0, 'H', cardNo )
+ msg[ 'dbId' ] = Poser.RPCParam( 0, 'L', dbId )
+ msg[ 'name' ] = Poser.RPCParam( 1, '32s', "" )
+ msg[ 'attributes' ] = Poser.RPCParam( 1, 'H', 0 )
+ msg[ 'version' ] = Poser.RPCParam( 1, 'H', 0 )
+ msg[ 'crDate' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'modDate' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'bckUpDate' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'modNum' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'appInfoID' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'sortInfoID' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'type' ] = Poser.RPCParam( 1, 'L', 0 )
+ msg[ 'creator' ] = Poser.RPCParam( 1, 'L', 0 )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def DmGetLastError( poserSocket ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapDmGetLastErr'] )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+def EvtEnqueueKey( poserSocket, ascii, keycode=0, modifiers=0 ):
+ msg = Poser.SysPacketRPC2( sysTraps['sysTrapEvtEnqueueKey'] )
+ msg[ 'ascii' ] = Poser.RPCParam( 0, 'H', ascii )
+ msg[ 'keycode' ] = Poser.RPCParam( 0, 'H', keycode )
+ msg[ 'modifiers' ] = Poser.RPCParam( 0, 'H', modifiers )
+ poserSocket.call( msg )
+ return msg[ 'D0' ]
+
+#-----------------------------------------------------------------------------
+
+def test():
+ ps = Poser.Socket()
+ ps.connect()
+
+ print "Enqueuing 'Hello'..."
+ EvtEnqueueKey( ps, ord('H') )
+ EvtEnqueueKey( ps, ord('e') )
+ EvtEnqueueKey( ps, ord('l') )
+ EvtEnqueueKey( ps, ord('l') )
+ EvtEnqueueKey( ps, ord('o') )
+ print "SysTicksPerSecond() =", SysTicksPerSecond( ps )
+
+ addr = MemPtrNew( ps, 10 )
+ print "MemPtrNew(10) =", addr
+ print "MemWriteMemory(",addr,",'123456789',10)"
+ MemWriteMemory( ps, addr, "123456789\0", 10 )
+
+ data = MemReadMemory( ps, addr, 10 )
+ print "MemReadMemory(",addr,",10)= ", data
+
+ print "DmNumDatabase(0) =", DmNumDatabases( ps, 0 )
+
+ print "DmFindDatabase(0, 'AddressDB') =", DmFindDatabase( ps, 0, "AddressDB" )
+ localid = DmFindDatabase( ps, 0, "MemoDB" )
+ print "DmFindDatabase(0, 'MemoDB') =", localid
+ print "DmDatabaseInfo(0,", localid,") =", DmDatabaseInfo( ps, 0, localid )
+ print "DmGetLastError() =", DmGetLastError( ps )
+
+## close the socket
+ ps.close()
+ sys.exit(1)
+
+#-----------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ test()
diff --git a/SrcShared/ATraps.cpp b/SrcShared/ATraps.cpp
new file mode 100644
index 0000000..91bbbf2
--- /dev/null
+++ b/SrcShared/ATraps.cpp
@@ -0,0 +1,453 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Includes
+// ---------------------------------------------------------------------------
+
+#include "EmCommon.h"
+#include "ATraps.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmCPU68K.h" // GetRegisters
+#include "EmException.h" // EmExceptionReset
+#include "EmPalmOS.h" // EmPalmOS
+#include "EmSession.h" // gSession
+#include "ErrorHandling.h" // Errors::ReportError
+#include "Miscellaneous.h" // StMemoryMapper
+#include "EmPalmFunction.h" // GetTrapName
+#include "Profiling.h" // StDisableAllProfiling
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Types
+// ---------------------------------------------------------------------------
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Functions
+// ---------------------------------------------------------------------------
+
+static Bool PrvHandleTrap12 (ExceptionNumber);
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Constants
+// ---------------------------------------------------------------------------
+
+const uint16 kOpcode_ROMCall = m68kTrapInstr + sysDispatchTrapNum;
+const uint16 kOpcode_ATrapReturn = m68kTrapInstr + kATrapReturnTrapNum;
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Variables
+// ---------------------------------------------------------------------------
+
+// ----- Saved variables -----------------------------------------------------
+
+// ----- UnSaved variables ---------------------------------------------------
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ ATrap
+// ===========================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::ATrap
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ATrap::ATrap (void) :
+#if (__GNUC__ < 2)
+/* Can't call the default constructor because there isn't one defined */
+/* on a struct as there is with a class under GCC 2.8.1 */
+ fNewRegisters (),
+#endif
+ fEmulatedStackMapper (this->GetStackBase (), kStackSize)
+{
+ // Get the registers.
+
+ EmAssert (gCPU68K);
+ gCPU68K->GetRegisters (fOldRegisters);
+ fNewRegisters = fOldRegisters;
+
+ // Make sure the CPU is not stopped. I suppose that we could force the CPU
+ // to no longer be stopped, but I'd rather that the Palm OS itself woke up
+ // first before we try making calls into it. Therefore, anything making
+ // an out-of-the-blue Palm OS call via this class (that is, a call outside
+ // of the context of a Palm OS function head- or tailpatch) should first
+ // bring the CPU to a halt by calling EmSession::ExecuteUntilSysCall first.
+
+ EmAssert (fNewRegisters.stopped == 0);
+
+ // Give ourselves our own private stack. We'll want this in case
+ // we're in the debugger and the stack pointer is hosed.
+
+ m68k_areg (fNewRegisters, 7) = EmBankMapped::GetEmulatedAddress (
+ this->GetStackBase () + kStackSize - 4);
+
+ // Remember this as a stack so that our stack sniffer won't complain.
+
+ char* stackBase = this->GetStackBase ();
+ StackRange range ( EmBankMapped::GetEmulatedAddress (&stackBase[0]),
+ EmBankMapped::GetEmulatedAddress (&stackBase[kStackSize - 4]));
+ EmPalmOS::RememberStackRange (range);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::~ATrap
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ATrap::~ATrap (void)
+{
+ // Put things back the way they were.
+
+ EmPalmOS::ForgetStack (EmBankMapped::GetEmulatedAddress (this->GetStackBase ()));
+
+ EmAssert (gCPU68K);
+ gCPU68K->SetRegisters (fOldRegisters);
+
+ // Check to see if anything interesting was registered while we
+ // were making the Palm OS subroutine call. The "check after end
+ // of cycle" bit may have gotten cleared when restoring the old
+ // registers, so set it on the off chance that it was. Doing this
+ // is harmless if there really aren't any scheduled tasks.
+
+ EmAssert (gSession);
+ gCPU68K->CheckAfterCycle ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::Call
+ *
+ * DESCRIPTION: Calls the given pseudo-ATrap.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::Call (uint16 trapWord)
+{
+ EmAssert (trapWord != sysTrapSysReset);
+
+ // Up until now, the registers in "regs" have been left alone. If any
+ // values were pushed on the stack, the stack position was reflected in
+ // fNewRegisters. Now's the time to move those values from fNewRegisters
+ // to regs.
+
+ EmAssert (gCPU68K);
+ gCPU68K->SetRegisters (fNewRegisters);
+
+ // Make the call.
+
+ this->DoCall(trapWord);
+
+ // Remember the resulting register values so that we can report them to
+ // the user when they call GetD0 and/or GetA0.
+
+ gCPU68K->GetRegisters (fNewRegisters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::PushByte
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::PushByte (uint8 iByte)
+{
+ StDisableAllProfiling stopper;
+
+ m68k_areg (fNewRegisters, 7) -= 2;
+ EmMemPut8 (m68k_areg (fNewRegisters, 7), iByte);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::PushWord
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::PushWord (uint16 iWord)
+{
+ StDisableAllProfiling stopper;
+
+ m68k_areg (fNewRegisters, 7) -= 2;
+ EmMemPut16 (m68k_areg (fNewRegisters, 7), iWord);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::PushLong
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::PushLong (uint32 iLong)
+{
+ StDisableAllProfiling stopper;
+
+ m68k_areg (fNewRegisters, 7) -= 4;
+ EmMemPut32 (m68k_areg (fNewRegisters, 7), iLong);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::SetNewDReg
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::SetNewDReg (int regNum, uint32 value)
+{
+ m68k_dreg (fNewRegisters, regNum) = value;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::SetNewAReg
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::SetNewAReg (int regNum, uint32 value)
+{
+ m68k_areg (fNewRegisters, regNum) = value;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::GetD0
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+uint32 ATrap::GetD0 (void)
+{
+ return m68k_dreg (fNewRegisters, 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::GetA0
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+uint32 ATrap::GetA0 (void)
+{
+ return m68k_areg (fNewRegisters, 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ATrap::DoCall
+ *
+ * DESCRIPTION: Calls the pseudo-ATrap. When we return, D0 or A0 should
+ * hold the result, the parameters will still be on the
+ * stack with the SP pointing to them, and the PC will be
+ * restored to what it was before this function was called.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ATrap::DoCall (uint16 trapWord)
+{
+ // Stop all profiling activities. Stop cycle counting and stop the
+ // recording of function entries and exits. We want our calls to
+ // ROM functions to be as transparent as possible.
+
+ StDisableAllProfiling stopper;
+
+
+ // Assert that the function we're trying to call is implemented.
+ //
+ // Oops...bad test...this doesn't work when we're calling a library.
+ // Instead, since we now invoke ROM functions by creating a TRAP $F
+ // sequence, we'll let our TRAP $F handler deal with validating the
+ // function call (it does that anyway).
+
+// EmAssert (LowMem::GetTrapAddress (trapWord));
+
+ // We call the ROM function by dummying up a sequence of 68xxx instructions
+ // for it. The sequence of instructions is:
+ //
+ // TRAP $F
+ // DC.W <dispatch number>
+ // TRAP $C
+ //
+ // The first two words invoke the function (calling any head- or tailpatches
+ // along the way). The third word allows the emulator to regain control
+ // after the function has returned.
+ //
+ // Note: this gets a little ugly on little-endian machines. The following
+ // instructions are stored on the emulator's stack. This memory is mapped
+ // into the emulated address space in such a fashion that no byteswapping of
+ // word or long values occurs. Thus, we have to put the data into Big Endian
+ // format when putting it into the array.
+ //
+ // However, opcodes are a special case. They are optimized in the emulator
+ // for fast access. Opcodes are *always* fetched a word at a time in host-
+ // endian order. Thus, the opcodes below have to be stored in host-endian
+ // order. That's why there's no call to Canonical to put them into Big
+ // Endian order.
+
+ uint16 code[] = { kOpcode_ROMCall, trapWord, kOpcode_ATrapReturn };
+
+ // Oh, OK, we do have to byteswap the trapWord. Opcodes are fetched with
+ // EmMemDoGet16, which always gets the value in host byte order. The
+ // trapWord is fetched with EmMemGet16, which gets values according to the
+ // rules of the memory bank. For the dummy bank, the defined byte order
+ // is Big Endian.
+
+ Canonical (code[1]);
+
+ // Map in the code stub so that the emulation code can access it.
+
+ StMemoryMapper mapper (code, sizeof (code));
+
+ // Prepare to handle the TRAP 12 exception.
+
+ EmAssert (gCPU68K);
+ gCPU68K->InstallHookException (kException_ATrapReturn, PrvHandleTrap12);
+
+ // Point the PC to our code.
+
+ emuptr newPC = EmBankMapped::GetEmulatedAddress (code);
+ m68k_setpc (newPC);
+
+ // Execute until the next break.
+
+ try
+ {
+ EmAssert (gSession);
+ gSession->ExecuteSubroutine ();
+ }
+ catch (EmExceptionReset& e)
+ {
+ e.SetTrapWord (trapWord);
+
+ // Remove the TRAP 12 exception handler.
+
+ EmAssert (gCPU68K);
+ gCPU68K->RemoveHookException (kException_ATrapReturn, PrvHandleTrap12);
+
+ throw;
+ }
+
+ // Remove the TRAP 12 exception handler.
+
+ EmAssert (gCPU68K);
+ gCPU68K->RemoveHookException (kException_ATrapReturn, PrvHandleTrap12);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ATrap::GetStackBase
+// ---------------------------------------------------------------------------
+
+char* ATrap::GetStackBase ()
+{
+ // Ensure that the stack is aligned to a longword address.
+
+ uint32 stackBase = (uint32) fStack;
+
+ stackBase += 3;
+ stackBase &= ~3;
+
+ return (char*) stackBase;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvHandleTrap12
+// ---------------------------------------------------------------------------
+
+Bool PrvHandleTrap12 (ExceptionNumber)
+{
+ EmAssert (gSession);
+ gSession->ScheduleSuspendSubroutineReturn ();
+
+ return true;
+}
diff --git a/SrcShared/ATraps.h b/SrcShared/ATraps.h
new file mode 100644
index 0000000..7558e0f
--- /dev/null
+++ b/SrcShared/ATraps.h
@@ -0,0 +1,58 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _ATRAPS_H_
+#define _ATRAPS_H_
+
+#include "Miscellaneous.h" // StMemoryMapper
+#include "UAE.h" // regstruct
+
+class SessionFile;
+
+class ATrap
+{
+ public:
+ ATrap (void);
+ ~ATrap (void);
+
+ void Call (uint16 trapWord);
+
+ void PushByte (uint8 iByte);
+ void PushWord (uint16 iWord);
+ void PushLong (uint32 iLong);
+
+ void SetNewDReg (int regNum, uint32 value);
+ void SetNewAReg (int regNum, uint32 value);
+
+ uint32 GetD0 (void);
+ uint32 GetA0 (void);
+
+ protected:
+
+ void DoCall (uint16 trapWord);
+
+ char* GetStackBase (void);
+
+ private:
+ regstruct fOldRegisters;
+ regstruct fNewRegisters;
+
+// static const int kStackSize = 4096; // VC++ is a bit medieval here...
+ enum { kStackSize = 4096 };
+ char fStack[kStackSize + 3];
+
+ StMemoryMapper fEmulatedStackMapper;
+};
+
+#endif /* _ATRAPS_H_ */
+
diff --git a/SrcShared/Byteswapping.cpp b/SrcShared/Byteswapping.cpp
new file mode 100644
index 0000000..473ae20
--- /dev/null
+++ b/SrcShared/Byteswapping.cpp
@@ -0,0 +1,488 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Byteswapping.h"
+
+#if BYTESWAP
+
+#include "UAE.h" // regstruct
+
+void Byteswap (HwrM68328Type& regs)
+{
+ Byteswap (regs.csAGroupBase);
+ Byteswap (regs.csBGroupBase);
+ Byteswap (regs.csCGroupBase);
+ Byteswap (regs.csDGroupBase);
+
+ Byteswap (regs.csAGroupMask);
+ Byteswap (regs.csBGroupMask);
+ Byteswap (regs.csCGroupMask);
+ Byteswap (regs.csDGroupMask);
+
+ Byteswap (regs.csASelect0);
+ Byteswap (regs.csASelect1);
+ Byteswap (regs.csASelect2);
+ Byteswap (regs.csASelect3);
+
+ Byteswap (regs.csBSelect0);
+ Byteswap (regs.csBSelect1);
+ Byteswap (regs.csBSelect2);
+ Byteswap (regs.csBSelect3);
+
+ Byteswap (regs.csCSelect0);
+ Byteswap (regs.csCSelect1);
+ Byteswap (regs.csCSelect2);
+ Byteswap (regs.csCSelect3);
+
+ Byteswap (regs.csDSelect0);
+ Byteswap (regs.csDSelect1);
+ Byteswap (regs.csDSelect2);
+ Byteswap (regs.csDSelect3);
+
+ Byteswap (regs.csDebug);
+
+ Byteswap (regs.pllControl);
+ Byteswap (regs.pllFreqSel);
+ Byteswap (regs.pllTest);
+
+ Byteswap (regs.intControl);
+ Byteswap (regs.intMaskHi);
+ Byteswap (regs.intMaskLo);
+ Byteswap (regs.intWakeupEnHi);
+ Byteswap (regs.intWakeupEnLo);
+ Byteswap (regs.intStatusHi);
+ Byteswap (regs.intStatusLo);
+ Byteswap (regs.intPendingHi);
+ Byteswap (regs.intPendingLo);
+
+ Byteswap (regs.pwmControl);
+ Byteswap (regs.pwmPeriod);
+ Byteswap (regs.pwmWidth);
+ Byteswap (regs.pwmCounter);
+
+ Byteswap (regs.tmr1Control);
+ Byteswap (regs.tmr1Prescaler);
+ Byteswap (regs.tmr1Compare);
+ Byteswap (regs.tmr1Capture);
+ Byteswap (regs.tmr1Counter);
+ Byteswap (regs.tmr1Status);
+
+ Byteswap (regs.tmr2Control);
+ Byteswap (regs.tmr2Prescaler);
+ Byteswap (regs.tmr2Compare);
+ Byteswap (regs.tmr2Capture);
+ Byteswap (regs.tmr2Counter);
+ Byteswap (regs.tmr2Status);
+
+ Byteswap (regs.wdControl);
+ Byteswap (regs.wdReference);
+ Byteswap (regs.wdCounter);
+
+ Byteswap (regs.spiSlave);
+
+ Byteswap (regs.spiMasterData);
+ Byteswap (regs.spiMasterControl);
+
+ Byteswap (regs.uControl);
+ Byteswap (regs.uBaud);
+ Byteswap (regs.uReceive);
+ Byteswap (regs.uTransmit);
+ Byteswap (regs.uMisc);
+
+ Byteswap (regs.lcdStartAddr);
+ Byteswap (regs.lcdScreenWidth);
+ Byteswap (regs.lcdScreenHeight);
+ Byteswap (regs.lcdCursorXPos);
+ Byteswap (regs.lcdCursorYPos);
+ Byteswap (regs.lcdCursorWidthHeight);
+ Byteswap (regs.lcdGrayPalette);
+
+ Byteswap (regs.rtcHourMinSec);
+ Byteswap (regs.rtcAlarm);
+ Byteswap (regs.rtcReserved);
+ Byteswap (regs.rtcControl);
+ Byteswap (regs.rtcIntStatus);
+ Byteswap (regs.rtcIntEnable);
+ Byteswap (regs.stopWatch);
+}
+
+
+void Byteswap (HwrM68EZ328Type& regs)
+{
+ Byteswap (regs.swID);
+
+ Byteswap (regs.csAGroupBase);
+ Byteswap (regs.csBGroupBase);
+ Byteswap (regs.csCGroupBase);
+ Byteswap (regs.csDGroupBase);
+
+ Byteswap (regs.csASelect);
+ Byteswap (regs.csBSelect);
+ Byteswap (regs.csCSelect);
+ Byteswap (regs.csDSelect);
+
+ Byteswap (regs.emuCS);
+
+ Byteswap (regs.pllControl);
+ Byteswap (regs.pllFreqSel);
+ Byteswap (regs.pllTest);
+
+ Byteswap (regs.intControl);
+ Byteswap (regs.intMaskHi);
+ Byteswap (regs.intMaskLo);
+ Byteswap (regs.intStatusHi);
+ Byteswap (regs.intStatusLo);
+ Byteswap (regs.intPendingHi);
+ Byteswap (regs.intPendingLo);
+
+ Byteswap (regs.pwmControl);
+
+ Byteswap (regs.tmr1Control);
+ Byteswap (regs.tmr1Prescaler);
+ Byteswap (regs.tmr1Compare);
+ Byteswap (regs.tmr1Capture);
+ Byteswap (regs.tmr1Counter);
+ Byteswap (regs.tmr1Status);
+
+ Byteswap (regs.spiMasterData);
+ Byteswap (regs.spiMasterControl);
+
+ Byteswap (regs.uControl);
+ Byteswap (regs.uBaud);
+ Byteswap (regs.uReceive);
+ Byteswap (regs.uTransmit);
+ Byteswap (regs.uMisc);
+ Byteswap (regs.uNonIntPresc);
+
+ Byteswap (regs.lcdStartAddr);
+ Byteswap (regs.lcdScreenWidth);
+ Byteswap (regs.lcdScreenHeight);
+ Byteswap (regs.lcdCursorXPos);
+ Byteswap (regs.lcdCursorYPos);
+ Byteswap (regs.lcdCursorWidthHeight);
+ Byteswap (regs.lcdContrastControlPWM);
+
+ Byteswap (regs.rtcHourMinSec);
+ Byteswap (regs.rtcAlarm);
+ Byteswap (regs.rtcWatchDog);
+ Byteswap (regs.rtcControl);
+ Byteswap (regs.rtcIntStatus);
+ Byteswap (regs.rtcIntEnable);
+ Byteswap (regs.stopWatch);
+ Byteswap (regs.rtcDay);
+ Byteswap (regs.rtcDayAlarm);
+
+ Byteswap (regs.dramConfig);
+ Byteswap (regs.dramControl);
+
+ Byteswap (regs.emuAddrCompare);
+ Byteswap (regs.emuAddrMask);
+ Byteswap (regs.emuControlCompare);
+ Byteswap (regs.emuControlMask);
+ Byteswap (regs.emuControl);
+ Byteswap (regs.emuStatus);
+}
+
+
+void Byteswap (HwrM68VZ328Type& regs)
+{
+ Byteswap (regs.scr);
+
+ Byteswap (regs.pcr);
+ Byteswap (regs.chipID);
+ Byteswap (regs.maskID);
+ Byteswap (regs.swID);
+ Byteswap (regs.ioDriveControl);
+
+ Byteswap (regs.csAGroupBase);
+ Byteswap (regs.csBGroupBase);
+ Byteswap (regs.csCGroupBase);
+ Byteswap (regs.csDGroupBase);
+
+ Byteswap (regs.csUGroupBase);
+
+ Byteswap (regs.csControl1);
+ Byteswap (regs.csControl2);
+ Byteswap (regs.csControl3);
+
+ Byteswap (regs.csASelect);
+ Byteswap (regs.csBSelect);
+ Byteswap (regs.csCSelect);
+ Byteswap (regs.csDSelect);
+
+ Byteswap (regs.emuCS);
+
+ Byteswap (regs.pllControl);
+ Byteswap (regs.pllFreqSel);
+
+ Byteswap (regs.pwrControl);
+
+ Byteswap (regs.intVector);
+ Byteswap (regs.intControl);
+ Byteswap (regs.intMaskHi);
+ Byteswap (regs.intMaskLo);
+ Byteswap (regs.intStatusHi);
+ Byteswap (regs.intStatusLo);
+ Byteswap (regs.intPendingHi);
+ Byteswap (regs.intPendingLo);
+ Byteswap (regs.intLevelControl);
+
+ Byteswap (regs.portADir);
+ Byteswap (regs.portAData);
+ Byteswap (regs.portAPullupEn);
+
+ Byteswap (regs.portBDir);
+ Byteswap (regs.portBData);
+ Byteswap (regs.portBPullupEn);
+ Byteswap (regs.portBSelect);
+
+ Byteswap (regs.portCDir);
+ Byteswap (regs.portCData);
+ Byteswap (regs.portCPulldnEn);
+ Byteswap (regs.portCSelect);
+
+ Byteswap (regs.portDDir);
+ Byteswap (regs.portDData);
+ Byteswap (regs.portDPullupEn);
+ Byteswap (regs.portDSelect);
+ Byteswap (regs.portDPolarity);
+ Byteswap (regs.portDIntReqEn);
+ Byteswap (regs.portDKbdIntEn);
+ Byteswap (regs.portDIntEdge);
+
+ Byteswap (regs.portEDir);
+ Byteswap (regs.portEData);
+ Byteswap (regs.portEPullupEn);
+ Byteswap (regs.portESelect);
+
+ Byteswap (regs.portFDir);
+ Byteswap (regs.portFData);
+ Byteswap (regs.portFPullupdnEn);
+ Byteswap (regs.portFSelect);
+
+ Byteswap (regs.portGDir);
+ Byteswap (regs.portGData);
+ Byteswap (regs.portGPullupEn);
+ Byteswap (regs.portGSelect);
+
+ Byteswap (regs.portJDir);
+ Byteswap (regs.portJData);
+ Byteswap (regs.portJPullupEn);
+ Byteswap (regs.portJSelect);
+
+ Byteswap (regs.portKDir);
+ Byteswap (regs.portKData);
+ Byteswap (regs.portKPullupdnEn);
+ Byteswap (regs.portKSelect);
+
+ Byteswap (regs.portMDir);
+ Byteswap (regs.portMData);
+ Byteswap (regs.portMPullupdnEn);
+ Byteswap (regs.portMSelect);
+
+ Byteswap (regs.pwmControl);
+ Byteswap (regs.pwmSampleHi);
+ Byteswap (regs.pwmSampleLo);
+ Byteswap (regs.pwmPeriod);
+ Byteswap (regs.pwmCounter);
+
+ Byteswap (regs.pwm2Control);
+ Byteswap (regs.pwm2Period);
+ Byteswap (regs.pwm2Width);
+ Byteswap (regs.pwm2Counter);
+
+ Byteswap (regs.tmr1Control);
+ Byteswap (regs.tmr1Prescaler);
+ Byteswap (regs.tmr1Compare);
+ Byteswap (regs.tmr1Capture);
+ Byteswap (regs.tmr1Counter);
+ Byteswap (regs.tmr1Status);
+
+ Byteswap (regs.tmr2Control);
+ Byteswap (regs.tmr2Prescaler);
+ Byteswap (regs.tmr2Compare);
+ Byteswap (regs.tmr2Capture);
+ Byteswap (regs.tmr2Counter);
+ Byteswap (regs.tmr2Status);
+
+ Byteswap (regs.spiRxD);
+ Byteswap (regs.spiTxD);
+ Byteswap (regs.spiCont1);
+ Byteswap (regs.spiIntCS);
+ Byteswap (regs.spiTest);
+ Byteswap (regs.spiSpc);
+
+ Byteswap (regs.spiMasterData);
+ Byteswap (regs.spiMasterControl);
+
+ Byteswap (regs.uControl);
+ Byteswap (regs.uBaud);
+ Byteswap (regs.uReceive);
+ Byteswap (regs.uTransmit);
+ Byteswap (regs.uMisc);
+ Byteswap (regs.uNonIntPresc);
+
+ Byteswap (regs.u2Control);
+ Byteswap (regs.u2Baud);
+ Byteswap (regs.u2Receive);
+ Byteswap (regs.u2Transmit);
+ Byteswap (regs.u2Misc);
+ Byteswap (regs.u2NonIntPresc);
+ Byteswap (regs.u2FIFOHMark);
+
+ Byteswap (regs.lcdStartAddr);
+ Byteswap (regs.lcdPageWidth);
+ Byteswap (regs.lcdScreenWidth);
+ Byteswap (regs.lcdScreenHeight);
+ Byteswap (regs.lcdCursorXPos);
+ Byteswap (regs.lcdCursorYPos);
+ Byteswap (regs.lcdCursorWidthHeight);
+ Byteswap (regs.lcdBlinkControl);
+ Byteswap (regs.lcdPanelControl);
+ Byteswap (regs.lcdPolarity);
+ Byteswap (regs.lcdACDRate);
+ Byteswap (regs.lcdPixelClock);
+ Byteswap (regs.lcdClockControl);
+ Byteswap (regs.lcdRefreshRateAdj);
+ Byteswap (regs.lcdReserved1);
+ Byteswap (regs.lcdPanningOffset);
+ Byteswap (regs.lcdFrameRate);
+ Byteswap (regs.lcdGrayPalette);
+ Byteswap (regs.lcdReserved2);
+ Byteswap (regs.lcdContrastControlPWM);
+ Byteswap (regs.lcdRefreshModeControl);
+ Byteswap (regs.lcdDMAControl);
+
+ Byteswap (regs.rtcHourMinSec);
+ Byteswap (regs.rtcAlarm);
+ Byteswap (regs.rtcWatchDog);
+ Byteswap (regs.rtcControl);
+ Byteswap (regs.rtcIntStatus);
+ Byteswap (regs.rtcIntEnable);
+ Byteswap (regs.stopWatch);
+ Byteswap (regs.rtcDay);
+ Byteswap (regs.rtcDayAlarm);
+
+ Byteswap (regs.dramConfig);
+ Byteswap (regs.dramControl);
+ Byteswap (regs.sdramControl);
+ Byteswap (regs.sdramPwDn);
+
+ Byteswap (regs.emuAddrCompare);
+ Byteswap (regs.emuAddrMask);
+ Byteswap (regs.emuControlCompare);
+ Byteswap (regs.emuControlMask);
+ Byteswap (regs.emuControl);
+ Byteswap (regs.emuStatus);
+}
+
+
+
+
+void Byteswap (regstruct& p)
+{
+ Byteswap (p.regs[0]);
+ Byteswap (p.regs[1]);
+ Byteswap (p.regs[2]);
+ Byteswap (p.regs[3]);
+ Byteswap (p.regs[4]);
+ Byteswap (p.regs[5]);
+ Byteswap (p.regs[6]);
+ Byteswap (p.regs[7]);
+
+ Byteswap (p.regs[8]);
+ Byteswap (p.regs[9]);
+ Byteswap (p.regs[10]);
+ Byteswap (p.regs[11]);
+ Byteswap (p.regs[12]);
+ Byteswap (p.regs[13]);
+ Byteswap (p.regs[14]);
+ Byteswap (p.regs[15]);
+
+ Byteswap (p.usp);
+ Byteswap (p.isp);
+ Byteswap (p.msp);
+ Byteswap (p.sr);
+ Byteswap (p.t1);
+ Byteswap (p.t0);
+ Byteswap (p.s);
+ Byteswap (p.m);
+ Byteswap (p.stopped);
+ Byteswap (p.intmask);
+ Byteswap (p.pc);
+ Byteswap (p.pc_p);
+ Byteswap (p.pc_oldp);
+ Byteswap (p.pc_meta_oldp);
+ Byteswap (p.vbr);
+ Byteswap (p.sfc);
+ Byteswap (p.dfc);
+
+#if 0 // we don't support FP
+ Byteswap (fp.regs[0]);
+ Byteswap (fp.regs[1]);
+ Byteswap (fp.regs[2]);
+ Byteswap (fp.regs[3]);
+ Byteswap (fp.regs[4]);
+ Byteswap (fp.regs[5]);
+ Byteswap (fp.regs[6]);
+ Byteswap (fp.regs[7]);
+
+ Byteswap (p.fpcr);
+ Byteswap (p.fpsr);
+ Byteswap (p.fpiar);
+#endif
+
+ Byteswap (p.spcflags);
+ Byteswap (p.kick_mask);
+ Byteswap (p.prefetch);
+}
+
+
+void Byteswap (SED1375RegsType& p)
+{
+ Byteswap (p.productRevisionCode);
+ Byteswap (p.mode0);
+ Byteswap (p.mode1);
+ Byteswap (p.mode2);
+ Byteswap (p.horizontalPanelSize);
+ Byteswap (p.verticalPanelSizeLSB);
+ Byteswap (p.verticalPanelSizeMSB);
+ Byteswap (p.FPLineStartPosition);
+ Byteswap (p.horizontalNonDisplayPeriod);
+ Byteswap (p.FPFRAMEStartPosition);
+ Byteswap (p.verticalNonDisplayPeriod);
+ Byteswap (p.MODRate);
+ Byteswap (p.screen1StartAddressLSB);
+ Byteswap (p.screen1StartAddressMSB);
+ Byteswap (p.screen1StartAddressMSBit);
+ Byteswap (p.screen2StartAddressLSB);
+ Byteswap (p.screen2StartAddressMSB);
+ Byteswap (p.screen1StartAddressMSBit);
+ Byteswap (p.memoryAddressOffset);
+ Byteswap (p.screen1VerticalSizeLSB);
+ Byteswap (p.screen1VerticalSizeMSB);
+ Byteswap (p.lookUpTableAddress);
+ Byteswap (p.unused1);
+ Byteswap (p.lookUpTableData);
+ Byteswap (p.GPIOConfigurationControl);
+ Byteswap (p.GPIOStatusControl);
+ Byteswap (p.scratchPad);
+ Byteswap (p.portraitMode);
+ Byteswap (p.lineByteCountRegister);
+ Byteswap (p.unused2);
+ Byteswap (p.unused3);
+ Byteswap (p.unused4);
+}
+
+#endif // BYTESWAP
diff --git a/SrcShared/Byteswapping.h b/SrcShared/Byteswapping.h
new file mode 100644
index 0000000..51c1d0b
--- /dev/null
+++ b/SrcShared/Byteswapping.h
@@ -0,0 +1,175 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _BYTESWAPPING_H_
+#define _BYTESWAPPING_H_
+
+#if !defined (BYTESWAP)
+#error "Must define BYTESWAP"
+#endif
+
+
+struct regstruct;
+
+
+/*
+** --------------------------------------------------------------------------------
+** Byte swapping
+** --------------------------------------------------------------------------------
+*/
+
+#define BYTE_SWAP_16(n) ((((uint16) n) >> 8) | \
+ (((uint16) n) << 8))
+
+#define BYTE_SWAP_32(n) ( (((uint32) n) << 24) | \
+ ((((uint32) n) << 8) & 0x00FF0000) | \
+ ((((uint32) n) >> 8) & 0x0000FF00) | \
+ (((uint32) n) >> 24))
+
+#ifdef _MSC_VER
+#define BYTE_SWAP_64(n) ( (((uint64) n) << 56) | \
+ ((((uint64) n) << 40) & 0x00FF000000000000i64) | \
+ ((((uint64) n) << 24) & 0x0000FF0000000000i64) | \
+ ((((uint64) n) << 8) & 0x000000FF00000000i64) | \
+ ((((uint64) n) >> 8) & 0x00000000FF000000i64) | \
+ ((((uint64) n) >> 24) & 0x0000000000FF0000i64) | \
+ ((((uint64) n) >> 40) & 0x000000000000FF00i64) | \
+ (((uint64) n) >> 56))
+#else
+#define BYTE_SWAP_64(n) ( (((uint64) n) << 56) | \
+ ((((uint64) n) << 40) & 0x00FF000000000000LL) | \
+ ((((uint64) n) << 24) & 0x0000FF0000000000LL) | \
+ ((((uint64) n) << 8) & 0x000000FF00000000LL) | \
+ ((((uint64) n) >> 8) & 0x00000000FF000000LL) | \
+ ((((uint64) n) >> 24) & 0x0000000000FF0000LL) | \
+ ((((uint64) n) >> 40) & 0x000000000000FF00LL) | \
+ (((uint64) n) >> 56))
+#endif
+
+
+inline void Byteswap(bool&)
+{
+}
+
+inline void Byteswap(char&)
+{
+}
+
+inline void Byteswap(signed char&)
+{
+}
+
+inline void Byteswap(unsigned char&)
+{
+}
+
+inline void Byteswap(short& v)
+{
+ v = (short) BYTE_SWAP_16(v);
+}
+
+inline void Byteswap(unsigned short& v)
+{
+ v = (unsigned short) BYTE_SWAP_16(v);
+}
+
+inline void Byteswap(int& v)
+{
+ if (sizeof(int) == 4)
+ v = (int) BYTE_SWAP_32(v);
+
+ else if (sizeof(int) == 2)
+ v = (int) BYTE_SWAP_16(v);
+}
+
+inline void Byteswap(unsigned int& v)
+{
+ if (sizeof(unsigned int) == 4)
+ v = (unsigned int) BYTE_SWAP_32(v);
+
+ else if (sizeof(unsigned int) == 2)
+ v = (unsigned int) BYTE_SWAP_16(v);
+}
+
+inline void Byteswap(long& v)
+{
+ v = (long) BYTE_SWAP_32(v);
+}
+
+inline void Byteswap(unsigned long& v)
+{
+ v = (unsigned long) BYTE_SWAP_32(v);
+}
+
+inline void Byteswap(int64& v)
+{
+ v = (int64) BYTE_SWAP_64(v);
+}
+
+inline void Byteswap(uint64& v)
+{
+ v = (uint64) BYTE_SWAP_64(v);
+}
+
+template <class T>
+inline void Byteswap(T*& v)
+{
+ Byteswap ((uint32&) v);
+}
+
+void Byteswap (HwrM68328Type&);
+void Byteswap (HwrM68EZ328Type&);
+void Byteswap (HwrM68VZ328Type&);
+void Byteswap (regstruct& r);
+void Byteswap (SED1375RegsType& p);
+
+#if BYTESWAP
+
+ template <class T>
+ inline void Canonical(T& v)
+ {
+ Byteswap (v);
+ }
+
+#else
+
+ template <class T>
+ inline void Canonical(T&)
+ {
+ }
+
+#endif
+
+
+#if WORDSWAP_MEMORY
+
+ inline void ByteswapWords (void* start, unsigned long length)
+ {
+ for (unsigned long ii = 0; ii < length / 2; ++ii)
+ {
+ unsigned short* p = ((unsigned short*) start) + ii;
+ unsigned char* bp = (unsigned char*) p;
+ *p = (((unsigned short) *bp) << 8) | (unsigned short) (*(bp + 1));
+ }
+ }
+
+#else
+
+ inline void ByteswapWords (void*, unsigned long)
+ {
+ }
+
+#endif // WORDSWAP_MEMORY
+
+#endif /* _BYTESWAPPING_H_ */
+
diff --git a/SrcShared/CGremlins.cpp b/SrcShared/CGremlins.cpp
new file mode 100644
index 0000000..b40bd01
--- /dev/null
+++ b/SrcShared/CGremlins.cpp
@@ -0,0 +1,2336 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+
+#include <stdio.h> // needed for sprintf.
+#include <stdlib.h> // needed for rand and srand
+#include <string.h> // needed for strcpy and friends
+
+
+#ifdef forSimulator
+
+#define PILOT_PRECOMPILED_HEADERS_OFF
+
+// Palm Includes
+#include <BuildDefines.h>
+#ifdef HAS_LOCAL_BUILD_DEFAULTS
+#include "LocalBuildDefaults.h"
+#endif
+#include <PalmTypes.h>
+
+#include <Chars.h>
+#include <DebugMgr.h>
+#include <ErrorBase.h>
+#include <FeatureMgr.h>
+#include <Field.h>
+#include <Form.h>
+#include <TextMgr.h>
+#include <PalmLocale.h>
+
+#include "CGremlinsStubs.h"
+#include "CGremlins.h"
+#include "Hardware.h"
+#include <EmuStubs.h>
+
+#define NON_PORTABLE
+#include "SystemPrv.h"
+#include "DataPrv.h"
+#include "SysEvtPrv.h"
+#include <SystemPkt.h>
+
+#include "ShellCmd.h"
+
+#else // !forSimulator
+
+#include "EmBankRegs.h" // RegsBank
+#include "EmEventPlayback.h" // RecordPenEvent, etc.
+#include "EmMemory.h" // EmMemPut16, EmMemPut32
+#include "EmPalmStructs.h" // EmAliasPenBtnInfoType
+#include "EmPatchState.h" // GetCurrentAppInfo
+#include "EmSession.h" // gSession, ScheduleAutoSaveState
+#include "ErrorHandling.h" // Errors::ThrowIfPalmError
+#include "Hordes.h" // Hordes::IsOn, TurnOn
+#include "Logging.h"
+#include "PreferenceMgr.h" // Preference<GremlinInfo>
+#include "ROMStubs.h" // FtrGet, TxtGetNextChar, TxtCharBounds, TxtByteAddr, FrmGetActiveForm...
+#include "SessionFile.h" // SessionFile
+#include "Strings.r.h" // kStr_ values
+#include "EmLowMem.h" // EmLowMem_SetGlobal for setting battery level
+
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Private function declarations
+// (actually just some operator override declarations we'll need)
+
+static EmStream& operator >> (EmStream&, DatabaseInfo&);
+static EmStream& operator << (EmStream&, const DatabaseInfo&);
+
+static EmStream& operator >> (EmStream&, GremlinInfo&);
+static EmStream& operator << (EmStream&, const GremlinInfo&);
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Private globals
+
+static int gIntlMgrExists = -1;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Private functions
+
+static Bool IntlMgrExists (void)
+{
+ if (gIntlMgrExists < 0)
+ {
+ // Note that we need to check by calling the feature manager rather than
+ // checking to see if the trap is implemented. sysTrapIntlDispatch is
+ // sysTrapPsrInit on 1.0 systems and sysUnused2 on intermediate systems.
+ // That means that the trap IS implemented, but just not the one we want.
+
+ UInt32 data;
+ Err err = FtrGet (sysFtrCreator, sysFtrNumIntlMgr, &data);
+
+ gIntlMgrExists = !err && (data & intlMgrExists) != 0;
+ }
+
+ return gIntlMgrExists != 0;
+}
+
+static UInt16 _TxtGetNextChar (const Char *inText, UInt32 inOffset, WChar *outChar)
+{
+ if (IntlMgrExists ())
+ {
+ return TxtGetNextChar (inText, inOffset, outChar);
+ }
+
+ if (outChar)
+ *outChar = (UInt8) inText[inOffset];
+
+ return sizeof (Char);
+}
+
+static WChar _TxtCharBounds (const Char *inText, UInt32 inOffset, UInt32 *outStart, UInt32 *outEnd)
+{
+ if (IntlMgrExists ())
+ {
+ return TxtCharBounds (inText, inOffset, outStart, outEnd);
+ }
+
+ if (outStart)
+ *outStart = inOffset;
+
+ if (outEnd)
+ *outEnd = inOffset + 1;
+
+ return inText[inOffset];
+}
+
+static UInt8 _TxtByteAttr (UInt8 inByte)
+{
+ if (IntlMgrExists ())
+ {
+ return TxtByteAttr (inByte);
+ }
+
+ return byteAttrSingle;
+}
+
+#define TxtGetNextChar _TxtGetNextChar
+#define TxtCharBounds _TxtCharBounds
+#define TxtByteAttr _TxtByteAttr
+
+#include "CGremlins.h"
+#include "CGremlinsStubs.h"
+
+#define PRINTF if (!LogGremlins ()) ; else LogAppendMsg
+
+
+// Use our own versions of rand() and srand() so that we generate the
+// same numbers on both platforms.
+
+#undef RAND_MAX
+#define RAND_MAX 0x7fff
+
+#define rand Gremlin_rand
+#define srand Gremlin_srand
+
+unsigned long int gGremlinNext = 1;
+
+static int rand(void)
+{
+// gGremlinNext = gGremlinNext * 1103515245 + 12345; // MSL numbers
+
+ gGremlinNext = gGremlinNext * 214013L + 2531011L; // VC++ numbers
+ PRINTF ("--- gGremlinNext == 0x%08X", (long) gGremlinNext);
+
+ return ((gGremlinNext >> 16) & 0x7FFF);
+}
+
+static void srand(unsigned int seed)
+{
+ gGremlinNext = seed;
+}
+
+
+#endif
+
+
+//#define randN(N) ((N) ? rand() / (RAND_MAX / (N)) : (0))
+#define randN(N) ((int) (((long) rand() * (N)) / ((long) RAND_MAX + 1)))
+#define randPercent (randN(100))
+
+#ifndef forSimulator
+#undef randN
+inline int randN (long N)
+{
+ int result = ((int) (((long) rand() * (N)) / ((long) RAND_MAX + 1)));
+ PRINTF ("--- randN(%ld) == 0x%08X", N, (long) result);
+ return result;
+}
+#endif
+
+#define PEN_MOVE_CHANCE 50 // 50% move pen else pen up
+#define PEN_BIG_MOVE_CHANCE 5 // 5% move pen really far
+
+#define KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE 10
+#define KEY_DOWN_EVENT_WITH_FOCUS_CHANCE 40
+#define PEN_DOWN_EVENT_CHANCE (70 + KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE)
+#define MENU_EVENT_CHANCE (PEN_DOWN_EVENT_CHANCE + 4)
+#define FIND_EVENT_CHANCE (MENU_EVENT_CHANCE + 2)
+#define KEYBOARD_EVENT_CHANCE (FIND_EVENT_CHANCE + 1)
+#define LOW_BATTERY_EVENT_CHANCE (KEYBOARD_EVENT_CHANCE + 2)
+#define APP_SWITCH_EVENT_CHANCE (LOW_BATTERY_EVENT_CHANCE + 4)
+// #define POWER_OFF_CHANCE (APP_SWITCH_EVENT_CHANCE + 1)
+
+#define LAUNCHER_EVENT_CHANCE 0 // percent of APP_SWITCH_EVENT_CHANCE
+
+
+#define commandKeyMask 0x0008
+
+
+#define TYPE_QUOTE_CHANCE 10
+
+#define MAX_SEED_VALUE 1000 // Max. # of seed values allowed.
+#define INITIAL_SEED 1
+
+#define LETTER_PROB 60
+
+// Chars less often than a letter
+#define SYMBOL_PROB (LETTER_PROB / 10)
+#define EXT_LTTR_PROB (LETTER_PROB / 3)
+#define EXTENDED_PROB (LETTER_PROB / 5)
+#define CONTROL_PROB (LETTER_PROB / 2)
+#define MENU_PROB (LETTER_PROB / 10)
+#define KBRD_PROB 1 // The formula results in 0
+ // ((LETTER_PROB / 30) / 3) // three chars to activate keyboard
+#define NXTFLD_PROB (LETTER_PROB / 10)
+#define SEND_DATA_PROB (LETTER_PROB / 60)
+
+// Chars more often than a letter
+#define SPACE_PROB (LETTER_PROB * 5)
+#define TAB_PROB (LETTER_PROB * 2)
+#define BACKSPACE_PROB (LETTER_PROB * 3)
+#define RETURN_PROB ((LETTER_PROB * 10) * 1) // extra exercise
+
+
+//Global variables
+Gremlins* TheGremlinsP; // Pointer to the Gremlins class.
+long IdleTimeCheck; // Tick count for the next idle query
+
+// Array of probabilities of a key being pressed for gremlin mode.
+#define NUM_OF_KEYS 0x110
+static const int chanceForKey[NUM_OF_KEYS] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0x07
+ BACKSPACE_PROB, TAB_PROB, RETURN_PROB, CONTROL_PROB, CONTROL_PROB, 0, 0, 0, // 0x08 - 0x0F
+ 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x17
+ 0, 0, 0, 0, CONTROL_PROB, CONTROL_PROB, CONTROL_PROB, CONTROL_PROB, // 0x18 - 0x1F
+
+ // Symbols
+ SPACE_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x20 - 0x23
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x24 - 0x27
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x28 - 0x2B
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x2C - 0x2F
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x30 - 0x33
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x34 - 0x37
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x38 - 0x3B
+ SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, SYMBOL_PROB, // 0x3C - 0x3F
+
+ // Uppercase
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x40 - 0x43
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x44 - 0x47
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x48 - 0x4B
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x4C - 0x4F
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x50 - 0x53
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x54 - 0x57
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x58 - 0x5B
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x5C - 0x5F
+
+ // Lowercase
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x60 - 0x63
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x64 - 0x67
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x68 - 0x6B
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x6C - 0x6F
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x70 - 0x73
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x74 - 0x77
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x78 - 0x8B
+ LETTER_PROB, LETTER_PROB, LETTER_PROB, LETTER_PROB, // 0x7C - 0x7F
+
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x80 - 0x83
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x84 - 0x87
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x88 - 0x8B
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x8C - 0x8F
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x90 - 0x93
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x94 - 0x97
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x98 - 0x9B
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0x9C - 0x9F
+
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA0 - 0xA3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA4 - 0xA7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xA8 - 0xAB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xAC - 0xAF
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB0 - 0xB3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB4 - 0xB7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xB8 - 0xBB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xBC - 0xBF
+
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC0 - 0xC3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC4 - 0xC7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xC8 - 0xCB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xCC - 0xCF
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD0 - 0xD3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD4 - 0xD7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xD8 - 0xDB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xDC - 0xDF
+
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE0 - 0xE3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE4 - 0xE7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xE8 - 0xEB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xEC - 0xEF
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF0 - 0xF3
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF4 - 0xF7
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xF8 - 0xFB
+ EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, EXTENDED_PROB, // 0xFC - 0xFF
+
+ // Virtual events
+ // DOLATER kwk - Why not generate keyboardAlphaChr (0x110) & keyboardNumericChr (0x111)?
+ 0, 0, 0, NXTFLD_PROB, 0, MENU_PROB, CONTROL_PROB, 0, // 0x100 - 0x107
+ CONTROL_PROB, KBRD_PROB, CONTROL_PROB, 0, NXTFLD_PROB, 0, 0, 0, // 0x108 - 0x10f
+
+};
+
+#define NUM_OF_QUOTES 18
+
+// Shakespearean quotes used by Gremlins for English text
+static const char * kAsciiQuotes[NUM_OF_QUOTES] = {
+ "Out out damn spot!",
+
+ "Et tu, Brute?",
+
+ "When in disgrace with fortune and mens' eyes "
+ "I all alone beweep my outcast state. "
+ "And trouble deaf heaven with my bootless cries and "
+ "look upon myself and curse my fate. "
+ "Wishing me like to one more rich in hope, "
+ "featured like him, like him with friends possest, "
+ "desiring this man's art and that man's scope, "
+ "with what I most enjoy contented least;"
+ "\n"
+ "Yet in these thoughts myself almost despising- "
+ "haply I think on thee: and then my state, "
+ "like to the lark at break of day arising "
+ "from sullen earth, sings hymns at Heaven's gate; "
+ "for thy sweet love rememb'red such wealth brings "
+ "that then I scorn to change my state with kings.",
+
+ "I think my wife is honest, and think she is not; "
+ "I think that thou art just, and think thou art not.",
+
+ "O that this too too sullied flesh would melt, thaw, "
+ "and resolve itself into a dew, "
+ "or that the Everlasting had not fixed "
+ "His canon 'gainst self-slaughter.",
+
+ "Come, you spirits that tend on mortal thoughts, unsex me here, "
+ "and fill me from the crown to the toe top-full "
+ "of direst cruelty.",
+
+ "I do not think but Desdemona's honest.",
+
+ "That I did love the Moor to live with him",
+
+ "What a piece of work is a man",
+
+ "Fair is foul, and foul is fair.",
+
+ "All hail, Macbeth, that shalt be King hereafter!",
+
+ "What's Montague?",
+
+ "To a nunnery, go, and quickly too.",
+
+ "I'll have some proof.",
+
+ "Now are we well resolved, and by God's help and yours, "
+ "the noble sinews of our power, France being ours, "
+ "we'll bend it to our awe or break it all to pieces.",
+
+ "Tennis balls, my liege.",
+
+ "De Sin: le col de Nick, le menton de Sin.",
+
+ "But swords I smile at, weapons laugh to scorn, "
+ "brandished by man that's of a woman born."
+
+};
+
+static const char * kShiftJISQuotes[NUM_OF_QUOTES] = {
+ "l‚ÍA‚©‚‚ÄX‚Ì_‚ðŽE‚µ‚½",
+
+ "‚à‚Ì‚Ì‚¯•P",
+
+ "l–Ê‚Æb‚Ìg‘ÌAŽ÷–Ø‚ÌŠp‚ðŽ‚ÂX‚Ì_EƒVƒV_‚ð"
+ "l‚͉½ŒÌŽE‚³‚˂΂Ȃç‚È‚©‚Á‚½‚Ì‚©|"
+ "‚±‚ÌŽž‘ãAlŠÔ‚ª‚Ó‚¦A‘½‚­‚ÌŒ´¶—Ñ‚ª‘ñ‚©‚ꂽ‚Æ‚Í‚¢‚¦A"
+ "‚Ü‚¾l‚ðŠñ‚¹‚‚¯‚Ê‘¾ŒÃ‚ÌX‚ª‚ ‚¿‚±‚¿‚ÉŽc‚Á‚Ä‚¢‚½"
+ "\n"
+ "‚»‚ꂼ‚ê‚ÌX‚ÍA’–‚âŽRŒ¢‚È‚Ç"
+ "‹‘å‚ÅŒ«‚©‚Á‚½b‚½‚¿‚ª•KŽ€‚É‚È‚Á‚ÄŽç‚Á‚Ä‚¢‚½"
+ "‚»‚µ‚ÄA¹ˆæ‚ðN‚·lŠÔ’B‚ðP‚¢"
+ "r‚Ô‚é_X‚Æ‹°‚ê‚ç‚ê‚Ä‚¢‚½"
+ "‚»‚Ìb’B‚ð]‚¦‚Ä‚¢‚½‚Ì‚ªAƒVƒV_‚Å‚ ‚é"
+ "r‚Ô‚é_X‚ðÅ‚àŒƒ‚µ‚­í‚Á‚Ä‚¢‚½‚Ì‚Í"
+ "ƒ^ƒ^ƒ‰ŽÒ‚ƌĂ΂ê‚黓SW’c‚¾‚Á‚½",
+
+ "—‚Ìg‚Ń^ƒ^ƒ‰W’c‚𗦂¢‚éƒGƒ{ƒVŒä‘O"
+ "”Þ—‚͌ȂªM”O‚ÅAX‚ðØ‚è‘ñ‚¢‚Ä‚¢‚½",
+
+ "‚»‚Ì”z‰º‚ÅAŒä‘O‚ðŒh‚¢•ç‚¤AƒSƒ“ƒU‚É‚¨ƒgƒL‚Æb˜Z"
+ "ƒVƒV_‚ð‚˂炤³‘Ì•s–¾‚Ì–VŽåEƒWƒR–V"
+ "–k‚Ì’n‚̉ʂẲB‚ê—¢‚ÉZ‚Þ˜V›Þ—EƒqƒC‚³‚Ü"
+ "‰³Ž–ŽåAƒiƒS‚Ì_Aƒ‚ƒ‚È‚ÇX‚ðŽç‚é_b‚½‚¿",
+
+ "‚»‚ê‚ÉX‚̸—ìEƒRƒ_ƒ}‚½‚¿c­—ƒTƒ“‚ÍlŠÔ‚Ì"
+ "Žq‚Å‚ ‚è‚È‚ª‚çŽRŒ¢ƒ‚ƒ‚Ɉç‚Ä‚ç‚ꂽu‚à‚Ì‚Ì‚¯•Pv",
+
+ "‚¾‚Á‚½ƒTƒ“‚ÍAX‚ðN‚·lŠÔ‚ðŒƒ‚µ‚­‘ž",
+
+ "‚ñ‚Å‚¢‚½‚»‚µ‚ÄAlŠÔ‚Ær‚Ô‚é_X‚ÌÅŒã",
+
+ "‚̑匈í‚ÉŠª‚«ž‚Ü‚ê‚é­”N",
+
+ "ƒAƒVƒ^ƒJ”Þ‚ÍAŽ€‚ÌŽô‚¢‚ð",
+
+ "‚©‚¯‚ç‚ꂽ‚ª‚䂦‚Éâq‚ê‚ðò‚ß‚é•û–@‚ð’T‚µ‚ÉA",
+
+ "—·‚Éo‚½­”N‚¾‚Á‚½",
+
+ "­”N‚Æ­—‚ÍŽSŒ€‚Ì’†‚Åo‰ï‚¢A",
+
+ "ŽŸ‘æ‚ÉS‚ð’ʂ킹",
+
+ "‚Ä‚ä‚­‚Ó‚½‚肪‘žˆ«‚ÆŽEC‚̉ʂĂɌ©‚¢‚¾‚µ‚½"
+ "Šó–]‚Ƃ͉½‚¾‚Á‚½‚Ì‚©­”N‚Æ­—‚̈¤"
+ "‚ð‰¡Ž…‚ɃVƒV_‚ð‚ß‚®‚élŠÔ‚Æb‚½‚¿",
+
+ "‚Ìí‚¢‚ðcŽ…‚É",
+
+ "”gàp–œä‚̈ê‘å–Ž–Ž‚ªA“WŠJ‚³‚ê‚Ä‚¢‚­c",
+
+ "Œ´ìE‹r–{@@F‹{è@x»@ì@@@@FŽ‰Æꎈê˜YE¬“c@–L»ì‘ŽwŠö@@"
+ "F“¿ŠÔN‰õƒvƒƒfƒ…[ƒT[F—é–Ø•q•v"
+};
+
+static const char * kBig5Quotes[NUM_OF_QUOTES] = {
+ "¦¹¶}¨÷²Ä¤@¦^¤]¡C§@",
+
+ "ªÌ¦Û¶³¡G¦]´¿",
+
+ "¾ä¹L¤@µf¹Ú¤Û¤§«á¡A¬G±N¯u¨ÆÁô¥h¡A¦Ó­É\"³qÆF\""
+ "¤§»¡¡A¼¶¦¹¤@®Ñ¤]¡C¬G¤ê\"ºÂ¤hÁô\"¤ª¤ª¡C"
+ "¦ý®Ñ¤¤©Ò°O¦ó¨Æ¦ó¤H¡H¦Û¤S¶³¡G¤µ­·¹Ð¸L¸L¡A¤@¨ÆµL¦¨¡A",
+
+ "©¿©À¤Î·í¤é©Ò¦³¤§¤k¤l¡A¤@¤@²Ó¦Ò¸û¥h¡A"
+ "ı¨ä¦æ¤î¨£ÃÑ¡A¬Ò¥X©ó§Ú¤§¤W¡C¦ó§Ú°ó°óŽ¬Ü¡A"
+ "¸Û¤£­Y©¼¸È³¦«v¡H¹ê·\\«h¦³¾l¡A®¬¤SµL¯q¤§¤jµL¥i¦p¦ó¤§"
+ "¤é¤]¡I·í¦¹¡A«h¦Û±ý±N¤w©¹©Ò¿à¤Ñ®¦¯ª¼w¡AÀA¦çÐK¤§"
+ "®É¡AÜ®¥ÌÅäªÎ¤§¤é¡A­I¤÷¥S±Ð¨|¤§®¦¡A­t®v "
+ "\n"
+ "¤Í³W½Í¤§¼w¡A¥H¦Ü¤µ¤é¤@§ÞµL¦¨¡A¥b¥Í¼ã­Ë¤§¸o¡A½s "
+ "­z¤@¶°¡A¥H§i¤Ñ¤U¤H¡G§Ú¤§¸o©T¤£§K¡AµM»Ó»Õ¤¤"
+ "¥»¦Û¾ú¾ú¦³¤H¡A¸U¤£¥i¦]§Ú¤§¤£¨v¡A¦ÛÅ@¤vµu "
+ "¡A¤@¨Ö¨Ï¨äª{·À¤]¡CÁö¤µ¤é¤§­TÝܽ´¼ø¡A¥Ë_÷§É¡A¨ä "
+ "±á¤i­·ÅS¡A¶¥¬h®xªá¡A¥ç¥¼¦³§«§Ú¤§ÃÌÃhµ§¾¥ªÌ¡CÁö§Ú "
+ "¥¼¾Ç¡A¤Uµ§µL¤å¡A¤S¦ó§«¥Î°²»y§ø¨¥¡A¼Åºt¥X¤@¬q¬G¨Æ"
+ "¨Ó¡A¥ç¥i¨Ï»Ó»Õ¬L¶Ç¡A½Æ¥i®®¥@¤§¥Ø¡A¯}¤H·T´e¡A¤£¥ç "
+ "©y¥G¡H¬G¤ê\"¸ë«B§ø\"¤ª¤ª¡C¦¹¦^¤¤¤Z¥Î\"¹Ú\"¥Î\"¤Û\"",
+
+ "µ¥¦r¡A¬O´£¿ô¾\\ªÌ²´¥Ø¡A¥ç¬O¦¹®Ñ¥ß·N¥»¦®¡C¦C¦ì¬Ý©x¡G§A"
+ "¹D¦¹®Ñ±q¦ó¦Ó¨Ó¡H»¡°_®Ú¥ÑÁöªñ¯î "
+ "­ð¡A²Ó«ö«h²`¦³½ì¨ý¡C«Ý¦b¤U±N¦¹¨Ó¾úª`©ú"
+ "­ì¨Ó¤k´E¤ó·Ò¥Û¸É¤Ñ¤§®É¡A©ó¤j¯î¤s",
+
+ "µL½]±V½m¦¨°ª¸g¤Q¤G¤V¡A¤è¸g¤G¤Q¥|¤V¹x¥Û¤T¸U¤»¤d¤­¦Ê¹s¤@¶ô¡C´E¬Ó"
+ "¤ó¥u¥Î¤F¤T¸U¤»¤d¤­¦Ê¶ô¡A¥u³æ³æ³Ñ¤F¤@¶ô¥¼¥Î¡A«K"
+ "±ó¦b¦¹¤s«C®G®p¤U¡C",
+
+ "½Öª¾¦¹¥Û¦Û¸g·Ò¤§«á¡AÆF©Ê¤w³q¡A¦]¨£_¥Û",
+
+ "­Ñ±o¸É¤Ñ¡A¿W¦Û¤vµL§÷¤£³ô¤J¿ï¡A¹E¦Û«è¦Û¼Û",
+
+ "¡A¤é©]´d¸¹ºF·\\¡C¤@¤é¡A¥¿·í¶Ø",
+
+ "±¥¤§»Ú¡A«X¨£¤@¹¬¤@¹D»·»·¦Ó¨Ó¡A",
+
+ "¥Í±o°©®æ¤£¤Z¡AÂׯ«­~²§¡A»¡»¡¯º¯º¨Ó¦Ü®p¤U¡A§¤¤_¥Û",
+
+ "Ãä°ª½Í§Ö½×¡C¥ý¬O",
+
+ "»¡¨Ç¶³¤sÃú®ü¯«¥P¥È¤Û¤§¨Æ¡A«á«K»¡¨ì",
+
+ "¬õ¹Ð¤¤ºaµØ´I¶Q¡C¦¹¥Û",
+
+ "Å¥¤F¡A¤£Ä±¥´°Ê¤Z¤ß¡A¤]·Q­n¨ì¤H¶¡¥h¨É¤@¨É³oºaµØ´I¶Q¡A¦ý"
+ "¦Û«ë²ÊÄø¡A¤£±o¤w¡A«K¤f¦R¤H¨¥¡A¦V¨º¹¬¹D»¡¹D¡G¤j®v¡A"
+ "§Ì¤lÄøª«¡A¤£¯à¨£Â§¤F¡C¾A»D¤G¦ì½Í¨º¤H¥@¶¡ºaÄ£ÁcµØ¡A",
+
+ "¤ß¤Á¼}¤§¡C§Ì¤l½èÁö²ÊÄø",
+
+ "¡A©Ê«oµy³q¡Aªp¨£¤G®v¥P§Î¹DÅé¡A©w«D¤Z«~¡A¥²",
+
+ "¦³¸É¤ÑÀÙ¥@¤§§÷¡A§Qª«ÀÙ¤H¤§¼w¡C¦p»Xµo¤@ÂI·O¤ß¡A"
+ "Äâ±a§Ì¤l±o¤J¬õ¹Ð¡A¦b¨º´I¶Q³õ¤¤¡A·Å¬X¶m¨½"
+};
+
+static const char * kGB2312Quotes[NUM_OF_QUOTES] = {
+ "´Ë¿ª¾íµÚÒ»»ØÒ²¡£×÷",
+
+ "Õß×ÔÔÆ£ºÒòÔø",
+
+ "Àú¹ýÒ»·¬ÃλÃÖ®ºó£¬¹Ê½«ÕæÊÂÒþÈ¥£¬¶ø½è¡°Í¨Á顱"
+ "֮˵£¬×«´ËÒ»ÊéÒ²¡£¹ÊÔ»¡°ÕçÊ¿Òþ¡±ÔÆÔÆ¡£"
+ "µ«ÊéÖÐËù¼ÇºÎʺÎÈË£¿×ÔÓÖÔÆ£º½ñ·ç³¾ÂµÂµ£¬Ò»ÊÂÎ޳ɣ¬",
+
+ "ºöÄî¼°µ±ÈÕËùÓÐ֮Ů×Ó£¬Ò»Ò»Ï¸¿¼½ÏÈ¥£¬"
+ "¾õÆäÐÐÖ¹¼ûʶ£¬½Ô³öÓÚÎÒÖ®ÉÏ¡£ºÎÎÒÌÃÌÃÐëü£¬"
+ "³Ï²»Èô±ËȹîÎÔÕ£¿ÊµÀ¢ÔòÓÐÓ࣬»ÚÓÖÎÞÒæÖ®´óÎÞ¿ÉÈçºÎÖ®"
+ "ÈÕÒ²£¡µ±´Ë£¬Ôò×ÔÓû½«ÒÑÍùËùÀµÌì¶÷×æµÂ£¬½õÒÂæýÖ®"
+ "ʱ£¬âÀ¸Ê÷зÊÖ®ÈÕ£¬±³¸¸ÐÖ½ÌÓýÖ®¶÷£¬¸ºÊ¦"
+ "\n"
+ "Óѹæ̸֮µÂ£¬ÒÔÖÁ½ñÈÕÒ»¼¼Î޳ɣ¬°ëÉúÁʵ¹Ö®×±à"
+ "ÊöÒ»¼¯£¬ÒÔ¸æÌìÏÂÈË£ºÎÒÖ®×ï¹Ì²»Ã⣬Ȼ¹ë¸óÖÐ"
+ "±¾×ÔÀúÀúÓÐÈË£¬Íò²»¿ÉÒòÎÒÖ®²»Ð¤£¬×Ô»¤¼º¶Ì"
+ "£¬Ò»²¢Ê¹ÆäãýÃðÒ²¡£Ëä½ñÈÕ֮é´ªÅî뻣¬ÍßÔîÉþ´²£¬Æä"
+ "³¿Ï¦·ç¶£¬½×ÁøÍ¥»¨£¬ÒàδÓзÁÎÒÖ®½ó»³±ÊÄ«Õß¡£ËäÎÒ"
+ "δѧ£¬Ï±ÊÎÞÎÄ£¬ÓֺηÁÓüÙÓï´åÑÔ£¬·óÑݳöÒ»¶Î¹ÊÊÂ"
+ "À´£¬Òà¿Éʹ¹ë¸óÕÑ´«£¬¸´¿ÉÔÃÊÀ֮Ŀ£¬ÆÆÈ˳îÃÆ£¬²»Òà"
+ "Ò˺õ£¿¹ÊÔ»¡°¼ÖÓê´å¡±ÔÆÔÆ¡£´Ë»ØÖз²Óá°ÃΡ±Ó᰻á±",
+
+ "µÈ×Ö£¬ÊÇÌáÐÑÔÄÕßÑÛÄ¿£¬ÒàÊÇ´ËÊéÁ¢Òâ±¾Ö¼¡£ÁÐλ¿´¹Ù£ºÄã"
+ "µÀ´ËÊé´ÓºÎ¶øÀ´£¿ËµÆð¸ùÓÉËä½ü»Ä"
+ "ÌÆ£¬Ï¸°´ÔòÉîÓÐȤζ¡£´ýÔÚϽ«´ËÀ´Àú×¢Ã÷"
+ "Ô­À´Å®æ´ÊÏÁ¶Ê¯²¹Ìì֮ʱ£¬ÓÚ´ó»Äɽ",
+
+ "ÎÞ»üÑÂÁ·³É¸ß¾­Ê®¶þÕÉ£¬·½¾­¶þÊ®ËÄÕÉÍçʯÈýÍòÁùǧÎå°ÙÁãÒ»¿é¡£æ´»Ê"
+ "ÊÏÖ»ÓÃÁËÈýÍòÁùǧÎå°Ù¿é£¬Ö»µ¥µ¥Ê£ÁËÒ»¿éδÓ㬱ã"
+ "ÆúÔÚ´ËɽÇ๡·åÏ¡£",
+
+ "Ë­Öª´Ëʯ×Ô¾­Á¶Ö®ºó£¬ÁéÐÔÒÑͨ£¬Òò¼ûÖÚʯ",
+
+ "¾ãµÃ²¹Ì죬¶À×Ô¼ºÎ޲IJ»¿°ÈëÑ¡£¬Ëì×ÔÔ¹×Ô̾",
+
+ "£¬ÈÕÒ¹±¯ºÅ²ÑÀ¢¡£Ò»ÈÕ£¬Õýµ±àµ",
+
+ "µ¿Ö®¼Ê£¬¶í¼ûһɮһµÀÔ¶Ô¶¶øÀ´£¬",
+
+ "ÉúµÃ¹Ç¸ñ²»·²£¬·áÉñåÄÒ죬˵˵ЦЦÀ´ÖÁ·åÏ£¬×øÓÚʯ",
+
+ "±ß¸ß̸¿ìÂÛ¡£ÏÈÊÇ",
+
+ "˵ЩÔÆɽÎíº£ÉñÏÉÐþ»Ã֮ʣ¬ºó±ã˵µ½",
+
+ "ºì³¾ÖÐÈÙ»ª¸»¹ó¡£´Ëʯ",
+
+ "ÌýÁË£¬²»¾õ´ò¶¯·²ÐÄ£¬Ò²ÏëÒªµ½È˼äÈ¥ÏíÒ»ÏíÕâÈÙ»ª¸»¹ó£¬µ«"
+ "×ÔºÞ´Ö´À£¬²»µÃÒÑ£¬±ã¿ÚÍÂÈËÑÔ£¬ÏòÄÇÉ®µÀ˵µÀ£º´óʦ£¬"
+ "µÜ×Ó´ÀÎ²»ÄܼûÀñÁË¡£ÊÊÎŶþλ̸ÄÇÈËÊÀ¼äÈÙÒ«·±»ª£¬",
+
+ "ÐÄÇÐĽ֮¡£µÜ×ÓÖÊËä´Ö´À",
+
+ "£¬ÐÔÈ´ÉÔͨ£¬¿ö¼û¶þʦÏÉÐεÀÌ壬¶¨·Ç·²Æ·£¬±Ø",
+
+ "Óв¹Ìì¼ÃÊÀÖ®²Ä£¬ÀûÎï¼ÃÈËÖ®µÂ¡£ÈçÃÉ·¢Ò»µã´ÈÐÄ£¬"
+ "Я´øµÜ×ÓµÃÈëºì³¾£¬ÔÚÄǸ»¹ó³¡ÖУ¬ÎÂÈáÏçÀï"
+};
+
+typedef struct
+{
+ UInt16 charEncoding;
+ const char** strings;
+} QuotesInfoType;
+
+static const QuotesInfoType kQuotesInfo[] =
+{
+ { charEncodingPalmSJIS, kShiftJISQuotes },
+
+ // All of the possible Traditional Chinese encodings.
+ { charEncodingBig5, kBig5Quotes },
+ { charEncodingBig5_HKSCS, kBig5Quotes },
+ { charEncodingBig5Plus, kBig5Quotes },
+ { charEncodingPalmBig5, kBig5Quotes },
+
+ // All of the possible Simplified Chinese encodings.
+ { charEncodingGB2312, kGB2312Quotes },
+ { charEncodingGBK, kGB2312Quotes },
+ { charEncodingPalmGB, kGB2312Quotes }
+};
+
+/***********************************************************************
+ *
+ * FUNCTION: GetFocusObject
+ *
+ * DESCRIPTION: Return whether the current form has the focus.
+ *
+ * CALLED BY: here
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: TRUE if the form has a focus set and FALSE if not
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * roger 8/25/95 Initial Revision
+ * roger 11/27/95 Ignored not editable fields.
+ *
+ ***********************************************************************/
+static FieldPtr GetFocusObject()
+{
+ FormPtr frm;
+ UInt16 focusObj;
+ FieldPtr textFieldP;
+
+
+ // Pick a point within one of the current form's objects
+ frm = FrmGetActiveForm ();
+
+ // The active window will not be the active form
+ // if a popup list of a menu is displayed.
+ if ((! frm) || (FrmGetWindowHandle (frm) != WinGetActiveWindow ()) ||
+ ((focusObj = FrmGetFocus(frm)) == noFocus))
+ {
+ if (!frm)
+ PRINTF ("--- GetFocusObject == NULL (FrmGetActiveForm () == NULL)");
+ else if (FrmGetWindowHandle (frm) != WinGetActiveWindow ())
+ PRINTF ("--- GetFocusObject == NULL (FrmGetWindowHandle () != WinGetActiveWindow ())");
+ else
+ PRINTF ("--- GetFocusObject == NULL (FrmGetFocus () == noFocus)");
+
+ return NULL;
+ }
+
+ // Get the field. If it's a table get it's field.
+ if (FrmGetObjectType(frm, focusObj) == frmTableObj)
+ {
+ textFieldP = TblGetCurrentField((TablePtr) FrmGetObjectPtr(frm, focusObj));
+ if (textFieldP == NULL)
+ {
+ PRINTF ("--- GetFocusObject == NULL (TblGetCurrentField () == NULL)");
+ return NULL;
+ }
+ }
+ else
+ {
+ textFieldP = (FieldPtr) FrmGetObjectPtr(frm, focusObj);
+
+ if (textFieldP == NULL)
+ {
+ PRINTF ("--- GetFocusObject == NULL (FrmGetObjectPtr () == NULL)");
+ }
+ }
+
+ return textFieldP;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: IsFocus
+ *
+ * DESCRIPTION: Return whether the current form has the focus.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: TRUE if the form has a focus set and FALSE if not
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * roger 8/25/95 Initial Revision
+ * roger 11/27/95 Ignored not editable fields, broke out GetFocusObject
+ *
+ ***********************************************************************/
+static int IsFocus()
+{
+ FieldPtr textFieldP;
+ FieldAttrType attr;
+
+
+
+ textFieldP = GetFocusObject();
+ if (textFieldP == NULL)
+ {
+ PRINTF ("--- IsFocus == false (textFieldP == NULL)");
+ return false;
+ }
+
+ // Now make sure that the field is editable.
+ FldGetAttributes(textFieldP, &attr);
+ if (!attr.editable)
+ {
+ PRINTF ("--- IsFocus == false (!attr.editable 0x%04X)", (uint32) *(uint16*) &attr);
+ return false;
+ }
+
+ PRINTF ("--- IsFocus == true");
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SpaceLeftInFocus
+ *
+ * DESCRIPTION: Return the number of characters which can be added to
+ * the object with the focus.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: The number of characters which can be added to
+ * the object with the focus.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * roger 11/27/95 Initial Revision
+ *
+ ***********************************************************************/
+static int SpaceLeftInFocus()
+{
+ FieldPtr textFieldP;
+ FieldAttrType attr;
+
+
+
+ textFieldP = GetFocusObject();
+ if (textFieldP == NULL)
+ return 0;
+
+ // Now make sure that the field is editable.
+ FldGetAttributes(textFieldP, &attr);
+ if (!attr.editable)
+ return 0;
+
+
+
+ return FldGetMaxChars(textFieldP) - FldGetTextLength(textFieldP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FakeLocalMovement
+ *
+ * DESCRIPTION: Generate a random point within the vicinity of the last
+ * point.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: currentX - the new x-coordinate of a pen movement.
+ * currentY - the new y-coordinate of a pen movement.
+ * lastX - the last x-coordinate of a pen movement.
+ * lastY - the last y-coordinate of a pen movement.
+ *
+ * RETURNED: Nothing.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/15/95 Initial Revision
+ *
+ ***********************************************************************/
+static void FakeLocalMovement(Int16* currentX, Int16* currentY, Int16 lastX, Int16 lastY)
+{
+ Int16 winWidth, winHeight;
+
+ *currentX = lastX + (randN(FntLineHeight() * 2) - FntLineHeight());
+ *currentY = lastY + (randN(FntLineHeight() * 2) - FntLineHeight()); // FntLineHeight
+
+ // Note: This code was incorrectly using Hwr Display constants to determine screen size.
+ // The approved of method is to use the size of the current window, which may also be
+ // the screen, however, this may not be correct for what gremilns needs to do.
+ // Something needs to be done for now just to get it to work. BRM 6/30/99
+ WinGetDisplayExtent(&winWidth, &winHeight);
+
+ // Clip to screen bounds
+ //
+ // KAAR: In original Gremlins, the point was pinned to [-1...winWidth/Height].
+ // That doesn't seem right, especially since -1 is used as a pen up indicator.
+ // So now I clip to [0...winWidth/Height).
+
+ if (*currentX < 0) *currentX = 0;
+ if (*currentX >= winWidth)
+ *currentX = winWidth - 1;
+
+ if (*currentY < 0) *currentY = 0;
+ if (*currentY >= winHeight)
+ *currentY = winHeight = 1;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RandomScreenXY
+ *
+ * DESCRIPTION: Generate a random point.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: x - the x-coordinate of a pen movement.
+ * y - the y-coordinate of a pen movement.
+ *
+ * RETURNED: Nothing.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/15/95 Initial Revision
+ *
+ ***********************************************************************/
+static void RandomScreenXY(Int16* x, Int16* y)
+{
+#ifdef __DEBUGGER_APPLICATION__
+
+ // Since the WinGetDisplayExtent() trap doesn't exist in all versions
+ // of the Palm OS, the debugger can't rely on it being around. So,
+ // for the debugger version of this build, we explicitely set the
+ // old screen width.
+ //
+ // DOLATER: Figure out a way to determine if the WinGetDisplayExtent()
+ // is around. If it is, then call it. Otherwise, revert to the
+ // old constants.
+ //
+ #define hwrDisplayWidth 160
+ #define hwrDisplayHeight 160
+
+ *x = randN(hwrDisplayWidth);
+ *y = randN(hwrDisplayHeight);
+
+#else
+
+ Int16 winWidth, winHeight;
+
+ WinGetDisplayExtent(&winWidth, &winHeight);
+
+ *x = randN(winWidth);
+ *y = randN(winHeight);
+
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RandomWindowXY
+ *
+ * DESCRIPTION: Generate a random point.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: x - the x-coordinate of a pen movement.
+ * y - the y-coordinate of a pen movement.
+ *
+ * RETURNED: Nothing.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * Keith 11/11/99 Initial Revision
+ *
+ ***********************************************************************/
+static void RandomWindowXY(Int16* x, Int16* y)
+{
+ // Every so often tap anywhere on the screen (10%)
+ if ((randN(10) == 1) || (WinGetActiveWindow () == NULL))
+ {
+ RandomScreenXY(x, y);
+ }
+ else
+ {
+ // We want to tap in the active window. However, WinGetWindowBounds
+ // works against the draw window, which is not necessarily the active
+ // window. Make it so.
+
+ WinHandle oldDraw = WinSetDrawWindow (WinGetActiveWindow());
+
+ RectangleType bounds;
+ WinGetWindowBounds (&bounds);
+
+ *x = bounds.topLeft.x + randN(bounds.extent.x);
+ *y = bounds.topLeft.y + randN(bounds.extent.y);
+
+ WinSetDrawWindow (oldDraw);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FakeEventXY
+ *
+ * DESCRIPTION: Generate random (x,y) coordindates to produce an event.
+ *
+ * CALLED BY: EmGremlins.cp
+ *
+ * PARAMETERS: x - x-coordinate of a pen down.
+ * y - y-coordinate of a pen down.
+ *
+ * RETURNED:
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 08/15/95 Initial Revision
+ * kwk 07/17/98 10% of the time, generate tap in silkscreen btn.
+ * kwk 08/04/99 Cranked percentage down to 5%, since otherwise
+ * we're always just bringing up the keyboard or
+ * the Find form.
+ *
+ ***********************************************************************/
+static void FakeEventXY(Int16* x, Int16* y)
+{
+ FormPtr frm;
+ Int16 objIndex;
+ RectangleType bounds;
+
+#ifndef forSimulator
+ // Every so often tap anywhere on the screen (2%)
+ if (randN(100) < 2)
+ {
+ RandomScreenXY(x, y);
+ return;
+ }
+#endif
+
+ // Pick a point within one of the current form's objects
+ frm = FrmGetActiveForm ();
+
+ // First see if we want to generate a tap in a silkscreen button. If not, then
+ // generate a point in the draw window if there no active form, or the active form
+ // is not the the active window.. The active window will not be the active form
+ // if a popup list of a menu is displayed.
+ //
+ // Also do this if there aren't any objects in the form.
+
+ if (randN(20) == 1) {
+ UInt16 numButtons;
+ const PenBtnInfoType* buttonListP = EvtGetPenBtnList(&numButtons);
+
+ const size_t size = EmAliasPenBtnInfoType<PAS>::GetSize ();
+ emuptr addr = ((emuptr) buttonListP) + randN(numButtons) * size;
+
+ EmAliasPenBtnInfoType<PAS> button (addr);
+ RectangleType randButtonRect;
+ randButtonRect.topLeft.x = button.boundsR.topLeft.x;
+ randButtonRect.topLeft.y = button.boundsR.topLeft.y;
+ randButtonRect.extent.x = button.boundsR.extent.x;
+ randButtonRect.extent.y = button.boundsR.extent.y;
+
+ *x = randButtonRect.topLeft.x + (randButtonRect.extent.x / 2);
+ *y = randButtonRect.topLeft.y + (randButtonRect.extent.y / 2);
+ } else if ((frm == NULL) ||
+ (FrmGetWindowHandle (frm) != WinGetActiveWindow ()))
+ {
+ RandomWindowXY (x, y);
+ }
+ else
+ {
+ // Generate a point in an one of the form's objects that we expect
+ // can do something with the point (i.e. labels are ignored).
+
+#ifdef forSimulator
+ do
+ {
+ objIndex = randN(numObjects);
+ switch (FrmGetObjectType (frm, objIndex))
+ {
+ case frmBitmapObj:
+ case frmLineObj:
+ case frmFrameObj:
+ case frmRectangleObj:
+ case frmLabelObj:
+ case frmTitleObj:
+ case frmPopupObj:
+ // do nothing for these
+ objIndex = -1;
+ break;
+
+ default:
+ FrmGetObjectBounds (frm, objIndex, &bounds);
+ *x = bounds.topLeft.x + randN(bounds.extent.x);
+ *y = bounds.topLeft.y + randN(bounds.extent.y);
+ WinWindowToDisplayPt(x, y);
+
+ if ( *x < -1 || *x > 1000 ||
+ *y < -1 || *y > 1000)
+ ErrDisplay("Invalid point made");
+
+ break;
+ } // end switch
+ } while (objIndex == -1); // don't leave until we found a useful object
+
+#else
+ // Get the list of objects we can click on.
+
+ vector<UInt16> okObjects;
+ ::CollectOKObjects (frm, okObjects);
+
+ // If there are no such objects, just generate a random point.
+
+ if (okObjects.size () == 0)
+ {
+ RandomWindowXY (x, y);
+ }
+
+ // If there are such objects, pick one and click on it.
+
+ else
+ {
+ objIndex = okObjects[randN(okObjects.size ())];
+
+ FrmGetObjectBounds (frm, objIndex, &bounds);
+
+ Int16 winWidth, winHeight;
+ ::WinGetDisplayExtent(&winWidth, &winHeight);
+
+ if (bounds.topLeft.x < 0)
+ bounds.topLeft.x = 0;
+
+ if (bounds.topLeft.y < 0)
+ bounds.topLeft.y = 0;
+
+ if (bounds.extent.x > winWidth - bounds.topLeft.x - 1)
+ bounds.extent.x = winWidth - bounds.topLeft.x - 1;
+
+ if (bounds.extent.y > winHeight - bounds.topLeft.y - 1)
+ bounds.extent.y = winHeight - bounds.topLeft.y - 1;
+
+ *x = bounds.topLeft.x + randN(bounds.extent.x);
+ *y = bounds.topLeft.y + randN(bounds.extent.y);
+
+ WinWindowToDisplayPt(x, y);
+ }
+#endif
+ } // end else
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: GremlinsSendEvent
+ *
+ * DESCRIPTION: Send a synthesized event to the device if it's
+ * idle.
+ *
+ * PARAMETERS: nothing
+ *
+ * RETURNS: nothing
+ *
+ * CALLED BY: the debugger's console object
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * art 11/2/95 Created.
+ * dia 8/26/98 Added try/catch block.
+ *
+ *************************************************************/
+#ifdef forSimulator
+
+void GremlinsSendEvent (void)
+{
+// long tick;
+// Boolean idle;
+// LowMemType* lowMemP = (LowMemType*)PilotGlobalsP;
+// SysEvtMgrGlobalsPtr sysEvtMgrGlobalsP;
+
+ if (!TheGremlinsP->IsInitialized() || !StubGremlinsIsOn())
+ return;
+
+ ErrTry
+ {
+#if EMULATION_LEVEL == EMULATION_WINDOWS
+ TheGremlinsP->GetFakeEvent();
+#else
+// This makes it go faster, but it is much less careful (not as reproducable).
+// The code was left here for future reference / fixing.
+
+// // If accessing remote device, low memory is at 0...
+// #if MEMORY_TYPE == MEMORY_REMOTE
+// lowMemP = (LowMemType*)0;
+// #endif
+//
+// // Find out if the device is idle.
+// tick = StubTimGetTicks();
+// if ((tick - IdleTimeCheck) >= 0)
+// {
+// sysEvtMgrGlobalsP = (SysEvtMgrGlobalsPtr)ShlDWord(&lowMemP->fixed.globals.sysEvtMgrGlobalsP);
+// idle = ShlByte(&sysEvtMgrGlobalsP->idle);
+// if (!idle)
+// {
+// IdleTimeCheck = tick + 12; // 10 times a second
+// return;
+// }
+// else
+// // Clear the idle bit so the the device will not send us another idle packet.
+// // Send an event
+// IdleTimeCheck = 0;
+//
+ TheGremlinsP->GetFakeEvent();
+// }
+#endif
+ }
+ ErrCatch (inErr)
+ {
+ if (inErr != -1)
+ {
+ char text[256];
+ UInt32 step;
+
+ // Print error & stop...
+ TheGremlinsP->Status (NULL, &step, NULL);
+ sprintf(text, "Error #%lx occurred while sending. Gremlins at %ld. Stopping.\n", inErr, step);
+ DbgMessage(text);
+ StubAppGremlinsOff();
+ }
+ }
+ ErrEndCatch
+}
+
+#endif
+
+
+/************************************************************
+ *
+ * FUNCTION: GremlinsProcessPacket
+ *
+ * DESCRIPTION: Send a synthesized event to the device if it's
+ * idle.
+ *
+ * PARAMETERS: bodyP - pointer to Gremlins packet from device.
+ *
+ * RETURNS: nothing
+ *
+ * CALLED BY: the debugger's console object
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * art 11/2/95 Created.
+ * dia 8/26/98 Added try/catch block.
+ *
+ *************************************************************/
+#ifdef forSimulator
+
+void GremlinsProcessPacket (void* bodyParamP)
+{
+ UInt8 flags;
+ SysPktGremlinsCmdType* bodyP = (SysPktGremlinsCmdType*)bodyParamP;
+ LowMemType* lowMemP = (LowMemType*)PilotGlobalsP;
+ SysEvtMgrGlobalsPtr sysEvtMgrGlobalsP;
+
+ if (!TheGremlinsP->IsInitialized())
+ return;
+
+ ErrTry
+ {
+ // See which action code got sent us
+ if (bodyP->action == sysPktGremlinsIdle) {
+
+ // If accessing remote device, low memory is at 0...
+ #if MEMORY_TYPE == MEMORY_REMOTE
+ lowMemP = (LowMemType*)0;
+ #endif
+
+ // Clear the idle bit so the the device will not send us another idle packet.
+ // Send an event
+ TheGremlinsP->GetFakeEvent();
+
+ // Turn the idle bit back on.
+ sysEvtMgrGlobalsP = (SysEvtMgrGlobalsPtr)ShlDWord((void *)&lowMemP->fixed.globals.sysEvtMgrGlobalsP);
+ flags = ShlByte((void *)&sysEvtMgrGlobalsP->gremlinsFlags);
+ flags |= grmGremlinsIdle;
+ ShlWriteMem (&flags, (UInt32)&sysEvtMgrGlobalsP->gremlinsFlags, sizeof(UInt8));
+
+// flags = ShlByte(&sysEvtMgrGlobalsP->gremlinsFlags);
+// ErrFatalDisplayIf (!(flags & grmGremlinsIdle), "Invalid flags");
+ }
+
+ else
+ ErrDisplay("Invalid action code");
+ }
+ ErrCatch (inErr)
+ {
+ if (inErr != -1)
+ {
+ char text[256];
+ UInt32 step;
+
+ // Print error & stop...
+ TheGremlinsP->Status (NULL, &step, NULL);
+ sprintf(text, "Error #%lx occurred while processing. Gremlins at %ld. Stopping.\n", inErr, step);
+ DbgMessage(text);
+ StubAppGremlinsOff();
+ }
+ }
+ ErrEndCatch
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, DatabaseInfo&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& inStream, DatabaseInfo& outInfo)
+{
+ inStream >> outInfo.creator;
+ inStream >> outInfo.type;
+ inStream >> outInfo.version;
+
+ inStream >> outInfo.dbID;
+ inStream >> outInfo.cardNo;
+ inStream >> outInfo.modDate;
+ inStream >> outInfo.dbAttrs;
+ inStream >> outInfo.name;
+
+ outInfo.dbName[0] = 0;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, const DatabaseInfo&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& inStream, const DatabaseInfo& inInfo)
+{
+ LocalID dbID = 0;
+ UInt16 cardNo = 0;
+ UInt32 modDate = 0;
+ UInt16 dbAttrs = 0;
+ char name[dmDBNameLength] = {0};
+
+ inStream << inInfo.creator;
+ inStream << inInfo.type;
+ inStream << inInfo.version;
+
+ // I have no idea why dummy values are written out for these fields.
+ // But it sure causes us problems later when we need to access them!
+ // See the code in Hordes::GetAppList that needs to patch up the missing
+ // information.
+
+ inStream << dbID;
+ inStream << cardNo;
+ inStream << modDate;
+ inStream << dbAttrs;
+ inStream << name;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, AppPreferences::GremlinInfo&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& inStream, GremlinInfo& outInfo)
+{
+ bool dummy;
+
+ inStream >> outInfo.fNumber;
+ inStream >> outInfo.fSteps;
+ inStream >> outInfo.fAppList;
+
+ inStream >> dummy; // forward compatibility: this field was
+ // fContinuePastWarnings
+
+ inStream >> dummy;
+ inStream >> dummy;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, const AppPreferences::GremlinInfo&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& inStream, const GremlinInfo& inInfo)
+{
+ bool dummy = false;
+
+ inStream << inInfo.fNumber;
+ inStream << inInfo.fSteps;
+ inStream << inInfo.fAppList;
+
+ inStream << dummy; // backward compatibility: this field was
+ // fContinuePastWarnings
+
+ inStream << dummy;
+ inStream << dummy;
+
+ return inStream;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: Default Constructor
+ *
+ * DESCRIPTION: Finds the key probablilities sum.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: main() of EmEmulatorApp.cp
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 08/01/95 Created.
+ * kwk 07/17/98 Moved key probability init into run-time
+ * section.
+ *
+ *************************************************************/
+Gremlins::Gremlins()
+{
+ keyProbabilitiesSum = 0;
+ inited = false;
+#ifdef forSimulator
+ number = -1;
+#else
+ number = ~0;
+#endif
+}
+
+/************************************************************
+ *
+ * FUNCTION: Destructor
+ *
+ * DESCRIPTION: Any necessary deallocation or cleanup.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: main() of EmEmulatorApp.cp
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/1/95 Created.
+ *
+ *************************************************************/
+Gremlins::~Gremlins()
+{
+}
+
+/************************************************************
+ *
+ * FUNCTION: IsInitialized
+ *
+ * DESCRIPTION: Returns whether or not Gremlins has be initialized.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: TRUE - has been initialized, FALSE - has not been initialized.
+ *
+ * CALLED BY: FindCommandStatus() in EmEmulatorApp.cp.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/1/95 Created.
+ *
+ *************************************************************/
+Boolean Gremlins::IsInitialized() const
+{
+ return inited;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: Initialize
+ *
+ * DESCRIPTION: Initialize the gremlins class.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: ObeyCommand() in EmEmulatorApp.cp.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/1/95 Created.
+ *
+ *************************************************************/
+void Gremlins::Initialize(UInt16 newNumber, UInt32 untilStep, UInt32 finalVal)
+{
+#ifndef forSimulator
+ gIntlMgrExists = -1;
+ ::ResetCalibrationInfo();
+ ::ResetClocks ();
+ EmLowMem_SetGlobal (hwrBatteryLevel, 255);
+ EmLowMem_SetGlobal (hwrBatteryPercent, 100);
+#endif
+
+ counter = 0;
+ until = untilStep;
+ finalUntil = finalVal;
+#ifndef forSimulator
+ saveUntil = until;
+#endif
+ catchUp = false;
+ needPenUp = false;
+ charsToType[0] = '\0';
+ inited = true;
+#ifdef forSimulator
+ // removed...test will always fail because newNumber is unsigned...
+// if (newNumber == -1)
+// newNumber = INITIAL_SEED;
+ //newNumber = clock() % MAX_SEED_VALUE + 1;
+#endif
+ number = newNumber;
+ srand(number);
+
+ IdleTimeCheck = 0;
+
+ // Update menus (needed when init. called from console)
+ StubAppGremlinsOn ();
+}
+
+
+
+/************************************************************
+ *
+ * FUNCTION: Reset
+ *
+ * DESCRIPTION: Un-initialize the gremlins class.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void Gremlins::Reset(void)
+{
+ inited = false;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: New
+ *
+ * DESCRIPTION: Start new Gremlins
+ *
+ * PARAMETERS: GremlinInfo info
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void
+Gremlins::New (const GremlinInfo& info)
+{
+ if (LogGremlins ())
+ {
+ string templ = Platform::GetString (kStr_GremlinStarted);
+ LogAppendMsg (templ.c_str (), (int) info.fNumber, info.fSteps);
+ }
+
+ // If needed, switch to an "approved" application.
+ // This code roughly follows that in AppsViewSwitchApp in Launcher.
+
+ if (info.fAppList.size () > 0)
+ {
+ // Switch to the first on the list.
+
+ DatabaseInfo dbInfo = *(info.fAppList.begin ());
+
+ //---------------------------------------------------------------------
+ // If this is an executable, call SysUIAppSwitch
+ //---------------------------------------------------------------------
+ if (::IsExecutable (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs))
+ {
+ Err err = ::SysUIAppSwitch (dbInfo.cardNo, dbInfo.dbID,
+ sysAppLaunchCmdNormalLaunch, NULL);
+ Errors::ThrowIfPalmError (err);
+ }
+
+ //---------------------------------------------------------------------
+ // else, this must be a launchable data database. Find it's owner app
+ // and launch it with a pointer to the data database name.
+ //---------------------------------------------------------------------
+ else
+ {
+ DmSearchStateType searchState;
+ UInt16 cardNo;
+ LocalID dbID;
+ Err err = ::DmGetNextDatabaseByTypeCreator (true, &searchState,
+ sysFileTApplication, dbInfo.creator,
+ true, &cardNo, &dbID);
+ Errors::ThrowIfPalmError (err);
+
+ // Create the param block
+ emuptr cmdPBP = (emuptr) ::MemPtrNew (sizeof (SysAppLaunchCmdOpenDBType));
+ Errors::ThrowIfNULL ((void*) cmdPBP);
+
+ // Fill it in
+ ::MemPtrSetOwner ((MemPtr) cmdPBP, 0);
+ EmMemPut16 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, cardNo), dbInfo.cardNo);
+ EmMemPut32 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, dbID), dbInfo.dbID);
+
+ // Switch now
+ err = ::SysUIAppSwitch (cardNo, dbID, sysAppLaunchCmdOpenDB, (MemPtr) cmdPBP);
+ Errors::ThrowIfPalmError (err);
+ }
+ }
+
+ this->Initialize (info.fNumber, info.fSteps, info.fFinal);
+
+ gremlinStartTime = Platform::GetMilliseconds ();
+
+ // Make sure the app's awake. Normally, we post events on a patch to
+ // SysEvGroupWait. However, if the Palm device is already waiting,
+ // then that trap will never get called. By calling EvtWakeup now,
+ // we'll wake up the Palm device from its nap.
+
+ Errors::ThrowIfPalmError (EvtWakeup ());
+
+ Hordes::TurnOn(true);
+
+ if (info.fSaveFrequency != 0)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleAutoSaveState ();
+ }
+}
+
+
+
+/************************************************************
+ *
+ * FUNCTION: Save
+ *
+ * DESCRIPTION: Saves Gremlin Info
+ *
+ * PARAMETERS: SessionFile to write to.
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void
+Gremlins::Save (SessionFile& f)
+{
+ gremlinStopTime = Platform::GetMilliseconds ();
+
+ const long kCurrentVersion = 2;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ Bool hordesIsOn = Hordes::IsOn ();
+
+ s << kCurrentVersion;
+
+ s << keyProbabilitiesSum;
+ s << lastPointY;
+ s << lastPointX;
+ s << lastPenDown;
+ s << number;
+ s << counter;
+ s << finalUntil;
+ s << saveUntil;
+ s << inited;
+ s << catchUp;
+ s << needPenUp;
+ s << charsToType;
+
+ s << (hordesIsOn != false);
+ s << gremlinStartTime;
+ s << gremlinStopTime;
+
+ s << gGremlinNext;
+
+ GremlinInfo info;
+
+ info.fAppList = gGremlinAppList;
+ info.fNumber = number;
+ info.fSaveFrequency = gGremlinSaveFrequency;
+ info.fSteps = until;
+ info.fFinal = finalUntil;
+
+ s << info;
+
+ f.WriteGremlinInfo (chunk);
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: Load
+ *
+ * DESCRIPTION: Loads Gremlin Info
+ *
+ * PARAMETERS: SessionFile to read from.
+ *
+ * RETURNS: TRUE if a Gremlin state have been loaded and it
+ * is ON.
+ * FALSE otherwise.
+ *
+ *************************************************************/
+Boolean
+Gremlins::Load (SessionFile& f)
+{
+ Chunk chunk;
+ bool fHordesOn;
+
+ if (f.ReadGremlinInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> keyProbabilitiesSum;
+ s >> lastPointY;
+ s >> lastPointX;
+ s >> lastPenDown;
+ s >> number;
+ s >> counter;
+ s >> finalUntil;
+ s >> saveUntil;
+ s >> inited;
+ s >> catchUp;
+ s >> needPenUp;
+ s >> charsToType;
+
+ s >> fHordesOn;
+
+ s >> gremlinStartTime;
+ s >> gremlinStopTime;
+
+ s >> gGremlinNext;
+
+ // sync until to finalUntil
+
+ until = finalUntil;
+
+ // Patch up the start and stop times.
+
+ int32 delta = gremlinStopTime - gremlinStartTime;
+ gremlinStopTime = Platform::GetMilliseconds ();
+ gremlinStartTime = gremlinStopTime - delta;
+
+ // Reset keyProbabilitiesSum to zero so that it gets
+ // recalculated. Writing it out to the session file
+ // was a bad idea. The value written out may not be
+ // appropriate for the version of Poser reading it in.
+
+ keyProbabilitiesSum = 0;
+ }
+
+ if (version >= 2)
+ {
+ GremlinInfo info;
+
+ s >> info;
+
+ Preference<GremlinInfo> pref (kPrefKeyGremlinInfo);
+ pref = info;
+ }
+ }
+
+ return fHordesOn;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: Status
+ *
+ * DESCRIPTION: Return the gremlin number and counter.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: DoGremlins() in ShellCmdSys.cpp.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * roger 8/4/95 Created.
+ * dia 9/1/98 Allows for NULL parameters.
+ *
+ *************************************************************/
+void Gremlins::Status(UInt16 *currentNumber, UInt32 *currentStep,
+ UInt32 *currentUntil)
+{
+ if (currentNumber) *currentNumber = number;
+ if (currentStep) *currentStep = counter;
+ if (currentUntil) *currentUntil = until;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: SetSeed
+ *
+ * DESCRIPTION: Allows the user to set the seed to be used.
+ *
+ * PARAMETERS: newSeed - the new value of the seed.
+ *
+ * RETURNS: TRUE - seed value set to new seed, FALSE - value not set.
+ *
+ * CALLED BY: Uncalled. (to be called from Debug Console)
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/2/95 Created.
+ *
+ *************************************************************/
+Boolean Gremlins::SetSeed(UInt32 newSeed)
+{
+ if (newSeed > MAX_SEED_VALUE)
+ return false;
+ else
+ {
+ number = (UInt16) newSeed;
+ srand(number);
+ return true;
+ }
+}
+
+/************************************************************
+ *
+ * FUNCTION: SetUntil
+ *
+ * DESCRIPTION: Allows the user to set the until value to be used.
+ *
+ * PARAMETERS: newUntil - the new value of until.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: Hordes::Step
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/2/95 Created.
+ *
+ *************************************************************/
+void Gremlins::SetUntil(UInt32 newUntil)
+{
+ until = newUntil;
+#ifndef forSimulator
+ saveUntil = until;
+#endif
+}
+
+/************************************************************
+ *
+ * FUNCTION: RestoreFinalUntil
+ *
+ * DESCRIPTION: Restores the original max gremlins limit.
+ *
+ * CALLED BY: Hordes::Resume
+ *
+ *************************************************************/
+
+void Gremlins::RestoreFinalUntil (void)
+{
+ until = finalUntil;
+}
+
+/************************************************************
+ *
+ * FUNCTION: Step
+ *
+ * DESCRIPTION: Allows Gremlins to go on step further then its
+ * set maximum.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY: ObeyCommand() in EmEmulatorApp.cp.
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * David 8/1/95 Created.
+ *
+ *************************************************************/
+void Gremlins::Step()
+{
+#ifndef forSimulator
+ saveUntil = until;
+#endif
+ until = counter + 1;
+}
+
+
+
+
+/************************************************************
+ *
+ * FUNCTION: Resume
+ *
+ * DESCRIPTION: Resumes Gremlin
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void
+Gremlins::Resume (void)
+{
+ gremlinStartTime = Platform::GetMilliseconds () - (gremlinStopTime - gremlinStartTime);
+
+ // Make sure we're all on the same page...
+ ::ResetCalibrationInfo ();
+
+ // Make sure the app's awake. Normally, we post events on a patch to
+ // SysEvGroupWait. However, if the Palm device is already waiting,
+ // then that trap will never get called. By calling EvtWakeup now,
+ // we'll wake up the Palm device from its nap.
+
+ Errors::ThrowIfPalmError (EvtWakeup ());
+}
+
+
+
+
+/************************************************************
+ *
+ * FUNCTION: Stop
+ *
+ * DESCRIPTION: Stops Gremlin
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void
+Gremlins::Stop (void)
+{
+ if (Hordes::IsOn())
+ {
+ Hordes::TurnOn(false);
+ gremlinStopTime = Platform::GetMilliseconds ();
+
+ unsigned short number;
+ unsigned long step;
+ unsigned long until;
+ this->Status (&number, &step, &until);
+
+ if (LogGremlins ())
+ {
+ string templ = Platform::GetString (kStr_GremlinEnded);
+ LogAppendMsg (templ.c_str (),
+ (int) number, step, until, (gremlinStopTime - gremlinStartTime));
+ }
+
+ LogDump ();
+ }
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: SendCharsToType
+ *
+ * DESCRIPTION: Send a char to the emulator if any are pending.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: true if a char was sent.
+ *
+ * CALLED BY: GetFakeEvent
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * roger 10/04/95 Created.
+ * kwk 07/28/98 Queue double-byte characters correctly.
+ *
+ *************************************************************/
+Boolean Gremlins::SendCharsToType()
+{
+ if (charsToType[0] != '\0')
+ {
+ WChar theChar;
+ UInt16 charSize = TxtGetNextChar(charsToType, 0, &theChar);
+ EmEventPlayback::RecordKeyEvent (theChar, 0, 0);
+ StubAppEnqueueKey(theChar, 0, 0);
+ PRINTF ("--- Gremlin #%ld Gremlins::SendCharsToType: key = %ld", (long) number, (long) theChar);
+ strcpy(&charsToType[0], &charsToType[charSize]);
+ return true;
+ }
+
+ return false;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: GetFakeEvent
+ *
+ * DESCRIPTION: Make a phony event for gremlin mode.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNS: TRUE if a key or point was enqueued, FALSE otherwise.
+ *
+ * CALLED BY: TDEProcessMacEvents in EmEmulatorEvents.cp.
+ *
+ * REVISION HISTORY:
+ * 06/01/95 rsf Created by Roger Flores.
+ * 07/31/95 David Moved to emulator level.
+ * 08/28/98 kwk Removed usage of TxtCharIsVirtual macro.
+ * 07/03/99 kwk Set command bit for page up/page down keydown
+ * events, since these are virtual (to match Graffiti behavior).
+ * 06/04/01 kwk Add support for Big-5 char encoding (Trad. Chinese).
+ *
+ *************************************************************/
+Boolean Gremlins::GetFakeEvent()
+{
+ int chance;
+ int i;
+ int spaceLeft;
+ PointType pen;
+ const char *quote;
+
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: Entering", (long) number);
+
+ if (! inited)
+ {
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: not initialized; leaving", (long) number);
+ return false;
+ }
+
+ // check to see if Gremlins has produced its max. # of "events."
+ if (counter > until)
+ {
+ StubAppGremlinsOff ();
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: End of Days; leaving", (long) number);
+ return false;
+ }
+
+ // Added - during Gremlin runs, we found that the timeout
+ // could get set to 30 seconds and that a Gremlin may type
+ // characters for more than 30 seconds at a time. EvtEnqueueKey
+ // doesn't reset the event timer, so it was possible for the
+ // device to go to sleep, even when typing was occuring.
+
+ ::EvtResetAutoOffTimer ();
+
+ // check to see if the event loop needs time to catch up.
+ if (catchUp)
+ {
+ EmEventPlayback::RecordNullEvent ();
+ catchUp = false;
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: playing catchup; leaving", (long) number);
+ return false;
+ }
+#ifdef forSimulator
+ counter++;
+#endif
+
+ // if no control object was entered, return a pen up.
+ if (needPenUp)
+ {
+ pen.x = -1;
+ pen.y = -1;
+ lastPointX = pen.x;
+ lastPointY = pen.y;
+ lastPenDown = false;
+ needPenUp = false;
+ EmEventPlayback::RecordPenEvent (pen);
+ StubAppEnqueuePt(&pen);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted pen up; leaving", (long) number);
+ return true;
+ }
+
+ // If we've queued up a quote string, and there are still characters to
+ // send, do so now.
+
+ if (SendCharsToType())
+ {
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: sent chars to type (1); leaving", (long) number);
+ return true;
+ }
+
+ chance = randPercent;
+
+ // Now fake an input
+ if ((chance < KEY_DOWN_EVENT_WITHOUT_FOCUS_CHANCE)
+ || (chance < KEY_DOWN_EVENT_WITH_FOCUS_CHANCE && IsFocus()))
+ {
+ if ((randPercent < TYPE_QUOTE_CHANCE) && IsFocus())
+ {
+ const char** quoteArray = kAsciiQuotes;
+
+ // 80% of the time we'll use text that's appropriate for the device's
+ // character encoding. The other 20%, we'll use 7-bit ASCII.
+ if (randN(10) < 8)
+ {
+ UInt32 encoding;
+ if (FtrGet(sysFtrCreator, sysFtrNumEncoding, &encoding) != errNone)
+ {
+ encoding = charEncodingPalmLatin;
+ }
+
+ for (UInt16 i = 0; i < sizeof(kQuotesInfo) / sizeof(QuotesInfoType); i++)
+ {
+ if (kQuotesInfo[i].charEncoding == encoding)
+ {
+ quoteArray = kQuotesInfo[i].strings;
+ break;
+ }
+ }
+ }
+
+ quote = quoteArray[randN(NUM_OF_QUOTES)];
+ strcat(charsToType, quote);
+
+ // The full field functionality doesn't need to be tested much
+ // If charsToType is more than the space remaining in the current
+ // field, then for each char past the full point give 1/3 chance to
+ // stop at that char.
+ spaceLeft = SpaceLeftInFocus();
+ if (strlen(charsToType) > (size_t) spaceLeft) {
+ UInt32 charStart, charEnd;
+ TxtCharBounds(charsToType, spaceLeft, &charStart, &charEnd);
+ i = charStart;
+ while (charsToType[i] != '\0') {
+ if (randPercent < 33) {
+ charsToType[i] = '\0';
+ break;
+ } else {
+ i += TxtNextCharSize(charsToType, i);
+ }
+ }
+ }
+
+ Bool result = SendCharsToType ();
+
+ if (!result)
+ EmEventPlayback::RecordNullEvent ();
+
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: sent chars to type (2); leaving", (long) number);
+ return result;
+ }
+ else
+ {
+ if (keyProbabilitiesSum == 0) {
+ for (Int16 i = 0; i < NUM_OF_KEYS; i++) {
+ if ((i > 0x00FF)
+ || ((TxtByteAttr(i) & byteAttrSingle) != 0)) {
+ keyProbabilitiesSum += chanceForKey[i];
+ }
+ }
+ }
+
+ chance = randN(keyProbabilitiesSum);
+
+ // Skip chars which cannot be single-byte, since we don't want to
+ // generate bogus high-byte values.
+
+ for (i = 0; i < NUM_OF_KEYS; i++) {
+ if ((i < 0x0100)
+ && ((TxtByteAttr(i) & byteAttrSingle) == 0)) {
+ continue;
+ } else if (chance < chanceForKey[i]) {
+ break;
+ } else {
+ chance -= chanceForKey[i];
+ }
+ }
+
+ // There's a fractional chance for a greater number to be generated. If
+ // so we do nothing.
+ if (i >= NUM_OF_KEYS)
+ return false;
+
+ if ((i > 255) || (i == chrPageUp) || (i == chrPageDown))
+ {
+ EmEventPlayback::RecordKeyEvent (i, 0, commandKeyMask);
+ StubAppEnqueueKey(i, 0, commandKeyMask);
+ }
+ else
+ {
+ EmEventPlayback::RecordKeyEvent (i, 0, 0);
+ StubAppEnqueueKey(i, 0, 0);
+ }
+
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = %ld; leaving", (long) number, i);
+ return true;
+ }
+ }
+
+ else if (chance < PEN_DOWN_EVENT_CHANCE)
+ {
+ needPenUp = true;
+
+ FakeEventXY(&pen.x, &pen.y);
+
+ lastPointX = pen.x;
+ lastPointY = pen.y;
+ lastPenDown = true;
+ EmEventPlayback::RecordPenEvent (pen);
+ StubAppEnqueuePt(&pen);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted pen event = (%ld, %ld), leaving",
+ (long) number, (long) pen.x, (long) pen.y);
+
+ // Draw a test pixel on the overlay
+ StubViewDrawPixel(pen.x, pen.y);
+ return true;
+ }
+
+
+ else if (chance < MENU_EVENT_CHANCE)
+ {
+ EmEventPlayback::RecordKeyEvent (vchrMenu, vchrMenu, commandKeyMask);
+ StubAppEnqueueKey(vchrMenu, vchrMenu, commandKeyMask);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrMenu, leaving", (long) number);
+ return true;
+ }
+
+
+ else if (chance < FIND_EVENT_CHANCE)
+ {
+ EmEventPlayback::RecordKeyEvent (vchrFind, vchrFind, commandKeyMask);
+ StubAppEnqueueKey(vchrFind, vchrFind, commandKeyMask);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrFind, leaving", (long) number);
+ return true;
+ }
+
+
+ else if (chance < KEYBOARD_EVENT_CHANCE)
+ {
+ EmEventPlayback::RecordKeyEvent (vchrKeyboard, vchrKeyboard, commandKeyMask);
+ StubAppEnqueueKey(vchrKeyboard, vchrKeyboard, commandKeyMask);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrKeyboard, leaving", (long) number);
+ return true;
+ }
+
+
+ else if (chance < LOW_BATTERY_EVENT_CHANCE)
+ {
+ EmEventPlayback::RecordKeyEvent (vchrLowBattery, vchrLowBattery, commandKeyMask);
+ StubAppEnqueueKey(vchrLowBattery, vchrLowBattery, commandKeyMask);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrLowBattery, leaving", (long) number);
+ return true;
+ }
+
+
+ else if (chance < APP_SWITCH_EVENT_CHANCE)
+ {
+ // Modify the standard APP_SWITCH_EVENT_CHANCE by another factor
+ // of 5%. Without it, we enter this code way too often, and
+ // Gremlins slows down a LOT! (Like, by a factor of 2.3).
+
+ if (randPercent < 5)
+ {
+ DatabaseInfoList appList = Hordes::GetAppList ();
+
+ if (appList.size () > 0)
+ {
+ // Switch to a random app on the list.
+
+ DatabaseInfo& dbInfo = appList [randN (appList.size ())];
+
+ //---------------------------------------------------------------------
+ // If this is an executable, call SysUIAppSwitch
+ //---------------------------------------------------------------------
+ if (::IsExecutable (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs))
+ {
+ EmuAppInfo currentApp = EmPatchState::GetCurrentAppInfo ();
+
+ EmEventPlayback::RecordSwitchEvent (dbInfo.cardNo, dbInfo.dbID,
+ currentApp.fCardNo, currentApp.fDBID);
+
+ Err err = ::SysUIAppSwitch (dbInfo.cardNo, dbInfo.dbID,
+ sysAppLaunchCmdNormalLaunch, NULL);
+ Errors::ThrowIfPalmError (err);
+
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: switched to app %s, leaving",
+ (long) number, dbInfo.name);
+
+ return true;
+ }
+
+ //---------------------------------------------------------------------
+ // else, say we tried and call it quits by falling through
+ //---------------------------------------------------------------------
+
+ }
+ }
+ }
+
+/*
+ else if (chance < POWER_OFF_CHANCE)
+ {
+ EmEventPlayback::RecordKeyEvent (vchrAutoOff, vchrAutoOff, commandKeyMask);
+ StubAppEnqueueKey(vchrAutoOff, vchrAutoOff, commandKeyMask);
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: posted key = vchrAutoOff, leaving", (long) number);
+ return true;
+ }
+*/
+ PRINTF ("--- Gremlin #%ld Gremlins::GetFakeEvent: exiting with no event.",
+ (long) number);
+
+ // If nothing happened fall out to generate a nilEvent
+
+ EmEventPlayback::RecordNullEvent ();
+ return false;
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: GetPenMovement
+ *
+ * DESCRIPTION: Make a phony pen movement.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ * CALLED BY:
+ *
+ * REVISION HISTORY:
+ * Name Date Description
+ * ---- ---- -----------
+ * Roger 6/1/95 Created.
+ * David 7/31/95 Moved to emulator level.
+ *
+ *************************************************************/
+void Gremlins::GetPenMovement()
+{
+ // This function is not called anywhere that I can see. And since it
+ // calls FakeLocalMovement, which calls WinGetDisplayExtent, which
+ // doesn't exist in PalmDebugger, out it goes...
+
+#ifndef __DEBUGGER_APPLICATION__
+ PointType pen;
+
+
+ // check to see if Gremlins has produced its max. # of "events."
+/* if (counter > until)
+ {
+ testMode &= ~gremlinsOn;
+ theApp->UpdateMenus();
+ }
+*/
+#ifdef forSimulator
+ counter++;
+#endif
+
+ needPenUp = false;
+ if (randPercent < PEN_MOVE_CHANCE)
+ {
+ if (lastPenDown)
+ {
+ // move a small distance from the last pen position
+ if (randPercent < PEN_BIG_MOVE_CHANCE)
+ {
+ RandomScreenXY(&pen.x, &pen.y);
+ }
+ else
+ {
+ FakeLocalMovement(&pen.x, &pen.y, lastPointX, lastPointY);
+ }
+ }
+ else
+ {
+ // start the pen anywhere!
+ RandomScreenXY(&pen.x, &pen.y);
+ }
+ StubViewDrawLine(pen.x, pen.y, lastPointX, lastPointY);
+ }
+ else
+ {
+ lastPenDown = false;
+ pen.x = -1;
+ pen.y = -1;
+ catchUp = true;
+ }
+ lastPointX = pen.x;
+ lastPointY = pen.y;
+ EmEventPlayback::RecordPenEvent (pen);
+ StubAppEnqueuePt(&pen);
+#endif
+
+ PRINTF ("--- Gremlin #%ld Gremlins::GetPenMovement: pen = (%ld, %ld)",
+ (long) number, (long) pen.x, (long) pen.y);
+}
+
+
+/************************************************************
+ *
+ * FUNCTION: BumpCounter
+ *
+ * DESCRIPTION: Bumps Gremlin event counter
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNS: Nothing.
+ *
+ *************************************************************/
+void Gremlins::BumpCounter()
+{
+ PRINTF ("--- Gremlin #%ld: bumping counter", (long) number);
+ ++counter;
+}
diff --git a/SrcShared/CGremlins.h b/SrcShared/CGremlins.h
new file mode 100644
index 0000000..6d496e6
--- /dev/null
+++ b/SrcShared/CGremlins.h
@@ -0,0 +1,94 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _CGREMLINS_H_
+#define _CGREMLINS_H_
+
+#include "EmStream.h"
+#include "EmStructs.h" // GremlinEventList
+
+class SessionFile;
+
+
+extern unsigned long int gGremlinNext;
+
+class Gremlins
+{
+public:
+ Gremlins();
+ ~Gremlins();
+
+ void New(const GremlinInfo& info);
+
+ Boolean IsInitialized() const;
+ void Initialize(UInt16 newNumber = -1, UInt32 untilStep = -1, UInt32 finalVal = -1);
+ void Reset (void);
+
+ void Save(SessionFile &f);
+ Boolean Load(SessionFile &f);
+
+ void Status(UInt16 *currentNumber, UInt32 *currentStep,
+ UInt32 *currentUntil);
+ Boolean SetSeed(UInt32 newSeed);
+ void SetUntil(UInt32 newUntil);
+ void RestoreFinalUntil(void);
+
+ void Step();
+ void Resume();
+ void Stop();
+
+ Boolean GetFakeEvent();
+ void GetPenMovement();
+ Boolean SendCharsToType();
+
+ void BumpCounter();
+
+ UInt32 GetStartTime() { return gremlinStartTime; }
+ UInt32 GetStopTime() { return gremlinStopTime; }
+
+
+private:
+
+ UInt16 keyProbabilitiesSum; // The sum of all the key possiblities.
+// PointType lastPoint; // The previous point enqueued to TD.
+ Int16 lastPointX, lastPointY;
+ Boolean lastPenDown; // TRUE - last point caused a penDownEvent, FALSE - pen is up or already down.
+ UInt16 number; // the random seed (-1 means not started)
+ UInt32 counter; // The number of "events" produced by Gremlins.
+ UInt32 until; // The maximum number of "events" to produce.
+ UInt32 finalUntil; // As above, but not manipulated, as until is by Hordes
+ UInt32 saveUntil;
+ Boolean inited; // TRUE - Gremlins has been initialized, FALSE - not inited.
+ Boolean catchUp; // TRUE - Event loop needs time to catch up, FALSE - event loop doesn't need time.
+ Boolean needPenUp; // TRUE - A pen up need to be enqueued, FALSE - pen up doesn't need to be enqueued.
+ char charsToType[2048]; // Chars to send to the emulator.
+
+ UInt32 gremlinStartTime;
+ UInt32 gremlinStopTime;
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void GremlinsSendEvent (void);
+
+extern void GremlinsProcessPacket (void* pktBodyP);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _CGREMLINS_H_ */
diff --git a/SrcShared/CGremlinsStubs.cpp b/SrcShared/CGremlinsStubs.cpp
new file mode 100644
index 0000000..7a2e954
--- /dev/null
+++ b/SrcShared/CGremlinsStubs.cpp
@@ -0,0 +1,279 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "CGremlinsStubs.h"
+
+#include "Platform.h" // Platform::ViewDrawLine
+#include "ROMStubs.h" // EvtEnqueuePenPoint, EvtEnqueueKey
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubEnqueuePt
+// ---------------------------------------------------------------------------
+// This is a stub routine that called the application object's method that
+// enqueues a point.
+
+void StubAppEnqueuePt(const PointType* pen)
+{
+ // Make a copy of the point, as we may be munging it.
+
+ PointType pt = *pen;
+
+ // Enqueue the new pen position. We must "reverse" correct it because the
+ // Event Manager assumes that all points enqueued are raw digitizer points.
+
+ if (pt.x != -1 || pt.y != -1)
+ {
+ (void) ::PenScreenToRaw(&pt);
+ }
+
+ ::EvtEnqueuePenPoint(&pt);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubAppEnqueueKey
+// ---------------------------------------------------------------------------
+// This is a stub routine that called the Application object's method that
+// enqueues a key.
+
+void StubAppEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers)
+{
+ switch (ascii)
+ {
+ // This translates some control characters into system chars.
+ // Following is a list of such system chars and whether or
+ // now we support them specially.
+ //
+ // * = Handled here
+ // ! = Handled elsewhere
+ //
+ // * vchrLowBattery 0x0101 // Display low battery dialog
+ // vchrEnterDebugger 0x0102 // Enter Debugger
+ // * vchrNextField 0x0103 // Go to next field in form
+ // vchrStartConsole 0x0104 // Startup console task
+ //
+ // * vchrMenu 0x0105 // Ctl-A
+ // * vchrCommand 0x0106 // Ctl-C
+ // * vchrConfirm 0x0107 // Ctl-D
+ // * vchrLaunch 0x0108 // Ctl-E
+ // * vchrKeyboard 0x0109 // Ctl-F popup the keyboard in appropriate mode
+ // vchrFind 0x010A
+ // vchrCalc 0x010B
+ // * vchrPrevField 0x010C
+ // vchrAlarm 0x010D // sent before displaying an alarm
+ // vchrRonamatic 0x010E // stroke from graffiti area to top half of screen
+ // vchrGraffitiReference 0x010F // popup the Graffiti reference
+ // vchrKeyboardAlpha 0x0110 // popup the keyboard in alpha mode
+ // vchrKeyboardNumeric 0x0111 // popup the keyboard in number mode
+ // vchrLock 0x0112 // switch to the Security app and lock the device
+ // * vchrBacklight 0x0113 // toggle state of backlight
+ // * vchrAutoOff 0x0114 // power off due to inactivity timer
+ // Added for PalmOS 3.0
+ // vchrExgTest 0x0115 // put exchange Manager into test mode (&.t)
+ // vchrSendData 0x0116 // Send data if possible
+ // vchrIrReceive 0x0117 // Initiate an Ir receive manually (&.i)
+ // Added for PalmOS 3.1
+ // vchrTsm1 0x0118 // Text Services silk-screen button
+ // vchrTsm2 0x0119 // Text Services silk-screen button
+ // vchrTsm3 0x011A // Text Services silk-screen button
+ // vchrTsm4 0x011B // Text Services silk-screen button
+ // Added for PalmOS 3.2
+ // vchrRadioCoverageOK 0x011C // Radio coverage check successful
+ // vchrRadioCoverageFail 0x011D // Radio coverage check failure
+ // vchrPowerOff 0x011E // Posted after autoOffChr or hardPowerChr
+ // // to put system to sleep with SysSleep.
+ // Added for PalmOS 3.5
+ // vchrResumeSleep 0x011F // Posted by NotifyMgr clients after they
+ // // have deferred a sleep request in order
+ // // to resume it.
+ // vchrLateWakeup 0x0120 // Posted by the system after waking up
+ // // to broadcast a late wakeup notification.
+ // // FOR SYSTEM USE ONLY
+ // vchrTsmMode 0x0121 // Posted by TSM to trigger mode change.
+ // vchrBrightness 0x0122 // Activates brightness adjust dialog
+ // * vchrContrast 0x0123 // Activates contrast adjust dialog
+ // vchrExgIntData 0x01FF // Exchange Manager wakeup event
+ //
+ // The application launching buttons generate the following
+ // key codes and will also set the commandKeyMask bit in the
+ // modifiers field
+ // vchrHardKeyMin 0x0200
+ // vchrHardKeyMax 0x02FF // 256 hard keys
+ //
+ // ! vchrHard1 0x0204
+ // ! vchrHard2 0x0205
+ // ! vchrHard3 0x0206
+ // ! vchrHard4 0x0207
+ // ! vchrHardPower 0x0208
+ // vchrHardCradle 0x0209 // Button on cradle pressed
+ // vchrHardCradle2 0x020A // Button on cradle pressed and hwrDockInGeneric1
+ // // input on dock asserted (low).
+ // vchrHardContrast 0x020B // Sumo's Contrast button
+ // vchrHardAntenna 0x020C // Eleven's Antenna switch
+ // vchrHardBrightness 0x020D // Hypothetical Brightness button
+
+ case 0x01: // control-A
+ ascii = vchrMenu;
+ modifiers = commandKeyMask;
+ break;
+ case 0x02: // control-B
+ ascii = vchrLowBattery;
+ modifiers = commandKeyMask;
+ break;
+ case 0x03: // control-C
+ ascii = vchrCommand;
+ modifiers = commandKeyMask;
+ break;
+ case 0x04: // control-D
+ ascii = vchrConfirm;
+ modifiers = commandKeyMask;
+ break;
+ case 0x05: // control-E
+ ascii = vchrLaunch;
+ modifiers = commandKeyMask;
+ break;
+ case 0x06: // control-F
+ ascii = vchrKeyboard;
+ modifiers = commandKeyMask;
+ break;
+ case 0x0D: // control-M
+ ascii = chrLineFeed;
+ break;
+ case 0x0E: // control-N
+ ascii = vchrNextField;
+ modifiers = commandKeyMask;
+ break;
+ case 0x10: // control-P
+ ascii = vchrPrevField;
+ modifiers = commandKeyMask;
+ break;
+ case 0x13: // control-S
+ ascii = vchrAutoOff;
+ modifiers = commandKeyMask;
+ break;
+ case 0x14: // control-T
+ ascii = vchrHardContrast;
+ modifiers = commandKeyMask;
+ break;
+ case 0x15: // control-U
+ ascii = vchrBacklight;
+ modifiers = commandKeyMask;
+ break;
+ }
+
+
+#if 0 // Turning this bit off for now. It never worked because (a) the values
+ // assigned to "status" were incorrect (they should be correct now) and
+ // (b) they only worked for non-EZ devices. EZ devices kind of ignore
+ // the "status" parameter and probe the keyboard settings directly,
+ // something we don't handle at this point of control. So I'm turning
+ // this off and just posting the ascii keys. Since the old method
+ // never worked, then there's no issue with the Key Manager no longer
+ // doing the right thing.
+
+ // If this is one of the hard keys, send it through the Key Manager so that
+ // it can do the right things concering double-taps, etc.
+ if ((modifiers & commandKeyMask) &&
+ (ascii > hardKeyMin || (ascii == pageUpChr) || (ascii == pageDownChr)))
+ {
+
+ DWord status = 0;
+
+ switch (ascii)
+ {
+ case hardPowerChr: status = hwr328IntLoInt0; break;
+ case pageUpChr: status = hwr328IntLoInt1; break;
+ case pageDownChr: status = hwr328IntLoInt2; break;
+ case hard1Chr: status = hwr328IntLoInt3; break;
+ case hard2Chr: status = hwr328IntLoInt4; break;
+ case hard3Chr: status = hwr328IntLoInt5; break;
+ case hard4Chr: status = hwr328IntLoInt6; break;
+ case hardCradleChr: status = hwr328IntHiIRQ1 << 16; break;
+ case hardAntennaChr: status = hwr328IntHiIRQ2 << 16; break;
+ }
+
+ // I'm dubious that this is the correct thing to do in the emulator.
+ // This is an interrupt routine that we're calling directly. But
+ // what if a "real" interrupt is triggered from some other source
+ // while this call is executing (for instance, the user clicks on
+ // one of the "keyboard buttons", thus generating a keyboard
+ // interrupt)? It's possible that the two will stomp on each other.
+ // The best thing to do is to post events the emulator way.
+ // However, I'm hard-pressed to do that. That would require calling
+ // Hardware_ButtonEvent twice (once to signal the keyboard
+ // interrupt, and another to clear it), but I don't know how to give
+ // the processor time in between to respond to the first call.
+
+ if (status != 0)
+ ::KeyHandleInterrupt (false, status);
+ }
+
+ // For other keys, enqueue them directly.
+ else
+#endif
+ {
+ ::EvtEnqueueKey (ascii, keycode, modifiers);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubAppGremlinsOn
+// ---------------------------------------------------------------------------
+// Stub routine that update the Gremlins menu an the global variable the
+// keeps track of the ????
+
+void StubAppGremlinsOn (void)
+{
+ // Called from Gremlins::Initialize.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubAppGremlinsOff
+// ---------------------------------------------------------------------------
+// Stub routine that update the Gremlins menu an the global variable the
+// keeps track of the ????
+
+void StubAppGremlinsOff (void)
+{
+ // Called by Gremlins when counter > until.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubViewDrawLine
+// ---------------------------------------------------------------------------
+// This is a stub routine that called the View object's method that draw
+// a line.
+
+void StubViewDrawLine (int xStart, int yStart, int xEnd, int yEnd)
+{
+ Platform::ViewDrawLine (xStart, yStart, xEnd, yEnd);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubViewDrawPixel
+// ---------------------------------------------------------------------------
+// This is a stub routine that called the View object's method that draw
+// a pixel.
+
+void StubViewDrawPixel (int xPos, int yPos)
+{
+ Platform::ViewDrawPixel (xPos, yPos);
+}
+
+
diff --git a/SrcShared/CGremlinsStubs.h b/SrcShared/CGremlinsStubs.h
new file mode 100644
index 0000000..fd4da59
--- /dev/null
+++ b/SrcShared/CGremlinsStubs.h
@@ -0,0 +1,39 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef __GREMLINSSTUBS_H__
+#define __GREMLINSSTUBS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern void StubAppEnqueuePt(const PointType* pen);
+
+extern void StubAppEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers);
+
+extern void StubAppGremlinsOn (void);
+
+extern void StubAppGremlinsOff (void);
+
+extern void StubViewDrawLine (int xStart, int yStart, int xEnd, int yEnd);
+
+extern void StubViewDrawPixel (int xPos, int yPos);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __GREMLINSSTUBS_H__
diff --git a/SrcShared/ChunkFile.cpp b/SrcShared/ChunkFile.cpp
new file mode 100644
index 0000000..620d97d
--- /dev/null
+++ b/SrcShared/ChunkFile.cpp
@@ -0,0 +1,830 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "ChunkFile.h"
+
+#include "Byteswapping.h" // Canonical
+#include "Platform.h" // ReallocMemory
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile constructor
+ *
+ * DESCRIPTION: Initialize the ChunkFile object. Sets the fStream data
+ * member to refer to the given EmStream (which must
+ * exist for the life of the ChunkFile).
+ *
+ * PARAMETERS: s - EmStream to utilize for read/write operations.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+ChunkFile::ChunkFile (EmStream& s) :
+ fStream (s)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile destructor
+ *
+ * DESCRIPTION: Releases ChunkFile resources. Currently does nothing.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+ChunkFile::~ChunkFile (void)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::FindChunk
+ *
+ * DESCRIPTION: Find the requested chunk. If successful, the file
+ * marker will be pointing to the chunk data which can
+ * then be read with ReadChunk.
+ *
+ * PARAMETERS: targetTag - the tag of the chunk to find.
+ *
+ * RETURNED: Size of the chunk, in bytes. If the chunk can't be
+ * found, kChunkNotFound is returned.
+ *
+ ***********************************************************************/
+
+long ChunkFile::FindChunk (Tag targetTag)
+{
+ long len = kChunkNotFound;
+ long fileOffset = 0;
+ long fileLength = fStream.GetLength ();
+
+ fStream.SetMarker (fileOffset, kStreamFromStart);
+
+ while (fileOffset < fileLength)
+ {
+ Tag chunkTag;
+ long chunkLen;
+
+ fStream.GetBytes (&chunkTag, sizeof (chunkTag));
+ fStream.GetBytes (&chunkLen, sizeof (chunkLen));
+
+ Canonical (chunkTag);
+ Canonical (chunkLen);
+
+ if (chunkTag == targetTag)
+ {
+ len = chunkLen;
+ break;
+ }
+
+ fStream.SetMarker (chunkLen, kStreamFromMarker);
+ fileOffset += sizeof (chunkTag) + sizeof (chunkLen) + chunkLen;
+ }
+
+ return len;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Find the requested chunk. If successful, the file
+ * marker will be pointing to the chunk data which can
+ * then be read with ReadChunk.
+ *
+ * PARAMETERS: targetTag - the tag of the chunk to find.
+ *
+ * RETURNED: Size of the chunk, in bytes. If the chunk can't be
+ * found, kChunkNotFound is returned.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadChunk (int index, Tag& tag, Chunk& chunk)
+{
+ long fileOffset = 0;
+ long fileLength = fStream.GetLength ();
+
+ fStream.SetMarker (fileOffset, kStreamFromStart);
+
+ while (fileOffset < fileLength)
+ {
+ // Read the chunk's tag and length.
+
+ Tag chunkTag;
+ long chunkLen;
+
+ fStream.GetBytes (&chunkTag, sizeof (chunkTag));
+ fStream.GetBytes (&chunkLen, sizeof (chunkLen));
+
+ Canonical (chunkTag);
+ Canonical (chunkLen);
+
+ // If this is the chunk we're looking for, read it in.
+
+ if (index == 0)
+ {
+ tag = chunkTag;
+ chunk.SetLength (chunkLen);
+ this->ReadChunk (chunkLen, chunk.GetPointer ());
+
+ // Return that we found the chunk.
+
+ return true;
+ }
+
+ // Move to the next chunk.
+
+ fStream.SetMarker (chunkLen, kStreamFromMarker);
+ fileOffset += sizeof (chunkTag) + sizeof (chunkLen) + chunkLen;
+ --index;
+ }
+
+ // Return that we didn't find the chunk.
+
+ return false;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Read a block of bytes into the given buffer.
+ *
+ * PARAMETERS: tag - marker identifying the data to read.
+ *
+ * chunk - object to contain the returned data.
+ *
+ * RETURNED: True if the data was found and read in.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadChunk (Tag tag, Chunk& chunk)
+{
+ long size = this->FindChunk (tag);
+
+ if (size == kChunkNotFound)
+ return false;
+
+ chunk.SetLength (size);
+ this->ReadChunk (size, chunk.GetPointer ());
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadInt
+ *
+ * DESCRIPTION: Read an integer (scalar) from the file.
+ *
+ * PARAMETERS: tag - marker of the value to be read.
+ *
+ * val - reference to variable to receive the integer.
+ *
+ * RETURNED: True if the value existed; false if the tag could not
+ * be found.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadInt (Tag tag, uint8& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int8& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, uint16& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int16& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, uint32& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int32& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadString
+ *
+ * DESCRIPTION: Read a string from the file.
+ *
+ * PARAMETERS: tag - marker of the string to be read.
+ *
+ * s - reference to variable to receive the string.
+ *
+ * RETURNED: True if the string existed; false if the tag could not
+ * be found.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadString (Tag tag, char* s)
+{
+ long len = ChunkFile::FindChunk (tag);
+ if (len == kChunkNotFound)
+ return false;
+
+ if (len > 0)
+ {
+ ChunkFile::ReadChunk (len, s);
+ }
+
+ s[len] = '\0'; // Null terminator
+
+ return true;
+}
+
+Bool ChunkFile::ReadString (Tag tag, string& s)
+{
+ long len = ChunkFile::FindChunk (tag);
+ if (len == kChunkNotFound)
+ return false;
+
+ s.resize (len);
+ if (len > 0)
+ {
+ ChunkFile::ReadChunk (len, &s[0]);
+ }
+
+ return true;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteChunk
+ *
+ * DESCRIPTION: Write the given data to the file. The data is marked
+ * with the given tag. No effort is made to find any
+ * existing chunks with the same tag and deleting them.
+ *
+ * PARAMETERS: tag - marker for the data being written.
+ *
+ * chunk - object containing the data to write.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteChunk (Tag tag, const Chunk& chunk)
+{
+ this->WriteChunk (tag, chunk.GetLength (), chunk.GetPointer ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteInt
+ *
+ * DESCRIPTION: Write the given value to disk, marking it with the
+ * given tag.
+ *
+ * PARAMETERS: tag - marker used to later retrieve the value.
+ *
+ * val - integer to write to disk. All integers are
+ * stored in Big Endian format, and are written in
+ * their native size (1, 2, or 4 bytes).
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteInt (Tag tag, uint8 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int8 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, uint16 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int16 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, uint32 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int32 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteString
+ *
+ * DESCRIPTION: Write the given string to disk, marking it with the
+ * given tag.
+ *
+ * PARAMETERS: tag - marker used to later retrieve the value.
+ *
+ * s - string to write to disk.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteString (Tag tag, const char* s)
+{
+ ChunkFile::WriteChunk (tag, strlen (s), s);
+}
+
+void ChunkFile::WriteString (Tag tag, const string& s)
+{
+ ChunkFile::WriteChunk (tag, s.size (), s.c_str ());
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Read a block of bytes into the given buffer
+ *
+ * PARAMETERS: size - number of bytes to read.
+ *
+ * data - buffer to write the bytes to.
+ *
+ * RETURNED: Nothing (exceptions can be thrown).
+ *
+ ***********************************************************************/
+
+void ChunkFile::ReadChunk (uint32 size, void* data)
+{
+ // Merely read the requested bytes starting at the current location.
+
+ fStream.GetBytes (data, size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteChunk
+ *
+ * DESCRIPTION: Write the given data to the file. The data is marked
+ * with the given tag. No effort is made to find any
+ * existing chunks with the same tag and deleting them.
+ *
+ * PARAMETERS: tag - marker for the data being written.
+ *
+ * size - number of bytes to write.
+ *
+ * data - pointer to buffer containing bytes to write.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteChunk (Tag tag, uint32 size, const void* data)
+{
+ // Write the 4-byte tag in Big Endian format.
+
+ Canonical (tag);
+ fStream.PutBytes (&tag, sizeof (tag));
+
+ // Write the chunk size in Big Endian format. Return the size
+ // back to host format when done so that it can be used to write
+ // the actual data.
+
+ Canonical (size);
+ fStream.PutBytes (&size, sizeof (size));
+ Canonical (size);
+
+ // Write the chunk data.
+
+ fStream.PutBytes (data, size);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::GetFile
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmStream& ChunkFile::GetStream (void) const
+{
+ return fStream;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Default constructor. Creates a "chunk" that initially
+ * has no memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+Chunk::Chunk (void) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Parameterized constructor. Creates a "chunk" with a
+ * block of memory with the given length.
+ *
+ * PARAMETERS: inLength - number of bytes for the initial block of
+ * memory.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::Chunk (long inLength) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+ SetLength (inLength);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Copy constructor. Creates a "chunk" containing a copy
+ * of the given data.
+ *
+ * PARAMETERS: other - chunk containing the data to copy.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::Chunk (const Chunk& other) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+ this->SetLength (other.GetLength ());
+ memcpy (this->GetPointer (), other.GetPointer (), other.GetLength ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::~Chunk
+ *
+ * DESCRIPTION: Destructor. Disposes of the owned block of memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::~Chunk (void)
+{
+ Platform::DisposeMemory (fPtr);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::operator=
+ *
+ * DESCRIPTION: Assignment operator. Makes the controlled chunk
+ * contain a copy of the data managed by the other chunk.
+ *
+ * PARAMETERS: other - chunk containing the data to copy.
+ *
+ * RETURNED: Referenced to the controlled object.
+ *
+ ***********************************************************************/
+
+Chunk& Chunk::operator= (const Chunk& other)
+{
+ if (this != &other)
+ {
+ this->SetLength (other.GetLength ());
+ memcpy (this->GetPointer (), other.GetPointer (), other.GetLength ());
+ }
+
+ return *this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::GetPointer
+ *
+ * DESCRIPTION: Returns a pointer to the owned block of memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: A pointer to the owned block of memory.
+ *
+ ***********************************************************************/
+
+void* Chunk::GetPointer (void) const
+{
+ return fPtr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::GetLength
+ *
+ * DESCRIPTION: Returns the number of useable bytes in the block of
+ * memory. The actual number of allocated bytes may be
+ * larger, but shouldn't be used.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The number of usable bytes in the chunk.
+ *
+ ***********************************************************************/
+
+long Chunk::GetLength (void) const
+{
+ return fUsedSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::SetLength
+ *
+ * DESCRIPTION: Set the number of useable bytes in the owned block of
+ * memory. The number of bytes actually allocated may
+ * be greater than passed in. After this call, any
+ * previous pointers returned by GetPointer may be
+ * invalid.
+ *
+ * PARAMETERS: inLength - the number of useable bytes to make available.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Chunk::SetLength (long inLength)
+{
+ if (inLength > fAllocatedSize)
+ {
+ const long kSlushFund = 100;
+ long newAllocatedLength = inLength + kSlushFund;
+ fPtr = Platform::ReallocMemory (fPtr, newAllocatedLength);
+ fAllocatedSize = newAllocatedLength;
+ }
+
+ // As a special case, allow the clean up of memory by setting the
+ // length to zero.
+
+ else if (inLength == 0)
+ {
+ Platform::DisposeMemory (fPtr);
+ fAllocatedSize = 0;
+ }
+
+ fUsedSize = inLength;
+}
+
+
+// ===========================================================================
+// EmStreamChunk.cpp
+// ===========================================================================
+//
+// A Stream whose bytes are in a Chunk
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmStreamChunk(Handle) Parameterized Constructor [public]
+// ---------------------------------------------------------------------------
+// Construct from an existing Chunk
+
+EmStreamChunk::EmStreamChunk(Chunk* chunk) :
+ EmStream (),
+ fChunk (*chunk),
+ fOwnedChunk (chunk)
+{
+ EmStream::SetLength (fChunk.GetLength ());
+}
+
+
+EmStreamChunk::EmStreamChunk(Chunk& chunk) :
+ EmStream (),
+ fChunk (chunk),
+ fOwnedChunk (NULL)
+{
+ EmStream::SetLength (fChunk.GetLength ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ~EmStreamChunk Destructor [public]
+// ---------------------------------------------------------------------------
+
+EmStreamChunk::~EmStreamChunk()
+{
+ delete fOwnedChunk;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SetLength [public]
+// ---------------------------------------------------------------------------
+// Set the length, in bytes, of the EmStreamChunk
+
+void
+EmStreamChunk::SetLength(
+ int32 inLength)
+{
+ fChunk.SetLength (inLength);
+ EmStream::SetLength (inLength);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PutBytes
+// ---------------------------------------------------------------------------
+// Write bytes from a buffer to a EmStreamChunk
+//
+// Returns an error code and passes back the number of bytes actually
+// written, which may be less than the number requested if an error occurred.
+//
+// Grows data Chunk if necessary.
+
+ErrCode
+EmStreamChunk::PutBytes(
+ const void *inBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ int32 endOfWrite = GetMarker () + ioByteCount;
+
+ if (endOfWrite > GetLength ()) // Need to grow Chunk
+ {
+ SetLength (endOfWrite);
+ }
+ // Copy bytes into Chunk
+ if (ioByteCount > 0)
+ {
+ memmove ((char*) fChunk.GetPointer () + GetMarker (), inBuffer, ioByteCount);
+ SetMarker (ioByteCount, kStreamFromMarker);
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetBytes
+// ---------------------------------------------------------------------------
+// Read bytes from a EmStreamChunk to a buffer
+//
+// Returns an error code and passes back the number of bytes actually
+// read, which may be less than the number requested if an error occurred.
+//
+// Errors:
+// readErr Attempt to read past the end of the EmStreamChunk
+
+ErrCode
+EmStreamChunk::GetBytes(
+ void *outBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ // Upper bound is number of bytes from
+ // marker to end
+ if ((GetMarker () + ioByteCount) > GetLength ())
+ {
+ ioByteCount = GetLength () - GetMarker ();
+ err = 1;
+ }
+ // Copy bytes from Handle into buffer
+
+ memmove (outBuffer, (char*) fChunk.GetPointer () + GetMarker (), ioByteCount);
+ SetMarker (ioByteCount, kStreamFromMarker);
+
+ return err;
+}
diff --git a/SrcShared/ChunkFile.h b/SrcShared/ChunkFile.h
new file mode 100644
index 0000000..0f03dde
--- /dev/null
+++ b/SrcShared/ChunkFile.h
@@ -0,0 +1,131 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _CHUNKFILE_H_
+#define _CHUNKFILE_H_
+
+#include "EmStream.h" // EmStream
+
+class Chunk;
+
+
+/*
+ ChunkFile is a class for managing files containing tagged
+ chunks of data. It contain member functions for writing
+ tagged data to a file, finding that data later, and reading
+ the data back into user-specified buffers. There are also
+ member functions for writing common data types (numbers and
+ strings) in a platform-independent fashion.
+
+ There is no facility for *updating* chunk files. That is,
+ there is no way to modify the contents of a chunk that already
+ exists in a a chunk file (regardless of whether or not the
+ length of the chunk changes).
+
+ The format of a chunk file is simple. It's essentially a
+ variable-length array of:
+
+ tag: 4 bytes
+ size: 4 bytes
+ data: "size" bytes of data
+
+ "tag", "size", and any integer values written with WriteInt
+ are stored in Big Endian format. Strings are stored without
+ the NULL terminator. Data is packed as tightly as possible;
+ there's no word or longword alignment.
+ */
+
+class ChunkFile
+{
+ public:
+ ChunkFile (EmStream& s);
+ ~ChunkFile (void);
+
+ typedef uint32 Tag;
+
+// static const long kChunkNotFound = -1; // VC++ is a bit medieval here...
+ enum { kChunkNotFound = -1 };
+ long FindChunk (Tag tag); // Returns chunk size
+
+ Bool ReadChunk (int index, Tag& tag, Chunk&);
+ Bool ReadChunk (Tag tag, Chunk&);
+ void ReadChunk (uint32 size, void* data);
+ Bool ReadInt (Tag tag, uint8&);
+ Bool ReadInt (Tag tag, int8&);
+ Bool ReadInt (Tag tag, uint16&);
+ Bool ReadInt (Tag tag, int16&);
+ Bool ReadInt (Tag tag, uint32&);
+ Bool ReadInt (Tag tag, int32&);
+ Bool ReadString (Tag tag, char*);
+ Bool ReadString (Tag tag, string&);
+
+ void WriteChunk (Tag tag, const Chunk&);
+ void WriteChunk (Tag tag, uint32 size, const void* data);
+ void WriteInt (Tag tag, uint8);
+ void WriteInt (Tag tag, int8);
+ void WriteInt (Tag tag, uint16);
+ void WriteInt (Tag tag, int16);
+ void WriteInt (Tag tag, uint32);
+ void WriteInt (Tag tag, int32);
+ void WriteString (Tag tag, const char*);
+ void WriteString (Tag tag, const string&);
+
+ EmStream& GetStream (void) const;
+
+ private:
+ EmStream& fStream;
+};
+
+
+class Chunk
+{
+ public:
+ Chunk (void);
+ Chunk (long inLength);
+ Chunk (const Chunk&);
+ ~Chunk (void);
+
+ Chunk& operator= (const Chunk&);
+
+ void* GetPointer (void) const;
+ long GetLength (void) const;
+ void SetLength (long inLength);
+
+ private:
+ void* fPtr;
+ long fUsedSize;
+ long fAllocatedSize;
+};
+
+
+class EmStreamChunk : public EmStream
+{
+ public:
+ EmStreamChunk (Chunk*);
+ EmStreamChunk (Chunk&);
+ virtual ~EmStreamChunk (void);
+
+ virtual void SetLength (int32 inLength);
+
+ virtual ErrCode PutBytes (const void* inBuffer,
+ int32 ioByteCount);
+ virtual ErrCode GetBytes (void* outBuffer,
+ int32 ioByteCount);
+
+ private:
+ Chunk& fChunk;
+ Chunk* fOwnedChunk;
+};
+
+
+#endif // _CHUNKFILE_H_
diff --git a/SrcShared/DebugMgr.cpp b/SrcShared/DebugMgr.cpp
new file mode 100644
index 0000000..91b74db
--- /dev/null
+++ b/SrcShared/DebugMgr.cpp
@@ -0,0 +1,2098 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Includes
+// ---------------------------------------------------------------------------
+
+#include "EmCommon.h"
+#include "DebugMgr.h"
+
+#include "EmCPU68K.h" // gCPU68K
+#include "EmErrCodes.h" // kError_NoError
+#include "EmException.h" // EmExceptionReset
+#include "EmHAL.h" // EmHAL
+#include "EmLowMem.h" // LowMem_SetGlobal, LowMem_GetGlobal
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmPalmFunction.h" // SysTrapIndex, IsSystemTrap
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmSession.h" // EmSessionStopper, SuspendByDebugger
+#include "ErrorHandling.h" // ReportUnhandledException
+#include "Logging.h" // gErrLog
+#include "MetaMemory.h" // MetaMemory::MarkInstructionBreak
+#include "Platform.h" // Platform::SendPacket
+#include "ROMStubs.h" // FtrSet, FtrUnregister
+#include "SessionFile.h" // SessionFile
+#include "SLP.h" // SLP::EventCallback
+#include "SocketMessaging.h" // CSocket::Write
+#include "Strings.r.h" // kStr_ values
+#include "SystemPacket.h" // SystemPacket::
+#include "UAE.h" // m68k_areg, m68k_dreg, etc.
+
+#include "ctype.h" // isspace, isdigit, isxdigit
+
+
+#define PRINTF if (!LogHLDebugger ()) ; else LogAppendMsg
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Types
+// ---------------------------------------------------------------------------
+
+struct NamedConditionType
+{
+ const char* name;
+ compareFun function;
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Functions
+// ---------------------------------------------------------------------------
+
+static uint32 PrvGetAddressRegister (int num);
+static uint32 PrvGetDataRegister (int num);
+static Bool PrvBPEquals (uint32 a, uint32 b);
+static Bool PrvBPNotEquals (uint32 a, uint32 b);
+static Bool PrvBPGreater (uint32 a, uint32 b);
+static Bool PrvBPGreaterOrEqual (uint32 a, uint32 b);
+static Bool PrvBPLess (uint32 a, uint32 b);
+static Bool PrvBPLessOrEqual (uint32 a, uint32 b);
+static const char* PrvSkipWhite (const char* p);
+
+static Bool PrvParseDecimal (const char **ps, int *i);
+static Bool PrvParseUnsigned (const char **ps, uint32 *u);
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Constants
+// ---------------------------------------------------------------------------
+
+#define kOpcode_ADD 0x0697 // ADD.L X, (A7)
+#define kOpcode_LINK 0x4E50
+#define kOpcode_RTE 0x4E73
+#define kOpcode_RTD 0x4E74
+#define kOpcode_RTS 0x4E75
+#define kOpcode_JMP 0x4ED0
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Variables
+// ---------------------------------------------------------------------------
+
+// ----- Saved variables -----------------------------------------------------
+
+DebugGlobalsType gDebuggerGlobals;
+
+
+// ----- UnSaved variables ---------------------------------------------------
+
+static NamedConditionType kConditions[] =
+{
+ {"==", &PrvBPEquals},
+ {"!=", &PrvBPNotEquals},
+ {">", &PrvBPGreater},
+ {">=", &PrvBPGreaterOrEqual},
+ {"<", &PrvBPLess},
+ {"<=", &PrvBPLessOrEqual},
+ {NULL, NULL}
+};
+
+emuptr gExceptionAddress;
+int gExceptionSize;
+Bool gExceptionForRead;
+
+
+// If we're listening for a debugger connection, the first three sockets
+// contain references to those listening entities. As soon as a connection
+// is made, we set gConnectedDebugSocket and NULL out the other three,
+// deleting any listening sockets that are no longer needed.
+
+static CSocket* gDebuggerSocket1; // TCP socket on user-defined port
+static CSocket* gDebuggerSocket2; // TCP socket on port 2000
+static CSocket* gDebuggerSocket3; // Platform-specific socket
+static CTCPSocket* gConnectedDebugSocket;
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ Debug
+// ===========================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Startup
+ *
+ * DESCRIPTION: Create all the sockets we'll need for the application
+ * and start them listening for clients. Call this once
+ * at application startup.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Startup (void)
+{
+ Debug::CreateListeningSockets ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Shutdown
+ *
+ * DESCRIPTION: Delete the sockets we use. CSocket::Shutdown would do
+ * this anyway, but it's a good idea to do it here, too,
+ * so as to drop the references in our global variables.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Shutdown (void)
+{
+ Debug::DeleteListeningSockets ();
+
+ if (gConnectedDebugSocket)
+ {
+ gConnectedDebugSocket->Close ();
+ delete gConnectedDebugSocket;
+ gConnectedDebugSocket = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::ConnectedToTCPDebugger
+ *
+ * DESCRIPTION: Return whether or not we're connected to a debugger (or
+ * reasonably think so; we don't check for aborted
+ * or broken connections). This function is called during
+ * Palm OS bootup to determine if the 'gdbS' feature needs
+ * to be installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if we were connected to a debugger the last time
+ * we checked.
+ *
+ ***********************************************************************/
+
+Bool Debug::ConnectedToTCPDebugger (void)
+{
+ return Debug::GetTCPDebuggerSocket () != NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::GetTCPDebuggerSocket
+ *
+ * DESCRIPTION: Return the socket that's connected to the debugger (if
+ * any).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The pointer to the CSocket object connected to an
+ * external debugger. Returns NULL if not connected to
+ * a debugger.
+ *
+ ***********************************************************************/
+
+CTCPSocket* Debug::GetTCPDebuggerSocket (void)
+{
+ return gConnectedDebugSocket;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::GetDebuggerSocket
+ *
+ * DESCRIPTION: Return the socket that's connected to the debugger (if
+ * any).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The pointer to the CSocket object connected to an
+ * external debugger. Returns NULL if not connected to
+ * a debugger.
+ *
+ ***********************************************************************/
+
+CSocket* Debug::GetDebuggerSocket (void)
+{
+ // Get the preferred (TCP) socket.
+
+ CSocket* s = Debug::GetTCPDebuggerSocket ();
+
+ // If we don't have one (we're not connected via such a socket),
+ // try the backward-compatible, platform-specific socket.
+
+ if (s == NULL)
+ s = gDebuggerSocket3;
+
+ // If we finally have a socket, return it.
+
+ return s;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+/*-----------------------------------------------------------------------------------*\
+
+ Notes on side-stepping the ROM debugger:
+
+ The debugger manipulates the following low-memory globals:
+
+ Byte dbgWasEntered; // set true the first time debugger is entered
+ Byte dbgInDebugger; // true if in debugger
+ Byte dbgTracing; // tracing in debugger
+ Ptr dbgGlobalsP; // pointer to dbgGlobals
+ Ptr dbgSerGlobalsP; // pointer to Debugger Serial globals
+
+ We set dbgWasEntered and dbgInDebugger in EnterDebugger. We clear
+ dbgInDebugger in ExitDebugger. Both of these values are examined by
+ other parts of the ROM.
+
+ dbgTracing is set when the ROM debugger needs to single step. It needs
+ to single-step if there are breakpoints in the ROM, or if we need to
+ execute over an installed breakpoint. We have other ways to do these
+ (we can actually install breakpoints into the ROM, and our CPU loop has
+ a mechanism for fetching the opcode that is currently overwritten by
+ a breakpoint), so we never have to set dbgTracing to true.
+
+ dbgGlobalsP appears to be accessed only by the ROM debugger code. Since
+ we should intercept everything that would cause that code to be accessed,
+ we shouldn't have to do anything with that block.
+
+ dbgSerGlobalsP is initialized by DbgInit. None of the ROM debugger code
+ looks at it. Only the serial code does.
+
+ May want to patch the following traps:
+
+ ConGetS
+ ConPutS
+
+ sysTrapDbgSrcMessage
+ sysTrapDbgMessage
+ sysTrapDbgGetMessage
+ sysTrapDbgCommSettings
+
+\*-----------------------------------------------------------------------------------*/
+
+void Debug::Initialize (void)
+{
+ memset (&gDebuggerGlobals, 0, sizeof (gDebuggerGlobals));
+
+ EmAssert (gSession);
+ gSession->AddInstructionBreakHandlers (
+ InstallInstructionBreaks,
+ RemoveInstructionBreaks,
+ HandleInstructionBreak);
+
+ // Install functions that will cause the CPU loop to exit if we're
+ // connected to an external debugger.
+
+ EmAssert (gCPU68K);
+
+ gCPU68K->InstallHookException (kException_BusErr, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_AddressErr, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_IllegalInstr, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_DivideByZero, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Chk, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Privilege, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trace, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_ATrap, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_FTrap, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_AutoVec7, Debug::BreakIfConnected);
+
+ gCPU68K->InstallHookException (kException_SoftBreak, Debug::BreakIfConnected);
+ // Handspring implements this one.
+// gCPU68K->InstallHookException (kException_Trap1, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap2, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap3, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap4, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap5, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap6, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap7, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap9, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap10, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap11, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap13, Debug::BreakIfConnected);
+ gCPU68K->InstallHookException (kException_Trap14, Debug::BreakIfConnected);
+
+ // This one's a little different. We want to exit the CPU loop
+ // on a TRAP 8, but we want to do it conditionally. If desired,
+ // HandleTrap8 will cause the CPU loop to exit (leaving the PC just
+ // after the TRAP instruction). Otherwise, it will treat the TRAP
+ // like a NOP.
+
+ gCPU68K->InstallHookException (kException_HardBreak, Debug::HandleTrap8);
+
+#if 0 // !!! TBD
+
+ // Install Debugger Traps into trap table
+ dispatchTableP[ SysTrapIndex (sysTrapDbgSrcMessage) ] = (Ptr)DbgMessage;
+ dispatchTableP[ SysTrapIndex (sysTrapDbgMessage) ] = (Ptr)DbgMessage;
+ dispatchTableP[ SysTrapIndex (sysTrapDbgGetMessage) ] = (Ptr)DbgGetMessage;
+ dispatchTableP[ SysTrapIndex (sysTrapDbgCommSettings) ] = (Ptr)DbgCommSettings;
+
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Reset (void)
+{
+ gDebuggerGlobals.firstEntrance = true;
+
+ // Set flags that we're no longer in the debugger. This is the same
+ // as the last few steps of ExitDebugger.
+
+ gDebuggerGlobals.excType = 0;
+ EmLowMem_SetGlobal (dbgInDebugger, false);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Save (SessionFile& f)
+{
+ const long kCurrentVersion = 1;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ s << (bool) false; // inDebugger
+ s << gDebuggerGlobals.ignoreDbgBreaks;
+ s << (bool) false; // reEntered
+ s << gDebuggerGlobals.firstEntrance;
+ s << gDebuggerGlobals.stepSpy;
+ s << gDebuggerGlobals.breakingOnATrap;
+ s << gDebuggerGlobals.continueOverATrap;
+ s << gDebuggerGlobals.continueOverBP;
+
+ s << gDebuggerGlobals.checkTrapWordOnExit;
+ s << gDebuggerGlobals.trapWord;
+ s << gDebuggerGlobals.refNum;
+
+ int ii;
+ for (ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ s << (emuptr) gDebuggerGlobals.bp[ii].addr;
+ s << gDebuggerGlobals.bp[ii].enabled;
+ s << gDebuggerGlobals.bp[ii].installed;
+
+ s << (uint16) 0; // gDebuggerGlobals.bpOpcode[ii];
+
+ if (gDebuggerGlobals.bpCondition[ii])
+ {
+ // Save only the source string; we can reconstruct
+ // the rest of the fields from that.
+
+ s << gDebuggerGlobals.bpCondition[ii]->source;
+ }
+ else
+ {
+ s << "";
+ }
+ }
+
+ for (ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ s << gDebuggerGlobals.trapBreak[ii];
+ s << gDebuggerGlobals.trapParam[ii];
+ }
+
+ s << gDebuggerGlobals.ssAddr;
+ s << gDebuggerGlobals.ssValue;
+
+ s << gDebuggerGlobals.excType;
+
+ s << gDebuggerGlobals.watchEnabled;
+ s << gDebuggerGlobals.watchAddr;
+ s << gDebuggerGlobals.watchBytes;
+
+ f.WriteDebugInfo (chunk);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Load (SessionFile& f)
+{
+ // Delete any old state.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ Debug::DeleteBreakpointCondition (ii);
+ }
+
+ // Load the new state.
+
+ Chunk chunk;
+ if (f.ReadDebugInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ bool dummyBool;
+ uint16 dummyShort;
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> dummyBool; // inDebugger
+ s >> gDebuggerGlobals.ignoreDbgBreaks;
+ s >> dummyBool; // reEntered
+ s >> gDebuggerGlobals.firstEntrance;
+ s >> gDebuggerGlobals.stepSpy;
+ s >> gDebuggerGlobals.breakingOnATrap;
+ s >> gDebuggerGlobals.continueOverATrap;
+ s >> gDebuggerGlobals.continueOverBP;
+
+ s >> gDebuggerGlobals.checkTrapWordOnExit;
+ s >> gDebuggerGlobals.trapWord;
+ s >> gDebuggerGlobals.refNum;
+
+ int ii;
+ for (ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ emuptr temp;
+ s >> temp; gDebuggerGlobals.bp[ii].addr = (MemPtr) temp;
+ s >> gDebuggerGlobals.bp[ii].enabled;
+ s >> gDebuggerGlobals.bp[ii].installed;
+
+ s >> dummyShort; // gDebuggerGlobals.bpOpcode[ii];
+
+ string source;
+ s >> source;
+
+ if (source.size () > 0)
+ {
+ BreakpointCondition* bc = NewBreakpointCondition (source.c_str ());
+ gDebuggerGlobals.bpCondition[ii] = bc;
+ }
+ }
+
+ for (ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ s >> gDebuggerGlobals.trapBreak[ii];
+ s >> gDebuggerGlobals.trapParam[ii];
+ }
+
+ s >> gDebuggerGlobals.ssAddr;
+ s >> gDebuggerGlobals.ssValue;
+
+ s >> gDebuggerGlobals.excType;
+
+ s >> gDebuggerGlobals.watchEnabled;
+ s >> gDebuggerGlobals.watchAddr;
+ s >> gDebuggerGlobals.watchBytes;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::Dispose (void)
+{
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ Debug::DeleteBreakpointCondition (ii);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::HandleNewPacket
+ *
+ * DESCRIPTION: Completely handle a packet sent from an external
+ * debugger, setting any state and sending a reply if
+ * necessary.
+ *
+ * PARAMETERS: slp - a reference to a SerialLink Protocol object that
+ * contains the packet information and the horse...uh,
+ * socket it rode in on.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode Debug::HandleNewPacket (SLP& slp)
+{
+ ErrCode result = kError_NoError;
+
+ PRINTF ("Entering Debug::HandleNewPacket.");
+
+ const EmProxySlkPktHeaderType& header = slp.Header ();
+ const EmProxySysPktBodyType& body = slp.Body ();
+// const EmProxySlkPktFooterType& footer = slp.Footer ();
+
+ EmAssert ((header.dest == slkSocketDebugger) || (header.dest == slkSocketConsole));
+
+ // If the packet is for the debugger socket, then we pretty much need
+ // to have the CPU stopped. If not, when the PalmDebugger user executes
+ // "g", the restored registers may not be what the machine expects.
+ //
+ // As a courtesy, we stop the CPU if we get a "state" packet. That way,
+ // the user can enter the debugger by typing "att" in the PalmDebugger and
+ // doesn't have to fuss with shortcut-.1.
+ //
+ // Otherwise, we ignore the packet.
+
+ if (header.dest == slkSocketDebugger)
+ {
+ EmSuspendState state = gSession->GetSuspendState ();
+ if (!state.fCounters.fSuspendByDebugger)
+ {
+ if (body.command == sysPktStateCmd)
+ {
+ // This will send the state packet as well as set our
+ // "in the debugger" state.
+
+ result = Debug::EnterDebugger (kException_SoftBreak, &slp);
+ goto Exit;
+ }
+
+ PRINTF ("Packet is for the debugger, we're not in debug mode, and the packet is not a state command; leaving Debug::HandleNewPacket.");
+
+ // This packet is for the debugger socket, we're not in the
+ // debugger, and the packet is not a "state" command, so just
+ // ignore this request.
+
+ goto Exit;
+ }
+ }
+
+ {
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // Goose the ROM, so it doesn't go to sleep while we're exchanging packets.
+ // Do this by hand; we can't call ROM functions as subroutines while in
+ // the debugger (we don't know what state the ROM is in).
+
+ // EvtResetAutoOffTimer ();
+ EmLowMem_SetGlobal (sysAutoOffEvtTicks, EmLowMem_GetGlobal (hwrCurTicks));
+
+ switch (body.command)
+ {
+ case sysPktStateCmd:
+ result = SystemPacket::SendState (slp);
+ break;
+
+ case sysPktReadMemCmd:
+ result = SystemPacket::ReadMem (slp);
+ break;
+
+ case sysPktWriteMemCmd:
+ result = SystemPacket::WriteMem (slp);
+ break;
+
+ case sysPktSingleStepCmd:
+ // I don't think there's anything to do here. I think that
+ // single-stepping is performed by the debugger setting the
+ // trace bit in the SR and sending a sysPktContinueCmd.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktGetRtnNameCmd:
+ result = SystemPacket::SendRoutineName (slp);
+ break;
+
+ case sysPktReadRegsCmd:
+ result = SystemPacket::ReadRegs (slp);
+ break;
+
+ case sysPktWriteRegsCmd:
+ result = SystemPacket::WriteRegs (slp);
+ break;
+
+ case sysPktContinueCmd:
+ result = SystemPacket::Continue (slp);
+ break;
+
+ case sysPktRPCCmd:
+ result = SystemPacket::RPC (slp);
+ break;
+
+ case sysPktGetBreakpointsCmd:
+ result = SystemPacket::GetBreakpoints (slp);
+ break;
+
+ case sysPktSetBreakpointsCmd:
+ result = SystemPacket::SetBreakpoints (slp);
+ break;
+
+// case sysPktRemoteUIUpdCmd:
+// // Sent TO debugger; never received FROM debugger.
+// break;
+
+// case sysPktRemoteEvtCmd:
+// // Sent TO debugger; never received FROM debugger.
+// break;
+
+ case sysPktDbgBreakToggleCmd:
+ result = SystemPacket::ToggleBreak (slp);
+ break;
+
+ case sysPktFlashCmd:
+ // Not supported in this release.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktCommCmd:
+ // Not supported in this release.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktGetTrapBreaksCmd:
+ result = SystemPacket::GetTrapBreaks (slp);
+ break;
+
+ case sysPktSetTrapBreaksCmd:
+ result = SystemPacket::SetTrapBreaks (slp);
+ break;
+
+ case sysPktGremlinsCmd:
+ // Not supported in this release.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktFindCmd:
+ result = SystemPacket::Find (slp);
+ break;
+
+ case sysPktGetTrapConditionsCmd:
+ result = SystemPacket::GetTrapConditions (slp);
+ break;
+
+ case sysPktSetTrapConditionsCmd:
+ result = SystemPacket::SetTrapConditions (slp);
+ break;
+
+ case sysPktChecksumCmd:
+ // Not supported in this release.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktExecFlashCmd:
+ // Not supported in this release.
+ PRINTF (" Not supported in this release.");
+ break;
+
+ case sysPktRemoteMsgCmd:
+ // Nothing for us to do. With a serial link,
+ // these are sent to clear the input port.
+ PRINTF (" Should not be *receiving these!");
+ break;
+
+#if 0
+ case 0xFF:
+ {
+ // This is a special comand only for Poser
+
+ char fn[256];
+ strcpy (fn, (char*) &body.data[14]);
+
+ EmFileRefList fileList;
+ fileList.push_back (fn);
+
+ ::LoadPalmFileList (fileList);
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ Exit:
+ PRINTF ("Exiting Debug::HandleNewPacket.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::BreakIfConnected
+ *
+ * DESCRIPTION: Handle the given exception. If we're connected to a
+ * debugger, we want to let it handle it, so change the CPU
+ * state and return TRUE (to say that we handled the
+ * execption). Otherwise return false to perform default
+ * handling (which means handing it off to the emulated ROM).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool Debug::BreakIfConnected (ExceptionNumber exceptionNumber)
+{
+ // Dump any logged information to a file.
+
+ LogDump ();
+
+ // If we're in the middle of calling a Palm OS subroutine, we're in
+ // really bad shape. Throw an exception that will eventually hard
+ // reset the device.
+ //
+ // We can be nested for three reasons: the UI thread is making a
+ // Palm OS call, the the UI thread is handling an RPC packet, or
+ // the CPU thread is making a Palm OS call (probably as part of
+ // a trap patch). Let's examine these three cases.
+ //
+ // 1. The UI thread is making the Palm OS call.
+ //
+ // TBD
+ //
+ // 2. The UI thread is handling an RPC packet.
+ //
+ // In this case, the EmException object is thrown past the following:
+ //
+ // Function Action
+ // ------------------------- -----------------------------------
+ // Debug::BreakIfConnected Throws the exception
+ // EmCPU68K::HandleException -
+ // <<<Exception generator>>> -
+ // EmCPU68K::Execute -
+ // EmSession::CallCPU -
+ // EmSession::ExecuteSubroutine Unlock fSharedLock
+ // ATrap::DoCall Add Trap Word and rethrow
+ // SystemPacket::RPC Skips sending of response
+ // RPC::HandleNewPacket / Clear gCurrentPacket
+ // Debug::HandleNewPacket -
+ // SLP::HandleNewPacket Reset the CPU before unstopping
+ // SLP::HandleDataReceived -
+ // SLP::EventCallback -
+ // -- one of the following --
+ // CMMFSocket::HandlePacket Display error message
+ // CTCPSocket::Idle Display error message
+ // CPPCSocket::HandlePacket Record excpetion for display in UI thread.
+ //
+ // 3. The CPU thread is making the Palm OS call.
+ //
+ // In this case, the EmException object is thrown past the following:
+ //
+ // Function Action
+ // ------------------------- -----------------------------------
+ // Debug::BreakIfConnected Throws the exception
+ // EmCPU68K::HandleException -
+ // <<<Exception generator>>> -
+ // EmCPU68K::Execute -
+ // EmSession::CallCPU -
+ // EmSession::ExecuteSubroutine Unlock fSharedLock
+ // ATrap::DoCall Add Trap Word and rethrow
+ // ROMStubs function -
+ // Trap Patch function -
+ // Patches::HandlePatches -
+ // Patches::HandleSystemCall -
+ // EmPalmOS::HandleSystemCall -
+ // -- either --
+ // EmPalmOS::HandleTrap15 -
+ // EmCPU68K::HandleException -
+ // <<<Exception generator>>> -
+ // -- or --
+ // EmPalmOS::HandleJSR_Ind -
+ // cpuemu function -
+ // -- end --
+ // EmCPU68K::Execute -
+ // EmSession::CallCPU -
+ // -- one of the following --
+ // EmSession::ExecuteIncremental Display error message and Reset
+ // EmSession::Run Display error message and Reset
+
+ if (gSession->IsNested ())
+ {
+ EmExceptionReset e (kResetSoft);
+ e.SetException (exceptionNumber);
+ throw e;
+ }
+
+ // If we entered due to a breakpoint (TRAP 0), backup the PC.
+
+ emuptr curpc = m68k_getpc ();
+ if (exceptionNumber == kException_SoftBreak)
+ {
+ m68k_setpc (curpc - 2);
+ }
+
+ // Try entering the debugger. If that fails, show a dialog,
+ // giving the user Debug or Reset options.
+
+ uint16 opcode = EmMemGet16 (curpc & ~1); // Protect against odd PC.
+
+ switch (exceptionNumber)
+ {
+ case kException_BusErr:
+ Errors::ReportErrBusError (gExceptionAddress, gExceptionSize, gExceptionForRead);
+ break;
+
+ case kException_AddressErr:
+ Errors::ReportErrAddressError (gExceptionAddress, gExceptionSize, gExceptionForRead);
+ break;
+
+ case kException_IllegalInstr:
+ Errors::ReportErrIllegalInstruction (opcode);
+ break;
+
+ case kException_DivideByZero:
+ Errors::ReportErrDivideByZero ();
+ break;
+
+ case kException_Chk:
+ Errors::ReportErrCHKInstruction ();
+ break;
+
+ case kException_Trap:
+ Errors::ReportErrTRAPVInstruction ();
+ break;
+
+ case kException_Privilege:
+ Errors::ReportErrPrivilegeViolation (opcode);
+ break;
+
+ case kException_Trace:
+ Errors::ReportErrTrace ();
+ break;
+
+ case kException_ATrap:
+ Errors::ReportErrATrap (opcode);
+ break;
+
+ case kException_FTrap:
+ Errors::ReportErrFTrap (opcode);
+ break;
+
+ case kException_Trap0:
+ case kException_Trap1:
+ case kException_Trap2:
+ case kException_Trap3:
+ case kException_Trap4:
+ case kException_Trap5:
+ case kException_Trap6:
+ case kException_Trap7:
+ case kException_Trap8:
+ case kException_Trap9:
+ case kException_Trap10:
+ case kException_Trap11:
+ case kException_Trap12:
+ case kException_Trap13:
+ case kException_Trap14:
+ case kException_Trap15:
+ Errors::ReportErrTRAPx (exceptionNumber - kException_Trap0);
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ // If we got here, the user was allowed to click "Continue" for
+ // some reason. Say we handled the exception and muddle on.
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::HandleTrap8
+ *
+ * DESCRIPTION: The CPU just encountered a TRAP 8, which is what gets
+ * compiled into the developer's code when he "calls" the
+ * DbgBreak or DbgSrcBreak "function". HandleTrap8
+ * determines whether or not this TRAP 8 should be handled
+ * as an exception (in which case we'd enter the debugger)
+ * or should be skipped like a NOP. If "ignoreDbgBreaks" is
+ * true, then merely return TRUE to say that we completely
+ * handled the exception. Otherwise, change the CPU state
+ * to non-running before we return TRUE.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool Debug::HandleTrap8 (ExceptionNumber exceptionNumber)
+{
+ // Don't break on trapbreaks if we're calling the ROM internally.
+
+ if (gSession->IsNested ())
+ return true;
+
+ if (gDebuggerGlobals.ignoreDbgBreaks)
+ {
+ return true;
+ }
+
+ return Debug::BreakIfConnected (exceptionNumber);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::HandleSystemCall
+ *
+ * DESCRIPTION: An A-Trap is about to be executed. This function is
+ * called to determine if we want to break on this A-Trap.
+ * If there are A-Trap breaks registered with the debugger,
+ * and if the "continueOverATrap" flag is not set (if it were set,
+ * that would mean that we'd just exited the debugger, and
+ * don't need to re-break on the A-Trap that caused us to
+ * enter the debugger), then scan the break table to see if
+ * the A-Trap we're about to execute is one we want to
+ * break on.
+ *
+ * If it is, call Debug::EnterDebugger,
+ * which will cause the CPU to break at the end of this
+ * opcode. Also return TRUE, which tells the normal A-Trap
+ * handler that we completely handled this A-Trap, and that
+ * it doesn't need to do any trap dispatcher stuff. Finally,
+ * back-up the PC so that it points to the A-Trap again so
+ * that when we resume execution we'll start at that A-Trap.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool Debug::HandleSystemCall (const SystemCallContext& context)
+{
+ // Don't break on trapbreaks if we're calling the ROM internally.
+
+ if (gSession->IsNested ())
+ return false;
+
+ Bool doBreak = false;
+
+ if (!gDebuggerGlobals.continueOverATrap && gDebuggerGlobals.breakingOnATrap)
+ {
+ doBreak = Debug::MustBreakOnTrapSystemCall (context.fTrapWord, context.fExtra);
+
+ // If we're supposed to break here, try entering the debugger.
+
+ if (doBreak)
+ {
+ // Entering the debugger means trying to send a "state" packet
+ // to the external debugger. Make sure the PC we pass it is correct.
+
+ emuptr oldPC = m68k_getpc ();
+ m68k_setpc (context.fPC);
+
+ if (Debug::EnterDebugger (kException_SoftBreak, NULL) == kError_NoError)
+ {
+ // Check again on the way out to see if there's still
+ // a breakpoint at this location. If so, we need to
+ // set *another* flag to make sure we skip over the
+ // breakpoint. Otherwise, we'd just break here over
+ // and over again.
+
+ gDebuggerGlobals.checkTrapWordOnExit = true;
+ gDebuggerGlobals.trapWord = context.fTrapWord;
+ gDebuggerGlobals.refNum = context.fExtra;
+ }
+ else
+ {
+ m68k_setpc (oldPC);
+ }
+ }
+ }
+
+ // Clear the flag telling us to inhibit the ATrapBreak check.
+
+ gDebuggerGlobals.continueOverATrap = false;
+
+ return doBreak;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::EnterDebugger
+ *
+ * DESCRIPTION: Put the emulator into "debug mode". This pretty much
+ * consists of setting up a bunch of flags, figuring out
+ * why we entered the debugger, and telling the external
+ * debugger that we've entered debug mode and what the
+ * current CPU state is.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+//
+// Reasons for entering the debugger:
+//
+// Single step:
+// reason == kException_Trace
+//
+// Normal processing.
+//
+// Step spy:
+// reason == kException_Trace
+//
+// Normal processing.
+//
+// User breakpoint (temporary or otherwise):
+// reason == kException_Trap0 + sysDbgBreakpointTrapNum
+//
+// Normal processing.
+//
+// Compiled breakpoint (DbgBreak, DbgSrcBreak):
+// reason == kException_Trap0 + sysDbgTrapNum
+//
+// Ignore if DbgGlobalsType.ignoreDbgBreaks is true.
+//
+// Actually, now we catch this one a little earlier. In
+// Software_ProcessException, we call an installed exception
+// handler that leads to calling Debug::HandleTrap8. That
+// function will return TRUE if ignoreDbgBreaks is true, which
+// will effectively turn the TRAP 8 into a NOP. Otherwise, it
+// returns false, which will lead to EnterDebugger being called
+// to handle the exception.
+//
+// "A-Trap" break:
+// reason == kException_Trace
+//
+// When looking for an A-Trap to break on, the debugger uses
+// a special trap dispatcher. Called on every TRAP F, when it
+// finds a trap to break on, it sets DbgGlobalsType.breakingOnATrap,
+// sets the tracing SR bit, and then calls the original trap
+// dispatcher.
+//
+// Because the trap dispatcher is run in supervisor mode, the
+// tracing bit doesn't do anything until it RTE's.
+//
+// Normal processing.
+//
+// Exception (bus error, address error, etc):
+// reason == exception code
+//
+// Normal processing.
+//
+// The debugger is silently entered if reason == kException_Trace.
+// Otherwise, it displays a message saying what exception occurred.
+
+ErrCode Debug::EnterDebugger (ExceptionNumber reason, SLP* slp)
+{
+ PRINTF ("Entering Debug::EnterDebugger.");
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // Save the reason for our entering the debugger.
+
+ gDebuggerGlobals.excType = (UInt16) (reason * 4);
+
+ // Turn off sound in case it was on when the debugger was entered.
+
+ EmHAL::TurnSoundOff ();
+
+ // Send a state message packet notifying the host that we've entered.
+ // If we can't send the packet (perhaps because there is no external
+ // debugger listening) return false saying that we failed to enter
+ // the debugger. When we return false, we indicate that perhaps the
+ // emulated ROM debugger should take over.
+ //
+ // Concurrency note: in the multi-threaded version of the emulator,
+ // EnterDebugger will be called from one thread (the CPU thread),
+ // while the UI thread will be listening for packets from the
+ // external debugger. When SendState sends the packet from this
+ // thread, the external debugger could receive it and send us back
+ // a message immediately. The question is, is this OK? Are there
+ // problems with the UI thread trying to debug us before the CPU
+ // thread has had a chance to stop itself? Let's see: the UI thread
+ // will receive the message, and start to handle it by telling the
+ // CPU thread to stop. That means that we should have a chance to
+ // clean up (set our flags, remove breakpoints, etc.) and stop before
+ // the UI thread tries to debug us.
+
+ ErrCode result = kError_NoError;
+
+ if (!slp)
+ {
+ CSocket* debuggerSocket = Debug::GetDebuggerSocket ();
+ if (debuggerSocket)
+ {
+ SLP newSLP (debuggerSocket);
+ result = SystemPacket::SendState (newSLP);
+ }
+ else
+ {
+ result = 1; // !!! Need a not "connected to debugger" error!
+ }
+ }
+ else
+ {
+ result = SystemPacket::SendState (*slp);
+ }
+
+ if (result == kError_NoError)
+ {
+ // Flag to the ROM that we're in the debugger. "dbgInDebugger" gets
+ // cleared in ExitDebugger. "dbgWasDebugger" stays set to true.
+
+ EmLowMem_SetGlobal (dbgWasEntered, true);
+ EmLowMem_SetGlobal (dbgInDebugger, true);
+
+ EmAssert (gSession);
+ gSession->ScheduleSuspendException ();
+
+ PRINTF ("Entered debug mode.");
+ }
+ else
+ {
+ PRINTF ("Failed to enter debug mode.");
+ }
+
+ PRINTF ("Exiting Debug::EnterDebugger.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::ExitDebugger
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode Debug::ExitDebugger (void)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // If we're continuing, but we're on a breakpoint, set a boolean
+ // that causes us to ignore the breakpoint when we hit it.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (gDebuggerGlobals.bp[ii].enabled == false)
+ continue;
+
+ emuptr addr = (emuptr) gDebuggerGlobals.bp[ii].addr;
+ if (!addr)
+ continue;
+
+ if (addr == m68k_getpc ())
+ gDebuggerGlobals.continueOverBP = true;
+ }
+
+ // Check to see if we (a) stopped here because of a request
+ // to break on a particular system call and (b) that we're
+ // still requested to break on this call. If so, set a flag
+ // to skip over the next break-on-system-call. Otherwise,
+ // we'd just break at this location over and over again.
+
+ if (gDebuggerGlobals.checkTrapWordOnExit)
+ {
+ gDebuggerGlobals.checkTrapWordOnExit = false;
+
+ if (MustBreakOnTrapSystemCall (gDebuggerGlobals.trapWord,
+ gDebuggerGlobals.refNum))
+ {
+ // Set the flag that tells this function to not break
+ // the next time it's entered.
+
+ gDebuggerGlobals.continueOverATrap = true;
+ }
+ }
+
+ // Set flags that we're no longer in the debugger.
+
+ gDebuggerGlobals.excType = 0;
+ EmLowMem_SetGlobal (dbgInDebugger, false);
+
+ EmSuspendState state = gSession->GetSuspendState ();
+ state.fCounters.fSuspendByDebugger = 0;
+ gSession->SetSuspendState (state);
+
+ return kError_NoError;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::HandleInstructionBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::HandleInstructionBreak (void)
+{
+ // Don't break on soft breakpoints if we're calling the ROM internally.
+
+ if (gSession->IsNested ())
+ return;
+
+ // Don't break on soft breakpoints if we're exiting the debugger.
+
+ if (gDebuggerGlobals.continueOverBP)
+ {
+ gDebuggerGlobals.continueOverBP = false;
+ return;
+ }
+
+ Debug::ConditionalBreak ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::InstallInstructionBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::InstallInstructionBreaks (void)
+{
+ // Install the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (gDebuggerGlobals.bp[ii].enabled)
+ {
+ MetaMemory::MarkInstructionBreak ((emuptr) gDebuggerGlobals.bp[ii].addr);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::RemoveInstructionBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::RemoveInstructionBreaks (void)
+{
+ // Remove the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (gDebuggerGlobals.bp[ii].enabled)
+ {
+ MetaMemory::UnmarkInstructionBreak ((emuptr) gDebuggerGlobals.bp[ii].addr);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::NewBreakpointCondition
+ *
+ * DESCRIPTION: Create a new breakpoint condition by parsing the given
+ * source string. Returns NULL on parse error.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+BreakpointCondition* Debug::NewBreakpointCondition (const char* sourceString)
+{
+ const char* source = sourceString;
+ registerFun regType;
+ int regNum;
+ Bool indirect = false;
+ uint32 indirectOffset;
+ int size = 4;
+
+ compareFun condition;
+ int value;
+
+ source = PrvSkipWhite (source);
+ if (!source)
+ return NULL;
+
+ if (isdigit (*source))
+ {
+ indirect = true;
+ if (!PrvParseUnsigned (&source, &indirectOffset))
+ return NULL;
+
+ source = PrvSkipWhite (source);
+
+ if (*source != '(')
+ return NULL;
+
+ ++source;
+ source = PrvSkipWhite (source);
+ }
+
+ switch (tolower (*source++))
+ {
+ case 'd':
+ regType = PrvGetDataRegister;
+ break;
+
+ case 'a':
+ regType = PrvGetAddressRegister;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ source = PrvSkipWhite (source);
+
+ if (!PrvParseDecimal (&source, &regNum))
+ return NULL;
+
+ source = PrvSkipWhite (source);
+
+ if (indirect)
+ {
+ if (*source != ')')
+ return NULL;
+
+ ++source;
+ source = PrvSkipWhite (source);
+ }
+
+ if (*source == '.')
+ {
+ ++source;
+
+ switch (*source)
+ {
+ case 'b': size = 1; break;
+ case 'w': size = 2; break;
+ case 'l': size = 4; break;
+ default: return NULL;
+ }
+
+ ++source;
+ source = PrvSkipWhite (source);
+ }
+
+ condition = NULL;
+ for (NamedConditionType* c = kConditions; c->name; ++c)
+ {
+ if (!strncmp (source, c->name, strlen (c->name)))
+ {
+ condition = c->function;
+ source += strlen (c->name);
+ break;
+ }
+ }
+
+ if (!condition)
+ return NULL;
+
+ if (sscanf (source, "%i", &value) != 1)
+ return NULL;
+
+ BreakpointCondition* bc = new BreakpointCondition;
+
+ bc->regType = regType;
+ bc->regNum = regNum;
+ bc->indirect = indirect;
+ bc->indirectOffset = indirectOffset;
+ bc->size = size;
+
+ bc->condition = condition;
+ bc->value = value;
+ bc->source = _strdup (sourceString);
+
+ return bc;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::SetBreakpoint
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::SetBreakpoint (int index, emuptr addr, BreakpointCondition* c)
+{
+ Debug::ClearBreakpoint (index);
+
+ EmAssert (gSession);
+ gSession->RemoveInstructionBreaks ();
+
+ gDebuggerGlobals.bp[index].enabled = true;
+ gDebuggerGlobals.bp[index].installed = false;
+ gDebuggerGlobals.bp[index].addr = (MemPtr) addr;
+ gDebuggerGlobals.bpCondition[index] = c;
+
+ gSession->InstallInstructionBreaks ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::ClearBreakpoint
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::ClearBreakpoint (int index)
+{
+ EmAssert (gSession);
+ gSession->RemoveInstructionBreaks ();
+
+ gDebuggerGlobals.bp[index].enabled = false;
+ gDebuggerGlobals.bp[index].addr = NULL;
+
+ Debug::DeleteBreakpointCondition (index);
+
+ gSession->InstallInstructionBreaks ();
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::DeleteBreakpointCondition
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::DeleteBreakpointCondition (int index)
+{
+ BreakpointCondition*& cond = gDebuggerGlobals.bpCondition[index];
+
+ if (cond)
+ {
+ if (cond->source)
+ {
+ free (cond->source);
+ }
+
+ delete cond;
+ cond = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::BreakpointInstalled
+ *
+ * DESCRIPTION: Return whether or not any breakpoints are installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: TRUE if so.
+ *
+ ***********************************************************************/
+
+Bool Debug::BreakpointInstalled (void)
+{
+ // Install the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (gDebuggerGlobals.bp[ii].enabled)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::MustBreakOnTrapSystemCall
+ *
+ * DESCRIPTION: Test the given trapWord (and optional refNum) to see
+ * if this is a combination that we expect to break on.
+ *
+ * PARAMETERS: trapWord - the system function dispatch number (Axxx)
+ * to test.
+ *
+ * refNum - the library reference number to test. This
+ * value is used only if trapWord is in the range for
+ * library function calls.
+ *
+ * RETURNED: True if we should break on this combination.
+ *
+ ***********************************************************************/
+
+Bool Debug::MustBreakOnTrapSystemCall (uint16 trapWord, uint16 refNum)
+{
+ Bool doBreak = false;
+ uint16 trapIndex = ::SysTrapIndex (trapWord);
+
+ // Do different compares for system traps and library traps.
+
+ if (::IsSystemTrap (trapWord))
+ {
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ if (trapIndex == ::SysTrapIndex (gDebuggerGlobals.trapBreak[ii]))
+ {
+ doBreak = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ if (trapIndex == ::SysTrapIndex (gDebuggerGlobals.trapBreak[ii]) &&
+ refNum == gDebuggerGlobals.trapParam[ii])
+ {
+ doBreak = true;
+ break;
+ }
+ }
+ }
+
+ return doBreak;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::DoCheckStepSpy
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void Debug::DoCheckStepSpy (emuptr writeAddress, int writeBytes)
+{
+ CEnableFullAccess munge;
+
+ uint32 newValue = EmMemGet32 (gDebuggerGlobals.ssAddr);
+ if (newValue != gDebuggerGlobals.ssValue)
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrStepSpy (writeAddress, writeBytes,
+ gDebuggerGlobals.ssAddr, gDebuggerGlobals.ssValue, newValue));
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::DoCheckWatchpoint
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void Debug::DoCheckWatchpoint (emuptr writeAddress, int writeBytes)
+{
+ if (writeAddress < gDebuggerGlobals.watchAddr + gDebuggerGlobals.watchBytes &&
+ writeAddress + writeBytes > gDebuggerGlobals.watchAddr)
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrWatchpoint (writeAddress, writeBytes,
+ gDebuggerGlobals.watchAddr, gDebuggerGlobals.watchBytes));
+ }
+}
+
+
+////// breakpoint conditions
+
+uint32 PrvGetAddressRegister (int num)
+{
+ return m68k_areg (regs, num);
+}
+
+uint32 PrvGetDataRegister (int num)
+{
+ return m68k_dreg (regs, num);
+}
+
+Bool PrvBPEquals (uint32 a, uint32 b)
+{
+ return a == b;
+}
+
+Bool PrvBPNotEquals (uint32 a, uint32 b)
+{
+ return a != b;
+}
+
+// Comparisons are unsigned for now. Would it be more useful if they were signed?
+
+Bool PrvBPGreater (uint32 a, uint32 b)
+{
+ return a > b;
+}
+
+Bool PrvBPGreaterOrEqual (uint32 a, uint32 b)
+{
+ return a >= b;
+}
+
+Bool PrvBPLess (uint32 a, uint32 b)
+{
+ return a < b;
+}
+
+Bool PrvBPLessOrEqual (uint32 a, uint32 b)
+{
+ return a <= b;
+}
+
+const char* PrvSkipWhite (const char* p)
+{
+ while (p && isspace (*p))
+ ++p;
+
+ return p;
+}
+
+/* Parse a signed decimal integer */
+
+Bool PrvParseDecimal (const char **ps, int *i)
+{
+ const char *s = *ps;
+
+ if (sscanf (s, "%d", i) != 1)
+ return false;
+
+ while (isdigit (*s))
+ ++s;
+
+ *ps = s;
+
+ return true;
+}
+
+/* Parse an unsigned integer which may be either decimal or hex (e.g. "0xabc")
+ */
+Bool PrvParseUnsigned (const char **ps, uint32 *u)
+{
+ const char *s = *ps;
+
+ if (sscanf (s, "%li", u) != 1)
+ return false;
+
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) /* hex */
+ {
+ s += 2;
+ while (isxdigit (*s))
+ ++s;
+ }
+ else /* decimal */
+ {
+ while (isdigit (*s))
+ ++s;
+ }
+
+ *ps = s;
+
+ return true;
+}
+
+Bool BreakpointCondition::Evaluate (void)
+{
+ uint32 r = regType (regNum);
+
+ if (indirect)
+ {
+ if (size == 4)
+ r = EmMemGet32 (r + indirectOffset);
+ else if (size == 2)
+ r = EmMemGet16 (r + indirectOffset);
+ else if (size == 1)
+ r = EmMemGet8 (r + indirectOffset);
+ else
+ return false;
+ }
+ else
+ {
+ if (size == 2)
+ r = (uint16) r;
+ else if (size == 1)
+ r = (uint8) r;
+ }
+
+ return condition (r, value);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::ConditionalBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::ConditionalBreak (void)
+{
+ MemPtr bpAddress = (MemPtr) m68k_getpc ();
+
+ // Loop over the breakpoints to see if we've hit one.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ // This breakpoint is not enabled, so just skip over it.
+
+ if (!gDebuggerGlobals.bp[ii].enabled)
+ continue;
+
+ // This breakpoint is not for this PC, so just skip over it.
+
+ if (gDebuggerGlobals.bp[ii].addr != bpAddress)
+ continue;
+
+ // If there is a condition for this breakpoint but it evaluates
+ // to false, just skip over the breakpoint.
+
+ BreakpointCondition* bc = gDebuggerGlobals.bpCondition[ii];
+
+ if (bc && bc->Evaluate () == false)
+ continue;
+
+ // Clear temporary breakpoint if we hit it.
+
+ if (bpAddress == gDebuggerGlobals.bp[dbgTempBPIndex].addr)
+ {
+ gDebuggerGlobals.bp[dbgTempBPIndex].enabled = false;
+ }
+
+ // Break into the debugger. If we can't do that (for instance,
+ // if no debugger is connected), just leave.
+
+ Debug::EnterDebugger (kException_SoftBreak, NULL);
+ break;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::CreateListeningSockets
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void PrvFireUpSocket (CSocket*& s)
+{
+ if (s)
+ {
+ if (s->Open () != errNone)
+ {
+ s->Delete();
+ s = NULL;
+ }
+ }
+}
+
+void Debug::CreateListeningSockets (void)
+{
+ Preference<long> portPref (kPrefKeyDebuggerSocketPort);
+
+ EmAssert (gDebuggerSocket1 == NULL);
+ EmAssert (gDebuggerSocket2 == NULL);
+ EmAssert (gDebuggerSocket3 == NULL);
+
+ if (*portPref != 0)
+ {
+ gDebuggerSocket1 = new CTCPSocket (&Debug::EventCallback, *portPref);
+ gDebuggerSocket2 = new CTCPSocket (&Debug::EventCallback, 2000);
+ }
+
+ gDebuggerSocket3 = Platform::CreateDebuggerSocket ();
+
+ ::PrvFireUpSocket (gDebuggerSocket1);
+ ::PrvFireUpSocket (gDebuggerSocket2);
+ ::PrvFireUpSocket (gDebuggerSocket3);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::DeleteListeningSockets
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Debug::DeleteListeningSockets (void)
+{
+ if (gDebuggerSocket1)
+ {
+ gDebuggerSocket1->Close ();
+ gDebuggerSocket1->Delete();
+ gDebuggerSocket1 = NULL;
+ }
+
+ if (gDebuggerSocket2)
+ {
+ gDebuggerSocket2->Close ();
+ gDebuggerSocket2->Delete();
+ gDebuggerSocket2 = NULL;
+ }
+
+ if (gDebuggerSocket3)
+ {
+ gDebuggerSocket3->Close ();
+ gDebuggerSocket3->Delete();
+ gDebuggerSocket3 = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::EventCallback
+ *
+ * DESCRIPTION: Callback function for TCP-based debugger-related
+ * sockets. This function takes care of installing and
+ * removing the 'gdbS' Feature (for gdb support), and
+ * forwards debugger packets to the Debug sub-system.
+ *
+ * PARAMETERS: s - the socket that connected, disconnected, or received
+ * some data.
+ *
+ * event - a code indicating what happened.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Debug::EventCallback (CSocket* s, int event)
+{
+ switch (event)
+ {
+ case CSocket::kConnected:
+ {
+ EmAssert (gDebuggerSocket1 == s ||
+ gDebuggerSocket2 == s ||
+ gDebuggerSocket3 == s);
+ EmAssert (gConnectedDebugSocket == NULL);
+
+ // We've connected on one of the TCP sockets we were listening
+ // on. Delete the other listening sockets so that we don't
+ // connect with it, too. We actually delete the other
+ // Sockets so that we don't accidentally start listening with
+ // them again (our TCPSockets are pretty tenacious when it comes
+ // to auto-starting the listening process).
+
+ if (s == gDebuggerSocket1)
+ {
+ gConnectedDebugSocket = (CTCPSocket*) gDebuggerSocket1;
+ gDebuggerSocket1 = NULL;
+ }
+ else if (s == gDebuggerSocket2)
+ {
+ gConnectedDebugSocket = (CTCPSocket*) gDebuggerSocket2;
+ gDebuggerSocket2 = NULL;
+ }
+ else // s == gDebuggerSocket3
+ {
+ gDebuggerSocket3 = NULL;
+ }
+
+ Debug::DeleteListeningSockets ();
+
+ // If we're listening on a socket, install the 'gdbS' feature. The
+ // existance of this feature causes programs written the the prc tools
+ // to enter the debugger when they're launched.
+
+ if (EmPatchState::UIInitialized ())
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped ())
+ {
+ ::FtrSet ('gdbS', 0, 0x12BEEF34);
+ }
+ }
+ break;
+ }
+
+ case CSocket::kDataReceived:
+ {
+ break;
+ }
+
+ case CSocket::kDisconnected:
+ {
+ // Let's start listening for a new debugger connection.
+
+ EmAssert (gDebuggerSocket1 == NULL);
+ EmAssert (gDebuggerSocket2 == NULL);
+ EmAssert (gDebuggerSocket3 == NULL);
+ EmAssert (gConnectedDebugSocket == s);
+
+ gConnectedDebugSocket = NULL;
+ s->Delete();
+
+ Debug::CreateListeningSockets ();
+
+ if (EmPatchState::UIInitialized ())
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped ())
+ {
+ ::FtrUnregister ('gdbS', 0);
+ }
+ }
+
+ break;
+ }
+ }
+
+ SLP::EventCallback (s, event);
+}
+
+
diff --git a/SrcShared/DebugMgr.h b/SrcShared/DebugMgr.h
new file mode 100644
index 0000000..351b729
--- /dev/null
+++ b/SrcShared/DebugMgr.h
@@ -0,0 +1,209 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _DEBUGMGR_H_
+#define _DEBUGMGR_H_
+
+#include "EmCPU68K.h" // ExceptionNumber
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmTypes.h" // ErrCode
+
+// Types
+
+#pragma mark Types
+
+class SLP;
+class CSocket;
+class CTCPSocket;
+
+struct SystemCallContext;
+
+typedef uint32 (*registerFun)(int num);
+typedef Bool (*compareFun)(UInt32 a, UInt32 b);
+
+// Breakpoint conditions are of the form:
+//
+// <register-expr>[<size>] <cond> <value>
+//
+// where:
+//
+// <register-expr>
+// is either a 68000 register (e.g. "d5") or an indirect reference at
+// a constant offset from a 68000 register (e.g. "8(a6)"). An indirect
+// reference reads from memory; when you set up a breakpoint condition
+// involving an indirect reference, you must be sure that the indirect
+// reference will point to a valid memory address whenever the breakpoint
+// is hit.
+//
+// <size>
+// is either ".l" (long), ".w" (word) or ".b" (byte). If no size is
+// specified, the expression is assumed to be long.
+//
+// <cond>
+// is a binary comparison operator: ==, !=, <=, >=, <, or >
+//
+// <value>
+// is a 32-bit integer
+//
+// All comparisons are unsigned!
+
+struct BreakpointCondition
+{
+ registerFun regType;
+ int regNum;
+ Bool indirect;
+ uint32 indirectOffset;
+ int size; /* number of bytes to compare: 4, 2, or 1 */
+
+ compareFun condition;
+ uint32 value;
+
+ // The source text. We keep this around so that, for example, a user can specify
+ // a condition using either hex or decimal notation and they will see the same
+ // notation the next time they edit the breakpoint.
+
+ char* source;
+
+ Bool Evaluate (void);
+};
+
+struct EmBreakpointType
+{
+ MemPtr addr; // address of breakpoint
+ Boolean enabled; // true if enabled
+ Boolean installed; // for alignment
+};
+
+struct DebugGlobalsType
+{
+ // Mode settings
+
+ bool ignoreDbgBreaks; // if true, ignore DbgBreak's
+ bool firstEntrance; // true first time we enter debugger
+ bool stepSpy; // true if step spying.
+ bool breakingOnATrap; // true if there are A-Traps to check
+ bool continueOverATrap; // true if skipping over next system call
+ bool continueOverBP; // true if skipping over next breakpoint
+
+ bool checkTrapWordOnExit;
+ uint16 trapWord;
+ uint16 refNum;
+
+ // Breakpoints and saved opcodes behind each one
+
+ EmBreakpointType bp[dbgTotalBreakpoints];
+ BreakpointCondition* bpCondition[dbgTotalBreakpoints]; // condition, or NULL if none
+
+ // Current trap breaks
+
+ UInt16 trapBreak[dbgTotalTrapBreaks];
+ UInt16 trapParam[dbgTotalTrapBreaks];
+
+ // Step spy support
+
+ emuptr ssAddr; // address to step spy on
+ UInt32 ssValue; // saved value
+
+ // Exception type
+
+ int32 excType; // why we entered debugger
+
+ // (adam) Data breakpoint support. This is similar to the step spy capability, but can monitor
+ // an arbitrary range of addresses for writes, and doesn't require a saved value.
+
+ bool watchEnabled;
+ emuptr watchAddr; // address to watch, or 0 if none
+ UInt32 watchBytes; // number of bytes to watch
+};
+
+// class Debug
+
+#pragma mark class Debug
+
+ // Referenced in SystemPacket.cpp
+extern DebugGlobalsType gDebuggerGlobals;
+
+extern emuptr gExceptionAddress;
+extern int gExceptionSize;
+extern Bool gExceptionForRead;
+
+
+class Debug
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void Startup (void);
+ static void Shutdown (void);
+ static Bool ConnectedToTCPDebugger (void);
+ static CTCPSocket* GetTCPDebuggerSocket (void);
+ static CSocket* GetDebuggerSocket (void);
+
+ static ErrCode HandleNewPacket (SLP&);
+
+ static Bool BreakIfConnected (ExceptionNumber);
+ static Bool HandleTrap8 (ExceptionNumber);
+ static Bool HandleSystemCall (const SystemCallContext& context);
+ static ErrCode EnterDebugger (ExceptionNumber, SLP*);
+ static ErrCode ExitDebugger (void);
+ static void CheckStepSpy (emuptr writeAddress, int writeBytes);
+
+ static void HandleInstructionBreak (void);
+ static void InstallInstructionBreaks(void);
+ static void RemoveInstructionBreaks (void);
+
+ static BreakpointCondition*
+ NewBreakpointCondition (const char* sourceString);
+ static void SetBreakpoint (int index, emuptr addr, BreakpointCondition* c);
+ static void ClearBreakpoint (int index);
+ static void DeleteBreakpointCondition (int index);
+
+ static Bool BreakpointInstalled (void);
+
+ private:
+ static void ConditionalBreak (void);
+ static Bool MustBreakOnTrapSystemCall (uint16 trapWord, uint16 refNum);
+
+ static void DoCheckStepSpy (emuptr writeAddress, int writeBytes);
+ static void DoCheckWatchpoint (emuptr writeAddress, int writeBytes);
+
+ static void EventCallback (CSocket* s, int event);
+ static void CreateListeningSockets (void);
+ static void DeleteListeningSockets (void);
+};
+
+
+// This function is called from the memory setter functions. Make it inline so
+// that the common case where stepSpy == FALSE executes quickly. Yes, this
+// _does_ make a difference.
+
+inline void Debug::CheckStepSpy (emuptr writeAddress, int writeBytes)
+{
+ if (gDebuggerGlobals.stepSpy)
+ {
+ Debug::DoCheckStepSpy (writeAddress, writeBytes);
+ }
+
+ if (gDebuggerGlobals.watchEnabled)
+ {
+ Debug::DoCheckWatchpoint (writeAddress, writeBytes);
+ }
+}
+
+
+#endif /* _DEBUGMGR_H_ */
+
diff --git a/SrcShared/EcmIf.h b/SrcShared/EcmIf.h
new file mode 100644
index 0000000..fc96525
--- /dev/null
+++ b/SrcShared/EcmIf.h
@@ -0,0 +1,388 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ 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.
+\* ===================================================================== */
+
+
+#ifndef EcmIf_h
+#define EcmIf_h
+
+#include <string>
+
+/*
+ This file is the root file for ECM, the Extended Component Model
+ system used within the Palm OS Emulator.
+
+ ECM is a COM-like component system. "Packages" (that is, plug-ins
+ in the form of DLLs and the like) publicize their functionality in
+ the form of "interfaces". Packages can be queried (that is, the
+ module can be asked for a particular interface by name, and the
+ module can either return the interface, or fail, indicating that the
+ requested facility is not supported).
+
+ Interfaces are expressed as a table of function pointers. As such,
+ they are very similar to C++ vtables, are are often created using
+ C++ class definitions.
+
+ Every interface has base functionality. That is, every interface
+ starts off its function table with three standard functions:
+ RequestInterface, Refer, and Release. These three functions are
+ defined as member functions of the pure virtual class IEcmComponent.
+ Therefore, for consistancy, all C++ classes defining interfaces
+ should ultimately descend from IEcmComponent.
+
+ The three methods in IEcmComponent are pure virtual, and so need to
+ be implemented in the class descending from it. The implementation
+ of these functions will likely be the same for all interfaces, and
+ so there is a concrete subclass of IEcmComponent that provides a
+ standard implementation. This subclass is EcmObject. Therefore,
+ most interface implementation classes will probably descend from
+ EcmObject and not directly from IEcmComponent.
+
+ When an interface is defined (that is, the set of functions in the
+ function table is established), it is introduced with the macro
+ "ecm_interface". This tells the reader that the following C++
+ struct/class merely defines a set of functions for a client to use.
+ Thus a new interface would look as follows:
+
+ ecm_interface MyBaseInterface
+ {
+ virtual EcmErr MyFunction1() = 0;
+ virtual EcmErr MyFunction2() = 0;
+ virtual EcmErr MyFunction3() = 0;
+ };
+
+ When an interface needs to be extended (that is, a base interface
+ needs to have some more functions added to it), the interface
+ is again introduced with "ecm_interface", but is followed by the
+ macro "ecm_extends" in the place where a C++ class indicates the
+ base class it descends from. Thus, an interface that inherited
+ from a base interface would look as follows:
+
+ ecm_interface MyDerivedInterface : ecm_extends MyBaseInterface
+ {
+ virtual EcmErr MyFunction4() = 0;
+ virtual EcmErr MyFunction5() = 0;
+ virtual EcmErr MyFunction6() = 0;
+ };
+
+ So far, we've just defined interfaces: the layout of the function
+ pointer table. We also need to implement the functions. To do
+ that, we create a class that descends from the interface we want
+ to implement, using the macro "ecm_implements". Thus, to implement
+ the functions described by MyDerivedInterface, we use the following:
+
+ class MyDerivedImplementation : ecm_implements MyDerivedInterface
+ {
+ virtual EcmErr MyFunction1();
+ virtual EcmErr MyFunction2();
+ virtual EcmErr MyFunction3();
+ virtual EcmErr MyFunction4();
+ virtual EcmErr MyFunction5();
+ virtual EcmErr MyFunction6();
+ };
+
+ Once all of these interface and implementation classes are defined,
+ they need to be used somehow. The plug-in needs to be given a way
+ to get to the interfaces it needs, and the container for the plug-in
+ needs to know what interfaces the plug-in supports.
+
+ This exchange of interface information takes place when the plug-in
+ is loaded. The plug-in needs to support an entry point that will
+ (a) accept a container object and (b) return a package object. The
+ as with all interfaces, these objects contain RequestInterface methods
+ from with all other interfaces can be obtained.
+
+ Obtaining an interface using RequestInterface is simple: you pass a
+ "name" of an interface to some ECM object, and that object will
+ say that it supports or doesn't support that interface. If it does
+ support that interface, it returns a pointer to the interface.
+*/
+
+
+#define ecm_interface struct
+#define ecm_implements virtual public
+#define ecm_extends virtual public
+
+
+#define ECM_CLASS_IF_LIST_BEGIN(classname, basename) \
+ virtual EcmErr FindInterface(const EcmIfName &name, void **iPP) \
+ { \
+ if (iPP == NULL) \
+ return kEcmErrInvalidParameter;
+
+
+#define ECM_CLASS_IF(ifid, iftype) \
+ if (name == (ifid)) \
+ { \
+ *iPP = (void *) static_cast<iftype *>(this); \
+ return kEcmErrNone; \
+ }
+
+
+#define ECM_CLASS_IF_LIST_END(classname, basename) \
+ return(basename::FindInterface(name, iPP)); \
+ }
+
+
+
+// ===========================================================================
+//
+// Extended Component Model (ECM) -- Interfaces
+//
+// We're adding support for component interfaces because
+// exporting c++ classes is a real pain from loadable libraries
+// (at least Windows DLLs), Anyway, component design using interfaces
+// works really well for "plugin" type designs.
+//
+// In our implementation, an interface is a c++ abstract base class.
+// ===========================================================================
+
+
+enum EcmErr
+{
+ kEcmErrNone,
+ kEcmErrYikes, // if this shows up, something really unexpected happened!
+ // flag any appearance of this return code as a defect.
+
+ kEcmErrInvalidParameter, // a parameter was not set up correctly
+ kEcmErrInvalidHandle, // handle doesn't refer to anything appropriate
+ kEcmErrInvalidIfName, // invalid name of interface or event interface
+ kEcmErrInvalidPubName, // invalid name of publisher
+ kEcmErrInvalidSrvName, // invalid name of service
+ kEcmErrInvalidCompName, // invalid name of component
+ kEcmErrBadEventType, // inapropriate event type
+ kEcmErrInvalidConnection, //
+ kEcmErrAlreadyConnected, //
+ kEcmErrNotInitialized //
+};
+
+
+
+
+// ===========================================================================
+// EcmIfName -- type to define name used to reference an interface.
+// NOTE: If ECM becomes more widely used, this can be optimized to use an
+// atom table of strings. An actual string comparison would then only need
+// to be done once.
+// ===========================================================================
+
+typedef string EcmIfName;
+typedef string EcmCompName;
+
+
+// ===========================================================================
+// EcmHandle -- Handle used for opaque references
+// ===========================================================================
+
+typedef void* EcmHandle;
+
+
+
+// ===========================================================================
+// IEcmComponent all interfaces must extend IEcmComponent..
+// this is how all patch modules appear to the patching sub-system
+// ===========================================================================
+
+const EcmIfName kEcmComponentIfn = "component.i.ecm";
+
+ecm_interface IEcmComponent
+{
+ /***********************************************************************
+ *
+ * FUNCTION: RequestInterface
+ *
+ * DESCRIPTION: Requests an interface of type EcmIfName from the component
+ *
+ * PARAMETERS: name [IN ] Name of the interface being requested.
+ * iPP [OUT ] Interface to the event being sent.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr RequestInterface(const EcmIfName &name, void **iPP) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Refer
+ *
+ * DESCRIPTION: Called before handing an interface pointer off to another
+ * "piece of code", adding an addition owner. This is used to
+ * maintain the reference count so the component can be destroyed
+ * at the appropriate time.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: ECMErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Refer() = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Release
+ *
+ * DESCRIPTION: Releases the interface from a reference, when the reference count is 0,
+ * the component can be destroyed.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: ECMErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Release() = 0;
+};
+
+
+
+// ===========================================================================
+// IEcmContainer
+// ===========================================================================
+
+const EcmIfName kEcmContainerIfn = "container.i.ecm";
+
+ecm_interface IEcmContainer : ecm_extends IEcmComponent
+{
+};
+
+
+
+// ===========================================================================
+// IEcmPackage
+// ===========================================================================
+
+const EcmIfName kEcmPackageIfn = "package.i.ecm";
+
+ecm_interface IEcmPackage : ecm_extends IEcmComponent
+{
+};
+
+
+
+// ===========================================================================
+// IEcmEventBase
+// ===========================================================================
+
+const EcmIfName kEcmEventBaseIfn = "eventbase.events.i.ecm";
+
+ecm_interface IEcmEventBase : ecm_extends IEcmComponent
+{
+
+
+};
+
+
+
+// ===========================================================================
+// IEcmEventListener
+// ===========================================================================
+
+const EcmIfName kEcmEventListenerIfn = "listener.events.i.ecm";
+
+/**
+ ** Base interface for all event sinks.
+ **/
+ecm_interface IEcmEventListener
+{
+ /***********************************************************************
+ *
+ * FUNCTION: OnEvent
+ *
+ * DESCRIPTION: Delivers an event to the event listener
+ *
+ * PARAMETERS: evtIP [IN ] Interface to the event being sent.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrBadEventType
+ *
+ *
+ ***********************************************************************/
+
+ EcmErr OnEvent(const IEcmEventBase *evtIP);
+};
+
+
+// ===========================================================================
+// IEcmEvents
+// ===========================================================================
+
+const EcmIfName kEcmEventsIfn = "events.i.ecm";
+
+ecm_interface IEcmEvents
+{
+ /***********************************************************************
+ *
+ * FUNCTION: RequestListener
+ *
+ * DESCRIPTION: Obtains an event listener interface (for a "category of events")
+ *
+ * PARAMETERS: name [IN ] Name of the event interface being requested.
+ * listenerIPP [OUT ] Interface to the given event listener.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidParameter
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr RequestListener(const EcmIfName &name, void **listenerIPP) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Subscribe
+ *
+ * DESCRIPTION: Allows an event "consumer" to subscribe to the named "category of events"
+ *
+ * PARAMETERS: publisher [IN ] Name of the event publisher being requested.
+ * subscriberIP [IN ] Interface to the subscribers event listener interface
+ * handle [OUT ] Unique identifier handle associated with the subscription.
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidParameter
+ * ECMErrInvalidName
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Subscribe(const EcmIfName &publisher, const IEcmEventListener *subscriberIP, EcmHandle &handle) = 0;
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Unsubscribe
+ *
+ * DESCRIPTION: Unsubscribes from an event publisher.
+ *
+ * PARAMETERS: handle [IN ] Unique identifier created by "IEcmComponent::Subscribe".
+ *
+ * RETURNED: ECMErrNone
+ * ECMErrInvalidHandle
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Unsubscribe(const EcmHandle handle) = 0;
+
+};
+
+
+#endif // EcmIf_h
diff --git a/SrcShared/EcmObject.h b/SrcShared/EcmObject.h
new file mode 100644
index 0000000..a1984b5
--- /dev/null
+++ b/SrcShared/EcmObject.h
@@ -0,0 +1,191 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ 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.
+\* ===================================================================== */
+
+#ifndef EcmObject_h
+#define EcmObject_h
+
+#include "EcmIf.h"
+
+/*
+ This file define a concrete implementation of the IEcmComponent
+ interface, as defined in EcmIf.h. IEcmComponent describes an object
+ with RequestInterface, Refer, and Release functions. EcmObject
+ provides implementations of those functions that find the requested
+ interface, increment a refcount, and decrement a refcount (deleting
+ the object if necessary), respectively.
+
+ RequestInterface works by making use of the FindInterface helper
+ function. FindInterface is implemented by all EcmObject subclasses
+ to cast itself to the right type and return the casted pointer if
+ the subclass supports the requested interface.
+
+ In order to make the implementation of FindInterface in all subclasses
+ simple and consistant, three macros are provided: ECM_CLASS_IF_LIST_BEGIN,
+ ECM_CLASS_IF, and ECM_CLASS_IF_LIST_END. The first macro introduces
+ a list of interfaces a particular class supports, the second macro is
+ used once for each interface supported, and the final macro cleans up
+ the list. In all, the three macros as used as follows in the class
+ declaration of the class implementing an interface:
+
+ class EmImplementation : public EcmObject,
+ ecm_implements IEmBaseInterface1,
+ ecm_implements IEmBaseInterface2
+ {
+ public:
+
+ ECM_CLASS_IF_LIST_BEGIN(EmImplementation, EcmObject)
+ ECM_CLASS_IF(kBaseIfn1, IEmBaseInterface1)
+ ECM_CLASS_IF(kBaseIfn2, IEmBaseInterface2)
+ ECM_CLASS_IF_LIST_END(EmImplementation, EcmObject)
+
+ ...
+ };
+*/
+
+
+// ===========================================================================
+//
+// Extended Component Model (ECM) -- Base Class
+//
+// We're adding support for component interfaces because
+// exporting c++ classes is a real pain from loadable libraries
+// (at least Windows DLLs), Anyway, component design using interfaces
+// works really well for "plugin" type designs.
+//
+// In our implementation, an interface is a c++ abstract base class.
+// ===========================================================================
+
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4250 )
+
+ // 'class1' : inherits 'class2::member' via dominance
+ //
+ // There were two or more members with the same name. The one in class2
+ // was inherited since it was a base class for the other classes that
+ // contained this member.
+#endif
+
+
+class EcmObject :
+ ecm_implements IEcmComponent
+{
+ public:
+ EcmObject() : fRefCount(0)
+ {
+ }
+
+
+
+ //This forms the root of the interface request implementation:
+ // Derived classes will implement the same function, then a request for an interface will move up
+ // through the ranks, until a match has been found.
+ //
+ virtual EcmErr FindInterface(const EcmIfName &name, void **iPP)
+ {
+ if (iPP == NULL)
+ return kEcmErrInvalidParameter;
+
+ if (name == kEcmComponentIfn)
+ {
+ *iPP = (void *) static_cast<IEcmComponent *>(this);
+ return kEcmErrNone;
+ }
+
+ //Interface never found:
+ return kEcmErrInvalidIfName;
+ }
+
+
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: RequestInterface
+ *
+ * DESCRIPTION: Requests an interface of type EcmIfName from the component
+ *
+ * PARAMETERS: name [IN ] Name of the interface being requested.
+ * iPP [OUT ] Interface to the event being sent.
+ *
+ * RETURNED: kEcmErrNone
+ * kEcmErrInvalidName
+ *
+ *
+ ***********************************************************************/
+ virtual EcmErr RequestInterface(const EcmIfName &name, void **iPP)
+ {
+ EcmErr err = FindInterface(name, iPP);
+
+ if (err == kEcmErrNone)
+ {
+ Refer();
+ }
+
+ return err;
+ }
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Refer
+ *
+ * DESCRIPTION: Called before handing an interface pointer off to another
+ * "piece of code", adding an addition owner. This is used to
+ * maintain the reference count so the component can be destroyed
+ * at the appropriate time.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: kEcmErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Refer()
+ {
+ fRefCount++;
+ return kEcmErrNone;
+ }
+
+
+ /***********************************************************************
+ *
+ * FUNCTION: Release
+ *
+ * DESCRIPTION: Releases the interface from a reference, when the reference count is 0,
+ * the component can be destroyed.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: kEcmErrNone
+ *
+ *
+ ***********************************************************************/
+
+ virtual EcmErr Release()
+ {
+ fRefCount--;
+
+ if (fRefCount == 0)
+ delete this;
+
+ return kEcmErrNone;
+ }
+
+ protected:
+ unsigned long fRefCount;
+};
+
+
+#endif // EcmObject_h
diff --git a/SrcShared/EmAction.cpp b/SrcShared/EmAction.cpp
new file mode 100644
index 0000000..9e5f4a1
--- /dev/null
+++ b/SrcShared/EmAction.cpp
@@ -0,0 +1,166 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmAction.h"
+
+#include "ErrorHandling.h" // Errors::ReportIfError
+#include "Strings.r.h" // kStr_GenericOperation
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionComposite::EmActionComposite
+// ---------------------------------------------------------------------------
+
+EmActionComposite::EmActionComposite (void) :
+ EmAction (kStr_GenericOperation)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionComposite::~EmActionComposite
+// ---------------------------------------------------------------------------
+
+EmActionComposite::~EmActionComposite (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionComposite::Do
+// ---------------------------------------------------------------------------
+
+void EmActionComposite::Do (void)
+{
+ EmActionList::iterator iter = fActions.begin ();
+
+ while (iter != fActions.end ())
+ {
+ (*iter)->Do ();
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionComposite::AddAction
+// ---------------------------------------------------------------------------
+
+void EmActionComposite::AddAction (EmAction* action)
+{
+ fActions.push_back (action);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::EmActionHandler
+// ---------------------------------------------------------------------------
+
+EmActionHandler::EmActionHandler (void) :
+ fActions ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::~EmActionHandler
+// ---------------------------------------------------------------------------
+
+EmActionHandler::~EmActionHandler (void)
+{
+ this->DeleteAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::PostAction
+// ---------------------------------------------------------------------------
+
+void EmActionHandler::PostAction (EmAction* action)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fActions.push_back (action);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::GetNextAction
+// ---------------------------------------------------------------------------
+
+EmAction* EmActionHandler::GetNextAction (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ EmAction* result = NULL;
+
+ if (!fActions.empty ())
+ {
+ result = fActions.front ();
+ fActions.erase (fActions.begin ());
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::GetNextAction
+// ---------------------------------------------------------------------------
+//
+// This function is an EXCEPTION_CATCH_POINT.
+
+void EmActionHandler::DoAll (void)
+{
+ EmAction* action = NULL;
+ while ((action = this->GetNextAction ()) != NULL)
+ {
+ try
+ {
+ action->Do ();
+ }
+ catch (ErrCode errCode)
+ {
+ this->DeleteAll ();
+
+ StrCode operation = action->GetDescription ();
+
+ Errors::ReportIfError (operation, errCode, 0, false);
+ }
+
+ delete action;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmActionHandler::DeleteAll
+// ---------------------------------------------------------------------------
+
+void EmActionHandler::DeleteAll (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ EmActionList::iterator iter = fActions.begin ();
+
+ while (iter != fActions.end ())
+ {
+ delete *iter;
+ ++iter;
+ }
+
+ fActions.clear ();
+}
diff --git a/SrcShared/EmAction.h b/SrcShared/EmAction.h
new file mode 100644
index 0000000..eb2a996
--- /dev/null
+++ b/SrcShared/EmAction.h
@@ -0,0 +1,73 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmAction_h
+#define EmAction_h
+
+#include "omnithread.h" // omni_mutex
+
+#include <vector>
+
+class EmAction;
+typedef vector <EmAction*> EmActionList;
+
+class EmAction
+{
+ public:
+ EmAction (StrCode strCode) : fStrCode (strCode) {}
+ virtual ~EmAction (void) {}
+
+ virtual void Do (void) = 0;
+
+ StrCode GetDescription (void) const { return fStrCode; };
+
+ private:
+ StrCode fStrCode;
+};
+
+
+class EmActionComposite : public EmAction
+{
+ public:
+ EmActionComposite (void);
+ virtual ~EmActionComposite (void);
+
+ virtual void Do (void);
+
+ void AddAction (EmAction*);
+
+ private:
+ EmActionList fActions;
+};
+
+
+class EmActionHandler
+{
+ public:
+ EmActionHandler (void);
+ virtual ~EmActionHandler (void);
+
+ public:
+ void PostAction (EmAction*);
+ EmAction* GetNextAction (void);
+ void DoAll (void);
+
+ private:
+ void DeleteAll (void);
+
+ private:
+ omni_mutex fMutex;
+ EmActionList fActions;
+};
+
+#endif // EmAction
diff --git a/SrcShared/EmApplication.cpp b/SrcShared/EmApplication.cpp
new file mode 100644
index 0000000..ac60f4a
--- /dev/null
+++ b/SrcShared/EmApplication.cpp
@@ -0,0 +1,1160 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmApplication.h"
+
+#include "EmCommands.h" // EmCommandID
+#include "EmDlg.h" // EmDlg, DoEditPreferences, etc.
+#include "EmDocument.h" // EmDocument::AskNewSession, etc.
+#include "EmErrCodes.h" // kError_OnlySameType
+#include "EmEventPlayback.h" // EmEventPlayback::ReplayEvents
+#include "EmMinimize.h" // EmMinimize::Start
+#include "EmPatchState.h" // EmPatchState::IsTimeToQuit
+#include "EmROMTransfer.h" // EmROMTransfer::ROMTransfer
+#include "EmSession.h" // EmStopMethod
+#include "EmTransport.h" // EmTransport::CloseAllTransports
+#include "EmTypes.h" // StrCode
+#include "EmWindow.h" // gWindow
+#include "ErrorHandling.h" // Errors::ReportIfError
+#include "HostControl.h" // hostSignalQuit
+#include "Startup.h" // CreateSession, OpenSession, DetermineStartupActions
+#include "Strings.r.h" // kStr_CmdAbout, etc.
+
+#include "DebugMgr.h" // Debug::Startup
+#include "EmDlg.h" // DoCommonDialog
+#include "EmRPC.h" // RPC::Startup
+#include "Logging.h" // LogStartup
+#include "SocketMessaging.h" // CSocket::Startup
+
+#if HAS_TRACER
+#include "TracerPlatform.h" // gTracer.Initialize();
+#endif
+
+typedef void (EmApplication::*EmCommandFn)(EmCommandID);
+
+
+static const struct
+{
+ EmCommandID fCommandID;
+ EmCommandFn fFn;
+ StrCode fErrStrCode;
+}
+kCommand[] =
+{
+ { kCommandAbout, &EmApplication::DoAbout, kStr_CmdAbout },
+ { kCommandSessionNew, &EmApplication::DoNew, kStr_CmdNew },
+ { kCommandSessionOpenOther, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen0, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen1, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen2, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen3, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen4, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen5, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen6, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen7, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen8, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionOpen9, &EmApplication::DoOpen, kStr_CmdOpen },
+ { kCommandSessionClose, &EmApplication::DoClose, kStr_CmdClose },
+ { kCommandQuit, &EmApplication::DoQuit, kStr_CmdQuit },
+
+ { kCommandDownloadROM, &EmApplication::DoDownload, kStr_CmdTransferROM },
+
+ { kCommandPreferences, &EmApplication::DoPreferences, kStr_CmdPreferences },
+ { kCommandLogging, &EmApplication::DoLogging, kStr_CmdLoggingOptions },
+ { kCommandDebugging, &EmApplication::DoDebugging, kStr_CmdDebugOptions },
+ { kCommandErrorHandling, &EmApplication::DoErrorHandling,kStr_CmdErrorHandling },
+#if HAS_TRACER
+ { kCommandTracing, &EmApplication::DoTracing, kStr_CmdTracingOptions },
+#endif
+ { kCommandSkins, &EmApplication::DoSkins, kStr_CmdSkins },
+ { kCommandHostFS, &EmApplication::DoHostFS, kStr_CmdHostFSOptions },
+ { kCommandBreakpoints, &EmApplication::DoBreakpoints, kStr_CmdBreakpoints },
+
+ { kCommandEventReplay, &EmApplication::DoReplay, kStr_CmdEventReplay },
+ { kCommandEventMinimize, &EmApplication::DoMinimize, kStr_CmdEventMinimize },
+
+ { kCommandEmpty, &EmApplication::DoNothing, 0 },
+ { kCommandFile, &EmApplication::DoNothing, 0 },
+ { kCommandEdit, &EmApplication::DoNothing, 0 },
+ { kCommandGremlins, &EmApplication::DoNothing, 0 },
+#if HAS_PROFILING
+ { kCommandProfile, &EmApplication::DoNothing, 0 },
+#endif
+ { kCommandRoot, &EmApplication::DoNothing, 0 },
+ { kCommandOpen, &EmApplication::DoNothing, 0 },
+ { kCommandImport, &EmApplication::DoNothing, 0 },
+ { kCommandSettings, &EmApplication::DoNothing, 0 },
+ { kCommandDivider, &EmApplication::DoNothing, 0 }
+};
+
+EmApplication* gApplication;
+
+class EmActionSessionClose : public EmAction
+{
+ public:
+ EmActionSessionClose (const EmFileRef& ref) :
+ EmAction (kStr_CmdClose),
+ fRef (ref)
+ {
+ }
+
+ virtual ~EmActionSessionClose (void)
+ {
+ }
+
+ virtual void Do (void)
+ {
+ gApplication->HandleSessionClose (fRef);
+ }
+
+ private:
+ EmFileRef fRef;
+};
+
+
+class EmActionQuit : public EmAction
+{
+ public:
+ EmActionQuit (void) :
+ EmAction (kStr_CmdQuit)
+ {
+ }
+
+ virtual ~EmActionQuit (void)
+ {
+ }
+
+ virtual void Do (void)
+ {
+ gApplication->HandleQuit ();
+ }
+
+ private:
+};
+
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::EmApplication
+// ---------------------------------------------------------------------------
+// Constructor. Sets the document reference to NULL, sets the quit flag to
+// false, and sets the global gApplication variable to point to us.
+
+EmApplication::EmApplication (void) :
+ EmActionHandler (),
+ fQuit (false)
+{
+ EmAssert (gApplication == NULL);
+ gApplication = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::~EmApplication
+// ---------------------------------------------------------------------------
+// Destructor. Makes sure the document has been closed, removes the reference
+// to us in gApplication, and performs some necessary final cleanup.
+
+EmApplication::~EmApplication (void)
+{
+ EmAssert (fQuit);
+
+ EmAssert (gApplication == this);
+ gApplication = NULL;
+
+ EmTransport::CloseAllTransports ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::Startup
+// ---------------------------------------------------------------------------
+// Performs one-time startup initialization.
+
+Bool EmApplication::Startup (int argc, char** argv)
+{
+ // Load our preferences.
+
+ gPrefs->Load ();
+
+ CSocket::Startup ();
+ Debug::Startup (); // Create our sockets
+ RPC::Startup (); // Create our sockets
+
+#if HAS_TRACER
+ gTracer.Initialize ();
+#endif
+
+ LogStartup ();
+
+ // Check to see if any skins were loaded. Report a possible problem if
+ // not. Only warn the user once. Don't warn for bound Posers, which have
+ // the only skin they need to use included as a resource.
+
+ Preference<Bool> pref (kPrefKeyWarnAboutSkinsDir);
+ if (!this->IsBound () && *pref)
+ {
+ SkinNameList names;
+ SkinGetSkinNames (EmDevice (), names);
+
+ if (names.size () <= 1)
+ {
+ EmDlg::DoCommonDialog (kStr_MissingSkins, kDlgFlags_OK);
+
+ pref = false;
+ }
+ }
+
+ // Determine what startup options the user has specified on the command
+ // line.
+
+ Bool result = Startup::DetermineStartupActions (argc, argv);
+
+ if (!result)
+ {
+ this->SetTimeToQuit (true);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::Shutdown
+// ---------------------------------------------------------------------------
+// Performs one-time shutdown operations.
+
+void EmApplication::Shutdown (void)
+{
+ RPC::SignalWaiters (hostSignalQuit);
+
+ Debug::Shutdown ();
+ RPC::Shutdown ();
+ CSocket::Shutdown ();
+
+ LogShutdown ();
+
+#if HAS_TRACER
+ gTracer.Dispose ();
+#endif
+
+ // Save the preferences.
+
+ gPrefs->Save ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleStartupActions
+// ---------------------------------------------------------------------------
+// Kick off any actions required when Poser starts up. The rules for what
+// needs to be done are defined by the Startup class, based on command line
+// options, preferences, and the state of the CapsLock key. Here, all we do
+// is respond to the results of all those options and either open an old
+// session, create a new one, or do nothing.
+//
+// !!! This function should probably be replaced with EmActions posted by
+// Startup::DetermineStartupActions.
+//
+// This function is an EXCEPTION_CATCH_POINT.
+
+void EmApplication::HandleStartupActions (void)
+{
+ EmFileRef ref;
+ Configuration cfg;
+
+ try
+ {
+ if (this->IsBoundFully ())
+ {
+ this->HandleOpenBound ();
+ }
+ else if (this->IsBoundPartially ())
+ {
+ this->HandleNewBound ();
+ }
+ else if (Startup::OpenSession (ref))
+ {
+ this->HandleOpenFromFile (ref);
+ }
+ else if (Startup::CreateSession (cfg))
+ {
+ this->HandleNewFromConfig (cfg);
+ }
+ else if (Startup::Minimize (ref))
+ {
+ this->HandleMinimize (ref);
+ }
+ }
+ catch (ErrCode errCode)
+ {
+ Errors::ReportIfError (kStr_GenericOperation, errCode, 0, false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleCommand
+// ---------------------------------------------------------------------------
+// Handle a user command. Normally the command is generated when the user
+// makes a menu selection, but the command could really come from anywhere
+// (for example, a toolbar with icon buttons, or from the dialog with the New,
+// Open, Download, and Quit pushbuttons in it).
+//
+// This method examines the command, synchronizes with the CPU thread as
+// necessary, executes the command, and catches any exceptions, showing them
+// in an error dialog.
+//
+// This function is an EXCEPTION_CATCH_POINT.
+
+Bool EmApplication::HandleCommand (EmCommandID commandID)
+{
+ // Find information on how this command should be handled.
+
+ size_t ii;
+ for (ii = 0; ii < countof (kCommand); ++ii)
+ {
+ if (kCommand[ii].fCommandID == commandID)
+ break;
+ }
+
+ // If we couldn't find an entry for this command, assume that it's not a
+ // command for the application, and return false indicating that we did
+ // not handle the command.
+
+ if (ii >= countof (kCommand))
+ {
+ return false; // We did not handle this command.
+ }
+
+ // Execute the command. Catch any exceptions and report them to the user.
+
+ if (kCommand[ii].fFn)
+ {
+ try
+ {
+ (this->*(kCommand[ii].fFn)) (commandID);
+ }
+ catch (ErrCode errCode)
+ {
+ StrCode operation = kCommand[ii].fErrStrCode;
+
+ Errors::ReportIfError (operation, errCode, 0, false);
+ }
+ }
+
+ return true; // We handled this command.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleIdle
+// ---------------------------------------------------------------------------
+// Perform any application-level idle time operations.
+
+void EmApplication::HandleIdle (void)
+{
+ // Don't let us recurse. This could happen if, for example, we were
+ // handling a debugger packet, an exception occurs, and Poser tries to
+ // show an error message in a dialog. That dialog would allow re-entry
+ // into this function.
+
+ static Bool inHandleIdle;
+
+ if (inHandleIdle)
+ return;
+
+ EmValueChanger<Bool> oldInHandleIdle (inHandleIdle, true);
+
+ // Pop off deferred actions and handle them.
+
+ this->DoAll ();
+
+ // Idle the document.
+
+ if (gDocument)
+ {
+ gDocument->HandleIdle ();
+ }
+
+ // Idle the window.
+
+ if (gWindow)
+ {
+ gWindow->HandleIdle ();
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleNewFromUser
+// ---------------------------------------------------------------------------
+// Create a new session asking the user for configuration information.
+// Starting configuration information can be passed in. If it is not,
+// configuration information from the prefs is used.
+
+EmDocument* EmApplication::HandleNewFromUser (const Configuration* inCfg)
+{
+ EmAssert (!this->IsBound ());
+
+ // Get the current configuration.
+
+ Configuration cfg;
+
+ if (inCfg)
+ {
+ cfg = *inCfg;
+ }
+ else
+ {
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ cfg = *pref;
+ }
+
+ // Ask the user for missing information.
+
+ if (!EmDocument::AskNewSession (cfg))
+ {
+ return NULL;
+ }
+
+ // Create the new document.
+
+ return this->HandleNewFromConfig (cfg);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleNew
+// ---------------------------------------------------------------------------
+// Create a new session from the current configuration information in the
+// preferences.
+
+EmDocument* EmApplication::HandleNewFromPrefs (void)
+{
+ EmAssert (!this->IsBound ());
+
+ // Get the current configuration.
+
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ Configuration cfg = *pref;
+
+ // Create the new document.
+
+ return this->HandleNewFromConfig (cfg);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleNewFromROM
+// ---------------------------------------------------------------------------
+// Create a new session from the given ROM.
+
+EmDocument* EmApplication::HandleNewFromROM (const EmFileRef& romRef)
+{
+ EmAssert (!this->IsBound ());
+
+ // Get the current (last specified) configuration.
+
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ Configuration cfg = *pref;
+
+ // Update the ROM file setting with the one passed in to this function.
+
+ cfg.fROMFile = romRef;
+
+ // Create the new document.
+
+ return this->HandleNewFromUser (&cfg);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleNewFromConfig
+// ---------------------------------------------------------------------------
+// Create a new session from the given configuration, closing any previous
+// session first. An exception is thrown if the configuration is invalid.
+//
+// This function is the bottleneck for creating new sessions.
+
+EmDocument* EmApplication::HandleNewFromConfig (const Configuration& cfg)
+{
+ EmAssert (!this->IsBound ());
+
+ // Validate the configuration.
+
+ if (!cfg.IsValid ())
+ {
+ Errors::Throw (kError_InvalidConfiguration);
+ }
+
+ // Close any previous document. If the use cancels, return NULL.
+
+ if (!this->CloseDocument (false))
+ {
+ return NULL;
+ }
+
+ // Create the new document.
+
+ EmAssert (gDocument == NULL);
+
+ EmDocument::DoNew (cfg);
+
+ return gDocument;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleNewBound
+// ---------------------------------------------------------------------------
+
+EmDocument* EmApplication::HandleNewBound (void)
+{
+ EmAssert (this->IsBoundPartially ());
+
+ if (!this->CloseDocument (false))
+ {
+ return NULL;
+ }
+
+ EmAssert (gDocument == NULL);
+
+ EmDocument::DoNewBound ();
+
+ return gDocument;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleOpenFromUser
+// ---------------------------------------------------------------------------
+// Open a previous session, asking the user to find it.
+
+EmDocument* EmApplication::HandleOpenFromUser (EmFileType type)
+{
+ EmAssert (!this->IsBound ());
+
+ EmFileRef file;
+
+ if (EmDocument::AskLoadSession (file, type))
+ {
+ return this->HandleOpenFromFile (file);
+ }
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleOpenFromPrefs
+// ---------------------------------------------------------------------------
+// Open a previous session, using information from the preferences.
+
+EmDocument* EmApplication::HandleOpenFromPrefs (void)
+{
+ EmAssert (!this->IsBound ());
+
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ EmFileRef file = *pref;
+
+ return this->HandleOpenFromFile (file);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleOpenFromFile
+// ---------------------------------------------------------------------------
+// Open the given saved session, closing any previous session first.
+//
+// This function is the bottleneck for opening sessions.
+
+EmDocument* EmApplication::HandleOpenFromFile (const EmFileRef& file)
+{
+ EmAssert (!this->IsBound ());
+
+ // Close any previous document. If the use cancels, return NULL.
+
+ if (!this->CloseDocument (false))
+ {
+ return NULL;
+ }
+
+ // Open the old document.
+
+ EmAssert (gDocument == NULL);
+
+ EmDocument::DoOpen (file);
+
+ return gDocument;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleOpenBound
+// ---------------------------------------------------------------------------
+
+EmDocument* EmApplication::HandleOpenBound (void)
+{
+ EmAssert (this->IsBoundFully ());
+
+ if (!this->CloseDocument (false))
+ {
+ return NULL;
+ }
+
+ EmAssert (gDocument == NULL);
+
+ EmDocument::DoOpenBound ();
+
+ return gDocument;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleFileList
+// ---------------------------------------------------------------------------
+// Grovel over the given list of files and determine what to do with them. The
+// list can be any set of files that the emulator recognizes: session files,
+// ROM files, PRC/PDB/PQA files, etc. This function must figure out what
+// files they are, validate them, and handle them (open an old session, create
+// a new session, install files, etc.)
+//
+// This function is an EXCEPTION_CATCH_POINT.
+
+void EmApplication::HandleFileList (const EmFileRefList& fileList)
+{
+ int operation = kStr_GenericOperation;
+
+ try
+ {
+ // Grovel over the file list, counting up how many of each kind of
+ // file was passed to us.
+
+ int prcCount = 0;
+ int psfCount = 0;
+ int romCount = 0;
+ int otherCount = 0;
+
+ EmFileRefList::const_iterator iter = fileList.begin();
+ while (iter != fileList.end())
+ {
+ // egcs 1.1.1 can't seem to handle iter->Method() here...
+ if ((*iter).IsType (kFileTypePalmApp)) prcCount++;
+ else if ((*iter).IsType (kFileTypePalmDB)) prcCount++;
+ else if ((*iter).IsType (kFileTypePalmQA)) prcCount++;
+ else if ((*iter).IsType (kFileTypeSession)) psfCount++;
+ else if ((*iter).IsType (kFileTypeROM)) romCount++;
+ else otherCount++;
+
+ ++iter;
+ }
+
+ // If we're able to use the Exchange Manager, let us beam in any file
+ // type. Later, we may want to do something like PrvFindTarget to see
+ // if there's actually a handler installed for any given file type
+ // before trying to beam it. For now, let's just let the OS return an
+ // error in that case.
+ //
+ // Note that the check of "otherCount" is a cheap way to ensure that a
+ // session is currently running. If no session were running, then the
+ // call to CanUseExgMgr would crash, as it tries to call into the ROM.
+
+ if (otherCount && EmFileImport::CanUseExgMgr ())
+ {
+ prcCount += otherCount;
+ otherCount = 0;
+ }
+
+ // If we have a heterogeneous list, throw an exception.
+
+ if ((prcCount > 0) + (psfCount > 0) + (romCount > 0) + (otherCount > 0) > 1)
+ {
+ Errors::Throw (kError_OnlySameType);
+ }
+
+ // If we have PRC/PDB/PQA files, install them.
+
+ else if (prcCount > 0)
+ {
+ operation = prcCount == 1 ? kStr_CmdInstall : kStr_CmdInstallMany;
+ EmDlg::DoDatabaseImport (fileList, kMethodBest);
+ }
+
+ // If we have a session file, open it. If there's more than one, open
+ // just the first one.
+
+ else if (psfCount > 0)
+ {
+ operation = kStr_CmdOpen;
+
+ if (!this->IsBoundFully ())
+ {
+ if (psfCount > 1)
+ {
+ Errors::Throw (kError_OnlyOnePSF);
+ }
+ else
+ {
+ this->HandleOpenFromFile (fileList[0]);
+ }
+ }
+ }
+
+ // If we have a ROM file, create a new session based on it. If
+ // there's more than one, utilize just the first one.
+
+ else if (romCount > 0)
+ {
+ operation = kStr_CmdNew;
+
+ if (!this->IsBound ())
+ {
+ if (romCount > 1)
+ {
+ Errors::Throw (kError_OnlyOneROM);
+ }
+ else
+ {
+ this->HandleNewFromROM (fileList[0]);
+ }
+ }
+ }
+
+ // If there's any other file type, throw an exception.
+
+ else
+ {
+ Errors::Throw (kError_UnknownType);
+ }
+ }
+
+ // Catch any exceptions and report them.
+
+ catch (ErrCode errCode)
+ {
+ Errors::ReportIfError (kStr_GenericOperation, errCode, 0, false);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleMinimize
+// ---------------------------------------------------------------------------
+// Open a session/event file and start the minimization process on it. Called
+// in response to Startup::ScheduleMinimize.
+
+void EmApplication::HandleMinimize (const EmFileRef& ref)
+{
+ if (this->HandleOpenFromFile (ref))
+ {
+ EmMinimize::Start ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleSessionClose
+// ---------------------------------------------------------------------------
+// Close a session, writing it out to the given file. If the file is not
+// specified, just close the file without saving it. Called in response to
+// ScheduleSessionClose.
+
+void EmApplication::HandleSessionClose (const EmFileRef& ref)
+{
+ if (gDocument)
+ {
+ if (ref.IsSpecified ())
+ {
+ gDocument->HandleSaveTo (ref);
+ }
+
+ gDocument->HandleClose (kSaveNever, false);
+ }
+
+ EmAssert (gDocument == NULL);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::HandleQuit
+// ---------------------------------------------------------------------------
+// Quit the emulator, closing any session without saving it. Called in
+// response to ScheduleQuit.
+
+void EmApplication::HandleQuit (void)
+{
+ if (gDocument)
+ {
+ gDocument->HandleClose (kSaveNever, true);
+ }
+
+ EmAssert (gDocument == NULL);
+
+ this->SetTimeToQuit (true);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::ScheduleSessionClose
+// ---------------------------------------------------------------------------
+// Schedule the emulator to close the session to the given file at some safe
+// point in the future.
+
+void EmApplication::ScheduleSessionClose (const EmFileRef& ref)
+{
+ this->PostAction (new EmActionSessionClose (ref));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::ScheduleQuit
+// ---------------------------------------------------------------------------
+// Schedule the emulator to quit at some safe point in the future.
+
+void EmApplication::ScheduleQuit (void)
+{
+ this->PostAction (new EmActionQuit);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoAbout
+// ---------------------------------------------------------------------------
+// Show the All Important About Box.
+
+void EmApplication::DoAbout (EmCommandID)
+{
+ EmDlg::DoAboutBox ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoNew
+// ---------------------------------------------------------------------------
+// Create a new document, asking the user for configuration information.
+
+void EmApplication::DoNew (EmCommandID)
+{
+ EmAssert (!this->IsBoundFully ());
+
+ if (this->IsBoundPartially ())
+ {
+ this->HandleNewBound ();
+ }
+ else
+ {
+ this->HandleNewFromUser (NULL);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoOpen
+// ---------------------------------------------------------------------------
+// Open a previously saved document. Either ask the user for a document, or
+// fetch a document from the MRU list.
+
+void EmApplication::DoOpen (EmCommandID commandID)
+{
+ EmAssert (!this->IsBound ());
+
+ if (commandID == kCommandSessionOpenOther)
+ {
+ this->HandleOpenFromUser (kFileTypeSession);
+ }
+ else
+ {
+ int index = commandID - kCommandSessionOpen0;
+ EmFileRef file = gEmuPrefs->GetIndRAMMRU (index);
+
+ if (file.IsSpecified ())
+ {
+ this->HandleOpenFromFile (file);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoClose
+// ---------------------------------------------------------------------------
+// Attempt to close the current document.
+
+void EmApplication::DoClose (EmCommandID)
+{
+ this->CloseDocument (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoQuit
+// ---------------------------------------------------------------------------
+// Attempt to close the current document and quit the application.
+
+void EmApplication::DoQuit (EmCommandID)
+{
+ if (this->CloseDocument (true))
+ {
+ this->SetTimeToQuit (true);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoDownload
+// ---------------------------------------------------------------------------
+// Display the ROM Transfer dialog, and download the actual ROM if the user
+// doesn't cancel the operation.
+
+void EmApplication::DoDownload (EmCommandID)
+{
+ EmROMTransfer::ROMTransfer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoPreferences
+// ---------------------------------------------------------------------------
+// Display the General Preferences dialog.
+
+void EmApplication::DoPreferences (EmCommandID)
+{
+ EmDlg::DoEditPreferences ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoLogging
+// ---------------------------------------------------------------------------
+// Display the Logging Preferences dialog.
+
+void EmApplication::DoLogging (EmCommandID)
+{
+ EmDlg::DoEditLoggingOptions (kNormalLogging);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoDebugging
+// ---------------------------------------------------------------------------
+// Display the Debugging Preferences dialog.
+
+void EmApplication::DoDebugging (EmCommandID)
+{
+ EmDlg::DoEditDebuggingOptions ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoErrorHandling
+// ---------------------------------------------------------------------------
+// Display the Error Handling Preferences dialog.
+
+void EmApplication::DoErrorHandling (EmCommandID)
+{
+ EmDlg::DoEditErrorHandling ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoTracing
+// ---------------------------------------------------------------------------
+// Display the Tracing Preferences dialog.
+
+#if HAS_TRACER
+void EmApplication::DoTracing (EmCommandID)
+{
+ EmDlg::DoEditTracingOptions ();
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoSkins
+// ---------------------------------------------------------------------------
+// Display the Skins Preferences dialog.
+
+void EmApplication::DoSkins (EmCommandID)
+{
+ EmDlg::DoEditSkins ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoHostFS
+// ---------------------------------------------------------------------------
+// Display the HostFS Preferences dialog.
+
+void EmApplication::DoHostFS (EmCommandID)
+{
+ EmDlg::DoEditHostFSOptions ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoBreakpoints
+// ---------------------------------------------------------------------------
+// Display the Breakpoints Preferences dialog.
+
+void EmApplication::DoBreakpoints (EmCommandID)
+{
+ EmDlg::DoEditBreakpoints ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoReplay
+// ---------------------------------------------------------------------------
+// Open a document specified by the user and start the Playback process.
+
+void EmApplication::DoReplay (EmCommandID)
+{
+ if (this->HandleOpenFromUser (kFileTypeEvents))
+ {
+ EmAssert (gSession);
+ EmEventPlayback::LoadEvents (gSession->GetFile ());
+ EmEventPlayback::ReplayEvents (true);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoMinimize
+// ---------------------------------------------------------------------------
+// Open a document specified by the user and start the Minimization process.
+
+void EmApplication::DoMinimize (EmCommandID)
+{
+ if (this->HandleOpenFromUser (kFileTypeEvents))
+ {
+ EmMinimize::Start ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::DoNothing
+// ---------------------------------------------------------------------------
+// Null operation. Used for menu items that can be selected but that don't
+// actually do anything.
+
+void EmApplication::DoNothing (EmCommandID)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::CloseDocument
+// ---------------------------------------------------------------------------
+// Handles the request to close a document. This request can be denied: if
+// the user is asked if they want to save the document, they can cancel the
+// operation. This function returns true if there is no running document when
+// it exits (that is, the current document was closed or there was no document
+// open to begin with). Otherwise, it returns false to indicate that a
+// document is still open.
+
+Bool EmApplication::CloseDocument (Bool quitting)
+{
+ if (gDocument)
+ {
+ gDocument->HandleClose (quitting);
+ }
+
+ return gDocument == NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::IsBound
+// ---------------------------------------------------------------------------
+// Returns whether or not this application is bound in any sort of fashion.
+// We cache the result in case this function is called from time-critical
+// functions.
+
+Bool EmApplication::IsBound (void)
+{
+ static int result;
+
+ if (result == 0)
+ {
+ result = this->ROMResourcePresent () ? 1 : -1;
+ }
+
+ return result > 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::IsBoundPartially
+// ---------------------------------------------------------------------------
+// Returns whether or not this application is partially bound. Returns false
+// if fully bound or not bound.
+// We cache the result in case this function is called from time-critical
+// functions.
+
+Bool EmApplication::IsBoundPartially (void)
+{
+ static int result;
+
+ if (result == 0)
+ {
+ result = (this->ROMResourcePresent () && !this->PSFResourcePresent ()) ? 1 : -1;
+ }
+
+ return result > 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmApplication::IsBoundFully
+// ---------------------------------------------------------------------------
+// Returns whether or not this application is fully bound. Return false if
+// partially bound or not bound.
+// We cache the result in case this function is called from time-critical
+// functions.
+
+Bool EmApplication::IsBoundFully (void)
+{
+ static int result;
+
+ if (result == 0)
+ {
+ result = this->PSFResourcePresent () ? 1 : -1;
+ }
+
+ return result > 0;
+}
+
+
diff --git a/SrcShared/EmApplication.h b/SrcShared/EmApplication.h
new file mode 100644
index 0000000..069157f
--- /dev/null
+++ b/SrcShared/EmApplication.h
@@ -0,0 +1,244 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmApplication_h
+#define EmApplication_h
+
+#include "EmAction.h" // EmActionHandler
+#include "EmCommands.h" // EmCommandID
+#include "EmDevice.h" // EmDevice
+#include "EmFileRef.h" // EmFileRef, EmFileRefList
+#include "EmTypes.h" // RAMSizeType
+
+/*
+ EmApplication is an abstract class for handling Palm OS Emulator
+ operations that don't require a document (or session) to be open or
+ running. That is, it deals with the commands that create or open
+ documents, showing preferences and other dialogs, and quitting the
+ application. It is responsible for the following commands:
+
+ * About Box
+ * New Session
+ * Open Session
+ * Close Session
+ * Quitting
+ * Download ROM
+ * All Preferences dialogs
+ * Event Playback and Minimization
+
+ EmApplication is mostly a cross-platform "code sharing" class. It's
+ not a true application class in that it doesn't deal with getting
+ user events, menu selections, or other platform-specific operations.
+ But once those events and selections are made, the EmApplication
+ class can be used to *handle* those operations in a cross-platofrm
+ way. Thus, you will most likely create a sub-class of EmApplication
+ that deals with user interaction and translate those into cross-
+ platform operations.
+*/
+
+class Chunk;
+class EmDocument;
+struct Configuration;
+
+class EmApplication : public EmActionHandler
+{
+ public:
+ EmApplication (void);
+ virtual ~EmApplication (void);
+
+ public:
+ virtual Bool Startup (int argc, char** argv);
+ virtual void Shutdown (void);
+
+ public:
+ void HandleStartupActions(void);
+ Bool HandleCommand (EmCommandID);
+ void HandleIdle (void);
+
+ public:
+ Bool GetTimeToQuit (void) { return fQuit; }
+ virtual void SetTimeToQuit (Bool q) { fQuit = q; }
+
+ public:
+ /*
+ This ramp of functions is responsible for creating new sessions.
+ They all return a pointer to any document they create. Note that
+ fDocument could be non-NULL and these functions return NULL if
+ the user cancelled the closing of the current document.
+
+ HandleNewFromUser Presents the dialog asking the user for new
+ configuration information. Initial dialog
+ settings can either be provided or fetched
+ from preferences. HandleNewFromConfig is
+ called to perform the actual open.
+
+ HandleNewFromPref Creates a new session from the configuration
+ information stored in the "last configuration"
+ preference. HandleNewFromConfig is called to
+ perform the actual open.
+
+ HandleNewFromROM Presents the dialog asking the user for new
+ configuration information. Initial dialog
+ settings are provided from the "last config-
+ uration" preference and the provided ROM.
+ HandleNewFromConfig is called to perform the
+ actual open.
+
+ HandleNewFromConfig Creates a new session based on the given
+ configuration information. First validates
+ the configuration and throws an exception if
+ that fails. Then attempts to close any current
+ session, returning NULL if that operation is
+ cancelled by the user. Finally, creates the
+ actual document. This function is the bottle-
+ neck for all document creation.
+ */
+
+ EmDocument* HandleNewFromUser (const Configuration*);
+ EmDocument* HandleNewFromPrefs (void);
+ EmDocument* HandleNewFromROM (const EmFileRef&);
+ EmDocument* HandleNewFromConfig (const Configuration&);
+ EmDocument* HandleNewBound (void);
+
+ /*
+ This ramp of functions is responsible for opening old sessions.
+ They all return a pointer to any document they open. Note that
+ fDocument could be non-NULL and these functions return NULL if
+ the user cancelled the closing of the current document.
+
+ HandleNewFromUser Asks the user for a file to open. HandleOpenFromFile
+ is called to perform the actual open.
+
+ HandleOpenFromPrefs Open the session file stored in the "last
+ session file" preference. HandleOpenFromFile
+ is called to perform the actual open.
+
+ HandleOpenFromFile Opens the given file. First attempts to close
+ any current session, returning NULL if that
+ operation is cancelled by the user. Then opens
+ the actual document. This function is the
+ bottleneck for all document opening.
+ */
+
+ EmDocument* HandleOpenFromUser (EmFileType);
+ EmDocument* HandleOpenFromPrefs (void);
+ EmDocument* HandleOpenFromFile (const EmFileRef&);
+ EmDocument* HandleOpenBound (void);
+
+ /*
+ Deal with figuring out what to do with the given files. Parse
+ them up, figure out what type(s) they are, and determine whether
+ to open them, create new sessions with them, install them, etc.
+ */
+
+ void HandleFileList (const EmFileRefList&);
+
+ /*
+ Open the given session/event file for minimization.
+ */
+
+ void HandleMinimize (const EmFileRef&);
+
+ /*
+ Close a session, writing it out to the given file. If the file
+ is not specified, just close the file without saving it. Called
+ in response to ScheduleSessionClose.
+ */
+
+ void HandleSessionClose (const EmFileRef&);
+
+ /*
+ Quit the emulator, closing any session without saving it. Called
+ in response to ScheduleQuit.
+ */
+
+ void HandleQuit (void);
+
+ public:
+ // The following functions schedule actions for the application
+ // to take the next chance it gets (at idle time).
+
+ void ScheduleSessionClose (const EmFileRef&);
+ void ScheduleQuit (void); // Close Now and Quit
+
+ public:
+ // Command handling functions, called from HandleCommand.
+ //
+ // I'd like these to be private, but I build up a static table containing
+ // references to these functions, thus requiring them to be public.
+
+ void DoAbout (EmCommandID);
+ void DoNew (EmCommandID);
+ void DoOpen (EmCommandID);
+ void DoClose (EmCommandID);
+ void DoQuit (EmCommandID);
+
+ void DoDownload (EmCommandID);
+
+ void DoPreferences (EmCommandID);
+ void DoLogging (EmCommandID);
+ void DoDebugging (EmCommandID);
+ void DoErrorHandling (EmCommandID);
+#if HAS_TRACER
+ void DoTracing (EmCommandID);
+#endif
+ void DoSkins (EmCommandID);
+ void DoHostFS (EmCommandID);
+ void DoBreakpoints (EmCommandID);
+
+ void DoReplay (EmCommandID);
+ void DoMinimize (EmCommandID);
+
+ void DoNothing (EmCommandID);
+
+ public:
+ // Bound Poser facilities.
+
+ Bool IsBound (void);
+ Bool IsBoundPartially (void);
+ Bool IsBoundFully (void);
+
+ virtual void BindPoser (Bool /*fullSave*/,
+ const EmFileRef& /*dest*/) {}
+
+ virtual Bool ROMResourcePresent (void) { return false; }
+ virtual Bool GetROMResource (Chunk&) { return false; }
+
+ virtual Bool PSFResourcePresent (void) { return false; }
+ virtual Bool GetPSFResource (Chunk&) { return false; }
+
+ virtual Bool ConfigResourcePresent (void) { return false; }
+ virtual Bool GetConfigResource (Chunk&) { return false; }
+
+ virtual Bool SkinfoResourcePresent (void) { return false; }
+ virtual Bool GetSkinfoResource (Chunk&) { return false; }
+
+ virtual Bool Skin1xResourcePresent (void) { return false; }
+ virtual Bool GetSkin1xResource (Chunk&) { return false; }
+
+ virtual Bool Skin2xResourcePresent (void) { return false; }
+ virtual Bool GetSkin2xResource (Chunk&) { return false; }
+
+ virtual EmDevice GetBoundDevice (void) { return EmDevice (); }
+ virtual RAMSizeType GetBoundRAMSize (void) { return 0; }
+
+ private:
+ Bool CloseDocument (Bool quitting);
+
+ private:
+ Bool fQuit;
+};
+
+extern EmApplication* gApplication;
+
+#endif // EmApplication_h
diff --git a/SrcShared/EmAssert.h b/SrcShared/EmAssert.h
new file mode 100644
index 0000000..7e62b8d
--- /dev/null
+++ b/SrcShared/EmAssert.h
@@ -0,0 +1,45 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmAssert_h
+#define EmAssert_h
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void MyAssertFailed (
+ const char* assertion,
+ const char* file,
+ unsigned int line);
+
+// Use EmAssert to assert only in debug mode.
+// Use EmASSERT to assert even in release mode.
+// The latter should be used only temporarily to
+// find bugs that occur only in release mode.
+
+#define EmASSERT(expr) \
+ ((void) ((expr) ? 0 : \
+ (MyAssertFailed (#expr, \
+ __FILE__, __LINE__), 0)))
+
+#ifdef NDEBUG
+
+ #define EmAssert(expr) ((void) 0)
+
+#else
+
+ #define EmAssert(expr) EmASSERT (expr)
+
+#endif
+
+#endif // EmAssert.h
diff --git a/SrcShared/EmCommands.h b/SrcShared/EmCommands.h
new file mode 100644
index 0000000..7cd0452
--- /dev/null
+++ b/SrcShared/EmCommands.h
@@ -0,0 +1,114 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmCommands_h
+#define EmCommands_h
+
+enum EmCommandID
+{
+ kCommandNone,
+
+ kCommandFirst = 1000, // PowerPlant reserves all up to 999
+
+ kCommandSessionNew = kCommandFirst,
+ kCommandSessionOpenOther,
+ kCommandSessionOpen0,
+ kCommandSessionOpen1,
+ kCommandSessionOpen2,
+ kCommandSessionOpen3,
+ kCommandSessionOpen4,
+ kCommandSessionOpen5,
+ kCommandSessionOpen6,
+ kCommandSessionOpen7,
+ kCommandSessionOpen8,
+ kCommandSessionOpen9,
+ kCommandSessionClose,
+
+ kCommandSessionSave,
+ kCommandSessionSaveAs,
+ kCommandSessionBound,
+ kCommandScreenSave,
+ kCommandSessionInfo,
+
+ kCommandImportOther,
+ kCommandImport0,
+ kCommandImport1,
+ kCommandImport2,
+ kCommandImport3,
+ kCommandImport4,
+ kCommandImport5,
+ kCommandImport6,
+ kCommandImport7,
+ kCommandImport8,
+ kCommandImport9,
+ kCommandExport,
+
+ kCommandHotSync,
+ kCommandReset,
+ kCommandDownloadROM,
+
+ kCommandUndo,
+ kCommandCut,
+ kCommandCopy,
+ kCommandPaste,
+ kCommandClear,
+
+ kCommandPreferences,
+ kCommandLogging,
+ kCommandDebugging,
+ kCommandErrorHandling,
+#if HAS_TRACER
+ kCommandTracing,
+#endif
+ kCommandSkins,
+ kCommandHostFS,
+ kCommandBreakpoints,
+
+ kCommandGremlinsNew,
+ kCommandGremlinsSuspend,
+ kCommandGremlinsStep,
+ kCommandGremlinsResume,
+ kCommandGremlinsStop,
+
+ kCommandEventReplay,
+ kCommandEventMinimize,
+
+#if HAS_PROFILING
+ kCommandProfileStart,
+ kCommandProfileStop,
+ kCommandProfileDump,
+#endif
+
+ kCommandAbout,
+ kCommandQuit,
+
+ kCommandEmpty,
+
+ kCommandFile,
+ kCommandEdit,
+ kCommandGremlins,
+#if HAS_PROFILING
+ kCommandProfile,
+#endif
+
+ kCommandRoot,
+ kCommandOpen,
+ kCommandImport,
+ kCommandSettings,
+
+ kCommandDivider
+};
+
+DEFINE_SCALAR_MODIFIERS (EmCommandID)
+
+#endif // EmCommands_h
diff --git a/SrcShared/EmCommon.cpp b/SrcShared/EmCommon.cpp
new file mode 100644
index 0000000..c8b97a3
--- /dev/null
+++ b/SrcShared/EmCommon.cpp
@@ -0,0 +1,14 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
diff --git a/SrcShared/EmCommon.h b/SrcShared/EmCommon.h
new file mode 100644
index 0000000..f4ca70a
--- /dev/null
+++ b/SrcShared/EmCommon.h
@@ -0,0 +1,141 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmCommon_h
+#define EmCommon_h
+
+// Common header file included by all Palm OS Emulator files.
+
+// ==================================================================================
+// Configuration
+// ==================================================================================
+
+// Define some symbols that control how the Mac and PowerPlant headers are handled.
+// We need to do this here and not in EmCommonMac.h, as including Switches.h and
+// EmTypes.h could pull in some system headers before we have a chance to include
+// EmCommonMac.h.
+
+#define PP_Suppress_Notes_20 1
+#define PP_Suppress_Notes_21 1
+#define PP_Suppress_Notes_22 1
+
+#define PP_Target_Carbon 1
+#define PP_Target_Classic (!PP_Target_Carbon)
+
+#define PP_StdDialogs_Option PP_StdDialogs_NavServicesOnly
+#define PP_Obsolete_ThrowExceptionCode 1
+
+#define TARGET_API_MAC_CARBON PP_Target_Carbon
+#define TARGET_API_MAC_OS8 PP_Target_Classic
+#define OTCARBONAPPLICATION PP_Target_Carbon
+
+
+// Pull in switches that define our configuration. We require that the following
+// symbols be defined externally, but all the rest are defined in Switches.h.
+//
+// _DEBUG or NDEBUG
+// HAS_PROFILING (0 or 1)
+// INCLUDE_SECRET_STUFF (0 or 1)
+
+#include "Switches.h"
+
+
+// ==================================================================================
+// Some very handy macros.
+// ==================================================================================
+
+#define countof(a) (sizeof(a) / sizeof (a[0]))
+
+#define UNUSED_PARAM(x) ((void) x);
+
+#define COMPILE_TIME_ASSERT(x) do { char _dummy[(x) ? 1 : -1]; UNUSED_PARAM (_dummy)} while (0)
+
+#define DEFINE_SCALAR_MODIFIERS(type) \
+ /* Pre-increment operator */ \
+ inline type operator++(type& x) \
+ { \
+ x = type (x + 1); \
+ return x; \
+ } \
+ \
+ /* Post-increment operator */ \
+ inline type operator++(type& x, int) \
+ { \
+ type result = x; \
+ x = type (x + 1); \
+ return result; \
+ } \
+ \
+ /* Pre-decrement operator */ \
+ inline type operator--(type& x) \
+ { \
+ x = type (x - 1); \
+ return x; \
+ } \
+ \
+ /* Post-decrement operator */ \
+ inline type operator--(type& x, int) \
+ { \
+ type result = x; \
+ x = type (x - 1); \
+ return result; \
+ }
+
+
+// ==================================================================================
+// Platform-independent definitions
+// ==================================================================================
+
+#include "EmTypes.h"
+//#include "EmStructs.h"
+
+
+// ==================================================================================
+// Platform-specific definitions
+// ==================================================================================
+
+#if PLATFORM_MAC
+ #include "EmCommonMac.h"
+#endif
+
+#if PLATFORM_UNIX
+ #include "EmCommonUnix.h"
+#endif
+
+#if PLATFORM_WINDOWS
+ #include "EmCommonWin.h"
+#endif
+
+using namespace std;
+
+// Everyone gets EmAssert!
+
+#include "EmAssert.h"
+
+
+// Compile-time checks to see that the sizes are right.
+
+extern char check1 [sizeof(int8) == 1 ? 1 : 0];
+extern char check2 [sizeof(int16) == 2 ? 1 : 0];
+extern char check3 [sizeof(int32) == 4 ? 1 : 0];
+extern char check4 [sizeof(int64) == 8 ? 1 : 0];
+
+extern char check5 [sizeof(uint8) == 1 ? 1 : 0];
+extern char check6 [sizeof(uint16) == 2 ? 1 : 0];
+extern char check7 [sizeof(uint32) == 4 ? 1 : 0];
+extern char check8 [sizeof(uint64) == 8 ? 1 : 0];
+
+extern char check9 [sizeof(emuptr) == 4 ? 1 : 0];
+
+
+#endif /* EmCommon_h */
diff --git a/SrcShared/EmDevice.cpp b/SrcShared/EmDevice.cpp
new file mode 100644
index 0000000..779b1a9
--- /dev/null
+++ b/SrcShared/EmDevice.cpp
@@ -0,0 +1,1374 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDevice.h"
+
+/*
+ This file controls the creation of a new device in the Palm OS
+ Emulator. In order to add a new device to the set of supported
+ devices:
+
+ * Add a new kDeviceFoo value to DeviceType.
+
+ * Add information about the new device to the kDeviceInfo array.
+
+ * Define and add a sub-class of EmRegs to describe the hardware
+ registers for the device (e.g., EmRegsEZPalmV). This sub-class
+ can be a typedef of another sub-class if the hardware is the
+ same (e.g., EmRegsEZPalmVx).
+
+ * Define and add any other EmRegs sub-classes as needed if the
+ device has any special hardware needs (e.g., EmRegsUSBVisor).
+
+ * Add a new "case" statement in CreateRegs that creates the
+ appropriate EmRegs sub-classes.
+
+ * If your needs are extensive and creating a sub-class of EmRegs
+ isn't sufficient, then consider creating a new EmBankFoo and
+ managing that in EmMemory.cpp along with all the other EmBankFoos.
+
+ * Modify SupportsROM to make sure that your device appears on the
+ device list when your ROM is selected, and try to make sure that
+ it does not appear for other ROMs. If ROMs for this device can
+ be identified via companyID and halID fields in the card header,
+ then you don't need to do anything here.
+*/
+
+#include "Platform.h" // _stricmp
+
+#include "EmBankRegs.h" // AddSubBank
+#include "EmROMReader.h" // EmROMReader
+#include "EmStreamFile.h" // EmStreamFile
+#include "Miscellaneous.h" // StMemory
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "HwrMiscFlags.h" // hwrMiscFlagIDTouchdown, etc.
+
+ #ifndef hwrMiscFlagIDPalmIIIc
+ #define hwrMiscFlagIDPalmIIIc (hwrMiscFlagID4 | hwrMiscFlagID1)
+ #endif
+
+ // The m100 ID has changed
+ #undef hwrMiscFlagIDm100
+ #define hwrMiscFlagIDm100 (hwrMiscFlagID3 | hwrMiscFlagID1)
+
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+#include "EmCPU68K.h"
+#include "EmCPUARM.h"
+
+#include "EmRegs328Pilot.h"
+#include "EmRegs328PalmPilot.h"
+#include "EmRegs328PalmIII.h"
+#include "EmRegs328PalmVII.h"
+#include "EmRegs328Symbol1700.h"
+
+#include "EmRegsEZPalmIIIc.h"
+#include "EmRegsEZPalmIIIe.h"
+#include "EmRegsEZPalmIIIx.h"
+#include "EmRegsEZPalmV.h"
+#include "EmRegsEZPalmVx.h"
+#include "EmRegsEZPalmVII.h"
+#include "EmRegsEZPalmVIIx.h"
+#include "EmRegsEZPalmM100.h"
+#include "EmRegsEZVisor.h"
+#include "EmRegsEZTemp.h"
+
+#include "EmRegsSZTemp.h"
+
+#include "EmRegsVZPalmM500.h"
+#include "EmRegsVZPalmM505.h"
+#include "EmRegsVZVisorPrism.h"
+#include "EmRegsVZVisorPlatinum.h"
+#include "EmRegsVZVisorEdge.h"
+#include "EmRegsVZTemp.h"
+
+#include "EmRegsASICSymbol1700.h"
+#include "EmRegsFrameBuffer.h"
+#include "EmRegsPLDPalmVIIEZ.h"
+#include "EmRegsSED1375.h"
+#include "EmRegsSED1376.h"
+#include "EmRegsUSBPhilipsPDIUSBD12.h"
+#include "EmRegsUSBVisor.h"
+
+#include "EmTRG.h"
+
+#include "EmRegsMediaQ11xx.h"
+
+
+enum // DeviceType
+{
+ kDeviceUnspecified = 0,
+ kDevicePilot,
+ kDevicePalmPilot,
+ kDevicePalmIII,
+ kDevicePalmIIIc,
+ kDevicePalmIIIe,
+ kDevicePalmIIIx,
+ kDevicePalmV,
+ kDevicePalmVx,
+ kDevicePalmVII,
+ kDevicePalmVIIEZ,
+ kDevicePalmVIIx,
+ kDevicePalmM100,
+ kDevicePalmM125,
+ kDevicePalmM130,
+ kDevicePalmM500,
+ kDevicePalmM505,
+ kDevicePalmM515,
+ kDevicePalmI705,
+ kDeviceARMRef,
+ kDeviceSymbol1500,
+ kDeviceSymbol1700,
+ kDeviceSymbol1740,
+ kDeviceTRGpro,
+ kDeviceHandEra330,
+ kDeviceVisor,
+ kDeviceVisorPrism,
+ kDeviceVisorPlatinum,
+ kDeviceVisorEdge,
+ kDeviceLast
+};
+
+struct DeviceInfo
+{
+ int fDeviceID;
+
+ const char* fDeviceMenuName; // This string appears in the Device menu.
+
+ const char* fDeviceNames[8]; // These strings can be specified on the command line
+ // to specify that this device be emulated. The first
+ // string in the array is also the "preferred" string,
+ // in that it is used to identify the device in the
+ // Preferences and Session files.
+
+ uint32 fFlags; // One or more of the flags below.
+
+ RAMSizeType fMinRAMSize; // Minimum RAM size (in K). Used to prune back the
+ // RAM size menu.
+
+ long fHardwareID; // Some devices have a hardware ID they report via
+ // hardware register munging.
+
+ long fHardwareSubID; // Some devices have a hardware sub-ID they report via
+ // hardware registr munging.
+
+ struct
+ {
+ uint32 fCompanyID; // The "companyID" field in a v5 CardHeader. This field
+ // is used to identify which ROMs can run on which devices.
+ // Set it to zero if the ROM for your device doesn't have
+ // a v5 CardHeader.
+
+ uint32 fHalID; // The "halID" field in a v5 CardHeader. This field
+ // is used to identify which ROMs can run on which devices.
+ // Set it to zero if the ROM for your device doesn't have
+ // a v5 CardHeader.
+
+ } fCardHeaderInfo[1]; // It's possible that in the future, more than one HAL
+ // could properly execute on this device. Make this an
+ // array so that we can add more than one HAL ID.
+};
+
+
+// (None of these values are (is?) exposed, so they can be freely reordered.)
+
+static const uint32 kSupports68328 = 0x00000001;
+static const uint32 kSupports68EZ328 = 0x00000002;
+static const uint32 kSupports68VZ328 = 0x00000004;
+static const uint32 kSupports68SZ328 = 0x00000008;
+static const uint32 kSupportsARM = 0x00000010;
+
+static const uint32 kHasFlash = 0x00000100;
+
+static const long hwrMiscFlagIDNone = 0xFF;
+static const long hwrMiscFlagExtSubIDNone = 0xFF;
+
+#define UNSUPPORTED 0
+
+
+/* Miscellaneous symbols used to discriminate between ROMs. Do not assume that
+ these are meant to convey actual ownership or documented interfaces. */
+
+#define PALM_MANUF "Palm Computing"
+#define HANDSPRING_MANUF "Handspring, Inc."
+#define SYMBOL_DB "ScanMgr"
+#define SYMBOL_1500_DB "ResetApp" // But not available in 3.5 version of 1500 ROM
+#define SYMBOL_1700_DB "ResetAppScan" // But now also available in 3.5 version of 1500 ROM
+#define SYMBOL_1740_DB "S24PowerDown" // Only on 1740s, which have the Spectrum 24 wireless
+#define PALM_VII_DB "WMessaging"
+#define PALM_VII_IF1_DB "RAM NetIF"
+#define PALM_VII_IF2_DB "RAM NetIFRM"
+#define PALM_VII_EZ_NEW_DB "TuneUp"
+#define PALM_VIIX_DB "iMessenger"
+#define PALM_m100_DB "cclkPalmClock"
+
+
+// Table used to describe the various hardware devices we support.
+// Some good summary background information is at:
+//
+// <http://www.palmos.com/dev/tech/hardware/compare.html>
+
+static const DeviceInfo kDeviceInfo[] =
+{
+ // ===== Palm Devices =====
+ {
+ kDevicePilot, "Pilot",
+ { "Pilot", "Pilot1000", "Pilot5000", "TD", "Touchdown" },
+ kSupports68328, 128, hwrMiscFlagIDTouchdown, hwrMiscFlagExtSubIDNone,
+ },
+ {
+ kDevicePalmPilot, "PalmPilot",
+ { "PalmPilot", "PalmPilotPersonal", "PalmPilotProfessional", "Striker" },
+ kSupports68328, 128, hwrMiscFlagIDPalmPilot, hwrMiscFlagExtSubIDNone,
+ },
+ {
+ kDevicePalmIII, "Palm III",
+ { "PalmIII", "Rocky" },
+ kSupports68328 + kHasFlash, 512, hwrMiscFlagIDRocky, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'rcky' }}
+ },
+ {
+ kDevicePalmIIIc, "Palm IIIc",
+ { "PalmIIIc", "Austin", "ColorDevice" },
+ kSupports68EZ328 + kHasFlash, 8192, hwrMiscFlagIDPalmIIIc, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'astn' }}
+ },
+ {
+ kDevicePalmIIIe, "Palm IIIe",
+ { "PalmIIIe", "Robinson" },
+ kSupports68EZ328, 2048, hwrMiscFlagIDBrad, hwrMiscFlagExtSubIDBrad,
+ },
+ {
+ kDevicePalmIIIx, "Palm IIIx",
+ { "PalmIIIx", "Brad" },
+ kSupports68EZ328 + kHasFlash, 4096, hwrMiscFlagIDBrad, hwrMiscFlagExtSubIDBrad,
+ {{ 'palm', 'sumo' }}
+ },
+ {
+ kDevicePalmV, "Palm V",
+ { "PalmV", "Razor", "Sumo" },
+ kSupports68EZ328 + kHasFlash, 2048, hwrMiscFlagIDSumo, hwrMiscFlagExtSubIDSumo,
+ {{ 'palm', 'sumo' }}
+ },
+ {
+ kDevicePalmVx, "Palm Vx",
+ { "PalmVx", "Cobra" },
+ kSupports68EZ328 + kHasFlash, 8192, hwrMiscFlagIDSumo, hwrMiscFlagExtSubIDCobra,
+ {{ 'palm', 'sumo' }}
+ },
+ {
+ kDevicePalmVII, "Palm VII",
+ { "PalmVII", "Jerry", "Eleven" },
+ kSupports68328 + kHasFlash, 2048, hwrMiscFlagIDJerry, hwrMiscFlagExtSubIDNone,
+ },
+ {
+ kDevicePalmVIIEZ, "Palm VII (EZ)",
+ { "PalmVIIEZ", "Bonanza" },
+ kSupports68EZ328 + kHasFlash, 2048, hwrMiscFlagIDJerryEZ, 0,
+ // sub-id *should* be hwrMiscFlagExtSubIDNone, but
+ // a bug in Rangoon (OS 3.5 for Palm VII EZ) has it
+ // accidentally looking for and using the sub-id. In
+ // order to get the hard keys to work, we need to
+ // return zero here.
+ },
+ {
+ kDevicePalmVIIx, "Palm VIIx",
+ { "PalmVIIx", "Octopus" },
+ kSupports68EZ328 + kHasFlash, 8192, hwrMiscFlagIDJerryEZ, hwrMiscFlagExtSubIDBrad,
+ // David Mai says that he *guesses* that the sub-id is zero
+ },
+ {
+ kDevicePalmM100, "Palm m100",
+ { "PalmM100", "m100", "Calvin" },
+ kSupports68EZ328, 2048, hwrMiscFlagIDm100, hwrMiscFlagExtSubIDBrad,
+ {{ 'palm', 'clvn' }}
+ },
+ {
+ kDevicePalmM125, "Palm m125",
+ { "PalmM125", "m120", "m125", "m110", "m115", "JV", "Stu" },
+ kSupports68VZ328 + kHasFlash, 2048, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'vstu' }}
+ },
+ {
+ kDevicePalmM130, "Palm m130",
+ { "PalmM130", "m130", "Hobbes", "PalmM130" },
+ kSupports68VZ328, 8192, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'vhbs' }}
+ },
+ {
+ kDevicePalmM500, "Palm m500",
+ { "PalmM500", "m500", "Tornado" },
+ kSupports68VZ328 + kHasFlash, 8192, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'vtrn' }}
+ },
+ {
+ kDevicePalmM505, "Palm m505",
+ { "PalmM505", "m505", "EmeraldCity", "VZDevice" },
+ kSupports68VZ328 + kHasFlash, 8192, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'ecty' }}
+ },
+ {
+ kDevicePalmM515, "Palm m515",
+ { "PalmM515", "m515", "PalmM525", "m525", "Lighthouse", "GatorReef" },
+ kSupports68VZ328 + kHasFlash, 16384, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'vlit' }}
+ },
+ {
+ kDevicePalmI705, "Palm i705",
+ { "PalmI705", "i705", "Everest", "PalmI705" },
+ kSupports68VZ328 + kHasFlash, 8192, hwrMiscFlagIDNone, hwrMiscFlagExtSubIDNone,
+ {{ 'palm', 'skyw' }}
+ },
+ {
+ kDeviceARMRef, "ARM Ref",
+ { "ARMRef" },
+ kSupportsARM, 0, 0
+ },
+
+ // ===== Symbol devices =====
+ {
+ kDeviceSymbol1500, "Symbol 1500",
+ { "Symbol1500" },
+ kSupports68328 + kHasFlash, 2048, hwrMiscFlagIDRocky, hwrMiscFlagExtSubIDNone,
+ },
+ {
+ kDeviceSymbol1700, "Symbol 1700",
+ { "Symbol1700" },
+ kSupports68328 + kHasFlash, 2048, hwrMiscFlagIDRocky, hwrMiscFlagExtSubIDNone,
+ },
+ {
+ kDeviceSymbol1740, "Symbol 1740",
+ { "Symbol1740" },
+ kSupports68328 + kHasFlash, 2048, hwrMiscFlagIDRocky, hwrMiscFlagExtSubIDNone,
+ },
+
+ // ===== TRG/HandEra devices =====
+
+ {
+ kDeviceTRGpro, "TRGpro",
+ { "TRGpro" },
+ kSupports68EZ328 + kHasFlash, 8192, hwrOEMCompanyIDTRG, hwrTRGproID,
+ {{ 'trgp', 'trg1' }}
+ },
+
+ {
+ kDeviceHandEra330, "HandEra 330",
+ { "HandEra330" },
+ kSupports68VZ328 + kHasFlash, 8192, hwrOEMCompanyIDTRG, hwrTRGproID + 1,
+ {{ 'trgp', 'trg2' }}
+ },
+
+ // ===== Handspring devices =====
+ {
+ kDeviceVisor, "Visor",
+ { "Visor", "Lego" },
+ kSupports68EZ328, 2048, halModelIDLego, 0, // Hardware ID for first Visor
+ },
+ {
+ kDeviceVisorPlatinum, "Visor Platinum",
+ { "VisorPlatinum" },
+ kSupports68VZ328, 8192, halModelIDVisorPlatinum, 0
+ },
+ {
+ kDeviceVisorPrism, "Visor Prism",
+ { "VisorPrism" },
+ kSupports68VZ328, 8192, halModelIDVisorPrism, 0
+ },
+ {
+ kDeviceVisorEdge, "Visor Edge",
+ { "VisorEdge" },
+ kSupports68VZ328, 8192, halModelIDVisorEdge, 0
+ }
+};
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::EmDevice
+ *
+ * DESCRIPTION: Constructors
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDevice::EmDevice (void) :
+ fDeviceID (kDeviceUnspecified)
+{
+}
+
+
+EmDevice::EmDevice (int id) :
+ fDeviceID (id)
+{
+}
+
+
+EmDevice::EmDevice (const char* s) :
+ fDeviceID (this->GetDeviceID (s))
+{
+}
+
+
+EmDevice::EmDevice (const string& s) :
+ fDeviceID (this->GetDeviceID (s.c_str ()))
+{
+}
+
+
+EmDevice::EmDevice (const EmDevice& other) :
+ fDeviceID (other.fDeviceID)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::~EmDevice
+ *
+ * DESCRIPTION: Destructor
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDevice::~EmDevice (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::operator==
+ * FUNCTION: EmDevice::operator!=
+ *
+ * DESCRIPTION: Destructor
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+bool EmDevice::operator== (const EmDevice& other) const
+{
+ return fDeviceID == other.fDeviceID;
+}
+
+
+bool EmDevice::operator!= (const EmDevice& other) const
+{
+ return fDeviceID != other.fDeviceID;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::Supported
+ *
+ * DESCRIPTION: Returns whether or not this EmDevice represents a device
+ * we currently support emulating.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::Supported (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return info != NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::Supports68328
+ *
+ * DESCRIPTION: Returns whether or not this device is based on the
+ * MC68328.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::Supports68328 (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kSupports68328) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::Supports68EZ328
+ *
+ * DESCRIPTION: Returns whether or not this device is based on the
+ * MC68EZ328.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::Supports68EZ328 (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kSupports68EZ328) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::Supports68VZ328
+ *
+ * DESCRIPTION: Returns whether or not this device is based on the
+ * MC68VZ328.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::Supports68VZ328 (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kSupports68VZ328) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::Supports68SZ328
+ *
+ * DESCRIPTION: Returns whether or not this device is based on the
+ * MC68SZ328.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::Supports68SZ328 (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kSupports68SZ328) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::SupportsARM
+ *
+ * DESCRIPTION: Returns whether or not this device is based on the
+ * MC68VZ328.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::SupportsARM (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kSupportsARM) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::PrismPlatinumEdgeHack
+ *
+ * DESCRIPTION: Handspring's Prism, Platinum, and Edge have card headers
+ * saying they run on EZ's when they really run on VZ's.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::PrismPlatinumEdgeHack (void) const
+{
+ return fDeviceID == kDeviceVisorPrism ||
+ fDeviceID == kDeviceVisorPlatinum ||
+ fDeviceID == kDeviceVisorEdge;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::EdgeHack
+ *
+ * DESCRIPTION: Handspring's Edge uses bit 3 of port D for powered-cradle
+ * detection, so we need to apply a few hacks.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::EdgeHack (void) const
+{
+ return fDeviceID == kDeviceVisorEdge;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::SupportsROM
+ *
+ * DESCRIPTION: Returns whether or not this device can support the
+ * execution of a particular ROM.
+ *
+ * PARAMETERS: A reference to an EmROMReader object. Hopefully one
+ * that has successfully acquired the details of a ROM.
+ *
+ * RETURNED: True if ROM is supported by device.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::SupportsROM (const EmFileRef& romFileRef) const
+{
+ // Load the ROM image into memory.
+
+ EmStreamFile romStream (romFileRef, kOpenExistingForRead);
+ StMemory romImage (romStream.GetLength ());
+
+ romStream.GetBytes (romImage.Get (), romStream.GetLength ());
+
+ // Create a ROM Reader on the ROM image.
+
+ EmROMReader reader (romImage.Get (), romStream.GetLength ());
+
+ // Grovel over the ROM.
+
+ if (reader.AcquireCardHeader ())
+ {
+ UInt16 version = reader.GetCardVersion ();
+
+ if (version < 5)
+ {
+ reader.AcquireROMHeap ();
+ reader.AcquireDatabases ();
+ reader.AcquireFeatures ();
+ reader.AcquireSplashDB ();
+ }
+ }
+
+ return this->SupportsROM (reader);
+}
+
+
+Bool EmDevice::SupportsROM (const EmROMReader& ROM) const
+{
+ /* If the ROM is recent enough, use the embedded hardware ID information
+ to determine whether it will work with this device */
+
+ if (ROM.GetCardVersion () >= 5)
+ {
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+ for (size_t ii = 0; ii < countof (info->fCardHeaderInfo); ++ii)
+ {
+ if (info->fCardHeaderInfo[ii].fCompanyID &&
+ info->fCardHeaderInfo[ii].fHalID &&
+ info->fCardHeaderInfo[ii].fCompanyID == ROM.GetCompanyID () &&
+ info->fCardHeaderInfo[ii].fHalID == ROM.GetHalID ())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /* Otherwise, we will use miscellaneous pieces of data to heuristically
+ discriminate between ROMs. Do not assume that any of these tests are
+ meant to convey ownership or documented interfaces. */
+
+ bool is7 = ROM.ContainsDB (PALM_VII_IF1_DB) || ROM.ContainsDB (PALM_VII_IF2_DB);
+ bool is328 = (ROM.GetCardVersion () <= 2) || ROM.GetFlag328 ();
+ bool isColor = ROM.GetSplashChunk () && (ROM.IsBitmapColor (*ROM.GetSplashChunk (), true) == 1);
+
+ if (Supports68328 () && !is328)
+ return false;
+ else if (Supports68EZ328 () && !ROM.GetFlagEZ ())
+ return false;
+ else if (Supports68VZ328 () && !ROM.GetFlagVZ ())
+ {
+ /* Make a hack for the Prism, Platinum and Edge below since
+ Handspring seems to report the EZ bit in their ROMs. */
+
+ if (!this->PrismPlatinumEdgeHack ())
+ {
+ return false;
+ }
+ }
+
+ switch (fDeviceID)
+ {
+ case kDeviceUnspecified:
+ return false;
+ break;
+
+ case kDevicePilot:
+ if ((ROM.Version () < 0x020000) &&
+ (ROM.GetCardManufacturer () == PALM_MANUF)
+ )
+ return true;
+ break;
+
+ case kDevicePalmPilot:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () >= 0x020000) &&
+ (ROM.Version () < 0x030000)
+ )
+ return true;
+ break;
+
+ case kDevicePalmIII:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () >= 0x030000) &&
+ !ROM.ContainsDB (SYMBOL_DB) &&
+ !is7
+ )
+ return true;
+ break;
+
+ case kDevicePalmIIIc:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ !ROM.ContainsDB (PALM_m100_DB) &&
+ !is7 &&
+ isColor
+ )
+ return true;
+ break;
+
+ case kDevicePalmIIIe:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ !ROM.ContainsDB (PALM_m100_DB) &&
+ !is7 &&
+ !isColor &&
+ (ROM.Version () == 0x030100)
+ )
+ return true;
+ break;
+
+ case kDevicePalmIIIx:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ !ROM.ContainsDB (PALM_m100_DB) &&
+ !is7 &&
+ !isColor
+ )
+ return true;
+ break;
+
+ case kDevicePalmV:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ !ROM.ContainsDB (PALM_m100_DB) &&
+ !is7 &&
+ !isColor
+ )
+ return true;
+ break;
+
+ case kDevicePalmVx:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ !ROM.ContainsDB (PALM_m100_DB) &&
+ !is7 &&
+ !isColor &&
+ (ROM.Version () >= 0x030300)
+ )
+ return true;
+ break;
+
+ case kDevicePalmVII:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () >= 0x030000) &&
+ !ROM.ContainsDB (SYMBOL_DB) &&
+ is7
+ )
+ return true;
+ break;
+
+ case kDevicePalmVIIEZ:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ is7 &&
+ (!ROM.ContainsDB (PALM_VIIX_DB) ||
+ ROM.ContainsDB (PALM_VII_EZ_NEW_DB)) &&
+ !isColor
+ )
+ return true;
+ break;
+
+ case kDevicePalmVIIx:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ is7 &&
+ ROM.ContainsDB (PALM_VIIX_DB) &&
+ !ROM.ContainsDB (PALM_VII_EZ_NEW_DB) &&
+ !isColor
+ )
+ return true;
+ break;
+
+ case kDevicePalmM100:
+ if (ROM.ContainsDB (PALM_m100_DB))
+ return true;
+ break;
+
+ case kDeviceSymbol1500:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () < 0x030500) &&
+ ROM.ContainsDB (SYMBOL_1500_DB) &&
+ !ROM.ContainsDB (SYMBOL_1700_DB) &&
+ !ROM.ContainsDB (SYMBOL_1740_DB)
+ )
+ return true;
+ break;
+
+ case kDeviceSymbol1700:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () < 0x030500) &&
+ !ROM.ContainsDB (SYMBOL_1500_DB) &&
+ ROM.ContainsDB (SYMBOL_1700_DB) &&
+ !ROM.ContainsDB (SYMBOL_1740_DB)
+ )
+ return true;
+ break;
+
+ case kDeviceSymbol1740:
+ if ((ROM.GetCardManufacturer () == PALM_MANUF) &&
+ (ROM.Version () < 0x030500) &&
+ !ROM.ContainsDB (SYMBOL_1500_DB) &&
+ ROM.ContainsDB (SYMBOL_1700_DB) &&
+ ROM.ContainsDB (SYMBOL_1740_DB)
+ )
+ return true;
+ break;
+
+ case kDeviceTRGpro:
+ case kDeviceHandEra330:
+ if (ROM.GetCardManufacturer () == TRGPRO_MANUF)
+ return true;
+ break;
+
+ case kDeviceVisor:
+ if ((ROM.GetCardManufacturer () == HANDSPRING_MANUF) &&
+ (ROM.Version () == 0x030100)
+ )
+ return true;
+ break;
+
+ case kDeviceVisorPrism:
+ if ((ROM.GetCardManufacturer () == HANDSPRING_MANUF) &&
+ (ROM.Version () >= 0x030500)
+ )
+ return true;
+ break;
+
+ case kDeviceVisorPlatinum:
+ if ((ROM.GetCardManufacturer () == HANDSPRING_MANUF) &&
+ (ROM.Version () >= 0x030500)
+ )
+ return true;
+ break;
+
+ case kDeviceVisorEdge:
+ if ((ROM.GetCardManufacturer () == HANDSPRING_MANUF) &&
+ (ROM.Version () >= 0x030500)
+ )
+ return true;
+ break;
+
+ case kDeviceLast:
+ EmAssert (false);
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::CreateCPU
+ *
+ * DESCRIPTION: Create the CPU object.
+ *
+ * PARAMETERS: session - EmSession object used to initialize the CPU
+ * object.
+ *
+ * RETURNED: Pointer to the created object. Caller is responsible
+ * for destroying the object when it's done with it.
+ *
+ ***********************************************************************/
+
+EmCPU* EmDevice::CreateCPU (EmSession* session) const
+{
+ EmCPU* result = NULL;
+
+ if (this->Supports68328 () ||
+ this->Supports68EZ328 () ||
+ this->Supports68VZ328 () ||
+ this->Supports68SZ328 ())
+ {
+ result = new EmCPU68K (session);
+ }
+ else if (this->SupportsARM ())
+ {
+ result = new EmCPUARM (session);
+ }
+
+ EmAssert (result);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::CreateRegs
+ *
+ * DESCRIPTION: Create the register object that manages the Dragonball
+ * (or derivative) hardware registers.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Pointer to the created object. Caller is responsible
+ * for destroying the object when it's done with it.
+ *
+ ***********************************************************************/
+
+void EmDevice::CreateRegs (void) const
+{
+ switch (fDeviceID)
+ {
+ case kDevicePilot:
+ EmBankRegs::AddSubBank (new EmRegs328Pilot);
+ break;
+
+ case kDevicePalmPilot:
+ EmBankRegs::AddSubBank (new EmRegs328PalmPilot);
+ break;
+
+ case kDevicePalmIII:
+ EmBankRegs::AddSubBank (new EmRegs328PalmIII);
+ break;
+
+ case kDevicePalmIIIc:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmIIIc);
+ EmBankRegs::AddSubBank (new EmRegsSED1375 ((emuptr) sed1375RegsAddr, sed1375BaseAddress));
+ EmBankRegs::AddSubBank (new EmRegsFrameBuffer (sed1375BaseAddress, sed1375VideoMemSize));
+ break;
+
+ case kDevicePalmIIIe:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmIIIe);
+ break;
+
+ case kDevicePalmIIIx:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmIIIx);
+ break;
+
+ case kDevicePalmV:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmV);
+ break;
+
+ case kDevicePalmVx:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmVx);
+ break;
+
+ case kDevicePalmVII:
+ EmBankRegs::AddSubBank (new EmRegs328PalmVII);
+ break;
+
+ case kDevicePalmVIIEZ:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmVII);
+ EmBankRegs::AddSubBank (new EmRegsPLDPalmVIIEZ);
+ break;
+
+ case kDevicePalmVIIx:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmVIIx);
+ EmBankRegs::AddSubBank (new EmRegsPLDPalmVIIEZ);
+ break;
+
+ case kDevicePalmM100:
+ EmBankRegs::AddSubBank (new EmRegsEZPalmM100);
+ break;
+
+ case kDevicePalmM125:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmM125);
+ EmBankRegs::AddSubBank (new EmRegsUSBPhilipsPDIUSBD12 (0x1F000000));
+ break;
+
+ case kDevicePalmM130:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmM130);
+ EmBankRegs::AddSubBank (new EmRegsMediaQ11xx (MMIO_BASE, T_BASE));
+ EmBankRegs::AddSubBank (new EmRegsFrameBuffer (T_BASE, MMIO_OFFSET));
+ break;
+
+ case kDevicePalmM500:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmM500);
+ EmBankRegs::AddSubBank (new EmRegsUSBPhilipsPDIUSBD12 (0x10400000));
+ break;
+
+ case kDevicePalmM505:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmM505);
+ EmBankRegs::AddSubBank (new EmRegsSED1376PalmGeneric (sed1376RegsAddr, sed1376VideoMemStart));
+ EmBankRegs::AddSubBank (new EmRegsFrameBuffer (sed1376VideoMemStart, sed1376VideoMemSize));
+ EmBankRegs::AddSubBank (new EmRegsUSBPhilipsPDIUSBD12 (0x10400000));
+ break;
+
+ case kDevicePalmM515:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmM505);
+ EmBankRegs::AddSubBank (new EmRegsSED1376PalmGeneric (sed1376RegsAddr, sed1376VideoMemStart));
+ EmBankRegs::AddSubBank (new EmRegsFrameBuffer (sed1376VideoMemStart, sed1376VideoMemSize));
+ EmBankRegs::AddSubBank (new EmRegsUSBPhilipsPDIUSBD12 (0x10400000));
+ break;
+
+ case kDevicePalmI705:
+ EmBankRegs::AddSubBank (new EmRegsVZPalmI705);
+ EmBankRegs::AddSubBank (new EmRegsPLDPalmI705 (0x11000000));
+ EmBankRegs::AddSubBank (new EmRegsUSBPhilipsPDIUSBD12 (0x1F000000));
+ break;
+
+ case kDeviceARMRef:
+ break;
+
+ case kDeviceSymbol1500:
+ EmBankRegs::AddSubBank (new EmRegs328PalmIII);
+ break;
+
+ case kDeviceSymbol1700:
+ EmBankRegs::AddSubBank (new EmRegs328Symbol1700);
+ EmBankRegs::AddSubBank (new EmRegsASICSymbol1700);
+ break;
+
+ case kDeviceSymbol1740:
+ EmBankRegs::AddSubBank (new EmRegs328Symbol1700);
+ EmBankRegs::AddSubBank (new EmRegsASICSymbol1700);
+ break;
+
+ case kDeviceTRGpro:
+ OEMCreateTRGRegObjs (hwrTRGproID);
+ break;
+
+ case kDeviceHandEra330:
+ OEMCreateTRGRegObjs (hwrTRGproID + 1);
+ break;
+
+ case kDeviceVisor:
+ EmBankRegs::AddSubBank (new EmRegsEZVisor);
+ EmBankRegs::AddSubBank (new EmRegsUSBVisor);
+ break;
+
+ case kDeviceVisorPrism:
+ EmBankRegs::AddSubBank (new EmRegsVZVisorPrism);
+ EmBankRegs::AddSubBank (new EmRegsSED1376VisorPrism (0x11800000, 0x11820000));
+ EmBankRegs::AddSubBank (new EmRegsFrameBuffer (0x11820000, 80 * 1024L));
+ EmBankRegs::AddSubBank (new EmRegsUSBVisor);
+ break;
+
+ case kDeviceVisorPlatinum:
+ EmBankRegs::AddSubBank (new EmRegsVZVisorPlatinum);
+ EmBankRegs::AddSubBank (new EmRegsUSBVisor);
+ break;
+
+ case kDeviceVisorEdge:
+ EmBankRegs::AddSubBank (new EmRegsVZVisorEdge);
+ EmBankRegs::AddSubBank (new EmRegsUSBVisor);
+ break;
+
+ default:
+ break;
+ }
+
+ EmHAL::EnsureCoverage ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::HasFlash
+ *
+ * DESCRIPTION: Returns whether or not this device uses Flash RAM.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmDevice::HasFlash (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return (info->fFlags & kHasFlash) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::MinRAMSize
+ *
+ * DESCRIPTION: Returns the minimum RAM size that this device should
+ * be configured with. Some devices can't operate lower
+ * than the levels they ship with, as they run out of
+ * memory and crash.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Minimum RAM size, in K (so 1024 == 1 Meg).
+ *
+ ***********************************************************************/
+
+RAMSizeType EmDevice::MinRAMSize (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+ return info->fMinRAMSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::HardwareID
+ *
+ * DESCRIPTION: Returns the hardware ID of this device. This ID is the
+ * one that eventually gets put into GHwrMiscGFlags by
+ * HwrIdentifyFeatures.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The device's hardware ID.
+ *
+ ***********************************************************************/
+
+long EmDevice::HardwareID (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+// EmAssert (info->fHardwareID != hwrMiscFlagIDNone);
+
+ return info->fHardwareID;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::HardwareSubID
+ *
+ * DESCRIPTION: Returns the hardware ID of this device. This ID is the
+ * one that eventually gets put into GHwrMiscGFlags by
+ * HwrIdentifyFeatures.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The device's hardware ID.
+ *
+ ***********************************************************************/
+
+long EmDevice::HardwareSubID (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+ EmAssert (info->fHardwareSubID != hwrMiscFlagExtSubIDNone);
+
+ return info->fHardwareSubID;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetMenuString
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+string EmDevice::GetMenuString (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+ return string (info->fDeviceMenuName);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetIDString
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+string EmDevice::GetIDString (void) const
+{
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+ return string (info->fDeviceNames[0]);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetIDStrings
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+StringList EmDevice::GetIDStrings (void) const
+{
+ StringList result;
+
+ const DeviceInfo* info = this->GetDeviceInfo ();
+
+ size_t ii = 0;
+ while (ii < countof (info->fDeviceNames) && info->fDeviceNames[ii])
+ {
+ result.push_back (string (info->fDeviceNames[ii]));
+ ++ii;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetDeviceList
+ *
+ * DESCRIPTION: Return the list of devices Poser emulates.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Collection containing the results.
+ *
+ ***********************************************************************/
+
+EmDeviceList EmDevice::GetDeviceList (void)
+{
+ EmDeviceList result;
+
+ for (size_t ii = 0; ii < countof (kDeviceInfo); ++ii)
+ {
+ const DeviceInfo* info = &kDeviceInfo[ii];
+
+ result.push_back (EmDevice (info->fDeviceID));
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetDeviceInfo
+ *
+ * DESCRIPTION: Look up and return the DeviceInfo block for the
+ * managed device.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Const pointer to the DeviceInfo block.
+ *
+ ***********************************************************************/
+
+const DeviceInfo* EmDevice::GetDeviceInfo (void) const
+{
+ for (size_t ii = 0; ii < countof (kDeviceInfo); ++ii)
+ {
+ const DeviceInfo* info = &kDeviceInfo[ii];
+
+ if (info->fDeviceID == fDeviceID)
+ return info;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDevice::GetDeviceID
+ *
+ * DESCRIPTION: Look up and return the unique ID for the
+ * managed device.
+ *
+ * PARAMETERS: s - a string identifying the device. Can be any of the
+ * strings in the fDeviceNames in the DeviceInfo array.
+ * The comparison to this string is case-insensitive.
+ *
+ * RETURNED: The device's unique ID. kDeviceUnspecified if a match
+ * could not be found.
+ *
+ ***********************************************************************/
+
+int EmDevice::GetDeviceID (const char* s) const
+{
+ // Iterate over each entry in the kDeviceInfo array.
+
+ for (size_t ii = 0; ii < countof (kDeviceInfo); ++ii)
+ {
+ const DeviceInfo* info = &kDeviceInfo[ii];
+
+ // Iterate over each string in the fDeviceNames array.
+
+ size_t jj = 0;
+ while (jj < countof (info->fDeviceNames) && info->fDeviceNames[jj])
+ {
+ // If we find a match, return the unique ID.
+
+ if (_stricmp (info->fDeviceNames[jj], s) == 0)
+ {
+ return info->fDeviceID;
+ }
+
+ ++jj;
+ }
+ }
+
+ // No match.
+
+ return kDeviceUnspecified;
+}
diff --git a/SrcShared/EmDevice.h b/SrcShared/EmDevice.h
new file mode 100644
index 0000000..4e876cc
--- /dev/null
+++ b/SrcShared/EmDevice.h
@@ -0,0 +1,84 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDevice_h
+#define EmDevice_h
+
+#include <vector> // vector
+#include <utility> // pair
+#include <string> // string
+
+class EmCPU;
+class EmFileRef;
+class EmRegs;
+class EmSession;
+struct DeviceInfo;
+
+class EmROMReader;
+
+class EmDevice;
+typedef vector<EmDevice> EmDeviceList;
+
+
+class EmDevice
+{
+ public:
+ EmDevice (void);
+ EmDevice (const char*);
+ EmDevice (const string&);
+ EmDevice (const EmDevice&);
+ ~EmDevice (void);
+
+ bool operator== (const EmDevice&) const;
+ bool operator!= (const EmDevice&) const;
+
+ Bool Supported (void) const;
+
+ Bool Supports68328 (void) const;
+ Bool Supports68EZ328 (void) const;
+ Bool Supports68VZ328 (void) const;
+ Bool Supports68SZ328 (void) const;
+ Bool SupportsARM (void) const;
+
+ Bool PrismPlatinumEdgeHack (void) const;
+ Bool EdgeHack (void) const;
+
+ Bool SupportsROM (const EmFileRef&) const;
+ Bool SupportsROM (const EmROMReader&) const;
+
+ EmCPU* CreateCPU (EmSession*) const;
+ void CreateRegs (void) const;
+
+ Bool HasFlash (void) const;
+
+ RAMSizeType MinRAMSize (void) const;
+
+ long HardwareID (void) const;
+ long HardwareSubID (void) const;
+
+ string GetMenuString (void) const;
+ string GetIDString (void) const;
+ vector<string> GetIDStrings (void) const;
+
+ public:
+ static EmDeviceList GetDeviceList (void);
+
+ private:
+ EmDevice (int);
+ const DeviceInfo* GetDeviceInfo (void) const;
+ int GetDeviceID (const char*) const;
+
+ int fDeviceID;
+};
+
+#endif /* EmDevice_h */
diff --git a/SrcShared/EmDirRef.cpp b/SrcShared/EmDirRef.cpp
new file mode 100644
index 0000000..2ec21af
--- /dev/null
+++ b/SrcShared/EmDirRef.cpp
@@ -0,0 +1,15 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDirRef.h"
diff --git a/SrcShared/EmDirRef.h b/SrcShared/EmDirRef.h
new file mode 100644
index 0000000..0cba877
--- /dev/null
+++ b/SrcShared/EmDirRef.h
@@ -0,0 +1,91 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDirRef_h
+#define EmDirRef_h
+
+#include <string>
+#include <vector>
+
+class EmFileRef;
+class EmDirRef;
+
+typedef vector<EmFileRef> EmFileRefList;
+typedef vector<EmDirRef> EmDirRefList;
+
+class EmDirRef
+{
+ public:
+ EmDirRef (void);
+ EmDirRef (const EmDirRef&);
+ EmDirRef (const char*);
+ EmDirRef (const string&);
+ EmDirRef (const EmDirRef&, const char*);
+ EmDirRef (const EmDirRef&, const string&);
+#if PLATFORM_MAC
+ EmDirRef (const unsigned char*);
+ EmDirRef (const FSSpec&);
+ EmDirRef (AliasHandle);
+#endif
+ ~EmDirRef (void);
+
+ EmDirRef& operator= (const EmDirRef&);
+
+ Bool IsSpecified (void) const;
+ Bool Exists (void) const;
+ void Create (void) const;
+
+ string GetName (void) const;
+ EmDirRef GetParent (void) const;
+ string GetFullPath (void) const;
+
+ void GetChildren (EmFileRefList*, EmDirRefList*) const;
+
+ bool operator== (const EmDirRef&) const;
+ bool operator!= (const EmDirRef&) const;
+ bool operator< (const EmDirRef&) const;
+ bool operator> (const EmDirRef&) const;
+
+ bool FromPrefString (const string&);
+ string ToPrefString (void) const;
+
+ static EmDirRef GetEmulatorDirectory (void);
+ static EmDirRef GetPrefsDirectory (void);
+
+#if PLATFORM_MAC
+ public:
+ // Needed in order to convert an EmDirRef into something
+ // that PowerPlant or Mac OS can deal with.
+
+ FSSpec GetFSSpec (void) const;
+ AliasHandle GetAlias (void) const;
+
+ private:
+ void UpdateAlias (void);
+ void UpdateSpec (void);
+
+ AliasHandle fDirAlias;
+ FSSpec fDirSpec;
+#endif
+
+#if PLATFORM_WINDOWS || PLATFORM_UNIX
+ private:
+ void MaybeAppendSlash (void);
+ void MaybeResolveLink (void);
+
+ private:
+ string fDirPath;
+#endif
+};
+
+#endif /* EmDirRef_h */
diff --git a/SrcShared/EmDlg.cpp b/SrcShared/EmDlg.cpp
new file mode 100644
index 0000000..d6fa5ed
--- /dev/null
+++ b/SrcShared/EmDlg.cpp
@@ -0,0 +1,6319 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDlg.h"
+
+#include "DebugMgr.h" // gDebuggerGlobals
+#include "EmApplication.h" // gApplication, BindPoser
+#include "EmBankDRAM.h" // EmBankDRAM::ValidAddress
+#include "EmBankROM.h" // EmBankROM::ValidAddress
+#include "EmBankSRAM.h" // EmBankSRAM::ValidAddress
+#include "EmEventPlayback.h" // GetCurrentEvent, GetNumEvents
+#include "EmFileImport.h" // EmFileImport
+#include "EmMinimize.h" // EmMinimize::Stop
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmROMTransfer.h" // EmROMTransfer
+#include "EmROMReader.h" // EmROMReader
+#include "EmSession.h" // gSession
+#include "EmStreamFile.h" // EmStreamFile
+#include "EmTransportSerial.h" // PortNameList, GetSerialPortNameList, etc.
+#include "EmTransportSocket.h" // PortNameList, GetPortNameList, etc.
+#include "EmTransportUSB.h" // EmTransportUSB
+#include "ErrorHandling.h" // Errors::SetParameter
+#include "Hordes.h" // Hordes::New
+#include "LoadApplication.h" // SavePalmFile
+#include "Logging.h" // FOR_EACH_LOG_PREF
+#include "Miscellaneous.h" // MemoryTextList, GetMemoryTextList
+#include "Platform.h" // GetString, GetMilliseconds, Beep, CopyToClipboard
+#include "PreferenceMgr.h" // Preference, gEmuPrefs
+#include "ROMStubs.h" // FSCustomControl, SysLibFind, IntlSetStrictChecks
+#include "Strings.r.h" // kStr_AppName
+#include "Skins.h" // SkinNameList
+
+#if HAS_TRACER
+#include "TracerPlatform.h" // gTracer
+#endif
+
+#include "algorithm" // find, remove_if, unary_function<>
+
+
+#if !PLATFORM_UNIX
+static void PrvAppendDescriptors (EmTransportDescriptorList& menuItems,
+ const EmTransportDescriptorList& rawItems);
+static void PrvAppendDescriptors (EmTransportDescriptorList& menuItems,
+ const string& rawItem);
+static string PrvGetMenuItemText (EmDlgID whichMenu,
+ const EmTransportDescriptor& item);
+static void PrvAppendMenuItems (EmDlgRef dlg, EmDlgItemID dlgItem,
+ const EmTransportDescriptorList& menuItems,
+ const EmTransportDescriptor& pref,
+ const string& socketAddr = string());
+#endif // !PLATFORM_UNIX
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DoGetFile
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoGetFile ( EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList)
+{
+ DoGetFileParameters parameters (result, prompt, defaultPath, filterList);
+
+ return EmDlg::RunDialog (EmDlg::HostRunGetFile, &parameters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DoGetFileList
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoGetFileList ( EmFileRefList& results,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList)
+{
+ DoGetFileListParameters parameters (results, prompt, defaultPath, filterList);
+
+ return EmDlg::RunDialog (EmDlg::HostRunGetFileList, &parameters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DoPutFile
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoPutFile ( EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList,
+ const string& defaultName)
+{
+ DoPutFileParameters parameters (result, prompt, defaultPath, filterList, defaultName);
+
+ return EmDlg::RunDialog (EmDlg::HostRunPutFile, &parameters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DoGetDirectory
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoGetDirectory ( EmDirRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath)
+{
+ DoGetDirectoryParameters parameters (result, prompt, defaultPath);
+
+ return EmDlg::RunDialog (EmDlg::HostRunGetDirectory, &parameters);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoAboutBox
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoAboutBox (void)
+{
+ return EmDlg::RunDialog (EmDlg::HostRunAboutBox, NULL);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoSessionNew
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct SessionNewData
+{
+ Configuration* cfg;
+ Configuration fWorkingCfg;
+ EmDeviceList fDevices;
+};
+
+
+void EmDlg::PrvBuildROMMenu (const EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+
+ EmDlg::ClearMenu (dlg, kDlgItemNewROM);
+
+ EmDlg::AppendToMenu (dlg, kDlgItemNewROM, Platform::GetString (kStr_OtherMRU));
+ EmDlg::AppendToMenu (dlg, kDlgItemNewROM, std::string());
+
+ EmFileRefList romList;
+ gEmuPrefs->GetROMMRU (romList);
+
+ if (romList.size () == 0)
+ {
+ EmDlg::AppendToMenu (dlg, kDlgItemNewROM, Platform::GetString (kStr_EmptyMRU));
+ EmDlg::DisableMenuItem (dlg, kDlgItemNewROM, 2);
+ EmDlg::SetItemValue (dlg, kDlgItemNewROM, 2);
+ cfg.fROMFile = EmFileRef ();
+ }
+ else
+ {
+ int menuID = 2;
+ Bool selected = false;
+
+ EmFileRefList::iterator iter = romList.begin ();
+ while (iter != romList.end ())
+ {
+ EmDlg::AppendToMenu (dlg, kDlgItemNewROM, iter->GetName());
+
+ if (cfg.fROMFile == *iter)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewROM, menuID);
+ selected = true;
+ }
+
+ ++iter;
+ ++menuID;
+ }
+
+ //
+ // If we couldn't find the last-used ROM, try to find
+ // one that we can use.
+ //
+
+ if (!selected)
+ {
+ EmFileRefList::iterator iter = romList.begin ();
+ while (iter != romList.end ())
+ {
+ if (EmDlg::PrvCanUseROMFile (*iter) != kROMFileUnknown)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewROM, 2 + (iter - romList.begin ()));
+ cfg.fROMFile = *iter;
+ return;
+ }
+
+ ++iter;
+ }
+
+ //
+ // If we *still* can't find a ROM image to use, just
+ // zap the whole list and try again with an empty one.
+ //
+
+ Preference<EmFileRefList> pref (kPrefKeyROM_MRU);
+ pref = EmFileRefList ();
+ EmDlg::PrvBuildROMMenu (context);
+ }
+ }
+}
+
+
+struct PrvSupportsROM : unary_function<EmDevice&, bool>
+{
+ PrvSupportsROM(EmROMReader& inROM) : ROM(inROM) {}
+ bool operator()(EmDevice& item)
+ {
+ return !item.SupportsROM(ROM);
+ }
+
+private:
+ const EmROMReader& ROM;
+};
+
+
+void EmDlg::PrvBuildDeviceMenu (const EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+
+ EmDeviceList devices = EmDevice::GetDeviceList ();
+
+ EmDeviceList::iterator iter = devices.begin();
+ EmDeviceList::iterator devices_end = devices.end();
+ int menuID = 0;
+ Bool selected = false;
+ unsigned int version = 0;
+
+ PrvFilterDeviceList(cfg.fROMFile, devices, devices_end, version);
+ iter = devices.begin();
+
+ if (iter == devices_end)
+ {
+ /* We filtered out too many things, so reset to displaying all */
+ devices_end = devices.end();
+ }
+
+ data.fDevices = EmDeviceList(iter, devices_end);
+
+ EmDlg::ClearMenu (dlg, kDlgItemNewDevice);
+
+ while (iter != devices_end)
+ {
+ EmDlg::AppendToMenu (dlg, kDlgItemNewDevice, iter->GetMenuString ());
+
+ if (cfg.fDevice == *iter)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewDevice, menuID);
+ selected = true;
+ }
+
+ ++iter;
+ ++menuID;
+ }
+
+ if (!selected)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewDevice, menuID-1);
+ cfg.fDevice = data.fDevices [menuID-1];
+
+ /* Rely on caller to (always) invoke PrvBuildSkinMenu */
+ }
+}
+
+
+void EmDlg::PrvBuildSkinMenu (const EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+
+ SkinNameList skins;
+ ::SkinGetSkinNames (cfg.fDevice, skins);
+ SkinName chosenSkin = ::SkinGetSkinName (cfg.fDevice);
+
+ SkinNameList::iterator iter = skins.begin ();
+ int menuID = 0;
+
+ EmDlg::ClearMenu (dlg, kDlgItemNewSkin);
+
+ while (iter != skins.end())
+ {
+ EmDlg::AppendToMenu (dlg, kDlgItemNewSkin, *iter);
+
+ if (chosenSkin == *iter)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewSkin, menuID);
+ }
+
+ ++iter;
+ ++menuID;
+ }
+}
+
+
+void EmDlg::PrvBuildMemorySizeMenu (const EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+
+ MemoryTextList sizes;
+ ::GetMemoryTextList (sizes);
+ EmDlg::PrvFilterMemorySizes (sizes, cfg);
+
+ MemoryTextList::iterator iter = sizes.begin();
+ int menuID = 0;
+ Bool selected = false;
+
+ EmDlg::ClearMenu (dlg, kDlgItemNewMemorySize);
+
+ while (iter != sizes.end())
+ {
+ EmDlg::AppendToMenu (dlg, kDlgItemNewMemorySize, iter->second);
+
+ if (cfg.fRAMSize == iter->first)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewMemorySize, menuID);
+ selected = true;
+ }
+
+ ++iter;
+ ++menuID;
+ }
+
+ if (!selected)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemNewMemorySize, 0);
+ cfg.fRAMSize = sizes[0].first;
+ }
+}
+
+
+void EmDlg::PrvNewSessionSetOKButton (const EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+ EmFileRef& rom = cfg.fROMFile;
+
+ EmDlg::EnableDisableItem (dlg, kDlgItemOK, rom.IsSpecified ());
+}
+
+
+void EmDlg::PrvFilterDeviceList(const EmFileRef& romFile, EmDeviceList& devices,
+ EmDeviceList::iterator& devices_end, unsigned int& version)
+{
+ devices_end = devices.end ();
+ version = 0;
+
+ if (romFile.IsSpecified ())
+ {
+ try
+ {
+ EmStreamFile hROM(romFile, kOpenExistingForRead);
+ StMemory romImage (hROM.GetLength ());
+
+ hROM.GetBytes (romImage.Get (), hROM.GetLength ());
+
+ EmROMReader ROM(romImage.Get (), hROM.GetLength ());
+
+ if (ROM.AcquireCardHeader ())
+ {
+ version = ROM.GetCardVersion ();
+
+ if (version < 5)
+ {
+ ROM.AcquireROMHeap ();
+ ROM.AcquireDatabases ();
+ ROM.AcquireFeatures ();
+ ROM.AcquireSplashDB ();
+ }
+ }
+
+ devices_end = remove_if (devices.begin (), devices.end (),
+ PrvSupportsROM (ROM));
+ }
+ catch (ErrCode)
+ {
+ /* On any of our errors, don't remove any devices */
+ }
+ }
+}
+
+
+void EmDlg::PrvFilterMemorySizes (MemoryTextList& sizes, const Configuration& cfg)
+{
+ RAMSizeType minSize = cfg.fDevice.MinRAMSize ();
+ MemoryTextList::iterator iter = sizes.begin();
+
+ while (iter != sizes.end())
+ {
+ if (iter->first < minSize)
+ {
+ sizes.erase (iter);
+ iter = sizes.begin ();
+ continue;
+ }
+
+ ++iter;
+ }
+}
+
+
+//
+// Check out a ROM, and see if we can find any devices for it. If
+// so, return TRUE. If not and the card header is < 5, warn the
+// user but return TRUE anyway. Otherwise, if we can't identify
+// the ROM and it has a v5 card header or greater, show an error
+// message and return FALSE.
+//
+
+EmROMFileStatus EmDlg::PrvCanUseROMFile (EmFileRef& testRef)
+{
+ if (!testRef.Exists ())
+ return kROMFileUnknown;
+
+ EmDeviceList devices = EmDevice::GetDeviceList ();
+ EmDeviceList::iterator devices_end;
+ unsigned int version;
+
+ EmDlg::PrvFilterDeviceList (testRef, devices, devices_end, version);
+
+ if (devices_end == devices.begin ())
+ {
+ // No devices matched
+
+ if (version < 5)
+ {
+ return kROMFileDubious;
+ }
+
+ return kROMFileUnknown;
+ }
+
+ return kROMFileOK;
+}
+
+
+EmDlgFnResult EmDlg::PrvSessionNew (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ SessionNewData& data = *(SessionNewData*) context.fUserData;
+ Configuration& cfg = data.fWorkingCfg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ //
+ // Make a copy of the configuration that we update as the
+ // user makes dialog selections.
+ //
+
+ cfg = *(data.cfg);
+
+ //
+ // If a file is usable, make sure it is in the MRU list.
+ //
+
+ if (EmDlg::PrvCanUseROMFile (cfg.fROMFile) != kROMFileUnknown)
+ {
+ gEmuPrefs->UpdateROMMRU (cfg.fROMFile);
+ }
+
+ // If a file is not usable, then zap our reference to it.
+ // PrvBuildROMMenu will then try to find an alternate.
+ //
+
+ else
+ {
+ cfg.fROMFile = EmFileRef ();
+ }
+
+ //
+ // Build our menus.
+ //
+
+ EmDlg::PrvBuildROMMenu (context);
+ EmDlg::PrvBuildDeviceMenu (context);
+ EmDlg::PrvBuildSkinMenu (context);
+ EmDlg::PrvBuildMemorySizeMenu (context);
+ EmDlg::PrvNewSessionSetOKButton (context);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ *(data.cfg) = cfg;
+
+ SkinNameList skins;
+ ::SkinGetSkinNames (cfg.fDevice, skins);
+ long menuID = EmDlg::GetItemValue (dlg, kDlgItemNewSkin);
+
+ ::SkinSetSkinName (cfg.fDevice, skins[menuID]);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemNewDevice:
+ {
+ EmDeviceList::size_type index = EmDlg::GetItemValue (dlg, kDlgItemNewDevice);
+
+ cfg.fDevice = data.fDevices [index];
+
+ EmDlg::PrvBuildSkinMenu (context);
+ EmDlg::PrvBuildMemorySizeMenu (context);
+ break;
+ }
+
+ case kDlgItemNewSkin:
+ {
+ break;
+ }
+
+ case kDlgItemNewMemorySize:
+ {
+ MemoryTextList sizes;
+ ::GetMemoryTextList (sizes);
+ EmDlg::PrvFilterMemorySizes (sizes, cfg);
+
+ MemoryTextList::size_type index = EmDlg::GetItemValue (dlg, kDlgItemNewMemorySize);
+
+ cfg.fRAMSize = sizes [index].first;
+ break;
+ }
+
+ case kDlgItemNewROMBrowse:
+ break;
+
+ case kDlgItemNewROM:
+ {
+ EmFileTypeList typeList;
+ typeList.push_back (kFileTypeROM);
+
+ int romStatus = kROMFileUnknown;
+ EmFileRef romFileRef;
+ EmDirRef romDirRef (cfg.fROMFile.GetParent ());
+
+ //
+ // See what menu item was selected: "Other..." or a
+ // ROM from the MRU list.
+ //
+
+ int index = EmDlg::GetItemValue (dlg, kDlgItemNewROM);
+
+ //
+ // User selected from MRU list.
+ //
+
+ if (index >= 2)
+ {
+ romFileRef = gEmuPrefs->GetIndROMMRU (index - 2);
+ }
+
+ //
+ // Ask user for new ROM.
+ //
+
+ else
+ {
+ if (EmDlg::DoGetFile (romFileRef, "Choose ROM file:",
+ romDirRef, typeList) == kDlgItemOK)
+ {
+ }
+
+ // If the user cancelled from the dialog, restore the
+ // previously selected ROM.
+
+ else
+ {
+ romFileRef = cfg.fROMFile;
+ }
+ }
+
+ // Respond to the ROM selection.
+
+ romStatus = EmDlg::PrvCanUseROMFile (romFileRef);
+
+ if (romStatus == kROMFileDubious)
+ {
+ Errors::DoDialog (kStr_UnknownDeviceWarning, kDlgFlags_OK);
+ }
+ else if (romStatus == kROMFileUnknown)
+ {
+ Errors::DoDialog (kStr_UnknownDeviceError, kDlgFlags_OK);
+ }
+
+ //
+ // If we can identify the ROM or we want to go ahead and
+ // use it anyway, update our dialog items.
+ //
+
+ if (romStatus != kROMFileUnknown)
+ {
+ cfg.fROMFile = romFileRef;
+ gEmuPrefs->UpdateROMMRU (cfg.fROMFile);
+ }
+
+ EmDlg::PrvNewSessionSetOKButton (context);
+
+ EmDlg::PrvBuildROMMenu (context);
+ EmDlg::PrvBuildDeviceMenu (context);
+ EmDlg::PrvBuildSkinMenu (context);
+ EmDlg::PrvBuildMemorySizeMenu (context);
+
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ } // switch (context.fItemID)
+
+ break;
+ } // case kDlgCmdItemSelected
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ } // switch (command)
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoSessionNew (Configuration& cfg)
+{
+ SessionNewData data;
+ data.cfg = &cfg;
+
+ return EmDlg::RunDialog (EmDlg::PrvSessionNew, &data, kDlgSessionNew);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoSessionSave
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::DoSessionSave (const string& docName, Bool quitting)
+{
+ string appName = Platform::GetString (kStr_AppName);
+ string docName2 (docName);
+
+ if (docName2.empty ())
+ docName2 = Platform::GetString (kStr_Untitled);
+
+ DoSessionSaveParameters parameters (appName, docName2, quitting);
+
+ EmDlgItemID result = EmDlg::RunDialog (EmDlg::HostRunSessionSave, &parameters);
+
+ EmAssert (result == kDlgItemYes || result == kDlgItemNo || result == kDlgItemCancel);
+
+ return result;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoHordeNew
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct HordeNewData
+{
+ HordeInfo info;
+ EmDatabaseList appList;
+};
+
+
+UInt32 EmDlg::PrvSelectedAppNameToIndex (EmDatabaseList list, const string& appName)
+{
+ if (appName.empty ())
+ return 0;
+
+ uint32 index = 0;
+
+ EmDatabaseList::iterator iter = list.begin ();
+
+ while (iter != list.end ())
+ {
+ if (strcmp ((*iter).name, appName.c_str ()) == 0)
+ return index;
+
+ index += 1;
+ iter++;
+ }
+
+ return 0;
+}
+
+
+DatabaseInfo EmDlg::PrvSelectedIndexToApp (EmDatabaseList appList, uint32 index)
+{
+ return appList[index];
+}
+
+
+void EmDlg::PrvSelectedList (EmDatabaseList selectedApps, StringList &selectedAppStrings)
+{
+ selectedAppStrings.clear ();
+
+ EmDatabaseList::iterator iter = selectedApps.begin ();
+
+ while (iter != selectedApps.end ())
+ {
+ selectedAppStrings.push_back ((*iter).name);
+
+ ++iter;
+ }
+}
+
+
+EmDlgFnResult EmDlg::PrvHordeNew (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ HordeNewData& data = *(HordeNewData*) context.fUserData;
+ HordeInfo& info = data.info;
+
+ // These variables and iterators are used in multiple case statements,
+ // so I'm putting them here both so that the compiler will not complain,
+ // and so that they can be declared once, so that their names won't be
+ // confusing.
+
+ Bool selected;
+ EmDatabaseList selectedApps;
+ StringList selectedAppStrings;
+ EmDlgListIndexList items;
+ EmDlgListIndexList::iterator iter1;
+ EmDatabaseList::iterator iter2;
+ UInt32 currentSelection;
+
+ // Initialize
+
+ selectedApps.clear ();
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Get Horde preference settings.
+
+ Preference<HordeInfo> pref (kPrefKeyHordeInfo);
+ info = *pref;
+
+ // Install the settings into the dialog box items.
+
+ EmDlg::SetItemValue (dlg, kDlgItemHrdStart, info.fStartNumber);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdStop, info.fStopNumber);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdDepthSwitch, info.fDepthSwitch);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdDepthSave, info.fDepthSave);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdDepthStop, info.fDepthStop);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdCheckSwitch, info.fCanSwitch);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdCheckSave, info.fCanSave);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdCheckStop, info.fCanStop);
+
+ // Get the list of applications.
+
+ ::GetDatabases (data.appList, kApplicationsOnly);
+
+ // Insert the names of the applications into the list.
+
+ selected = false;
+ EmDatabaseList::iterator iter = data.appList.begin();
+ while (iter != data.appList.end())
+ {
+ DatabaseInfo& thisDB = *iter;
+
+ // Add the current item.
+
+ EmDlg::AppendToList (dlg, kDlgItemHrdAppList, thisDB.name);
+
+ // If the item we just added is in our "selected" list,
+ // then select it, and add it to our list of selected
+ // apps (from which the first to be run will be selected
+ // by the user).
+
+ EmDatabaseList::iterator begin = info.fAppList.begin ();
+ EmDatabaseList::iterator end = info.fAppList.end ();
+
+ if (find (begin, end, thisDB) != end)
+ {
+ selected = true;
+ int index = iter - data.appList.begin();
+ EmDlg::SelectListItem (dlg, kDlgItemHrdAppList, index);
+ selectedApps.push_back (thisDB);
+ }
+
+ ++iter;
+ }
+
+ // If nothing's selected, then select something (the first item).
+
+ if (!selected)
+ {
+ EmDlg::SelectListItem (dlg, kDlgItemHrdAppList, 0);
+ }
+
+ // Set up the selected apps menu from the string list we populated
+ // above. Default to the first app on the list (as was done previously,
+ // before this menu existed.
+
+ EmDlg::PrvSelectedList (selectedApps, selectedAppStrings);
+ currentSelection = EmDlg::PrvSelectedAppNameToIndex (selectedApps, info.fFirstLaunchedAppName);
+ EmDlg::ClearMenu (dlg, kDlgItemHrdFirstLaunchedApp);
+ EmDlg::AppendToMenu (dlg, kDlgItemHrdFirstLaunchedApp, selectedAppStrings);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdFirstLaunchedApp, currentSelection);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ info.fStartNumber = EmDlg::GetItemValue (dlg, kDlgItemHrdStart);
+ info.fStopNumber = EmDlg::GetItemValue (dlg, kDlgItemHrdStop);
+ info.fDepthSwitch = EmDlg::GetItemValue (dlg, kDlgItemHrdDepthSwitch);
+ info.fDepthSave = EmDlg::GetItemValue (dlg, kDlgItemHrdDepthSave);
+ info.fDepthStop = EmDlg::GetItemValue (dlg, kDlgItemHrdDepthStop);
+ info.fCanSwitch = EmDlg::GetItemValue (dlg, kDlgItemHrdCheckSwitch);
+ info.fCanSave = EmDlg::GetItemValue (dlg, kDlgItemHrdCheckSave);
+ info.fCanStop = EmDlg::GetItemValue (dlg, kDlgItemHrdCheckStop);
+
+ // Get the indexes for the selected items.
+
+ EmDlg::GetSelectedItems (dlg, kDlgItemHrdAppList, items);
+
+ // first make a dummy app list, unordered, so that we can figure out
+ // which application was selected.
+
+ DatabaseInfoList dummyAppList;
+ dummyAppList.clear ();
+ EmDlgListIndexList::iterator dummyIter = items.begin ();
+
+ while (dummyIter != items.end ())
+ {
+ DatabaseInfo dummyDbInfo = data.appList[*dummyIter];
+
+ dummyAppList.push_back (dummyDbInfo);
+
+ ++dummyIter;
+ }
+
+ DatabaseInfo dbInfoStartApp = EmDlg::PrvSelectedIndexToApp (dummyAppList,
+ EmDlg::GetItemValue (dlg, kDlgItemHrdFirstLaunchedApp));
+ info.fFirstLaunchedAppName = dbInfoStartApp.name;
+
+ // push the app to be launched first onto the stack then
+ // use the indexes to get the actual items, and add those
+ // items to the "result" container.
+
+ info.fAppList.clear ();
+ info.fAppList.push_back (dbInfoStartApp);
+
+ EmDlgListIndexList::iterator iter = items.begin ();
+
+ while (iter != items.end ())
+ {
+ DatabaseInfo dbInfo = data.appList[*iter];
+
+ // don't add the starting app twice, however harmless that may be
+
+ if (strcmp (dbInfo.name, dbInfoStartApp.name) != 0)
+ {
+ info.fAppList.push_back (dbInfo);
+ }
+
+ ++iter;
+ }
+
+ // Transfer the new fields to the old fields for Hordes to use.
+
+ info.NewToOld ();
+
+ // Save the preferences
+
+ Preference<HordeInfo> pref (kPrefKeyHordeInfo);
+ pref = info;
+
+ // Startup up the gremlin sub-system.
+
+ Hordes::New (info);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemHrdAppList:
+ case kDlgItemHrdFirstLaunchedApp:
+
+ // First, clean out the list of selected applications,
+ // or, alternately, the list of applications that will
+ // be run.
+
+ info.fAppList.clear ();
+
+ // Get the indices of the selected items.
+
+ EmDlg::GetSelectedItems (dlg, kDlgItemHrdAppList, items);
+
+ // Use the indices to get the actual items, and add those
+ // items to the "result" container.
+
+ iter1 = items.begin ();
+ while (iter1 != items.end())
+ {
+ DatabaseInfo dbInfo = data.appList[*iter1];
+ info.fAppList.push_back (dbInfo);
+ ++iter1;
+ }
+
+ // Now that we have a current fAppList, let's update our popup
+ // menu for selecting the first launched app.
+
+ // Initialize the string list that the pop-up menu will use
+ // to populate itself, then iterate through the list of applications.
+
+ selectedApps.clear ();
+
+ selected = false;
+ iter2 = data.appList.begin();
+ while (iter2 != data.appList.end())
+ {
+ DatabaseInfo& thisDB = *iter2;
+
+ // If the item we just looked at is in our "selected" list,
+ // then select it, and add it to our list of selected
+ // apps (from which the first to be run will be selected
+ // by the user).
+
+ EmDatabaseList::iterator begin = info.fAppList.begin ();
+ EmDatabaseList::iterator end = info.fAppList.end ();
+
+ int index = iter2 - data.appList.begin();
+
+ if (find (begin, end, thisDB) != end)
+ {
+ selected = true;
+ EmDlg::SelectListItem (dlg, kDlgItemHrdAppList, index);
+ selectedApps.push_back (thisDB);
+ }
+
+ ++iter2;
+ }
+
+ // Set up the selected apps menu from the string list we populated
+ // above. Default to the first app on the list (as was done previously,
+ // before this menu existed.
+
+ EmDlg::PrvSelectedList (selectedApps, selectedAppStrings);
+
+ if (context.fItemID == kDlgItemHrdFirstLaunchedApp)
+ {
+ info.fFirstLaunchedAppName = selectedAppStrings
+ [EmDlg::GetItemValue (dlg, kDlgItemHrdFirstLaunchedApp)];
+ }
+ else // kDlgItemHrdAppList
+ {
+ currentSelection = EmDlg::PrvSelectedAppNameToIndex (selectedApps, info.fFirstLaunchedAppName);
+ EmDlg::ClearMenu (dlg, kDlgItemHrdFirstLaunchedApp);
+ EmDlg::AppendToMenu (dlg, kDlgItemHrdFirstLaunchedApp, selectedAppStrings);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdFirstLaunchedApp, currentSelection);
+ }
+
+ break;
+
+ case kDlgItemHrdStart:
+ case kDlgItemHrdStop:
+ case kDlgItemHrdCheckSwitch:
+ case kDlgItemHrdCheckSave:
+ case kDlgItemHrdCheckStop:
+ case kDlgItemHrdDepthSwitch:
+ case kDlgItemHrdDepthSave:
+ case kDlgItemHrdDepthStop:
+ break;
+
+ case kDlgItemHrdSelectAll:
+
+ // Initialize the app list that the pop-up menu will use
+ // to populate itself, then iterate through the list of applications.
+
+ selectedApps.clear ();
+
+ selected = false;
+ iter2 = data.appList.begin ();
+ while (iter2 != data.appList.end ())
+ {
+ DatabaseInfo& thisDB = *iter2;
+
+ // Regardless of whether this item is really selected or
+ // not, select it, since we are Selecting All here.
+
+ int index = iter2 - data.appList.begin ();
+
+ selected = true;
+ EmDlg::SelectListItem (dlg, kDlgItemHrdAppList, index);
+ selectedApps.push_back (thisDB);
+
+ ++iter2;
+ }
+
+ // Set up the selected apps menu from the string list we populated
+ // above. Default to the first app on the list (as was done previously,
+ // before this menu existed.
+
+ EmDlg::PrvSelectedList (selectedApps, selectedAppStrings);
+ currentSelection = EmDlg::PrvSelectedAppNameToIndex (selectedApps, info.fFirstLaunchedAppName);
+ EmDlg::ClearMenu (dlg, kDlgItemHrdFirstLaunchedApp);
+ EmDlg::AppendToMenu (dlg, kDlgItemHrdFirstLaunchedApp, selectedAppStrings);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdFirstLaunchedApp, currentSelection);
+ break;
+
+ case kDlgItemHrdSelectNone:
+
+ // Initialize the app list that the pop-up menu will use
+ // to populate itself, then iterate through the list of applications.
+
+ selectedApps.clear ();
+
+ iter2 = data.appList.begin ();
+ while (iter2 != data.appList.end ())
+ {
+ // Regardless of whether this item is really selected or
+ // not, unselect it, since we are Selecting None here.
+
+ int index = iter2 - data.appList.begin ();
+ selected = false;
+ EmDlg::UnselectListItem (dlg, kDlgItemHrdAppList, index);
+
+ ++iter2;
+ }
+
+ EmDlg::SelectListItem (dlg, kDlgItemHrdAppList, 0);
+
+ // This set of braces is here to keep the compiler from complaining
+ // about initializing within a case
+
+ {
+ DatabaseInfo& thisDB = *(data.appList.begin ());
+ selectedApps.push_back (thisDB);
+ }
+
+ // Set up the selected apps menu from the string list we populated
+ // above. Default to the first app on the list (as was done previously,
+ // before this menu existed.
+
+ EmDlg::PrvSelectedList (selectedApps, selectedAppStrings);
+
+ // Update our first launched app pref
+
+ info.fFirstLaunchedAppName = selectedAppStrings[0];
+
+ EmDlg::ClearMenu (dlg, kDlgItemHrdFirstLaunchedApp);
+ EmDlg::AppendToMenu (dlg, kDlgItemHrdFirstLaunchedApp, selectedAppStrings);
+ EmDlg::SetItemValue (dlg, kDlgItemHrdFirstLaunchedApp, 0);
+
+ break;
+
+ case kDlgItemHrdLogging:
+ EmDlg::DoEditLoggingOptions (kGremlinLogging);
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoHordeNew (void)
+{
+ HordeNewData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvHordeNew, &data, kDlgHordeNew);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoDatabaseImport
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct DatabaseImportData
+{
+ EmFileRefList fFiles;
+ EmFileImportMethod fMethod;
+ EmStreamFile* fStream;
+ EmFileImport* fImporter;
+ long fProgressCurrent; // Progress into the current file
+ long fProgressBase; // Progress accumulated by previous files
+ long fProgressMax; // Progress max value.
+ long fCurrentFile; // Current file we're installing.
+ long fDoneStart;
+};
+
+
+EmDlgFnResult EmDlg::PrvDatabaseImport (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ DatabaseImportData& data = *(DatabaseImportData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ data.fStream = NULL;
+ data.fImporter = NULL;
+
+ try
+ {
+ data.fCurrentFile = 0;
+ data.fStream = new EmStreamFile (data.fFiles[data.fCurrentFile], kOpenExistingForRead);
+ data.fImporter = new EmFileImport (*data.fStream, data.fMethod);
+ data.fProgressCurrent = -1;
+ data.fProgressBase = 0;
+ data.fProgressMax = EmFileImport::CalculateProgressMax (data.fFiles, data.fMethod);
+ data.fDoneStart = 0;
+
+ long remainingFiles = data.fFiles.size () - data.fCurrentFile;
+ string curAppName = data.fFiles[data.fCurrentFile].GetName ();
+
+ EmDlg::SetItemValue (dlg, kDlgItemImpNumFiles, remainingFiles);
+// EmDlg::SetItemText (dlg, kDlgItemImpCurAppName, curAppName);
+ }
+ catch (...)
+ {
+ delete data.fImporter;
+ delete data.fStream;
+
+ data.fStream = NULL;
+ data.fImporter = NULL;
+ }
+
+ context.fNeedsIdle = true;
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ if (data.fImporter)
+ {
+ // Prevent against recursion (can occur if we need to display an error dialog).
+
+ static Bool inIdle;
+ if (inIdle)
+ break;
+
+ inIdle = true;
+
+ // Install a little bit of the file.
+
+ ErrCode err = data.fImporter->Continue ();
+
+ // If an error occurred, display a dialog.
+
+ if (err)
+ {
+ string curAppName = data.fFiles[data.fCurrentFile].GetName ();
+ Errors::SetParameter ("%filename", curAppName);
+ Errors::ReportIfError (kStr_CmdInstall, err, 0, false);
+ }
+
+ // Everything went OK. Get the current progress amount.
+ // If it changed, update the dialog.
+ else
+ {
+ long progressCurrent = data.fImporter->GetProgress ();
+ long progressMax = data.fProgressMax;
+
+ if (data.fProgressCurrent != progressCurrent)
+ {
+ data.fProgressCurrent = progressCurrent;
+
+ progressCurrent += data.fProgressBase;
+
+ // Scale progressMax to < 32K (progress control on Windows
+ // prefers it that way).
+
+ long divider = progressMax / (32 * 1024L) + 1;
+
+ progressMax /= divider;
+ progressCurrent /= divider;
+
+ long remainingFiles = data.fFiles.size () - data.fCurrentFile;
+ string curAppName = data.fFiles[data.fCurrentFile].GetName ();
+
+ EmDlg::SetItemValue (dlg, kDlgItemImpNumFiles, remainingFiles);
+// EmDlg::SetItemText (dlg, kDlgItemImpCurAppName, curAppName);
+ EmDlg::SetItemMax (dlg, kDlgItemImpProgress, progressMax);
+ EmDlg::SetItemValue (dlg, kDlgItemImpProgress, progressCurrent);
+ }
+ }
+
+ // If we're done with this file, clean up, and prepare for any
+ // subsequent files.
+
+ if (data.fImporter->Done ())
+ {
+ gEmuPrefs->UpdatePRCMRU (data.fFiles[data.fCurrentFile]);
+
+ data.fProgressCurrent = -1;
+ data.fProgressBase += data.fImporter->GetProgress ();
+
+ delete data.fImporter;
+ data.fImporter = NULL;
+
+ delete data.fStream;
+ data.fStream = NULL;
+
+ data.fCurrentFile++;
+ if (data.fCurrentFile < (long) data.fFiles.size ())
+ {
+ try
+ {
+ data.fStream = new EmStreamFile (data.fFiles[data.fCurrentFile], kOpenExistingForRead);
+ data.fImporter = new EmFileImport (*data.fStream, data.fMethod);
+ }
+ catch (...)
+ {
+ delete data.fImporter;
+ delete data.fStream;
+
+ data.fStream = NULL;
+ data.fImporter = NULL;
+ }
+ }
+ else
+ {
+ // There are no more files to install. Initialize our
+ // counter used to delay the closing of the dialog.
+
+ data.fDoneStart = Platform::GetMilliseconds ();
+ }
+ }
+
+ inIdle = false;
+ }
+
+ // After we're done installing all files, wait a little bit in order to
+ // see the completed progress dialog.
+
+ else if (Platform::GetMilliseconds () - data.fDoneStart > 500)
+ {
+ return kDlgResultClose;
+ }
+
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ if (context.fItemID == kDlgItemCancel)
+ data.fImporter->Cancel ();
+
+ delete data.fImporter;
+ data.fImporter = NULL;
+
+ return kDlgResultClose;
+ }
+
+ case kDlgItemImpNumFiles:
+// case kDlgItemImpCurAppName:
+ case kDlgItemImpProgress:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoDatabaseImport (const EmFileRefList& files, EmFileImportMethod method)
+{
+ // Validate the list of files.
+
+ EmFileRefList newFileList;
+ EmFileRefList::const_iterator iter = files.begin ();
+
+ while (iter != files.end ())
+ {
+ if (iter->IsSpecified () && iter->Exists ())
+ {
+ newFileList.push_back (*iter);
+ }
+ else
+ {
+ // !!! Report that the file doesn't exist.
+ }
+
+ ++iter;
+ }
+
+ if (newFileList.size () <= 0)
+ {
+ return kDlgItemOK;
+ }
+
+ // Stop the session so that the files can be safely loaded.
+
+ EmAssert (gSession);
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (!stopper.Stopped ())
+ return kDlgItemCancel;
+
+ DatabaseImportData data;
+
+ data.fFiles = newFileList;
+ data.fMethod = method;
+
+ return EmDlg::RunDialog (EmDlg::PrvDatabaseImport, &data, kDlgDatabaseImport);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoDatabaseExport
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct ExportDatbaseData
+{
+ EmDatabaseList fAllDatabases;
+};
+
+
+Bool EmDlg::PrvExportFile (const DatabaseInfo& db)
+{
+ UInt16 dbAttributes;
+ UInt32 dbType;
+ UInt32 dbCreator;
+ ErrCode err = ::DmDatabaseInfo (db.cardNo, db.dbID, NULL,
+ &dbAttributes, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, &dbType, &dbCreator);
+ Errors::ThrowIfPalmError (err);
+
+ // Figure out the file type.
+
+ EmFileType type = kFileTypeNone;
+
+ if ((dbAttributes & dmHdrAttrResDB) != 0)
+ {
+ type = kFileTypePalmApp;
+ }
+ else
+ {
+ if (dbCreator == sysFileCClipper)
+ type = kFileTypePalmQA;
+ else
+ type = kFileTypePalmDB;
+ }
+
+ EmFileRef result;
+ string prompt ("Save as...");
+ EmDirRef defaultPath;
+ EmFileTypeList filterList;
+ string defaultName (db.dbName);
+
+ string extension = type == kFileTypePalmApp ? ".prc" :
+ type == kFileTypePalmQA ? ".pqa" : ".pdb";
+
+ if (!::EndsWith (defaultName.c_str (), extension.c_str ()))
+ {
+ defaultName += extension;
+ }
+
+ filterList.push_back (type);
+ filterList.push_back (kFileTypePalmAll);
+ filterList.push_back (kFileTypeAll);
+
+ EmDlgItemID item = EmDlg::DoPutFile ( result,
+ prompt,
+ defaultPath,
+ filterList,
+ defaultName);
+
+ if (item == kDlgItemOK)
+ {
+ EmStreamFile stream (result, kCreateOrEraseForUpdate,
+ kFileCreatorInstaller, type);
+
+ ::SavePalmFile (stream, db.cardNo, db.dbName);
+ }
+
+ return (item == kDlgItemOK);
+}
+
+
+EmDlgFnResult EmDlg::PrvDatabaseExport (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ ExportDatbaseData& data = *(ExportDatbaseData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Get the list of installed databases.
+
+ ::GetDatabases (data.fAllDatabases, kAllDatabases);
+
+ // Add then names of the databases to the list.
+
+ EmDatabaseList::iterator iter = data.fAllDatabases.begin();
+ while (iter != data.fAllDatabases.end())
+ {
+ string itemText (iter->dbName);
+
+ // If the database name is different from any user-visible
+ // name, then use both of them.
+
+ if (strcmp (iter->dbName, iter->name) != 0)
+ {
+ itemText += " (";
+ itemText += iter->name;
+ itemText += ")";
+ }
+
+ EmDlg::AppendToList (dlg, kDlgItemExpDbList, itemText.c_str ());
+ ++iter;
+ }
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Get the indexes for the selected items.
+
+ EmDlgListIndexList items;
+ EmDlg::GetSelectedItems(dlg, kDlgItemExpDbList, items);
+
+ // Export each item.
+
+ Bool cancel = false;
+ EmDlgListIndexList::iterator iter = items.begin ();
+ while (!cancel && iter != items.end ())
+ {
+ DatabaseInfo& db = data.fAllDatabases[*iter];
+
+ cancel = !EmDlg::PrvExportFile (db);
+
+ ++iter;
+ }
+
+ if (cancel)
+ break;
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemExpDbList:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoDatabaseExport (void)
+{
+ ExportDatbaseData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvDatabaseExport, &data, kDlgDatabaseExport);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoReset
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvReset (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EmResetType& choice = *(EmResetType*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemRstSoft, 1);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ if (EmDlg::GetItemValue (dlg, kDlgItemRstSoft))
+ {
+ choice = kResetSoft;
+ }
+ else if (EmDlg::GetItemValue (dlg, kDlgItemRstHard))
+ {
+ choice = kResetHard;
+ }
+ else
+ {
+ EmAssert (EmDlg::GetItemValue (dlg, kDlgItemRstDebug));
+ choice = kResetDebug;
+ }
+
+ if (EmDlg::GetItemValue (dlg, kDlgItemRstNoExt) != 0)
+ {
+ choice = (EmResetType) ((int) choice | kResetNoExt);
+ }
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemRstSoft:
+ case kDlgItemRstHard:
+ case kDlgItemRstDebug:
+ case kDlgItemRstNoExt:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoReset (EmResetType& type)
+{
+ return EmDlg::RunDialog (EmDlg::PrvReset, &type, kDlgReset);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoROMTransferQuery
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct ROMTransferQueryData
+{
+#if !PLATFORM_UNIX
+ EmTransportDescriptorList fPortNameList;
+#endif
+ EmTransport::Config** fConfig;
+};
+
+
+#if !PLATFORM_UNIX
+void EmDlg::PrvGetDlqPortItemList (EmTransportDescriptorList& menuItems)
+{
+ EmTransportDescriptorList descListSerial;
+ EmTransportDescriptorList descListUSB;
+
+ EmTransportSerial::GetDescriptorList (descListSerial);
+ EmTransportUSB::GetDescriptorList (descListUSB);
+
+ ::PrvAppendDescriptors (menuItems, descListSerial);
+ ::PrvAppendDescriptors (menuItems, descListUSB);
+}
+#endif
+
+
+void EmDlg::PrvConvertBaudListToStrings (const EmTransportSerial::BaudList& baudList,
+ StringList& baudStrList)
+{
+ EmTransportSerial::BaudList::const_iterator iter = baudList.begin();
+ while (iter != baudList.end())
+ {
+ char buffer[20];
+ ::FormatInteger (buffer, *iter);
+ strcat (buffer, " bps");
+ baudStrList.push_back (buffer);
+ ++iter;
+ }
+}
+
+EmDlgFnResult EmDlg::PrvROMTransferQuery (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ ROMTransferQueryData& data = *(ROMTransferQueryData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // On Unix, the port is specified in an edit text item.
+ // On other platforms, we present a list of ports in a menu.
+
+ // !!! TBD: restore port setting from a preference.
+
+#if PLATFORM_UNIX
+ EmDlg::SetItemText (dlg, kDlgItemDlqPortList, "/dev/ttyS0");
+#else
+ Preference<string> pref (kPrefKeyPortDownload);
+ ::PrvAppendMenuItems (dlg, kDlgItemDlqPortList, data.fPortNameList, *pref);
+#endif
+
+ EmTransportSerial::BaudList baudList;
+ EmTransportSerial::GetSerialBaudList (baudList);
+
+ StringList baudStrList;
+ EmDlg::PrvConvertBaudListToStrings (baudList, baudStrList);
+
+ EmDlg::AppendToMenu (dlg, kDlgItemDlqBaudList, baudStrList);
+ EmDlg::SetItemValue (dlg, kDlgItemDlqBaudList, 0); // 115K baud
+
+ // Load the instructions string. Load it in 9 parts,
+ // as the entire string is greater than:
+ //
+ // Rez can handle on the Mac.
+ // MSDev's string editor on Windows.
+ // The ANSI-allowed string length (for Unix).
+
+ string ins;
+ for (int ii = 0; ii < 9; ++ii)
+ {
+ string temp = Platform::GetString (kStr_ROMTransferInstructions + ii);
+ ins += temp;
+ }
+
+ EmDlg::SetItemText (dlg, kDlgItemDlqInstructions, ins);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Get the selected settings.
+
+#if PLATFORM_UNIX
+ string portName = EmDlg::GetItemText (dlg, kDlgItemDlqPortList);
+ EmTransportDescriptor portDesc (portName);
+#else
+ long portNum = EmDlg::GetItemValue (dlg, kDlgItemDlqPortList);
+ EmTransportDescriptor portDesc = data.fPortNameList [portNum];
+ string portName = portDesc.GetSchemeSpecific ();
+#endif
+
+ EmTransportType transportType;
+ transportType = portDesc.GetType ();
+
+ switch (transportType)
+ {
+ case kTransportSerial:
+ {
+ long baudNum = EmDlg::GetItemValue (dlg, kDlgItemDlqBaudList);
+
+ EmTransportSerial::BaudList baudList;
+ EmTransportSerial::GetSerialBaudList (baudList);
+
+ EmTransportSerial::ConfigSerial* serConfig = new EmTransportSerial::ConfigSerial;
+
+ serConfig->fPort = portName;
+ serConfig->fBaud = baudList [baudNum];
+ serConfig->fParity = EmTransportSerial::kNoParity;
+ serConfig->fStopBits = 1;
+ serConfig->fDataBits = 8;
+ serConfig->fHwrHandshake = true;
+
+ *data.fConfig = serConfig;
+
+ break;
+ }
+
+ case kTransportUSB:
+ {
+ EmTransportUSB::ConfigUSB* usbConfig = new EmTransportUSB::ConfigUSB;
+
+ *data.fConfig = usbConfig;
+
+ break;
+ }
+
+ case kTransportSocket:
+ case kTransportNull:
+ break;
+
+ case kTransportUnknown:
+ EmAssert (false);
+ break;
+ }
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemDlqInstructions:
+ case kDlgItemDlqPortList:
+ case kDlgItemDlqBaudList:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoROMTransferQuery (EmTransport::Config*& config)
+{
+ config = NULL;
+
+ ROMTransferQueryData data;
+ data.fConfig = &config;
+
+#if !PLATFORM_UNIX
+ // Generate the list here, and do it just once. It's important to
+ // do it just once, as the list of ports could possibly change between
+ // the time they're added to the menu and the time one is chosen to
+ // be returned. This could happen, for example, on the Mac where
+ // opening a USB connection creates a new "virtual" serial port.
+
+ EmDlg::PrvGetDlqPortItemList (data.fPortNameList);
+#endif
+
+ return EmDlg::RunDialog (EmDlg::PrvROMTransferQuery, &data, kDlgROMTransferQuery);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoROMTransferProgress
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvROMTransferProgress (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EmROMTransfer& transferer = *(EmROMTransfer*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ context.fNeedsIdle = true;
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ try
+ {
+ if (!transferer.Continue (dlg))
+ return kDlgResultClose;
+ }
+ catch (ErrCode /*err*/)
+ {
+ // !!! Should report error code?
+ return kDlgResultClose;
+ }
+
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ transferer.Abort (dlg);
+ return kDlgResultClose;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoROMTransferProgress (EmROMTransfer& transferer)
+{
+ return EmDlg::RunDialog (EmDlg::PrvROMTransferProgress, &transferer, kDlgROMTransferProgress);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditPreferences
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditPreferencesData
+{
+ EmTransportDescriptor prefPortSerial; // Selected menu item for serial
+ EmTransportDescriptor prefPortIR; // Selected menu item for IR
+ EmTransportDescriptor prefPortMystery; // Selected menu item for Mystery
+ bool prefRedirectNetLib;
+ bool prefEnableSounds;
+ CloseActionType prefCloseAction;
+ string prefUserName;
+
+#if !PLATFORM_UNIX
+ string prefPortSerialSocket; // Socket address for serial
+ string prefPortIRSocket; // Socket address for serial
+
+ EmTransportDescriptorList menuItemsSerial; // Built-up menu for serial
+ EmTransportDescriptorList menuItemsIR; // Built-up menu for IR
+ EmTransportDescriptorList menuItemsMystery; // Built-up menu for Mystery
+#endif
+};
+
+
+void EmDlg::PrvEditPrefToDialog (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+#if !PLATFORM_UNIX
+
+ // ------------------------------------------------------------
+ // Set up the port menus.
+ // ------------------------------------------------------------
+
+ EmDlg::ClearMenu (dlg, kDlgItemPrfRedirectSerial);
+ EmDlg::ClearMenu (dlg, kDlgItemPrfRedirectIR);
+ EmDlg::ClearMenu (dlg, kDlgItemPrfRedirectMystery);
+
+ ::PrvAppendMenuItems (dlg, kDlgItemPrfRedirectSerial, data.menuItemsSerial, data.prefPortSerial, data.prefPortSerialSocket);
+ ::PrvAppendMenuItems (dlg, kDlgItemPrfRedirectIR, data.menuItemsIR, data.prefPortIR, data.prefPortIRSocket);
+ ::PrvAppendMenuItems (dlg, kDlgItemPrfRedirectMystery, data.menuItemsMystery, data.prefPortMystery);
+
+ // IR emulation appears to be consistantly flaky no matter what's
+ // used for the underlying transport (local TCP, serial, etc.).
+ // So always disable it for now, until we can figure out why it's
+ // flakey and can work around it.
+
+ EmDlg::DisableItem (dlg, kDlgItemPrfRedirectIR);
+
+#else
+
+ // ------------------------------------------------------------
+ // Set up the port text items.
+ // ------------------------------------------------------------
+
+ EmDlg::SetItemText (dlg, kDlgItemPrfRedirectSerial, data.prefPortSerial.GetMenuName ());
+ EmDlg::SetItemText (dlg, kDlgItemPrfRedirectIR, data.prefPortIR.GetMenuName ());
+ EmDlg::SetItemText (dlg, kDlgItemPrfRedirectMystery, data.prefPortMystery.GetMenuName ());
+
+#endif
+
+ // ------------------------------------------------------------
+ // Set up the Redirect NetLib and Enable Sounds checkboxes.
+ // ------------------------------------------------------------
+
+ EmDlg::SetItemValue (dlg, kDlgItemPrfRedirectNetLib, data.prefRedirectNetLib);
+ EmDlg::SetItemValue (dlg, kDlgItemPrfEnableSound, data.prefEnableSounds);
+
+ // ------------------------------------------------------------
+ // Set up the Close Action radio buttons.
+ // ------------------------------------------------------------
+
+ if (data.prefCloseAction == kSaveAlways)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemPrfSaveAlways, 1);
+ }
+ else if (data.prefCloseAction == kSaveAsk)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemPrfSaveAsk, 1);
+ }
+ else
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemPrfSaveNever, 1);
+ }
+
+ // ------------------------------------------------------------
+ // Set up the HotSync User Name edit text item.
+ // ------------------------------------------------------------
+
+ EmDlg::SetItemText (dlg, kDlgItemPrfUserName, data.prefUserName);
+}
+
+
+void EmDlg::PrvEditPrefFromDialog (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+#if !PLATFORM_UNIX
+
+ // ------------------------------------------------------------
+ // Save the port settings.
+ // ------------------------------------------------------------
+
+ data.prefPortSerial = data.menuItemsSerial [EmDlg::GetItemValue (dlg, kDlgItemPrfRedirectSerial)];
+ data.prefPortIR = data.menuItemsIR [EmDlg::GetItemValue (dlg, kDlgItemPrfRedirectIR)];
+ data.prefPortMystery = data.menuItemsMystery [EmDlg::GetItemValue (dlg, kDlgItemPrfRedirectMystery)];
+
+#else
+
+ // ------------------------------------------------------------
+ // Save the port settings.
+ // ------------------------------------------------------------
+
+ data.prefPortSerial = EmDlg::GetItemText (dlg, kDlgItemPrfRedirectSerial);
+ data.prefPortIR = EmDlg::GetItemText (dlg, kDlgItemPrfRedirectIR);
+ data.prefPortMystery = EmDlg::GetItemText (dlg, kDlgItemPrfRedirectMystery);
+
+#endif
+
+ // ------------------------------------------------------------
+ // Save the Redirect NetLib and Enable Sounds settings.
+ // ------------------------------------------------------------
+
+ data.prefRedirectNetLib = EmDlg::GetItemValue (dlg, kDlgItemPrfRedirectNetLib) != 0;
+ data.prefEnableSounds = EmDlg::GetItemValue (dlg, kDlgItemPrfEnableSound) != 0;
+
+ // ------------------------------------------------------------
+ // Save the Close Action settings.
+ // ------------------------------------------------------------
+
+ if (EmDlg::GetItemValue (dlg, kDlgItemPrfSaveAlways) != 0)
+ {
+ data.prefCloseAction = kSaveAlways;
+ }
+ else if (EmDlg::GetItemValue (dlg, kDlgItemPrfSaveAsk) != 0)
+ {
+ data.prefCloseAction = kSaveAsk;
+ }
+ else
+ {
+ data.prefCloseAction = kSaveNever;
+ }
+
+ // ------------------------------------------------------------
+ // Save the HotSync User Name setting.
+ // ------------------------------------------------------------
+
+ data.prefUserName = EmDlg::GetItemText (dlg, kDlgItemPrfUserName);
+}
+
+
+#if !PLATFORM_UNIX
+
+// Build up descriptors lists for each menu.
+
+void EmDlg::PrvBuildDescriptorLists (EmDlgContext& context)
+{
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+ EmTransportDescriptorList descListNull;
+ EmTransportDescriptorList descListSerial;
+ EmTransportDescriptorList descListSocket;
+
+ EmTransportNull::GetDescriptorList (descListNull);
+ EmTransportSerial::GetDescriptorList (descListSerial);
+ EmTransportSocket::GetDescriptorList (descListSocket);
+
+ data.menuItemsSerial.clear ();
+ data.menuItemsIR.clear ();
+ data.menuItemsMystery.clear ();
+
+ ::PrvAppendDescriptors (data.menuItemsSerial, descListNull);
+ ::PrvAppendDescriptors (data.menuItemsSerial, descListSerial);
+ ::PrvAppendDescriptors (data.menuItemsSerial, descListSocket);
+
+ ::PrvAppendDescriptors (data.menuItemsIR, descListNull);
+ ::PrvAppendDescriptors (data.menuItemsIR, descListSerial);
+ ::PrvAppendDescriptors (data.menuItemsIR, descListSocket);
+
+ ::PrvAppendDescriptors (data.menuItemsMystery, descListNull);
+ ::PrvAppendDescriptors (data.menuItemsMystery, descListSerial);
+
+ // Find the socket descriptors, and add the socket-specific information.
+
+ {
+ EmTransportDescriptorList::iterator iter = data.menuItemsSerial.begin ();
+ while (iter != data.menuItemsSerial.end ())
+ {
+ if (iter->GetType () == kTransportSocket)
+ {
+ *iter = EmTransportDescriptor (iter->GetScheme () + ":" + data.prefPortSerialSocket);
+ break;
+ }
+
+ ++iter;
+ }
+ }
+
+ {
+ EmTransportDescriptorList::iterator iter = data.menuItemsIR.begin ();
+ while (iter != data.menuItemsIR.end ())
+ {
+ if (iter->GetType () == kTransportSocket)
+ {
+ *iter = EmTransportDescriptor (iter->GetScheme () + ":" + data.prefPortIRSocket);
+ break;
+ }
+
+ ++iter;
+ }
+ }
+}
+
+#endif // !UNIX
+
+
+// Transfer the preferences into local variables so that we can
+// change them with impunity. Also build up some menu lists.
+
+void EmDlg::PrvGetEditPreferences (EmDlgContext& context)
+{
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+ Preference<EmTransportDescriptor> prefPortSerial (kPrefKeyPortSerial);
+ Preference<EmTransportDescriptor> prefPortIR (kPrefKeyPortIR);
+ Preference<EmTransportDescriptor> prefPortMystery (kPrefKeyPortMystery);
+ Preference<bool> prefRedirectNetLib (kPrefKeyRedirectNetLib);
+ Preference<bool> prefEnableSounds (kPrefKeyEnableSounds);
+ Preference<CloseActionType> prefCloseAction (kPrefKeyCloseAction);
+ Preference<string> prefUserName (kPrefKeyUserName);
+
+ Preference<string> prefPortSerialSocket(kPrefKeyPortSerialSocket);
+ Preference<string> prefPortIRSocket (kPrefKeyPortIRSocket);
+
+ data.prefPortSerial = *prefPortSerial;
+ data.prefPortIR = *prefPortIR;
+ data.prefPortMystery = *prefPortMystery;
+ data.prefRedirectNetLib = *prefRedirectNetLib;
+ data.prefEnableSounds = *prefEnableSounds;
+ data.prefCloseAction = *prefCloseAction;
+ data.prefUserName = *prefUserName;
+
+#if !PLATFORM_UNIX
+ data.prefPortSerialSocket = *prefPortSerialSocket;
+ data.prefPortIRSocket = *prefPortIRSocket;
+
+ EmDlg::PrvBuildDescriptorLists (context);
+#endif
+}
+
+
+// Transfer our update preferences back to the Preferences system.
+
+void EmDlg::PrvPutEditPreferences (EmDlgContext& context)
+{
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+ Preference<EmTransportDescriptor> prefPortSerial (kPrefKeyPortSerial);
+ Preference<EmTransportDescriptor> prefPortIR (kPrefKeyPortIR);
+ Preference<EmTransportDescriptor> prefPortMystery (kPrefKeyPortMystery);
+ Preference<bool> prefRedirectNetLib (kPrefKeyRedirectNetLib);
+ Preference<bool> prefEnableSounds (kPrefKeyEnableSounds);
+ Preference<CloseActionType> prefCloseAction (kPrefKeyCloseAction);
+ Preference<string> prefUserName (kPrefKeyUserName);
+
+ Preference<string> prefPortSerialSocket(kPrefKeyPortSerialSocket);
+ Preference<string> prefPortIRSocket (kPrefKeyPortIRSocket);
+
+ prefPortSerial = data.prefPortSerial;
+ prefPortIR = data.prefPortIR;
+ prefPortMystery = data.prefPortMystery;
+ prefRedirectNetLib = data.prefRedirectNetLib;
+ prefEnableSounds = data.prefEnableSounds;
+ prefCloseAction = data.prefCloseAction;
+ prefUserName = data.prefUserName;
+
+#if !PLATFORM_UNIX
+ prefPortSerialSocket = data.prefPortSerialSocket;
+ prefPortIRSocket = data.prefPortIRSocket;
+#endif
+}
+
+
+Bool EmDlg::PrvEditPreferencesValidate (EmDlgContext& context)
+{
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+ if (data.prefUserName.size () > dlkMaxUserNameLength)
+ {
+ EmDlg::DoCommonDialog (kStr_UserNameTooLong, kDlgFlags_OK);
+ return false;
+ }
+
+ return true;
+}
+
+
+#if !PLATFORM_UNIX
+// Fetch an IP address from the user, store it in the appropriate
+// field, and rebuild the menus.
+
+void EmDlg::PrvGetPrefSocketAddress (EmDlgContext& context)
+{
+ EmAssert ((context.fItemID == kDlgItemPrfRedirectSerial) ||
+ (context.fItemID == kDlgItemPrfRedirectIR));
+
+ EmDlgRef dlg = context.fDlg;
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+
+ // Move current settings into our local data.
+
+ EmDlg::PrvEditPrefFromDialog (context);
+
+ // Figure out which descriptor was selected.
+
+ string address;
+ EmTransportDescriptor selectedDesc;
+
+ if (context.fItemID == kDlgItemPrfRedirectSerial)
+ {
+ address = data.prefPortSerialSocket;
+ selectedDesc = data.menuItemsSerial [EmDlg::GetItemValue (dlg, context.fItemID)];
+ }
+ else if (context.fItemID == kDlgItemPrfRedirectIR)
+ {
+ address = data.prefPortIRSocket;
+ selectedDesc = data.menuItemsIR [EmDlg::GetItemValue (dlg, context.fItemID)];
+ }
+
+ // If it was for the socket menu item, get the address.
+
+ if (selectedDesc.GetType () == kTransportSocket)
+ {
+ EmDlgItemID item = EmDlg::DoGetSocketAddress (address);
+
+ if (item == kDlgItemOK)
+ {
+ EmTransportDescriptor prefDesc = EmTransportDescriptor (
+ selectedDesc.GetScheme () + ":" + address);
+
+ if (context.fItemID == kDlgItemPrfRedirectSerial)
+ {
+ data.prefPortSerial = prefDesc;
+ data.prefPortSerialSocket = address;
+ }
+ else if (context.fItemID == kDlgItemPrfRedirectIR)
+ {
+ data.prefPortIR = prefDesc;
+ data.prefPortIRSocket = address;
+ }
+
+ EmDlg::PrvBuildDescriptorLists (context);
+ EmDlg::PrvEditPrefToDialog (context);
+ }
+ }
+}
+#endif
+
+EmDlgFnResult EmDlg::PrvEditPreferences (EmDlgContext& context)
+{
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::PrvGetEditPreferences (context);
+ EmDlg::PrvEditPrefToDialog (context);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Make sure all the preferences are something we can live with.
+
+ EmDlg::PrvEditPrefFromDialog (context);
+ if (!EmDlg::PrvEditPreferencesValidate (context))
+ break;
+
+ // Save the preferences.
+
+ EmDlg::PrvPutEditPreferences (context);
+
+ // Update the emulated environment with the
+ // new preferences.
+
+ if (gSession && EmPatchState::UIInitialized ())
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped ())
+ {
+ EditPreferencesData& data = *(EditPreferencesData*) context.fUserData;
+ ::SetHotSyncUserName (data.prefUserName.c_str ());
+
+ // Update the transports used for UART emulation.
+
+ gEmuPrefs->SetTransports ();
+ }
+ }
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemPrfRedirectSerial:
+ case kDlgItemPrfRedirectIR:
+#if !PLATFORM_UNIX
+ EmDlg::PrvGetPrefSocketAddress (context);
+#endif
+ break;
+
+ case kDlgItemPrfRedirectMystery:
+ case kDlgItemPrfRedirectNetLib:
+ case kDlgItemPrfEnableSound:
+ case kDlgItemPrfSaveAlways:
+ case kDlgItemPrfSaveAsk:
+ case kDlgItemPrfSaveNever:
+ case kDlgItemPrfUserName:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditPreferences (void)
+{
+ EditPreferencesData data;
+
+ EmDlgID dlgID = gApplication->IsBoundFully ()
+ ? kDlgEditPreferencesFullyBound
+ : kDlgEditPreferences;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditPreferences, &data, dlgID);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditLoggingOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditLoggingOptionsData
+{
+ LoggingType fActiveSet;
+
+ // Define a "uint8" variable for each of the logging options we
+ // support. The name of each variable is of the form "f<name>",
+ // where "<name>" is what appear in the FOR_EACH_LOG_PREF macro.
+
+#undef DEFINE_STORAGE
+#define DEFINE_STORAGE(name) uint8 f##name;
+ FOR_EACH_LOG_PREF (DEFINE_STORAGE)
+};
+
+
+void EmDlg::PrvFetchLoggingPrefs (EmDlgContext& context)
+{
+ // Transfer all of the logging values from the preferences
+ // to our local storage.
+
+ EditLoggingOptionsData& data = *(EditLoggingOptionsData*) context.fUserData;
+
+ #undef GET_PREF
+ #define GET_PREF(name) \
+ { \
+ Preference<uint8> pref(kPrefKey##name); \
+ data.f##name = *pref; \
+ }
+
+ FOR_EACH_LOG_PREF (GET_PREF)
+}
+
+
+void EmDlg::PrvInstallLoggingPrefs (EmDlgContext& context)
+{
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ // Transfer all of the logging values from our local
+ // storages to the preferences system.
+
+ EditLoggingOptionsData& data = *(EditLoggingOptionsData*) context.fUserData;
+
+ #undef SET_PREF
+ #define SET_PREF(name) \
+ { \
+ Preference<uint8> pref(kPrefKey##name); \
+ pref = data.f##name; \
+ }
+
+ FOR_EACH_LOG_PREF (SET_PREF)
+}
+
+
+void EmDlg::PrvLoggingPrefsToButtons (EmDlgContext& context)
+{
+ // Set the buttons in the current panel.
+
+ EditLoggingOptionsData& data = *(EditLoggingOptionsData*) context.fUserData;
+ int bitmask = data.fActiveSet;
+
+ #undef TO_BUTTON
+ #define TO_BUTTON(name) \
+ EmDlg::SetItemValue (context.fDlg, kDlgItemLog##name, (data.f##name & bitmask) != 0);
+
+ FOR_EACH_LOG_PREF (TO_BUTTON)
+}
+
+
+void EmDlg::PrvLoggingPrefsFromButtons (EmDlgContext& context)
+{
+ // Update our local preference values from the buttons in the current panel.
+
+ EditLoggingOptionsData& data = *(EditLoggingOptionsData*) context.fUserData;
+ int bitmask = data.fActiveSet;
+
+ #undef FROM_BUTTON
+ #define FROM_BUTTON(name) \
+ if (EmDlg::GetItemValue (context.fDlg, kDlgItemLog##name) != 0) \
+ data.f##name |= bitmask; \
+ else \
+ data.f##name &= ~bitmask;
+
+ FOR_EACH_LOG_PREF (FROM_BUTTON)
+}
+
+
+EmDlgFnResult EmDlg::PrvEditLoggingOptions (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditLoggingOptionsData& data = *(EditLoggingOptionsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::PrvFetchLoggingPrefs (context);
+ EmDlg::PrvLoggingPrefsToButtons (context);
+
+ if (data.fActiveSet == kNormalLogging)
+ EmDlg::SetItemValue (dlg, kDlgItemLogNormal, 1);
+ else
+ EmDlg::SetItemValue (dlg, kDlgItemLogGremlins, 1);
+
+ // Disable unsupported options.
+
+ EmDlg::DisableItem (dlg, kDlgItemLogLogCPUOpcodes);
+ EmDlg::DisableItem (dlg, kDlgItemLogLogApplicationCalls);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ EmDlg::PrvLoggingPrefsFromButtons (context);
+ EmDlg::PrvInstallLoggingPrefs (context);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemLogNormal:
+ case kDlgItemLogGremlins:
+ EmDlg::PrvLoggingPrefsFromButtons (context);
+ if (context.fItemID == kDlgItemLogNormal)
+ data.fActiveSet = kNormalLogging;
+ else
+ data.fActiveSet = kGremlinLogging;
+ EmDlg::PrvLoggingPrefsToButtons (context);
+ break;
+
+ #undef DUMMY_CASE
+ #define DUMMY_CASE(name) case kDlgItemLog##name:
+ FOR_EACH_LOG_PREF (DUMMY_CASE)
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditLoggingOptions (LoggingType initialSet)
+{
+ EditLoggingOptionsData data;
+
+ data.fActiveSet = initialSet;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditLoggingOptions, &data, kDlgEditLogging);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditDebuggingOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditDebuggingOptionsData
+{
+ // Define a "Bool" variable for each of the debugging options we
+ // support. The name of each variable is of the form "f<name>",
+ // where "<name>" is what appear in the FOR_EACH_REPORT_PREF macro.
+
+#undef DEFINE_STORAGE
+#define DEFINE_STORAGE(name) Bool f##name;
+ FOR_EACH_REPORT_PREF (DEFINE_STORAGE)
+
+ DEFINE_STORAGE(DialogBeep)
+};
+
+
+void EmDlg::PrvFetchDebuggingPrefs (EmDlgContext& context)
+{
+ // Transfer all of the debugging values from the preferences
+ // to our local storage.
+
+ EditDebuggingOptionsData& data = *(EditDebuggingOptionsData*) context.fUserData;
+
+ #undef GET_PREF
+ #define GET_PREF(name) \
+ { \
+ Preference<Bool> pref(kPrefKey##name); \
+ data.f##name = *pref; \
+ }
+
+ FOR_EACH_REPORT_PREF (GET_PREF)
+
+ GET_PREF(DialogBeep)
+}
+
+
+void EmDlg::PrvInstallDebuggingPrefs (EmDlgContext& context)
+{
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ // Transfer all of the debugging values from our local
+ // storages to the preferences system.
+
+ EditDebuggingOptionsData& data = *(EditDebuggingOptionsData*) context.fUserData;
+
+ #undef SET_PREF
+ #define SET_PREF(name) \
+ { \
+ Preference<Bool> pref(kPrefKey##name); \
+ pref = data.f##name; \
+ }
+
+ FOR_EACH_REPORT_PREF (SET_PREF)
+
+
+ SET_PREF(DialogBeep)
+}
+
+
+void EmDlg::PrvDebuggingPrefsToButtons (EmDlgContext& context)
+{
+ // Set the buttons in the current panel.
+
+ EditDebuggingOptionsData& data = *(EditDebuggingOptionsData*) context.fUserData;
+
+ #undef TO_BUTTON
+ #define TO_BUTTON(name) \
+ EmDlg::SetItemValue (context.fDlg, kDlgItemDbg##name, data.f##name);
+
+ FOR_EACH_REPORT_PREF (TO_BUTTON)
+
+ TO_BUTTON(DialogBeep)
+}
+
+
+void EmDlg::PrvDebuggingPrefsFromButtons (EmDlgContext& context)
+{
+ // Update our local preference values from the buttons in the current panel.
+
+ EditDebuggingOptionsData& data = *(EditDebuggingOptionsData*) context.fUserData;
+
+ #undef FROM_BUTTON
+ #define FROM_BUTTON(name) \
+ data.f##name = EmDlg::GetItemValue (context.fDlg, kDlgItemDbg##name) != 0;
+
+ FOR_EACH_REPORT_PREF (FROM_BUTTON)
+
+ FROM_BUTTON(DialogBeep)
+}
+
+
+EmDlgFnResult EmDlg::PrvEditDebuggingOptions (EmDlgContext& context)
+{
+// EmDlgRef dlg = context.fDlg;
+// EditDebuggingOptionsData& data = *(EditDebuggingOptionsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::PrvFetchDebuggingPrefs (context);
+ EmDlg::PrvDebuggingPrefsToButtons (context);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ EmDlg::PrvDebuggingPrefsFromButtons (context);
+ EmDlg::PrvInstallDebuggingPrefs (context);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ #undef DUMMY_CASE
+ #define DUMMY_CASE(name) case kDlgItemDbg##name:
+ FOR_EACH_REPORT_PREF (DUMMY_CASE)
+
+ DUMMY_CASE(DialogBeep)
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditDebuggingOptions (void)
+{
+ EditDebuggingOptionsData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditDebuggingOptions, &data, kDlgEditDebugging);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditDebuggingOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+// Map from an EmErrorHandlingOption to the menu string for it.
+
+struct
+{
+ EmErrorHandlingOption fOption;
+ StrCode fString;
+} kMenuItemText[] =
+{
+ { kShow, kStr_ShowInDialog },
+ { kContinue, kStr_AutomaticallyContinue },
+ { kQuit, kStr_AutomaticallyQuit },
+ { kSwitch, kStr_NextGremlin }
+};
+
+
+// Struct representing a single menu item.
+
+struct EmErrorHandlingMenuItemBundle
+{
+ EmErrorHandlingOption fOption;
+};
+
+
+// Menu items for the four menus in the dialog box.
+
+EmErrorHandlingMenuItemBundle kMenuItems1[] =
+{
+ { kShow },
+ { kContinue }
+};
+
+
+EmErrorHandlingMenuItemBundle kMenuItems2[] =
+{
+ { kShow },
+ { kQuit }
+};
+
+
+EmErrorHandlingMenuItemBundle kMenuItems3[] =
+{
+ { kShow },
+ { kContinue },
+ { kSwitch }
+};
+
+
+EmErrorHandlingMenuItemBundle kMenuItems4[] =
+{
+ { kShow },
+ { kQuit },
+ { kSwitch }
+};
+
+
+// Struct containing all information for a single menu in the dialog box.
+
+struct EmErrorHandlingMenuBundle
+{
+ EmErrorHandlingMenuItemBundle* fMenuItems; // Menu items
+ size_t fNumItems; // Number of menu items
+ EmDlgItemID fDlgItem; // Dialog item to get these items
+ PrefKeyType fPrefKey; // Preference to get selected option
+ PrefKeyType fLogPrefKey; // Logging option to turn on
+ LoggingType fLogType; // Flag in the logging option to turn on
+ Bool fEnableLogging; // True if logging option should be turned on
+};
+
+// Information for the Gremlins Off / On Warning menu.
+
+EmErrorHandlingMenuBundle gMenu1 =
+{
+ kMenuItems1,
+ countof (kMenuItems1),
+ kDlgItemErrWarningOff,
+ kPrefKeyWarningOff,
+ kPrefKeyLogWarningMessages,
+ kNormalLogging
+};
+
+// Information for the Gremlins Off / On Error menu.
+
+EmErrorHandlingMenuBundle gMenu2 =
+{
+ kMenuItems2,
+ countof (kMenuItems2),
+ kDlgItemErrErrorOff,
+ kPrefKeyErrorOff,
+ kPrefKeyLogErrorMessages,
+ kNormalLogging
+};
+
+// Information for the Gremlins On / On Warning menu.
+
+EmErrorHandlingMenuBundle gMenu3 =
+{
+ kMenuItems3,
+ countof (kMenuItems3),
+ kDlgItemErrWarningOn,
+ kPrefKeyWarningOn,
+ kPrefKeyLogWarningMessages,
+ kGremlinLogging
+};
+
+// Information for the Gremlins On / On Error menu.
+
+EmErrorHandlingMenuBundle gMenu4 =
+{
+ kMenuItems4,
+ countof (kMenuItems4),
+ kDlgItemErrErrorOn,
+ kPrefKeyErrorOn,
+ kPrefKeyLogErrorMessages,
+ kGremlinLogging
+};
+
+
+// Return the text of the menu item for the given error handling option.
+// Makes use of the kMenuItemText map above.
+
+string EmDlg::PrvMenuItemText (EmErrorHandlingOption item)
+{
+ for (size_t ii = 0; ii < countof (kMenuItemText); ++ii)
+ {
+ if (kMenuItemText[ii].fOption == item)
+ {
+ return Platform::GetString (kMenuItemText[ii].fString);
+ }
+ }
+
+ EmAssert (false);
+
+ return string();
+}
+
+
+// Build up the menu items in the dialog, based on the information in
+// the given EmErrorHandlingMenuBundle. Results are stored in "items".
+
+void EmDlg::PrvBuildMenu ( EmErrorHandlingMenuBundle& menu,
+ StringList& items)
+{
+ size_t numItems = menu.fNumItems;
+
+ for (size_t ii = 0; ii < numItems; ++ii)
+ {
+ items.push_back (EmDlg::PrvMenuItemText (menu.fMenuItems[ii].fOption));
+ }
+};
+
+
+// Find the menu item index in the given menu corresponding to the
+// given EmErrorHandlingOption. This function is used when selecting
+// the initial menu item based on the current preference settings.
+
+long EmDlg::PrvFindIndex ( EmErrorHandlingMenuBundle& menu,
+ EmErrorHandlingOption toFind)
+{
+ size_t numItems = menu.fNumItems;
+
+ for (size_t ii = 0; ii < numItems; ++ii)
+ {
+ if (menu.fMenuItems[ii].fOption == toFind)
+ return (long) ii;
+ }
+
+ return -1;
+}
+
+
+// Build up the menu items in the dialog for the given menu, and select
+// the initial menu item based on the current preference setting.
+
+void EmDlg::PrvErrorHandlingToDialog ( EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ StringList menuItemsText;
+ EmDlg::PrvBuildMenu (menu, menuItemsText);
+
+ Preference<EmErrorHandlingOption> pref (menu.fPrefKey);
+ long index = EmDlg::PrvFindIndex (menu, *pref);
+ if (index < 0)
+ index = 0;
+
+ EmDlg::AppendToMenu (dlg, menu.fDlgItem, menuItemsText);
+ EmDlg::SetItemValue (dlg, menu.fDlgItem, index);
+}
+
+
+// Take the currently selected item and use it to establish a new
+// preference setting.
+
+void EmDlg::PrvErrorHandlingFromDialog (EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu)
+{
+ EmDlgRef dlg = context.fDlg;
+ long index = EmDlg::GetItemValue (dlg, menu.fDlgItem);
+
+ EmAssert (index >= 0);
+ EmAssert (index < (long) menu.fNumItems);
+
+ Preference<EmErrorHandlingOption> pref (menu.fPrefKey);
+ pref = menu.fMenuItems[index].fOption;
+}
+
+
+// Ask the user if they'd like us to change the Logging Option settings
+// for them as appropriate.
+
+EmDlgItemID EmDlg::PrvAskChangeLogging (void)
+{
+ string msg = Platform::GetString (kStr_MustTurnOnLogging);
+ EmDlgItemID result = EmDlg::DoCommonDialog (msg, kDlgFlags_YES_No);
+
+ return result;
+}
+
+
+// Check a single menu item selection, seeing if a corresponding change
+// in the logging options needs to be made.
+
+void EmDlg::PrvCheckSetting ( EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu)
+{
+ Preference<uint8> pref (menu.fLogPrefKey);
+
+ EmDlgRef dlg = context.fDlg;
+ long index = EmDlg::GetItemValue (dlg, menu.fDlgItem);
+ EmErrorHandlingOption option = menu.fMenuItems[index].fOption;
+
+ Bool needLogging = option != kShow;
+ Bool haveLogging = (*pref & menu.fLogType) != 0;
+
+ menu.fEnableLogging = needLogging && !haveLogging;
+}
+
+
+// Check all menus to see if any of them require a change in the logging options.
+
+Bool EmDlg::PrvCheckSettings (EmDlgContext& context)
+{
+ EmDlg::PrvCheckSetting (context, gMenu1);
+ EmDlg::PrvCheckSetting (context, gMenu2);
+ EmDlg::PrvCheckSetting (context, gMenu3);
+ EmDlg::PrvCheckSetting (context, gMenu4);
+
+ return
+ gMenu1.fEnableLogging ||
+ gMenu2.fEnableLogging ||
+ gMenu3.fEnableLogging ||
+ gMenu4.fEnableLogging;
+}
+
+
+// Enable a single logging option corresponding to the given menu,
+// if appropriate.
+
+void EmDlg::PrvEnableLoggingOption (EmErrorHandlingMenuBundle& menu)
+{
+ if (menu.fEnableLogging)
+ {
+ Preference<uint8> pref (menu.fLogPrefKey);
+ pref = *pref | menu.fLogType;
+ }
+}
+
+
+// Enable all necessary logging options.
+
+void EmDlg::PrvEnableLoggingOptions (void)
+{
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ EmDlg::PrvEnableLoggingOption (gMenu1);
+ EmDlg::PrvEnableLoggingOption (gMenu2);
+ EmDlg::PrvEnableLoggingOption (gMenu3);
+ EmDlg::PrvEnableLoggingOption (gMenu4);
+}
+
+
+EmDlgFnResult EmDlg::PrvErrorHandling (EmDlgContext& context)
+{
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::PrvErrorHandlingToDialog (context, gMenu1);
+ EmDlg::PrvErrorHandlingToDialog (context, gMenu2);
+ EmDlg::PrvErrorHandlingToDialog (context, gMenu3);
+ EmDlg::PrvErrorHandlingToDialog (context, gMenu4);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ if (EmDlg::PrvCheckSettings (context))
+ {
+ if (EmDlg::PrvAskChangeLogging () == kDlgItemNo)
+ {
+ // Don't commit the changes; don't close the dialog.
+ return kDlgResultContinue;
+ }
+
+ EmDlg::PrvEnableLoggingOptions ();
+ }
+
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ EmDlg::PrvErrorHandlingFromDialog (context, gMenu1);
+ EmDlg::PrvErrorHandlingFromDialog (context, gMenu2);
+ EmDlg::PrvErrorHandlingFromDialog (context, gMenu3);
+ EmDlg::PrvErrorHandlingFromDialog (context, gMenu4);
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemErrWarningOff:
+ case kDlgItemErrErrorOff:
+ case kDlgItemErrWarningOn:
+ case kDlgItemErrErrorOn:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditErrorHandling (void)
+{
+ return EmDlg::RunDialog (EmDlg::PrvErrorHandling, NULL, kDlgEditErrorHandling);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditSkins
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditSkinsData
+{
+ EmDevice fDevice;
+ SkinNameList fSkins;
+};
+
+
+EmDlgFnResult EmDlg::PrvEditSkins (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditSkinsData& data = *(EditSkinsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Get the skin the user has chosen.
+
+ SkinName prefSkin = ::SkinGetSkinName (data.fDevice);
+
+ // Add each skin in the list to the UI element.
+
+ Bool selected = false;
+ int index = 0;
+ SkinNameList::iterator skinIter = data.fSkins.begin();
+
+ while (skinIter != data.fSkins.end())
+ {
+ EmDlg::AppendToList (dlg, kDlgItemSknSkinList, *skinIter);
+
+ // Select the currently-used skin.
+
+ if (*skinIter == prefSkin)
+ {
+ EmDlg::SelectListItem (dlg, kDlgItemSknSkinList, index);
+ selected = true;
+ }
+
+ ++index;
+ ++skinIter;
+ }
+
+ // Ensure that *something* was selected.
+
+ if (!selected)
+ {
+ EmDlg::SelectListItem (dlg, kDlgItemSknSkinList, 0);
+ }
+
+ // Set up the checkboxes
+
+ {
+ Preference<ScaleType> pref (kPrefKeyScale);
+ EmDlg::SetItemValue (dlg, kDlgItemSknDoubleScale, (*pref == 2) ? 1 : 0);
+ }
+
+ {
+ Preference<RGBType> pref (kPrefKeyBackgroundColor);
+ EmDlg::SetItemValue (dlg, kDlgItemSknWhiteBackground, pref.Loaded () ? 1 : 0);
+ }
+
+ {
+ Preference<bool> pref (kPrefKeyDimWhenInactive);
+ EmDlg::SetItemValue (dlg, kDlgItemSknDim, *pref ? 1 : 0);
+ }
+
+ {
+ Preference<bool> pref (kPrefKeyShowDebugMode);
+ EmDlg::SetItemValue (dlg, kDlgItemSknRed, *pref ? 1 : 0);
+ }
+
+ {
+ Preference<bool> pref (kPrefKeyShowGremlinMode);
+ EmDlg::SetItemValue (dlg, kDlgItemSknGreen, *pref ? 1 : 0);
+ }
+
+ {
+ Preference<bool> pref (kPrefKeyStayOnTop);
+ EmDlg::SetItemValue (dlg, kDlgItemSknStayOnTop, *pref ? 1 : 0);
+ }
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Update the skin choice.
+
+ // Get the selected skin.
+
+ EmDlgListIndex index = EmDlg::GetSelectedItem (dlg, kDlgItemSknSkinList);
+ EmAssert (index != kDlgItemListNone);
+
+ // Update the preferences.
+
+ ::SkinSetSkinName (data.fDevice, data.fSkins[index]);
+
+ // Update the scale.
+
+ Preference<ScaleType> prefScale (kPrefKeyScale);
+ prefScale = (GetItemValue (dlg, kDlgItemSknDoubleScale) != 0) ? 2 : 1;
+
+ // Update the background color.
+
+ if (EmDlg::GetItemValue (dlg, kDlgItemSknWhiteBackground) != 0)
+ {
+ RGBType color (0xFF, 0xFF, 0xFF);
+ Preference<RGBType> prefBackgroundColor (kPrefKeyBackgroundColor);
+ prefBackgroundColor = color;
+ }
+ else
+ {
+ gPrefs->DeletePref (kPrefKeyBackgroundColor);
+ }
+
+ // Update "Dim When Inactive" setting.
+
+ {
+ Preference<bool> pref (kPrefKeyDimWhenInactive);
+ pref = (GetItemValue (dlg, kDlgItemSknDim) != 0) ? true : false;
+ }
+
+ // Update "Show Debug Mode" setting.
+
+ {
+ Preference<bool> pref (kPrefKeyShowDebugMode);
+ pref = (GetItemValue (dlg, kDlgItemSknRed) != 0) ? true : false;
+ }
+
+ // Update "Show Gremlin Mode" setting.
+
+ {
+ Preference<bool> pref (kPrefKeyShowGremlinMode);
+ pref = (GetItemValue (dlg, kDlgItemSknGreen) != 0) ? true : false;
+ }
+
+ // Update the stay on top setting.
+
+ {
+ Preference<bool> pref (kPrefKeyStayOnTop);
+ pref = (GetItemValue (dlg, kDlgItemSknStayOnTop) != 0) ? true : false;
+ }
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemSknSkinList:
+ case kDlgItemSknDoubleScale:
+ case kDlgItemSknWhiteBackground:
+ case kDlgItemSknDim:
+ case kDlgItemSknRed:
+ case kDlgItemSknGreen:
+ case kDlgItemSknStayOnTop:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditSkins (void)
+{
+ Preference<Configuration> prefConfiguration (kPrefKeyLastConfiguration);
+ Configuration cfg = *prefConfiguration;
+
+ EditSkinsData data;
+ data.fDevice = cfg.fDevice;
+
+ ::SkinGetSkinNames (data.fDevice, data.fSkins);
+
+ return EmDlg::RunDialog (EmDlg::PrvEditSkins, &data, kDlgEditSkins);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditHostFSOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditHostFSOptionsData
+{
+ SlotInfoList fWorkingInfo;
+};
+
+const int kMaxVolumes = 8;
+
+void EmDlg::PrvEditHostFSOptionsOK (EmDlgContext& context)
+{
+ EditHostFSOptionsData& data = *(EditHostFSOptionsData*) context.fUserData;
+
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+
+ Preference<SlotInfoList> pref (kPrefKeySlotList);
+ SlotInfoList origList = *pref;
+ pref = data.fWorkingInfo;
+
+ // For any that changed, mount/unmount the cards.
+
+ UInt16 refNum;
+ Err err = ::SysLibFind ("HostFS Library", &refNum);
+
+ if (err != errNone || refNum == sysInvalidRefNum)
+ {
+ EmDlg::DoCommonDialog (kStr_NeedHostFS, kDlgFlags_OK);
+ return;
+ }
+
+ // We've made sure that we have the HostFS library,
+ // so it's OK to try to notify it about changes.
+
+ // Iterate over all the items before the user changed
+ // them in the Options dialog.
+
+ SlotInfoList::iterator iter1 = origList.begin ();
+ while (iter1 != origList.end ())
+ {
+ // Iterate over all the items *after* the user changed
+ // them in the dialog.
+
+ SlotInfoList::iterator iter2 = data.fWorkingInfo.begin ();
+ while (iter2 != data.fWorkingInfo.end ())
+ {
+ // Compare one item from the "before" list to one item
+ // in the "after" list. If they're for the same volume,
+ // we will want to compare them further.
+
+ if (iter1->fSlotNumber == iter2->fSlotNumber)
+ {
+ // The volume in this slot either used to be mounted
+ // and now is not, or didn't used to be mounted but
+ // now is. We'll need to tell the HostFS library.
+
+ if (iter1->fSlotOccupied != iter2->fSlotOccupied)
+ {
+ const UInt32 kCreator = 'pose';
+ const UInt16 kMounted = 1;
+ const UInt16 kUnmounted = 0;
+
+ UInt16 selector = iter2->fSlotOccupied ? kMounted : kUnmounted;
+ void* cardNum = (void*) iter1->fSlotNumber;
+
+ // Note, in order to make this call, the CPU should be stopped
+ // in the UI task. That's because mounting and unmounting can
+ // send out notification. If the notification is sent out while
+ // the current Palm OS task is not the UI task, then the
+ // notification manager calls SysTaskWait. This will switch
+ // to another task if it can, and prime a timer to re-awake
+ // the background task if not. However, this timer is based
+ // on an interrupt going off, and while we're calling into the
+ // ROM, interrupts are turned off, leading to a hang.
+ // Therefore, is is imperative that we call this function
+ // while the UI task is the current task.
+
+ ::FSCustomControl (refNum, kCreator, selector, cardNum, NULL);
+ }
+
+ break;
+ }
+
+ ++iter2;
+ }
+
+ ++iter1;
+ }
+}
+
+
+EmDlgFnResult EmDlg::PrvEditHostFSOptions (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditHostFSOptionsData& data = *(EditHostFSOptionsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Get the current preferences.
+
+ Preference<SlotInfoList> pref (kPrefKeySlotList);
+ data.fWorkingInfo = *pref;
+
+ // Make sure there are at least kMaxVolume entries. If not, then
+ // fill in the missing ones.
+
+ long curSize = data.fWorkingInfo.size ();
+ while (curSize < kMaxVolumes)
+ {
+ SlotInfoType info;
+ info.fSlotNumber = curSize + 1;
+ info.fSlotOccupied = false;
+ data.fWorkingInfo.push_back (info);
+
+ curSize++;
+ }
+
+ // Install the volumes into the list.
+
+ EmDlg::ClearList (dlg, kDlgItemHfsList);
+
+ for (int ii = 0; ii < kMaxVolumes; ++ii)
+ {
+ EmDlg::AppendToList (dlg, kDlgItemHfsList, string (1, (char) ('1' + ii)));
+ }
+
+ // Select one of the volumes.
+
+ EmDlg::SelectListItem (dlg, kDlgItemHfsList, 0);
+
+ // Call ourselves to make sure that the other dialog
+ // items are properly initialized in light of the
+ // currently selected item.
+
+ EmDlgContext subContext (context);
+ subContext.fCommandID = kDlgCmdItemSelected;
+ subContext.fItemID = kDlgItemHfsList;
+ EmDlg::PrvEditHostFSOptions (subContext);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // User pressed OK, save the changes.
+
+ EmDlg::PrvEditHostFSOptionsOK (context);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemHfsList:
+ {
+ // User changed the currently selected card.
+
+ EmDlgListIndex item = EmDlg::GetSelectedItem (dlg, kDlgItemHfsList);
+ if (item >= 0)
+ {
+ SlotInfoType& info = data.fWorkingInfo[item];
+
+ // Get the path to the card's root. If empty, display
+ // a default message so that the user doesn't just see
+ // a blank pane.
+
+ string fullPath (info.fSlotRoot.GetFullPath ());
+ if (fullPath.empty ())
+ fullPath = "<Not selected>";
+
+ // Set the root path text and the button that says if
+ // it's mounted or not.
+
+ EmDlg::SetItemText (dlg, kDlgItemHfsPath, fullPath);
+ EmDlg::SetItemValue (dlg, kDlgItemHfsMounted, info.fSlotOccupied);
+ }
+ break;
+ }
+
+ case kDlgItemHfsPath:
+ break;
+
+ case kDlgItemHfsMounted:
+ {
+ // User toggled the checkbox that says whether or not the
+ // card is mounted. Save the new setting.
+
+ EmDlgListIndex item = EmDlg::GetSelectedItem (dlg, kDlgItemHfsList);
+ if (item >= 0)
+ {
+ SlotInfoType& info = data.fWorkingInfo[item];
+
+ info.fSlotOccupied = EmDlg::GetItemValue (dlg, kDlgItemHfsMounted);
+ }
+ break;
+ }
+
+ case kDlgItemHfsBrowse:
+ {
+ // User clicked on the Browse button. Bring up a
+ // "Get Directory" dialog.
+
+ EmDlgListIndex item = EmDlg::GetSelectedItem (dlg, kDlgItemHfsList);
+ if (item >= 0)
+ {
+ SlotInfoType& info = data.fWorkingInfo[item];
+
+ EmDirRef result;
+ string prompt ("Select a directory:");
+ EmDirRef defaultPath (info.fSlotRoot);
+
+ if (EmDlg::DoGetDirectory (result, prompt, defaultPath) == kDlgItemOK)
+ {
+ info.fSlotRoot = result;
+ EmDlg::SetItemText (dlg, kDlgItemHfsPath, result.GetFullPath ());
+ }
+ }
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditHostFSOptions (void)
+{
+ EditHostFSOptionsData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditHostFSOptions, &data, kDlgEditHostFS);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditBreakpoints
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditCodeBreakpointData
+{
+ Bool fEnabled;
+ emuptr fAddress;
+ string fCondition;
+};
+
+
+struct EditBreakpointsData
+{
+ EditCodeBreakpointData fCodeBreakpoints[dbgTotalBreakpoints];
+};
+
+
+// Enable or disable the Edit and Clear buttons.
+
+void EmDlg::PrvEnableCodeBreakpointControls (EmDlgContext& context, bool enable)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ EmDlg::EnableDisableItem (dlg, kDlgItemBrkButtonEdit, enable);
+ EmDlg::EnableDisableItem (dlg, kDlgItemBrkButtonClear, enable);
+}
+
+
+// Enable or disable the Start Address and Number Of Bytes edit items.
+
+void EmDlg::PrvEnableDataBreakpointControls (EmDlgContext& context, bool enable)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ EmDlg::EnableDisableItem (dlg, kDlgItemBrkStartAddress, enable);
+ EmDlg::EnableDisableItem (dlg, kDlgItemBrkNumberOfBytes, enable);
+}
+
+
+// Install the current set of code breakpoints into the list item.
+
+void EmDlg::PrvRefreshCodeBreakpointList (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditBreakpointsData& data = *(EditBreakpointsData*) context.fUserData;
+
+ EmDlgListIndex selected = EmDlg::GetSelectedItem (dlg, kDlgItemBrkList);
+
+ EmDlg::ClearList (dlg, kDlgItemBrkList);
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ char text[256];
+
+ if (data.fCodeBreakpoints[ii].fEnabled)
+ {
+ sprintf (text, "at 0x%08lX", data.fCodeBreakpoints[ii].fAddress);
+ string condition = data.fCodeBreakpoints[ii].fCondition;
+ if (!condition.empty ())
+ {
+ strcat (text, " when ");
+ strcat (text, condition.c_str ());
+ }
+ }
+ else
+ {
+ sprintf (text, "(#%d - not set)", ii);
+ }
+
+ EmDlg::AppendToList (dlg, kDlgItemBrkList, text);
+ }
+
+ if (selected != kDlgItemListNone)
+ {
+ EmDlg::SelectListItem (dlg, kDlgItemBrkList, selected);
+ }
+}
+
+
+// Copy the breakpoint information from the Debugger globals.
+
+void EmDlg::PrvGetCodeBreakpoints (EmDlgContext& context)
+{
+ EditBreakpointsData& data = *(EditBreakpointsData*) context.fUserData;
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ data.fCodeBreakpoints[ii].fEnabled = gDebuggerGlobals.bp[ii].enabled;
+ data.fCodeBreakpoints[ii].fAddress = (emuptr) gDebuggerGlobals.bp[ii].addr;
+ data.fCodeBreakpoints[ii].fCondition = "";
+
+ BreakpointCondition* c = gDebuggerGlobals.bpCondition[ii];
+ if (c)
+ {
+ data.fCodeBreakpoints[ii].fCondition = c->source;
+ }
+ }
+}
+
+
+// Install the breakpoint information into the Debugger globals.
+
+void EmDlg::PrvSetCodeBreakpoints (EmDlgContext& context)
+{
+ EditBreakpointsData& data = *(EditBreakpointsData*) context.fUserData;
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (data.fCodeBreakpoints[ii].fEnabled)
+ {
+ BreakpointCondition* c = NULL;
+
+ string condition = data.fCodeBreakpoints[ii].fCondition;
+ if (!condition.empty ())
+ {
+ c = Debug::NewBreakpointCondition (condition.c_str ());
+ }
+
+ Debug::SetBreakpoint (ii, data.fCodeBreakpoints[ii].fAddress, c);
+ }
+ else
+ {
+ Debug::ClearBreakpoint (ii);
+ }
+ }
+}
+
+
+EmDlgFnResult EmDlg::PrvEditBreakpoints (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditBreakpointsData& data = *(EditBreakpointsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Set up the list of code breakpoints.
+
+ EmDlg::PrvGetCodeBreakpoints (context);
+ EmDlg::PrvRefreshCodeBreakpointList (context);
+
+ // Initially no breakpoint is selected in the list, so the "edit" and
+ // "clear" buttons should be disabled.
+
+ EmDlg::PrvEnableCodeBreakpointControls (context, false);
+
+ // Set up the data breakpoint items
+
+ char text[256];
+
+ EmDlg::SetItemValue (dlg, kDlgItemBrkCheckEnabled,
+ gDebuggerGlobals.watchEnabled ? 1 : 0);
+
+ sprintf (text, "0x%08lX", gDebuggerGlobals.watchAddr);
+ EmDlg::SetItemText (dlg, kDlgItemBrkStartAddress, text);
+
+ sprintf (text, "0x%08lX", gDebuggerGlobals.watchBytes);
+ EmDlg::SetItemText (dlg, kDlgItemBrkNumberOfBytes, text);
+
+ EmDlg::PrvEnableDataBreakpointControls (context, gDebuggerGlobals.watchEnabled);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // User pressed OK, save the changes.
+
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ // Set the code breakpoints
+
+ EmDlg::PrvSetCodeBreakpoints (context);
+
+
+ // Set data breakpoint
+
+ gDebuggerGlobals.watchEnabled = EmDlg::GetItemValue (dlg, kDlgItemBrkCheckEnabled) != 0;
+
+ if (gDebuggerGlobals.watchEnabled)
+ {
+ gDebuggerGlobals.watchAddr = EmDlg::GetItemValue (dlg, kDlgItemBrkStartAddress);
+ gDebuggerGlobals.watchBytes = EmDlg::GetItemValue (dlg, kDlgItemBrkNumberOfBytes);
+ }
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemBrkList:
+ {
+ EmDlgListIndex selected = EmDlg::GetSelectedItem (dlg, kDlgItemBrkList);
+ EmDlg::PrvEnableCodeBreakpointControls (context, selected != kDlgItemListNone);
+ break;
+ }
+
+ case kDlgItemBrkButtonEdit:
+ {
+ EmDlgListIndex selected = EmDlg::GetSelectedItem (dlg, kDlgItemBrkList);
+ if (selected != kDlgItemListNone)
+ {
+ EmDlg::DoEditCodeBreakpoint (data.fCodeBreakpoints[selected]);
+ EmDlg::PrvRefreshCodeBreakpointList (context);
+ }
+ break;
+ }
+
+ case kDlgItemBrkButtonClear:
+ {
+ EmDlgListIndex selected = EmDlg::GetSelectedItem (dlg, kDlgItemBrkList);
+ if (selected != kDlgItemListNone)
+ {
+ data.fCodeBreakpoints[selected].fEnabled = false;
+ EmDlg::PrvRefreshCodeBreakpointList (context);
+ }
+ break;
+ }
+
+ case kDlgItemBrkCheckEnabled:
+ {
+ long enabled = EmDlg::GetItemValue (dlg, kDlgItemBrkCheckEnabled);
+ EmDlg::PrvEnableDataBreakpointControls (context, enabled != 0);
+ break;
+ }
+
+ case kDlgItemBrkStartAddress:
+ {
+ break;
+ }
+
+ case kDlgItemBrkNumberOfBytes:
+ {
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditBreakpoints (void)
+{
+ EditBreakpointsData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditBreakpoints, &data, kDlgEditBreakpoints);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditCodeBreakpoint
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvEditCodeBreakpoint (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditCodeBreakpointData& data = *(EditCodeBreakpointData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ char text[256];
+
+ sprintf (text, "0x%08lX", data.fAddress);
+ EmDlg::SetItemText (dlg, kDlgItemBrkAddress, text);
+
+ EmDlg::SetItemText (dlg, kDlgItemBrkCondition, data.fCondition);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // User pressed OK, save the changes.
+ char text[256];
+
+ data.fAddress = EmDlg::GetItemValue (dlg, kDlgItemBrkAddress);
+ data.fCondition = EmDlg::GetItemText (dlg, kDlgItemBrkCondition);
+
+ if (data.fAddress & 1)
+ {
+ string formatStr = Platform::GetString (kStr_InvalidAddressNotEven);
+ string addressStr = EmDlg::GetItemText (dlg, kDlgItemBrkAddress);
+ sprintf (text, formatStr.c_str (), addressStr.c_str ());
+ EmDlg::DoCommonDialog (text, kDlgFlags_OK);
+ break;
+ }
+
+ if (!EmBankROM::ValidAddress (data.fAddress, 2) &&
+ !EmBankSRAM::ValidAddress (data.fAddress, 2) &&
+ !EmBankDRAM::ValidAddress (data.fAddress, 2))
+ {
+ string formatStr = Platform::GetString (kStr_InvalidAddressNotInROMOrRAM);
+ string addressStr = EmDlg::GetItemText (dlg, kDlgItemBrkAddress);
+ sprintf (text, formatStr.c_str (), addressStr.c_str ());
+ EmDlg::DoCommonDialog (text, kDlgFlags_OK);
+ break;
+ }
+
+ if (!data.fCondition.empty ())
+ {
+ BreakpointCondition* c = NULL;
+
+ c = Debug::NewBreakpointCondition (data.fCondition.c_str ());
+ if (!c)
+ {
+ string formatStr = Platform::GetString (kStr_CannotParseCondition);
+ sprintf (text, formatStr.c_str (), data.fCondition.c_str ());
+ EmDlg::DoCommonDialog (text, kDlgFlags_OK);
+ break;
+ }
+
+ delete c;
+ }
+
+ data.fEnabled = true;
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemBrkAddress:
+ case kDlgItemBrkCondition:
+ {
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditCodeBreakpoint (EditCodeBreakpointData& data)
+{
+ return EmDlg::RunDialog (EmDlg::PrvEditCodeBreakpoint, &data, kDlgEditCodeBreakpoint);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoEditCodeBreakpoint
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+#if HAS_TRACER
+struct EditTracingOptionsData
+{
+ unsigned short fTracerType;
+};
+
+
+void EmDlg::PrvPopTracerSettings (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditTracingOptionsData& data = *(EditTracingOptionsData*) context.fUserData;
+
+ // Propagate settings from controls to internal table
+
+ if (data.fTracerType)
+ {
+ TracerTypeInfo* info = gTracer.GetTracerTypeInfo (data.fTracerType);
+ EmAssert (info);
+
+ string value = EmDlg::GetItemText (dlg, kDlgItemTrcTargetValue);
+ value = value.substr (0, sizeof (info->paramTmpVal) - 1);
+ strcpy (info->paramTmpVal, value.c_str ());
+
+ info->autoConnectTmpState = EmDlg::GetItemValue (dlg, kDlgItemTrcAutoConnect) != 0;
+ }
+}
+
+
+void EmDlg::PrvPushTracerSettings (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditTracingOptionsData& data = *(EditTracingOptionsData*) context.fUserData;
+
+ // Propagate settings from internal table to controls
+ if (data.fTracerType == 0)
+ {
+ EmDlg::SetItemText (dlg, kDlgItemTrcTargetValue, "");
+ EmDlg::SetItemText (dlg, kDlgItemTrcTargetText, "");
+
+ EmDlg::DisableItem (dlg, kDlgItemTrcTargetValue);
+ EmDlg::DisableItem (dlg, kDlgItemTrcTargetText);
+
+ EmDlg::SetItemValue (dlg, kDlgItemTrcAutoConnect, 0);
+ EmDlg::DisableItem (dlg, kDlgItemTrcAutoConnect);
+ }
+ else
+ {
+ TracerTypeInfo* info = gTracer.GetTracerTypeInfo (data.fTracerType);
+
+ EmDlg::SetItemText (dlg, kDlgItemTrcTargetValue, info->paramTmpVal);
+ EmDlg::SetItemText (dlg, kDlgItemTrcTargetText, info->paramDescr);
+
+ EmDlg::EnableItem (dlg, kDlgItemTrcTargetValue);
+ EmDlg::EnableItem (dlg, kDlgItemTrcTargetText);
+
+ if (info->autoConnectSupport)
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemTrcAutoConnect, info->autoConnectTmpState);
+ EmDlg::EnableItem (dlg, kDlgItemTrcAutoConnect);
+ }
+ else
+ {
+ EmDlg::SetItemValue (dlg, kDlgItemTrcAutoConnect, 0);
+ EmDlg::DisableItem (dlg, kDlgItemTrcAutoConnect);
+ }
+ }
+}
+
+
+EmDlgFnResult EmDlg::PrvEditTracingOptions (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditTracingOptionsData& data = *(EditTracingOptionsData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Copy prefs states to internal states
+
+ unsigned short ii;
+
+ for (ii = 1; ii <= gTracer.GetTracerTypeCount (); ++ii)
+ {
+ TracerTypeInfo* info = gTracer.GetTracerTypeInfo (ii);
+ EmAssert(info);
+
+ strcpy (info->paramTmpVal, info->paramCurVal);
+ info->autoConnectTmpState = info->autoConnectCurState;
+ }
+
+ // Get the currently selected tracer type.
+
+ data.fTracerType = gTracer.GetCurrentTracerTypeIndex ();
+
+ // Build up the menu of tracer types and select the current one.
+
+ EmDlg::AppendToMenu (dlg, kDlgItemTrcOutput, "None (discards traces)");
+
+ for (ii = 1; ii <= gTracer.GetTracerTypeCount (); ++ii)
+ {
+ TracerTypeInfo* info = gTracer.GetTracerTypeInfo (ii);
+ EmAssert (info);
+
+ EmDlg::AppendToMenu (dlg, kDlgItemTrcOutput, info->friendlyName);
+ }
+
+ EmDlg::SetItemValue (dlg, kDlgItemTrcOutput, data.fTracerType);
+
+ // Install settings for this tracer type.
+
+ EmDlg::PrvPushTracerSettings (context);
+
+ // Show the version information.
+
+ char version[100];
+ gTracer.GetLibraryVersionString(version, 100);
+ EmDlg::SetItemText (dlg, kDlgItemTrcInfo, version);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ Bool parameterValueChanged = false;
+
+ // If the user made a selection...
+
+ if (data.fTracerType)
+ {
+ // Commit the current settings for the current tracer type.
+
+ EmDlg::PrvPopTracerSettings (context);
+
+ // Get the pointer to the current tracer info.
+
+ TracerTypeInfo* info = gTracer.GetTracerTypeInfo (data.fTracerType);
+ EmAssert (info);
+
+ // If the tracer data changed, make it permanent.
+
+ if (strcmp (info->paramCurVal, info->paramTmpVal) != 0)
+ {
+ parameterValueChanged = true;
+ strcpy (info->paramCurVal, info->paramTmpVal);
+ }
+
+ info->autoConnectCurState = info->autoConnectTmpState;
+ }
+
+ // Make the selected tracer the current one.
+
+ gTracer.SetCurrentTracerTypeIndex (data.fTracerType, parameterValueChanged);
+
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemTrcOutput:
+ {
+ // Save the current settings for the old tracer type.
+ EmDlg::PrvPopTracerSettings (context);
+
+ // Get the new tracer type.
+ data.fTracerType = EmDlg::GetItemValue (dlg, kDlgItemTrcOutput);
+
+ // Install the settings for the new tracer type.
+ EmDlg::PrvPushTracerSettings (context);
+
+ break;
+ }
+
+ case kDlgItemTrcTargetText:
+ case kDlgItemTrcTargetValue:
+ case kDlgItemTrcInfo:
+ {
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoEditTracingOptions (void)
+{
+ EditTracingOptionsData data;
+
+ return EmDlg::RunDialog (EmDlg::PrvEditTracingOptions, &data, kDlgEditTracingOptions);
+}
+#endif
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoCommonDialog
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+struct EditCommonDialogData
+{
+ const char* fMessage;
+ EmCommonDialogFlags fFlags;
+ uint32 fFirstBeepTime;
+ uint32 fLastBeepTime;
+};
+
+
+struct ButtonState
+{
+ ButtonState (void) :
+ fTextID (0),
+ fDefault (false),
+ fCancel (false),
+ fEnabled (false)
+ {
+ }
+
+ ButtonState (StrCode textID, Bool def, Bool cancel, Bool enabled) :
+ fTextID (textID),
+ fDefault (def),
+ fCancel (cancel),
+ fEnabled (enabled)
+ {
+ }
+
+ StrCode fTextID;
+ Bool fDefault;
+ Bool fCancel;
+ Bool fEnabled;
+};
+
+
+EmDlgFnResult EmDlg::PrvCommonDialog (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ EditCommonDialogData& data = *(EditCommonDialogData*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ // Get the right icon. They all start out as invisible, so
+ // show the right one.
+
+ EmDlgItemID iconID = kDlgItemCmnIconCaution;
+
+#if 0
+#pragma message ("Fix me")
+ {
+ switch (data.fFlags & kAlertMask)
+ {
+ case kNoteAlert: iconID = kDlgItemCmnIconNote; break;
+ case kCautionAlert: iconID = kDlgItemCmnIconCaution; break;
+ case kErrorAlert: iconID = kDlgItemCmnIconStop; break;
+ }
+ }
+#endif
+
+ EmDlg::ShowItem (dlg, iconID);
+
+ // Sort out the button situation.
+
+ // Determine what the buttons should say and how they should look.
+
+ ButtonState buttons[3];
+ {
+ for (int ii = 0, buttonIndex = 0; ii < 3; ++ii)
+ {
+ int flags = GET_BUTTON (ii, data.fFlags);
+ if (flags & kButtonVisible)
+ {
+ StrCode kStringCodes[] =
+ {
+ 0,
+ kStr_OK,
+ kStr_Cancel,
+ kStr_Yes,
+ kStr_No,
+ kStr_Continue,
+ kStr_Debug,
+ kStr_Reset,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ ButtonState newButton (
+ kStringCodes[flags & kButtonMask],
+ (flags & kButtonDefault) != 0,
+ (flags & kButtonEscape) != 0,
+ (flags & kButtonEnabled) != 0);
+
+ buttons[buttonIndex] = newButton;
+
+ ++buttonIndex;
+ }
+ }
+ }
+
+ // Make the UI elements match what we determined above.
+
+ for (int ii = 0; ii < 3; ++ii)
+ {
+ EmDlgItemID itemID = (EmDlgItemID) (kDlgItemCmnButton1 + ii);
+
+ if (buttons[ii].fTextID)
+ {
+ // The button is visible. Set its text and enable/disable it.
+
+ EmDlg::SetItemText (dlg, itemID, buttons[ii].fTextID);
+ EmDlg::EnableDisableItem (dlg, itemID, buttons[ii].fEnabled);
+
+ if (buttons[ii].fDefault)
+ {
+ EmDlg::SetDlgDefaultButton (context, itemID);
+ }
+
+ if (buttons[ii].fCancel)
+ {
+ EmDlg::SetDlgCancelButton (context, itemID);
+ }
+ }
+ else
+ {
+ // The button is invisible. Hide it, and move the others over.
+
+ EmDlg::HideItem (dlg, itemID);
+ }
+ }
+
+ // Measure the text, resize the box it goes into, and set the text.
+
+ EmRect r = EmDlg::GetItemBounds (dlg, kDlgItemCmnText);
+ int height = EmDlg::GetTextHeight (dlg, kDlgItemCmnText, data.fMessage);
+ int delta = height - r.Height ();
+
+ if (delta > 0)
+ {
+#if PLATFORM_WINDOWS
+ // With PowerPlant and FLTK, resizing the window will resize
+ // and move around the elements for us.
+
+ r.fBottom += delta;
+ EmDlg::SetItemBounds (dlg, kDlgItemCmnText, r);
+#endif
+
+ r = EmDlg::GetDlgBounds (dlg);
+ r.fBottom += delta;
+ EmDlg::SetDlgBounds (dlg, r);
+ }
+
+ EmDlg::SetItemText (dlg, kDlgItemCmnText, data.fMessage);
+
+ // Set us up to idle so that we can beep.
+
+ Preference<Bool> pref (kPrefKeyDialogBeep);
+
+ if (*pref)
+ {
+ context.fNeedsIdle = true;
+ data.fFirstBeepTime = data.fLastBeepTime = Platform::GetMilliseconds ();
+ }
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ const uint32 kBeepTimeout = 60 * 1024L; // 60 seconds
+ const uint32 kBeepInterval = 2 * 1024L; // 2 seconds
+ uint32 curTime = Platform::GetMilliseconds ();
+ uint32 delta1 = curTime - data.fFirstBeepTime;
+ uint32 delta2 = curTime - data.fLastBeepTime;
+
+ if (delta1 < kBeepTimeout && delta2 > kBeepInterval)
+ {
+ data.fLastBeepTime = curTime;
+ Platform::Beep ();
+ }
+
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemCmnButton1:
+ case kDlgItemCmnButton2:
+ case kDlgItemCmnButton3:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemCmnButtonCopy:
+ {
+ string text = EmDlg::GetItemText (context.fDlg, kDlgItemCmnText);
+ ByteList hostChars;
+ ByteList palmChars;
+
+ copy (text.begin (), text.end (), back_inserter (hostChars));
+
+ Platform::CopyToClipboard (palmChars, hostChars);
+ break;
+ }
+
+ case kDlgItemCmnText:
+ case kDlgItemCmnIconStop:
+ case kDlgItemCmnIconCaution:
+ case kDlgItemCmnIconNote:
+ break;
+
+ case kDlgItemOK:
+ EmAssert (false);
+ break;
+
+ case kDlgItemCancel:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoCommonDialog (StrCode msg,
+ EmCommonDialogFlags flags)
+{
+ string str (Platform::GetString (msg));
+ return EmDlg::DoCommonDialog (str, flags);
+}
+
+
+EmDlgItemID EmDlg::DoCommonDialog (const char* msg,
+ EmCommonDialogFlags flags)
+{
+ EditCommonDialogData data;
+
+ data.fMessage = msg;
+ data.fFlags = flags;
+
+ EmDlgItemID result;
+ EmDlgItemID button = EmDlg::RunDialog (EmDlg::PrvCommonDialog, &data, kDlgCommonDialog);
+
+ switch (button)
+ {
+ case kDlgItemCmnButton1:
+ result = (EmDlgItemID) (GET_BUTTON (0, flags) & kButtonMask);
+ break;
+
+ case kDlgItemCmnButton2:
+ result = (EmDlgItemID) (GET_BUTTON (1, flags) & kButtonMask);
+ break;
+
+ case kDlgItemCmnButton3:
+ result = (EmDlgItemID) (GET_BUTTON (2, flags) & kButtonMask);
+ break;
+
+ default:
+ EmAssert (false);
+ result = (EmDlgItemID) 0; // prevent compiler warnings.
+ }
+
+ return result;
+}
+
+
+EmDlgItemID EmDlg::DoCommonDialog (const string& msg,
+ EmCommonDialogFlags flags)
+{
+ return EmDlg::DoCommonDialog (msg.c_str (), flags);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoSaveBound
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvSaveBound (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::DisableItem (dlg, kDlgItemOK);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ Bool fullSave = EmDlg::GetItemValue (dlg, kDlgItemBndSaveRAM) != 0;
+ EmFileRef destFile;
+ EmFileTypeList filterList (1, kFileTypeApplication);
+
+#if PLATFORM_MAC
+ string newName ("Emulator_Bound");
+#elif PLATFORM_UNIX
+ string newName ("pose_bound");
+#elif PLATFORM_WINDOWS
+ string newName ("Emulator_Bound.exe");
+#else
+#error "Unsupported platform"
+#endif
+
+ if (EmDlg::DoPutFile (destFile, "Save new emulator",
+ EmDirRef::GetEmulatorDirectory (), filterList, newName) == kDlgItemOK)
+ {
+ EmAssert (gApplication);
+ gApplication->BindPoser (fullSave, destFile);
+ }
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemBndSaveROM:
+ case kDlgItemBndSaveRAM:
+ EmDlg::EnableItem (dlg, kDlgItemOK);
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoSaveBound (void)
+{
+ return EmDlg::RunDialog (EmDlg::PrvSaveBound, NULL, kDlgSaveBound);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::SessionInfo
+ *
+ * DESCRIPTION: Called when the Session Info menu item is selected.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvSessionInfo (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ Preference<Configuration> pref1 (kPrefKeyLastConfiguration);
+ Preference<EmFileRef> pref2 (kPrefKeyLastPSF);
+
+ Configuration cfg = *pref1;
+ EmDevice device = cfg.fDevice;
+ string deviceStr = device.GetMenuString ();
+ RAMSizeType ramSize = cfg.fRAMSize;
+ EmFileRef romFile = cfg.fROMFile;
+ string romFileStr = romFile.GetFullPath ();
+ EmFileRef sessionRef = *pref2;
+ string sessionPath = sessionRef.GetFullPath ();
+
+ if (sessionPath.empty ())
+ sessionPath = "<Not selected>";
+
+ EmDlg::SetItemText (dlg, kDlgItemInfDeviceFld, deviceStr);
+ EmDlg::SetItemValue (dlg, kDlgItemInfRAMFld, ramSize);
+ EmDlg::SetItemText (dlg, kDlgItemInfROMFld, romFileStr);
+ EmDlg::SetItemText (dlg, kDlgItemInfSessionFld, sessionPath);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ case kDlgItemCancel:
+ return kDlgResultClose;
+
+ case kDlgItemInfDeviceFld:
+ case kDlgItemInfRAMFld:
+ case kDlgItemInfROMFld:
+ case kDlgItemInfSessionFld:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoSessionInfo (void)
+{
+ return EmDlg::RunDialog (EmDlg::PrvSessionInfo, NULL, kDlgSessionInfo);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: DoGetSocketAddress
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlg::PrvGetSocketAddress (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ EmDlg::SetItemText (dlg, kDlgItemSocketAddress, *(string*) context.fUserData);
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ *(string*) context.fUserData = EmDlg::GetItemText (dlg, kDlgItemSocketAddress);
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemSocketAddress:
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+EmDlgItemID EmDlg::DoGetSocketAddress (string& addr)
+{
+ return EmDlg::RunDialog (EmDlg::PrvGetSocketAddress, &addr, kDlgGetSocketAddress);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: GremlinControl
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgRef gGremlinControl;
+
+// Update the message "Gremlin #%gremlin_number".
+
+void EmDlg::PrvGrmUpdateGremlinNumber (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ int32 number = Hordes::GremlinNumber ();
+ string numberStr = ::FormatInteger (number);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%gremlin_number", numberStr);
+
+ string text = Errors::ReplaceParameters (kStr_GremlinNumber);
+ EmDlg::SetItemText (dlg, kDlgItemGrmNumber, text);
+}
+
+
+// Update the message "Event %current_event of %last_event" or
+// "Event %current_event".
+
+void EmDlg::PrvGrmUpdateEventNumber (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ // Update the "Event #: xxx of yyy" message.
+
+ int32 counter = Hordes::EventCounter ();
+ int32 limit = Hordes::EventLimit ();
+
+ string counterStr = ::FormatInteger (counter);
+ string limitStr = ::FormatInteger (limit);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%current_event", counterStr);
+ Errors::SetParameter ("%last_event", limitStr);
+
+ // If there is a max event number (indicated by a non -1 value
+ // for Hordes::EventLimit), display a string including that
+ // value. Otherwise, the number of events to post is unlimited.
+ // In that case, we just show the current event number.
+
+ string text = Errors::ReplaceParameters (
+ limit > 0
+ ? kStr_GremlinXofYEvents
+ : kStr_GremlinXEvents);
+ EmDlg::SetItemText (dlg, kDlgItemGrmEventNumber, text);
+}
+
+
+// Update the message "Elapsed Time: %elapsed_time"
+
+void EmDlg::PrvGrmUpdateElapsedTime (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 elapsed = Hordes::ElapsedMilliseconds ();
+ string elapsedStr = ::FormatElapsedTime (elapsed);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%elapsed_time", elapsedStr);
+
+ string text = Errors::ReplaceParameters (kStr_GremlinElapsedTime);
+ EmDlg::SetItemText (dlg, kDlgItemGrmElapsedTime, text);
+}
+
+
+void EmDlg::PrvGrmUpdateAll (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ EmDlg::PrvGrmUpdateGremlinNumber (context);
+ EmDlg::PrvGrmUpdateEventNumber (context);
+ EmDlg::PrvGrmUpdateElapsedTime (context);
+
+ // Update the buttons.
+
+ EmDlg::EnableDisableItem (dlg, kDlgItemGrmStop, Hordes::CanStop ());
+ EmDlg::EnableDisableItem (dlg, kDlgItemGrmResume, Hordes::CanResume ());
+ EmDlg::EnableDisableItem (dlg, kDlgItemGrmStep, Hordes::CanStep ());
+}
+
+
+EmDlgFnResult EmDlg::PrvGremlinControl (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ Preference<PointType> pref (kPrefKeyGCWLocation);
+
+ if (pref.Loaded ())
+ {
+ EmDlg::MoveDlgTo (dlg, pref->x, pref->y);
+ EmDlg::EnsureDlgOnscreen (dlg);
+ }
+ else
+ {
+ EmDlg::CenterDlg (dlg);
+ }
+
+ // Set a timer so that we can periodically update the displayed values.
+
+ context.fNeedsIdle = true;
+
+ // Set the initial contents of the dialog.
+
+ EmDlg::PrvGrmUpdateAll (context);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ static UInt32 lastIdle = 0;
+
+ UInt32 curIdle = Platform::GetMilliseconds ();
+
+ if (curIdle - lastIdle > 500)
+ {
+ lastIdle = curIdle;
+
+ EmDlg::PrvGrmUpdateAll (context);
+ }
+
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ case kDlgItemGrmStop:
+ {
+ EmSessionStopper stopper (gSession, kStopNow);
+ if (stopper.Stopped())
+ {
+ Hordes::Stop ();
+ }
+ break;
+ }
+
+ case kDlgItemGrmResume:
+ {
+ // Resuming attempts to make Palm OS calls (for instance,
+ // to reset the pen calibration), so make sure we're stopped
+ // at a good place.
+
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped())
+ {
+ Hordes::Resume ();
+ }
+ break;
+ }
+
+ case kDlgItemGrmStep:
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped())
+ {
+ Hordes::Step ();
+ }
+ break;
+ }
+
+ case kDlgItemGrmNumber:
+ case kDlgItemGrmEventNumber:
+ case kDlgItemGrmElapsedTime:
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ {
+ EmRect bounds = EmDlg::GetDlgBounds (dlg);
+
+ Preference<EmPoint> pref (kPrefKeyGCWLocation);
+ pref = bounds.TopLeft ();
+
+ gGremlinControl = NULL;
+
+ break; // Return value is ignored for destroy
+ }
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+void EmDlg::GremlinControlOpen (void)
+{
+ if (!gGremlinControl)
+ {
+ gGremlinControl = EmDlg::DialogOpen (EmDlg::PrvGremlinControl, NULL, kDlgGremlinControl);
+ }
+ else
+ {
+ // !!! Bring to front
+ }
+}
+
+
+void EmDlg::GremlinControlClose (void)
+{
+ if (gGremlinControl)
+ {
+ EmDlg::DialogClose (gGremlinControl);
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: MinimizeControl
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgRef gMinimizeProgress;
+
+
+// Update the message "Pass #%pass_number".
+
+void EmDlg::PrvMinUpdatePassNumber (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 pass = EmMinimize::GetPassNumber ();
+ string passStr = ::FormatInteger (pass);
+
+ if (pass == 0)
+ {
+ passStr = "LAST";
+ }
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%pass_number", passStr);
+
+ string text = Errors::ReplaceParameters (kStr_MinimizePassNumber);
+ EmDlg::SetItemText (dlg, kDlgItemMinPassNumber, text);
+}
+
+
+// Update the message "Event %current_event of %last_event".
+//
+// "last_event" is the last event number of the current pass.
+// "current_event" is between one and that number, inclusive.
+
+void EmDlg::PrvMinUpdateEventNumber (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 current = EmEventPlayback::GetCurrentEvent ();
+ string currentStr = ::FormatInteger (current);
+
+ uint32 total = EmEventPlayback::GetNumEvents ();
+ string totalStr = ::FormatInteger (total);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%current_event", currentStr);
+ Errors::SetParameter ("%last_event", totalStr);
+
+ string text = Errors::ReplaceParameters (kStr_MinimizeXofYEvents);
+ EmDlg::SetItemText (dlg, kDlgItemMinEventNumber, text);
+}
+
+
+// Update the message "Elapsed Time: %elapsed_time".
+
+void EmDlg::PrvMinUpdateElapsed (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 elapsed = EmMinimize::GetElapsedTime ();
+ string elapsedStr = ::FormatElapsedTime (elapsed);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%elapsed_time", elapsedStr);
+
+ string text = Errors::ReplaceParameters (kStr_MinimizeElapsedTime);
+ EmDlg::SetItemText (dlg, kDlgItemMinElapsed, text);
+}
+
+
+// Update the message "Excluding range %first_event to %last_event".
+//
+// When formatting the last event number, subtract one to hide the
+// fact that we work on a half-open interval. Then add one to both
+// the begin and end to convert a 0-based range to a 1-based range
+// (so that the first event is reported as 1 instead of zero).
+
+void EmDlg::PrvMinUpdateRange (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 begin, end;
+ EmMinimize::GetCurrentRange (begin, end);
+
+ string beginStr = ::FormatInteger (begin + 1);
+ string endStr = ::FormatInteger (end);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%first_event", beginStr);
+ Errors::SetParameter ("%last_event", endStr);
+
+ string text = Errors::ReplaceParameters (kStr_MinimizeRange);
+ EmDlg::SetItemText (dlg, kDlgItemMinRange, text);
+}
+
+
+// Update the message "Discarded %num_discarded_events of %num_total_events events".
+//
+// "num_total_events" is the initial number of events at pass 1.
+// "num_discarded_events" is between zero and that number.
+
+void EmDlg::PrvMinUpdateDiscarded (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 discarded = EmMinimize::GetNumDiscardedEvents ();
+ string discardedStr = ::FormatInteger (discarded);
+
+ uint32 total = EmMinimize::GetNumInitialEvents ();
+ string totalStr = ::FormatInteger (total);
+
+ Errors::ClearAllParameters ();
+ Errors::SetParameter ("%num_discarded_events", discardedStr);
+ Errors::SetParameter ("%num_total_events", totalStr);
+
+ string text = Errors::ReplaceParameters (kStr_MinimizeDiscarded);
+ EmDlg::SetItemText (dlg, kDlgItemMinDiscarded, text);
+}
+
+
+// Update the progress bar.
+//
+// Max value of the progress bar is the current maximum event for this pass.
+// Current value of the bar is the lower end of the range we are currently
+// examining for exclusion. Given the way we walk through the ranges of
+// events to exclude, this will give a jerky yet increasing progress bar.
+
+void EmDlg::PrvMinUpdateProgress (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ uint32 begin, end;
+ EmMinimize::GetCurrentRange (begin, end);
+
+ uint32 total = EmEventPlayback::GetNumEvents ();
+
+ // Make sure "total" is less than 32K (that's the most that the standard
+ // Win32 progress bar can handle).
+
+ int divider = (total / 32768) + 1;
+
+ total /= divider;
+ begin /= divider;
+ end /= divider;
+
+ EmDlg::SetItemMax (dlg, kDlgItemMinProgress, total);
+ EmDlg::SetItemValue (dlg, kDlgItemMinProgress, begin);
+}
+
+
+// Update all elements of the dialog box.
+
+void EmDlg::PrvMinUpdateAll (EmDlgContext& context)
+{
+ EmDlg::PrvMinUpdatePassNumber (context);
+ EmDlg::PrvMinUpdateEventNumber (context);
+ EmDlg::PrvMinUpdateElapsed (context);
+ EmDlg::PrvMinUpdateRange (context);
+ EmDlg::PrvMinUpdateDiscarded (context);
+ EmDlg::PrvMinUpdateProgress (context);
+}
+
+
+EmDlgFnResult EmDlg::PrvMinimizeProgress (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ Preference<PointType> pref (kPrefKeyMPWLocation);
+
+ if (pref.Loaded ())
+ {
+ EmDlg::MoveDlgTo (dlg, pref->x, pref->y);
+ EmDlg::EnsureDlgOnscreen (dlg);
+ }
+ else
+ {
+ EmDlg::CenterDlg (dlg);
+ }
+
+ // Set a timer so that we can periodically update the displayed values.
+
+ context.fNeedsIdle = true;
+
+ // Set the initial contents of the dialog.
+
+ EmDlg::PrvMinUpdateAll (context);
+
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ if (!EmMinimize::IsOn ())
+ {
+ return kDlgResultClose;
+ }
+
+ static UInt32 lastIdle = 0;
+
+ UInt32 curIdle = Platform::GetMilliseconds ();
+
+ if (curIdle - lastIdle > 500)
+ {
+ lastIdle = curIdle;
+
+ EmDlg::PrvMinUpdateAll (context);
+ }
+
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemCancel:
+ {
+ EmMinimize::Stop ();
+ return kDlgResultClose;
+ }
+
+ case kDlgItemMinRange:
+ case kDlgItemMinElapsed:
+ case kDlgItemMinDiscarded:
+ case kDlgItemMinProgress:
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ {
+ EmRect bounds = EmDlg::GetDlgBounds (dlg);
+
+ Preference<EmPoint> pref (kPrefKeyMPWLocation);
+ pref = bounds.TopLeft ();
+
+ gMinimizeProgress = NULL;
+
+ break; // Return value is ignored for destroy
+ }
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+
+
+void EmDlg::MinimizeProgressOpen (void)
+{
+ if (!gMinimizeProgress)
+ {
+ gMinimizeProgress = EmDlg::DialogOpen (EmDlg::PrvMinimizeProgress, NULL, kDlgMinimizeProgress);
+ }
+ else
+ {
+ // !!! Bring to front
+ }
+}
+
+
+void EmDlg::MinimizeProgressClose (void)
+{
+ if (gMinimizeProgress)
+ {
+ EmDlg::DialogClose (gMinimizeProgress);
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: RunDialog
+ *
+ * DESCRIPTION: Common routine that all dialog clients go through.
+ * This function checks to see if we are in the UI thread
+ * or not. If not, it forwards the call to the session
+ * so that it can block and wait for the UI thread to
+ * pick up and handle the call. If we are already in the
+ * UI thread, then call the Host routine that displays
+ * and drives the dialog.
+ *
+ * PARAMETERS: fn - the custom dialog handler
+ * userData - custom data passed back to the dialog handler.
+ * dlgID - ID of dialog to create.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::RunDialog (EmDlgFn fn, void* userData, EmDlgID dlgID)
+{
+ RunDialogParameters parameters (fn, userData, dlgID);
+ return EmDlg::RunDialog (EmDlg::HostRunDialog, &parameters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RunDialog
+ *
+ * DESCRIPTION: Common routine that all dialog clients go through.
+ * This function checks to see if we are in the UI thread
+ * or not. If not, it forwards the call to the session
+ * so that it can block and wait for the UI thread to
+ * pick up and handle the call. If we are already in the
+ * UI thread, then call the Host routine that displays
+ * and drives the dialog.
+ *
+ * PARAMETERS: fn - the custom dialog handler
+ * userData - custom data passed back to the dialog handler.
+ * dlgID - ID of dialog to create.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::RunDialog (EmDlgThreadFn fn, const void* parameters)
+{
+#if HAS_OMNI_THREAD
+ if (gSession && gSession->InCPUThread ())
+ {
+ return gSession->BlockOnDialog (fn, parameters);
+ }
+#else
+ if (gSession && gSession->GetSessionState () == kRunning)
+ {
+ return gSession->BlockOnDialog (fn, parameters);
+ }
+#endif
+
+ return fn (parameters);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DialogOpen
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: fn - the custom dialog handler
+ * userData - custom data passed back to the dialog handler.
+ * dlgID - ID of dialog to create.
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+EmDlgRef EmDlg::DialogOpen (EmDlgFn fn, void* data, EmDlgID dlgID)
+{
+ return EmDlg::HostDialogOpen (fn, data, dlgID);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DialogClose
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void EmDlg::DialogClose (EmDlgRef dlg)
+{
+ EmDlg::HostDialogClose (dlg);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::MoveDlgTo
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::MoveDlgTo (EmDlgRef dlg, EmCoord x, EmCoord y)
+{
+ EmDlg::MoveDlgTo (dlg, EmPoint (x, y));
+}
+
+
+void EmDlg::MoveDlgTo (EmDlgRef dlg, const EmPoint& pt)
+{
+ EmRect bounds = EmDlg::GetDlgBounds (dlg);
+ bounds += (pt - bounds.TopLeft ());
+ EmDlg::SetDlgBounds (dlg, bounds);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::EnsureDlgOnscreen
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::EnsureDlgOnscreen (EmDlgRef dlg)
+{
+ EmRect bounds = EmDlg::GetDlgBounds (dlg);
+
+ if (Platform::PinToScreen (bounds))
+ {
+ EmDlg::SetDlgBounds (dlg, bounds);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemText
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemText (EmDlgRef dlg, EmDlgItemID item, StrCode strCode)
+{
+ string str = Platform::GetString (strCode);
+ EmDlg::SetItemText (dlg, item, str);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemText
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemText (EmDlgRef dlg, EmDlgItemID item, const char* str)
+{
+ EmDlg::SetItemText (dlg, item, string (str));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::EnableDisableItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::EnableDisableItem (EmDlgRef dlg, EmDlgItemID item, Bool enable)
+{
+ if (enable)
+ EmDlg::EnableItem (dlg, item);
+ else
+ EmDlg::DisableItem (dlg, item);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::ShowHideItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::ShowHideItem (EmDlgRef dlg, EmDlgItemID item, Bool show)
+{
+ if (show)
+ EmDlg::ShowItem (dlg, item);
+ else
+ EmDlg::HideItem (dlg, item);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::AppendToMenu
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::AppendToMenu (EmDlgRef dlg, EmDlgItemID item, const string& text)
+{
+ StringList strList;
+ strList.push_back (text);
+
+ EmDlg::AppendToMenu (dlg, item, strList);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::AppendToList
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::AppendToList (EmDlgRef dlg, EmDlgItemID item, const string& text)
+{
+ StringList strList;
+ strList.push_back (text);
+
+ EmDlg::AppendToList (dlg, item, strList);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SelectListItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SelectListItem (EmDlgRef dlg, EmDlgItemID item, EmDlgListIndex listItem)
+{
+ EmDlgListIndexList itemList;
+ itemList.push_back (listItem);
+
+ EmDlg::SelectListItems (dlg, item, itemList);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::UnselectListItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::UnselectListItem (EmDlgRef dlg, EmDlgItemID item, EmDlgListIndex listItem)
+{
+ EmDlgListIndexList itemList;
+ itemList.push_back (listItem);
+
+ EmDlg::UnselectListItems (dlg, item, itemList);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetSelectedItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgListIndex EmDlg::GetSelectedItem (EmDlgRef dlg, EmDlgItemID item)
+{
+ EmDlgListIndexList itemList;
+ EmDlg::GetSelectedItems (dlg, item, itemList);
+
+ if (itemList.size () > 0)
+ {
+ return itemList[0];
+ }
+
+ return kDlgItemListNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::StringToLong
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmDlg::StringToLong (const char* s, long* num)
+{
+ if (sscanf(s, "%li", num) == 1)
+ return true;
+
+ return false;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgContext::EmDlgContext (void) :
+ fFn (NULL),
+ fFnResult (kDlgResultNone),
+ fDlg (NULL),
+ fDlgID (kDlgNone),
+ fPanelID (kDlgPanelNone),
+ fItemID (kDlgItemNone),
+ fCommandID (kDlgCmdNone),
+ fNeedsIdle (false),
+ fUserData (NULL),
+ fDefaultItem (kDlgItemNone),
+ fCancelItem (kDlgItemNone)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgContext::EmDlgContext (const EmDlgContext& other) :
+ fFn (other.fFn),
+ fFnResult (other.fFnResult),
+ fDlg (other.fDlg),
+ fDlgID (other.fDlgID),
+ fPanelID (other.fPanelID),
+ fItemID (other.fItemID),
+ fCommandID (other.fCommandID),
+ fNeedsIdle (other.fNeedsIdle),
+ fUserData (other.fUserData),
+ fDefaultItem (other.fDefaultItem),
+ fCancelItem (other.fCancelItem)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::Init
+ *
+ * DESCRIPTION: Call the custom dialog handler to initialize the dialog.
+ * If the dialog says that it wants idle time, then start
+ * idleing it.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The result returned by the dialog handler.
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlgContext::Init (void)
+{
+ fFnResult = kDlgResultNone;
+
+ if (fFn)
+ {
+ fItemID = kDlgItemNone;
+ fCommandID = kDlgCmdInit;
+
+ fFnResult = fFn (*this);
+
+ if (fNeedsIdle)
+ EmDlg::HostStartIdling (*this);
+ }
+
+ return fFnResult;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::Idle
+ *
+ * DESCRIPTION: Call the custom dialog handler to idle.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The result returned by the dialog handler.
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlgContext::Idle (void)
+{
+ fFnResult = kDlgResultNone;
+
+ if (fFn)
+ {
+ fItemID = kDlgItemNone;
+ fCommandID = kDlgCmdIdle;
+
+ fFnResult = fFn (*this);
+ }
+
+ return fFnResult;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::Event
+ *
+ * DESCRIPTION: Call the custom dialog handler to handle an event.
+ *
+ * PARAMETERS: item - dialog item that was selected.
+ *
+ * RETURNED: The result returned by the dialog handler.
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlgContext::Event (EmDlgItemID itemID)
+{
+ fFnResult = kDlgResultNone;
+
+ if (fFn)
+ {
+ fItemID = itemID;
+ fCommandID = kDlgCmdItemSelected;
+
+ fFnResult = fFn (*this);
+ }
+
+ return fFnResult;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::Destroy
+ *
+ * DESCRIPTION: Call the custom dialog handler to tell it that the
+ * dialog is being destroyed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmDlgContext::Destroy (void)
+{
+ if (fFn)
+ {
+ fItemID = kDlgItemNone;
+ fCommandID = kDlgCmdDestroy;
+
+ fFnResult = fFn (*this);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::PanelEnter
+ *
+ * DESCRIPTION: Call the custom dialog handler to idle.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The result returned by the dialog handler.
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlgContext::PanelEnter (void)
+{
+ fItemID = kDlgItemNone;
+ fCommandID = kDlgCmdPanelEnter;
+
+ fFnResult = fFn (*this);
+ return fFnResult;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlgContext::PanelExit
+ *
+ * DESCRIPTION: Call the custom dialog handler to idle.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The result returned by the dialog handler.
+ *
+ ***********************************************************************/
+
+EmDlgFnResult EmDlgContext::PanelExit (void)
+{
+ fItemID = kDlgItemNone;
+ fCommandID = kDlgCmdPanelExit;
+
+ fFnResult = fFn (*this);
+ return fFnResult;
+}
+
+
+#pragma mark -
+
+#if !PLATFORM_UNIX
+// Append one set of descriptors to another set, separating them if
+// necessary with an empty descriptor.
+
+static void PrvAppendDescriptors (EmTransportDescriptorList& menuItems,
+ const EmTransportDescriptorList& rawItems)
+{
+ // If there are items to be added and items already added,
+ // insert a divider first.
+
+ if (menuItems.size () > 0 && rawItems.size () > 0)
+ {
+ menuItems.push_back (EmTransportDescriptor ());
+ }
+
+ // Add the menu items to the menu.
+
+ std::copy (rawItems.begin (), rawItems.end (), back_inserter (menuItems));
+}
+
+
+// Append one descriptors to a set, separating it if
+// necessary with an empty descriptor.
+
+static void PrvAppendDescriptors (EmTransportDescriptorList& menuItems,
+ const string& rawItem)
+{
+ EmTransportDescriptorList rawItems;
+ rawItems.push_back (EmTransportDescriptor (rawItem));
+
+ ::PrvAppendDescriptors (rawItems, menuItems);
+}
+
+
+// Return the text that should be put into the menu item.
+
+static string PrvGetMenuItemText (EmDlgItemID whichMenu,
+ const EmTransportDescriptor& item,
+ const string& socketAddr)
+{
+ // Get the text to add to the menu.
+
+ string itemText = item.GetMenuName ();
+
+ // If this menu item is for a socket, see if we'd like to
+ // augment the text for it with socket/port info.
+
+ if (item.GetType () == kTransportSocket)
+ {
+ if (whichMenu == kDlgItemPrfRedirectSerial || whichMenu == kDlgItemPrfRedirectSerial)
+ {
+ // If the user has selected a socket for their serial or IR
+ // port, then add the socket address/port, as well as a "..."
+ // so that they can bring up a dialog allowing them to specify
+ // that information.
+
+ if (socketAddr.size () > 0)
+ {
+ itemText += " (" + socketAddr + ")";
+ }
+
+ itemText += "...";
+ }
+ }
+
+ return itemText;
+}
+
+
+// Append the given descriptors to the indicated menu. Empty descriptors
+// are turned into divider menu items. If the descriptor in "pref" is
+// found, then select that descriptor in the menu. Otherwise, select the
+// first item in the menu.
+
+static void PrvAppendMenuItems (EmDlgRef dlg, EmDlgItemID dlgItem,
+ const EmTransportDescriptorList& menuItems,
+ const EmTransportDescriptor& pref,
+ const string& socketAddr)
+{
+ Bool selected = false;
+
+ // Iterate over all the items in "menuItems".
+
+ EmTransportDescriptorList::const_iterator iter = menuItems.begin ();
+ while (iter != menuItems.end ())
+ {
+ // If this is descriptor is of a known type, add it to the menu as an item.
+
+ if (iter->GetType () != kTransportUnknown)
+ {
+ // Add the menu item to the menu.
+
+ string itemText = ::PrvGetMenuItemText (dlgItem, *iter, socketAddr);
+ EmDlg::AppendToMenu (dlg, dlgItem, itemText);
+
+ // If this is the item the user has selected, then select it
+ // in the menu.
+
+ if (iter->GetType () == kTransportSocket)
+ {
+ if (pref.GetType () == kTransportSocket)
+ {
+ EmDlg::SetItemValue (dlg, dlgItem, iter - menuItems.begin ());
+ selected = true;
+ }
+ }
+ else if (*iter == pref)
+ {
+ EmDlg::SetItemValue (dlg, dlgItem, iter - menuItems.begin ());
+ selected = true;
+ }
+ }
+
+ // If this descriptor is not of a known type, add it as a menu divider.
+
+ else
+ {
+ EmDlg::AppendToMenu (dlg, dlgItem, "");
+ }
+
+ ++iter;
+ }
+
+ // If we couldn't find a menu item to select,
+ // pick a default.
+
+ if (!selected)
+ {
+ EmDlg::SetItemValue (dlg, dlgItem, 0);
+ }
+}
+#endif // !PLATFORM_UNIX
+
+
+#pragma mark -
+
+#if 0
+ // Template for callback function
+
+EmDlgFnResult EmDlg::PrvCallback (EmDlgContext& context)
+{
+ EmDlgRef dlg = context.fDlg;
+ <type>& data = *(<type>*) context.fUserData;
+
+ switch (context.fCommandID)
+ {
+ case kDlgCmdInit:
+ {
+ break;
+ }
+
+ case kDlgCmdIdle:
+ {
+ break;
+ }
+
+ case kDlgCmdItemSelected:
+ {
+ switch (context.fItemID)
+ {
+ case kDlgItemOK:
+ {
+ // Fall thru...
+ }
+
+ case kDlgItemCancel:
+ {
+ return kDlgResultClose;
+ }
+
+ default:
+ EmAssert (false);
+ }
+
+ break;
+ }
+
+ case kDlgCmdDestroy:
+ break;
+
+ case kDlgCmdPanelEnter:
+ case kDlgCmdPanelExit:
+ case kDlgCmdNone:
+ EmAssert (false);
+ break;
+ }
+
+ return kDlgResultContinue;
+}
+#endif
diff --git a/SrcShared/EmDlg.h b/SrcShared/EmDlg.h
new file mode 100644
index 0000000..685a3f5
--- /dev/null
+++ b/SrcShared/EmDlg.h
@@ -0,0 +1,922 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDlg_h
+#define EmDlg_h
+
+#include "EmFileImport.h" // EmFileImportMethod
+#include "EmFileRef.h" // EmFileRefList
+#include "EmTransport.h" // EmTransport
+#include "EmTransportSerial.h" // EmTransportSerial::BaudList
+#include "EmTypes.h" // EmResetType
+#include "EmStructs.h" // DatabaseInfoList
+#include "Logging.h" // FOR_EACH_LOG_PREF, FOR_EACH_REPORT_PREF
+
+/*
+ EmDlg fulfills two purposes:
+
+ * Provides a "repository" for all dialogs the emulator shows.
+ Each dialog is invoked by calling an EmDlg entry point. This
+ entry point takes an optional set of parameters, shows and
+ handles all interaction with the dialog, and returns the
+ EmDlgItemID of the dialog item used to close the dialog (e.g.,
+ OK, Cancel, etc.).
+
+ * Provides a cross-platform interface for manipulating dialogs
+ and their items.
+
+ For the most part, clients of EmDlg use it to open and handle dialogs,
+ and EmDlg itself uses the cross-platform part in order to update
+ text, item states, etc., of the dialog.
+
+ To add a new dialog:
+
+ * Define a new EmDlgID. New ids should be added to the end of
+ the current list of IDs. They should not be renumbered.
+ Dialogs on some platforms (in particular, the Mac) are dependant
+ on the numbers assigned to the EmDlgIDs, so don't renumber them
+ without also renumbering all Mac dialogs and dialog items.
+
+ * Define new EmDlgItemIDs for all the items in the dialog. All
+ dialog items need to have unique IDs assigned to them -- even
+ across all dialogs -- so use the DLG_BASE macro to establish a
+ little number space for them based on the EmDlgID of the dialog
+ they're in.
+
+ * Define a new entry point. This entry point should have a name
+ along the lines of Do<Something> (e.g., DoHordeNew,
+ DoDatabaseExport). This entry point can take any number of
+ parameters you like.
+
+ * Implement this entry point by calling EmDlg::RunDialog, passing
+ to it the EmDlgID of the dialog box to show, a pointer to a
+ callback procedure, and a pointer to any custom data to pass to
+ the callback procedure (usually a pointer to a parameter block
+ containing the parameters passed to the entry point).
+
+ * Implement the callback procedure. The callback procedure is
+ responsible for initializing the dialog and its elements,
+ for handling clicks on the dialog items, and for finalizing and
+ closing the dialog. A template for a callback procedure is kept
+ at the bottom of EmDlg.cpp.
+
+ * The callback procedure is passed a reference to an
+ EmDlgContext. This structure contains information about the
+ dialog and why the callback procedure is being called. The
+ first thing the callback should do is examine the fCommandID
+ field. This field is of type EmDlgCmdID, and can be one of the
+ following values:
+
+ * kDlgCmdInit Passed to the callback procedure once to
+ initialize the dialog and its elements.
+
+ * kDlgCmdIdle Passed to the callback procedure several
+ times a second to allow the dialog to idle.
+ Sent to the callback only if it indicates
+ that it wants idle time (by setting the
+ fNeedsIdle field when initialized).
+
+ * kDlgCmdItemSelected Passed to the callback procedure any time
+ a dialog item is selected.
+
+ * kDlgCmdDestroy Passed to the callback procedure once when
+ the dialog is being destroyed. The dialog
+ may choose to perform any last minute
+ cleanup here.
+
+ * If the command is kDlgCmdItemSelected, then the callback
+ procedure should examine the fItemID field. This indicates what
+ dialog item was selected.
+
+ * The callback procedure returns an EmDlgFnResult. This can be
+ one of the following values:
+
+ * kDlgResultContinue Keep the dialog open--we're not done yet.
+
+ * kDlgResultClose Close the dialog. Either the user pressed
+ a button to close the dialog, or the dialog
+ has some sort of auto-close feature, or an
+ error occurred.
+
+ * Define your platform-specific dialogs. In general, create your
+ dialogs as you would naturally on that platform (e.g., use
+ Constructor on the Mac, VC++'s dialog editor on Windows, or
+ fluid if using FLTK on Unix). However, to hook those dialogs up
+ to the cross-platform mechanism, the following additional steps
+ need to be taken:
+
+ Macintosh
+ ---------
+ * The dialog's 'ppob' resource ID should be kDialogIDBase
+ (2000) plus the EmDlgID of the dialog.
+
+ * The dialog items should have IDs (and, if applicable,
+ message values) of kDialogItemIDBase (5000) plus their
+ EmDlgItemID.
+
+ Unix (FLTK)
+ -----------
+ * Name the function that creates the dialog along the lines
+ of "PrvMake<DialogName>". In PrvMakeDialog() in
+ EmDlgFltk.cpp, add a case statement to call this function.
+
+ * When creating widgets in fluid, include a line like the
+ following in the "code" sections:
+
+ ::PrvSetWidgetID (o, kDlgItemOK);
+
+ Windows
+ -------
+ * Create the dialog and items using any resource symbols you
+ care to define. Note that the values for your resource
+ symbols must be unique from those for all other dialog
+ items. The Emulator will enforce this with checks in
+ PrvFromDlgItemID and PrvToDlgItemID (two internal routines
+ used when creating and manipulating dialogs -- these checks
+ are made only in debug builds).
+
+ * In EmDlgWin.cpp, map the symbols you've defined to the
+ cross-platform symbols by adding the appropriate entries to
+ kDlgIDMap and kDlgItemIDMap.
+*/
+
+class EmROMTransfer;
+
+
+enum EmDlgCmdID
+{
+ kDlgCmdNone = 0,
+
+ kDlgCmdInit = 1,
+ kDlgCmdIdle = 2,
+ kDlgCmdItemSelected = 3,
+ kDlgCmdDestroy = 4,
+ kDlgCmdPanelEnter = 5,
+ kDlgCmdPanelExit = 6
+};
+
+enum EmDlgFnResult
+{
+ kDlgResultNone = 0,
+
+ kDlgResultContinue = 1,
+ kDlgResultClose = 2
+};
+
+enum EmDlgID
+{
+ kDlgNone = 0,
+
+ kDlgAboutBox = 1,
+ kDlgSessionNew = 2,
+ kDlgSessionSave = 3,
+ kDlgHordeNew = 4,
+ kDlgDatabaseImport = 5,
+ kDlgDatabaseExport = 6,
+ kDlgROMTransferQuery = 7,
+ kDlgROMTransferProgress = 8,
+ kDlgGremlinControl = 9,
+ kDlgEditPreferences = 10,
+ kDlgEditLogging = 11,
+ kDlgEditDebugging = 12,
+ kDlgEditSkins = 13,
+ kDlgCommonDialog = 14,
+ kDlgSaveBound = 15,
+ kDlgEditHostFS = 16,
+ kDlgEditBreakpoints = 17,
+ kDlgEditCodeBreakpoint = 18,
+ kDlgEditTracingOptions = 19,
+ kDlgEditPreferencesFullyBound = 20,
+ kDlgReset = 21,
+ kDlgSessionInfo = 22,
+ kDlgGetSocketAddress = 23,
+ kDlgEditErrorHandling = 24,
+ kDlgMinimizeProgress = 25
+};
+
+enum EmDlgPanelID
+{
+ kDlgPanelNone = 0,
+
+ kDlgPanelAbtMain = 1,
+ kDlgPanelAbtWindows = 2,
+ kDlgPanelAbtMac = 3,
+ kDlgPanelAbtUAE = 4,
+ kDlgPanelAbtQNX = 5
+};
+
+#define DLG_BASE(dlgID) ((dlgID) * 100)
+enum EmDlgItemID
+{
+ kDlgItemNone = 0,
+
+ kDlgItemOK = 0x01,
+ kDlgItemCancel = 0x02,
+ kDlgItemYes = 0x03,
+ kDlgItemNo = 0x04,
+ kDlgItemContinue = 0x05,
+ kDlgItemDebug = 0x06,
+ kDlgItemReset = 0x07,
+ kDlgItemNextGremlin = 0x08,
+
+ kDlgItemAbtAppName = DLG_BASE(kDlgAboutBox) + 0,
+ kDlgItemAbtURLPalmWeb = DLG_BASE(kDlgAboutBox) + 1,
+ kDlgItemAbtURLPalmMail = DLG_BASE(kDlgAboutBox) + 2,
+ kDlgItemAbtURLWindowsWeb = DLG_BASE(kDlgAboutBox) + 3,
+ kDlgItemAbtURLWindowsMail = DLG_BASE(kDlgAboutBox) + 4,
+ kDlgItemAbtURLMacWeb = DLG_BASE(kDlgAboutBox) + 5,
+ kDlgItemAbtURLMacMail = DLG_BASE(kDlgAboutBox) + 6,
+ kDlgItemAbtURLUAEWeb = DLG_BASE(kDlgAboutBox) + 7,
+ kDlgItemAbtURLUAEMail = DLG_BASE(kDlgAboutBox) + 8,
+ kDlgItemAbtURLQNXWeb = DLG_BASE(kDlgAboutBox) + 9,
+ kDlgItemAbtURLQNXMail = DLG_BASE(kDlgAboutBox) + 10,
+
+ kDlgItemNewDevice = DLG_BASE(kDlgSessionNew) + 0,
+ kDlgItemNewSkin = DLG_BASE(kDlgSessionNew) + 1,
+ kDlgItemNewMemorySize = DLG_BASE(kDlgSessionNew) + 2,
+ kDlgItemNewROM = DLG_BASE(kDlgSessionNew) + 3,
+ kDlgItemNewROMBrowse = DLG_BASE(kDlgSessionNew) + 4,
+
+ kDlgItemHrdAppList = DLG_BASE(kDlgHordeNew) + 0,
+ kDlgItemHrdStart = DLG_BASE(kDlgHordeNew) + 1,
+ kDlgItemHrdStop = DLG_BASE(kDlgHordeNew) + 2,
+ kDlgItemHrdCheckSwitch = DLG_BASE(kDlgHordeNew) + 3,
+ kDlgItemHrdCheckSave = DLG_BASE(kDlgHordeNew) + 4,
+ kDlgItemHrdCheckStop = DLG_BASE(kDlgHordeNew) + 5,
+ kDlgItemHrdDepthSwitch = DLG_BASE(kDlgHordeNew) + 6,
+ kDlgItemHrdDepthSave = DLG_BASE(kDlgHordeNew) + 7,
+ kDlgItemHrdDepthStop = DLG_BASE(kDlgHordeNew) + 8,
+ kDlgItemHrdLogging = DLG_BASE(kDlgHordeNew) + 9,
+ kDlgItemHrdFirstLaunchedApp = DLG_BASE(kDlgHordeNew) + 10,
+ kDlgItemHrdSelectAll = DLG_BASE(kDlgHordeNew) + 11,
+ kDlgItemHrdSelectNone = DLG_BASE(kDlgHordeNew) + 12,
+
+ kDlgItemImpNumFiles = DLG_BASE(kDlgDatabaseImport) + 0,
+ kDlgItemImpProgress = DLG_BASE(kDlgDatabaseImport) + 1,
+
+ kDlgItemExpDbList = DLG_BASE(kDlgDatabaseExport) + 0,
+
+ kDlgItemDlqInstructions = DLG_BASE(kDlgROMTransferQuery) + 0,
+ kDlgItemDlqPortList = DLG_BASE(kDlgROMTransferQuery) + 1,
+ kDlgItemDlqBaudList = DLG_BASE(kDlgROMTransferQuery) + 2,
+
+ kDlgItemDlpMessage = DLG_BASE(kDlgROMTransferProgress) + 0,
+ kDlgItemDlpProgress = DLG_BASE(kDlgROMTransferProgress) + 1,
+
+ kDlgItemGrmNumber = DLG_BASE(kDlgGremlinControl) + 0,
+ kDlgItemGrmEventNumber = DLG_BASE(kDlgGremlinControl) + 1,
+ kDlgItemGrmElapsedTime = DLG_BASE(kDlgGremlinControl) + 2,
+ kDlgItemGrmStop = DLG_BASE(kDlgGremlinControl) + 3,
+ kDlgItemGrmResume = DLG_BASE(kDlgGremlinControl) + 4,
+ kDlgItemGrmStep = DLG_BASE(kDlgGremlinControl) + 5,
+
+ kDlgItemPrfRedirectSerial = DLG_BASE(kDlgEditPreferences) + 0,
+ kDlgItemPrfRedirectIR = DLG_BASE(kDlgEditPreferences) + 1,
+ kDlgItemPrfRedirectMystery = DLG_BASE(kDlgEditPreferences) + 2,
+ kDlgItemPrfRedirectNetLib = DLG_BASE(kDlgEditPreferences) + 9,
+ kDlgItemPrfEnableSound = DLG_BASE(kDlgEditPreferences) + 10,
+ kDlgItemPrfSaveAlways = DLG_BASE(kDlgEditPreferences) + 11,
+ kDlgItemPrfSaveAsk = DLG_BASE(kDlgEditPreferences) + 12,
+ kDlgItemPrfSaveNever = DLG_BASE(kDlgEditPreferences) + 13,
+ kDlgItemPrfUserName = DLG_BASE(kDlgEditPreferences) + 14,
+
+ kDlgItemLogNormal = DLG_BASE(kDlgEditLogging) + 0,
+ kDlgItemLogGremlins = DLG_BASE(kDlgEditLogging) + 1,
+ kDlgItemLogCheckBase = DLG_BASE(kDlgEditLogging) + 10,
+#undef DEFINE_BUTTON_ID
+#define DEFINE_BUTTON_ID(name) kDlgItemLog##name,
+ FOR_EACH_LOG_PREF(DEFINE_BUTTON_ID)
+
+ kDlgItemDbgDialogBeep = DLG_BASE(kDlgEditDebugging) + 0,
+ kDlgItemDbgCheckBase = DLG_BASE(kDlgEditDebugging) + 10,
+#undef DEFINE_BUTTON_ID
+#define DEFINE_BUTTON_ID(name) kDlgItemDbg##name,
+ FOR_EACH_REPORT_PREF(DEFINE_BUTTON_ID)
+
+ kDlgItemSknSkinList = DLG_BASE(kDlgEditSkins) + 0,
+ kDlgItemSknDoubleScale = DLG_BASE(kDlgEditSkins) + 1,
+ kDlgItemSknWhiteBackground = DLG_BASE(kDlgEditSkins) + 2,
+ kDlgItemSknDim = DLG_BASE(kDlgEditSkins) + 3,
+ kDlgItemSknRed = DLG_BASE(kDlgEditSkins) + 4,
+ kDlgItemSknGreen = DLG_BASE(kDlgEditSkins) + 5,
+ kDlgItemSknStayOnTop = DLG_BASE(kDlgEditSkins) + 6,
+
+ kDlgItemCmnText = DLG_BASE(kDlgCommonDialog) + 0,
+ kDlgItemCmnIconStop = DLG_BASE(kDlgCommonDialog) + 1,
+ kDlgItemCmnIconCaution = DLG_BASE(kDlgCommonDialog) + 2,
+ kDlgItemCmnIconNote = DLG_BASE(kDlgCommonDialog) + 3,
+ kDlgItemCmnButton1 = DLG_BASE(kDlgCommonDialog) + 4,
+ kDlgItemCmnButton2 = DLG_BASE(kDlgCommonDialog) + 5,
+ kDlgItemCmnButton3 = DLG_BASE(kDlgCommonDialog) + 6,
+ kDlgItemCmnButtonCopy = DLG_BASE(kDlgCommonDialog) + 7,
+
+ kDlgItemBndSaveROM = DLG_BASE(kDlgSaveBound) + 0,
+ kDlgItemBndSaveRAM = DLG_BASE(kDlgSaveBound) + 1,
+
+ kDlgItemHfsList = DLG_BASE(kDlgEditHostFS) + 0,
+ kDlgItemHfsPath = DLG_BASE(kDlgEditHostFS) + 1,
+ kDlgItemHfsMounted = DLG_BASE(kDlgEditHostFS) + 2,
+ kDlgItemHfsBrowse = DLG_BASE(kDlgEditHostFS) + 3,
+
+ kDlgItemBrkList = DLG_BASE(kDlgEditBreakpoints) + 0,
+ kDlgItemBrkButtonEdit = DLG_BASE(kDlgEditBreakpoints) + 1,
+ kDlgItemBrkButtonClear = DLG_BASE(kDlgEditBreakpoints) + 2,
+ kDlgItemBrkCheckEnabled = DLG_BASE(kDlgEditBreakpoints) + 3,
+ kDlgItemBrkStartAddress = DLG_BASE(kDlgEditBreakpoints) + 4,
+ kDlgItemBrkNumberOfBytes = DLG_BASE(kDlgEditBreakpoints) + 5,
+
+ kDlgItemBrkAddress = DLG_BASE(kDlgEditCodeBreakpoint) + 0,
+ kDlgItemBrkCondition = DLG_BASE(kDlgEditCodeBreakpoint) + 1,
+
+ kDlgItemTrcOutput = DLG_BASE(kDlgEditTracingOptions) + 0,
+ kDlgItemTrcTargetText = DLG_BASE(kDlgEditTracingOptions) + 1,
+ kDlgItemTrcTargetValue = DLG_BASE(kDlgEditTracingOptions) + 2,
+ kDlgItemTrcInfo = DLG_BASE(kDlgEditTracingOptions) + 3,
+ kDlgItemTrcAutoConnect = DLG_BASE(kDlgEditTracingOptions) + 4,
+
+ kDlgItemRstSoft = DLG_BASE(kDlgReset) + 0,
+ kDlgItemRstHard = DLG_BASE(kDlgReset) + 1,
+ kDlgItemRstDebug = DLG_BASE(kDlgReset) + 2,
+ kDlgItemRstNoExt = DLG_BASE(kDlgReset) + 3,
+
+ kDlgItemInfDeviceFld = DLG_BASE(kDlgSessionInfo) + 0,
+ kDlgItemInfRAMFld = DLG_BASE(kDlgSessionInfo) + 1,
+ kDlgItemInfROMFld = DLG_BASE(kDlgSessionInfo) + 2,
+ kDlgItemInfSessionFld = DLG_BASE(kDlgSessionInfo) + 3,
+
+ kDlgItemSocketAddress = DLG_BASE(kDlgGetSocketAddress) + 0,
+
+ kDlgItemErrWarningOff = DLG_BASE(kDlgEditErrorHandling) + 0,
+ kDlgItemErrErrorOff = DLG_BASE(kDlgEditErrorHandling) + 1,
+ kDlgItemErrWarningOn = DLG_BASE(kDlgEditErrorHandling) + 2,
+ kDlgItemErrErrorOn = DLG_BASE(kDlgEditErrorHandling) + 3,
+
+ kDlgItemMinPassNumber = DLG_BASE(kDlgMinimizeProgress) + 0,
+ kDlgItemMinEventNumber = DLG_BASE(kDlgMinimizeProgress) + 1,
+ kDlgItemMinElapsed = DLG_BASE(kDlgMinimizeProgress) + 2,
+ kDlgItemMinRange = DLG_BASE(kDlgMinimizeProgress) + 3,
+ kDlgItemMinDiscarded = DLG_BASE(kDlgMinimizeProgress) + 4,
+ kDlgItemMinProgress = DLG_BASE(kDlgMinimizeProgress) + 5,
+
+ kDlgItemLast
+};
+
+
+enum EmCommonDialogFlags
+{
+ // Each button is stored in an 8-bit field. A button ID is
+ // stored in the lower 4-bits, and the upper 4-bits are use
+ // to hold flags indicating if the button is the default button,
+ // if the button is enabled, or if the button is even visible.
+ // There are three of these fields, filling 24 of the 32 bits of
+ // the flags parameter.
+
+ /*
+ The various buttons have different positions depending on the platform
+ being run on:
+
+ Mac/Unix:
+
+ +----------------------------------+
+ | ** |
+ | ** Blah blah blah |
+ | ** |
+ | |
+ | |
+ | Button3 Button2 Button1 |
+ +----------------------------------+
+
+ Windows:
+
+ +----------------------------------+
+ | ** Button1 |
+ | ** Blah blah blah Button2 |
+ | ** Button3 |
+ | |
+ | |
+ | |
+ +----------------------------------+
+ */
+
+ kButtonMask = 0x0F,
+
+ kButtonDefault = 0x10,
+ kButtonEscape = 0x20,
+ kButtonVisible = 0x40,
+ kButtonEnabled = 0x80,
+
+ kButtonFieldShift = 8,
+ kButtonFieldMask = 0x000000FF,
+
+ // The following naming convention is used for the following values:
+ //
+ // An all-upper name
+ // the button is the default button (and visible and enabled)
+ //
+ // A first-upper name
+ // the button is visible and enabled.
+ //
+ // An all-lower name
+ // the button is visible but disabled.
+
+#define SET_BUTTON(p, x) (((long)(x) & kButtonFieldMask) << (kButtonFieldShift * (p)))
+#define GET_BUTTON(p, x) (((x) >> (kButtonFieldShift * (p))) & kButtonFieldMask)
+
+#define SET_BUTTON_DEFAULT(p, x) SET_BUTTON(p, (x) | kButtonVisible | kButtonEnabled | kButtonDefault)
+#define SET_BUTTON_ESCAPE(p, x) SET_BUTTON(p, (x) | kButtonVisible | kButtonEnabled | kButtonEscape)
+#define SET_BUTTON_STANDARD(p, x) SET_BUTTON(p, (x) | kButtonVisible | kButtonEnabled)
+#define SET_BUTTON_DISABLED(p, x) SET_BUTTON(p, (x) | kButtonVisible)
+
+ kDlgFlags_None = 0,
+
+ kDlgFlags_OK = SET_BUTTON_DEFAULT (0, kDlgItemOK),
+
+ kDlgFlags_CANCEL = SET_BUTTON_DEFAULT (0, kDlgItemCancel),
+
+ kDlgFlags_OK_Cancel = SET_BUTTON_DEFAULT (0, kDlgItemOK)
+ | SET_BUTTON_ESCAPE (1, kDlgItemCancel),
+
+ kDlgFlags_Ok_CANCEL = SET_BUTTON_STANDARD (0, kDlgItemOK)
+ | SET_BUTTON_DEFAULT (1, kDlgItemCancel),
+
+ kDlgFlags_YES_No = SET_BUTTON_DEFAULT (0, kDlgItemYes)
+ | SET_BUTTON_ESCAPE (1, kDlgItemNo),
+
+ kDlgFlags_Yes_NO = SET_BUTTON_STANDARD (0, kDlgItemYes)
+ | SET_BUTTON_DEFAULT (1, kDlgItemNo),
+
+ kDlgFlags_Continue_DEBUG_Reset = SET_BUTTON_STANDARD (0, kDlgItemContinue)
+ | SET_BUTTON_DEFAULT (1, kDlgItemDebug)
+ | SET_BUTTON_STANDARD (2, kDlgItemReset),
+
+ kDlgFlags_continue_DEBUG_Reset = SET_BUTTON_DISABLED (0, kDlgItemContinue)
+ | SET_BUTTON_DEFAULT (1, kDlgItemDebug)
+ | SET_BUTTON_STANDARD (2, kDlgItemReset),
+
+ kDlgFlags_continue_debug_RESET = SET_BUTTON_DISABLED (0, kDlgItemContinue)
+ | SET_BUTTON_DISABLED (1, kDlgItemDebug)
+ | SET_BUTTON_DEFAULT (2, kDlgItemReset)
+};
+
+typedef vector<EmDlgItemID> EmDlgItemIDList;
+
+typedef long EmDlgItemIndex;
+typedef vector<EmDlgItemIndex> EmDlgItemIndexList;
+
+typedef long EmDlgListIndex; // Zero-based
+typedef vector<EmDlgListIndex> EmDlgListIndexList;
+const EmDlgListIndex kDlgItemListNone = -1;
+
+struct EmDlgContext;
+
+typedef EmDlgItemID (*EmDlgThreadFn)(const void*);
+typedef EmDlgFnResult (*EmDlgFn)(EmDlgContext&);
+typedef void* EmDlgRef;
+
+enum EmROMFileStatus
+{
+ kROMFileOK,
+ kROMFileDubious,
+ kROMFileUnknown
+};
+
+struct EmDlgContext
+{
+ EmDlgContext (void);
+ EmDlgContext (const EmDlgContext&);
+
+ EmDlgFnResult Init ();
+ EmDlgFnResult Event (EmDlgItemID);
+ EmDlgFnResult Idle ();
+ void Destroy ();
+ EmDlgFnResult PanelEnter ();
+ EmDlgFnResult PanelExit ();
+
+ EmDlgFn fFn;
+ EmDlgFnResult fFnResult;
+ EmDlgRef fDlg;
+ EmDlgID fDlgID;
+ EmDlgPanelID fPanelID;
+ EmDlgItemID fItemID;
+ EmDlgCmdID fCommandID;
+ bool fNeedsIdle;
+ void* fUserData;
+
+ EmDlgItemID fDefaultItem;
+ EmDlgItemID fCancelItem;
+};
+
+struct DoGetFileParameters
+{
+ DoGetFileParameters (EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList) :
+ fResult (result),
+ fPrompt (prompt),
+ fDefaultPath (defaultPath),
+ fFilterList (filterList)
+ {
+ }
+
+ EmFileRef& fResult;
+ const string& fPrompt;
+ const EmDirRef& fDefaultPath;
+ const EmFileTypeList& fFilterList;
+};
+
+struct DoGetFileListParameters
+{
+ DoGetFileListParameters (EmFileRefList& results,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList) :
+ fResults (results),
+ fPrompt (prompt),
+ fDefaultPath (defaultPath),
+ fFilterList (filterList)
+ {
+ }
+
+ EmFileRefList& fResults;
+ const string& fPrompt;
+ const EmDirRef& fDefaultPath;
+ const EmFileTypeList& fFilterList;
+};
+
+struct DoPutFileParameters
+{
+ DoPutFileParameters (EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList,
+ const string& defaultName) :
+ fResult (result),
+ fPrompt (prompt),
+ fDefaultPath (defaultPath),
+ fFilterList (filterList),
+ fDefaultName (defaultName)
+ {
+ }
+
+ EmFileRef& fResult;
+ const string& fPrompt;
+ const EmDirRef& fDefaultPath;
+ const EmFileTypeList& fFilterList;
+ const string& fDefaultName;
+};
+
+struct DoGetDirectoryParameters
+{
+ DoGetDirectoryParameters (EmDirRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath) :
+ fResult (result),
+ fPrompt (prompt),
+ fDefaultPath (defaultPath)
+ {
+ }
+
+ EmDirRef& fResult;
+ const string& fPrompt;
+ const EmDirRef& fDefaultPath;
+};
+
+struct DoSessionSaveParameters
+{
+ DoSessionSaveParameters (const string& appName,
+ const string& docName,
+ Bool quitting) :
+ fAppName (appName),
+ fDocName (docName),
+ fQuitting (quitting)
+ {
+ }
+
+ const string& fAppName;
+ const string& fDocName;
+ Bool fQuitting;
+};
+
+struct RunDialogParameters
+{
+ RunDialogParameters (EmDlgFn fn, void* userData, EmDlgID dlgID) :
+ fFn (fn),
+ fUserData (userData),
+ fDlgID (dlgID)
+ {
+ }
+
+ EmDlgFn fFn;
+ void* fUserData;
+ EmDlgID fDlgID;
+};
+
+// !!! Needs to be moved elsewhere
+typedef DatabaseInfoList EmDatabaseList;
+struct EditCodeBreakpointData;
+struct EmErrorHandlingMenuBundle;
+
+class EmDlg
+{
+ public:
+ static EmDlgItemID DoGetFile (EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList);
+ static EmDlgItemID DoGetFileList (EmFileRefList& results,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList);
+ static EmDlgItemID DoPutFile (EmFileRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath,
+ const EmFileTypeList& filterList,
+ const string& defaultName);
+ static EmDlgItemID DoGetDirectory (EmDirRef& result,
+ const string& prompt,
+ const EmDirRef& defaultPath);
+
+ static EmDlgItemID DoAboutBox (void);
+
+ static EmDlgItemID DoSessionNew (Configuration&);
+ static EmDlgItemID DoSessionSave (const string& docName,
+ Bool quitting);
+
+ static EmDlgItemID DoHordeNew (void);
+
+ static EmDlgItemID DoDatabaseImport (const EmFileRefList&,
+ EmFileImportMethod method);
+ static EmDlgItemID DoDatabaseExport (void);
+ static EmDlgItemID DoReset (EmResetType&);
+ static EmDlgItemID DoROMTransferQuery (EmTransport::Config*&);
+ static EmDlgItemID DoROMTransferProgress (EmROMTransfer&);
+
+ static EmDlgItemID DoEditPreferences (void);
+ static EmDlgItemID DoEditLoggingOptions (LoggingType);
+ static EmDlgItemID DoEditDebuggingOptions (void);
+ static EmDlgItemID DoEditErrorHandling (void);
+ static EmDlgItemID DoEditSkins (void);
+ static EmDlgItemID DoEditHostFSOptions (void);
+ static EmDlgItemID DoEditBreakpoints (void);
+ static EmDlgItemID DoEditCodeBreakpoint (EditCodeBreakpointData&);
+#if HAS_TRACER
+ static EmDlgItemID DoEditTracingOptions (void);
+#endif
+
+ static EmDlgItemID DoCommonDialog (StrCode msg,
+ EmCommonDialogFlags);
+ static EmDlgItemID DoCommonDialog (const char* msg,
+ EmCommonDialogFlags);
+ static EmDlgItemID DoCommonDialog (const string& msg,
+ EmCommonDialogFlags);
+
+ static EmDlgItemID DoSaveBound (void);
+ static EmDlgItemID DoSessionInfo (void);
+ static EmDlgItemID DoGetSocketAddress (string&);
+
+ static void GremlinControlOpen (void);
+ static void GremlinControlClose (void);
+
+ static void MinimizeProgressOpen (void);
+ static void MinimizeProgressClose (void);
+
+ static EmDlgItemID RunDialog (EmDlgFn, void*, EmDlgID);
+ static EmDlgItemID RunDialog (EmDlgThreadFn, const void* parameters);
+
+ static EmDlgRef DialogOpen (EmDlgFn, void*, EmDlgID);
+ static void DialogClose (EmDlgRef);
+
+ private:
+ static EmDlgItemID HostRunGetFile (const void* parameters);
+ static EmDlgItemID HostRunGetFileList (const void* parameters);
+ static EmDlgItemID HostRunPutFile (const void* parameters);
+ static EmDlgItemID HostRunGetDirectory (const void* parameters);
+ static EmDlgItemID HostRunAboutBox (const void* parameters);
+ static EmDlgItemID HostRunSessionSave (const void* parameters);
+ static EmDlgItemID HostRunDialog (const void* parameters);
+
+ static EmDlgRef HostDialogOpen (EmDlgFn, void*, EmDlgID);
+ static void HostDialogClose (EmDlgRef);
+
+ public: // public right now for PrvIdleCallback, PrvCreateDialog
+ static void HostDialogInit (EmDlgContext&);
+ static void HostStartIdling (EmDlgContext&);
+ static void HostStopIdling (EmDlgContext&);
+
+#if PLATFORM_WINDOWS
+ static BOOL CALLBACK PrvHostModalProc (HWND hWnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam);
+ static BOOL CALLBACK PrvHostModelessProc (HWND hWnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam);
+#endif
+
+ private:
+ friend struct EmDlgContext; // To call HostStartIdling
+
+ private:
+ static EmDlgFnResult PrvSessionNew (EmDlgContext&);
+ static EmDlgFnResult PrvHordeNew (EmDlgContext&);
+ static EmDlgFnResult PrvDatabaseImport (EmDlgContext&);
+ static EmDlgFnResult PrvDatabaseExport (EmDlgContext&);
+ static EmDlgFnResult PrvReset (EmDlgContext&);
+ static EmDlgFnResult PrvROMTransferQuery (EmDlgContext&);
+ static EmDlgFnResult PrvROMTransferProgress (EmDlgContext&);
+ static EmDlgFnResult PrvEditPreferences (EmDlgContext&);
+ static EmDlgFnResult PrvEditLoggingOptions (EmDlgContext&);
+ static EmDlgFnResult PrvEditDebuggingOptions (EmDlgContext&);
+ static EmDlgFnResult PrvErrorHandling (EmDlgContext&);
+ static EmDlgFnResult PrvEditSkins (EmDlgContext&);
+ static EmDlgFnResult PrvEditHostFSOptions (EmDlgContext&);
+ static EmDlgFnResult PrvEditBreakpoints (EmDlgContext&);
+ static EmDlgFnResult PrvEditCodeBreakpoint (EmDlgContext&);
+#if HAS_TRACER
+ static EmDlgFnResult PrvEditTracingOptions (EmDlgContext&);
+#endif
+ static EmDlgFnResult PrvCommonDialog (EmDlgContext&);
+ static EmDlgFnResult PrvSaveBound (EmDlgContext&);
+ static EmDlgFnResult PrvSessionInfo (EmDlgContext&);
+ static EmDlgFnResult PrvGetSocketAddress (EmDlgContext&);
+ static EmDlgFnResult PrvGremlinControl (EmDlgContext&);
+ static EmDlgFnResult PrvMinimizeProgress (EmDlgContext&);
+
+ // DoSessionNew
+
+ static void PrvBuildROMMenu (const EmDlgContext&);
+ static void PrvBuildDeviceMenu (const EmDlgContext&);
+ static void PrvBuildSkinMenu (const EmDlgContext&);
+ static void PrvBuildMemorySizeMenu (const EmDlgContext&);
+ static void PrvNewSessionSetOKButton (const EmDlgContext&);
+ static void PrvFilterDeviceList (const EmFileRef& romFile,
+ EmDeviceList& devices,
+ EmDeviceList::iterator& devices_end,
+ unsigned int& version);
+ static void PrvFilterMemorySizes (MemoryTextList& sizes,
+ const Configuration& cfg);
+ static EmROMFileStatus PrvCanUseROMFile (EmFileRef& testRef);
+
+ // DoHordeNew
+
+ static UInt32 PrvSelectedAppNameToIndex (EmDatabaseList list, const string& appName);
+ static DatabaseInfo PrvSelectedIndexToApp (EmDatabaseList list, uint32 index);
+ static void PrvSelectedList (EmDatabaseList selectedApps,
+ StringList &selectedAppStrings);
+
+ // DoDatabaseExport
+
+ static Bool PrvExportFile (const DatabaseInfo& db);
+
+ // DoROMTransferQuery
+
+ static void PrvGetDlqPortItemList (EmTransportDescriptorList& menuItems);
+ static void PrvConvertBaudListToStrings (const EmTransportSerial::BaudList& baudList,
+ StringList& baudStrList);
+
+ // DoEditPreferences
+
+ static void PrvEditPrefToDialog (EmDlgContext& context);
+ static void PrvEditPrefFromDialog (EmDlgContext& context);
+ static void PrvBuildDescriptorLists (EmDlgContext& context);
+ static void PrvGetEditPreferences (EmDlgContext& context);
+ static void PrvPutEditPreferences (EmDlgContext& context);
+ static Bool PrvEditPreferencesValidate (EmDlgContext& context);
+ static void PrvGetPrefSocketAddress (EmDlgContext& context);
+
+ // DoEditLoggingOptions
+
+ static void PrvFetchLoggingPrefs (EmDlgContext& context);
+ static void PrvInstallLoggingPrefs (EmDlgContext& context);
+ static void PrvLoggingPrefsToButtons (EmDlgContext& context);
+ static void PrvLoggingPrefsFromButtons (EmDlgContext& context);
+
+ // DoEditDebuggingOptions
+
+ static void PrvFetchDebuggingPrefs (EmDlgContext& context);
+ static void PrvInstallDebuggingPrefs (EmDlgContext& context);
+ static void PrvDebuggingPrefsToButtons (EmDlgContext& context);
+ static void PrvDebuggingPrefsFromButtons (EmDlgContext& context);
+
+ // DoEditErrorHandling
+
+ static string PrvMenuItemText (EmErrorHandlingOption item);
+ static void PrvBuildMenu (EmErrorHandlingMenuBundle& menu,
+ StringList& items);
+ static long PrvFindIndex (EmErrorHandlingMenuBundle& menu,
+ EmErrorHandlingOption toFind);
+ static void PrvErrorHandlingToDialog (EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu);
+ static void PrvErrorHandlingFromDialog (EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu);
+ static EmDlgItemID PrvAskChangeLogging (void);
+ static void PrvCheckSetting (EmDlgContext& context,
+ EmErrorHandlingMenuBundle& menu);
+ static Bool PrvCheckSettings (EmDlgContext& context);
+ static void PrvEnableLoggingOption (EmErrorHandlingMenuBundle& menu);
+ static void PrvEnableLoggingOptions (void);
+
+ // DoEditHostFSOptions
+
+ static void PrvEditHostFSOptionsOK (EmDlgContext& context);
+
+ // DoEditBreakpoints
+
+ static void PrvEnableCodeBreakpointControls (EmDlgContext& context, bool enable);
+ static void PrvEnableDataBreakpointControls (EmDlgContext& context, bool enable);
+ static void PrvRefreshCodeBreakpointList (EmDlgContext& context);
+ static void PrvGetCodeBreakpoints (EmDlgContext& context);
+ static void PrvSetCodeBreakpoints (EmDlgContext& context);
+
+ // DoEditTracingOptions
+
+#if HAS_TRACER
+ static void PrvPopTracerSettings (EmDlgContext& context);
+ static void PrvPushTracerSettings (EmDlgContext& context);
+#endif
+
+ // GremlinControl
+
+ static void PrvGrmUpdateGremlinNumber (EmDlgContext& context);
+ static void PrvGrmUpdateEventNumber (EmDlgContext& context);
+ static void PrvGrmUpdateElapsedTime (EmDlgContext& context);
+ static void PrvGrmUpdateAll (EmDlgContext& context);
+
+ // Minimization Progress
+
+ static void PrvMinUpdatePassNumber (EmDlgContext& context);
+ static void PrvMinUpdateEventNumber (EmDlgContext& context);
+ static void PrvMinUpdateElapsed (EmDlgContext& context);
+ static void PrvMinUpdateRange (EmDlgContext& context);
+ static void PrvMinUpdateDiscarded (EmDlgContext& context);
+ static void PrvMinUpdateProgress (EmDlgContext& context);
+ static void PrvMinUpdateAll (EmDlgContext& context);
+
+ public: // Most of these are really "Host" functions
+ static void SetDlgBounds (EmDlgRef, const EmRect&);
+ static EmRect GetDlgBounds (EmDlgRef);
+ static void MoveDlgTo (EmDlgRef, EmCoord x, EmCoord y);
+ static void MoveDlgTo (EmDlgRef, const EmPoint&);
+ static void CenterDlg (EmDlgRef);
+ static void EnsureDlgOnscreen (EmDlgRef);
+
+ static void SetDlgDefaultButton (EmDlgContext&, EmDlgItemID);
+ static void SetDlgCancelButton (EmDlgContext&, EmDlgItemID);
+
+ static void SetItemMin (EmDlgRef, EmDlgItemID, long max);
+ static void SetItemValue (EmDlgRef, EmDlgItemID, long value);
+ static void SetItemMax (EmDlgRef, EmDlgItemID, long max);
+ static void SetItemBounds (EmDlgRef, EmDlgItemID, const EmRect&);
+
+ static void SetItemText (EmDlgRef, EmDlgItemID, StrCode);
+ static void SetItemText (EmDlgRef, EmDlgItemID, const char*);
+ static void SetItemText (EmDlgRef, EmDlgItemID, string);
+
+ static long GetItemMin (EmDlgRef, EmDlgItemID);
+ static long GetItemValue (EmDlgRef, EmDlgItemID);
+ static long GetItemMax (EmDlgRef, EmDlgItemID);
+ static EmRect GetItemBounds (EmDlgRef, EmDlgItemID);
+ static string GetItemText (EmDlgRef, EmDlgItemID);
+
+ static void EnableItem (EmDlgRef, EmDlgItemID);
+ static void DisableItem (EmDlgRef, EmDlgItemID);
+ static void EnableDisableItem (EmDlgRef, EmDlgItemID, Bool);
+
+ static void ShowItem (EmDlgRef, EmDlgItemID);
+ static void HideItem (EmDlgRef, EmDlgItemID);
+ static void ShowHideItem (EmDlgRef, EmDlgItemID, Bool);
+
+ static void ClearMenu (EmDlgRef, EmDlgItemID);
+ static void AppendToMenu (EmDlgRef, EmDlgItemID, const string&);
+ static void AppendToMenu (EmDlgRef, EmDlgItemID, const StringList&);
+ static void EnableMenuItem (EmDlgRef, EmDlgItemID, long);
+ static void DisableMenuItem (EmDlgRef, EmDlgItemID, long);
+
+ static void ClearList (EmDlgRef, EmDlgItemID);
+ static void AppendToList (EmDlgRef, EmDlgItemID, const string&);
+ static void AppendToList (EmDlgRef, EmDlgItemID, const StringList&);
+ static void SelectListItem (EmDlgRef, EmDlgItemID, EmDlgListIndex);
+ static void SelectListItems (EmDlgRef, EmDlgItemID, const EmDlgListIndexList&);
+ static void UnselectListItem (EmDlgRef, EmDlgItemID, EmDlgListIndex);
+ static void UnselectListItems (EmDlgRef, EmDlgItemID, const EmDlgListIndexList&);
+ static EmDlgListIndex GetSelectedItem (EmDlgRef, EmDlgItemID);
+ static void GetSelectedItems (EmDlgRef, EmDlgItemID, EmDlgListIndexList&);
+
+ static int GetTextHeight (EmDlgRef, EmDlgItemID, const string&);
+
+ static Bool StringToLong (const char*, long*);
+};
+
+#endif /* EmDlg_h */
diff --git a/SrcShared/EmDocument.cpp b/SrcShared/EmDocument.cpp
new file mode 100644
index 0000000..2dab9aa
--- /dev/null
+++ b/SrcShared/EmDocument.cpp
@@ -0,0 +1,1211 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDocument.h"
+
+#include "EmApplication.h" // SetDocument
+#include "EmCommands.h" // EmCommandID, kCommandSessionClose, etc.
+#include "EmPatchState.h" // EmPatchState::EvtGetEventCalled
+#include "EmRPC.h" // RPC::Idle
+#include "EmSession.h" // EmStopMethod
+#include "EmWindow.h" // EmWindow, gWindow
+#include "ErrorHandling.h" // Errors::ReportIfError
+#include "Hordes.h" // Hordes::PostLoad, Suspend, Step, Resume, Stop
+#include "Platform.h" // Platform::GetBoundDevice
+#include "SocketMessaging.h" // CSocket::IdleAll
+#include "Startup.h" // Startup::NewHorde
+#include "Strings.r.h" // kStr_CmdClose, etc.
+
+#if HAS_PROFILING
+#include "Profiling.h" // ProfileStart, ProfileStop, ProfileDump
+#endif
+
+EmDocument* gDocument;
+
+typedef void (EmDocument::*EmCommandFn)(EmCommandID);
+
+
+static const struct
+{
+ EmCommandID fCommandID;
+ EmCommandFn fFn;
+ StrCode fErrStrCode;
+}
+kCommand[] =
+{
+ { kCommandSessionSave, &EmDocument::DoSave, kStr_CmdSave },
+ { kCommandSessionSaveAs, &EmDocument::DoSaveAs, kStr_CmdSave },
+ { kCommandSessionBound, &EmDocument::DoSaveBound, kStr_CmdSaveBound },
+ { kCommandScreenSave, &EmDocument::DoSaveScreen, kStr_CmdSaveScreen },
+ { kCommandSessionInfo, &EmDocument::DoInfo, kStr_CmdSessionInfo },
+ { kCommandImportOther, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport0, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport1, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport2, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport3, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport4, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport5, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport6, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport7, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport8, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandImport9, &EmDocument::DoImport, kStr_CmdInstall },
+ { kCommandExport, &EmDocument::DoExport, kStr_CmdInstall },
+ { kCommandHotSync, &EmDocument::DoHotSync, kStr_CmdHotSync },
+ { kCommandReset, &EmDocument::DoReset, kStr_CmdReset },
+ { kCommandGremlinsNew, &EmDocument::DoGremlinNew, kStr_CmdGremlinNew },
+ { kCommandGremlinsSuspend, &EmDocument::DoGremlinSuspend, kStr_CmdGremlinSuspend },
+ { kCommandGremlinsStep, &EmDocument::DoGremlinStep, kStr_CmdGremlinStep },
+ { kCommandGremlinsResume, &EmDocument::DoGremlinResume, kStr_CmdGremlinResume },
+ { kCommandGremlinsStop, &EmDocument::DoGremlinStop, kStr_CmdGremlinStop }
+
+#if HAS_PROFILING
+ ,
+ { kCommandProfileStart, &EmDocument::DoProfileStart, kStr_CmdProfileStart },
+ { kCommandProfileStop, &EmDocument::DoProfileStop, kStr_CmdProfileStop },
+ { kCommandProfileDump, &EmDocument::DoProfileDump, kStr_CmdProfileDump }
+#endif
+};
+
+
+class EmActionNewHorde : public EmAction
+{
+ public:
+ EmActionNewHorde (const HordeInfo& info) :
+ EmAction (kStr_CmdGremlinNew),
+ fInfo (info)
+ {
+ }
+
+ virtual ~EmActionNewHorde (void)
+ {
+ }
+
+ virtual void Do (void)
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ Hordes::New (fInfo);
+ }
+
+ private:
+ HordeInfo fInfo;
+};
+
+
+class EmActionDialog : public EmAction
+{
+ public:
+ EmActionDialog (EmDlgThreadFn fn,
+ const void* parms,
+ EmDlgItemID& result) :
+ EmAction (0),
+ fDlgFn (fn),
+ fDlgParms (parms),
+ fDlgResult (result)
+ {
+ }
+
+ virtual ~EmActionDialog (void) {}
+
+ virtual void Do (void);
+
+ private:
+ EmDlgThreadFn fDlgFn;
+ const void* fDlgParms;
+ EmDlgItemID& fDlgResult;
+};
+
+
+void EmActionDialog::Do (void)
+{
+ // Show any error messages from the CPU thread.
+
+ fDlgResult = EmDlg::RunDialog (fDlgFn, fDlgParms);
+
+#if HAS_OMNI_THREAD
+ EmAssert (gSession);
+ gSession->UnblockDialog ();
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoNew
+// ---------------------------------------------------------------------------
+// Bottleneck for all document creation. Creates a new document, associates
+// it with the given application, creates a new window, creates a new session,
+// and sets last configuration and last session preferences accordingly.
+// On success, the new document is returned. On failure, an exception is
+// thrown.
+
+EmDocument* EmDocument::DoNew (const Configuration& cfg)
+{
+ // Create the new document.
+
+ EmDocument* doc = EmDocument::HostCreateDocument ();
+
+ try
+ {
+ // Create the new session.
+
+ doc->fSession = new EmSession;
+ doc->fSession->CreateNew (cfg);
+ doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession!
+
+ // Save the newly created configuration for next time.
+
+ {
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ pref = doc->fSession->GetConfiguration ();
+ }
+
+ // Zap the last-saved session file, so that we give preference
+ // to a New operation at startup and not an Open operation.
+
+ {
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ pref = EmFileRef();
+ }
+
+ // Set the ROM's file type, so that the icon looks right.
+
+ cfg.fROMFile.SetCreatorAndType (kFileCreatorEmulator, kFileTypeROM);
+ }
+ catch (...)
+ {
+ delete doc;
+ throw;
+ }
+
+ // If we got here, then everything worked. Open a window on the session.
+
+ doc->PrvOpenWindow ();
+
+ return doc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoOpen
+// ---------------------------------------------------------------------------
+// Bottleneck for all document opening. Creates a new document, associates
+// it with the given application, creates a new window, opens an old session,
+// and sets last configuration and last session preferences accordingly.
+// On success, the new document is returned. On failure, an exception is
+// thrown.
+
+EmDocument* EmDocument::DoOpen (const EmFileRef& file)
+{
+ // Create the new document.
+
+ Bool hordesIsOn = false;
+ EmDocument* doc = EmDocument::HostCreateDocument ();
+
+ try
+ {
+ // Open the old session.
+
+ doc->fSession = new EmSession;
+ doc->fFile = file; // !!! Actually, this is redundant with EmSession's.
+ doc->fSession->CreateOld (file);
+
+ // Get this here before we start up the thread. If we were to first
+ // start up the thread, it would proceed to run the Gremlin, which
+ // may temporarily turn off the "Gremlins is running" flag (see
+ // Hordes::SaveRootState), which would lead us to not open the
+ // Gremlin Control Window.
+
+ hordesIsOn = Hordes::IsOn ();
+
+ doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession!
+
+ // Patch up anything for Hordes.
+
+ Hordes::PostLoad ();
+
+ // Save the newly created configuration for next time.
+
+ {
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ pref = doc->fSession->GetConfiguration ();
+ }
+
+ // Save the last-opened session file for next time.
+
+ {
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ pref = file;
+ }
+
+ // Update the session MRU list.
+
+ gEmuPrefs->UpdateRAMMRU (file);
+ }
+ catch (...)
+ {
+ delete doc;
+ throw;
+ }
+
+ // If we got here, then everything worked. Open a window on the session.
+
+ doc->PrvOpenWindow ();
+
+ // If we loaded a session file with a Gremlin running, make sure
+ // the Gremlin control window is open. Do this after opening the
+ // LCD window so that the Gremlin window is properly a child window
+ // of the LCD window.
+
+ if (hordesIsOn)
+ {
+ EmDlg::GremlinControlOpen ();
+ }
+
+ return doc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoNewBound
+// ---------------------------------------------------------------------------
+
+EmDocument* EmDocument::DoNewBound (void)
+{
+ EmAssert (gApplication->IsBoundPartially ());
+
+ // Create the new document.
+
+ EmDocument* doc = EmDocument::HostCreateDocument ();
+
+ try
+ {
+ // Create the new session.
+
+ doc->fSession = new EmSession;
+ doc->fSession->CreateBound ();
+ doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession!
+ }
+ catch (...)
+ {
+ delete doc;
+ throw;
+ }
+
+ // If we got here, then everything worked. Open a window on the session.
+
+ doc->PrvOpenWindow ();
+
+ return doc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoOpenBound
+// ---------------------------------------------------------------------------
+
+EmDocument* EmDocument::DoOpenBound (void)
+{
+ EmAssert (gApplication->IsBoundFully ());
+
+ EmDocument* doc = EmDocument::HostCreateDocument ();
+
+ try
+ {
+ doc->fSession = new EmSession;
+ doc->fSession->CreateBound ();
+ doc->fSession->CreateThread (false); // !!! Created here, but destroyed in EmSession::~EmSession!
+ }
+ catch (...)
+ {
+ delete doc;
+ throw;
+ }
+
+ // If we got here, then everything worked. Open a window on the session.
+
+ doc->PrvOpenWindow ();
+
+ return doc;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::EmDocument
+// ---------------------------------------------------------------------------
+// Constructor. Set our data members to NULL, and set the global application
+// variable to point to us.
+
+EmDocument::EmDocument (void) :
+ EmActionHandler (),
+ fSession (NULL),
+ fFile ()
+{
+ EmAssert (gDocument == NULL);
+ gDocument = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::~EmDocument
+// ---------------------------------------------------------------------------
+// Destructor. Close the Gremlin Control window, disassociate us from the
+// application object, clear the global document variable, and delete the
+// session object.
+//
+// Note that we don't close the window object here. We defer that to any
+// document subclass in case it's not appropriate to close the window for
+// this platform (for instance, the window stays open on Unix).
+
+EmDocument::~EmDocument (void)
+{
+ EmDlg::GremlinControlClose ();
+
+ EmAssert (gDocument == this);
+ gDocument = NULL;
+
+ delete fSession;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleCommand
+// ---------------------------------------------------------------------------
+// Handle a user command. Normally the command is generated when the user
+// makes a menu selection, but the command could really come from anywhere
+// (for example, a toolbar with icon buttons, or from the dialog with the
+// New, Open, Download, and Quit pushbuttons in it).
+//
+// This method examines the command, synchronizes with the CPU thread as
+// necessary, executes the command, and catches any exceptions, showing them
+// in an error dialog.
+//
+// This function is an EXCEPTION_CATCH_POINT.
+
+Bool EmDocument::HandleCommand (EmCommandID commandID)
+{
+ // Find information on how this command should be handled.
+
+ size_t ii;
+ for (ii = 0; ii < countof (kCommand); ++ii)
+ {
+ if (kCommand[ii].fCommandID == commandID)
+ break;
+ }
+
+ // If we couldn't find an entry for this command, assume that it's not
+ // a command for the document, and return false indicating that we did
+ // not handle the command.
+
+ if (ii >= countof (kCommand))
+ {
+ return false; // We did not handle this command.
+ }
+
+ // Execute the command. Catch any exceptions and report them to the user.
+
+ if (kCommand[ii].fFn)
+ {
+ try
+ {
+ (this->*(kCommand[ii].fFn)) (commandID);
+ }
+ catch (ErrCode errCode)
+ {
+ StrCode operation = kCommand[ii].fErrStrCode;
+
+ Errors::ReportIfError (operation, errCode, 0, false);
+ }
+ }
+
+ return true; // We handled this command.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleKey
+// ---------------------------------------------------------------------------
+// Handle the user pressing a key on their keyboard.
+
+void EmDocument::HandleKey (const EmKeyEvent& event)
+{
+ EmAssert (fSession);
+
+ fSession->PostKeyEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleButton
+// ---------------------------------------------------------------------------
+// Handle the user pressing on a skin button with their mouse.
+
+void EmDocument::HandleButton (SkinElementType theButton, Bool isDown)
+{
+ EmAssert (fSession);
+
+ EmButtonEvent event (theButton, isDown);
+ fSession->PostButtonEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleIdle
+// ---------------------------------------------------------------------------
+// Perform any document-level idle time operations.
+
+void EmDocument::HandleIdle (void)
+{
+ // Idle our sockets.
+
+ CSocket::IdleAll ();
+
+ // Idle any packets that are looking for signals.
+ // That is, see if any have timed out by now.
+
+ RPC::Idle ();
+
+ // If we need to start a new Gremlin Horde, and the OS
+ // is now booted enough to handle our mucking about as
+ // we start it up, then start starting it up.
+
+ if (EmPatchState::EvtGetEventCalled ())
+ {
+ HordeInfo info;
+ if (Startup::NewHorde (&info))
+ {
+ this->ScheduleNewHorde (info);
+ }
+ }
+
+ // Pop off deferred actions and handle them.
+
+ this->DoAll ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleSave
+// ---------------------------------------------------------------------------
+// Perform a standard Save operation. If the document hasn't been saved
+// before, perform a "Save As" operation. Return whether or not the user
+// cancelled the operation. On failure, an exception is thrown.
+
+Bool EmDocument::HandleSave (void)
+{
+ if (!fFile.IsSpecified ())
+ {
+ return this->HandleSaveAs ();
+ }
+
+ return this->HandleSaveTo (fFile);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleSaveAs
+// ---------------------------------------------------------------------------
+// Perform a standard Save As operation, asking the user for a file name.
+// Return whether or not the user cancelled the operation. On failure,
+// an exception is thrown.
+
+Bool EmDocument::HandleSaveAs (void)
+{
+ EmFileRef destRef;
+
+ // Ask the user for a file to which to save the file.
+
+ if (this->AskSaveSession (destRef))
+ {
+ // If they did not cancel, save the file.
+
+ return this->HandleSaveTo (destRef);
+ }
+
+ // Return that we did not save the file.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleSaveTo
+// ---------------------------------------------------------------------------
+// Perform a save operation to the given file. The given file may or may not
+// already exist, but it must at least be specified. The user will NOT be
+// asked for a file name. On success, the "last session" preference and the
+// session MRU preference will be updated and this function will return true.
+// On failure, an exception is thrown.
+//
+// This is the bottleneck routine for all document saving. Note that this
+// is different from "session saving", which is a lower-level operation that
+// can occur while Gremlins is running.
+
+Bool EmDocument::HandleSaveTo (const EmFileRef& destRef)
+{
+ EmAssert (destRef.IsSpecified ());
+
+ // Suspend the session so that we can save its data.
+
+ EmSessionStopper stopper (fSession, kStopNow);
+
+ // Have the session save itself.
+
+ const Bool kUpdateFileRef = true;
+ fSession->Save (destRef, kUpdateFileRef);
+
+ // Remember that we are now associated with this file.
+
+ fFile = destRef;
+
+ // Save the last-saved session file for next time.
+
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ pref = destRef;
+
+ // Update the MRU menu.
+
+ gEmuPrefs->UpdateRAMMRU (destRef);
+
+ // Return that we saved the file.
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleClose
+// ---------------------------------------------------------------------------
+// Handle a request to close the document. Get the user's preference with
+// regards to saving the document before it's closed, and then call the
+// version of HandleClose that takes the CloseActionType parameter.
+//
+// NOTE: this method can "delete this", so be careful not to access it after
+// this method returns TRUE.
+
+Bool EmDocument::HandleClose (Bool quitting)
+{
+ Preference<CloseActionType> pref (kPrefKeyCloseAction);
+ return this->HandleClose (*pref, quitting);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HandleClose
+// ---------------------------------------------------------------------------
+// Handle a request to close the document. First, determine whether or not
+// to save the document, based either on preference or on querying the user.
+// Second, try to save the document if that's required. Third, if the
+// document was saved or the user didn't cancel the save operation, close
+// the document by deleting it. Finally, return whether or not the document
+// was closed.
+//
+// NOTE: this method can "delete this", so be careful not to access it after
+// this method returns TRUE.
+
+Bool EmDocument::HandleClose (CloseActionType closeAction, Bool quitting)
+{
+ EmDlgItemID answer;
+
+ // If we have to ask, then ask.
+
+ if (closeAction == kSaveAsk)
+ {
+ answer = this->AskSaveChanges (quitting);
+ }
+
+ // If we always save, then pretend we asked and the user said yes.
+
+ else if (closeAction == kSaveAlways)
+ {
+ answer = kDlgItemYes;
+ }
+
+ // If we never save, then pretend we asked and the user said no.
+
+ else // if (closeAction == kSaveNever)
+ {
+ answer = kDlgItemNo;
+ }
+
+ EmAssert (answer == kDlgItemYes || answer == kDlgItemNo || answer == kDlgItemCancel);
+
+ Bool closeIt = true;
+
+ // If we want to save the document, then save it. If the save
+ // succeeds, then set the flag to also close the document.
+
+ if (answer == kDlgItemYes)
+ {
+ closeIt = this->HandleSave ();
+ }
+
+ // We don't want to save the document, and we no longer want
+ // to close it, either.
+
+ else if (answer == kDlgItemCancel)
+ {
+ closeIt = false;
+ }
+
+ // We didn't want to save the document, but we want to close
+ // it anyway.
+
+ else // answer == kDlgItemNo
+ {
+ closeIt = true;
+ }
+
+ // Close the document by deleting it.
+
+ if (closeIt)
+ {
+ delete this;
+ }
+
+ // Return whether or not we closed the document. It may or may not
+ // have been saved -- we're not saying which way with this response.
+
+ return closeIt;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::ScheduleNewHorde
+// ---------------------------------------------------------------------------
+
+void EmDocument::ScheduleNewHorde (const HordeInfo& info)
+{
+ this->PostAction (new EmActionNewHorde (info));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::ScheduleDialog
+// ---------------------------------------------------------------------------
+
+void EmDocument::ScheduleDialog (EmDlgThreadFn fn,
+ const void* parms,
+ EmDlgItemID& result)
+{
+ this->PostAction (new EmActionDialog (fn, parms, result));
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoSave
+// ---------------------------------------------------------------------------
+// Handle the Save menu item.
+
+void EmDocument::DoSave (EmCommandID)
+{
+ this->HandleSave ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoSaveAs
+// ---------------------------------------------------------------------------
+// Handle the Save As menu item.
+
+void EmDocument::DoSaveAs (EmCommandID)
+{
+ this->HandleSaveAs ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoSaveBound
+// ---------------------------------------------------------------------------
+// Handle the Save Bound menu item.
+
+void EmDocument::DoSaveBound (EmCommandID)
+{
+ if (this->HostCanSaveBound ())
+ {
+ EmDlg::DoSaveBound ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoSaveScreen
+// ---------------------------------------------------------------------------
+// Handle the Save Screen menu item.
+
+void EmDocument::DoSaveScreen (EmCommandID)
+{
+ EmFileRef destRef;
+ if (this->AskSaveScreen (destRef))
+ {
+ this->HostSaveScreen (destRef);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoInfo
+// ---------------------------------------------------------------------------
+// Handle the Session Info menu item.
+
+void EmDocument::DoInfo (EmCommandID)
+{
+ EmDlg::DoSessionInfo ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoImport
+// ---------------------------------------------------------------------------
+// Handle the Install Application/Database menu items. We handle all menu
+// items in the sub-menu here.
+
+void EmDocument::DoImport (EmCommandID commandID)
+{
+ EmFileRefList fileList;
+
+ // Ask the user for files to install.
+
+ if (commandID == kCommandImportOther)
+ {
+ // If, when asking the user for a file to install, they press
+ // cancel, then just return right now.
+
+ if (!this->AskImportFiles (fileList))
+ {
+ return;
+ }
+ }
+
+ // Get a file to install from the MRU list.
+
+ else
+ {
+ int index = commandID - kCommandImport0;
+ EmFileRef importRef = gEmuPrefs->GetIndPRCMRU (index);
+
+ // If, for some reason, the returned file reference is not
+ // specified, then just silently return right now. If the
+ // file doesn't exist, we'll let DoDatabaseImport report it
+ // or throw an exception.
+
+ if (!importRef.IsSpecified ())
+ {
+ return;
+ }
+
+ // Put file in list.
+
+ fileList.push_back (importRef);
+ }
+
+ // Call the EmDlg routine that installs the file in tune with a
+ // progress dialog.
+
+ EmDlg::DoDatabaseImport (fileList, kMethodBest);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoExport
+// ---------------------------------------------------------------------------
+// Handle the Export Database menu item.
+
+void EmDocument::DoExport (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopOnSysCall);
+ EmDlg::DoDatabaseExport ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoHotSync
+// ---------------------------------------------------------------------------
+// Handle the HotSync menu item by simulating a press on the cradle button.
+
+void EmDocument::DoHotSync (EmCommandID)
+{
+ this->HandleButton (kElement_CradleButton, true);
+ this->HandleButton (kElement_CradleButton, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoReset
+// ---------------------------------------------------------------------------
+// Handle the Reset menu item.
+
+void EmDocument::DoReset (EmCommandID)
+{
+ EmResetType type;
+
+ if (EmDlg::DoReset (type) == kDlgItemOK)
+ {
+ EmSessionStopper stopper (fSession, kStopNow);
+ fSession->Reset (type);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoGremlinNew
+// ---------------------------------------------------------------------------
+// Handle the New Gremlin menu item.
+
+void EmDocument::DoGremlinNew (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopOnSysCall);
+ EmDlg::DoHordeNew ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoGremlinSuspend
+// ---------------------------------------------------------------------------
+// Handle the Suspend Gremlin menu item.
+
+void EmDocument::DoGremlinSuspend (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopOnSysCall);
+ Hordes::Suspend ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoGremlinStep
+// ---------------------------------------------------------------------------
+// Handle the Step Gremlin menu item.
+
+void EmDocument::DoGremlinStep (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopOnSysCall);
+ Hordes::Step ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoGremlinResume
+// ---------------------------------------------------------------------------
+// Handle the Resume Gremlin menu item.
+
+void EmDocument::DoGremlinResume (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopOnSysCall);
+ Hordes::Resume ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoGremlinStop
+// ---------------------------------------------------------------------------
+// Handle the Stop Gremlin menu item.
+
+void EmDocument::DoGremlinStop (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopNow);
+ Hordes::Stop ();
+}
+
+
+#if HAS_PROFILING
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoProfileStart
+// ---------------------------------------------------------------------------
+// Handle the Start Profile menu item.
+
+void EmDocument::DoProfileStart (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopNow);
+ ::ProfileStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoProfileStop
+// ---------------------------------------------------------------------------
+// Handle the Stop Profile menu item.
+
+void EmDocument::DoProfileStop (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopNow);
+ ::ProfileStop ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::DoProfileDump
+// ---------------------------------------------------------------------------
+// Handle the Dump Profile menu item.
+
+void EmDocument::DoProfileDump (EmCommandID)
+{
+ EmSessionStopper stopper (fSession, kStopNow);
+ ::ProfileDump (NULL);
+}
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskNewSession
+// ---------------------------------------------------------------------------
+// Ask the user for new session configuration information. If the user
+// cancels, return false. Otherwise, return true and store the new
+// configuration information in cfg. The cfg parameter is also used to
+// provide the initial settings in the dialog box.
+
+Bool EmDocument::AskNewSession (Configuration& cfg)
+{
+ EmAssert (!gApplication->IsBound ());
+
+ // Ask the user for new configuration information.
+
+ EmDlgItemID item = EmDlg::DoSessionNew (cfg);
+
+ // Return whether or not the user cancelled the operation.
+
+ return item == kDlgItemOK;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskSaveSession
+// ---------------------------------------------------------------------------
+// Ask the user for a file to which to save the document. If the user
+// cancels, return false. Otherwise, return true and store the specified
+// file name in "ref". The ref parameter also provides a default file name
+// if it is specified.
+
+Bool EmDocument::AskSaveSession (EmFileRef& ref)
+{
+ // Start by showing the user the directory in which they saved the
+ // last session file.
+
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ EmFileRef lastSession = *pref;
+
+ // Get other parameters used in presenting the dialog.
+
+ string prompt (Platform::GetString (kStr_SaveSessionAs));
+ EmDirRef defaultPath (lastSession.GetParent ());
+ EmFileTypeList filterList;
+ string defaultName (ref.GetName ());
+
+ filterList.push_back (kFileTypeSession);
+ filterList.push_back (kFileTypeAll);
+
+ // Ask the user for a file name.
+
+ EmDlgItemID item = EmDlg::DoPutFile (
+ ref, prompt, defaultPath, filterList, defaultName);
+
+ // Return whether or not the user cancelled the operation.
+
+ return item == kDlgItemOK;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskLoadSession
+// ---------------------------------------------------------------------------
+// Ask the user for a session document to load. If the user cancels, return
+// false. Otherwise, return true and store the specified file name in "ref".
+// The ref parameter also provides a default file name if it is specified.
+
+Bool EmDocument::AskLoadSession (EmFileRef& ref, EmFileType type)
+{
+ EmAssert (!gApplication->IsBoundFully ());
+
+ // Start by showing the user the directory in which they saved the
+ // last session file.
+
+ Preference<EmFileRef> pref (kPrefKeyLastPSF);
+ EmFileRef lastSession = *pref;
+
+ // Get other parameters used in presenting the dialog.
+
+ string prompt (Platform::GetString (kStr_LoadSession));
+ EmDirRef defaultPath (lastSession.GetParent ());
+ EmFileTypeList filterList;
+
+ filterList.push_back (type);
+ filterList.push_back (kFileTypeAll);
+
+ // Ask the user for a file name.
+
+ EmDlgItemID item = EmDlg::DoGetFile (
+ ref, prompt, defaultPath, filterList);
+
+ // Return whether or not the user cancelled the operation.
+
+ return item == kDlgItemOK;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskSaveChanges
+// ---------------------------------------------------------------------------
+// Ask the user if they want to save their changes to the session document.
+// If the document had been saved before, ask the user if they want to save
+// changes to the document with that name. Otherwise, ask them if they want
+// to save the "Untitled" document. Also, ask them if they'd like to save
+// the changes before "closing" or before "quitting". Return the user's
+// choice from the dialog: Yes, No, or Cancel.
+
+EmDlgItemID EmDocument::AskSaveChanges (Bool quitting)
+{
+ string name;
+
+ if (fFile.IsSpecified ())
+ {
+ name = fFile.GetName ();
+ }
+ else
+ {
+ // DoSessionSave provides the kStr_Untitled string
+ // if the given string is empty.
+ }
+
+ EmDlgItemID item = EmDlg::DoSessionSave (name, quitting);
+
+ EmAssert (item == kDlgItemYes || item == kDlgItemNo || item == kDlgItemCancel);
+
+ return item;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskSaveScreen
+// ---------------------------------------------------------------------------
+// Ask the user for a file to which they want to save the screen contents. If
+// the user cancels, return false. Otherwise, return true and store the
+// specified file name in "ref". The ref parameter also provides a default
+// file name if it is specified.
+
+Bool EmDocument::AskSaveScreen (EmFileRef& ref)
+{
+ // !!! Need to preserve the last directory to which a picture was
+ // saved so that we can restore it here.
+
+ // Get other parameters used in presenting the dialog.
+
+ string prompt (Platform::GetString (kStr_SaveScreenAs));
+ EmDirRef defaultPath;
+ EmFileTypeList filterList;
+ string defaultName;
+
+ filterList.push_back (kFileTypePicture);
+ filterList.push_back (kFileTypeAll);
+
+ // Ask the user for a file name.
+
+ EmDlgItemID item = EmDlg::DoPutFile (
+ ref, prompt, defaultPath, filterList, defaultName);
+
+ // Return whether or not the user cancelled the operation.
+
+ return item == kDlgItemOK;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::AskImportFiles
+// ---------------------------------------------------------------------------
+// Ask the user for files they want to import. If the user cancels, return
+// false. Otherwise, return true and store the specified file names in
+// "listRef".
+
+Bool EmDocument::AskImportFiles (EmFileRefList& listRef)
+{
+ // Get other parameters used in presenting the dialog.
+
+ string prompt (Platform::GetString (kStr_ImportFile));
+ EmDirRef defaultPath;
+ EmFileTypeList filterList;
+
+ filterList.push_back (kFileTypePalmApp);
+ filterList.push_back (kFileTypePalmDB);
+ filterList.push_back (kFileTypePalmQA);
+
+ // Start by showing the user the directory from which they
+ // last loaded a PRC/PDB/PQA file.
+
+ EmFileRef lastImport = gEmuPrefs->GetIndPRCMRU (0);
+ if (lastImport.IsSpecified ())
+ {
+ defaultPath = lastImport.GetParent ();
+ }
+
+ // Ask the user for file names.
+
+ EmDlgItemID item = EmDlg::DoGetFileList (
+ listRef, prompt, defaultPath, filterList);
+
+ // Return whether or not the user cancelled the operation.
+
+ return item == kDlgItemOK;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HostCanSaveBound
+// ---------------------------------------------------------------------------
+
+Bool EmDocument::HostCanSaveBound (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HostSaveScreen
+// ---------------------------------------------------------------------------
+
+void EmDocument::HostSaveScreen (const EmFileRef&)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::PrvOpenWindow
+// ---------------------------------------------------------------------------
+// Create the window for a new document.
+
+void EmDocument::PrvOpenWindow (void)
+{
+ if (gWindow == NULL)
+ {
+ EmWindow::NewWindow ();
+ }
+ else
+ {
+ // If the window is already open, then at least reset it so that
+ // it can get its new skin.
+
+ gWindow->WindowReset ();
+ }
+}
diff --git a/SrcShared/EmDocument.h b/SrcShared/EmDocument.h
new file mode 100644
index 0000000..c80a4de
--- /dev/null
+++ b/SrcShared/EmDocument.h
@@ -0,0 +1,188 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDocument_h
+#define EmDocument_h
+
+#include "EmAction.h" // EmAction
+#include "EmCommands.h" // EmCommandID
+#include "EmDlg.h" // EmDlgItemID
+#include "EmFileRef.h" // EmFileRef
+#include "Skins.h" // SkinElementType
+
+class EmApplication;
+class EmSession;
+class EmWindow;
+
+struct EmKeyEvent;
+
+/*
+ EmDocument is responsible for handling commands operations related to
+ an open and running document. It is responsible for the following:
+
+ * Creating new documents
+ * Loading old documents
+ * Saving documents (possibly asking for a (new) name).
+ * Closing documents
+ * Handling document-specific commands:
+ * Save
+ * Save As
+ * Save Bound
+ * Save Screen
+ * Session Info
+ * Import Database
+ * Export Database
+ * HotSync
+ * Reset
+ * Undo/Cut/Copy/Paste/Clear
+ * Gremlins (New/Stop/Resume/Step)
+ * Profiling (Start/Stop/Dump)
+ * Migrating key and buttons events.
+
+ EmDocument is mostly a cross-platform "code sharing" class. It's
+ not a true document class in that it doesn't deal with getting
+ user events, menu selections, or other platform-specific operations.
+ But once those events and selections are made, the EmDocument
+ class can be used to *handle* those operations in a cross-platofrm
+ way. Thus, you will most likely create a sub-class of EmDocument
+ that deals with user interaction and translate those into cross-
+ platform operations.
+
+ EmDocument is owned by the EmApplication. In turn, EmDocument owns
+ the EmWindow in which it displays its stuff.
+*/
+
+
+class EmDocument : public EmActionHandler
+{
+ public:
+ /*
+ Bottlenecks for creating and opening documents.
+ */
+ static EmDocument* DoNew (const Configuration&);
+ static EmDocument* DoOpen (const EmFileRef&);
+
+ static EmDocument* DoNewBound (void);
+ static EmDocument* DoOpenBound (void);
+
+ protected:
+ EmDocument (void);
+ virtual ~EmDocument (void);
+
+ public:
+ Bool HandleCommand (EmCommandID);
+ void HandleKey (const EmKeyEvent&);
+ void HandleButton (SkinElementType, Bool isDown);
+ virtual void HandleIdle (void);
+
+ public:
+ EmSession* GetSession (void) const { return fSession; }
+ EmFileRef GetFileRef (void) const { return fFile; }
+
+ public:
+ /*
+ This ramp of functions is responsible for saving sessions.
+ They all return a Boolean indicating whether or not the
+ session was actually saved. On failure, they throw exceptions.
+
+ HandleSave Standard Save operation. If the document has
+ been saved before, calls through to HandleSaveTo.
+ Otherwise, calls through to HandleSaveAs.
+
+ HandleSaveAs Standard Save As operation. Asks the user for a
+ file to which to save the document. If the user
+ doesn't cancel, call through to HandleSaveTo.
+
+ HandleSaveTo Bottleneck for all save operations. Assumes the
+ given file reference is valid; the file may or
+ may not already exist. On success, the document
+ remembers that it is associated with the file it
+ just saved itself to and updates the "last session"
+ and "session MRU" preferences.
+ */
+
+ Bool HandleSave (void);
+ Bool HandleSaveAs (void);
+ Bool HandleSaveTo (const EmFileRef&);
+
+ Bool HandleClose (Bool quitting); // Deletes self!
+ Bool HandleClose (CloseActionType, Bool quitting); // Deletes self!
+
+ public:
+ // The following functions schedule actions for the document
+ // to take the next chance it gets (at idle time).
+
+ void ScheduleNewHorde (const HordeInfo&);
+ void ScheduleDialog (EmDlgThreadFn fn,
+ const void* parms,
+ EmDlgItemID& result);
+
+ public:
+ // Command handling functions, called from HandleCommand.
+ //
+ // I'd like these to be private, but I build up a static table containing
+ // references to these functions, thus requiring them to be public.
+ void DoSave (EmCommandID);
+ void DoSaveAs (EmCommandID);
+ void DoSaveBound (EmCommandID);
+ void DoSaveScreen (EmCommandID);
+ void DoInfo (EmCommandID);
+ void DoImport (EmCommandID);
+ void DoExport (EmCommandID);
+ void DoHotSync (EmCommandID);
+ void DoReset (EmCommandID);
+
+ void DoGremlinNew (EmCommandID);
+ void DoGremlinSuspend (EmCommandID);
+ void DoGremlinStep (EmCommandID);
+ void DoGremlinResume (EmCommandID);
+ void DoGremlinStop (EmCommandID);
+
+#if HAS_PROFILING
+ void DoProfileStart (EmCommandID);
+ void DoProfileStop (EmCommandID);
+ void DoProfileDump (EmCommandID);
+#endif
+
+ public:
+ // I'd like these to be private, but they are currently needed
+ // by the "What To Do" dialog.
+ static Bool AskNewSession (Configuration&);
+ static Bool AskSaveSession (EmFileRef&);
+ static Bool AskLoadSession (EmFileRef&, EmFileType);
+
+ public:
+ // I'd like these to be private, but CEmulatorDoc::AskSaveChanges
+ // needs access to AskSaveChanges.
+ EmDlgItemID AskSaveChanges (Bool quitting);
+ Bool AskSaveScreen (EmFileRef&);
+ Bool AskImportFiles (EmFileRefList&);
+
+ public:
+ // I'd like these to be private, but at least one part of Poser
+ // needs access to HostSaveScreen.
+ static EmDocument* HostCreateDocument (void);
+ virtual Bool HostCanSaveBound (void);
+ virtual void HostSaveScreen (const EmFileRef&);
+
+ private:
+ void PrvOpenWindow (void);
+
+ protected:
+ EmSession* fSession;
+ EmFileRef fFile;
+};
+
+extern EmDocument* gDocument;
+
+#endif // EmDocument_h
diff --git a/SrcShared/EmErrCodes.h b/SrcShared/EmErrCodes.h
new file mode 100644
index 0000000..1cc6a23
--- /dev/null
+++ b/SrcShared/EmErrCodes.h
@@ -0,0 +1,117 @@
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmErrCodes_h
+#define EmErrCodes_h
+
+#include "EmTypes.h" // ErrCode
+
+// Platform-independent errors numbers that can be thrown from
+// platform-independent code. These numbers ideally should not
+// collide with platform-specific error codes. Mac error codes
+// are 16-bit negative numbers, so take the range 0...-32768.
+// Windows error codes are generally in the range 0...<big positive number>.
+// Palm OS error codes are 16-bit positive numbers, so are
+// in the range 0...32767. Thus, Mac and Windows errors don't
+// collide. Palm OS error codes collide with Windows, so we
+// shift them down into the range 0xFFFBxxxx, where xxxx is the
+// Palm OS error code. Finally, we have our own Emulator-specific
+// error codes. Those we'll keep in 0xFFFDxxxx.
+
+const ErrCode kError_NoError = 0;
+const ErrCode kError_EmuErrBase = 0xFFFE0000; // arbitrary value
+const ErrCode kError_EmuErrRange = 0x00010000; // arbitrary value
+
+const ErrCode kError_OutOfMemory = kError_EmuErrBase + 1;
+
+const ErrCode kError_BadROM = kError_EmuErrBase + 2;
+const ErrCode kError_WrongROMForType = kError_EmuErrBase + 3;
+const ErrCode kError_UnsupportedROM = kError_EmuErrBase + 4;
+const ErrCode kError_InvalidDevice = kError_EmuErrBase + 5;
+const ErrCode kError_InvalidSessionFile = kError_EmuErrBase + 6;
+const ErrCode kError_InvalidConfiguration = kError_EmuErrBase + 7;
+
+const ErrCode kError_CantDownloadROM_BadBaudRate = kError_EmuErrBase + 10;
+const ErrCode kError_CantDownloadROM_SerialPortBusy = kError_EmuErrBase + 11;
+const ErrCode kError_CantDownloadROM_Generic = kError_EmuErrBase + 12;
+
+const ErrCode kError_UnimplementedTrap = kError_EmuErrBase + 13;
+const ErrCode kError_InvalidLibraryRefNum = kError_EmuErrBase + 14;
+
+const ErrCode kError_CommOpen = kError_EmuErrBase + 15;
+const ErrCode kError_CommNotOpen = kError_EmuErrBase + 16;
+const ErrCode kError_CantOpenPort = kError_EmuErrBase + 17;
+const ErrCode kError_InvalidPort = kError_EmuErrBase + 18;
+const ErrCode kError_CantFindSerialPort = kError_EmuErrBase + 19;
+
+const ErrCode kError_OnlySameType = kError_EmuErrBase + 20;
+const ErrCode kError_OnlyOnePSF = kError_EmuErrBase + 21;
+const ErrCode kError_OnlyOneROM = kError_EmuErrBase + 22;
+const ErrCode kError_UnknownType = kError_EmuErrBase + 23;
+
+const ErrCode kError_BadDB_NameNotNULLTerminated = kError_EmuErrBase + 30;
+const ErrCode kError_BadDB_NameNotPrintable = kError_EmuErrBase + 31;
+const ErrCode kError_BadDB_FileTooSmall = kError_EmuErrBase + 32;
+const ErrCode kError_BadDB_nextRecordListIDNonZero = kError_EmuErrBase + 33;
+const ErrCode kError_BadDB_ResourceTooSmall = kError_EmuErrBase + 34;
+const ErrCode kError_BadDB_RecordTooSmall = kError_EmuErrBase + 35;
+const ErrCode kError_BadDB_ResourceOutOfRange = kError_EmuErrBase + 36;
+const ErrCode kError_BadDB_RecordOutOfRange = kError_EmuErrBase + 37;
+const ErrCode kError_BadDB_OverlappingResource = kError_EmuErrBase + 38;
+const ErrCode kError_BadDB_OverlappingRecord = kError_EmuErrBase + 39;
+const ErrCode kError_BadDB_ResourceMemError = kError_EmuErrBase + 40;
+const ErrCode kError_BadDB_RecordMemError = kError_EmuErrBase + 41;
+const ErrCode kError_BadDB_AppInfoMemError = kError_EmuErrBase + 42;
+const ErrCode kError_BadDB_DuplicateResource = kError_EmuErrBase + 43;
+
+const ErrCode kError_CorruptedHeap_ChunkNotInHeap = kError_EmuErrBase + 50;
+const ErrCode kError_CorruptedHeap_ChunkTooLarge = kError_EmuErrBase + 51;
+const ErrCode kError_CorruptedHeap_InvalidFlags = kError_EmuErrBase + 52;
+const ErrCode kError_CorruptedHeap_HOffsetNotInMPT = kError_EmuErrBase + 53;
+const ErrCode kError_CorruptedHeap_HOffsetNotBackPointing = kError_EmuErrBase + 54;
+const ErrCode kError_CorruptedHeap_InvalidLockCount = kError_EmuErrBase + 55;
+
+
+const ErrCode kError_PalmOSErrBase = 0xFFFC0000; // arbitrary value
+const ErrCode kError_PalmOSErrRange = (1 << (sizeof (Err) * 8));
+
+const ErrCode kError_StdCErrBase = 0xFFFA0000; // arbitrary value
+const ErrCode kError_StdCErrRange = 0x00010000; // arbitrary range
+
+
+inline ErrCode ConvertFromStdCError (int err)
+ { return (ErrCode) err ? (err + kError_StdCErrBase) : err; }
+
+inline int ConvertToStdCError (ErrCode err)
+ { return (int) err ? (err - kError_StdCErrBase) : err; }
+
+
+inline ErrCode ConvertFromPalmError (Err err)
+ { return (ErrCode) err ? (err + kError_PalmOSErrBase) : err; }
+
+inline Err ConvertToPalmError (ErrCode err)
+ { return (Err) err ? (err - kError_PalmOSErrBase) : err; }
+
+
+inline Bool IsStdCError (ErrCode err)
+ { return err >= kError_StdCErrBase && err < kError_StdCErrBase + kError_StdCErrRange; }
+
+inline Bool IsPalmError (ErrCode err)
+ { return err >= kError_PalmOSErrBase && err < kError_PalmOSErrBase + kError_PalmOSErrRange; }
+
+inline Bool IsEmuError (ErrCode err)
+ { return err >= kError_EmuErrBase && err < kError_EmuErrBase + kError_EmuErrRange; }
+
+inline Bool IsPlatformError (ErrCode err)
+ { return !::IsPalmError (err) && !::IsStdCError (err) && !::IsEmuError (err); }
+
+#endif // EmErrCodes_h
diff --git a/SrcShared/EmEventOutput.cpp b/SrcShared/EmEventOutput.cpp
new file mode 100644
index 0000000..b173321
--- /dev/null
+++ b/SrcShared/EmEventOutput.cpp
@@ -0,0 +1,2012 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmEventOutput.h"
+
+#include "EmMemory.h" // EmMem_strcpy
+#include "EmPalmOS.h" // GenerateStackCrawl
+#include "EmPalmStructs.h" // EmAliasControlType
+#include "EmPatchState.h" // EmPatchState::GetCurrentAppInfo
+#include "EmSession.h" // gSession
+#include "ErrorHandling.h" // Errors::GetAppName, GetAppVersion
+#include "Miscellaneous.h" // StackCrawlStrings
+#include "PreferenceMgr.h" // Preference, gEmuPrefs
+#include "ROMStubs.h" // FtrGet
+
+
+// Special rank positions:
+
+#define kObjectRank_None -2
+#define kObjectRank_Last -1
+
+// PalmOS table font:
+
+#define tableFont boldFont
+
+// WindowFlagsType modal flag bit:
+
+#define WindowTypeFlags_modal 0x2000
+
+// Useful macros:
+
+static inline Bool PrvIsPenEvent (const EmRecordedEvent& event)
+{
+ return event.eType == kRecordedPenEvent;
+}
+
+static inline Bool PrvIsPenUp (const PointType& pt)
+{
+ return pt.x == -1 && pt.y == -1;
+}
+
+static inline Bool PrvIsPenDown (const PointType& pt)
+{
+ return !::PrvIsPenUp (pt);
+}
+
+static inline Bool PrvIsPenUp (const EmRecordedEvent& event)
+{
+ return ::PrvIsPenEvent (event) && ::PrvIsPenUp (event.penEvent.coords);
+}
+
+static inline Bool PrvIsPenDown (const EmRecordedEvent& event)
+{
+ return ::PrvIsPenEvent (event) && ::PrvIsPenDown (event.penEvent.coords);
+}
+
+
+#define POINT_IN_RECT(X,Y,R) (X >= R.topLeft.x && \
+ Y >= R.topLeft.y && \
+ X <= R.topLeft.x + R.extent.x && \
+ Y <= R.topLeft.y + R.extent.y)
+
+#define IS_EXTENDED(chrcode) (chrcode >= 0x0080 && chrcode <= 0x00FF)
+
+
+// Global state variables:
+
+EmEventInfoList EmEventOutput::fgEventInfo;
+Bool EmEventOutput::fgIsGatheringInfo;
+int EmEventOutput::fgCounter;
+UInt16 EmEventOutput::fgPreviousFormID;
+Bool EmEventOutput::fgEventAwaitingInfo; // Set if tapped on field or list; cleared when we get the awaited information.
+Bool EmEventOutput::fgWaitForPenUp;
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::StartGatheringInfo
+ *
+ * DESCRIPTION: Reset our state in preparation to start gathering info.
+ * This should be called each time we start replaying an
+ * event list.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::StartGatheringInfo (void)
+{
+ fgEventInfo.clear ();
+ fgCounter = 0;
+ fgPreviousFormID = 0;
+ fgEventAwaitingInfo = false;
+ fgWaitForPenUp = false;
+
+ EmEventOutput::GatherInfo (true);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::IsGatheringInfo
+ *
+ * DESCRIPTION: Return whether or not we are currently gathering information.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if we are currently gathering info.
+ *
+ ***********************************************************************/
+
+Bool EmEventOutput::IsGatheringInfo (void)
+{
+ return fgIsGatheringInfo;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::GatherInfo
+ *
+ * DESCRIPTION: Turn information gathering on or off.
+ *
+ * PARAMETERS: gatherInfo - whether or not we're turning on
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::GatherInfo (Bool gatherInfo)
+{
+ fgIsGatheringInfo = gatherInfo;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetStringFromEmuMemory
+ *
+ * DESCRIPTION: Retrieve a string from emulator memory and store it in
+ * a string object.
+ *
+ * PARAMETERS: emustr - pointer to the string in emulator memory
+ *
+ * RETURNED: The string object.
+ *
+ ***********************************************************************/
+
+static string PrvGetStringFromEmuMemory (emuptr emustr)
+{
+ string str;
+
+ if (!emustr)
+ return str;
+
+ size_t len = EmMem_strlen (emustr);
+
+ if (len)
+ {
+ char* temp = new char [len + 1];
+
+ if (temp == NULL)
+ {
+ // Failed to allocate space for temporary buffer.
+ return str;
+ }
+
+ EmMem_strcpy (temp, emustr);
+
+ str = temp;
+
+ delete [] temp;
+ }
+
+ return str;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvClearEventData
+ *
+ * DESCRIPTION: Clear out information gathered and stored in an event
+ * without disturbing the event itself.
+ *
+ * PARAMETERS: event - event to clear
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+static void PrvClearEventData (EmEventInfo& eventInfo)
+{
+ eventInfo.text.empty ();
+ eventInfo.newFormText.empty ();
+ eventInfo.stackCrawl.clear ();
+
+ eventInfo.objKind = (FormObjectKind) -1;
+ eventInfo.objID = 0;
+ eventInfo.rank = kObjectRank_None;
+ eventInfo.row = -1;
+ eventInfo.column = -1;
+ eventInfo.style = (ControlStyleType) -1;
+
+ eventInfo.asciiCode = 0;
+ eventInfo.keyCode = 0;
+ eventInfo.modifiers = 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::GetEventInfo
+ *
+ * DESCRIPTION: Master function for retrieving information from the
+ * emulator related to gremlin events being posted.
+ *
+ * PARAMETERS: event - the current event being replayed.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::GetEventInfo (const EmRecordedEvent& event)
+{
+ if (!fgIsGatheringInfo)
+ return;
+
+ CEnableFullAccess munge; // Direct access to form.window.windowFlags.flags.
+
+ // Clear current event data.
+
+ EmEventInfo eventInfo;
+ ::PrvClearEventData (eventInfo);
+
+ eventInfo.event = event;
+
+ // Get the active form and form id.
+ // This may be incorrect for popup dialogs.
+
+ FormType* frmP = ::FrmGetActiveForm ();
+
+ UInt16 currentFormID = 0;
+
+ if (frmP)
+ {
+ currentFormID = ::FrmGetFormId (frmP);
+ }
+
+ // If the active form has changed since last event:
+
+ if ((currentFormID != fgPreviousFormID) && currentFormID)
+ {
+ // Cancel the event awaiting info, because it is no longer possible to get info.
+
+ fgEventAwaitingInfo = false;
+
+ if (currentFormID)
+ {
+ // If there was a previous event, associate the form change with it.
+
+ if (fgEventInfo.size () > 0)
+ {
+ EmEventInfo& prevEvent = fgEventInfo.back ();
+
+ EmAliasFormType<PAS> form ((emuptr) frmP);
+
+ // Get the new form's title.
+
+ emuptr emuTitle = (emuptr)::FrmGetTitle (frmP);
+
+ if (emuTitle)
+ {
+ string title = ::PrvGetStringFromEmuMemory (emuTitle);
+
+ if (!title.empty ())
+ {
+ if (form.window.windowFlags.flags & WindowTypeFlags_modal)
+ {
+ prevEvent.newFormText = string("open the \"") + title + string("\" dialog");
+ }
+ else
+ {
+ prevEvent.newFormText = string("go to the \"") + title + string("\" view");
+ }
+ }
+ }
+
+ // If there is no title:
+
+ if (prevEvent.newFormText.empty ())
+ {
+ if (form.window.windowFlags.flags & WindowTypeFlags_modal)
+ {
+ prevEvent.newFormText = "go to a new dialog";
+ }
+ else
+ {
+ prevEvent.newFormText += "go to a new view";
+ }
+ }
+ }
+ }
+ }
+
+ // A previous pen down event may have set the fgEventAwaitingInfo flag.
+ // This flag means that we want to scope out the state of the system
+ // later to find out what the pen event caused to happen. We gather
+ // that information on the next event after the ensuing pen up event.
+ //
+ // This will not work 100% of the time, because the event's target object
+ // may have disappeared, the active form may have changed, or the
+ // application may have done something to the object.
+
+ if (fgEventAwaitingInfo)
+ {
+ // If we're waiting for a pen-up event, see if we found it.
+
+ if (fgWaitForPenUp)
+ {
+ if (::PrvIsPenUp (eventInfo.event))
+ {
+ fgWaitForPenUp = false;
+ }
+ }
+ else
+ {
+ EmEventOutput::GetAwaitedEventInfo ();
+
+ fgEventAwaitingInfo = false;
+ }
+ }
+
+ // Get information about current event.
+ // Skip pen up events.
+
+ if (!::PrvIsPenUp (eventInfo.event))
+ {
+ switch (eventInfo.event.eType)
+ {
+ case kRecordedPenEvent:
+
+ EmEventOutput::GetPenEventInfo (eventInfo);
+
+ break;
+
+ case kRecordedAppSwitchEvent:
+
+ EmEventOutput::GetAppSwitchEventInfo (eventInfo);
+
+ break;
+
+ default:
+
+ break;
+ }
+ }
+
+ fgPreviousFormID = currentFormID;
+
+ // For some reason, I sometimes see *two* sets of instructions
+ // in the output -- one a duplicate of the other. However, they
+ // are all number consecutively, which implies that OutputEvents
+ // is called just once, and that the doubling effect is because
+ // two sets of events are in fgEventInfo. Put a check here to
+ // see if that's the case.
+
+ if (fgEventInfo.size () > 0)
+ {
+ EmAssert (fgEventInfo.back ().event.eType != kRecordedErrorEvent);
+ }
+
+ fgEventInfo.push_back (eventInfo);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::PoppingUpForm
+ *
+ * DESCRIPTION: Called by the FrmPopupForm headpatch to tell us that
+ * the application is popping up a dialog.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::PoppingUpForm (void)
+{
+ if (!fgIsGatheringInfo)
+ return;
+
+ // If there was a previous event, associate the form change with it.
+
+ if (fgEventInfo.size () > 0)
+ {
+ fgEventInfo.back ().newFormText = "popup a dialog";
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::ErrorOccurred
+ *
+ * DESCRIPTION: Called by Errors::HandleDialog to tell us the text of
+ * the error that occurred.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::ErrorOccurred (const string& msg)
+{
+ if (!fgIsGatheringInfo)
+ return;
+
+ // Create a new event recording the information.
+
+ EmEventInfo eventInfo;
+
+ eventInfo.event.eType = kRecordedErrorEvent;
+ eventInfo.text = msg;
+
+ // Capture the stack crawl.
+
+ EmStackFrameList stackCrawl;
+ EmPalmOS::GenerateStackCrawl (stackCrawl);
+
+ // Generate a full stack crawl.
+
+ ::StackCrawlStrings (stackCrawl, eventInfo.stackCrawl);
+
+ // Save this information at the end of our collection.
+
+ fgEventInfo.push_back (eventInfo);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvObjectIsHigherRank
+ *
+ * DESCRIPTION: Determine if an object is ranked higher inside a form
+ * than another object. Ranking is top to bottom, then
+ * left to right.
+ *
+ * PARAMETERS: r1 - bounds of object in question
+ *
+ * r2 - bounds of object we're comparing to
+ *
+ * RETURNED: True if object (r1) is higher-ranked.
+ *
+ ***********************************************************************/
+
+static Bool PrvObjectIsHigherRank (RectangleType& r1, RectangleType& r2)
+{
+ if (r2.topLeft.y < r1.topLeft.y)
+ return true;
+
+ if (r2.topLeft.y == r1.topLeft.y)
+ {
+ if (r2.topLeft.x < r1.topLeft.x)
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFindObjectRank
+ *
+ * DESCRIPTION: Find the rank number of an object inside a form.
+ *
+ * PARAMETERS: frmP - pointer to form containing the object
+ *
+ * objectIndices - vector array of object indexes in form
+ *
+ * object1 - index of the object to rank
+ *
+ * RETURNED: Rank value of the object.
+ *
+ ***********************************************************************/
+
+static int16 PrvFindObjectRank (FormPtr frmP, vector<uint16>& objectIndices, uint16 object1)
+{
+ EmAssert (frmP);
+
+ RectangleType r1;
+ ::FrmGetObjectBounds (frmP, object1, &r1);
+
+ FormObjectKind objectKind1 = ::FrmGetObjectType (frmP, object1);
+
+ int rank = 0;
+ uint16 siblingCount = 0;
+
+ vector<uint16>::iterator iter = objectIndices.begin ();
+
+ while (iter != objectIndices.end ())
+ {
+ // Make sure object is not ourself
+
+ if (*iter != object1)
+ {
+ // Make sure object is the same kind
+
+ FormObjectKind objectKind2 = ::FrmGetObjectType (frmP, *iter);
+
+ if (objectKind2 == objectKind1)
+ {
+ siblingCount++;
+
+ RectangleType r2;
+ ::FrmGetObjectBounds (frmP, *iter, &r2);
+
+ if (::PrvObjectIsHigherRank (r1, r2))
+ rank++;
+ }
+ }
+
+ ++iter;
+ }
+
+ // No ranking if we are all alone.
+
+ if (siblingCount == 0)
+ return kObjectRank_None;
+
+ // Special case for the last object in the form.
+
+ else if (rank == siblingCount)
+ return kObjectRank_Last;
+
+ // Else just use the rank number.
+
+ return rank;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPointInTableItem
+ *
+ * DESCRIPTION: This routine computes which row, column a point is in.
+ * It was adapted from the function 'PointInTableItem' in
+ * UI/src/Table.cpp by art and peter.
+ *
+ * PARAMETERS: tableP - pointer to a table object
+ *
+ * x - point's x coordinate
+ *
+ * y - point's y coordinate
+ *
+ * rrow - return the row
+ *
+ * rcol - return the column
+ *
+ * RETURNED: True if the point is in at item.
+ *
+ ***********************************************************************/
+
+static Boolean PrvPointInTableItem (TableType* tableP, Coord x, Coord y, Int16& rrow, Int16& rcol)
+{
+ EmAssert (tableP);
+
+ CEnableFullAccess munge;
+
+ Int16 row, col;
+ Int16 numRows, numCols;
+ RectangleType r;
+
+ EmAliasTableType<PAS> table ((emuptr)tableP);
+
+ RectangleType bounds;
+ bounds.topLeft.x = table.bounds.topLeft.x;
+ bounds.topLeft.y = table.bounds.topLeft.y;
+ bounds.extent.x = table.bounds.extent.x;
+ bounds.extent.y = table.bounds.extent.y;
+
+ if (!POINT_IN_RECT(x, y, bounds))
+ return false;
+
+ r.topLeft.x = table.bounds.topLeft.x;
+ r.topLeft.y = table.bounds.topLeft.y;
+
+ numRows = table.numRows;
+ for (row = table.topRow; row < numRows; row++)
+ {
+ // Is the point within the bounds of the row.
+
+ r.extent.x = table.bounds.extent.x;
+ r.extent.y = ::TblGetRowHeight (tableP, row);
+
+ if (POINT_IN_RECT(x, y, r))
+ {
+ numCols = table.numColumns;
+ for (col = 0; col < numCols; col++)
+ {
+ // Is the point within the bounds of the column
+
+ r.extent.x = ::TblGetColumnWidth (tableP, col);
+ r.extent.y = ::TblGetRowHeight (tableP, row);
+
+ if (POINT_IN_RECT(x, y, r))
+ {
+ rrow = row;
+ rcol = col;
+ return true;
+ }
+
+ // Move to the next column.
+
+ r.topLeft.x += r.extent.x + ::TblGetColumnSpacing (tableP, col);
+ }
+
+ // We were in a useable row, but we were not in any of the columns.
+
+ return false;
+ }
+
+ // Move to next row.
+
+ r.topLeft.x = table.bounds.topLeft.x;
+ r.topLeft.y += ::TblGetRowHeight (tableP, row);
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::GetPenEventInfo
+ *
+ * DESCRIPTION: Get information about the current pen event. EventAwaitingInfo
+ * is set for events that need to retrieve info a little later.
+ *
+ * PARAMETERS: event - the current event being replayed
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::GetPenEventInfo (EmEventInfo& eventInfo)
+{
+ EmAssert (eventInfo.event.eType == kRecordedPenEvent);
+ EmAssert (fgIsGatheringInfo);
+
+ CEnableFullAccess munge;
+
+ // Get the pen location in display coordinates.
+
+ EmPoint displayPt (eventInfo.event.penEvent.coords);
+ Int16 displayX = displayPt.fX;
+ Int16 displayY = displayPt.fY;
+
+ EmPoint localPt = displayPt;
+ Int16 localX = displayX;
+ Int16 localY = displayY;
+
+ // Get the active form.
+
+ FormPtr frmP = ::FrmGetActiveForm ();
+
+ // Get the objects in that form.
+
+ vector<uint16> objectIndices;
+ ::CollectOKObjects (frmP, objectIndices);
+
+ // Convert the pen location to local form coordinates.
+
+ if (frmP)
+ {
+ WinHandle oldDrawWin = ::WinSetDrawWindow (::FrmGetWindowHandle (frmP));
+ ::WinDisplayToWindowPt (&localX, &localY);
+ ::WinSetDrawWindow (oldDrawWin);
+
+ localPt = EmPoint (localX, localY);
+ }
+
+ // Iterate over the objects, finding one we hit.
+
+ vector<uint16>::iterator iter = objectIndices.begin ();
+
+ while (iter != objectIndices.end ())
+ {
+ RectangleType r;
+ ::FrmGetObjectBounds (frmP, *iter, &r);
+
+ EmRect bounds (r);
+
+ // Must expand bounds a little to match what PalmOS detects as tapping inside an object.
+
+ bounds.fBottom += 2;
+ bounds.fRight += 2;
+
+ if (bounds.Contains (localPt))
+ {
+ break;
+ }
+
+ ++iter;
+ };
+
+ // If we found a hit on a form object...
+
+ if (iter != objectIndices.end ())
+ {
+ eventInfo.objID = *iter;
+
+ // Get its type.
+
+ eventInfo.objKind = ::FrmGetObjectType (frmP, *iter);
+
+ // Get its rank.
+
+ eventInfo.rank = ::PrvFindObjectRank (frmP, objectIndices, *iter);
+
+ // Get special info for object type.
+
+ switch (eventInfo.objKind)
+ {
+ case frmFieldObj:
+ {
+ // Set up to retrieve info during the next event.
+
+ eventInfo.text.empty ();
+ fgEventAwaitingInfo = true;
+ fgWaitForPenUp = false;
+
+ break;
+ }
+
+ case frmControlObj:
+ {
+ emuptr ctlP = (emuptr) ::FrmGetObjectPtr (frmP, *iter);
+
+ if (ctlP)
+ {
+ EmAliasControlType<PAS> control (ctlP);
+
+ // Store control style.
+
+ eventInfo.style = control.style;
+
+ // Store text label if it exists.
+
+ eventInfo.text = ::PrvGetStringFromEmuMemory (control.text);
+
+ if (!eventInfo.text.empty ())
+ {
+ // Check if label is unique. If so, no need for rank.
+
+ eventInfo.rank = kObjectRank_None;
+
+ // TODO: Else rank it amongst peers with same label.
+ }
+ }
+
+ break;
+ }
+
+ case frmListObj:
+ {
+ // Set up to retrieve info during the next event.
+
+ eventInfo.text.empty ();
+ eventInfo.row = -1;
+ fgEventAwaitingInfo = true;
+ fgWaitForPenUp = true;
+
+ break;
+ }
+
+ case frmTableObj:
+ {
+ TableType* tableP = (TableType*)::FrmGetObjectPtr (frmP, *iter);
+
+ if (tableP)
+ {
+ ::PrvPointInTableItem (tableP, localX, localY,
+ eventInfo.row, eventInfo.column);
+ }
+
+ break;
+ }
+
+ case frmLabelObj:
+
+// my ($label_id) = FrmGetObjectId ($form, $ii);
+// my ($address, $label) = FrmGetLabel($form, $label_id);
+// $line .= " \"$label\"";
+
+// event.text = "labeltext";
+ break;
+
+ case frmTitleObj:
+
+// my ($address, $title) = FrmGetTitle($form,);
+// $line .= " \"$title\"";
+
+// event.text = "titletext";
+ break;
+
+ default:
+ break; // Handle all other cases to keep gcc happy.
+ }
+ }
+
+ // Otherwise, see if we hit in the silkscreen area.
+
+ else
+ {
+ UInt16 numButtons;
+ const PenBtnInfoType* buttonListP = EvtGetPenBtnList(&numButtons);
+ EmAliasPenBtnInfoType<PAS> buttonList ((emuptr) buttonListP);
+
+ for (UInt16 buttonIndex = 0; buttonIndex < numButtons; ++buttonIndex)
+ {
+ EmAliasPenBtnInfoType<PAS> button = buttonList[buttonIndex];
+
+ RectangleType buttonBounds;
+ buttonBounds.topLeft.x = button.boundsR.topLeft.x;
+ buttonBounds.topLeft.y = button.boundsR.topLeft.y;
+ buttonBounds.extent.x = button.boundsR.extent.x;
+ buttonBounds.extent.y = button.boundsR.extent.y;
+
+ if (POINT_IN_RECT(displayX, displayY, buttonBounds))
+ {
+ eventInfo.asciiCode = button.asciiCode;
+ eventInfo.keyCode = button.keyCode;
+ eventInfo.modifiers = button.modifiers;
+ break;
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::GetAppSwitchEventInfo
+ *
+ * DESCRIPTION: Get information about the current app switch event.
+ * In particular, any recorded "from application"
+ * information recorded in it is probably incorrect now,
+ * so let's generate some new information.
+ *
+ * PARAMETERS: event - the current event being replayed
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::GetAppSwitchEventInfo (EmEventInfo& eventInfo)
+{
+ EmuAppInfo currentApp = EmPatchState::GetCurrentAppInfo ();
+
+ eventInfo.event.appSwitchEvent.oldCardNo = currentApp.fCardNo;
+ eventInfo.event.appSwitchEvent.oldDbID = currentApp.fDBID;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFindInsertionPointString
+ *
+ * DESCRIPTION: Create a string that identifies where a field was tapped,
+ * using the position insertion point. Currently we just
+ * copy the contents of the field up to the insertion point.
+ *
+ * PARAMETERS: emustr - contents of the field in emulator memory
+ *
+ * pos - position of the insertion point
+ *
+ * RETURNED: String identifying where the field was tapped.
+ *
+ ***********************************************************************/
+
+static string PrvFindInsertionPointString (emuptr emustr, UInt16 pos)
+{
+ EmAssert (emustr);
+
+ // Copy the text before pos from emulator memory into local temp buffer.
+
+ char* temp = new char [pos + 1];
+ if (temp == NULL)
+ {
+ // Failed to create temp buffer.
+ return string ();
+ }
+
+ ::EmMem_strncpy (temp, emustr, (size_t) pos);
+
+ // Perhaps.. Scan backwards from pos until string up to pos is unique inside entire field string.
+ // For now we'll just use the entire string up to pos.
+
+ temp[pos] = 0;
+
+ // Return result.
+
+ string finalString = temp;
+
+ delete [] temp;
+
+ return finalString;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::GetAwaitedEventInfo
+ *
+ * DESCRIPTION: Master function to get information from the emulator about
+ * an event that has been waiting for information. This
+ * mechanism is used to give the running application or OS
+ * enough time to respond to a gremlin event before we try to
+ * get information about it. This is used for finding where we
+ * tapped inside a field, a list, or a table. After the gremlin
+ * taps inside the target object, FldHandleEvent, LstHandleEvent,
+ * or TblHandleEvent will compute the new insertion point or
+ * selection due to that pen event. We then try to retrieve the
+ * results of that computation. This method won't work if the
+ * application changes the target object before we have a chance
+ * to retrieve its info, or the object gets destroyed.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::GetAwaitedEventInfo (void)
+{
+ EmAssert (fgEventAwaitingInfo);
+ EmAssert (fgIsGatheringInfo);
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // It is entirely possible that the active form has been destroyed or changed.
+
+ FormType* frmP = ::FrmGetActiveForm ();
+
+ if (frmP == NULL)
+ {
+ return;
+ }
+
+ // Look for an event that needs completing.
+
+ Bool foundAwaitedEvent = false;
+ EmEventInfoList::reverse_iterator iter = fgEventInfo.rbegin ();
+
+ while (!foundAwaitedEvent && iter != fgEventInfo.rend ())
+ {
+ EmEventInfo& awaitingEvent = *iter++;
+
+ switch (awaitingEvent.event.eType)
+ {
+ case kRecordedPenEvent:
+ {
+ switch (awaitingEvent.objKind)
+ {
+ case frmFieldObj:
+ {
+ // Find the field text to tap after.
+
+ FieldType* fldP = (FieldType*) ::FrmGetObjectPtr (frmP, awaitingEvent.objID);
+
+ if (fldP)
+ {
+ emuptr txtP = (emuptr) ::FldGetTextPtr (fldP);
+
+ if (txtP)
+ {
+ UInt16 pos = ::FldGetInsPtPosition (fldP);
+
+ if (pos == 0)
+ {
+ // Tap at the beginning.
+
+ awaitingEvent.text = " at the beginning";
+ }
+ else
+ {
+ // Tap after the text 'blah'.
+
+ string aftertext =
+ ::PrvFindInsertionPointString (txtP, pos);
+
+ awaitingEvent.text = " after the text \"" + aftertext + "\"";
+ }
+ }
+ }
+
+ foundAwaitedEvent = true;
+
+ break;
+ } // case frmFieldObj
+
+ case frmListObj:
+ {
+ // Find the list item to tap on.
+
+ ListType* lstP = (ListType*)::FrmGetObjectPtr (frmP, awaitingEvent.objID);
+
+ if (lstP)
+ {
+ Int16 currentItem = ::LstGetSelection (lstP);
+
+ // If there is a selection:
+
+ if (currentItem != noListSelection)
+ {
+ // Use text if it exists, else use row number.
+
+ emuptr textP = (emuptr) ::LstGetSelectionText (lstP, currentItem);
+
+ if (textP && ::EmMem_strlen(textP) > 0)
+ {
+ // This may not be unique...
+ awaitingEvent.text = ::PrvGetStringFromEmuMemory (textP);
+ }
+ else
+ {
+ // Should this be relative to topItem?
+ awaitingEvent.row = currentItem;
+ }
+ }
+ }
+
+ foundAwaitedEvent = true;
+
+ break;
+ } // case frmListObj
+
+ default:
+ {
+ // fgEventAwaitingInfo set inappropriately
+
+ EmAssert (false);
+ }
+ } // switch (objKind)
+
+ break;
+ } // case pen event
+
+ default:
+ {
+ // fgEventAwaitingInfo set inappropriately
+
+ EmAssert (false);
+ }
+ } // switch (eType)
+ } // while
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputEvents
+ *
+ * DESCRIPTION: Master output function - write out a text description of
+ * a gremlin event list.
+ *
+ * PARAMETERS: events - list of events to output
+ *
+ * stream - string stream to write output into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputEvents (strstream& stream)
+{
+ // Start step counter from one. The current step number is not necessarily
+ // the same as the current event index, because multiple events can go into
+ // a single step.
+
+ fgCounter = 1;
+
+ // Write out starting step.
+
+ EmEventOutput::OutputStartStep (stream);
+
+ // Iterate over all the events.
+
+ EmEventInfoList::iterator iter (fgEventInfo.begin ());
+
+ while (iter != fgEventInfo.end ())
+ {
+ switch (iter->event.eType)
+ {
+ case kRecordedKeyEvent:
+
+ EmEventOutput::OutputKeyEventStep (iter, stream);
+ break;
+
+ case kRecordedPenEvent:
+
+ EmEventOutput::OutputPenEventStep (*iter, stream);
+ break;
+
+ case kRecordedAppSwitchEvent:
+
+ EmEventOutput::OutputAppSwitchEventStep (*iter, stream);
+ break;
+
+ case kRecordedErrorEvent:
+
+ EmEventOutput::OutputErrorEvent (*iter, stream);
+ break;
+
+ case kRecordedNullEvent:
+
+ // No output for null events.
+ break;
+
+ default:
+
+ stream << "Unknown event" << endl;
+ EmAssert (false);
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputStartStep
+ *
+ * DESCRIPTION: Write out the description of the starting step,
+ * ie launching the application being exercised.
+ *
+ * PARAMETERS: stream - the output stream to write into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputStartStep (strstream& stream)
+{
+ stream << endl;
+ stream << fgCounter << ". ";
+
+ // Get and write out application name and version.
+
+ string appNameUC;
+ string appNameLC;
+ string appVersion;
+
+ Errors::GetAppName (appNameUC, appNameLC);
+ Errors::GetAppVersion (appVersion);
+
+ stream << "Start \"" << appNameLC << "\" " << appVersion << "";
+
+ // Device name:
+
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+
+ Configuration cfg = *pref;
+ EmDevice device = cfg.fDevice;
+ string deviceStr = device.GetMenuString ();
+
+ stream << " on a " << deviceStr;
+
+ // ROM version:
+
+ UInt32 romVersionData;
+ ::FtrGet (sysFileCSystem, sysFtrNumROMVersion, &romVersionData);
+
+ UInt32 romVersionMajor = sysGetROMVerMajor (romVersionData);
+ UInt32 romVersionMinor = sysGetROMVerMinor (romVersionData);
+
+ stream
+ << " running Palm OS "
+ << romVersionMajor << "." << romVersionMinor
+ << "." << endl;
+
+ fgCounter++;
+}
+
+
+#pragma mark -
+
+enum KeyType
+{
+ kKeyType_Writeable, // a normal character that can be entered by typing/graffiti
+ kKeyType_Button, // a button
+ kKeyType_Event // an event, not necessarily from user input
+};
+
+
+struct KeyDescription
+{
+ char * description;
+ uint16 chrcode;
+ KeyType type;
+};
+
+
+// List of text descriptions for different kinds of character codes.
+// Palm OS chr and vchr defines are in Core/System/Chars.h.
+// Items followed by a '-' are not currently generated by gremlins.
+
+static KeyDescription gKeyDescription [] =
+{
+ { "backspace", chrBackspace, kKeyType_Writeable }, // 0x0008
+ { "tab", chrHorizontalTabulation, kKeyType_Writeable }, // 0x0009
+ { "new line", chrLineFeed, kKeyType_Writeable }, // 0x000A
+ { "page up", vchrPageUp, kKeyType_Button }, // 0x000B
+ { "page down", vchrPageDown, kKeyType_Button }, // 0x000C
+ { "carriage return", chrCarriageReturn, kKeyType_Writeable }, // 0x000D
+ { "escape", chrEscape, kKeyType_Writeable }, // 0x001B -
+ { "left arrow", chrLeftArrow, kKeyType_Button }, // 0x001C
+ { "right arrow", chrRightArrow, kKeyType_Button }, // 0x001D
+ { "up arrow", chrUpArrow, kKeyType_Button }, // 0x001E
+ { "down arrow", chrDownArrow, kKeyType_Button }, // 0x001F
+// { " ", chrSpace, kKeyType_Writeable }, // 0x0020
+
+ // Everything here (0x0021 to 0x007E) is printable.
+
+ { "<delete>", chrDelete, kKeyType_Writeable }, // 0x007F
+
+ // extended characters from 0x0080 to 0x00FF
+
+ // Remaining are either commands or wide characters.
+
+ { "low battery", vchrLowBattery, kKeyType_Event }, // 0x0101
+ { "next field", vchrNextField, kKeyType_Button }, // 0x0103
+ { "Menu", vchrMenu, kKeyType_Button }, // 0x0105
+ { "command", vchrCommand, kKeyType_Button }, // 0x0106
+ { "Home", vchrLaunch, kKeyType_Button }, // 0x0108
+ { "Keyboard", vchrKeyboard, kKeyType_Button }, // 0x0109
+ { "Find", vchrFind, kKeyType_Button }, // 0x010A
+ { "Calculator", vchrCalc, kKeyType_Button }, // 0x010B -
+ { "prev field", vchrPrevField, kKeyType_Button }, // 0x010C
+
+ // Currently, nothing beyond here is generated by gremlins.
+
+ { "Keyboard \"abc\"", vchrKeyboardAlpha, kKeyType_Button }, // 0x0110
+ { "Keyboard \"123\"", vchrKeyboardNumeric, kKeyType_Button }, // 0x0111
+ { "lock", vchrLock, kKeyType_Button }, // 0x0112
+ { "Backlight", vchrBacklight, kKeyType_Button }, // 0x0113
+ { "auto off", vchrAutoOff, kKeyType_Event }, // 0x0114 - This one is currently disabled.
+
+ // PalmOS 3.0
+
+ { "exgtest", vchrExgTest, kKeyType_Event }, // 0x0115
+ { "send data", vchrSendData, kKeyType_Event }, // 0x0116
+ { "ir receive", vchrIrReceive, kKeyType_Event }, // 0x0117
+
+ // PalmOS 3.1
+
+ { "tsm1", vchrTsm1, kKeyType_Event }, // 0x0118
+ { "tsm2", vchrTsm2, kKeyType_Event }, // 0x0119
+ { "tsm3", vchrTsm3, kKeyType_Event }, // 0x011A
+ { "tsm4", vchrTsm4, kKeyType_Event }, // 0x011B
+
+ // PalmOS 3.2
+
+ { "radio coverage OK", vchrRadioCoverageOK, kKeyType_Event }, // 0x011C
+ { "radio coverage fail", vchrRadioCoverageFail, kKeyType_Event }, // 0x011D
+ { "power off", vchrPowerOff, kKeyType_Event }, // 0x011E
+
+ // PalmOS 3.5
+
+ { "resume sleep", vchrResumeSleep, kKeyType_Event }, // 0x011F
+
+ { "late wakeup", vchrLateWakeup, kKeyType_Event }, // 0x0120
+
+ { "tsm mode", vchrTsmMode, kKeyType_Event }, // 0x0121
+ { "Brightness", vchrBrightness, kKeyType_Button }, // 0x0122
+ { "Contrast", vchrContrast, kKeyType_Button }, // 0x0123
+ { "exg int data", vchrExgIntData, kKeyType_Event }, // 0x01FF
+
+ { "hard 1 (Date Book)", vchrHard1, kKeyType_Button }, // 0x0204
+ { "hard 2 (Address Book)", vchrHard2, kKeyType_Button }, // 0x0205
+ { "hard 3 (ToDo List)", vchrHard3, kKeyType_Button }, // 0x0206
+ { "hard 4 (Note Pad)", vchrHard4, kKeyType_Button }, // 0x0207
+ { "hard power", vchrHardPower, kKeyType_Button }, // 0x0208
+ { "hard cradle", vchrHardCradle, kKeyType_Button }, // 0x0209
+ { "hard cradle 2", vchrHardCradle2, kKeyType_Button }, // 0x020A
+ { "hard contrast", vchrHardContrast, kKeyType_Button }, // 0x020B
+ { "hard antenna", vchrHardAntenna, kKeyType_Event }, // 0x020C
+ { "hard brightness", vchrHardBrightness, kKeyType_Button }, // 0x020D
+
+ { NULL, 0, (KeyType) 0 }
+};
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFindKeyDescription
+ *
+ * DESCRIPTION: Search for the text description of a character code
+ * recieved in event.data.keyDown.ascii.
+ *
+ * PARAMETERS: chrcode - the character code value to search for
+ *
+ * RETURNED: pointer to a KeyDescription structure that describes
+ * the character code, or null if no description found.
+ *
+ ***********************************************************************/
+
+static KeyDescription* PrvFindKeyDescription (uint16 chrcode)
+{
+ // Iterate over the key description list and find an element with
+ // the same key code.
+
+ for (KeyDescription* kd = gKeyDescription; kd->description != NULL; kd++)
+ {
+ if (kd->chrcode == chrcode)
+ return kd;
+ }
+
+ // Failed to find description.
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvIsKeyWriteable
+ *
+ * DESCRIPTION: Determine whether a key event is writeable or not. By
+ * 'writeable' we mean that the key event can be reproduced
+ * by a user by typing or graffiti, as in a normal printable
+ * text character. This routine is used to determine whether
+ * multiple key events can be merged together into a single
+ * string.
+ *
+ * PARAMETERS: kd - the key description structure for this event, if it exists
+ *
+ * chrcode - the character code, ie from event.data.keyDown.ascii
+ *
+ * modifiers - the modifiers for this event
+ *
+ * RETURNED: True if the key event is writeable.
+ *
+ ***********************************************************************/
+
+static Bool PrvIsKeyWriteable (KeyDescription* kd, uint16 chrcode, uint16 modifiers)
+{
+ // If commandKeyMask is set, can't be writeable.
+
+ if (modifiers & commandKeyMask)
+ return false;
+
+ // Everything above 0x0100 without commandKeyMask set is a writeable wide character..?
+
+ if (chrcode >= 0x100)
+ return true;
+
+ // Remaining values are below 0x100 without commandKeyMask set.
+ // If the key has a description, use it to determine writeability.
+
+ if (kd)
+ {
+ return kd->type == kKeyType_Writeable;
+ }
+
+ // If the key's character code is printable, we'll assume it's writeable.
+
+ if (isprint (chrcode))
+ return true;
+
+ // If the key's character code is in the extended ascii range, we'll assume it's
+ // writeable. Problem with this is that it's not easy to enter an extended character
+ // into a Palm device..
+
+ if (IS_EXTENDED(chrcode))
+ return true;
+
+ // Anything else (meaning values below 0x0080 without commandKeyMask set and
+ // no key description specified) assumed to be unwriteable.
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputKeyEventStep
+ *
+ * DESCRIPTION: Write out the description of a key event. This routine
+ * handles key events that look like button presses or special
+ * event notifications (like LowBattery), as well as writeable
+ * characters. Successive writeable characters are merged
+ * together into a single string if possible.
+ *
+ * PARAMETERS: events - the entire event list
+ *
+ * iter - an iterator over the events list, currently
+ * located at a key event
+ *
+ * stream - the output stream to write into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputKeyEventStep (EmEventInfoList::iterator& eventInfoIter, strstream& stream)
+{
+ EmAssert (eventInfoIter->event.eType == kRecordedKeyEvent);
+
+ stream << fgCounter << ". ";
+
+ KeyDescription* kd = ::PrvFindKeyDescription (eventInfoIter->event.keyEvent.ascii);
+
+ // If this key event is writeable, then build up a string
+ // of characters to write.
+
+ if (::PrvIsKeyWriteable (kd, eventInfoIter->event.keyEvent.ascii, eventInfoIter->event.keyEvent.modifiers))
+ {
+ string charString;
+
+ // Scan forward until we find an event that doesn't involve writing,
+ // or we hit the end of the list.
+
+ do
+ {
+ // Add character onto string: Use description if available, else just
+ // use the character itself.
+
+ if (kd)
+ {
+ charString += string ("<") + kd->description + string (">");
+ }
+
+ else if (IS_EXTENDED (eventInfoIter->event.keyEvent.ascii))
+ {
+ // Put brackets around extended character number
+
+ char temp[16];
+ sprintf (temp, "<%3d>", (int) eventInfoIter->event.keyEvent.ascii);
+ charString += temp;
+ }
+
+ else
+ {
+ charString += eventInfoIter->event.keyEvent.ascii;
+ }
+
+ ++eventInfoIter;
+
+ // Stop if this event is not a key event.
+
+ if (eventInfoIter->event.eType != kRecordedKeyEvent)
+ break;
+
+ // Stop if this key event is not writeable.
+
+ kd = ::PrvFindKeyDescription (eventInfoIter->event.keyEvent.ascii);
+
+ if (!::PrvIsKeyWriteable (kd, eventInfoIter->event.keyEvent.ascii, eventInfoIter->event.keyEvent.modifiers))
+ break;
+
+ } while (eventInfoIter != fgEventInfo.end ());
+
+ // Undigest the event that caused us to break.
+
+ --eventInfoIter;
+
+ // Output the string.
+
+ stream << "Write \"" << charString << "\"." << endl;
+ }
+
+ else
+ {
+ if (kd)
+ {
+ // Check if it's a button.
+
+ if (kd->type == kKeyType_Button)
+ {
+ stream << "Tap the " << kd->description << " button." << endl;
+ }
+
+ // Check if it's an event.
+
+ else if (kd->type == kKeyType_Event)
+ {
+ stream
+ << "Application receives a "
+ << kd->description << " event." << endl;
+ }
+ }
+
+ else
+ {
+ stream
+ << "Write character "
+ << eventInfoIter->event.keyEvent.ascii << "." << endl;
+ }
+ }
+
+ fgCounter++;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetRankString
+ *
+ * DESCRIPTION: Return a text string to describe a rank number.
+ *
+ * PARAMETERS: rank - the rank number to describe
+ *
+ * RETURNED: String containing the rank description.
+ *
+ ***********************************************************************/
+
+static string PrvGetRankString (int rank)
+{
+ string rankString;
+
+ // Special cases:
+
+ if (rank == kObjectRank_Last) rankString = "last";
+ else if (rank == 0) rankString = "first";
+ else if (rank == 1) rankString = "second";
+ else if (rank == 2) rankString = "third";
+
+ else
+ {
+ // Just use 'nth'.
+
+ char temp[16];
+ sprintf (temp, "%d", rank);
+ rankString = temp + string("th");
+ }
+
+ return rankString;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetObjectKindString
+ *
+ * DESCRIPTION: Return a string describing the type of a form object.
+ *
+ * PARAMETERS: objKind - the type of the object
+ *
+ * style - the style (for control objects)
+ *
+ * RETURNED: A string describing the object's type.
+ *
+ ***********************************************************************/
+
+static string PrvGetObjectKindString (FormObjectKind objKind, ControlStyleType style)
+{
+ string kindString;
+
+ switch (objKind)
+ {
+ case frmFieldObj:
+ kindString = "field";
+ break;
+
+ case frmControlObj:
+
+ switch (style)
+ {
+ case buttonCtl:
+ kindString = "button";
+ break;
+
+ case pushButtonCtl:
+ kindString = "pushbutton";
+ break;
+
+ case checkboxCtl:
+ kindString = "checkbox";
+ break;
+
+ case popupTriggerCtl:
+ kindString = "popup trigger";
+ break;
+
+ case selectorTriggerCtl:
+ kindString = "selector trigger";
+ break;
+
+ case repeatingButtonCtl:
+ kindString = "repeating button";
+ break;
+
+ case sliderCtl:
+ kindString = "slider";
+ break;
+
+ case feedbackSliderCtl:
+ kindString = "feedback slider";
+ break;
+
+ default:
+ kindString = "control";
+ }
+
+ break;
+
+ case frmListObj:
+ kindString = "list";
+ break;
+
+ case frmTableObj:
+ kindString = "table";
+ break;
+
+ case frmBitmapObj:
+ kindString = "bitmap";
+ break;
+
+// case frmLineObj:
+// case frmFrameObj:
+// case frmRectangleObj:
+
+ case frmLabelObj:
+ kindString = "label";
+ break;
+
+ case frmTitleObj:
+ kindString = "title";
+ break;
+
+ case frmPopupObj:
+ kindString = "popup";
+ break;
+
+ case frmGraffitiStateObj:
+ kindString = "graffiti shift indicator";
+ break;
+
+ case frmGadgetObj:
+ kindString = "gadget";
+ break;
+
+ case frmScrollBarObj:
+ kindString = "scrollbar";
+ break;
+
+ default:
+ kindString = "(unknown object type)";
+ }
+
+ return kindString;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputPenEventStep
+ *
+ * DESCRIPTION: Write out the description of a pen event. 'Lift stylus'
+ * events are ignored for now.
+ *
+ * PARAMETERS: event - the pen event to describe
+ *
+ * stream - the output stream to write into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputPenEventStep (const EmEventInfo& eventInfo, strstream& stream)
+{
+ EmAssert (eventInfo.event.eType == kRecordedPenEvent);
+
+ PointType pen = eventInfo.event.penEvent.coords;
+ string text = eventInfo.text;
+ FormObjectKind kind = eventInfo.objKind;
+ Int16 rank = eventInfo.rank;
+
+ if (::PrvIsPenUp (pen))
+ {
+ // Skip lift stylus events.
+ // stream << "Lift stylus." << endl;
+ }
+ else
+ {
+ stream << fgCounter << ". ";
+
+ // Tap on silkscreen
+
+ KeyDescription* kd;
+ if (eventInfo.asciiCode != 0 &&
+ (kd = ::PrvFindKeyDescription (eventInfo.asciiCode)) != NULL)
+ {
+ // Check if it's a button.
+
+ if (kd->type == kKeyType_Button)
+ {
+ stream << "Tap the " << kd->description << " button";
+ }
+
+ // Check if it's an event.
+
+ else if (kd->type == kKeyType_Event)
+ {
+ stream << "Application receives a " << kd->description << " event";
+ }
+ }
+
+ // Tap somewhere.
+
+ else if (kind == -1)
+ {
+ // Just output location to tap at.
+
+ stream << "Tap at " << pen.x << ", " << pen.y;
+ }
+ else
+ {
+ // Command.
+
+ if ( (kind == frmFieldObj)
+ || (kind == frmTitleObj)
+ || (kind == frmTableObj))
+ {
+ stream << "Tap in the ";
+ }
+ else
+ {
+ stream << "Tap the ";
+ }
+
+ // Ranking.
+
+ Bool needRankPostfix = false;
+
+ if (rank == kObjectRank_None)
+ {
+ // Output control label or nothing.
+
+ if (!text.empty () && (kind == frmControlObj))
+ {
+ stream << "\"" << text << "\" ";
+ }
+ }
+ else
+ {
+ // Output ranking.
+
+ stream << ::PrvGetRankString (rank) << " ";
+
+ if (rank > 1)
+ needRankPostfix = true;
+ }
+
+ // Object kind.
+ // Skip this for the special 'nth list item' case.
+
+ if (!(kind == frmListObj &&
+ rank == kObjectRank_None &&
+ text.empty() &&
+ eventInfo.row != -1))
+ {
+ stream
+ << ::PrvGetObjectKindString (kind, eventInfo.style);
+ }
+
+ // Remainder of ranking.
+
+ if (needRankPostfix)
+ stream << " from the top";
+
+ // Special object data.
+
+ switch (kind)
+ {
+ case frmFieldObj:
+
+ if (!text.empty ())
+ {
+ // After the text 'blah'.
+
+ stream << text;
+ }
+ else
+ {
+ // Shouldn't need this because if event.text is empty then
+ // the field is empty so it doesn't matter where you tap.
+ // stream << " at " << pen.x << ", " << pen.y;
+ }
+
+ break;
+
+ case frmListObj:
+
+ // Output item text if we have it, else try the item number.
+
+ if (!text.empty ())
+ {
+ if (rank == kObjectRank_None)
+ {
+ // Special case for forms with only one list.
+
+ stream << " item \"" << text << "\"";
+ }
+ else
+ {
+ stream << ", in the \"" << text << "\" item";
+ }
+ }
+ else if (eventInfo.row != -1)
+ {
+ if (rank == kObjectRank_None)
+ {
+ // Special case for forms with only one list.
+
+ stream << ::PrvGetRankString (eventInfo.row) << " list item";
+ }
+ else
+ {
+ stream << ", in the " << ::PrvGetRankString (eventInfo.row) << " item";
+ }
+ }
+ else
+ {
+ stream << " at " << pen.x << ", " << pen.y;
+ }
+
+ break;
+
+ case frmTableObj:
+
+ // Output column, row if we have it, else use x, y pixel position.
+
+ if (eventInfo.row != -1)
+ {
+ stream
+ << " at column " << eventInfo.column
+ << " row " << eventInfo.row;
+ }
+ else
+ {
+ stream << " at " << pen.x << ", " << pen.y;
+ }
+
+ break;
+
+ default:
+ break; // Handle all other cases to keep gcc happy.
+ }
+ }
+
+ // Form change.
+
+ if (!eventInfo.newFormText.empty ())
+ {
+ // "To go to the 'A' dialog" or "To open the 'B' view".
+
+ stream << " to " << eventInfo.newFormText;
+ }
+
+ stream << "." << endl;
+
+ fgCounter++;
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputAppSwitchEventStep
+ *
+ * DESCRIPTION: Write out the description of an appSwitch event.
+ *
+ * PARAMETERS: event - the appSwitch event to describe
+ *
+ * stream - the output stream to write into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputAppSwitchEventStep (const EmEventInfo& eventInfo, strstream& stream)
+{
+ EmAssert (eventInfo.event.eType == kRecordedAppSwitchEvent);
+
+ stream << fgCounter << ". ";
+
+ uint16 cardNo = eventInfo.event.appSwitchEvent.cardNo;
+ uint32 dbID = eventInfo.event.appSwitchEvent.dbID;
+ uint16 oldCardNo = eventInfo.event.appSwitchEvent.oldCardNo;
+ uint32 oldDbID = eventInfo.event.appSwitchEvent.oldDbID;
+
+ char name [dmDBNameLength] = { 0 };
+ char oldName [dmDBNameLength] = { 0 };
+ uint16 version;
+ uint16 oldVersion;
+
+ #define GET_NAME(x, y) x, NULL, y, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+
+ ::DmDatabaseInfo (cardNo, dbID, GET_NAME(name, &version));
+ ::DmDatabaseInfo (oldCardNo, oldDbID, GET_NAME(oldName, &oldVersion));
+
+ if (strcmp (name, oldName) != 0)
+ {
+ stream << "Switch to \"" << name << "\" from \"" << oldName << "\"." << endl;
+ }
+ else
+ {
+ stream << "Relaunch \"" << name << "\"." << endl;
+ }
+
+ fgCounter++;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmEventOutput::OutputErrorEvent
+ *
+ * DESCRIPTION: Write out the description of an error event.
+ *
+ * PARAMETERS: event - the error event to describe
+ *
+ * stream - the output stream to write into
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmEventOutput::OutputErrorEvent (const EmEventInfo& eventInfo, strstream& stream)
+{
+ EmAssert (eventInfo.event.eType == kRecordedErrorEvent);
+
+ // Output error description. Do this a character at
+ // a time in order to convert line endings.
+
+ stream << endl;
+ stream << "Crash with error:" << endl << endl;
+
+ {
+ string::const_iterator iter = eventInfo.text.begin ();
+ while (iter != eventInfo.text.end ())
+ {
+ if (*iter == '\r' || *iter == '\n')
+ {
+ stream << endl;
+ }
+ else
+ {
+ stream << *iter;
+ }
+
+ ++iter;
+ }
+
+ stream << endl << endl;
+ }
+
+ // Output the stack crawl.
+
+ stream << "Function call stack:" << endl;
+
+ EmEventOutput::OutputStack (stream, eventInfo.stackCrawl);
+
+ stream << endl;
+}
+
+
+void EmEventOutput::OutputStack (strstream& stream, const StringList& stackCrawl)
+{
+ StringList::const_iterator iter = stackCrawl.begin ();
+
+ while (iter != stackCrawl.end ())
+ {
+ stream << "\t" << *iter << endl;
+ ++iter;
+ }
+}
diff --git a/SrcShared/EmEventOutput.h b/SrcShared/EmEventOutput.h
new file mode 100644
index 0000000..6566ffd
--- /dev/null
+++ b/SrcShared/EmEventOutput.h
@@ -0,0 +1,240 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmEventOutput_h
+#define EmEventOutput_h
+
+#include "EmEventPlayback.h" // EmRecordedEvent
+#include "EmStructs.h" // StringList
+
+#include <string> // string
+#include <strstream> // strstream
+
+
+/*
+ EmEventOutput tries to write out a human-readable list of steps from a
+ Gremlin event list. This process has two parts: gathering information
+ while the gremlin events are being played back, and running through the
+ event list and outputting the steps.
+
+ The information-gathering happens when EmEventPlayback::ReplayGetEvent
+ or ReplayGetPen calls EmEventOutput::GetEventInfo, right after a gremlin
+ event has been posted. GetEventInfo gets info about the posted event,
+ or about a previous event if necessary. This info is stored in the
+ gremlin event structure for later use.
+
+ The step outputting part currently happens when an event minimization
+ completes, and EmMinimize::MinimizationComplete calles
+ EmEventOutput::OutputEvents.
+
+ This system is accessed from the following locations:
+
+ * EmEventPlayback : Reports that events are being inserted into the
+ system, and that EmEventOutput may want to gather
+ additional contextual information about the event
+ to be used when later logging the event. To do
+ this, EmEventPlayback calls GetEventInfo, passing
+ in the event being played back.
+
+ * EmMinimize : Turns information gather on and off.
+ Triggers final output of events when minimization
+ is completed.
+
+ * SysHeadpatch::FrmPopupForm
+ : Report that a form is popping up.
+
+
+ Output is according to this grammar:
+ ------------------------------------
+
+ All steps are assumed to be numbered starting at one and incrementing by
+ one.
+
+ bugReport ::==
+ appStart
+ events*
+ crash
+
+ appStart ::==
+ Start "appName" appVersion on a deviceName running Palm OS osVersion.
+
+ events ::==
+ tap | write | startApp |
+ ejectCard # NYI
+
+ ranking ::==
+ first | second | third | nth | last
+ # counted top to bottom, left to right
+
+ formObjectType ::==
+ button | trigger | selector | checkbox |
+ pushbutton | gadget | field | list | table
+
+ changeForm ::==
+ to go to { the "formName" view | a new view }
+ to open { the "formName" dialog | a new dialog }
+ to popup a dialog |
+
+ tapStart ::==
+ Tap the "buttonName" {button | trigger | selector | checkbox} |
+ Tap the {ranking} {formObjectType} {from the top} |
+ Tap in the {ranking} field {from the top} {after the text "fieldText" | at the beginning} |
+ Tap the list item "itemName" |
+ Tap the {ranking} list item |
+ Tap the {ranking} list {from the top}, in the "itemName" item |
+ Tap the {ranking} list {from the top}, in the {ranking} item |
+ Tap the {ranking} list {from the top} at x, y |
+ Tap in the {ranking} table {from the top} at column n row n |
+ Tap in the {ranking} table {from the top} at x, y |
+ Tap the scroll {up | down} button | # NYI
+ Tap the "menuName \ menuItem" menu item | # NYI
+ Tap in the title | # NYI
+ Tap at x, y
+
+ tap ::==
+ tapStart {changeForm}.
+
+ key ::==
+ <backspace> |
+ <tab> |
+ <new line> |
+ <carriage return> |
+ <delete> |
+ c | # normal characters from 0x20 - 0x7E
+ <nnn> | # extended characters from 0x80 - 0xFF
+
+ keyButton ::==
+ page up | page down |
+ left arrow | right arrow | up arrow | down arrow |
+ prev field | next field |
+ menu |
+ command |
+ launch |
+ keyboard |
+ find |
+ calc |
+ ...
+
+ keyAppEvent ::==
+ low battery |
+ auto off |
+ exgtest |
+ send data |
+ ir receive |
+ ...
+
+ write ::==
+ Write "key+". | # combine adjacent keystrokes if possible.
+ Tap the keyButton button. |
+ Application receives a keyAppEvent event. |
+ Write character nnn. # for key events with no other description
+
+ startApp ::==
+ Switch to "appName appVersion" from "oldAppName oldAppVersion". |
+ Switch to any other app. | # if the crash happens before the app exits
+ Relaunch "appName appVersion".
+
+ crash ::==
+ Crash with error "errorDescription".
+ stackCrawl
+*/
+
+// As events are replayed, we are called to gather contextual information
+// about that event. We use that contextual information when preparing
+// out English output. The event being replayed is stored along with bits
+// and pieces of contextual information in the following structure.
+
+struct EmEventInfo
+{
+ EmRecordedEvent event;
+
+ string newFormText;
+ StringList stackCrawl;
+ string text;
+ FormObjectKind objKind;
+ UInt16 objID;
+ Int16 rank;
+ Int16 row;
+ Int16 column;
+ ControlStyleType style;
+
+ // Silkscreen button info
+ WChar asciiCode;
+ UInt16 keyCode;
+ UInt16 modifiers;
+};
+
+typedef vector<EmEventInfo> EmEventInfoList;
+
+class EmEventOutput
+{
+ // Interface for gathering event info:
+
+ public:
+ static void StartGatheringInfo (void);
+ static Bool IsGatheringInfo (void);
+ static void GatherInfo (Bool);
+
+ // Called by EmEventPlayback when returning a new event to be played back.
+
+ static void GetEventInfo (const EmRecordedEvent&);
+
+ // Called by SysHeadpatch::FrmPopupForm to report that a new form is
+ // being popped up.
+
+ static void PoppingUpForm (void);
+
+ // Called by Errors::HandleDialog to report that an error occurred
+ // and report the text.
+
+ static void ErrorOccurred (const string&);
+
+ private:
+ static void GetAwaitedEventInfo (void);
+ static void GetPenEventInfo (EmEventInfo&);
+ static void GetAppSwitchEventInfo (EmEventInfo&);
+
+ // Interface for outputting:
+
+ public:
+ // Called by Minimization when minimization is done and the accumulated
+ // information needs to be written out.
+
+ static void OutputEvents (strstream&);
+
+ // Utility routine to list a stack crawl. Exported here so that we
+ // can share it with EmMinimize, which uses it when reporting that
+ // it failed to produce an error on the last run.
+
+ static void OutputStack (strstream&, const StringList&);
+
+ private:
+ static void OutputStartStep (strstream&);
+ static void OutputKeyEventStep (EmEventInfoList::iterator&, strstream&);
+ static void OutputPenEventStep (const EmEventInfo&, strstream&);
+ static void OutputAppSwitchEventStep(const EmEventInfo&, strstream&);
+ static void OutputErrorEvent (const EmEventInfo&, strstream&);
+
+ // Globals:
+
+ private:
+ static EmEventInfoList fgEventInfo;
+ static Bool fgIsGatheringInfo;
+ static int fgCounter;
+ static UInt16 fgPreviousFormID;
+ static Bool fgEventAwaitingInfo;
+ static Bool fgWaitForPenUp;
+ static StringList fgLastStackCrawl;
+};
+
+#endif // EmEventOutput_h
diff --git a/SrcShared/EmEventPlayback.cpp b/SrcShared/EmEventPlayback.cpp
new file mode 100644
index 0000000..29c33cf
--- /dev/null
+++ b/SrcShared/EmEventPlayback.cpp
@@ -0,0 +1,1443 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmEventPlayback.h"
+
+#include "CGremlinsStubs.h" // StubAppEnqueueKey, StubAppEnqueuePt
+#include "EmEventOutput.h" // GetEventInfo
+#include "EmMemory.h" // EmMem_strlen, EmMem_strcpy
+#include "EmMinimize.h" // EmMinimize::IsOn
+#include "EmPalmStructs.h" // EmAliasControlType
+#include "EmStreamFile.h" // EmStreamFile
+#include "Logging.h" // LogAppendMsg
+#include "ROMStubs.h" // EvtResetAutoOffTimer
+#include "SessionFile.h" // SessionFile
+
+#include <ctype.h> // isprint
+
+#if _DEBUG
+#define LOG_PLAYBACK 1
+#else
+#define LOG_PLAYBACK 0
+#endif
+
+#define PRINTF if (!LOG_PLAYBACK) ; else LogAppendMsg
+
+
+EmStream& operator << (EmStream&, const EmRecordedEvent&);
+EmStream& operator >> (EmStream&, EmRecordedEvent&);
+
+EmStream& operator << (EmStream&, const Chunk&);
+EmStream& operator >> (EmStream&, Chunk&);
+
+
+// List of events that we've recorded or re-read from a session file.
+
+Chunk EmEventPlayback::fgEvents;
+EmRecordedEventFilter EmEventPlayback::fgMask;
+Bool EmEventPlayback::fgRecording;
+Bool EmEventPlayback::fgReplaying;
+EmEventPlayback::EmIterationState EmEventPlayback::fgIterationState;
+EmEventPlayback::EmIterationState EmEventPlayback::fgPrevIterationState;
+
+enum EmStoredEventType
+{
+ // These values are written to external files, and so should not
+ // be changed. New values should be added to the end, and current
+ // values should not be deleted.
+
+ kStoredKeyEvent, // 7 bytes
+ kStoredKeyEventCompressed, // 2 byte
+
+ kStoredPenEvent, // 5 bytes
+ kStoredPenEventCompressedUp, // 1 bytes
+ kStoredPenEventCompressedX, // 4 bytes
+ kStoredPenEventCompressedY, // 4 bytes
+ kStoredPenEventCompressedXY, // 3 bytes
+
+ kStoredAppSwitchEvent, // 13 bytes
+ kStoredAppSwitchEventCompressed, // N/A
+
+ kStoredNullEvent, // 1 bytes
+ kStoredNullEventCompressed, // N/A
+
+ kStoredErrorEvent, // 5 bytes
+ kStoredErrorEventCompressed // N/A
+};
+
+
+static inline Bool PrvIsPenEvent (const EmRecordedEvent& event)
+{
+ return event.eType == kRecordedPenEvent;
+}
+
+static inline Bool PrvIsPenUp (const PointType& pt)
+{
+ return pt.x == -1 && pt.y == -1;
+}
+
+static inline Bool PrvIsPenDown (const PointType& pt)
+{
+ return !::PrvIsPenUp (pt);
+}
+
+static inline Bool PrvIsPenUp (const EmRecordedEvent& event)
+{
+ return ::PrvIsPenEvent (event) && ::PrvIsPenUp (event.penEvent.coords);
+}
+
+static inline Bool PrvIsPenDown (const EmRecordedEvent& event)
+{
+ return ::PrvIsPenEvent (event) && ::PrvIsPenDown (event.penEvent.coords);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Initialize
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::Initialize (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Reset
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::Reset (void)
+{
+ fgRecording = false;
+ fgReplaying = false;
+
+ EmEventPlayback::ResetPlayback ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Save
+// ---------------------------------------------------------------------------
+// Save our state to the given file. This method is called when a session
+// file is being saved to disk. A session file can be saved under the
+// following circumstances:
+//
+// * Save / Save As
+// * Minimization (after final minimizing)
+// * Gremlin switching
+//
+// For Save / Save As, we don't really care about saving events. In fact,
+// event recording shouldn't even be on. (However, this may change in the
+// future if we want to record human-generated events.)
+//
+// For Minimization, we want to save the final minimal set of events to a
+// .pev file so that it can later be replayed.
+//
+// For Gremlins, we want to save events to a holding .pev file, seperate
+// from the "resume" files Hordes creates.
+//
+// Based on these requirements, we don't really want to unconditionally save
+// events when saving the session. Instead, we'll save them as needed from
+// the various sub-systems that need the events.
+
+void EmEventPlayback::Save (SessionFile&)
+{
+// EmEventPlayback::SaveEvents (f, fgEvents);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Load
+// ---------------------------------------------------------------------------
+// Load our state from the given file. This method is called when a session
+// file is being reloaded from disk. A session file can be loaded under the
+// following circumstances:
+//
+// * Open
+// * Replay
+// * Minimize
+// * Gremlin switching
+//
+// For "Open", we don't really care about any events stored with the session.
+// In fact, since session files with saved events are usually of a type that
+// the Open menu item doesn't allow, we shouldn't get into this situation.
+//
+// When Replaying, we want to load the events so that we can replay them.
+//
+// When Minimizing, we want to load the events so that we can filter them --
+// possibly many times -- and then start replaying them. However, we want
+// to load the events only once, so as not to affect any modifications we
+// may have made to the event set as part of minimizing them.
+//
+// When Gremlin Switching, we want to load the events, but load them from
+// a file different from the one holding the state.
+//
+// Based on these requirements, we don't really want to unconditionally load
+// events when loading the session. Instead, we'll load them as needed from
+// the various sub-systems that need the events.
+
+void EmEventPlayback::Load (SessionFile&)
+{
+// EmEventPlayback::LoadEvents (f, fgEvents);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Dispose
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::Dispose (void)
+{
+ EmEventPlayback::Clear ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::SaveEvents
+// ---------------------------------------------------------------------------
+// Saves the given events to the given session file. Saves all of the events
+// in their own chunk.
+
+void EmEventPlayback::SaveEvents (SessionFile& f)
+{
+ const uint32 kCurrentVersion = 1;
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+ s << fgEvents;
+
+ f.WriteGremlinHistory (chunk);
+
+#if 0
+ LogAppendMsg ("EmEventPlayback::SaveEvents: saved %d events", EmEventPlayback::GetNumEvents ());
+
+ EmRecordedEventList::size_type length = EmEventPlayback::GetNumEvents ();
+ EmRecordedEventList::size_type begin = length - 10;
+
+// if (begin < 0)
+ begin = 0;
+
+ for (EmRecordedEventList::size_type ii = begin; ii < length; ++ii)
+ {
+ LogAppendMsg ("%d:", ii);
+ EmEventPlayback::LogEvent (events[ii]);
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::LoadEvents
+// ---------------------------------------------------------------------------
+// Loads all of the events from a session file and returns them in the given
+// collection.
+
+void EmEventPlayback::LoadEvents (const EmFileRef& ref)
+{
+ EmStreamFile stream (ref, kOpenExistingForRead);
+ ChunkFile chunkFile (stream);
+ SessionFile sessionFile (chunkFile);
+
+ EmEventPlayback::LoadEvents (sessionFile);
+}
+
+
+void EmEventPlayback::LoadEvents (SessionFile& f)
+{
+ Chunk chunk;
+
+ fgEvents.SetLength (0); // Clear the list in case of failure.
+
+ if (f.ReadGremlinHistory (chunk))
+ {
+ uint32 version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+ s >> fgEvents;
+
+ // Set the event mask to be the same size, with all events enabled.
+ // (I'd use assign() here, but it's not support on my Linux's version
+ // of STL.)
+// fgMask.assign (events.size (), true);
+ fgMask = EmRecordedEventFilter (EmEventPlayback::CountNumEvents (), true);
+ }
+
+#if 0
+ LogAppendMsg ("EmEventPlayback::LoadEvents: loaded %d events", EmEventPlayback::GetNumEvents ());
+
+ // Iterate over all the events, counting them up.
+
+ long ii = 0;
+ EmRecordedEvent event;
+ EmStreamChunk s (fgEvents);
+
+ while (s.GetMarker () < s.GetLength ())
+ {
+ s >> event;
+
+ LogAppendMsg ("%d:", ii);
+ EmEventPlayback::LogEvent (event);
+
+ ++ii;
+ }
+#endif
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordEvents
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::RecordEvents (Bool record)
+{
+ fgRecording = record;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordingEvents
+// ---------------------------------------------------------------------------
+// Return whether or not we're recording events.
+
+Bool EmEventPlayback::RecordingEvents (void)
+{
+ return fgRecording;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordCharEvent
+// ---------------------------------------------------------------------------
+// Record a character event, as passed to EvtEnqueueKey.
+
+void EmEventPlayback::RecordKeyEvent (WChar ascii,
+ UInt16 keycode,
+ UInt16 modifiers)
+{
+ EmRecordedEvent event;
+ event.eType = kRecordedKeyEvent;
+
+ event.keyEvent.ascii = ascii;
+ event.keyEvent.keycode = keycode;
+ event.keyEvent.modifiers = modifiers;
+
+ EmEventPlayback::RecordEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordPenEvent
+// ---------------------------------------------------------------------------
+// Record a pen event, as passed to EvtEnqueuePen.
+
+void EmEventPlayback::RecordPenEvent (const PointType& coords)
+{
+ EmAssert (::PrvIsPenUp (coords) || ((coords.x >= 0) && (coords.y >= 0)));
+
+ EmRecordedEvent event;
+ event.eType = kRecordedPenEvent;
+
+ event.penEvent.coords = coords;
+
+ EmEventPlayback::RecordEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordSwitchEvent
+// ---------------------------------------------------------------------------
+// Record a psuedo-event indicating that Gremlins is trying to switch to
+// another application.
+
+void EmEventPlayback::RecordSwitchEvent (uint16 cardNo,
+ uint32 dbID,
+ uint16 oldCardNo,
+ uint32 oldDbID)
+{
+ EmRecordedEvent event;
+ event.eType = kRecordedAppSwitchEvent;
+
+ event.appSwitchEvent.cardNo = cardNo;
+ event.appSwitchEvent.dbID = dbID;
+ event.appSwitchEvent.oldCardNo = oldCardNo;
+ event.appSwitchEvent.oldDbID = oldDbID;
+
+ EmEventPlayback::RecordEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordNullEvent
+// ---------------------------------------------------------------------------
+// Record a NULL event.
+
+void EmEventPlayback::RecordNullEvent (void)
+{
+ EmRecordedEvent event;
+ event.eType = kRecordedNullEvent;
+
+ EmEventPlayback::RecordEvent (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordErrorEvent
+// ---------------------------------------------------------------------------
+// Record a psuedo-event indicating that an error occurred.
+
+void EmEventPlayback::RecordErrorEvent (void)
+{
+ EmRecordedEvent event;
+ event.eType = kRecordedErrorEvent;
+
+ EmEventPlayback::RecordEvent (event);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::Clear
+// ---------------------------------------------------------------------------
+// Clear all events that we've recorded so far.
+
+void EmEventPlayback::Clear (void)
+{
+ fgEvents.SetLength (0);
+ fgMask.clear ();
+ fgRecording = false;
+ fgReplaying = false;
+
+ EmEventPlayback::ResetPlayback ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::CullEvents
+// ---------------------------------------------------------------------------
+// Remove all filtered events.
+
+void EmEventPlayback::CullEvents (void)
+{
+ Chunk newEvents;
+ EmStreamChunk s (newEvents);
+
+ EmEventPlayback::ResetPlayback ();
+
+ EmRecordedEvent event;
+ while (EmEventPlayback::GetNextReplayEvent (event))
+ {
+ s << event;
+
+ // Keep track of pen up/down state so that GetNextReplayEvent
+ // will filter properly.
+
+ fgIterationState.fPenIsDown = ::PrvIsPenDown (event);
+ }
+
+ fgEvents = newEvents;
+
+ // Set the event mask to be the same size, with all events enabled.
+ // (I'd use assign() here, but it's not support on my Linux's version
+ // of STL.)
+// fgMask.assign (fgEvents.size (), true);
+ fgMask = EmRecordedEventFilter (EmEventPlayback::CountNumEvents (), true);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::CountEnabledEvents
+// ---------------------------------------------------------------------------
+// If we were to play all events right now given the current enabled state,
+// return how many events that would be.
+
+long EmEventPlayback::CountEnabledEvents (void)
+{
+ long result = 0;
+
+ // We may be in the middle of a playback right now, so save the
+ // playback state we'll be changing.
+
+ EmValueChanger<EmIterationState> oldIterationState (fgIterationState, EmIterationState ());
+
+ // Iterate over all the events, counting them up.
+
+ EmRecordedEvent event;
+ while (EmEventPlayback::GetNextReplayEvent (event))
+ {
+ ++result;
+
+ // Keep track of pen up/down state so that GetNextReplayEvent
+ // will filter properly.
+
+ fgIterationState.fPenIsDown = ::PrvIsPenDown (event);
+ }
+
+ return result;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::GetCurrentEvent
+// ---------------------------------------------------------------------------
+// Return the event number we've played back. This will be it's index plus
+// one. That is, it's the index of the event following the one we most
+// recently returned and presumably played.
+
+long EmEventPlayback::GetCurrentEvent (void)
+{
+ return fgIterationState.fIndex;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::GetNumEvents
+// ---------------------------------------------------------------------------
+// Return how many events we've recorded. If we're playing back, this count
+// may include events that have been masked out.
+
+long EmEventPlayback::GetNumEvents (void)
+{
+ return fgMask.size ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::CountNumEvents
+// ---------------------------------------------------------------------------
+// Return how many events we've recorded.
+
+long EmEventPlayback::CountNumEvents (void)
+{
+ long result = 0;
+
+ // Iterate over all the events, counting them up.
+
+ EmRecordedEvent event;
+ EmStreamChunk s (fgEvents);
+
+ while (s.GetMarker () < s.GetLength ())
+ {
+ s >> event;
+ ++result;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::GetEvent
+// ---------------------------------------------------------------------------
+// Return an event on our list of recorded events.
+
+void EmEventPlayback::GetEvent (long index, EmRecordedEvent& event)
+{
+ EmStreamChunk s (fgEvents);
+
+ while ((index-- >= 0) && (s.GetMarker () < s.GetLength ()))
+ {
+ s >> event;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::EnableEvents
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::EnableEvents (long begin, long end)
+{
+ if (begin < 0)
+ begin = 0;
+
+ if (end > (long) fgMask.size ())
+ end = (long) fgMask.size ();
+
+ for (long ii = begin; ii < end; ++ii)
+ {
+ fgMask[ii] = true;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::DisableEvents
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::DisableEvents (long begin, long end)
+{
+ if (begin < 0)
+ begin = 0;
+
+ if (end > (long) fgMask.size ())
+ end = (long) fgMask.size ();
+
+ for (long ii = begin; ii < end; ++ii)
+ {
+ fgMask[ii] = false;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayEvents
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::ReplayEvents (Bool replay)
+{
+ fgReplaying = replay;
+
+ if (replay)
+ {
+ EmEventPlayback::ResetPlayback ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayingEvents
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayingEvents (void)
+{
+ return fgReplaying;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayGetEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayGetEvent (void)
+{
+ EmAssert (EmEventPlayback::ReplayingEvents ());
+
+ Bool result = false;
+
+ EmRecordedEvent event;
+ if (EmEventPlayback::GetNextReplayEvent (event))
+ {
+ // Keep track of pen up/down state so that GetNextReplayEvent
+ // will filter properly.
+
+ fgIterationState.fPenIsDown = ::PrvIsPenDown (event);
+
+ switch (event.eType)
+ {
+ case kRecordedKeyEvent:
+
+ result = EmEventPlayback::ReplayKeyEvent (
+ event.keyEvent.ascii, event.keyEvent.keycode, event.keyEvent.modifiers);
+
+ break;
+
+ case kRecordedPenEvent:
+
+ result = EmEventPlayback::ReplayPenEvent (
+ event.penEvent.coords);
+
+ break;
+
+ case kRecordedAppSwitchEvent:
+
+ result = EmEventPlayback::ReplaySwitchEvent (
+ event.appSwitchEvent.cardNo, event.appSwitchEvent.dbID,
+ event.appSwitchEvent.oldCardNo, event.appSwitchEvent.oldDbID);
+
+ break;
+
+ case kRecordedNullEvent:
+
+ result = EmEventPlayback::ReplayNullEvent ();
+
+ break;
+
+ case kRecordedErrorEvent:
+
+ result = EmEventPlayback::ReplayErrorEvent ();
+
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ // Get information on this event.
+
+ EmEventOutput::GetEventInfo (event);
+ }
+ else
+ {
+ // No more events to return; turn ourself off.
+
+ EmEventPlayback::ReplayEvents (false);
+
+ // If minimization is running, tell it that we appear to have
+ // run the gamut.
+
+ if (EmMinimize::IsOn ())
+ {
+ EmMinimize::NoErrorOccurred ();
+ }
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayGetPen
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayGetPen (void)
+{
+ EmAssert (EmEventPlayback::ReplayingEvents ());
+
+ EmRecordedEvent event;
+ Bool haveEvent = EmEventPlayback::GetNextReplayEvent (event);
+
+ // The Palm OS shouldn't be asking for the pen location if the
+ // pen is up. And if the pen is still down, there should be a
+ // pen up event in here somewhere. Therefore, GetNextReplayEvent
+ // should not be returning false or a non-pen event. But if it
+ // does (and it *does* happen), fabricate a pen up.
+
+ if (!haveEvent)
+ {
+ PRINTF ("EmEventPlayback::ReplayGetPen[%ld]: no more events; fabricating a pen up event",
+ fgIterationState.fIndex - 1);
+
+ haveEvent = true;
+ event.eType = kRecordedPenEvent;
+ event.penEvent.coords.x = -1;
+ event.penEvent.coords.y = -1;
+
+ fgIterationState.fPenIsDown = false;
+ }
+ else if (event.eType != kRecordedPenEvent)
+ {
+ PRINTF ("EmEventPlayback::ReplayGetPen[%ld]: next event wasn't a pen event; fabricating a pen up event",
+ fgIterationState.fIndex - 1);
+
+ EmAssert (fgPrevIterationState.fOffset != -1);
+
+ fgIterationState = fgPrevIterationState;
+
+ // Invalidate the previously saved iteration state so that
+ // we can make sure we don't use it again.
+
+ fgPrevIterationState.fOffset = -1;
+
+ event.eType = kRecordedPenEvent;
+ event.penEvent.coords.x = -1;
+ event.penEvent.coords.y = -1;
+
+ fgIterationState.fPenIsDown = false;
+ }
+
+ EmAssert (haveEvent);
+ EmAssert (event.eType == kRecordedPenEvent);
+
+ Bool result = EmEventPlayback::ReplayPenEvent (event.penEvent.coords);
+
+ // Get information on this event.
+
+ EmEventOutput::GetEventInfo (event);
+
+ return result;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::RecordEvent
+// ---------------------------------------------------------------------------
+// Add the given event to our list of events, as long as recording is on.
+
+void EmEventPlayback::RecordEvent (const EmRecordedEvent& event)
+{
+ if (EmEventPlayback::RecordingEvents ())
+ {
+ EmStreamChunk s (fgEvents);
+ s.SetMarker (0, kStreamFromEnd);
+ s << event;
+
+ fgMask.push_back (true);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::FindFirstError
+// ---------------------------------------------------------------------------
+// Return the index of the first error event record. Return -1 if one could
+// not be found.
+
+long EmEventPlayback::FindFirstError (void)
+{
+ long result = 0;
+
+ // Iterate over all the events, counting them up.
+
+ EmRecordedEvent event;
+ EmStreamChunk s (fgEvents);
+
+ while (s.GetMarker () < s.GetLength ())
+ {
+ s >> event;
+
+ if (event.eType == kRecordedErrorEvent)
+ {
+ return result;
+ }
+
+ ++result;
+ }
+
+ return -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::LogEvents
+// ---------------------------------------------------------------------------
+// Print debug information about the given event to the Log file.
+
+void EmEventPlayback::LogEvents (void)
+{
+ long counter = 0;
+ EmRecordedEvent event;
+ EmStreamChunk s (fgEvents);
+
+ while (s.GetMarker () < s.GetLength ())
+ {
+ s >> event;
+
+ LogAppendMsg ("%d:", counter);
+ EmEventPlayback::LogEvent (event);
+
+ ++counter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::LogEvent
+// ---------------------------------------------------------------------------
+// Print debug information about the given event to the Log file.
+
+void EmEventPlayback::LogEvent (const EmRecordedEvent& inEvent)
+{
+ static const char* kStrings[] =
+ {
+ "kGremlinKeyEvent",
+ "kGremlinPenEvent",
+ "kGremlinAppSwitchEvent",
+ "kGremlinNullEvent",
+ "kGremlinErrorEvent"
+ };
+
+ LogAppendMsg (" eType = %d (%s)", inEvent.eType, kStrings[inEvent.eType]);
+
+ switch (inEvent.eType)
+ {
+ case kRecordedKeyEvent:
+
+ // If it's a printable character, print it. Otherwise,
+ // show its numerical value.
+
+ if ((inEvent.keyEvent.ascii < 0x0100) && isprint (inEvent.keyEvent.ascii))
+ LogAppendMsg (" ascii = %d (%c)", inEvent.keyEvent.ascii, (char) inEvent.keyEvent.ascii);
+ else
+ LogAppendMsg (" ascii = %d", inEvent.keyEvent.ascii);
+
+ // If there's a keycode, print it.
+
+ if (inEvent.keyEvent.keycode)
+ LogAppendMsg (" keycode = %d", inEvent.keyEvent.keycode);
+
+ // If there's a modifier, print it.
+
+ if (inEvent.keyEvent.modifiers)
+ LogAppendMsg (" modifiers = %d", inEvent.keyEvent.modifiers);
+
+ break;
+
+ case kRecordedPenEvent:
+
+ // Print X, Y.
+
+ LogAppendMsg (" coords.x = %d", inEvent.penEvent.coords.x);
+ LogAppendMsg (" coords.y = %d", inEvent.penEvent.coords.y);
+
+ break;
+
+ case kRecordedAppSwitchEvent:
+
+ LogAppendMsg (" cardNo = %d", inEvent.appSwitchEvent.cardNo);
+ LogAppendMsg (" dbID = %d", inEvent.appSwitchEvent.dbID);
+ LogAppendMsg (" oldCardNo = %d", inEvent.appSwitchEvent.oldCardNo);
+ LogAppendMsg (" oldDbID = %d", inEvent.appSwitchEvent.oldDbID);
+
+ break;
+
+ case kRecordedNullEvent:
+
+ break;
+
+ case kRecordedErrorEvent:
+
+ break;
+
+ default:
+
+ EmAssert (false);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ResetPlayback
+// ---------------------------------------------------------------------------
+
+void EmEventPlayback::ResetPlayback (void)
+{
+ fgIterationState = EmIterationState ();
+
+ // Invalidate the previously saved iteration state so that
+ // we can make sure we don't use it.
+
+ fgPrevIterationState.fOffset = -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::GetNextReplayEvent
+// ---------------------------------------------------------------------------
+
+/*
+ The filtering of events is a little tricky. The user can *request*
+ that an event be filtered or not filtered during subsequent event
+ playback. However, this request does not need to be heeded by the
+ actual playback function. This disobedience is mostly noticable
+ when dealing with pen events. If the pen is down and the pen up
+ is supposed to be filtered out, the pen event will be replayed
+ anyway. Similarly, if a pen up event is supposed to be returned but
+ the pen is not down (because previous pen down events were filtered
+ out), then event is not replayed.
+*/
+
+Bool EmEventPlayback::GetNextReplayEvent (EmRecordedEvent& event)
+{
+ EmStreamChunk s (fgEvents);
+ s.SetMarker (fgIterationState.fOffset, kStreamFromStart);
+
+ // Save the current position so that we can push back to it
+ // later if we have to (see EmEventPlayback::ReplayGetPen).
+
+ fgPrevIterationState = fgIterationState;
+
+ while (s.GetMarker () < s.GetLength ())
+ {
+ s >> event;
+
+ Bool eventEnabled = fgMask[fgIterationState.fIndex];
+
+ fgIterationState.fIndex++;
+ fgIterationState.fOffset = s.GetMarker ();
+
+ // If this is a pen up event:
+ //
+ // * Discard it if the pen is already up.
+ //
+ // * Return it if the pen is down, even if this event is
+ // masked out.
+
+ if (::PrvIsPenUp (event))
+ {
+ if (!fgIterationState.fPenIsDown)
+ {
+ continue;
+ }
+
+ return true;
+ }
+
+ // If this is any event and it's not masked out, return it.
+
+ if (eventEnabled)
+ {
+ // Make sure that the pen is not down if this is not a pen event.
+ // The code above should make sure that we never get into this
+ // state.
+ //
+ // Actually, it seems that Gremlins can generate a sequence of
+ // pen down events followed by something other than a pen up
+ // event. So no longer make this assert. Elsewhere in this
+ // module, we'll have to make sure we set fPenIsDown to false
+ // on non-pen events.
+
+ /*
+ if (!::PrvIsPenEvent (event) && fgIterationState.fPenIsDown)
+ {
+ EmAssert (false);
+ }
+ */
+
+ return true;
+ }
+
+ // This event is masked out -- move on to the next event.
+ }
+
+ // No event to return.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayKeyEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayKeyEvent (WChar ascii,
+ UInt16 keycode,
+ UInt16 modifiers)
+{
+ PRINTF ("EmEventPlayback::ReplayKeyEvent[%ld]: playing back key %d, %d, %d",
+ fgIterationState.fIndex - 1, ascii, keycode, modifiers);
+
+ // EvtEnqueueKey doesn't reset the event timer.
+
+ ::EvtResetAutoOffTimer ();
+
+ // Add the event to the event queue.
+
+ ::StubAppEnqueueKey (ascii, keycode, modifiers);
+
+ // Return that we posted an event.
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayPenEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayPenEvent (const PointType& pt)
+{
+ PRINTF ("EmEventPlayback::ReplayPenEvent[%ld]: playing back pen %d, %d",
+ fgIterationState.fIndex - 1, pt.x, pt.y);
+
+ // Add the event to the event queue.
+
+ ::StubAppEnqueuePt (&pt);
+
+ // Return that we posted an event.
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplaySwitchEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplaySwitchEvent (uint16 cardNo,
+ uint32 dbID,
+ uint16 /* oldCardNo */,
+ uint32 /* oldDbID */)
+{
+ PRINTF ("EmEventPlayback::ReplaySwitchEvent[%ld]: playing switch %d, %ld",
+ fgIterationState.fIndex - 1, cardNo, dbID);
+
+ // Switch to the indicated application.
+
+ ::SysUIAppSwitch (cardNo, dbID, sysAppLaunchCmdNormalLaunch, NULL);
+
+ // Return that we did NOT post an event, resulting in the event
+ // insertion mechanism posting a NULL event.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayNullEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayNullEvent (void)
+{
+ PRINTF ("EmEventPlayback::ReplayNullEvent[%ld]: playing NULL",
+ fgIterationState.fIndex - 1);
+
+ // Return that we did NOT post an event, resulting in the event
+ // insertion mechanism posting a NULL event.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmEventPlayback::ReplayErrorEvent
+// ---------------------------------------------------------------------------
+
+Bool EmEventPlayback::ReplayErrorEvent (void)
+{
+ PRINTF ("EmEventPlayback::ReplayErrorEvent[%ld]: playing error",
+ fgIterationState.fIndex - 1);
+
+ // Return that we did NOT post an event, resulting in the event
+ // insertion mechanism posting a NULL event.
+
+ return false;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ operator <<
+// ---------------------------------------------------------------------------
+// Flatten an EmRecordedEvent to the stream. Some events can be compressed by
+// not writing out fields that are commonly zero/NULL, or by writing out only
+// 8-bit values even though the field is a 16-bit type.
+
+EmStream& operator << (EmStream& inStream, const EmRecordedEvent& inEvent)
+{
+ switch (inEvent.eType)
+ {
+ case kRecordedKeyEvent:
+
+ if (inEvent.keyEvent.ascii < 256 &&
+ inEvent.keyEvent.keycode == 0 &&
+ inEvent.keyEvent.modifiers == 0)
+ {
+ inStream << (uint8) kStoredKeyEventCompressed;
+ inStream << (uint8) inEvent.keyEvent.ascii;
+ }
+ else
+ {
+ inStream << (uint8) kStoredKeyEvent;
+ inStream << inEvent.keyEvent.ascii;
+ inStream << inEvent.keyEvent.keycode;
+ inStream << inEvent.keyEvent.modifiers;
+ }
+
+ break;
+
+ case kRecordedPenEvent:
+
+ if (inEvent.penEvent.coords.x < 0 && inEvent.penEvent.coords.y < 0)
+ {
+ inStream << (uint8) kStoredPenEventCompressedUp;
+ }
+ else if (inEvent.penEvent.coords.x < 256 && inEvent.penEvent.coords.y < 256)
+ {
+ inStream << (uint8) kStoredPenEventCompressedXY;
+ inStream << (uint8) inEvent.penEvent.coords.x;
+ inStream << (uint8) inEvent.penEvent.coords.y;
+ }
+ else if (inEvent.penEvent.coords.x < 256)
+ {
+ inStream << (uint8) kStoredPenEventCompressedX;
+ inStream << (uint8) inEvent.penEvent.coords.x;
+ inStream << inEvent.penEvent.coords.y;
+ }
+ else if (inEvent.penEvent.coords.y < 256)
+ {
+ inStream << (uint8) kStoredPenEventCompressedX;
+ inStream << inEvent.penEvent.coords.x;
+ inStream << (uint8) inEvent.penEvent.coords.y;
+ }
+ else
+ {
+ inStream << (uint8) kStoredPenEvent;
+ inStream << inEvent.penEvent.coords.x;
+ inStream << inEvent.penEvent.coords.y;
+ }
+
+ break;
+
+ case kRecordedAppSwitchEvent:
+
+ inStream << (uint8) kStoredAppSwitchEvent;
+ inStream << inEvent.appSwitchEvent.cardNo;
+ inStream << inEvent.appSwitchEvent.dbID;
+ inStream << inEvent.appSwitchEvent.oldCardNo;
+ inStream << inEvent.appSwitchEvent.oldDbID;
+
+ break;
+
+ case kRecordedNullEvent:
+
+ inStream << (uint8) kStoredNullEvent;
+
+ break;
+
+ case kRecordedErrorEvent:
+
+ inStream << (uint8) kStoredErrorEvent;
+
+ break;
+
+ default:
+
+ EmAssert (false);
+ }
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >>
+// ---------------------------------------------------------------------------
+// Resurrect an EmRecordedEvent from the stream.
+
+EmStream& operator >> (EmStream& inStream, EmRecordedEvent& outEvent)
+{
+ uint8 temp;
+ uint8 storedType;
+ inStream >> storedType;
+
+ switch (storedType)
+ {
+ case kStoredKeyEvent:
+
+ outEvent.eType = kRecordedKeyEvent;
+
+ inStream >> outEvent.keyEvent.ascii;
+ inStream >> outEvent.keyEvent.keycode;
+ inStream >> outEvent.keyEvent.modifiers;
+
+ break;
+
+ case kStoredKeyEventCompressed:
+
+ outEvent.eType = kRecordedKeyEvent;
+
+ inStream >> temp;
+ outEvent.keyEvent.ascii = temp;
+ outEvent.keyEvent.keycode = 0;
+ outEvent.keyEvent.modifiers = 0;
+
+ break;
+
+ case kStoredPenEvent:
+
+ outEvent.eType = kRecordedPenEvent;
+
+ inStream >> outEvent.penEvent.coords.x;
+ inStream >> outEvent.penEvent.coords.y;
+
+ break;
+
+ case kStoredPenEventCompressedUp:
+
+ outEvent.eType = kRecordedPenEvent;
+ outEvent.penEvent.coords.x = -1;
+ outEvent.penEvent.coords.y = -1;
+
+ break;
+
+ case kStoredPenEventCompressedX:
+
+ outEvent.eType = kRecordedPenEvent;
+
+ inStream >> temp;
+ outEvent.penEvent.coords.x = temp;
+
+ inStream >> outEvent.penEvent.coords.y;
+
+ break;
+
+ case kStoredPenEventCompressedY:
+
+ outEvent.eType = kRecordedPenEvent;
+
+ inStream >> outEvent.penEvent.coords.x;
+
+ inStream >> temp;
+ outEvent.penEvent.coords.y = temp;
+
+ break;
+
+ case kStoredPenEventCompressedXY:
+
+ outEvent.eType = kRecordedPenEvent;
+
+ inStream >> temp;
+ outEvent.penEvent.coords.x = temp;
+
+ inStream >> temp;
+ outEvent.penEvent.coords.y = temp;
+
+ break;
+
+ case kStoredAppSwitchEvent:
+
+ outEvent.eType = kRecordedAppSwitchEvent;
+
+ inStream >> outEvent.appSwitchEvent.cardNo;
+ inStream >> outEvent.appSwitchEvent.dbID;
+ inStream >> outEvent.appSwitchEvent.oldCardNo;
+ inStream >> outEvent.appSwitchEvent.oldDbID;
+
+ break;
+
+ case kStoredAppSwitchEventCompressed:
+
+ EmAssert (false);
+
+ break;
+
+ case kStoredNullEvent:
+
+ outEvent.eType = kRecordedNullEvent;
+
+ break;
+
+ case kStoredNullEventCompressed:
+
+ EmAssert (false);
+
+ break;
+
+ case kStoredErrorEvent:
+
+ outEvent.eType = kRecordedErrorEvent;
+
+ break;
+
+ case kStoredErrorEventCompressed:
+
+ EmAssert (false);
+
+ break;
+
+ default:
+
+ EmAssert (false);
+ }
+
+ return inStream;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ operator <<
+// ---------------------------------------------------------------------------
+// Flatten a Chunk to the stream.
+
+EmStream& operator << (EmStream& s, const Chunk& chunk)
+{
+ s << chunk.GetLength ();
+ s.PutBytes (chunk.GetPointer (), chunk.GetLength ());
+ return s;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >>
+// ---------------------------------------------------------------------------
+// Resurrect a Chunk from the stream.
+
+EmStream& operator >> (EmStream& s, Chunk& chunk)
+{
+ long len;
+
+ s >> len;
+
+ chunk.SetLength (len);
+ s.GetBytes (chunk.GetPointer (), len);
+
+ return s;
+}
+
+
+EmRecordedEvent::EmRecordedEvent (void) :
+ eType (kRecordedUnknownEvent)
+{
+}
+
+EmRecordedEvent::EmRecordedEvent (const EmRecordedEvent& other)
+{
+ *this = other;
+}
+
+EmRecordedEvent::~EmRecordedEvent (void)
+{
+}
+
+EmRecordedEvent& EmRecordedEvent::operator= (const EmRecordedEvent& other)
+{
+ if (this != &other)
+ {
+ eType = other.eType;
+
+ switch (eType)
+ {
+ case kRecordedUnknownEvent:
+ EmAssert (false);
+ break;
+
+ case kRecordedKeyEvent:
+ keyEvent.ascii = other.keyEvent.ascii;
+ keyEvent.keycode = other.keyEvent.keycode;
+ keyEvent.modifiers = other.keyEvent.modifiers;
+ break;
+
+ case kRecordedPenEvent:
+ penEvent.coords = other.penEvent.coords;
+ break;
+
+ case kRecordedAppSwitchEvent:
+ appSwitchEvent.cardNo = other.appSwitchEvent.cardNo;
+ appSwitchEvent.dbID = other.appSwitchEvent.dbID;
+ appSwitchEvent.oldCardNo = other.appSwitchEvent.oldCardNo;
+ appSwitchEvent.oldDbID = other.appSwitchEvent.oldDbID;
+ break;
+
+ case kRecordedNullEvent:
+ break;
+
+ case kRecordedErrorEvent:
+ break;
+ }
+ }
+
+ return *this;
+}
diff --git a/SrcShared/EmEventPlayback.h b/SrcShared/EmEventPlayback.h
new file mode 100644
index 0000000..63a0a97
--- /dev/null
+++ b/SrcShared/EmEventPlayback.h
@@ -0,0 +1,200 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmEventPlayback_h
+#define EmEventPlayback_h
+
+#include "ChunkFile.h" // Chunk
+
+#include <limits.h> // LONG_MAX
+#include <vector> // vector
+
+/*
+ EmEventPlayback is responsible for managing the events generated
+ during a Gremlins run. It doesn't generate the events themselves,
+ but, one they're created, it has the following duties:
+
+ * Recording them in a list so that they can be replayed later.
+ * Replaying them later
+ * Saving them to and loading them from a file.
+ * Logging events for debugging.
+ * Filtering the events so that not all of them get replayed.
+
+ This system is accessed from the other following locations:
+
+ * CGremlins : record events as they are generated.
+ * EmDocument : start playback after loading.
+ * EmMinimize : set and filter events replayed.
+ * EmPalmOS : call Initialize, Reset, etc., methods.
+ * EmPatchMgr : reply events.
+ * EmPatchModuleSys : inhibit application switching.
+ * EmSession : inhibit user events during playback.
+ * Hordes : turn recording on/off; save and load events
+ as Gremlins are switched.
+*/
+
+class EmFileRef;
+class SessionFile;
+
+#ifdef _MSC_VER
+ // VC++ doesn't appear to find the bool specialization when you
+ // say just "vector<bool>", so let's use its typedef.
+typedef _Bvector EmRecordedEventFilter;
+#else
+typedef vector<bool> EmRecordedEventFilter;
+#endif
+
+enum EmRecordedEventType
+{
+ // New items can be freely added to this list, and the list
+ // can freely be re-ordered.
+
+ kRecordedUnknownEvent = -1,
+ kRecordedKeyEvent,
+ kRecordedPenEvent,
+ kRecordedAppSwitchEvent,
+ kRecordedNullEvent,
+ kRecordedErrorEvent
+};
+
+struct EmRecordedEvent
+{
+ EmRecordedEvent (void);
+ EmRecordedEvent (const EmRecordedEvent&);
+ ~EmRecordedEvent (void);
+
+ EmRecordedEvent& operator= (const EmRecordedEvent&);
+
+ EmRecordedEventType eType;
+
+ union
+ {
+ struct
+ {
+ WChar ascii;
+ UInt16 keycode;
+ UInt16 modifiers;
+ } keyEvent;
+
+ struct
+ {
+ PointType coords;
+ } penEvent;
+
+ struct
+ {
+ uint16 cardNo;
+ uint32 dbID;
+ uint16 oldCardNo;
+ uint32 oldDbID;
+ } appSwitchEvent;
+
+ struct
+ {
+ } nullEvent;
+
+ struct
+ {
+ } errorEvent;
+ };
+};
+
+
+
+class EmEventPlayback
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SaveEvents (SessionFile&);
+ static void LoadEvents (const EmFileRef&);
+ static void LoadEvents (SessionFile&);
+
+ static void RecordEvents (Bool);
+ static Bool RecordingEvents (void);
+ static void RecordKeyEvent (WChar ascii,
+ UInt16 keycode,
+ UInt16 modifiers);
+ static void RecordPenEvent (const PointType&);
+ static void RecordSwitchEvent (uint16 cardNo,
+ uint32 dbID,
+ uint16 oldCardNo,
+ uint32 oldDbID);
+ static void RecordNullEvent (void);
+ static void RecordErrorEvent (void);
+
+ static void Clear (void);
+ static void CullEvents (void);
+ static long CountEnabledEvents (void);
+
+ static long GetCurrentEvent (void);
+ static long GetNumEvents (void);
+ static long CountNumEvents (void);
+ static void GetEvent (long, EmRecordedEvent&);
+
+ static void EnableEvents (long begin = 0, long end = LONG_MAX);
+ static void DisableEvents (long begin = 0, long end = LONG_MAX);
+
+ static void ReplayEvents (Bool);
+ static Bool ReplayingEvents (void);
+ static Bool ReplayGetEvent (void);
+ static Bool ReplayGetPen (void);
+
+ static long FindFirstError (void);
+ static void LogEvents (void);
+
+ private:
+ static void RecordEvent (const EmRecordedEvent&);
+ static void LogEvent (const EmRecordedEvent&);
+ static void ResetPlayback (void);
+ static Bool GetNextReplayEvent (EmRecordedEvent&);
+
+ static Bool ReplayKeyEvent (WChar ascii,
+ UInt16 keycode,
+ UInt16 modifiers);
+ static Bool ReplayPenEvent (const PointType&);
+ static Bool ReplaySwitchEvent (uint16 cardNo,
+ uint32 dbID,
+ uint16 oldCardNo,
+ uint32 oldDbID);
+ static Bool ReplayNullEvent (void);
+ static Bool ReplayErrorEvent (void);
+
+ private:
+ static Chunk fgEvents;
+ static EmRecordedEventFilter fgMask;
+ static Bool fgRecording;
+ static Bool fgReplaying;
+
+ struct EmIterationState
+ {
+ EmIterationState (void) :
+ fIndex (0),
+ fOffset (0),
+ fPenIsDown (false)
+ {}
+
+ long fIndex;
+ long fOffset;
+ Bool fPenIsDown;
+ };
+
+ static EmIterationState fgIterationState;
+ static EmIterationState fgPrevIterationState;
+};
+
+#endif // EmEventPlayback_h
diff --git a/SrcShared/EmException.cpp b/SrcShared/EmException.cpp
new file mode 100644
index 0000000..dd664f8
--- /dev/null
+++ b/SrcShared/EmException.cpp
@@ -0,0 +1,242 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmException.h"
+
+#include "EmPalmFunction.h" // GetTrapName
+#include "EmSession.h" // gSession
+#include "ErrorHandling.h" // Errors::DoDialog
+#include "Hordes.h" // Hordes::Stop
+#include "Platform.h" // Platform::GetString
+#include "Strings.r.h" // kStr_InternalErrorException
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmException::EmException
+// ---------------------------------------------------------------------------
+
+EmException::EmException (void) throw () :
+ exception ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmException::~EmException
+// ---------------------------------------------------------------------------
+
+EmException::~EmException (void) throw ()
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionTopLevelAction::EmExceptionTopLevelAction
+// ---------------------------------------------------------------------------
+
+EmExceptionTopLevelAction::EmExceptionTopLevelAction (void) throw () :
+ EmException ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionTopLevelAction::~EmExceptionTopLevelAction
+// ---------------------------------------------------------------------------
+
+EmExceptionTopLevelAction::~EmExceptionTopLevelAction (void) throw ()
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionEnterDebugger::EmExceptionEnterDebugger
+// ---------------------------------------------------------------------------
+
+EmExceptionEnterDebugger::EmExceptionEnterDebugger (void) throw () :
+ EmExceptionTopLevelAction ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionEnterDebugger::~EmExceptionEnterDebugger
+// ---------------------------------------------------------------------------
+
+EmExceptionEnterDebugger::~EmExceptionEnterDebugger (void) throw ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionEnterDebugger::DoAction
+// ---------------------------------------------------------------------------
+
+void EmExceptionEnterDebugger::DoAction (void)
+{
+ // We've already entered debug mode. The only thing left to do
+ // is stop Gremlins.
+
+ // !!! This should probably be changed so that the only thing
+ // done at the point of error/exception is the sending of the
+ // state packet to the debugger. If that succeeds, this exception
+ // is thrown and performs the real entry into debug mode. Right
+ // now, both those tasks are intertwined in Debug::EnterDebugger.
+
+ // If we're entering the debugger while running a Gremlin, save the events.
+
+ if (Hordes::IsOn ())
+ {
+ Hordes::SaveEvents ();
+ }
+
+ Hordes::Stop ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionReset::EmExceptionReset
+// ---------------------------------------------------------------------------
+
+EmExceptionReset::EmExceptionReset (EmResetType type) throw () :
+ EmExceptionTopLevelAction (),
+ fType (type),
+ fWhat (),
+ fMessage (),
+ fException (0),
+ fTrapWord (0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionReset::~EmExceptionReset
+// ---------------------------------------------------------------------------
+
+EmExceptionReset::~EmExceptionReset (void) throw ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionReset::DoAction
+// ---------------------------------------------------------------------------
+
+void EmExceptionReset::DoAction (void)
+{
+ EmAssert (gSession);
+ gSession->Reset (fType);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionReset::what
+// ---------------------------------------------------------------------------
+
+const char* EmExceptionReset::what (void) const throw ()
+{
+ if (fWhat.empty ())
+ {
+ char buffer[1000] = {0};
+
+ string trapName (::GetTrapName (fTrapWord));
+ string errTemplate;
+
+ if (fException)
+ {
+ errTemplate = Platform::GetString (kStr_InternalErrorException);
+ sprintf (buffer, errTemplate.c_str (), fException, trapName.c_str ());
+ }
+ else if (!fMessage.empty ())
+ {
+ errTemplate = Platform::GetString (kStr_InternalErrorMessage);
+ sprintf (buffer, errTemplate.c_str (), fMessage.c_str (), trapName.c_str ());
+ }
+
+ if (strlen (buffer) > 0)
+ {
+ fWhat = buffer;
+
+ fWhat += Platform::GetString (kStr_WillNowReset);
+ }
+ }
+
+ return fWhat.c_str ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionReset::Display
+// ---------------------------------------------------------------------------
+
+void EmExceptionReset::Display (void) const
+{
+ // Generate fWhat.
+
+ this->what ();
+
+ // If there's something there, show it.
+
+ if (!fWhat.empty ())
+ {
+ Errors::DoDialog (this->what (), kDlgFlags_continue_debug_RESET, -1);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionNextGremlin::EmExceptionNextGremlin
+// ---------------------------------------------------------------------------
+
+EmExceptionNextGremlin::EmExceptionNextGremlin (void) throw () :
+ EmExceptionTopLevelAction ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionNextGremlin::~EmExceptionNextGremlin
+// ---------------------------------------------------------------------------
+
+EmExceptionNextGremlin::~EmExceptionNextGremlin (void) throw ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExceptionNextGremlin::DoAction
+// ---------------------------------------------------------------------------
+
+void EmExceptionNextGremlin::DoAction (void)
+{
+ Hordes::ErrorEncountered ();
+
+ // The previous session state has been safely tucked away in bed, and the
+ // next session state has been scheduled to be loaded. However, it will
+ // not actually be loaded until after the next opcode is executed. If
+ // that opcode causes an error (and may in fact be the reason for
+ // switching to a new Gremlin), then we'd end up executing it again. We
+ // don't want that, so let's run any queued "load next state" commands now.
+
+ EmAssert (gSession);
+ gSession->ExecuteSpecial (false);
+}
diff --git a/SrcShared/EmException.h b/SrcShared/EmException.h
new file mode 100644
index 0000000..20108ba
--- /dev/null
+++ b/SrcShared/EmException.h
@@ -0,0 +1,96 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmException_h
+#define EmException_h
+
+#include <exception>
+#include <string>
+
+// ---------- EmException ----------
+
+class EmException : public exception
+{
+ public:
+ EmException (void) throw ();
+ virtual ~EmException (void) throw ();
+};
+
+
+// ---------- EmExceptionTopLevelAction ----------
+// This class of exception is used to escape back
+// to the top level of the CPU loop and optionally
+// perform some action there.
+
+class EmExceptionTopLevelAction : public EmException
+{
+ public:
+ EmExceptionTopLevelAction (void) throw ();
+ virtual ~EmExceptionTopLevelAction (void) throw ();
+
+ virtual void DoAction (void) = 0;
+};
+
+
+// ---------- EmExceptionEnterDebugger ----------
+
+class EmExceptionEnterDebugger : public EmExceptionTopLevelAction
+{
+ public:
+ EmExceptionEnterDebugger (void) throw ();
+ virtual ~EmExceptionEnterDebugger (void) throw ();
+
+ virtual void DoAction (void);
+};
+
+
+// ---------- EmExceptionReset ----------
+
+class EmExceptionReset : public EmExceptionTopLevelAction
+{
+ public:
+ EmExceptionReset (EmResetType) throw ();
+ virtual ~EmExceptionReset (void) throw ();
+
+ virtual void DoAction (void);
+
+ void SetException (uint16 e) { fException = e; }
+ void SetMessage (const char* m) { fMessage = m; }
+ void SetTrapWord (uint16 tw) { fTrapWord = tw; }
+
+ virtual const char* what (void) const throw ();
+
+ void Display (void) const;
+
+ private:
+ EmResetType fType;
+ mutable string fWhat;
+ string fMessage;
+ uint16 fException;
+ uint16 fTrapWord;
+};
+
+
+// ---------- EmExceptionNextGremlin ----------
+
+class EmExceptionNextGremlin : public EmExceptionTopLevelAction
+{
+ public:
+ EmExceptionNextGremlin (void) throw ();
+ virtual ~EmExceptionNextGremlin (void) throw ();
+
+ virtual void DoAction (void);
+};
+
+
+#endif // EmException_h
diff --git a/SrcShared/EmExgMgr.cpp b/SrcShared/EmExgMgr.cpp
new file mode 100644
index 0000000..25f9374
--- /dev/null
+++ b/SrcShared/EmExgMgr.cpp
@@ -0,0 +1,681 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmExgMgr.h"
+
+#include "EmBankMapped.h" // EmBankMapped
+#include "EmCPU.h" // Emulator::SetBreakReason (kBreak_TaskFinished)
+#include "EmFileImport.h" // SetResult, SetDone
+#include "EmMemory.h" // EmMem_strncpy, EmMem_memset
+#include "EmPalmStructs.h" // SysLibTblEntryType, ExgGoToType, ExgSocketType
+#include "EmSession.h" // gSession, SuspendByTimeout
+#include "EmStream.h" // EmStream
+#include "EmStreamFile.h" // EmStreamFile
+#include "ROMStubs.h" // SysLibTblEntry
+
+
+// ======================================================================
+// Globals
+// ======================================================================
+
+#define exgLibCtlGetTitle 1 // get title for Exg dialogs
+#define exgLibCtlSpecificOp 0x8000 // start of range for library specific control codes
+
+const UInt16 kHostExgLibInitSocket = exgLibCtlSpecificOp | 0;
+const UInt16 kHostExgLibFreeSocket = exgLibCtlSpecificOp | 1;
+const UInt16 kHostExgLibBeamCompleted = exgLibCtlSpecificOp | 2;
+
+#define exgMemError (exgErrorClass | 1)
+#define exgErrStackInit (exgErrorClass | 2) // stack could not initialize
+#define exgErrUserCancel (exgErrorClass | 3)
+#define exgErrNoReceiver (exgErrorClass | 4) // receiver device not found
+#define exgErrNoKnownTarget (exgErrorClass | 5) // can't find a target app
+#define exgErrTargetMissing (exgErrorClass | 6) // target app is known but missing
+#define exgErrNotAllowed (exgErrorClass | 7) // operation not allowed
+#define exgErrBadData (exgErrorClass | 8) // internal data was not valid
+#define exgErrAppError (exgErrorClass | 9) // generic application error
+#define exgErrUnknown (exgErrorClass | 10) // unknown general error
+#define exgErrDeviceFull (exgErrorClass | 11) // device is full
+#define exgErrDisconnected (exgErrorClass | 12) // link disconnected
+#define exgErrNotFound (exgErrorClass | 13) // requested object not found
+#define exgErrBadParam (exgErrorClass | 14) // bad parameter to call
+#define exgErrNotSupported (exgErrorClass | 15) // operation not supported by this library
+#define exgErrDeviceBusy (exgErrorClass | 16) // device is busy
+#define exgErrBadLibrary (exgErrorClass | 17) // bad or missing ExgLibrary
+
+
+/***********************************************************************
+ *
+ * CLASS: EmExgMgr
+ *
+ * DESCRIPTION: This class represents an Exchange Manager driver
+ * library. It works in conjunction with an actual stub library
+ * installed by Poser into the current session when the session
+ * is created. Using HostControl callback functions, the stub
+ * library calls into methods in EmExgMgr subclasses. We thus
+ * create subclasses in order to provide specific library
+ * functionality.
+ *
+ * EmExgMgr doesn't do anything itself except define an interface.
+ * All useful functionality is provided by subclasses.
+ *
+ * Besides forwarding all calls ExgLib calls back to Poser via
+ * HostControl functions, the stub library does the following:
+ *
+ * * Looks for irGotDataChr characters in the event stream and
+ * starts a beam process when it finds one.
+ *
+ * * Sends a kHostExgLibInitSocket control code to the host
+ * driver to fill out the ExgSocketType data structure.
+ *
+ * * Calls ExgNotifyReceive. Note that having the stub library
+ * make this call is very important. If the host driver
+ * were to call ExgNotifyReceive in its implementation of
+ * ExgLibHandleEvent, then control would not be returned back
+ * to us until ExgNotifyReceive had completed. And without
+ * control, we can't update progress dialogs or look for
+ * clicks on Cancel buttons.
+ *
+ * * Sends a kHostExgLibFreeSocket control code to clean up anything
+ * set up by the kHostExgLibInitSocket code.
+ *
+ * * Sends a kHostExgLibBeamCompleted control code to the host
+ * driver in order to let it know that it can now remove any
+ * progress dialogs and/or display error messages.
+ *
+ * PROBLEMS:
+ *
+ * This module needs to take into account a number of problems
+ * in order to work:
+ *
+ * * There is a bug in Launcher 3.0 - 3.5 where it tries to send
+ * sysAppLaunchCmdSyncNotify to anything received that's not a
+ * PQA. We have a patch on SysAppLaunch to deal with this.
+ *
+ * * We have to make sure no UI will appear. We have patches on
+ * FrmCustomAlert and ExgDoDialog to make sure this doesn't happen.
+ *
+ * * Palm VII's aren't even registered to recieve PQAs!
+ *
+ ***********************************************************************/
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgr::EmExgMgr
+// ---------------------------------------------------------------------------
+// Constructor for abstract base class. Does nothing.
+
+EmExgMgr::EmExgMgr (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgr::~EmExgMgr
+// ---------------------------------------------------------------------------
+// Destructor for abstract base class. Does nothing.
+
+EmExgMgr::~EmExgMgr (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgr::GetExgMgr
+// ---------------------------------------------------------------------------
+// Static method for finding and returning the host-implemented Exchange
+// Manager driver associated with the given library or socket. Our stub
+// library stores the pointer to the EmExgMgr subclass in its library
+// globals field, so we fetch it from there.
+
+EmExgMgr* EmExgMgr::GetExgMgr (UInt16 libRefNum)
+{
+ emuptr entryP = (emuptr) ::SysLibTblEntry (libRefNum);
+ if (!entryP)
+ return NULL;
+
+ EmAliasSysLibTblEntryType<PAS> entry (entryP);
+ emuptr globalsP = entry.globalsP;
+ return (EmExgMgr*) globalsP;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * CLASS: EmExgMgrStream
+ *
+ * DESCRIPTION: .
+ *
+ ***********************************************************************/
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::EmExgMgrStream
+// ---------------------------------------------------------------------------
+
+EmExgMgrStream::EmExgMgrStream (EmStream& stream) :
+ fStream (stream)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::~EmExgMgrStream
+// ---------------------------------------------------------------------------
+
+EmExgMgrStream::~EmExgMgrStream (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibOpen
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibOpen (UInt16 /*libRefNum*/)
+{
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibClose
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibClose (UInt16 /*libRefNum*/)
+{
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibSleep
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibSleep (UInt16 /*libRefNum*/)
+{
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibWake
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibWake (UInt16 /*libRefNum*/)
+{
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibHandleEvent
+// ---------------------------------------------------------------------------
+
+Boolean EmExgMgrStream::ExgLibHandleEvent (UInt16 /*libRefNum*/, emuptr /*eventP*/)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibConnect
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibConnect (UInt16 libRefNum, emuptr exgSocketP)
+{
+ // Same as ExgLibPut? Applications seems to call ExgLibPut.
+ // Additionally, IrLib's version of ExgLibConnect merely forwards
+ // to ExgLibPut.
+
+ return EmExgMgrStream::ExgLibPut (libRefNum, exgSocketP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibAccept
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibAccept (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/)
+{
+ fStream.SetMarker (0, kStreamFromStart);
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibDisconnect
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibDisconnect (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/, Err error)
+{
+ return error;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibPut
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibPut (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/)
+{
+ // Same as ExgLibConnect? Applications seems to call ExgLibPut.
+ // Additionally, IrLib's version of ExgLibConnect merely forwards
+ // to ExgLibPut.
+
+ return exgErrNotSupported;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibGet
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibGet (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/)
+{
+ // What does this function do? Nothing in the ROM seems to call
+ // it, and the IrLib version merely returns zero.
+
+ return exgErrNotSupported;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibSend
+// ---------------------------------------------------------------------------
+
+UInt32 EmExgMgrStream::ExgLibSend (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/,
+ void* bufP, const UInt32 bufLen, Err* errP)
+{
+ if (bufLen > 0)
+ {
+ // Transfer the bytes.
+
+ *errP = fStream.PutBytes (bufP, bufLen);
+ }
+ else
+ {
+ *errP = errNone;
+ }
+
+ return bufLen;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibReceive
+// ---------------------------------------------------------------------------
+
+UInt32 EmExgMgrStream::ExgLibReceive (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/,
+ void* bufP, const UInt32 bufLen, Err* errP)
+{
+ // Determine how many bytes to transfer.
+
+ long amountToCopy = bufLen;
+ long amountLeftInBuffer = fStream.GetLength () - fStream.GetMarker ();
+ if (amountToCopy > amountLeftInBuffer)
+ amountToCopy = amountLeftInBuffer;
+
+ if (amountToCopy > 0)
+ {
+ // Transfer the bytes.
+
+ *errP = fStream.GetBytes (bufP, amountToCopy);
+ }
+ else
+ {
+ *errP = errNone;
+ }
+
+ return amountToCopy;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibControl
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibControl (UInt16 libRefNum, UInt16 op,
+ emuptr valueP, emuptr valueLenP)
+{
+ Err err = errNone;
+
+ switch (op)
+ {
+ case exgLibCtlGetTitle:
+ if (valueP && valueLenP)
+ {
+ EmAliasUInt16<PAS> valueLen (valueLenP);
+ EmMem_strncpy (valueP, "Poser Beam", valueLen);
+ }
+ else
+ {
+ err = exgErrBadParam;
+ }
+ break;
+
+ case kHostExgLibInitSocket:
+ if (valueP && valueLenP)
+ {
+ EmAliasUInt16<PAS> valueLen (valueLenP);
+ EmAliasExgSocketType<PAS> socket (valueP);
+
+ EmAssert ((UInt16) valueLen == socket.GetSize ());
+
+ const UInt16 kLocalModeBit = 0x8000;
+// const UInt16 kPacketModeBit = 0x4000;
+// const UInt16 kNoGoToBit = 0x2000;
+ const UInt16 kNoStatusBit = 0x1000;
+
+ EmMem_memset (valueP, 0, valueLen);
+
+ socket.libraryRef = libRefNum; // identifies the Exg library in use
+// socket.socketRef = 0; // used by Exg library to identify this connection
+// socket.target = 0; // Creator ID of application this is sent to
+// socket.count = 0; // # of objects in this connection (usually 1)
+// socket.length = 0; // # total byte count for all objects being sent (optional)
+// socket.time = 0; // last modified time of object (optional)
+// socket.appData = 0; // application specific info
+// socket.goToCreator = 0; // creator ID of app to launch with goto after receive
+// socket.goToParams; // If launchCreator then this contains goto find info
+// socket.goToParams.dbCardNo = 0; // card number of the database
+// socket.goToParams.dbID = 0; // LocalID of the database
+// socket.goToParams.recordNum = 0; // index of record that contain a match
+// socket.goToParams.uniqueID = 0; // postion in record of the match.
+// socket.goToParams.matchCustom = 0; // application specific info
+ socket.flags = kLocalModeBit | kNoStatusBit; // system flags
+// socket.description = EmMemNULL; // text description of object (for user)
+// socket.type = EmMemNULL; // Mime type of object (optional)
+// socket.name = EmMemNULL; // name of object, generally a file name (optional)
+
+ EmStreamFile* s = dynamic_cast<EmStreamFile*> (&fStream);
+ if (s)
+ {
+ fFileName = s->GetFileRef().GetName ();
+ EmBankMapped::MapPhysicalMemory (fFileName.c_str (), fFileName.size () + 1);
+ socket.name = EmBankMapped::GetEmulatedAddress (fFileName.c_str ());
+ }
+ }
+ else
+ {
+ err = exgErrBadParam;
+ }
+ break;
+
+ case kHostExgLibFreeSocket:
+ {
+ // Unmap file name and drop our reference to it.
+
+#ifndef NDEBUG
+ EmAliasUInt16<PAS> valueLen (valueLenP);
+#endif
+ EmAliasExgSocketType<PAS> socket (valueP);
+
+ EmAssert ((UInt16) valueLen == socket.GetSize ());
+
+ socket.name = EmMemNULL;
+ EmBankMapped::UnmapPhysicalMemory (fFileName.c_str ());
+ break;
+ }
+
+ default:
+ err = exgErrNotSupported;
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrStream::ExgLibRequest
+// ---------------------------------------------------------------------------
+
+Err EmExgMgrStream::ExgLibRequest (UInt16 /*libRefNum*/, emuptr /*exgSocketP*/)
+{
+ return exgErrNotSupported;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * CLASS: EmExgMgrImportWrapper
+ *
+ * DESCRIPTION: This class is used to wrap up other EmExgMgr
+ * implementations. It adds the facility for communicating
+ * information back to the EmFileImport class (for instance
+ * progress information and whether or not the beam
+ * process is completed). It also allows the beaming
+ * process to be aborted.
+ *
+ ***********************************************************************/
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::EmExgMgrImportWrapper
+// ---------------------------------------------------------------------------
+// Remember the wrapped object, as well as the EmFileImport object we
+// communicate with. Initialize our "aborting" flag to false.
+
+EmExgMgrImportWrapper::EmExgMgrImportWrapper (EmExgMgr& exgMgr, EmFileImport& importer) :
+ fExgMgr (exgMgr),
+ fImporter (importer),
+ fAborting (false)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::~EmExgMgrImportWrapper
+// ---------------------------------------------------------------------------
+
+EmExgMgrImportWrapper::~EmExgMgrImportWrapper (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::Cancel
+// ---------------------------------------------------------------------------
+// Set our "aborting" flag to true. This will cause our read and write
+// methods to return "user cancelled".
+
+void EmExgMgrImportWrapper::Cancel (void)
+{
+ fAborting = true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibOpen
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibOpen (UInt16 libRefNum)
+{
+ return fExgMgr.ExgLibOpen (libRefNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibClose
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibClose (UInt16 libRefNum)
+{
+ return fExgMgr.ExgLibClose (libRefNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibSleep
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibSleep (UInt16 libRefNum)
+{
+ return fExgMgr.ExgLibSleep (libRefNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibWake
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibWake (UInt16 libRefNum)
+{
+ return fExgMgr.ExgLibWake (libRefNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibHandleEvent
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Boolean EmExgMgrImportWrapper::ExgLibHandleEvent (UInt16 libRefNum, emuptr eventP)
+{
+ return fExgMgr.ExgLibHandleEvent (libRefNum, eventP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibConnect
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibConnect (UInt16 libRefNum, emuptr exgSocketP)
+{
+ return fExgMgr.ExgLibConnect (libRefNum, exgSocketP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibAccept
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibAccept (UInt16 libRefNum, emuptr exgSocketP)
+{
+ return fExgMgr.ExgLibAccept (libRefNum, exgSocketP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibDisconnect
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibDisconnect (UInt16 libRefNum, emuptr exgSocketP, Err error)
+{
+ return fExgMgr.ExgLibDisconnect (libRefNum, exgSocketP, error);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibPut
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibPut (UInt16 libRefNum, emuptr exgSocketP)
+{
+ return fExgMgr.ExgLibPut (libRefNum, exgSocketP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibGet
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibGet (UInt16 libRefNum, emuptr exgSocketP)
+{
+ return fExgMgr.ExgLibGet (libRefNum, exgSocketP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibSend
+// ---------------------------------------------------------------------------
+// If aborting, return "user cancelled". Otherwise, call the wrapped method.
+
+UInt32 EmExgMgrImportWrapper::ExgLibSend (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP)
+{
+ if (fAborting)
+ {
+ *errP = exgErrUserCancel;
+ return 0;
+ }
+
+ return fExgMgr.ExgLibSend (libRefNum, exgSocketP, bufP, bufLen, errP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibReceive
+// ---------------------------------------------------------------------------
+// If aborting, return "user cancelled". Otherwise, call the wrapped method.
+// Also, set the emulator flag indicating that the emulation loop should
+// exit. Doing this allows the UI task to regain control, update dialogs
+// and check for Stop button clicks.
+
+UInt32 EmExgMgrImportWrapper::ExgLibReceive (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP)
+{
+ if (fAborting)
+ {
+ *errP = exgErrUserCancel;
+ return 0;
+ }
+
+ UInt32 result = fExgMgr.ExgLibReceive (libRefNum, exgSocketP, bufP, bufLen, errP);
+
+ EmAssert (gSession);
+ gSession->ScheduleSuspendTimeout ();
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibControl
+// ---------------------------------------------------------------------------
+// See if the operation is "beam completed". If so, let the EmFileImport
+// object know so that it can close the progress dialog and report any
+// errors. In all cases, also call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibControl (UInt16 libRefNum, UInt16 op, emuptr valueP, emuptr valueLenP)
+{
+ if (op == kHostExgLibBeamCompleted)
+ {
+ EmAliasErr<PAS> err (valueP);
+
+ fImporter.SetResult ((Err) err);
+ fImporter.SetDone ();
+ }
+
+ return fExgMgr.ExgLibControl (libRefNum, op, valueP, valueLenP);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmExgMgrImportWrapper::ExgLibRequest
+// ---------------------------------------------------------------------------
+// Merely call the wrapped method.
+
+Err EmExgMgrImportWrapper::ExgLibRequest (UInt16 libRefNum, emuptr exgSocketP)
+{
+ return fExgMgr.ExgLibRequest (libRefNum, exgSocketP);
+}
diff --git a/SrcShared/EmExgMgr.h b/SrcShared/EmExgMgr.h
new file mode 100644
index 0000000..4783bcc
--- /dev/null
+++ b/SrcShared/EmExgMgr.h
@@ -0,0 +1,106 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmExgMgr_h
+#define EmExgMgr_h
+
+#include <string>
+
+class EmFileImport;
+class EmStream;
+
+class EmExgMgr
+{
+ public:
+ EmExgMgr (void);
+ virtual ~EmExgMgr (void);
+
+ static EmExgMgr* GetExgMgr (UInt16 libRefNum);
+
+ public:
+ virtual Err ExgLibOpen (UInt16 libRefNum) = 0;
+ virtual Err ExgLibClose (UInt16 libRefNum) = 0;
+ virtual Err ExgLibSleep (UInt16 libRefNum) = 0;
+ virtual Err ExgLibWake (UInt16 libRefNum) = 0;
+ virtual Boolean ExgLibHandleEvent (UInt16 libRefNum, emuptr eventP) = 0;
+ virtual Err ExgLibConnect (UInt16 libRefNum, emuptr exgSocketP) = 0;
+ virtual Err ExgLibAccept (UInt16 libRefNum, emuptr exgSocketP) = 0;
+ virtual Err ExgLibDisconnect (UInt16 libRefNum, emuptr exgSocketP, Err error) = 0;
+ virtual Err ExgLibPut (UInt16 libRefNum, emuptr exgSocketP) = 0;
+ virtual Err ExgLibGet (UInt16 libRefNum, emuptr exgSocketP) = 0;
+ virtual UInt32 ExgLibSend (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP) = 0;
+ virtual UInt32 ExgLibReceive (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP) = 0;
+ virtual Err ExgLibControl (UInt16 libRefNum, UInt16 op, emuptr valueP, emuptr valueLenP) = 0;
+ virtual Err ExgLibRequest (UInt16 libRefNum, emuptr exgSocketP) = 0;
+};
+
+
+class EmExgMgrStream : public EmExgMgr
+{
+ public:
+ EmExgMgrStream (EmStream&);
+ virtual ~EmExgMgrStream (void);
+
+ public:
+ virtual Err ExgLibOpen (UInt16 libRefNum);
+ virtual Err ExgLibClose (UInt16 libRefNum);
+ virtual Err ExgLibSleep (UInt16 libRefNum);
+ virtual Err ExgLibWake (UInt16 libRefNum);
+ virtual Boolean ExgLibHandleEvent (UInt16 libRefNum, emuptr eventP);
+ virtual Err ExgLibConnect (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibAccept (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibDisconnect (UInt16 libRefNum, emuptr exgSocketP,Err error);
+ virtual Err ExgLibPut (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibGet (UInt16 libRefNum, emuptr exgSocketP);
+ virtual UInt32 ExgLibSend (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP);
+ virtual UInt32 ExgLibReceive (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP);
+ virtual Err ExgLibControl (UInt16 libRefNum, UInt16 op, emuptr valueP, emuptr valueLenP);
+ virtual Err ExgLibRequest (UInt16 libRefNum, emuptr exgSocketP);
+
+ private:
+ EmStream& fStream;
+ string fFileName;
+};
+
+
+class EmExgMgrImportWrapper : public EmExgMgr
+{
+ public:
+ EmExgMgrImportWrapper (EmExgMgr&, EmFileImport&);
+ virtual ~EmExgMgrImportWrapper (void);
+
+ void Cancel (void);
+
+ public:
+ virtual Err ExgLibOpen (UInt16 libRefNum);
+ virtual Err ExgLibClose (UInt16 libRefNum);
+ virtual Err ExgLibSleep (UInt16 libRefNum);
+ virtual Err ExgLibWake (UInt16 libRefNum);
+ virtual Boolean ExgLibHandleEvent (UInt16 libRefNum, emuptr eventP);
+ virtual Err ExgLibConnect (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibAccept (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibDisconnect (UInt16 libRefNum, emuptr exgSocketP, Err error);
+ virtual Err ExgLibPut (UInt16 libRefNum, emuptr exgSocketP);
+ virtual Err ExgLibGet (UInt16 libRefNum, emuptr exgSocketP);
+ virtual UInt32 ExgLibSend (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP);
+ virtual UInt32 ExgLibReceive (UInt16 libRefNum, emuptr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP);
+ virtual Err ExgLibControl (UInt16 libRefNum, UInt16 op, emuptr valueP, emuptr valueLenP);
+ virtual Err ExgLibRequest (UInt16 libRefNum, emuptr exgSocketP);
+
+ private:
+ EmExgMgr& fExgMgr;
+ EmFileImport& fImporter;
+ Bool fAborting;
+};
+
+#endif // EmExgMgr_h
diff --git a/SrcShared/EmFileImport.cpp b/SrcShared/EmFileImport.cpp
new file mode 100644
index 0000000..2f514e7
--- /dev/null
+++ b/SrcShared/EmFileImport.cpp
@@ -0,0 +1,1823 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmFileImport.h"
+
+#include "EmCPU.h" // Emulator::ExecuteUntilIdle
+#include "EmDlg.h" // EmDlg::DoCommonDialog
+#include "EmErrCodes.h" // kError_OutOfMemory, ConvertFromPalmError, etc.
+#include "EmExgMgr.h" // EmExgMgrStream, EmExgMgrImport
+#include "EmLowMem.h" // TrapExists
+#include "EmPalmStructs.h" // SysLibTblEntryType, RecordEntryType, RsrcEntryType, etc.
+#include "EmPatchState.h" // EmPatchState::AutoAcceptBeamDialogs
+#include "EmSession.h" // ExecuteUntilIdle, gSession
+#include "EmStreamFile.h" // EmStreamFile, kOpenExistingForRead
+#include "ErrorHandling.h" // Errors::SetParameter
+#include "Miscellaneous.h" // StMemoryMapper
+#include "Platform.h" // Platform::DisposeMemory
+#include "ROMStubs.h" // ExgLibControl, DmFindDatabase, EvtEnqueueKey, EvtWakeup, DmDeleteDatabase, DmCreateDatabase...
+#include "Strings.r.h" // kStr_CmdInstall
+
+#include <algorithm> // find
+#include <stdio.h> // sprintf
+#include <time.h> // strftime
+
+
+/*
+ This module is responsible for installing files containing Palm OS
+ applications, databases, query applications, text data, vCals, and
+ vCards.
+
+ The entire installation process is handled by the EmFileImport
+ class. You can either create one of these and continually call its
+ Continue method until either it returns an error or its Done method
+ returns true. Using this approach is handy if you need to do
+ something else in-between calls to Continue (such as update a
+ progress dialog). If you don't need to do anything else (like
+ handle UI stuff), you could instead just call the static method
+ LoadPalmFileList. This method installs all the given files and
+ doesn't return until either an error occurs or the job is done.
+
+ Files are installed by one of two methods: either by using the
+ Exchange Manager, or by using low-level Database Manager routines.
+ The Exchange Manager is used when possible, and is the only way
+ that all supported file types can be installed. If the Exchange
+ Manager cannot be used (for example, we're emulating a Palm OS 2.0
+ device, or our custom Exchange Manager driver isn't installed),
+ only .prc, .pdb, and .pqa files can be installed. Additionally,
+ after the files are installed, any application that would like
+ to know about those files (like the Launcher) are NOT notified,
+ and may fail after the installation process. Therefore, we always
+ try to use the Exchange Manager if possible.
+
+ In order to use the Exchange Manager, we have to install and make
+ use of a small, custom driver library. This library is closely
+ integrated with Poser. In order to kick of an install process,
+ Poser makes an ExgLibControl call to our library. The library
+ then takes over, making the appropriate HostControl calls to
+ read in the contents of files, to update Poser's progress
+ indicator, and to report on the status of the install. Poser
+ merely sits back and updates the progress bar until the driver
+ says it's done.
+
+ If we're not using the Exchange Manager method, we instead use
+ standard Database Manager calls to install the file. That is,
+ we call DmCreateDatabase, DmNewResource, DmWrite, etc., in
+ order to convert the file into a database.
+*/
+
+const int kInstallStart = -1;
+const int kInstallMiddle = -2;
+const int kInstallEnd = -3;
+const int kInstallDone = -4;
+
+#define irGotDataChr 0x01FC // to initiate NotifyReceive
+
+const char kHostExgLibName[] = "HostExgLib";
+const UInt32 kHostExgLibCreator = 'HExg';
+
+ // Forward declarations.
+extern const uint8 kHostExgLib[];
+extern const int kHostExgLibSize;
+
+static Bool PrvDetermineMethod (EmFileImportMethod method);
+static Bool PrvCanUseExgMgr (void);
+static Bool PrvHasExgMgr (void);
+//static Bool PrvHostExgLibLoaded (void);
+static Bool PrvIsResources (UInt16 attributes);
+static Bool PrvIsResources (const EmAliasDatabaseHdrType<LAS>& hdr);
+static UInt32 PrvGetEntrySize (const EmAliasDatabaseHdrType<LAS>& hdr);
+static void PrvSetResourceTypeIDParameters (UInt32 resType, UInt16 resID);
+
+static ErrCode PrvValidateDatabase (const EmAliasDatabaseHdrType<LAS>& hdr, UInt32 size);
+static void PrvSetDate (const char* varName, uint32 seconds);
+static void PrvSetExgMgr (void* mgr);
+
+static UInt16 gHostExgLibRefNum;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::EmFileImport
+ *
+ * DESCRIPTION: Constructor. Initializes our data members.
+ *
+ * PARAMETERS: file - ref to file to install
+ * gotoWhenDone - if true, switch to the application that
+ * just received the file we installed and display it,
+ * if possible.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmFileImport::EmFileImport (EmStream& stream, EmFileImportMethod method) :
+ fUsingExgMgr (::PrvDetermineMethod (method)),
+ fGotoWhenDone (false),
+ fState (kInstallStart),
+ fError (errNone),
+ fStream (stream),
+
+ fExgMgrStream (NULL),
+ fExgMgrImport (NULL),
+ fOldAcceptBeamState (EmPatchState::AutoAcceptBeamDialogs (true)),
+
+ fFileBuffer (NULL),
+ fFileBufferSize (0),
+ fDBID (0),
+ fCardNo (0),
+ fOpenID (0),
+ fCurrentEntry (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::~EmFileImport
+ *
+ * DESCRIPTION: Destructor. Clean up.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmFileImport::~EmFileImport (void)
+{
+ ::PrvSetExgMgr (NULL);
+
+ delete fExgMgrStream;
+ delete fExgMgrImport;
+
+ Platform::DisposeMemory (fFileBuffer);
+
+ EmPatchState::AutoAcceptBeamDialogs (fOldAcceptBeamState);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::LoadPalmFile
+ *
+ * DESCRIPTION: Utility function to install a Palm application, given
+ * a buffer containing it.
+ *
+ * PARAMETERS: data - pointer to the image.
+ * size - number of bytes in the image
+ *
+ * RETURNED: result code
+ *
+ ***********************************************************************/
+
+ErrCode EmFileImport::LoadPalmFile (const void* data, uint32 size,
+ EmFileImportMethod method,
+ LocalID &newID)
+{
+ ErrCode err = errNone;
+ EmStreamBlock stream ((void*) data, size);
+ EmFileImport importer (stream, method);
+
+ while (!importer.Done () && err == errNone)
+ {
+ err = importer.Continue ();
+ }
+
+ newID = importer.GetLocalID ();
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::LoadPalmFileList
+ *
+ * DESCRIPTION: Utility function to install a collection of files. This
+ * is intended to be a faceless function; no UI is involved.
+ *
+ * PARAMETERS: fileList - collection of files to install.
+ *
+ * RETURNED: result code
+ *
+ ***********************************************************************/
+
+ErrCode EmFileImport::LoadPalmFileList (const EmFileRefList& fileList,
+ EmFileImportMethod method,
+ vector<LocalID>& newIDList)
+{
+ ErrCode err = errNone;
+
+ newIDList.clear ();
+
+ EmFileRefList::const_iterator iter = fileList.begin ();
+ while (iter != fileList.end ())
+ {
+ EmStreamFile stream (*iter, kOpenExistingForRead);
+ EmFileImport importer (stream, method);
+
+ while (!importer.Done () && err == errNone)
+ {
+ err = importer.Continue ();
+ }
+
+ newIDList.push_back (importer.GetLocalID ());
+
+ ++iter;
+ }
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::InstallExgMgrLib
+ *
+ * DESCRIPTION: Install our Exchange Manager stub driver library if it
+ * looks OK to do so. We install it if we're running
+ * OS 3.0 or later, and if the library is not already
+ * installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: result code
+ *
+ ***********************************************************************/
+
+ErrCode EmFileImport::InstallExgMgrLib (void)
+{
+ // Don't install it if we don't have the Exchange Manager.
+
+ if (!::PrvHasExgMgr ())
+ return errNone;
+
+ // Don't install it if it's already there.
+
+ LocalID id = ::DmFindDatabase (0, kHostExgLibName);
+ if (id != 0)
+ return errNone;
+
+ // OK to install it.
+
+ return EmFileImport::LoadPalmFile (kHostExgLib, kHostExgLibSize, kMethodHomebrew, id);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::CanUseExgMgr
+ *
+ * DESCRIPTION: Return whether or not it looks like we will use the
+ * Exchange Manager when installing files. Knowing this
+ * can be important upstream client who need to know
+ * what sorts of files to pass on to EmFileImport.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if we'll be using the ExgMgr.
+ *
+ ***********************************************************************/
+
+Bool EmFileImport::CanUseExgMgr (void)
+{
+ return ::PrvCanUseExgMgr ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::Continue
+ *
+ * DESCRIPTION: Install a small part of the application this object has
+ * been charged with installing. Clients should continually
+ * call this method until either it returns a non-zero
+ * result or the Done method returns true.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: result code
+ *
+ ***********************************************************************/
+
+ErrCode EmFileImport::Continue (void)
+{
+ // Install as much as we can in the allotted amount of time.
+
+ const uint32 kIntervalTimeMSecs = 100;
+ uint32 start = Platform::GetMilliseconds ();
+
+ while (fState != kInstallDone &&
+ (Platform::GetMilliseconds () - start) < kIntervalTimeMSecs)
+ {
+ this->IncrementalInstall ();
+
+ if (fError != errNone)
+ {
+ fState = kInstallDone;
+ }
+ }
+
+ return fError;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::Cancel
+ *
+ * DESCRIPTION: Clean up any partially installed file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: result code
+ *
+ ***********************************************************************/
+
+ErrCode EmFileImport::Cancel (void)
+{
+ if (fUsingExgMgr)
+ {
+ this->ExgMgrInstallCancel ();
+ }
+ else
+ {
+ this->HomeBrewInstallCancel ();
+ }
+
+ fState = kInstallDone;
+
+ return fError;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::Done
+ *
+ * DESCRIPTION: Returns whether or not the file this object has been
+ * charged with installing has been fully installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmFileImport::Done (void)
+{
+ return fState == kInstallDone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::GetProgress
+ *
+ * DESCRIPTION: Return a value indicating how far through the install
+ * process we currently are.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: A value ranging from 0 to the value returned from
+ * CalculateProgressMax if it were fed a list consisting
+ * solely of the file we're installing now.
+ *
+ ***********************************************************************/
+
+long EmFileImport::GetProgress (void)
+{
+ if (fUsingExgMgr)
+ {
+ return fStream.GetMarker ();
+ }
+ else
+ {
+ return fCurrentEntry;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::GetLocalID
+ *
+ * DESCRIPTION: Return the LocalID of the database we just installed.
+ * This is only valid when the importer is "Done".
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: -1 if no database has been installed, otherwise a valid
+ * LocalID.
+ *
+ ***********************************************************************/
+
+LocalID EmFileImport::GetLocalID (void)
+{
+ if (fUsingExgMgr)
+ {
+ return 0;
+ }
+ else
+ {
+ return fDBID;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::CalculateProgressMax
+ *
+ * DESCRIPTION: Generate a value that can be used as a progress
+ * indicator's maximum value. Note that the actual value
+ * returned is different depending on whether the Exchange
+ * or Database Manager is used, so don't try interpreting
+ * the result too closely.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: A progress indicator's maximum value.
+ *
+ ***********************************************************************/
+
+long EmFileImport::CalculateProgressMax (const EmFileRefList& files, EmFileImportMethod method)
+{
+ long result = 0;
+ Bool useExgMgr = ::PrvDetermineMethod (method);
+
+ EmFileRefList::const_iterator iter = files.begin ();
+ while (iter != files.end ())
+ {
+ EmStreamFile file (*iter, kOpenExistingForRead);
+
+ if (useExgMgr)
+ {
+ // Add up all the file sizes.
+
+ result += file.GetLength ();
+ }
+ else
+ {
+ // Add up all the number of entries.
+
+ EmProxyDatabaseHdrType hdr;
+ file.GetBytes (hdr.GetPtr (), hdr.GetSize ());
+ result += hdr.recordList.numRecords;
+ }
+
+ ++iter;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::SetResult
+ *
+ * DESCRIPTION: Called by external clients (notable the HostControl
+ * function called by our Exchange Manager driver) to set
+ * a result value.
+ *
+ * PARAMETERS: err - result of the install process. Can be errNone
+ * if no errors occurred.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::SetResult (Err err)
+{
+ this->SetResult (::ConvertFromPalmError (err));
+}
+
+
+void EmFileImport::SetResult (ErrCode err)
+{
+ fError = err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::SetDone
+ *
+ * DESCRIPTION: Called by external clients (notable the HostControl
+ * function called by our Exchange Manager driver) to set
+ * a result value.
+ *
+ * PARAMETERS: err - result of the install process. Can be errNone
+ * if no errors occurred.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::SetDone (void)
+{
+ fState = kInstallDone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::IncrementalInstall
+ *
+ * DESCRIPTION: Install a small part of the file. Examines the current
+ * installation method and state and calls a function
+ * appropriate for the next stage.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::IncrementalInstall (void)
+{
+ if (fUsingExgMgr)
+ {
+ switch (fState)
+ {
+ case kInstallStart: this->ExgMgrInstallStart (); break;
+ case kInstallMiddle: this->ExgMgrInstallMiddle (); break;
+ case kInstallEnd: this->ExgMgrInstallEnd (); break;
+ case kInstallDone: break;
+ }
+ }
+ else
+ {
+ switch (fState)
+ {
+ case kInstallStart: this->HomeBrewInstallStart (); break;
+ case kInstallMiddle: this->HomeBrewInstallMiddle (); break;
+ case kInstallEnd: this->HomeBrewInstallEnd (); break;
+ case kInstallDone: break;
+ }
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::ExgMgrInstallStart
+ *
+ * DESCRIPTION: Performs the first part of the installation process
+ * using the Exchange Manager. This stage involves telling
+ * our driver what file to install, and then telling it
+ * to start installing.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::ExgMgrInstallStart (void)
+{
+ this->ValidateStream ();
+ if (fError)
+ return;
+
+ // Create the stub ExgMgr driver callback object.
+
+ EmAssert (gHostExgLibRefNum != 0);
+ EmAssert (fExgMgrStream == NULL);
+ EmAssert (fExgMgrImport == NULL);
+
+ fStream.SetMarker (0, kStreamFromStart);
+ fExgMgrStream = new EmExgMgrStream (fStream);
+ fExgMgrImport = new EmExgMgrImportWrapper (*fExgMgrStream, *this);
+
+ // Tell the library what host-based driver to use.
+
+ ::PrvSetExgMgr (fExgMgrImport);
+
+ if (!fError)
+ {
+ // Kick off the install process.
+
+ Err err = ::EvtEnqueueKey (irGotDataChr, gHostExgLibRefNum, libEvtHookKeyMask);
+ this->SetResult (err);
+
+ err = ::EvtWakeup ();
+ }
+
+ fState = kInstallMiddle;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::ExgMgrInstallMiddle
+ *
+ * DESCRIPTION: Performs any repeating part of the installation process
+ * using the Exchange Manager. This stage merely involves
+ * giving the Emulator a chance to execute.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::ExgMgrInstallMiddle (void)
+{
+ EmAssert (gSession);
+// !!! gSession->ExecuteUntilIdle ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::ExgMgrInstallEnd
+ *
+ * DESCRIPTION: Performs any final part of the installation process
+ * using the Exchange Manager. There's nothing we need
+ * to do here. The end of the installation process is
+ * signalled when our Exchange Manager driver calls
+ * SetResult via the HostControl functions.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::ExgMgrInstallEnd (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::ExgMgrInstallCancel
+ *
+ * DESCRIPTION: Cancels the installation process using the Exchange
+ * Manager. We do this by sending a message to our
+ * Exchange Manager driver.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::ExgMgrInstallCancel (void)
+{
+ // Tell the library to stop.
+
+ fExgMgrImport->Cancel ();
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::HomeBrewInstallStart
+ *
+ * DESCRIPTION: Performs the first part of the installation process
+ * using the Database Manager. This stage involves
+ * loading the file, scoping out its header, deleting any
+ * old databases with the same name, creating the new
+ * database, setting its attributes, and opening it.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::HomeBrewInstallStart (void)
+{
+ this->ValidateStream ();
+ if (fError)
+ return;
+
+ Err err = errNone;
+
+ // Assume failure
+
+ fCardNo = 0;
+ fDBID = 0;
+ fOpenID = 0;
+
+ // Get the file and read it into memory.
+ // Set up a proxy to get to the header contents.
+
+ EmAssert (fFileBuffer == NULL);
+
+ fFileBufferSize = fStream.GetLength ();
+ fFileBuffer = Platform::AllocateMemory (fFileBufferSize);
+ if (!fFileBuffer)
+ {
+ this->SetResult (kError_OutOfMemory);
+ return;
+ }
+
+ fStream.SetMarker (0, kStreamFromStart);
+ fStream.GetBytes (fFileBuffer, fFileBufferSize);
+
+ EmAliasDatabaseHdrType<LAS> hdr (fFileBuffer);
+
+ // See if there's already a database with this name.
+ // If the database already exists, delete it.
+
+ LocalID tempID = ::DmFindDatabase (fCardNo, (Char*) hdr.name.GetPtr ());
+
+ if (tempID != 0)
+ {
+ err = ::DmDeleteDatabase (fCardNo, tempID);
+
+ if (err && err != dmErrROMBased)
+ goto Error;
+ }
+
+ // Create the new database
+
+ err = ::DmCreateDatabase (fCardNo, (Char*) hdr.name.GetPtr (),
+ hdr.creator, hdr.type, ::PrvIsResources (hdr));
+ if (err)
+ goto Error;
+
+ // Set the database info
+
+ fDBID = ::DmFindDatabase (fCardNo, (Char*) hdr.name.GetPtr ());
+ if (!fDBID)
+ {
+ err = ::DmGetLastErr ();
+ goto Error;
+ }
+
+ {
+ UInt16 attributes = hdr.attributes;
+ UInt16 version = hdr.version;
+ UInt32 creationDate = hdr.creationDate;
+ UInt32 modificationDate = hdr.modificationDate;
+ UInt32 lastBackupDate = hdr.lastBackupDate;
+ UInt32 modificationNumber = hdr.modificationNumber;
+ UInt32 type = hdr.type;
+ UInt32 creator = hdr.creator;
+
+ err = ::DmSetDatabaseInfo (fCardNo, fDBID, NULL,
+ &attributes, &version, &creationDate,
+ &modificationDate, &lastBackupDate,
+ &modificationNumber, NULL,
+ NULL, &type, &creator);
+
+ if (err)
+ goto Error;
+ }
+
+ // Open the new database
+
+ fOpenID = ::DmOpenDatabase (fCardNo, fDBID, dmModeReadWrite);
+ if (!fOpenID)
+ {
+ err = ::DmGetLastErr ();
+ goto Error;
+ }
+
+ // If this is a record database and there's an appInfo block, add it.
+
+ if (!::PrvIsResources (hdr))
+ {
+ if (hdr.appInfoID)
+ {
+ UInt32 recSize;
+ MemHandle newRecH;
+
+ EmAliasRecordEntryType<LAS> recordEntry (hdr.recordList.records);
+
+ if (hdr.sortInfoID)
+ {
+ recSize = (UInt32) hdr.sortInfoID - (UInt32) hdr.appInfoID;
+ }
+ else if (hdr.recordList.numRecords > 0)
+ {
+ recSize = (UInt32) recordEntry.localChunkID - (UInt32) hdr.appInfoID;
+ }
+ else
+ {
+ recSize = fFileBufferSize - (UInt32) hdr.appInfoID;
+ }
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%res_size", recSize);
+
+ // Allocate the new record.
+
+ newRecH = (MemHandle) ::DmNewHandle (fOpenID, recSize);
+ if (!newRecH)
+ {
+ err = ::DmGetLastErr ();
+ goto Error;
+ }
+
+ // Copy the data in.
+
+ UInt8* srcP = (UInt8*) hdr.GetPtr () + (UInt32) hdr.appInfoID;
+ UInt8* dstP = (UInt8*) ::MemHandleLock ((MemHandle) newRecH);
+ ::DmWrite (dstP, 0, srcP, recSize);
+ ::MemHandleUnlock ((MemHandle) newRecH);
+
+ // Store it in the header.
+
+ LocalID appInfoID = ::MemHandleToLocalID ((MemHandle) newRecH);
+ err = ::DmSetDatabaseInfo (fCardNo, fDBID, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, &appInfoID, NULL, NULL, NULL);
+
+ if (err)
+ goto Error;
+ }
+ }
+
+ // If there are resources/records, start installing them.
+
+ if (hdr.recordList.numRecords > 0)
+ fState = kInstallMiddle;
+ else
+ fState = kInstallEnd;
+
+ return;
+
+Error:
+ this->DeleteCurrentDatabase ();
+ this->SetResult (err);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::HomeBrewInstallMiddle
+ *
+ * DESCRIPTION: Performs any repeating part of the installation process
+ * using the Exchange Manager. This stage involves
+ * creating and installing the next resource or record
+ * in the file. If this is a record database and this
+ * is the first call to this method, we also install
+ * the appInfo record.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::HomeBrewInstallMiddle (void)
+{
+ Err err = errNone;
+
+ UInt8* srcP;
+ UInt8* dstP;
+
+ EmAssert (fFileBuffer);
+ EmAliasDatabaseHdrType<LAS> hdr (fFileBuffer);
+
+ //------------------------------------------------------------
+ // If it's a resource database, add the resources
+ //------------------------------------------------------------
+
+ if (::PrvIsResources (hdr))
+ {
+ UInt32 resSize;
+ MemHandle newResH;
+
+ EmAliasRsrcEntryType<LAS> rsrcEntry (hdr.recordList.resources[fCurrentEntry]);
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%record_number", fCurrentEntry);
+ ::PrvSetResourceTypeIDParameters (rsrcEntry.type, rsrcEntry.id);
+
+ // Calculate the size of the resource.
+
+ if (fCurrentEntry < hdr.recordList.numRecords - 1)
+ {
+ resSize = (UInt32) rsrcEntry[1].localChunkID;
+ resSize -= (UInt32) rsrcEntry.localChunkID;
+ }
+ else
+ {
+ resSize = fFileBufferSize - (UInt32) rsrcEntry.localChunkID;
+ }
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%res_size", resSize);
+
+ // Allocate the new resource.
+
+ newResH = (MemHandle) ::DmNewResource (fOpenID, rsrcEntry.type, rsrcEntry.id, resSize);
+ if (!newResH)
+ {
+ err = ::DmGetLastErr ();
+ if (err == dmErrMemError)
+ {
+ this->DeleteCurrentDatabase ();
+ this->SetResult (kError_BadDB_ResourceMemError);
+ return;
+ }
+ goto Error;
+ }
+
+ // Copy the data in.
+
+ srcP = (UInt8*) hdr.GetPtr () + (UInt32) rsrcEntry.localChunkID;
+ dstP = (UInt8*) ::MemHandleLock ((MemHandle) newResH);
+ ::DmWrite (dstP, 0, srcP, resSize);
+ ::MemHandleUnlock ((MemHandle) newResH);
+
+ // Done with it.
+
+ ::DmReleaseResource ((MemHandle) newResH);
+ }
+
+ //------------------------------------------------------------
+ // If it's a record database, add the records
+ //------------------------------------------------------------
+
+ else
+ {
+ UInt32 recSize;
+ MemHandle newRecH;
+
+ EmAliasRecordEntryType<LAS> recordEntry (hdr.recordList.records[fCurrentEntry]);
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%record_number", fCurrentEntry);
+
+ // Calculate the size of the record.
+
+ if (fCurrentEntry < hdr.recordList.numRecords - 1)
+ {
+ recSize = (UInt32) recordEntry[1].localChunkID;
+ recSize -= (UInt32) recordEntry.localChunkID;
+ }
+ else
+ {
+ recSize = fFileBufferSize - (UInt32) recordEntry.localChunkID;
+ }
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%res_size", recSize);
+
+ // Only add non-nil records. When the default databases are created
+ // they sometimes have nil records if the user had to delete a
+ // record they didn't want.
+
+ if (recSize)
+ {
+ // Allocate the new record.
+
+ UInt16 index = 0xFFFF;
+ newRecH = (MemHandle) ::DmNewRecord (fOpenID, &index, recSize);
+ if (!newRecH)
+ {
+ err = ::DmGetLastErr ();
+ if (err == dmErrMemError)
+ {
+ this->DeleteCurrentDatabase ();
+ this->SetResult (kError_BadDB_RecordMemError);
+ return;
+ }
+ goto Error;
+ }
+
+ // Copy the data in.
+
+ srcP = (UInt8*) hdr.GetPtr () + (UInt32) recordEntry.localChunkID;
+ dstP = (UInt8*) ::MemHandleLock ((MemHandle) newRecH);
+ ::DmWrite (dstP, 0, srcP, recSize);
+ ::MemHandleUnlock ((MemHandle) newRecH);
+
+ // Set the attributes.
+
+ UInt16 attr = recordEntry.attributes;
+ UInt32 id = recordEntry.uniqueID[0];
+ id = (id << 8) | recordEntry.uniqueID[1];
+ id = (id << 8) | recordEntry.uniqueID[2];
+ err = ::DmSetRecordInfo (fOpenID, index, &attr, &id);
+ if (err)
+ goto Error;
+
+ // Done with it.
+
+ ::DmReleaseRecord (fOpenID, index, true);
+ }
+ }
+
+ fCurrentEntry++;
+
+ if (fCurrentEntry >= hdr.recordList.numRecords)
+ {
+ fState = kInstallEnd;
+ }
+
+ return;
+
+Error:
+ this->DeleteCurrentDatabase ();
+ this->SetResult (err);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::HomeBrewInstallEnd
+ *
+ * DESCRIPTION: Performs any final part of the installation process
+ * using the Exchange Manager. This stage involves
+ * setting some final information about the database and
+ * then closing it up.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::HomeBrewInstallEnd (void)
+{
+ EmAssert (fFileBuffer);
+ EmAliasDatabaseHdrType<LAS> hdr (fFileBuffer);
+
+ // Fixup the modification # to match what was in the image.
+
+ EmAssert (fDBID);
+ UInt32 modificationNumber = hdr.modificationNumber;
+ Err err = ::DmSetDatabaseInfo (fCardNo, fDBID, NULL, NULL, NULL, NULL,
+ NULL, NULL, &modificationNumber, NULL, NULL, NULL, NULL);
+
+ if (err)
+ {
+ this->SetResult (err);
+ return;
+ }
+
+ // Close up and drop our references.
+
+ EmAssert (fOpenID);
+ ::DmCloseDatabase (fOpenID);
+
+ fOpenID = 0;
+// fDBID = 0; // Don't zap this, we return it in GetLocalID.
+
+ fState = kInstallDone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::HomeBrewInstallCancel
+ *
+ * DESCRIPTION: Cancels the installation process using the Database
+ * Manager. This stage involves merely deleting the
+ * database we were in the middle of creating.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::HomeBrewInstallCancel (void)
+{
+ this->DeleteCurrentDatabase ();
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::ValidateStream
+ *
+ * DESCRIPTION: Preflight the installation of certain files. If the
+ * stream contains a .prc, .pdb, or .pqa file, then make
+ * sure the contents are valid. Otherwise, the OS might
+ * discover the error and call ErrDisplay. We can't
+ * recover from that right now, so try to make sure it
+ * doesn't happen.
+ *
+ * Note: in general, the EmFileImport class doesn't care
+ * what kind of stream it's using for input. The stream
+ * could be a disk file, a memory buffer, or even a TCP
+ * socket. For the most part, we don't care. However,
+ * *this* function does. In order to help determine
+ * what the stream contains (one of the files we can
+ * validate, or something else, like a text, vCard, or
+ * vCal file), we look at the file type. Therefore,
+ * we try casting the base stream into an EmStreamFile.
+ * If that works, then we can check the file type. If
+ * the cast fails, then we just assume the best and
+ * say the file can be installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::ValidateStream (void)
+{
+ // Only validate resource/record files. Which, in turn, means
+ // that we can only validate EmStreamFiles. Anything else, well,
+ // we hope they're OK.
+
+ EmStreamFile* fileStream = dynamic_cast <EmStreamFile*> (&fStream);
+ if (fileStream == NULL)
+ return;
+
+ EmFileRef fileRef = fileStream->GetFileRef ();
+ if (fileRef.IsType (kFileTypePalmApp) ||
+ fileRef.IsType (kFileTypePalmDB) ||
+ fileRef.IsType (kFileTypePalmQA))
+ {
+ long len = fStream.GetLength ();
+ StMemory buffer (len);
+ void* bufferP = buffer.Get ();
+
+ fStream.SetMarker (0, kStreamFromStart);
+ fStream.GetBytes (bufferP, len);
+
+ EmAliasDatabaseHdrType<LAS> hdr (bufferP);
+
+ ErrCode err = ::PrvValidateDatabase (hdr, len);
+ this->SetResult (err);
+ }
+
+ // If we're installing something other than a resource/record
+ // file, then we can only do that if we're using the Exchange
+ // Manager
+
+ else
+ {
+ if (!fUsingExgMgr)
+ {
+ this->SetResult (kError_UnknownType);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileImport::DeleteCurrentDatabase
+ *
+ * DESCRIPTION: Delete the database currently being installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmFileImport::DeleteCurrentDatabase (void)
+{
+ if (fOpenID)
+ {
+ ::DmCloseDatabase (fOpenID);
+ fOpenID = 0;
+ }
+
+ if (fDBID)
+ {
+ ::DmDeleteDatabase (fCardNo, fDBID);
+ fDBID = 0;
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvDetermineMethod
+ *
+ * DESCRIPTION: Return whether or not we should use the Exchange
+ * Manager for installing the file. Right now, we check
+ * only for existance of the Exchange Manager and whether
+ * or not our library is installed. In the future, we may
+ * also check for valid file types and user preference
+ * settings.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if we'll be using the ExgMgr.
+ *
+ ***********************************************************************/
+
+Bool PrvDetermineMethod (EmFileImportMethod method)
+{
+ return
+ (method == kMethodExgMgr) ? true :
+ (method == kMethodHomebrew) ? false :
+ ::PrvCanUseExgMgr ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvCanUseExgMgr
+ *
+ * DESCRIPTION: Return whether or not we should use the Exchange
+ * Manager for installing the file. Right now, we check
+ * only for existance of the Exchange Manager and whether
+ * or not our library is installed. In the future, we may
+ * also check for valid file types and user preference
+ * settings.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if we'll be using the ExgMgr.
+ *
+ ***********************************************************************/
+
+Bool PrvCanUseExgMgr (void)
+{
+#if 0
+ return ::PrvHasExgMgr () && ::PrvHostExgLibLoaded ();
+#else
+ return false;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHasExgMgr
+ *
+ * DESCRIPTION: Return whether or not the Exchange Manager is installed.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if it is.
+ *
+ ***********************************************************************/
+
+Bool PrvHasExgMgr (void)
+{
+ return EmLowMem::TrapExists (sysTrapExgInit);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHostExgLibLoaded
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+#if 0
+Bool PrvHostExgLibLoaded (void)
+{
+ // Try finding the library.
+ UInt16 libRefNum;
+ Err err = ::SysLibFind (kHostExgLibName, &libRefNum);
+
+ // If we can't find it, try loading it.
+ if (err == sysErrLibNotFound)
+ err = ::SysLibLoad (sysFileTExgLib, kHostExgLibCreator, &libRefNum);
+
+ if (!err)
+ {
+ gHostExgLibRefNum = libRefNum;
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvIsResources
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool PrvIsResources (UInt16 attributes)
+{
+ return (attributes & dmHdrAttrResDB);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvIsResources
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool PrvIsResources (const EmAliasDatabaseHdrType<LAS>& hdr)
+{
+ return ::PrvIsResources (hdr.attributes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetEntrySize
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+UInt32 PrvGetEntrySize (const EmAliasDatabaseHdrType<LAS>& hdr)
+{
+ if (::PrvIsResources (hdr))
+ return EmAliasRsrcEntryType<LAS>::GetSize ();
+
+ return EmAliasRecordEntryType<LAS>::GetSize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvSetResourceTypeIDParameters
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void PrvSetResourceTypeIDParameters (UInt32 resType, UInt16 resID)
+{
+ char buffer[20];
+
+ sprintf (buffer, "%c%c%c%c",
+ (char) (resType >> 24),
+ (char) (resType >> 16),
+ (char) (resType >> 8),
+ (char) (resType >> 0));
+ Errors::SetParameter ("%res_type", buffer);
+
+ Errors::SetParameter ("%res_id", resID);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvValidateDatabaseHeader
+ *
+ * DESCRIPTION: Validates database header (to be used before any of the
+ * rest of the database is byteswapped or otherwise
+ * processed).
+ *
+ * PARAMETERS: hdrP - pointer to database header
+ * bufferSize - size of the buffer holding the database
+ *
+ * RETURNED: Err - error code
+ *
+ ***********************************************************************/
+
+static ErrCode PrvValidateDatabaseHeader(const EmAliasDatabaseHdrType<LAS>& hdr, UInt32 bufferSize)
+{
+ // Make sure the database name is not too long.
+
+ char* namePtr = (char*) hdr.name.GetPtr ();
+ size_t len = strlen (namePtr);
+
+ if (len >= dmDBNameLength)
+ {
+ char databaseName[dmDBNameLength];
+ memcpy (databaseName, namePtr, dmDBNameLength);
+
+ databaseName[dmDBNameLength - 4] = '.';
+ databaseName[dmDBNameLength - 3] = '.';
+ databaseName[dmDBNameLength - 2] = '.';
+ databaseName[dmDBNameLength - 1] = '\0';
+
+ Errors::SetParameter ("%database_name", databaseName);
+ return kError_BadDB_NameNotNULLTerminated;
+ }
+
+ // Check to see that name consists of printable characters
+
+ for (size_t ii = 0; ii < len; ++ii)
+ {
+ uint8 ch = (uint8) namePtr[ii];
+
+ if (ch < ' ' || ch > 0x7E)
+ {
+ Errors::SetParameter ("%database_name", namePtr);
+ return kError_BadDB_NameNotPrintable;
+ }
+ }
+
+ // Check that the modification date is not older than the creation date.
+ // We don't care about this and neither does the Palm OS, but HotSync does.
+
+ uint32 creationDate = hdr.creationDate;
+ uint32 modificationDate = hdr.modificationDate;
+
+ if (creationDate > modificationDate)
+ {
+ // Just show the problem here, but don't consider it fatal.
+ ::PrvSetDate ("%cr_date", hdr.creationDate);
+ ::PrvSetDate ("%mod_date", hdr.modificationDate);
+ Errors::SetParameter ("%database_name", namePtr);
+ string msg = Errors::ReplaceParameters (kStr_InconsistentDatabaseDates);
+ EmDlg::DoCommonDialog (msg, kDlgFlags_OK);
+ }
+
+ // Also check for zero creation dates.
+ // We don't care about this and neither does the Palm OS, but HotSync does.
+
+ else if (creationDate == 0)
+ {
+ // Just show the problem here, but don't consider it fatal.
+ Errors::SetParameter ("%database_name", namePtr);
+ string msg = Errors::ReplaceParameters (kStr_NULLDatabaseDate);
+ EmDlg::DoCommonDialog (msg, kDlgFlags_OK);
+ }
+
+ // Check that the resource/database records headers fit within the space
+ // of the buffer.
+
+ UInt32 endOfEntryArray = EmAliasDatabaseHdrType<LAS>::GetSize () +
+ ::PrvGetEntrySize (hdr) * hdr.recordList.numRecords;
+
+ if (endOfEntryArray > bufferSize)
+ return kError_BadDB_FileTooSmall;
+
+ // If we got here, we're okay.
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvValidateEntries
+ *
+ * DESCRIPTION: Validates entries in a database
+ *
+ * PARAMETERS: hdrP - pointer to database header
+ * bufferSize - size of the buffer holding the database
+ *
+ * RETURND: Err - error code
+ *
+ ***********************************************************************/
+
+static ErrCode PrvValidateEntries(const EmAliasDatabaseHdrType<LAS>& hdr, UInt32 bufferSize)
+{
+ Bool isResource = ::PrvIsResources (hdr);
+
+ // Establish the upper and lower ranges for localChunkIDs. These IDs are
+ // offsets from the beginning of the buffer/file, so they can't be larger
+ // than the size of the buffer/file, nor can they be smaller than the
+ // starting offset of the chunks.
+
+ UInt32 upperRange = bufferSize;
+ UInt32 lowerRange = EmAliasDatabaseHdrType<LAS>::GetSize () +
+ ::PrvGetEntrySize (hdr) * hdr.recordList.numRecords;
+
+ // Create an array to keep track of the discovered resource type/ids.
+ // This is so we can find duplicate entries.
+
+ typedef pair<UInt32, UInt16> ResTypeIDPair;
+ vector<ResTypeIDPair> resPairs;
+
+ // nextRecordListID not supported for now.
+
+ if (hdr.recordList.nextRecordListID != 0)
+ return kError_BadDB_nextRecordListIDNonZero;
+
+ for (UInt16 recordNumber = 0; recordNumber < hdr.recordList.numRecords; ++recordNumber)
+ {
+ LocalID itsLocalID;
+ long itsSize; // Use a signed value to detect decreasing LocalIDs
+
+ // Check for negative sizes and get the LocalID.
+ // ---------------------------------------------
+ // Though the code is similar for resources and for records, we have separate
+ // blocks so that we can safely cast to different types to access the localChunkID
+ // field.
+
+ if (isResource)
+ {
+ EmAliasRsrcEntryType<LAS> rsrcEntry (hdr.recordList.resources[recordNumber]);
+
+ // Set the error parameters in case an error occurs.
+
+ ::PrvSetResourceTypeIDParameters (rsrcEntry.type, rsrcEntry.id);
+
+ // Check for duplicate resources.
+
+ ResTypeIDPair thisPair (rsrcEntry.type, rsrcEntry.id);
+
+ if (find (resPairs.begin (), resPairs.end (), thisPair) != resPairs.end ())
+ return kError_BadDB_DuplicateResource;
+
+ resPairs.push_back (thisPair);
+
+ // Get the size of the resource.
+
+ if (recordNumber < hdr.recordList.numRecords - 1)
+ {
+ itsSize = (UInt32) rsrcEntry[1].localChunkID;
+ itsSize -= (UInt32) rsrcEntry.localChunkID;
+ }
+ else
+ itsSize = bufferSize - (UInt32) rsrcEntry.localChunkID;
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%res_size", itsSize);
+
+ // Check for negative sizes (zero is NOT okay for resources).
+
+ if (itsSize <= 0)
+ return kError_BadDB_ResourceTooSmall;
+
+ itsLocalID = rsrcEntry.localChunkID;
+ }
+ else
+ {
+ EmAliasRecordEntryType<LAS> recordEntry (hdr.recordList.records[recordNumber]);
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%record_number", recordNumber);
+
+ if (recordNumber < hdr.recordList.numRecords - 1)
+ {
+ itsSize = (UInt32) recordEntry[1].localChunkID;
+ itsSize -= (UInt32) recordEntry.localChunkID;
+ }
+ else
+ itsSize = bufferSize - (UInt32) recordEntry.localChunkID;
+
+ // Set the error parameters in case an error occurs.
+
+ Errors::SetParameter ("%res_size", itsSize);
+
+ // Check for negative sizes (zero is okay for records).
+
+ if (itsSize < 0)
+ return kError_BadDB_RecordTooSmall;
+
+ itsLocalID = recordEntry.localChunkID;
+ }
+
+ // Test that the beginning and ending of the chunk are in range.
+
+ if (itsLocalID < lowerRange || itsLocalID + itsSize > upperRange)
+ return isResource
+ ? kError_BadDB_ResourceOutOfRange
+ : kError_BadDB_RecordOutOfRange;
+ }
+
+ // If we got here, we're okay
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvValidateDatabase
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: hdrP - pointer to database header
+ * bufferSize - size of the buffer holding the database
+ *
+ * RETURNED: Err - error code
+ *
+ ***********************************************************************/
+
+static ErrCode PrvValidateDatabase (const EmAliasDatabaseHdrType<LAS>& hdr, UInt32 size)
+{
+ ErrCode err;
+
+ // Make sure the file has enough of a header to validate.
+
+ if (size < hdr.GetSize ())
+ {
+ err = kError_BadDB_FileTooSmall;
+ goto Exit;
+ }
+
+ // Validate the header.
+
+ err = ::PrvValidateDatabaseHeader (hdr, size);
+ if (err != errNone)
+ goto Exit;
+
+ // Check out the record entries; make sure they're okay
+
+ err = ::PrvValidateEntries (hdr, size);
+
+Exit:
+ if (!err)
+ Errors::ClearAllParameters ();
+
+ return err;
+}
+
+void PrvSetDate (const char* varName, uint32 seconds)
+{
+// this table tells you how many days since the last 'daysInFourYears' boundary.
+// That is, the first 12 entries give you the days in previous months for a leap year,
+// e.g. table entry 3 (March) is 60 because there are 31 days in January and 29 in February
+// each successive 12 entries give you the days in previous months for that year plus the
+// days in previous years. That allows you to do just one table lookup with (year % 4) + month
+// to find out how many days have gone by since the start of the previous leap year.
+// (See DateToDays for how this is used.)
+//
+// There's one extra entry at the end, so that this gives you the days in a given month:
+// daysInPrevMonths[(year%4)*12+month] - daysInPrevMonth[(year%4)*12+month-1]
+//
+// It's OK to use just one table for all this, because over our valid date range
+// (1904 - 2032) all years divisible by 4 are leap years.
+
+static const UInt16 daysInPrevMonths[] =
+{
+// +31 +29 +31 +30 +31 +30
+ 0, 31, 60, 91, 121, 152, // 1904, 1908, ...
+
+// +31 +31 +30 +31 +30 +31
+ 182, 213, 244, 274, 305, 335, // (leap years!)
+
+// +31 +28 +31 +30 +31 +30
+ 366+0, 366+31, 366+59, 366+90, 366+120, 366+151, // 1905, 1909, ...
+
+// +31 +31 +30 +31 +30 +31
+ 366+181, 366+212, 366+243, 366+273, 366+304, 366+334,
+
+ 731+0, 731+31, 731+59, 731+90, 731+120, 731+151, // 1906, 1910, ...
+ 731+181, 731+212, 731+243, 731+273, 731+304, 731+334,
+
+ 1096+0, 1096+31, 1096+59, 1096+90, 1096+120, 1096+151,// 1907, 1911, ...
+ 1096+181, 1096+212, 1096+243, 1096+273, 1096+304, 1096+334,
+
+ 1461
+};
+
+ UInt32 days;
+ UInt16 month;
+ DateTimeType dateTime;
+
+ // Now convert from seconds to days.
+ days = seconds / daysInSeconds;
+ seconds = seconds % daysInSeconds;
+ dateTime.weekDay = (days + 5) % daysInWeek;
+
+ // get year to nearest leap year
+ dateTime.year = firstYear + (days / daysInFourYears) * 4;
+
+ // now figure out month/year within 4-year range
+ days %= daysInFourYears;
+ month = 0;
+ while (days >= daysInPrevMonths[month])
+ month++;
+ month--;
+
+ dateTime.year += month / monthsInYear;
+ dateTime.month = (month % monthsInYear) + 1;
+ dateTime.day = days - daysInPrevMonths[month] + 1;
+
+ // now calc the time
+ dateTime.hour = seconds / hoursInSeconds;
+ seconds = seconds % hoursInSeconds;
+ dateTime.minute = seconds / minutesInSeconds;
+ seconds = seconds % minutesInSeconds;
+ dateTime.second = seconds;
+
+ // Convert this into text.
+
+ char buffer[200];
+ struct tm time;
+
+ time.tm_sec = dateTime.second;
+ time.tm_min = dateTime.minute;
+ time.tm_hour = dateTime.hour;
+ time.tm_mday = dateTime.day - 1;
+ time.tm_mon = dateTime.month - 1;
+ time.tm_year = dateTime.year - 1900;
+ time.tm_wday = dateTime.weekDay;
+ time.tm_yday = 0;
+ time.tm_isdst = -1;
+
+ strftime (buffer, 200, "%B %d, %Y, %I:%M:%S %p", &time);
+// strftime (buffer, 200, "%c", &time);
+
+ Errors::SetParameter (varName, buffer);
+}
+
+
+void PrvSetExgMgr (void* mgr)
+{
+ if (gHostExgLibRefNum)
+ {
+ emuptr tblP = (emuptr) ::SysLibTblEntry (gHostExgLibRefNum);
+ if (tblP)
+ {
+ EmAliasSysLibTblEntryType<PAS> tbl (tblP);
+ tbl.globalsP = (emuptr) mgr;
+ }
+ }
+}
+
+const uint8 kHostExgLib[] =
+{
+ 0x48, 0x6F, 0x73, 0x74, 0x45, 0x78, 0x67, 0x4C, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x01, 0xB5, 0x85, 0x65, 0x02, 0xB5, 0x85, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x78, 0x67, 0x6C,
+ 0x48, 0x45, 0x78, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x6C, 0x69,
+ 0x62, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x48, 0x7A, 0x00, 0x04, 0x06, 0x97,
+ 0x00, 0x00, 0x00, 0x06, 0x4E, 0x75, 0x2F, 0x0A, 0x2F, 0x03, 0x59, 0x4F, 0x24, 0x6F, 0x00, 0x12,
+ 0x48, 0x57, 0x3F, 0x3C, 0x00, 0x01, 0x2F, 0x3C, 0x70, 0x73, 0x79, 0x73, 0x4E, 0x4F, 0xA2, 0x7B,
+ 0x36, 0x00, 0x4F, 0xEF, 0x00, 0x0A, 0x66, 0x08, 0x0C, 0x97, 0x03, 0x00, 0x00, 0x00, 0x64, 0x06,
+ 0x30, 0x3C, 0x15, 0x02, 0x60, 0x0C, 0x4E, 0xBA, 0x02, 0x16, 0x24, 0x88, 0x42, 0xAA, 0x00, 0x04,
+ 0x70, 0x00, 0x58, 0x4F, 0x26, 0x1F, 0x24, 0x5F, 0x4E, 0x75, 0x3F, 0x2F, 0x00, 0x04, 0x3F, 0x3C,
+ 0x05, 0x80, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x54, 0x4F, 0x4E, 0x75, 0x3F, 0x2F, 0x00, 0x04,
+ 0x3F, 0x3C, 0x05, 0x81, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x54, 0x4F, 0x4E, 0x75, 0x3F, 0x2F,
+ 0x00, 0x04, 0x3F, 0x3C, 0x05, 0x83, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x54, 0x4F, 0x4E, 0x75,
+ 0x3F, 0x2F, 0x00, 0x04, 0x3F, 0x3C, 0x05, 0x82, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x54, 0x4F,
+ 0x4E, 0x75, 0x2F, 0x0A, 0x2F, 0x03, 0x59, 0x4F, 0x36, 0x2F, 0x00, 0x10, 0x24, 0x6F, 0x00, 0x12,
+ 0x0C, 0x52, 0x00, 0x04, 0x66, 0x10, 0x30, 0x2A, 0x00, 0x0C, 0x02, 0x40, 0x04, 0x00, 0x67, 0x06,
+ 0xB6, 0x6A, 0x00, 0x0A, 0x67, 0x06, 0x70, 0x00, 0x60, 0x00, 0x00, 0x9C, 0x0C, 0x6A, 0x01, 0xFC,
+ 0x00, 0x08, 0x66, 0x00, 0x00, 0x82, 0x3E, 0xBC, 0x00, 0x3C, 0x70, 0x00, 0x30, 0x17, 0x2F, 0x00,
+ 0x4E, 0x4F, 0xA0, 0x13, 0x24, 0x48, 0x20, 0x0A, 0x58, 0x4F, 0x66, 0x04, 0x70, 0x00, 0x60, 0x76,
+ 0x42, 0x67, 0x2F, 0x0A, 0x4E, 0x4F, 0xA0, 0x1B, 0x48, 0x6F, 0x00, 0x06, 0x2F, 0x0A, 0x3F, 0x3C,
+ 0x80, 0x00, 0x3F, 0x03, 0x4E, 0x4F, 0xA8, 0x0D, 0x3F, 0x40, 0x00, 0x14, 0x4A, 0x6F, 0x00, 0x14,
+ 0x4F, 0xEF, 0x00, 0x12, 0x66, 0x0C, 0x2F, 0x0A, 0x4E, 0x4F, 0xA3, 0x10, 0x3F, 0x40, 0x00, 0x06,
+ 0x58, 0x4F, 0x48, 0x57, 0x2F, 0x0A, 0x3F, 0x3C, 0x80, 0x01, 0x3F, 0x03, 0x4E, 0x4F, 0xA8, 0x0D,
+ 0x42, 0xA7, 0x48, 0x6F, 0x00, 0x12, 0x3F, 0x3C, 0x80, 0x02, 0x3F, 0x03, 0x4E, 0x4F, 0xA8, 0x0D,
+ 0x2F, 0x0A, 0x4E, 0x4F, 0xA0, 0x12, 0x4A, 0x6F, 0x00, 0x1E, 0x57, 0xC0, 0x44, 0x00, 0x48, 0x80,
+ 0x4F, 0xEF, 0x00, 0x20, 0x60, 0x12, 0x2F, 0x0A, 0x3F, 0x03, 0x3F, 0x3C, 0x05, 0x84, 0x4E, 0x4F,
+ 0xA3, 0x44, 0x54, 0x4F, 0x5C, 0x4F, 0x58, 0x4F, 0x26, 0x1F, 0x24, 0x5F, 0x4E, 0x75, 0x2F, 0x2F,
+ 0x00, 0x06, 0x3F, 0x2F, 0x00, 0x08, 0x3F, 0x3C, 0x05, 0x85, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F,
+ 0x5C, 0x4F, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x06, 0x3F, 0x2F, 0x00, 0x08, 0x3F, 0x3C, 0x05, 0x86,
+ 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x5C, 0x4F, 0x4E, 0x75, 0x3F, 0x2F, 0x00, 0x0A, 0x2F, 0x2F,
+ 0x00, 0x08, 0x3F, 0x2F, 0x00, 0x0A, 0x3F, 0x3C, 0x05, 0x87, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F,
+ 0x50, 0x4F, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x06, 0x3F, 0x2F, 0x00, 0x08, 0x3F, 0x3C, 0x05, 0x89,
+ 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x5C, 0x4F, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x06, 0x3F, 0x2F,
+ 0x00, 0x08, 0x3F, 0x3C, 0x05, 0x88, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x5C, 0x4F, 0x4E, 0x75,
+ 0x2F, 0x2F, 0x00, 0x12, 0x2F, 0x2F, 0x00, 0x12, 0x2F, 0x2F, 0x00, 0x12, 0x2F, 0x2F, 0x00, 0x12,
+ 0x3F, 0x2F, 0x00, 0x14, 0x3F, 0x3C, 0x05, 0x8A, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x4F, 0xEF,
+ 0x00, 0x12, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x12, 0x2F, 0x2F, 0x00, 0x12, 0x2F, 0x2F, 0x00, 0x12,
+ 0x2F, 0x2F, 0x00, 0x12, 0x3F, 0x2F, 0x00, 0x14, 0x3F, 0x3C, 0x05, 0x8B, 0x4E, 0x4F, 0xA3, 0x44,
+ 0x54, 0x4F, 0x4F, 0xEF, 0x00, 0x12, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x0C, 0x2F, 0x2F, 0x00, 0x0C,
+ 0x3F, 0x2F, 0x00, 0x0E, 0x3F, 0x2F, 0x00, 0x0E, 0x3F, 0x3C, 0x05, 0x8C, 0x4E, 0x4F, 0xA3, 0x44,
+ 0x54, 0x4F, 0x4F, 0xEF, 0x00, 0x0C, 0x4E, 0x75, 0x2F, 0x2F, 0x00, 0x06, 0x3F, 0x2F, 0x00, 0x08,
+ 0x3F, 0x3C, 0x05, 0x8D, 0x4E, 0x4F, 0xA3, 0x44, 0x54, 0x4F, 0x5C, 0x4F, 0x4E, 0x75, 0x41, 0xFA,
+ 0x00, 0x04, 0x4E, 0x75, 0x00, 0x1E, 0x00, 0x2A, 0x00, 0x2E, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A,
+ 0x00, 0x3E, 0x00, 0x42, 0x00, 0x46, 0x00, 0x4A, 0x00, 0x4E, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5A,
+ 0x00, 0x5E, 0x48, 0x6F, 0x73, 0x74, 0x45, 0x78, 0x67, 0x4C, 0x69, 0x62, 0x00, 0x00, 0x4E, 0xFA,
+ 0xFD, 0xCA, 0x4E, 0xFA, 0xFD, 0xD8, 0x4E, 0xFA, 0xFD, 0xF8, 0x4E, 0xFA, 0xFD, 0xE2, 0x4E, 0xFA,
+ 0xFE, 0x02, 0x4E, 0xFA, 0xFE, 0xCA, 0x4E, 0xFA, 0xFE, 0xDC, 0x4E, 0xFA, 0xFE, 0xEE, 0x4E, 0xFA,
+ 0xFF, 0x1A, 0x4E, 0xFA, 0xFF, 0x00, 0x4E, 0xFA, 0xFF, 0x28, 0x4E, 0xFA, 0xFF, 0x48, 0x4E, 0xFA,
+ 0xFF, 0x68, 0x4E, 0xFA, 0xFF, 0x84
+};
+
+const int kHostExgLibSize = sizeof (kHostExgLib);
+
diff --git a/SrcShared/EmFileImport.h b/SrcShared/EmFileImport.h
new file mode 100644
index 0000000..6eef35e
--- /dev/null
+++ b/SrcShared/EmFileImport.h
@@ -0,0 +1,96 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EMFILEIMPORT_H
+#define EMFILEIMPORT_H
+
+#include "EmDirRef.h" // EmFileRefList
+#include "EmTypes.h" // ErrCode
+
+class EmExgMgr;
+class EmExgMgrImportWrapper;
+class EmStream;
+
+enum EmFileImportMethod
+{
+ kMethodBest,
+ kMethodHomebrew,
+ kMethodExgMgr
+};
+
+
+class EmFileImport
+{
+ public:
+ EmFileImport (EmStream& stream,
+ EmFileImportMethod method);
+ ~EmFileImport (void);
+
+ static ErrCode LoadPalmFile (const void*, uint32, EmFileImportMethod, LocalID&);
+ static ErrCode LoadPalmFileList (const EmFileRefList&, EmFileImportMethod, vector<LocalID>&);
+
+ static ErrCode InstallExgMgrLib (void);
+ static Bool CanUseExgMgr (void);
+
+ // Interface for the dialog to display its stuff
+
+ ErrCode Continue (void);
+ ErrCode Cancel (void);
+ Bool Done (void);
+ long GetProgress (void);
+ LocalID GetLocalID (void);
+
+ void SetResult (Err);
+ void SetResult (ErrCode);
+ void SetDone (void);
+
+ static long CalculateProgressMax (const EmFileRefList&, EmFileImportMethod method);
+
+ private:
+ void IncrementalInstall (void);
+
+ void ExgMgrInstallStart (void);
+ void ExgMgrInstallMiddle (void);
+ void ExgMgrInstallEnd (void);
+ void ExgMgrInstallCancel (void);
+
+ void HomeBrewInstallStart (void);
+ void HomeBrewInstallMiddle (void);
+ void HomeBrewInstallEnd (void);
+ void HomeBrewInstallCancel (void);
+
+ void ValidateStream (void);
+ void DeleteCurrentDatabase (void);
+
+ private:
+ Bool fUsingExgMgr;
+ Bool fGotoWhenDone;
+ long fState;
+ ErrCode fError;
+ EmStream& fStream;
+
+ // Fields for ExgMgr installer
+ EmExgMgr* fExgMgrStream;
+ EmExgMgrImportWrapper* fExgMgrImport;
+ Bool fOldAcceptBeamState;
+
+ // Fields for homebrew installer
+ void* fFileBuffer;
+ long fFileBufferSize;
+ LocalID fDBID;
+ UInt16 fCardNo;
+ DmOpenRef fOpenID;
+ long fCurrentEntry;
+};
+
+#endif /* EMFILEIMPORT_H */
diff --git a/SrcShared/EmFileRef.cpp b/SrcShared/EmFileRef.cpp
new file mode 100644
index 0000000..d089919
--- /dev/null
+++ b/SrcShared/EmFileRef.cpp
@@ -0,0 +1,57 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmFileRef.h"
+
+static EmFileRef gEmulatorRef;
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::SetEmulatorRef
+ *
+ * DESCRIPTION: Set the ref corresponding to the emulator application.
+ *
+ * PARAMETERS: ref -.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void EmFileRef::SetEmulatorRef (const EmFileRef& ref)
+{
+ EmAssert (ref.IsSpecified ());
+ EmAssert (!gEmulatorRef.IsSpecified ());
+
+ gEmulatorRef = ref;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::GetEmulatorRef
+ *
+ * DESCRIPTION: Return the ref corresponding to the emulator application.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: ref - .
+ *
+ ***********************************************************************/
+
+EmFileRef EmFileRef::GetEmulatorRef (void)
+{
+ EmAssert (gEmulatorRef.IsSpecified ());
+
+ return gEmulatorRef;
+}
diff --git a/SrcShared/EmFileRef.h b/SrcShared/EmFileRef.h
new file mode 100644
index 0000000..9499018
--- /dev/null
+++ b/SrcShared/EmFileRef.h
@@ -0,0 +1,137 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmFileRef_h
+#define EmFileRef_h
+
+#include "EmDirRef.h" // EmDirRef
+#include <vector>
+
+enum EmFileCreator
+{
+ kFileCreatorNone,
+ kFileCreatorEmulator,
+ kFileCreatorInstaller,
+ kFileCreatorTeachText,
+ kFileCreatorCodeWarrior,
+ kFileCreatorCodeWarriorProfiler,
+
+ kFileCreatorLast
+};
+typedef vector<EmFileCreator> EmFileCreatorList;
+
+enum EmFileType
+{
+ kFileTypeNone,
+ kFileTypeApplication,
+ kFileTypeROM,
+ kFileTypeSession,
+ kFileTypeEvents,
+ kFileTypePreference,
+ kFileTypePalmApp,
+ kFileTypePalmDB,
+ kFileTypePalmQA,
+ kFileTypeText,
+ kFileTypePicture,
+ kFileTypeSkin,
+ kFileTypeProfile,
+ kFileTypePalmAll,
+ kFileTypeAll,
+
+ kFileTypeLast
+};
+
+enum EmFileAttr
+{
+ kFileAttrReadOnly=1,
+ kFileAttrHidden=2,
+ kFileAttrSystem=4,
+
+ kFileAttrLast
+};
+
+typedef vector<EmFileType> EmFileTypeList;
+
+class EmFileRef
+{
+ public:
+ EmFileRef (void);
+ EmFileRef (const EmFileRef&);
+ EmFileRef (const char*);
+ EmFileRef (const string&);
+ EmFileRef (const EmDirRef&, const char*);
+ EmFileRef (const EmDirRef&, const string&);
+#if PLATFORM_MAC
+ EmFileRef (const unsigned char*);
+ EmFileRef (const FSSpec&);
+ EmFileRef (AliasHandle);
+#endif
+ ~EmFileRef (void);
+
+ EmFileRef& operator= (const EmFileRef&);
+
+ Bool IsSpecified (void) const;
+ Bool Exists (void) const;
+ void Delete (void) const;
+
+ Bool IsType (EmFileType) const;
+ void SetCreatorAndType(EmFileCreator creator,
+ EmFileType fileType) const;
+ int GetAttr (int * attr) const;
+ int SetAttr (int attr) const;
+
+ string GetName (void) const;
+ EmDirRef GetParent (void) const;
+ string GetFullPath (void) const;
+
+ bool operator== (const EmFileRef&) const;
+ bool operator!= (const EmFileRef&) const;
+ bool operator< (const EmFileRef&) const;
+ bool operator> (const EmFileRef&) const;
+
+ bool FromPrefString (const string&);
+ string ToPrefString (void) const;
+
+ static void SetEmulatorRef (const EmFileRef&);
+ static EmFileRef GetEmulatorRef (void);
+
+#if PLATFORM_MAC
+ public:
+ // Needed in order to convert an EmFileRef into something
+ // that PowerPlant or Mac OS can deal with.
+
+ FSSpec GetFSSpec (void) const;
+ AliasHandle GetAlias (void) const;
+
+ private:
+ void UpdateAlias (void);
+ void UpdateSpec (void);
+
+ Bool IsType (OSType type, const char* suffix) const;
+
+ AliasHandle fFileAlias;
+ FSSpec fFileSpec;
+#endif
+
+#if PLATFORM_WINDOWS || PLATFORM_UNIX
+ private:
+ void MaybePrependCurrentDirectory (void);
+ void MaybeResolveLink (void);
+ void MaybeNormalize (void);
+
+ private:
+ string fFilePath;
+#endif
+};
+
+#endif /* EmFileRef_h */
diff --git a/SrcShared/EmJPEG.cpp b/SrcShared/EmJPEG.cpp
new file mode 100644
index 0000000..2e7193a
--- /dev/null
+++ b/SrcShared/EmJPEG.cpp
@@ -0,0 +1,902 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmJPEG.h"
+
+#include "EmPixMap.h" // SetSize, GetRowBytes, etc.
+#include "EmStream.h" // GetLength, GetBytes
+#include "Platform.h" // Platform::DisposeMemory, AllocateMemory
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressSource::EmJPEGDecompressSource (void)
+{
+ this->next_input_byte = 0;
+ this->bytes_in_buffer = 0;
+
+ // Fill in fields/function pointers used by JPEG engine
+
+ this->init_source = &init_source_cb;
+ this->fill_input_buffer = &fill_input_buffer_cb;
+ this->skip_input_data = &skip_input_data_cb;
+ this->resync_to_restart = &jpeg_resync_to_restart;
+ this->term_source = &term_source_cb;
+
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource destructor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressSource::~EmJPEGDecompressSource (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource::init_source_cb
+ *
+ * DESCRIPTION: Callback function that retrieves the pointer to the
+ * object managing the decompression and then calls the
+ * appropriate method of that object.
+ *
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressSource::init_source_cb (j_decompress_ptr cinfo)
+{
+ ((EmJPEGDecompressSource*) cinfo->src)->InitSource (cinfo);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource::fill_input_buffer_cb
+ *
+ * DESCRIPTION: Callback function that retrieves the pointer to the
+ * object managing the decompression and then calls the
+ * appropriate method of that object.
+ *
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded. It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return. If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer. In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there. However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later. In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any). The application should resume
+ * decompression after it has loaded more data into the input buffer. Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+boolean EmJPEGDecompressSource::fill_input_buffer_cb (j_decompress_ptr cinfo)
+{
+ return ((EmJPEGDecompressSource*) cinfo->src)->FillInputBuffer (cinfo);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource::skip_input_data_cb
+ *
+ * DESCRIPTION: Callback function that retrieves the pointer to the
+ * object managing the decompression and then calls the
+ * appropriate method of that object.
+ *
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return. If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ * num_bytes - number of bytes to skip.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressSource::skip_input_data_cb (j_decompress_ptr cinfo, long num_bytes)
+{
+ ((EmJPEGDecompressSource*) cinfo->src)->SkipInputData (cinfo, num_bytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSource::term_source_cb
+ *
+ * DESCRIPTION: Callback function that retrieves the pointer to the
+ * object managing the decompression and then calls the
+ * appropriate method of that object.
+ *
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read. Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressSource::term_source_cb (j_decompress_ptr cinfo)
+{
+ ((EmJPEGDecompressSource*) cinfo->src)->TermSource (cinfo);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: data - pointer to the memory buffer holding the
+ * compressed JPEG data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressMemSource::EmJPEGDecompressMemSource (const void* data, long len) :
+ fData (data),
+ fDataLen (len)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource destructor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressMemSource::~EmJPEGDecompressMemSource (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource::InitSource
+ *
+ * DESCRIPTION: Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressMemSource::InitSource (j_decompress_ptr /*cinfo*/)
+{
+ // Fill in fields/function pointers used by JPEG engine
+
+ this->next_input_byte = (const JOCTET*) fData;
+ this->bytes_in_buffer = (size_t) fDataLen;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource::FillInputBuffer
+ *
+ * DESCRIPTION: See fill_input_buffer_cb. Unused in this class.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+boolean EmJPEGDecompressMemSource::FillInputBuffer (j_decompress_ptr /*cinfo*/)
+{
+ EmAssert (false);
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource::SkipInputData
+ *
+ * DESCRIPTION: See skip_input_data_cb.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ * num_bytes - number of bytes to skip.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressMemSource::SkipInputData (j_decompress_ptr /*cinfo*/, long num_bytes)
+{
+ this->next_input_byte += (size_t) num_bytes;
+ this->bytes_in_buffer -= (size_t) num_bytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressMemSource::TermSource
+ *
+ * DESCRIPTION: See term_source_cb
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressMemSource::TermSource (j_decompress_ptr /*cinfo*/)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: data - pointer to the memory buffer holding the
+ * compressed JPEG data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressStreamSource::EmJPEGDecompressStreamSource (EmStream& s) :
+ fStream (s),
+ fBuffer (NULL)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource destructor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressStreamSource::~EmJPEGDecompressStreamSource (void)
+{
+ Platform::DisposeMemory (fBuffer);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource::InitSource
+ *
+ * DESCRIPTION: Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressStreamSource::InitSource (j_decompress_ptr /*cinfo*/)
+{
+ // Fill in fields/function pointers used by JPEG engine
+
+ this->bytes_in_buffer = (size_t) fStream.GetLength ();
+ this->fBuffer = Platform::AllocateMemory (this->bytes_in_buffer);
+ this->next_input_byte = (const JOCTET*) fBuffer;
+
+ fStream.GetBytes (fBuffer, this->bytes_in_buffer);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource::FillInputBuffer
+ *
+ * DESCRIPTION: See fill_input_buffer_cb. Unused in this class.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+boolean EmJPEGDecompressStreamSource::FillInputBuffer (j_decompress_ptr /*cinfo*/)
+{
+ EmAssert (false);
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource::SkipInputData
+ *
+ * DESCRIPTION: See skip_input_data_cb.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ * num_bytes - number of bytes to skip.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressStreamSource::SkipInputData (j_decompress_ptr /*cinfo*/, long num_bytes)
+{
+ this->next_input_byte += (size_t) num_bytes;
+ this->bytes_in_buffer -= (size_t) num_bytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressStreamSource::TermSource
+ *
+ * DESCRIPTION: See term_source_cb
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressStreamSource::TermSource (j_decompress_ptr /*cinfo*/)
+{
+}
+
+
+#pragma mark -
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSink::EmJPEGDecompressSink
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressSink::EmJPEGDecompressSink (void) :
+ fBuffer (NULL),
+ fBufferHeight (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressSink::~EmJPEGDecompressSink
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressSink::~EmJPEGDecompressSink (void)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ErrorExit
+ *
+ * DESCRIPTION: Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error. Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object. Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void ErrorExit (j_common_ptr)
+{
+ // !!! TBD if we want to handle mal-formed JPEG files.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: OutputMessage
+ *
+ * DESCRIPTION: Actual output of an error or trace message.
+ *
+ * Applications may override this method to send JPEG messages somewhere
+ * other than stderr.
+ *
+ * On Windows, printing to stderr is generally completely useless,
+ * so we provide optional code to produce an error-dialog popup.
+ * Most Windows applications will still prefer to override this routine,
+ * but if they don't, it'll do something at least marginally useful.
+ *
+ * NOTE: to use the library in an environment that doesn't support the
+ * C stdio library, you may have to delete the call to fprintf() entirely,
+ * not just not use this routine.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void OutputMessage (j_common_ptr)
+{
+ // !!! TBD if we want to report messages.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmitMessage
+ *
+ * DESCRIPTION: Decide whether to emit a trace or warning message.
+ *
+ * msg_level is one of:
+ * -1: recoverable corrupt-data warning, may want to abort.
+ * 0: important advisory messages (always display to user).
+ * 1: first level of tracing detail.
+ * 2,3,...: successively more detailed tracing messages.
+ * An application might override this method if it wanted to abort on warnings
+ * or change the policy about which messages to display.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void EmitMessage (j_common_ptr, int)
+{
+ // !!! TBD if we want to report messages
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FormatMessage
+ *
+ * DESCRIPTION: Format a message string for the most recent JPEG error
+ * or message.
+ *
+ * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
+ * characters. Note that no '\n' character is added to the string.
+ * Few applications should need to override this method.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void
+FormatMessage (j_common_ptr, char*)
+{
+ // !!! TBD if we want to report messages
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ResetError
+ *
+ * DESCRIPTION: Reset error state variables at start of a new image.
+ *
+ * This is called during compression startup to reset trace/error
+ * processing to default state, without losing any application-specific
+ * method pointers. An application might possibly want to override
+ * this method if it has additional error processing state.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static void ResetError (j_common_ptr)
+{
+ // !!! TBD if we want to reset after errors
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: InitError
+ *
+ * DESCRIPTION: Initialize the jpeg_error_mgr object. We use our own
+ * routine instead of jpeg_std_error so that we don't pull
+ * in a bunch of JPEG lib routines we don't want.
+ *
+ * PARAMETERS: err - pointer to the block used by the JPEG error mgr.
+ *
+ * RETURNED: Pointer to same.
+ *
+ ***********************************************************************/
+
+static struct jpeg_error_mgr*
+InitError (struct jpeg_error_mgr* err)
+{
+ err->error_exit = ErrorExit;
+ err->emit_message = EmitMessage;
+ err->output_message = OutputMessage;
+ err->format_message = FormatMessage;
+ err->reset_error_mgr = ResetError;
+
+ err->trace_level = 0; /* default = no tracing */
+ err->num_warnings = 0; /* no warnings emitted yet */
+ err->msg_code = 0; /* may be useful as a flag for "no error" */
+
+ /* Initialize message table pointers */
+ err->jpeg_message_table = NULL;
+ err->last_jpeg_message = 0;
+
+ err->addon_message_table = NULL;
+ err->first_addon_message = 0; /* for safety */
+ err->last_addon_message = 0;
+
+ return err;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink c'tor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressPixMapSink::EmJPEGDecompressPixMapSink (EmPixMap& pixMap) :
+ EmJPEGDecompressSink (),
+ fPixMap (pixMap),
+ fDataWidth (0),
+ fRowWidth (0),
+ fPadBytes (0),
+ fCurOutputRow (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink d'tor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmJPEGDecompressPixMapSink::~EmJPEGDecompressPixMapSink (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink::post_jpeg_read_header
+ *
+ * DESCRIPTION: Called by the JPEG decompression engine after the JPEG
+ * header has been read. Initializes some of our data
+ * members according to what was read.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void
+EmJPEGDecompressPixMapSink::post_jpeg_read_header (j_decompress_ptr cinfo)
+{
+ // Calculate output image dimensions so we can allocate space
+
+ jpeg_calc_output_dimensions (cinfo);
+
+ // Prepare the EmPixMap.
+
+ EmAssert (cinfo->out_color_space == JCS_RGB);
+
+ fPixMap.SetSize (EmPoint (cinfo->output_width, cinfo->output_height));
+ fPixMap.SetFormat (kPixMapFormat24RGB);
+
+ // Determine width of rows in the EmPixMap.
+
+ fDataWidth = cinfo->output_width * cinfo->output_components;
+ fRowWidth = fPixMap.GetRowBytes ();
+ fPadBytes = fRowWidth - fDataWidth;
+
+ // Prepare for write pass
+
+ fCurOutputRow = 0;
+
+ // Create decompressor output buffer. This buffer is passed to
+ // jpeg_read_scanlines as a scanline output buffer.
+
+ fBuffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, fDataWidth, 1);
+ fBufferHeight = 1;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink::start_output
+ *
+ * DESCRIPTION: Write any initial part of the output file.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressPixMapSink::start_output (j_decompress_ptr)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink::put_pixel_rows
+ *
+ * DESCRIPTION: Write some pixel data.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ * JDIMENSION - number of rows. This parameter is really
+ * just a holdover from the JPEG sample code; in our
+ * implementation, it's always 1.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressPixMapSink::put_pixel_rows (j_decompress_ptr, JDIMENSION)
+{
+ int line = fCurOutputRow++;
+ char* outptr = (char*) fPixMap.GetBits () + line * fRowWidth;
+ JSAMPROW inptr = fBuffer[0];
+
+ // Copy the source pixels. They're in RGB format, which is what
+ // we've set our destination pixmap to be.
+
+ memcpy (outptr, inptr, fDataWidth);
+
+ // Zero out the pad bytes.
+
+ if (fPadBytes)
+ {
+ memset (outptr + fDataWidth, 0, fPadBytes);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmJPEGDecompressPixMapSink::finish_output
+ *
+ * DESCRIPTION: Write any data that needs to be written after all the
+ * pixel rows have been processed.
+ *
+ * PARAMETERS: cinfo - data block describing the decompression process.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmJPEGDecompressPixMapSink::finish_output (j_decompress_ptr /* cinfo */)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ConvertJPEG
+ *
+ * DESCRIPTION: Drive the entire JPEG decompression process. Compressed
+ * data is provided by src_mgr; decompressed data is
+ * handled by dest_mgr. When this function is completed,
+ * the decompresed image can be picked up from dest_mgr.
+ *
+ * PARAMETERS: src_mgr - object that provides compressed JPEG data.
+ * dest_mgr - object that handles decompressed JPEG data.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ConvertJPEG (EmJPEGDecompressSource& src_mgr, EmJPEGDecompressSink& dest_mgr)
+{
+ // Modelled after main() in djpeg.c.
+
+ struct jpeg_decompress_struct cinfo; // Defined by JPEG lib; contains decompression state (including pointer to src manager).
+ struct jpeg_error_mgr jerr; // Defined by JPEG lib; contains methods for reporting errors
+
+
+ // Initialize the JPEG decompression object with default error handling.
+
+ cinfo.err = ::InitError (&jerr);
+ jpeg_create_decompress (&cinfo);
+
+ // Specify data source for decompression
+
+ cinfo.src = (jpeg_source_mgr*) &src_mgr;
+
+ // Read file header, set default decompression parameters
+
+ (void) jpeg_read_header (&cinfo, TRUE);
+
+ // Initialize the output module now to let it override any crucial
+ // option settings (for instance, GIF wants to force color quantization).
+
+ dest_mgr.post_jpeg_read_header (&cinfo);
+
+ // Start decompressor
+
+ (void) jpeg_start_decompress (&cinfo);
+
+ // Write output file header
+
+ dest_mgr.start_output (&cinfo);
+
+ // Process data
+
+ while (cinfo.output_scanline < cinfo.output_height)
+ {
+ JDIMENSION num_scanlines;
+ num_scanlines = jpeg_read_scanlines (&cinfo,
+ dest_mgr.fBuffer,
+ dest_mgr.fBufferHeight);
+ dest_mgr.put_pixel_rows (&cinfo, num_scanlines);
+ }
+
+ // Finish decompression and release memory.
+ // I must do it in this order because output module has allocated memory
+ // of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
+
+ dest_mgr.finish_output (&cinfo);
+ (void) jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: JPEGToPixMap
+ *
+ * DESCRIPTION: Convert a JPEG to an EmPixMap.
+ *
+ * PARAMETERS: stream - stream providing the input JPEG data
+ * pixMap - pixMap to receive the uncompressed image.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void JPEGToPixMap (EmStream& stream, EmPixMap& pixMap)
+{
+ EmJPEGDecompressStreamSource src_data (stream);
+ EmJPEGDecompressPixMapSink dest_data (pixMap);
+
+ ::ConvertJPEG (src_data, dest_data);
+}
diff --git a/SrcShared/EmJPEG.h b/SrcShared/EmJPEG.h
new file mode 100644
index 0000000..4cdead5
--- /dev/null
+++ b/SrcShared/EmJPEG.h
@@ -0,0 +1,167 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmJPEG_h
+#define EmJPEG_h
+
+// jmorecfg.h tries to typedef uint32 to be a long. BASETSD.H
+// already defines uint32 to be an int. Fortunately, they amount
+// to the same thing, so we can turn off the jmorecfg.h attempt
+// by defining the following symbol.
+
+#define XMD_H 1
+
+// jmorecfg.h also tries to define FAR. Undefine the one set up
+// by windef.h. Yes, that gives us two different definitions of
+// FAR, but hopefully that won't lead to conflict.
+
+#undef FAR
+
+
+extern "C"
+{
+ #include "jinclude.h"
+ #include "jpeglib.h"
+ #include "jerror.h"
+}
+
+class EmPixMap;
+class EmStream;
+
+
+// Abstract base class that acts as a source for compressed JPEG
+// data that needs to be decompressed. Clients subclass from this
+// and override the pure-virtual functions.
+
+class EmJPEGDecompressSource : public jpeg_source_mgr
+{
+ public:
+ EmJPEGDecompressSource (void);
+ virtual ~EmJPEGDecompressSource (void);
+
+ private:
+ virtual void InitSource (j_decompress_ptr cinfo) = 0;
+ virtual boolean FillInputBuffer (j_decompress_ptr cinfo) = 0;
+ virtual void SkipInputData (j_decompress_ptr cinfo, long num_bytes) = 0;
+ virtual void TermSource (j_decompress_ptr cinfo) = 0;
+
+ private:
+ static void init_source_cb (j_decompress_ptr cinfo);
+ static boolean fill_input_buffer_cb(j_decompress_ptr cinfo);
+ static void skip_input_data_cb (j_decompress_ptr cinfo, long num_bytes);
+ static void term_source_cb (j_decompress_ptr cinfo);
+};
+
+
+// Concrete class that provides compressed JPEG data from a memory buffer.
+
+class EmJPEGDecompressMemSource : public EmJPEGDecompressSource
+{
+ public:
+ EmJPEGDecompressMemSource (const void* data, long len);
+ virtual ~EmJPEGDecompressMemSource (void);
+
+ private:
+ virtual void InitSource (j_decompress_ptr cinfo);
+ virtual boolean FillInputBuffer (j_decompress_ptr cinfo);
+ virtual void SkipInputData (j_decompress_ptr cinfo, long num_bytes);
+ virtual void TermSource (j_decompress_ptr cinfo);
+
+ private:
+ const void* fData;
+ long fDataLen;
+};
+
+
+// Concrete class that provides compressed JPEG data from a stream.
+
+class EmJPEGDecompressStreamSource : public EmJPEGDecompressSource
+{
+ public:
+ EmJPEGDecompressStreamSource (EmStream&);
+ virtual ~EmJPEGDecompressStreamSource (void);
+
+ private:
+ virtual void InitSource (j_decompress_ptr cinfo);
+ virtual boolean FillInputBuffer (j_decompress_ptr cinfo);
+ virtual void SkipInputData (j_decompress_ptr cinfo, long num_bytes);
+ virtual void TermSource (j_decompress_ptr cinfo);
+
+ private:
+ EmStream& fStream;
+ void* fBuffer;
+};
+
+
+// Abstract base class for accepting decompressed JPEG images and
+// storing them in some client-specific fashion. Clients subclass
+// from this and override the pure-virtual functions.
+
+class EmJPEGDecompressSink
+{
+ public:
+ EmJPEGDecompressSink (void);
+ virtual ~EmJPEGDecompressSink (void);
+
+ virtual void post_jpeg_read_header (j_decompress_ptr cinfo) = 0;
+
+ virtual void start_output (j_decompress_ptr cinfo) = 0;
+ virtual void put_pixel_rows (j_decompress_ptr cinfo,
+ JDIMENSION rows_supplied) = 0;
+ virtual void finish_output (j_decompress_ptr cinfo) = 0;
+
+ public:
+ // These fields are passed jpeg_read_scanlines by ConvertJPEG
+ JSAMPARRAY fBuffer;
+ JDIMENSION fBufferHeight;
+};
+
+
+// EmJPEGDecompressSink sub-class that writes the output as an EmPixMap.
+
+class EmJPEGDecompressPixMapSink : public EmJPEGDecompressSink
+{
+ public:
+ EmJPEGDecompressPixMapSink (EmPixMap&);
+ virtual ~EmJPEGDecompressPixMapSink (void);
+
+ virtual void post_jpeg_read_header (j_decompress_ptr cinfo);
+
+ virtual void start_output (j_decompress_ptr cinfo);
+ virtual void put_pixel_rows (j_decompress_ptr cinfo,
+ JDIMENSION rows_supplied);
+ virtual void finish_output (j_decompress_ptr cinfo);
+
+ private:
+ EmPixMap& fPixMap;
+
+ JDIMENSION fDataWidth; /* JSAMPLEs per row */
+ JDIMENSION fRowWidth; /* physical width of one row in the BMP file */
+ int fPadBytes; /* number of padding bytes needed per row */
+ JDIMENSION fCurOutputRow; /* next row# to write to virtual array */
+};
+
+
+// Function that drives the decompression process. Clients define
+// the compressed JPEG data source and the decompressed JPEG data
+// output by providing the appropriate source and sink classes.
+
+void ConvertJPEG (EmJPEGDecompressSource&, EmJPEGDecompressSink&);
+
+
+// Utility function that converts a JPEG from the stream to the given pixmap.
+
+void JPEGToPixMap (EmStream&, EmPixMap&);
+
+
+#endif /* EmJPEG_h */
diff --git a/SrcShared/EmLowMem.cpp b/SrcShared/EmLowMem.cpp
new file mode 100644
index 0000000..da7b366
--- /dev/null
+++ b/SrcShared/EmLowMem.cpp
@@ -0,0 +1,273 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmLowMem.h"
+
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmPalmFunction.h" // SysTrapIndex
+#include "EmPatchState.h" // EmPatchState::OSMajorVersion
+
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+#include "SysEvtPrv.h" // SysEvtMgrGlobalsType
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+
+EmAliasLowMemHdrType<PAS> EmLowMem::fgLowMem (EmMemNULL);
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ EmLowMem
+// ===========================================================================
+
+static uint16 gSysDispatchTableSize;
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmLowMem::Initialize (void)
+{
+ gSysDispatchTableSize = 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmLowMem::Reset (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmLowMem::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmLowMem::Load (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmLowMem::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::GetEvtMgrIdle
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+uint8 EmLowMem::GetEvtMgrIdle (void)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // First, get sysEvtMgrGlobalsP, which is a pointer in low-memory.
+
+ emuptr sysEvtMgrGlobalsP = EmLowMem_GetGlobal (sysEvtMgrGlobalsP);
+
+ /*
+ ** Next look at the "idle" boolean in the SysEvtMgrGlobalsPtr
+ ** contained in sysEvtMgrGlobalsP:
+ **
+ ** struct SysEvtMgrGlobalsType
+ ** {
+ ** ...
+ ** Boolean idle;
+ ** ...
+ ** };
+ */
+
+ size_t idleOffset = offsetof (SysEvtMgrGlobalsType, idle);
+
+ // Under Palm OS 1.0, there was an extra 4-byte value at the
+ // location currently holding "gremlinsFlag", which is before
+ // the "idle" field. Under that version of the OS, we therefore
+ // have to add 4 to get the right offset.
+
+ if (EmPatchState::OSMajorVersion () == 1)
+ {
+ idleOffset += sizeof (Int32);
+ }
+
+ uint8 idle = EmMemGet8 (sysEvtMgrGlobalsP + idleOffset);
+
+ return idle;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::TrapExists
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmLowMem::TrapExists (uint16 iATrap)
+{
+#if 0
+ // No longer cache the dispatch table size. Handspring changes the
+ // size of the dispatch table after the first system call, resulting
+ // in Poser caching the old table size, and thus complaining that
+ // some functions are not implemented when in fact they are.
+
+ // If we haven't already, get the number of traps in this system.
+
+ if (gSysDispatchTableSize == 0)
+ {
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ gSysDispatchTableSize = EmLowMem_GetGlobal (sysDispatchTableSize);
+ }
+
+ return (::SysTrapIndex (iATrap) == ::SysTrapIndex (sysTrapHostControl)) ||
+ ::SysTrapIndex (iATrap) < gSysDispatchTableSize;
+#else
+ CEnableFullAccess munge; // Remove blocks on memory access.
+ uint16 sysDispatchTableSize = EmLowMem_GetGlobal (sysDispatchTableSize);
+ return (::SysTrapIndex (iATrap) == ::SysTrapIndex (sysTrapHostControl)) ||
+ ::SysTrapIndex (iATrap) < sysDispatchTableSize;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmLowMem::GetTrapAddress
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+emuptr EmLowMem::GetTrapAddress (uint16 iATrap)
+{
+ emuptr address = EmMemNULL;
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // If the trap number is not in range, just return NULL to signal
+ // that normal process of the TRAP $F should occur.
+
+// uint16 sysDispatchTableSize = EmLowMem_GetGlobal (sysDispatchTableSize);
+ uint16 sysDispatchTableSize = EmMemGet16 (256 + 62);
+
+ iATrap = ::SysTrapIndex (iATrap);
+
+ if ((iATrap == ::SysTrapIndex (sysTrapHostControl)) ||
+ (iATrap < sysDispatchTableSize))
+ {
+ // Get sysDispatchTableP, which is a pointer in low-memory.
+
+// uint32 sysDispatchTableP = EmLowMem_GetGlobal (sysDispatchTableP);
+ uint32 sysDispatchTableP = EmMemGet32 (256 + 34);
+
+ // If it's NULL, return NULL.
+
+ if (sysDispatchTableP != EmMemNULL)
+ {
+ // Next, get the right guy from its contents.
+
+ address = EmMemGet32 (sysDispatchTableP + iATrap * 4);
+ }
+ }
+
+ return address;
+}
diff --git a/SrcShared/EmLowMem.h b/SrcShared/EmLowMem.h
new file mode 100644
index 0000000..ecb22ab
--- /dev/null
+++ b/SrcShared/EmLowMem.h
@@ -0,0 +1,41 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmLowMem_h
+#define EmLowMem_h
+
+#include "EmPalmStructs.h"
+
+class SessionFile;
+
+class EmLowMem
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static uint8 GetEvtMgrIdle (void);
+ static Bool TrapExists (uint16 iATrap);
+ static emuptr GetTrapAddress (uint16 iATrap);
+
+ #define EmLowMem_GetGlobal(x) EmLowMem::fgLowMem.globals.x
+ #define EmLowMem_SetGlobal(x, v) EmLowMem::fgLowMem.globals.x = v
+ #define EmLowMem_AddressOf(x) EmLowMem::fgLowMem.globals.x.GetPtr ()
+
+ static EmAliasLowMemHdrType<PAS> fgLowMem;
+};
+
+#endif // EmLowMem_h
diff --git a/SrcShared/EmMapFile.cpp b/SrcShared/EmMapFile.cpp
new file mode 100644
index 0000000..185b8ad
--- /dev/null
+++ b/SrcShared/EmMapFile.cpp
@@ -0,0 +1,144 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmMapFile.h"
+
+#include "ChunkFile.h" // Chunk, EmStreamChunk
+#include "EmFileRef.h" // EmFileRef
+#include "EmStreamFile.h" // EmStreamFile
+#include "Miscellaneous.h" // Strip
+
+Bool
+EmMapFile::Read (const EmFileRef& f, StringStringMap& mapData)
+{
+ try
+ {
+ EmStreamFile fileStream (f, kOpenExistingForRead | kOpenText); // Will throw if fnf
+ return Read (fileStream, mapData);
+ }
+ catch (...)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+Bool
+EmMapFile::Read (EmStream& stream, StringStringMap& mapData)
+{
+ try
+ {
+ StringStringMap theData;
+ string line;
+ char ch;
+ ErrCode err;
+
+ do
+ {
+ err = stream.GetBytes (&ch, 1);
+
+ if (ch == '\n' || ch == '\r' || err != 0) // End of line or end of file.
+ {
+ // Skip leading WS
+ line = Strip (line.c_str (), " \t", true, false);
+
+ // Skip comment and empty lines
+ if ((line[0] == ';' ) || (line[0] == '#' ) || (line[0] == '\0'))
+ {
+ line.erase ();
+ continue;
+ }
+
+ // Everything else is data
+ string::size_type p = line.find ('=');
+ if (p == string::npos)
+ {
+ line.erase ();
+ continue;
+ }
+
+ // Split up the line into key/value sections and
+ // add it to our hash table.
+ string key (line, 0, p);
+ string value (line, p + 1, line.size ());
+
+ key = Strip (key.c_str (), " \t", true, true);
+ value = Strip (value.c_str (), " \t", true, true);
+
+ theData[key] = value;
+
+ line.erase ();
+ }
+ else
+ {
+ line += ch;
+ }
+ }
+ while (err == 0);
+
+ mapData = theData;
+ }
+ catch (...)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+
+Bool
+EmMapFile::Write (const EmFileRef& f, const StringStringMap& mapData)
+{
+ try
+ {
+ // Get the data in fairly raw form.
+
+ Chunk chunk;
+ EmStreamChunk chunkStream (chunk);
+
+ if (!Write (chunkStream, mapData))
+ return false;
+
+ // Now write that data to the file, letting the EmStreamFile
+ // class sort out line endings.
+
+ EmStreamFile fileStream (f, kCreateOrEraseForUpdate | kOpenText,
+ kFileCreatorCodeWarrior, kFileTypeText); // Will throw if can't create
+ return fileStream.PutBytes (chunk.GetPointer (), chunk.GetLength ());
+ }
+ catch (...)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+Bool
+EmMapFile::Write (EmStream& stream, const StringStringMap& mapData)
+{
+ StringStringMap::const_iterator iter;
+
+ for (iter = mapData.begin(); iter != mapData.end(); ++iter)
+ {
+ string line = iter->first + "=" + iter->second + "\n";
+ stream.PutBytes (line.c_str (), line.size ());
+ }
+
+ return true;
+}
diff --git a/SrcShared/EmMapFile.h b/SrcShared/EmMapFile.h
new file mode 100644
index 0000000..72f72f6
--- /dev/null
+++ b/SrcShared/EmMapFile.h
@@ -0,0 +1,37 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmMapFile_h
+#define EmMapFile_h
+
+#include "EmStructs.h" // StringStringMap
+
+class EmFileRef;
+class EmStream;
+
+class EmMapFile
+{
+ public:
+
+ static Bool Read ( const EmFileRef& f,
+ StringStringMap& mapData );
+ static Bool Read ( EmStream& stream,
+ StringStringMap& mapData );
+
+ static Bool Write ( const EmFileRef& f,
+ const StringStringMap& mapData );
+ static Bool Write ( EmStream& stream,
+ const StringStringMap& mapData );
+};
+
+#endif /* EmMapFile_h */
diff --git a/SrcShared/EmMenus.cpp b/SrcShared/EmMenus.cpp
new file mode 100644
index 0000000..a98cb9e
--- /dev/null
+++ b/SrcShared/EmMenus.cpp
@@ -0,0 +1,1274 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmMenus.h"
+
+#include "EmApplication.h" // IsBoundPartially
+#include "EmFileRef.h" // EmFileRefList
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmSession.h" // gSession
+#include "Hordes.h" // Hordes::CanNew, etc.
+#include "Platform.h" // Platform::GetString
+#include "PreferenceMgr.h" // gEmuPrefs
+#include "Profiling.h" // ProfileCanStart, etc.
+#include "Strings.r.h" // kStr_Menu...
+
+// ---------------------------------------------------------------------------
+
+#pragma mark Forward Declarations
+
+static void PrvInitializeMenus (Bool alternateLayout);
+static void PrvAddMenuItem (EmMenuItemList&, EmCommandID);
+static void PrvSetSubMenu (EmMenuItemList&, EmCommandID, EmMenuItemList&);
+static void PrvUpdateMruMenus (const EmFileRefList&, EmCommandID, EmMenuItemList&);
+static void PrvCollectFiles (EmFileRefList&, EmFileRefList&);
+static Bool PrvGetItemStatus (const EmMenuItem& item);
+static void PrvPrefsChanged (PrefKeyType key, void*);
+static EmMenuID PrvPreferredMenuID (EmMenuID);
+
+// ---------------------------------------------------------------------------
+
+#pragma mark -
+#pragma mark Private Globals
+
+static EmMenu gMenuMenubar;
+static EmMenu gMenuPartiallyBoundMenubar;
+static EmMenu gMenuFullyBoundMenubar;
+
+static EmMenu gMenuPopupMenu;
+static EmMenu gMenuPartiallyBoundPopupMenu;
+static EmMenu gMenuFullyBoundPopupMenu;
+
+static unsigned long gChangeCount;
+
+// ---------------------------------------------------------------------------
+// This array is accessed by index using the values in EmMenuItemID. Thus,
+// any changes in this array need corresponding changes in that list.
+
+struct EmPrvMenuItem
+{
+ EmCommandID fCommandID;
+#if 1
+ StrCode fTitle;
+#else
+ const char* fTitle;
+#endif
+};
+
+#define __________ kCommandDivider
+
+/*
+ Keyboard Equivalents
+
+ Mac OS X reserves certain keyboard combinations as equivalents to menu
+ commands; these shortcuts affect all applications. Even if your application
+ doesnÕt support all the combinations shown in Table 8-3, donÕt use any of
+ them for another function.
+
+ Table 8-3 Reserved and recommended keyboard equivalents
+
+ Menu Keys Command
+ ------------------------------------------------
+ Application Command-H* Hide
+ Application Command-Q* Quit
+ ................................................
+ Window Command-M* Minimize
+ ................................................
+ File Command-N* New
+ File Command-O Open
+ File Command-W Close
+ File Command-S Save
+ File Command-P Print
+ ................................................
+ Edit Command-Z Undo
+ Edit Command-X Cut
+ Edit Command-C Copy
+ Edit Command-V Paste
+ Edit Command-A Select All
+ ................................................
+ Format Command-T Open Font dialog
+ ------------------------------------------------
+ * These combinations are reserved by the system; the others are
+ recommended.
+
+ Some applications use other common keyboard equivalents, as shown in Table 8-4.
+ If you choose not to implement these functions in your product, you may use these
+ equivalents for other actions, although that could make your application less
+ intuitive for users accustomed to the combinations shown here.
+
+ Table 8-4 Common keyboard equivalents that are not reserved
+
+ Menu Keys Command
+ ------------------------------------------------
+ Edit (recommended) Command-F Find
+ Edit (recommended) Command-G Find Again
+ ................................................
+ Format Command-B Bold
+ Format Command-I Italic
+ Format Command-U Underline
+ ------------------------------------------------
+
+ Hmmm...that leaves: D, E, J, K, L, R, and Y for anything else!
+
+ A |
+ B | Breakpoints
+ C | Copy
+ D | Download ROM
+ E | Error Handling
+ F |
+ G |
+ H | HotSync
+ I | Import Database
+ J |
+ K | Skins
+ L | Logging Options
+ M | Save Screen
+ N | New Session
+ O | Open Session
+ P |
+ Q | Quit
+ R | Reset
+ S | Save Session
+ T | Tracing Options
+ U |
+ V | Paste
+ W | Close Session
+ X | Cut
+ Y |
+ Z | Undo
+ / | Preferences
+ \ | Debuging Options
+ [ | Profile Start
+ ] | Profile Stop
+
+ ===============================
+ Accelerator key mappings
+ ===============================
+
+ --+-----------------------------------------------------------------------------+--
+ | Top level Reset Open Import Settings Gremlins Profile Edit |
+ --+-----------------------------------------------------------------------------+--
+ A | Save As | A
+ B | Save Bound Breakpoints | B
+ C | Close Cold Copy | C
+ D | Export Debug Debugging Dump | D
+ E | Settings Error Handling | E
+ F | Profile | F
+ G | Gremlins | G
+ H | HotSync HostFS | H
+ I | Install | I
+ J | | J
+ K | | K
+ L | Logging | L
+ M | Minimize | M
+ N | New Normal New | N
+ O | Open Other Other | O
+ P | Properties Stop Stop Paste | P
+ Q | Quit | Q
+ R | Reset Resume Clear | R
+ S | Save Skins Step Start | S
+ T | Transfer ROM Tracing Cut | T
+ U | Undo | U
+ V | Save Screen | V
+ W | | W
+ X | Exit | X
+ Y | Replay | Y
+ Z | | Z
+ --+-----------------------------------------------------------------------------+--
+*/
+
+EmPrvMenuItem kPrvMenuItems[] =
+{
+ { kCommandSessionNew, kStr_MenuSessionNew },
+ { kCommandSessionOpenOther, kStr_MenuSessionOpenOther },
+ { kCommandSessionOpen0, kStr_MenuBlank },
+ { kCommandSessionOpen1, kStr_MenuBlank },
+ { kCommandSessionOpen2, kStr_MenuBlank },
+ { kCommandSessionOpen3, kStr_MenuBlank },
+ { kCommandSessionOpen4, kStr_MenuBlank },
+ { kCommandSessionOpen5, kStr_MenuBlank },
+ { kCommandSessionOpen6, kStr_MenuBlank },
+ { kCommandSessionOpen7, kStr_MenuBlank },
+ { kCommandSessionOpen8, kStr_MenuBlank },
+ { kCommandSessionOpen9, kStr_MenuBlank },
+ { kCommandSessionClose, kStr_MenuSessionClose },
+
+ { kCommandSessionSave, kStr_MenuSessionSave },
+ { kCommandSessionSaveAs, kStr_MenuSessionSaveAs },
+ { kCommandSessionBound, kStr_MenuSessionBound },
+ { kCommandScreenSave, kStr_MenuScreenSave },
+
+ { kCommandSessionInfo, kStr_MenuSessionInfo },
+
+ { kCommandImportOther, kStr_MenuImportOther },
+ { kCommandImport0, kStr_MenuBlank },
+ { kCommandImport1, kStr_MenuBlank },
+ { kCommandImport2, kStr_MenuBlank },
+ { kCommandImport3, kStr_MenuBlank },
+ { kCommandImport4, kStr_MenuBlank },
+ { kCommandImport5, kStr_MenuBlank },
+ { kCommandImport6, kStr_MenuBlank },
+ { kCommandImport7, kStr_MenuBlank },
+ { kCommandImport8, kStr_MenuBlank },
+ { kCommandImport9, kStr_MenuBlank },
+ { kCommandExport, kStr_MenuExport },
+
+ { kCommandHotSync, kStr_MenuHotSync },
+ { kCommandReset, kStr_MenuReset },
+ { kCommandDownloadROM, kStr_MenuDownloadROM },
+
+ { kCommandUndo, kStr_MenuUndo },
+ { kCommandCut, kStr_MenuCut },
+ { kCommandCopy, kStr_MenuCopy },
+ { kCommandPaste, kStr_MenuPaste },
+ { kCommandClear, kStr_MenuClear },
+
+ { kCommandPreferences, kStr_MenuPreferences },
+ { kCommandLogging, kStr_MenuLogging },
+ { kCommandDebugging, kStr_MenuDebugging },
+ { kCommandErrorHandling, kStr_MenuErrorHandling },
+#if HAS_TRACER
+ { kCommandTracing, kStr_MenuTracing },
+#endif
+ { kCommandSkins, kStr_MenuSkins },
+ { kCommandHostFS, kStr_MenuHostFS },
+ { kCommandBreakpoints, kStr_MenuBreakpoints },
+
+ { kCommandGremlinsNew, kStr_MenuGremlinsNew },
+ { kCommandGremlinsSuspend, kStr_MenuGremlinsSuspend },
+ { kCommandGremlinsStep, kStr_MenuGremlinsStep },
+ { kCommandGremlinsResume, kStr_MenuGremlinsResume },
+ { kCommandGremlinsStop, kStr_MenuGremlinsStop },
+ { kCommandEventReplay, kStr_MenuEventReplay },
+ { kCommandEventMinimize, kStr_MenuEventMinimize },
+
+#if HAS_PROFILING
+ { kCommandProfileStart, kStr_MenuProfileStart },
+ { kCommandProfileStop, kStr_MenuProfileStop },
+ { kCommandProfileDump, kStr_MenuProfileDump },
+#endif
+
+ { kCommandAbout, kStr_MenuAbout },
+ { kCommandQuit, kStr_MenuQuit },
+
+ { kCommandFile, kStr_MenuFile },
+ { kCommandEdit, kStr_MenuEdit },
+ { kCommandGremlins, kStr_MenuGremlins },
+#if HAS_PROFILING
+ { kCommandProfile, kStr_MenuProfile },
+#endif
+
+ { kCommandOpen, kStr_MenuOpen },
+ { kCommandImport, kStr_MenuImport },
+ { kCommandSettings, kStr_MenuSettings },
+
+ { __________, kStr_MenuBlank }
+};
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ MenuInitialize
+// ---------------------------------------------------------------------------
+// Create all of our menu hierarchies.
+
+void MenuInitialize (Bool alternateLayout)
+{
+ ::PrvInitializeMenus (alternateLayout);
+
+ gChangeCount = 1;
+
+ gPrefs->AddNotification (&::PrvPrefsChanged, kPrefKeyPSF_MRU);
+ gPrefs->AddNotification (&::PrvPrefsChanged, kPrefKeyPRC_MRU);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MenuFindMenu
+// ---------------------------------------------------------------------------
+// Find the top-level menu with the given menu ID and return a pointer to it.
+// If the menu ID is unknown, this function returns NULL.
+
+EmMenu* MenuFindMenu (EmMenuID menuID)
+{
+ EmMenu* menu = NULL;
+
+ menuID = ::PrvPreferredMenuID (menuID);
+
+ switch (menuID)
+ {
+ case kMenuMenubarFull: menu = &gMenuMenubar; break;
+ case kMenuMenubarPartiallyBound: menu = NULL; break;
+ case kMenuMenubarFullyBound: menu = NULL; break;
+
+ case kMenuPopupMenuFull: menu = &gMenuPopupMenu; break;
+ case kMenuPopupMenuPartiallyBound: menu = &gMenuPartiallyBoundPopupMenu; break;
+ case kMenuPopupMenuFullyBound: menu = &gMenuFullyBoundPopupMenu; break;
+
+ default:
+ EmAssert (false);
+ }
+
+ return menu;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MenuFindMenuItemByCommandID
+// ---------------------------------------------------------------------------
+// Find the menu item in the given menu (or menu hierarchy if recurse is true)
+// that has the given command ID. If more than one menu item has that ID, the
+// first one found is returned. If no menu item has that ID, return NULL.
+
+EmMenuItem* MenuFindMenuItemByCommandID (EmMenuItemList& menu,
+ EmCommandID cmd,
+ Bool recurse)
+{
+ EmMenuItemList::iterator iter = menu.begin ();
+ while (iter != menu.end ())
+ {
+ if (iter->GetCommand () == cmd)
+ {
+ return &(*iter);
+ }
+
+ if (recurse)
+ {
+ // Check the children by recursing.
+
+ EmMenuItemList& subMenu = iter->GetChildren ();
+ EmMenuItem* result = ::MenuFindMenuItemByCommandID (subMenu, cmd, recurse);
+ if (result)
+ return result;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MenuFindMenuContainingCommandID
+// ---------------------------------------------------------------------------
+// Return the menu containing the menu item that has the given command ID.
+// If no such menu item can be found, return NULL.
+
+EmMenuItemList* MenuFindMenuContainingCommandID (EmMenuItemList& menu, EmCommandID cmd)
+{
+ // Iterate over the given menu, looking for an item with the given command.
+
+ EmMenuItemList::iterator iter = menu.begin ();
+ while (iter != menu.end ())
+ {
+ // If we found the item, return the menu it's in.
+
+ if (iter->GetCommand () == cmd)
+ return &menu;
+
+ // Check the children by recursing.
+
+ EmMenuItemList& subMenu = iter->GetChildren ();
+ EmMenuItemList* result = ::MenuFindMenuContainingCommandID (subMenu, cmd);
+ if (result)
+ return result;
+
+ // Move to the next item in the menu.
+
+ ++iter;
+ }
+
+ // If we reach here, we couldn't find it. Indicate that by returning NULL.
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MenuUpdateMruMenus
+// ---------------------------------------------------------------------------
+// Update the MRU menu items according to the current preferences.
+
+void MenuUpdateMruMenus (EmMenu& menu)
+{
+ if (gChangeCount != menu.GetChangeCount ())
+ {
+ menu.SetChangeCount (gChangeCount);
+
+ EmFileRefList session, database;
+ ::PrvCollectFiles (session, database);
+
+ ::PrvUpdateMruMenus (session, kCommandSessionOpenOther, menu);
+ ::PrvUpdateMruMenus (database, kCommandImportOther, menu);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MenuUpdateMenuItemStatus
+// ---------------------------------------------------------------------------
+
+void MenuUpdateMenuItemStatus (EmMenuItemList& menu)
+{
+ EmMenuItemList::iterator iter = menu.begin ();
+ while (iter != menu.end ())
+ {
+ EmMenuItemList& children = iter->GetChildren ();
+
+ if (children.size () > 0)
+ {
+ iter->SetIsActive (true);
+ ::MenuUpdateMenuItemStatus (children);
+ }
+ else
+ {
+ iter->SetIsActive (::PrvGetItemStatus (*iter));
+ }
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ PrvInitializeMenus
+// ---------------------------------------------------------------------------
+// Create all of our menu hierarchies.
+
+void PrvInitializeMenus (Bool alternateLayout)
+{
+ // Create the menus. Create all the distinct menus first.
+ // We'll build up the hierarchy later.
+
+ // Create the "File" sub-menu.
+
+ EmMenuItemList subMenuFile;
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionNew);
+ ::PrvAddMenuItem (subMenuFile, kCommandOpen);
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionClose);
+ ::PrvAddMenuItem (subMenuFile, __________);
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionSave);
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionSaveAs);
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionBound);
+ ::PrvAddMenuItem (subMenuFile, kCommandScreenSave);
+ ::PrvAddMenuItem (subMenuFile, kCommandSessionInfo);
+ ::PrvAddMenuItem (subMenuFile, __________);
+ ::PrvAddMenuItem (subMenuFile, kCommandImport);
+ ::PrvAddMenuItem (subMenuFile, kCommandExport);
+ ::PrvAddMenuItem (subMenuFile, kCommandHotSync);
+ ::PrvAddMenuItem (subMenuFile, kCommandReset);
+ ::PrvAddMenuItem (subMenuFile, kCommandDownloadROM);
+
+ if (!alternateLayout)
+ {
+ ::PrvAddMenuItem (subMenuFile, __________);
+ ::PrvAddMenuItem (subMenuFile, kCommandQuit);
+ }
+
+ // Create the "Edit" sub-menu.
+
+ EmMenuItemList subMenuEdit;
+ ::PrvAddMenuItem (subMenuEdit, kCommandUndo);
+ ::PrvAddMenuItem (subMenuEdit, __________);
+ ::PrvAddMenuItem (subMenuEdit, kCommandCut);
+ ::PrvAddMenuItem (subMenuEdit, kCommandCopy);
+ ::PrvAddMenuItem (subMenuEdit, kCommandPaste);
+ ::PrvAddMenuItem (subMenuEdit, kCommandClear);
+
+ ::PrvAddMenuItem (subMenuEdit, __________);
+ // Strictly speaking, we should not include the Preferences
+ // menu item when using the Aqua interface. Apple prefers
+ // that that menu item be in the "application" menu under
+ // the About menu item. However, we have many Preferenc-like
+ // menu items. It would be nice to have them all in one
+ // place. However, I don't know how to put them all into
+ // the "application" menu, so I'll keep them all in the Edit
+ // menu. But there will also be the standard Preferences
+ // menu item in the "application" menu, which will do the
+ // same thing as the Preferences menu item in the Edit menu.
+#if (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
+// if (!alternateLayout)
+#endif
+ {
+ ::PrvAddMenuItem (subMenuEdit, kCommandPreferences);
+ }
+ ::PrvAddMenuItem (subMenuEdit, kCommandLogging);
+ ::PrvAddMenuItem (subMenuEdit, kCommandDebugging);
+ ::PrvAddMenuItem (subMenuEdit, kCommandErrorHandling);
+#if HAS_TRACER
+ ::PrvAddMenuItem (subMenuEdit, kCommandTracing);
+#endif
+ ::PrvAddMenuItem (subMenuEdit, kCommandSkins);
+ ::PrvAddMenuItem (subMenuEdit, kCommandHostFS);
+ ::PrvAddMenuItem (subMenuEdit, kCommandBreakpoints);
+
+ // Create the "Gremlins" sub-menu.
+
+ EmMenuItemList subMenuGremlins;
+ ::PrvAddMenuItem (subMenuGremlins, kCommandGremlinsNew);
+ ::PrvAddMenuItem (subMenuGremlins, __________);
+// ::PrvAddMenuItem (subMenuGremlins, kCommandGremlinsSuspend);
+ ::PrvAddMenuItem (subMenuGremlins, kCommandGremlinsStep);
+ ::PrvAddMenuItem (subMenuGremlins, kCommandGremlinsResume);
+ ::PrvAddMenuItem (subMenuGremlins, kCommandGremlinsStop);
+ ::PrvAddMenuItem (subMenuGremlins, __________);
+ ::PrvAddMenuItem (subMenuGremlins, kCommandEventReplay);
+ ::PrvAddMenuItem (subMenuGremlins, kCommandEventMinimize);
+
+ // Create the "Profile" sub-menu.
+
+#if HAS_PROFILING
+ EmMenuItemList subMenuProfile;
+ ::PrvAddMenuItem (subMenuProfile, kCommandProfileStart);
+ ::PrvAddMenuItem (subMenuProfile, kCommandProfileStop);
+ ::PrvAddMenuItem (subMenuProfile, __________);
+ ::PrvAddMenuItem (subMenuProfile, kCommandProfileDump);
+#endif
+
+ // Create the "Open Session" sub-menu.
+
+ EmMenuItemList subMenuOpen;
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpenOther);
+ ::PrvAddMenuItem (subMenuOpen, __________);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen0);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen1);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen2);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen3);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen4);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen5);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen6);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen7);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen8);
+ ::PrvAddMenuItem (subMenuOpen, kCommandSessionOpen9);
+
+ // Create the "Install Database" sub-menu.
+
+ EmMenuItemList subMenuImport;
+ ::PrvAddMenuItem (subMenuImport, kCommandImportOther);
+ ::PrvAddMenuItem (subMenuImport, __________);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport0);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport1);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport2);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport3);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport4);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport5);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport6);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport7);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport8);
+ ::PrvAddMenuItem (subMenuImport, kCommandImport9);
+
+ // Create the "Settings" sub-menu.
+
+ EmMenuItemList subMenuSettings;
+ ::PrvAddMenuItem (subMenuSettings, kCommandPreferences);
+ ::PrvAddMenuItem (subMenuSettings, kCommandLogging);
+ ::PrvAddMenuItem (subMenuSettings, kCommandDebugging);
+ ::PrvAddMenuItem (subMenuSettings, kCommandErrorHandling);
+#if HAS_TRACER
+ ::PrvAddMenuItem (subMenuSettings, kCommandTracing);
+#endif
+ ::PrvAddMenuItem (subMenuSettings, kCommandSkins);
+ ::PrvAddMenuItem (subMenuSettings, kCommandHostFS);
+ ::PrvAddMenuItem (subMenuSettings, kCommandBreakpoints);
+
+ // Create the Full menubar.
+
+ ::PrvAddMenuItem (gMenuMenubar, kCommandFile);
+ ::PrvAddMenuItem (gMenuMenubar, kCommandEdit);
+ ::PrvAddMenuItem (gMenuMenubar, kCommandGremlins);
+#if HAS_PROFILING
+ ::PrvAddMenuItem (gMenuMenubar, kCommandProfile);
+#endif
+
+ // Create the Full popup menu.
+
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandQuit);
+ ::PrvAddMenuItem (gMenuPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionNew);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandOpen);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionClose);
+ ::PrvAddMenuItem (gMenuPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionSave);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionSaveAs);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionBound);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandScreenSave);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSessionInfo);
+ ::PrvAddMenuItem (gMenuPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandImport);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandExport);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandHotSync);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandReset);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandDownloadROM);
+ ::PrvAddMenuItem (gMenuPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandGremlins);
+#if HAS_PROFILING
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandProfile);
+#endif
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandSettings);
+ ::PrvAddMenuItem (gMenuPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPopupMenu, kCommandAbout);
+
+ // Create the Partially-Bound popup menu.
+ // We remove:
+ // Close
+ // Save Bound
+ // Download ROM
+ // Gremlins
+ // Profile
+ // All settings bu Preferences and Skins
+
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandQuit);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandSessionNew);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandOpen);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandSessionSave);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandSessionSaveAs);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandScreenSave);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandSessionInfo);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandImport);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandExport);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandHotSync);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandReset);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandPreferences);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandSkins);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuPartiallyBoundPopupMenu, kCommandAbout);
+
+ // Create the Fully-Bound popup menu.
+ // We remove Partially Bound items plus:
+ // SessionNew
+ // Open
+ // SessionSave
+ // SessionSaveAs
+ // SessionInfo
+ // Export
+
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandQuit);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandScreenSave);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandImport);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandHotSync);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandReset);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandPreferences);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandSkins);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, __________);
+ ::PrvAddMenuItem (gMenuFullyBoundPopupMenu, kCommandAbout);
+
+ // Set sub-menus.
+
+ ::PrvSetSubMenu (subMenuFile, kCommandOpen, subMenuOpen);
+ ::PrvSetSubMenu (subMenuFile, kCommandImport, subMenuImport);
+
+ ::PrvSetSubMenu (gMenuMenubar, kCommandFile, subMenuFile);
+ ::PrvSetSubMenu (gMenuMenubar, kCommandEdit, subMenuEdit);
+ ::PrvSetSubMenu (gMenuMenubar, kCommandGremlins, subMenuGremlins);
+#if HAS_PROFILING
+ ::PrvSetSubMenu (gMenuMenubar, kCommandProfile, subMenuProfile);
+#endif
+
+ ::PrvSetSubMenu (gMenuPopupMenu, kCommandOpen, subMenuOpen);
+ ::PrvSetSubMenu (gMenuPopupMenu, kCommandImport, subMenuImport);
+ ::PrvSetSubMenu (gMenuPopupMenu, kCommandGremlins, subMenuGremlins);
+#if HAS_PROFILING
+ ::PrvSetSubMenu (gMenuPopupMenu, kCommandProfile, subMenuProfile);
+#endif
+ ::PrvSetSubMenu (gMenuPopupMenu, kCommandSettings, subMenuSettings);
+
+ ::PrvSetSubMenu (gMenuPartiallyBoundPopupMenu, kCommandOpen, subMenuOpen);
+ ::PrvSetSubMenu (gMenuPartiallyBoundPopupMenu, kCommandImport, subMenuImport);
+
+ ::PrvSetSubMenu (gMenuFullyBoundPopupMenu, kCommandImport, subMenuImport);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAddMenuItem
+// ---------------------------------------------------------------------------
+// Look up the template for the given command ID and use it to create a new
+// menu item, adding it to the given menu.
+
+void PrvAddMenuItem (EmMenuItemList& menu, EmCommandID cmd)
+{
+ // Get the template for this menu item.
+
+ EmPrvMenuItem* prvMenuItem = NULL;
+
+ for (size_t ii = 0; ii < countof (kPrvMenuItems); ++ii)
+ {
+ if (kPrvMenuItems[ii].fCommandID == cmd)
+ {
+ prvMenuItem = &kPrvMenuItems[ii];
+ break;
+ }
+ }
+
+ EmAssert (prvMenuItem);
+
+ // Create the new menu item.
+
+ EmMenuItem menuItem (prvMenuItem->fTitle, prvMenuItem->fCommandID);
+
+ // Add it to the menu.
+
+ menu.push_back (menuItem);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvSetSubMenu
+// ---------------------------------------------------------------------------
+// Find the menu item with the given command and set its children.
+
+void PrvSetSubMenu (EmMenuItemList& menu, EmCommandID cmd, EmMenuItemList& subMenu)
+{
+ // Find the menu item with the given command ID.
+
+ EmMenuItem* menuItem = ::MenuFindMenuItemByCommandID (menu, cmd, false);
+ EmAssert (menuItem);
+
+ // If we found it, set it's sub-menu to the given menu.
+
+ if (menuItem)
+ {
+ menuItem->SetChildren (subMenu);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvUpdateMruMenus
+// ---------------------------------------------------------------------------
+// Update the MRU menu items according to the current preferences.
+
+void PrvUpdateMruMenus (const EmFileRefList& files,
+ EmCommandID identifyingMenuItem,
+ EmMenuItemList& menu)
+{
+ EmMenuItemList* subMenu = ::MenuFindMenuContainingCommandID (menu, identifyingMenuItem);
+ if (!subMenu)
+ return;
+
+ // Clear out the old items.
+
+ subMenu->erase (subMenu->begin () + 2, subMenu->end ());
+
+ // Install the files from "files".
+
+ if (files.size () > 0)
+ {
+ int index = 1;
+ EmCommandID cmd = ++identifyingMenuItem;
+ EmFileRefList::const_iterator fileIter = files.begin ();
+
+ while (fileIter != files.end ())
+ {
+ string fileName (fileIter->GetFullPath ());
+#if !PLATFORM_MAC
+ // On Unix and Windows, the MRU items are prefixed with
+ // numbers that serve as mnemonic keys.
+
+ if (index <= 10)
+ {
+ char buffer[4];
+ sprintf (buffer, "&%d ", index < 10 ? index : 0);
+ fileName = buffer + fileName;
+ }
+#endif
+
+ EmMenuItem newItem (fileName, cmd);
+ subMenu->push_back (newItem);
+
+ ++fileIter;
+ ++cmd;
+ ++index;
+ }
+ }
+
+ // If no files, set the first one to be "(Empty)" and inactive
+
+ else
+ {
+ EmMenuItem emptyItem (kStr_MenuEmpty, kCommandEmpty);
+ emptyItem.SetIsActive (false);
+ subMenu->push_back (emptyItem);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCollectFiles
+// ---------------------------------------------------------------------------
+// Collect the MRU files from the preferences system.
+
+void PrvCollectFiles (EmFileRefList& session, EmFileRefList& database)
+{
+ int ii;
+
+ // Get the MRU list of session files.
+
+ for (ii = 0; ii < 10; ++ii)
+ {
+ EmFileRef ref = gEmuPrefs->GetIndRAMMRU (ii);
+
+ if (!ref.IsSpecified ())
+ break;
+
+ session.push_back (ref);
+ }
+
+ // Clear out that list, and get the list of database files.
+
+ for (ii = 0; ii < 10; ++ii)
+ {
+ EmFileRef ref = gEmuPrefs->GetIndPRCMRU (ii);
+
+ if (!ref.IsSpecified ())
+ break;
+
+ database.push_back (ref);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetItemStatus
+// ---------------------------------------------------------------------------
+// Return whether the given menu item should be enabled or not.
+
+Bool PrvGetItemStatus (const EmMenuItem& item)
+{
+ EmCommandID id = item.GetCommand ();
+
+ switch (id)
+ {
+ case kCommandNone: return false;
+
+ case kCommandSessionNew: return true;
+ case kCommandSessionOpenOther: return true;
+ case kCommandSessionOpen0: return true;
+ case kCommandSessionOpen1: return true;
+ case kCommandSessionOpen2: return true;
+ case kCommandSessionOpen3: return true;
+ case kCommandSessionOpen4: return true;
+ case kCommandSessionOpen5: return true;
+ case kCommandSessionOpen6: return true;
+ case kCommandSessionOpen7: return true;
+ case kCommandSessionOpen8: return true;
+ case kCommandSessionOpen9: return true;
+ case kCommandSessionClose: return gSession != NULL;
+
+ case kCommandSessionSave: return gSession != NULL;
+ case kCommandSessionSaveAs: return gSession != NULL;
+#if PLATFORM_WINDOWS
+ case kCommandSessionBound: return gSession != NULL;
+#else
+ case kCommandSessionBound: return false;
+#endif
+ case kCommandScreenSave: return gSession != NULL;
+ case kCommandSessionInfo: return gSession != NULL;
+
+ case kCommandImportOther: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport0: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport1: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport2: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport3: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport4: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport5: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport6: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport7: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport8: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandImport9: return gSession != NULL && EmPatchState::UIInitialized ();
+ case kCommandExport: return gSession != NULL && EmPatchState::UIInitialized ();
+
+ case kCommandHotSync: return gSession != NULL;
+ case kCommandReset: return gSession != NULL;
+ case kCommandDownloadROM: return true;
+
+ case kCommandUndo: return false;
+ case kCommandCut: return false;
+ case kCommandCopy: return false;
+ case kCommandPaste: return false;
+ case kCommandClear: return false;
+
+ case kCommandPreferences: return true;
+ case kCommandLogging: return true;
+ case kCommandDebugging: return true;
+ case kCommandErrorHandling: return true;
+#if HAS_TRACER
+ case kCommandTracing: return true;
+#endif
+ case kCommandSkins: return true;
+ case kCommandHostFS: return true;
+ case kCommandBreakpoints: return true;
+
+ case kCommandGremlinsNew: return gSession != NULL && Hordes::CanNew ();
+ case kCommandGremlinsSuspend: return gSession != NULL && Hordes::CanSuspend ();
+ case kCommandGremlinsStep: return gSession != NULL && Hordes::CanStep ();
+ case kCommandGremlinsResume: return gSession != NULL && Hordes::CanResume ();
+ case kCommandGremlinsStop: return gSession != NULL && Hordes::CanStop ();
+ case kCommandEventReplay: return true;
+ case kCommandEventMinimize: return true;
+
+#if HAS_PROFILING
+ case kCommandProfileStart: return gSession != NULL && ::ProfileCanStart ();
+ case kCommandProfileStop: return gSession != NULL && ::ProfileCanStop ();
+ case kCommandProfileDump: return gSession != NULL && ::ProfileCanDump ();
+#endif
+
+ case kCommandAbout: return true;
+ case kCommandQuit: return true;
+
+ case kCommandEmpty: return false;
+
+ case kCommandFile: return true;
+ case kCommandEdit: return true;
+ case kCommandGremlins: return true;
+#if HAS_PROFILING
+ case kCommandProfile: return true;
+#endif
+
+ case kCommandRoot: return true;
+ case kCommandOpen: return true;
+ case kCommandImport: return true;
+ case kCommandSettings: return true;
+
+ case kCommandDivider: return false;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetItemStatus
+// ---------------------------------------------------------------------------
+// Respond to the preference change by invalidating one of our flags. This
+// flag will be inspected later when getting a menu to display.
+
+void PrvPrefsChanged (PrefKeyType key, void*)
+{
+ if (strcmp (key, kPrefKeyPSF_MRU) == 0)
+ {
+ ++gChangeCount;
+ }
+ else if (strcmp (key, kPrefKeyPRC_MRU) == 0)
+ {
+ ++gChangeCount;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPreferredMenuID
+// ---------------------------------------------------------------------------
+// Translate the given menu ID into the one we really should use. For the
+// most cases, that merely means returning the given ID. However, for
+// kMenuMenubarPreferred and kMenuPopupMenuPreferred, that means checking
+// our "bound" state and returning the actual menu to use.
+
+EmMenuID PrvPreferredMenuID (EmMenuID id)
+{
+ switch (id)
+ {
+ case kMenuMenubarPreferred:
+ if (gApplication->IsBoundPartially ()) return kMenuMenubarPartiallyBound;
+ if (gApplication->IsBoundFully ()) return kMenuMenubarPartiallyBound;
+ return kMenuMenubarFull;
+ case kMenuMenubarFull: return kMenuMenubarFull;
+ case kMenuMenubarPartiallyBound: return kMenuMenubarPartiallyBound;
+ case kMenuMenubarFullyBound: return kMenuMenubarFullyBound;
+
+ case kMenuPopupMenuPreferred:
+ if (gApplication->IsBoundPartially ()) return kMenuPopupMenuPartiallyBound;
+ if (gApplication->IsBoundFully ()) return kMenuPopupMenuFullyBound;
+ return kMenuPopupMenuFull;
+ case kMenuPopupMenuFull: return kMenuPopupMenuFull;
+ case kMenuPopupMenuPartiallyBound: return kMenuPopupMenuPartiallyBound;
+ case kMenuPopupMenuFullyBound: return kMenuPopupMenuFullyBound;
+
+ case kMenuNone:
+ break;
+ }
+
+ return kMenuNone;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::EmMenuItem
+// ---------------------------------------------------------------------------
+
+EmMenuItem::EmMenuItem (void) :
+ fTitle (),
+ fShortcut (0),
+ fCommand (kCommandNone),
+ fFlagActive (false),
+ fFlagChecked (false),
+ fFlagDivider (true),
+ fChildren ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::EmMenuItem
+// ---------------------------------------------------------------------------
+
+EmMenuItem::EmMenuItem (const EmMenuItem& other) :
+ fTitle (other.fTitle),
+ fShortcut (other.fShortcut),
+ fCommand (other.fCommand),
+ fFlagActive (other.fFlagActive),
+ fFlagChecked (other.fFlagChecked),
+ fFlagDivider (other.fFlagDivider),
+ fChildren (other.fChildren)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::EmMenuItem
+// ---------------------------------------------------------------------------
+
+EmMenuItem::EmMenuItem (StrCode str, EmCommandID cmd) :
+ fTitle (this->ExtractTitle (Platform::GetString (str))),
+ fShortcut (this->ExtractShortcut (Platform::GetString (str))),
+ fCommand (cmd),
+ fFlagActive (true),
+ fFlagChecked (false),
+ fFlagDivider (cmd == kCommandDivider),
+ fChildren ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::EmMenuItem
+// ---------------------------------------------------------------------------
+
+EmMenuItem::EmMenuItem (const string& title, EmCommandID cmd) :
+ fTitle (this->ExtractTitle (title)),
+ fShortcut (this->ExtractShortcut (title)),
+ fCommand (cmd),
+ fFlagActive (true),
+ fFlagChecked (false),
+ fFlagDivider (cmd == kCommandDivider),
+ fChildren ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::~EmMenuItem
+// ---------------------------------------------------------------------------
+
+EmMenuItem::~EmMenuItem (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetTitle
+// ---------------------------------------------------------------------------
+
+string EmMenuItem::GetTitle (void) const
+{
+ return fTitle;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetShortcut
+// ---------------------------------------------------------------------------
+
+char EmMenuItem::GetShortcut (void) const
+{
+ return fShortcut;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetCommand
+// ---------------------------------------------------------------------------
+
+EmCommandID EmMenuItem::GetCommand (void) const
+{
+ return fCommand;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetChildren
+// ---------------------------------------------------------------------------
+
+EmMenuItemList& EmMenuItem::GetChildren (void)
+{
+ return fChildren;
+}
+
+const EmMenuItemList& EmMenuItem::GetChildren (void) const
+{
+ return fChildren;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetIsActive
+// ---------------------------------------------------------------------------
+
+Bool EmMenuItem::GetIsActive (void) const
+{
+ return fFlagActive;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetIsChecked
+// ---------------------------------------------------------------------------
+
+Bool EmMenuItem::GetIsChecked (void) const
+{
+ return fFlagChecked;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::GetIsDivider
+// ---------------------------------------------------------------------------
+
+Bool EmMenuItem::GetIsDivider (void) const
+{
+ return fFlagDivider;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetTitle
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetTitle (const string& title)
+{
+ fTitle = this->ExtractTitle (title);
+ fShortcut = this->ExtractShortcut (title);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetShortcut
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetShortcut (char shortcut)
+{
+ fShortcut = shortcut;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetCommand
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetCommand (EmCommandID command)
+{
+ fCommand = command;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetChildren
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetChildren (const EmMenuItemList& children)
+{
+ fChildren = children;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetIsActive
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetIsActive (Bool active)
+{
+ fFlagActive = active;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetIsChecked
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetIsChecked (Bool checked)
+{
+ fFlagChecked = checked;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::SetIsDivider
+// ---------------------------------------------------------------------------
+
+void EmMenuItem::SetIsDivider (Bool divider)
+{
+ fFlagDivider = divider;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::ExtractTitle
+// ---------------------------------------------------------------------------
+
+string EmMenuItem::ExtractTitle (const string& title) const
+{
+ string result (title);
+
+ // Look for any TAB, indicating a shortcut character.
+
+ string::size_type tabPos = result.find ('\t');
+ if (tabPos != string::npos)
+ {
+ result.erase (tabPos, 2);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMenuItem::ExtractShortcut
+// ---------------------------------------------------------------------------
+
+char EmMenuItem::ExtractShortcut (const string& title) const
+{
+ char result (0);
+
+ // Look for any TAB, indicating a shortcut character.
+
+ string::size_type tabPos = title.find ('\t');
+ if (tabPos != string::npos)
+ {
+ result = title[tabPos + 1];
+ }
+
+ return result;
+}
diff --git a/SrcShared/EmMenus.h b/SrcShared/EmMenus.h
new file mode 100644
index 0000000..1b0d65e
--- /dev/null
+++ b/SrcShared/EmMenus.h
@@ -0,0 +1,190 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmMenus_h
+#define EmMenus_h
+
+#include "EmCommands.h" // EmCommandID
+
+#include <string>
+#include <vector>
+
+
+/*
+ This file defines the objects and routines for creating, managing,
+ and manipulating menubars, menus, and menu items.
+
+ Menu items (EmMenuItem) are the base object clients deal with. A
+ menu item is pretty much what you think it is: a distinct item in
+ a menu. Every menu item has the following properties:
+
+ Title
+ This is the text that appears on screen. The title can also
+ contain an '&' to indicate any mnemonic character, and can
+ optionally be broken into two fields with a TAB character,
+ with the second field containing a single character to be
+ used as a shortcut or accelerator. Example:
+
+ "&New\tN"
+
+ Shortcut
+ This is the Cmd, Ctrl, or Alt shortcut character. It can
+ be specified along with the title (which makes associating
+ the title and shortcut easy in a string resource) or
+ separately via dedicated API.
+
+ Command
+ This is the value indicating what menu item was just selected
+ and what action should be taken. There is no rule that says
+ all menu items should have unique command numbers, but it makes
+ looking up menu items by their command number easier.
+
+ Flags
+ A set of Boolean flags.
+
+ Active/Inactive
+ Indicates whether the menu item is drawn normally and is
+ selectable, or is drawn grayed out and is not selectable.
+
+ Checked/Unchecked
+ Indicates whether or not the menu item is drawn with a
+ check mark next to it.
+
+ Visible/Invisible
+ Indicates whether or not the menu item appears in the
+ host menu at all.
+
+ Divider
+ Menu items marked as dividers appear as dividers or
+ separators in the host menu. The are implicitly inactive
+ and unchecked, implicitly have no children or shortcuts,
+ and their titles are ignored.
+
+ Children
+ Each menu item can have zero or more children. A menu item
+ with children is called a hierarchical menu, and the children
+ are grouped together in a sub-menu. Hierarchical menus
+ cannot be selected themselves (that is, highlighting one and
+ dismissing the menu does not result in a command number being
+ generated).
+
+ A menu (EmMenu) is merely an ordered collection of menu items.
+
+ A menubar is merely a menu where all the menu items are hierarchical.
+*/
+
+class EmMenuItem;
+typedef vector<EmMenuItem> EmMenuItemList;
+
+
+// This class is pretty straightforward. It's an example of what we
+// called "structification" at Taligent (and were told not to use).
+// The class is mostly data with getters and setters for that data.
+// The only non-straightforward parts are:
+//
+// * Calling SetTitle will check to see if a shortcut character
+// is included. If so, it is removed, stored as the shortcut
+// character, and the remaining string is stored as the title
+// without it.
+//
+// * GetChildren returns a non-const reference to the children.
+// Thus, you can modify the collection directly. Of course,
+// you can also just replace whatever collection is there by
+// calling SetChildren.
+
+class EmMenuItem
+{
+ public:
+ EmMenuItem (void); // Creates a divider
+ EmMenuItem (const EmMenuItem&);
+ EmMenuItem (StrCode, EmCommandID);
+ EmMenuItem (const string&, EmCommandID);
+ ~EmMenuItem (void);
+
+ string GetTitle (void) const;
+ char GetShortcut (void) const;
+ EmCommandID GetCommand (void) const;
+ EmMenuItemList& GetChildren (void);
+ const EmMenuItemList& GetChildren (void) const;
+ Bool GetIsActive (void) const;
+ Bool GetIsChecked (void) const;
+ Bool GetIsDivider (void) const;
+
+ void SetTitle (const string&);
+ void SetShortcut (char);
+ void SetCommand (EmCommandID);
+ void SetChildren (const EmMenuItemList&);
+ void SetIsActive (Bool);
+ void SetIsChecked (Bool);
+ void SetIsDivider (Bool);
+
+ private:
+ string ExtractTitle (const string&) const;
+ char ExtractShortcut (const string&) const;
+
+ private:
+ string fTitle;
+ char fShortcut;
+ EmCommandID fCommand;
+ Bool fFlagActive;
+ Bool fFlagChecked;
+ Bool fFlagDivider;
+ EmMenuItemList fChildren;
+};
+
+
+// An EmMenu is a top-level menu. It is the same as an EmMenuItemList,
+// with the addition of a changecount used as a timestamp. This
+// changecount is used to determine if the menu needs to be updated in
+// the face of any changes (such as the MRU lists changing).
+
+class EmMenu : public EmMenuItemList
+{
+ public:
+ EmMenu (void) : EmMenuItemList () {}
+ EmMenu (const EmMenuItemList& o) : EmMenuItemList (o) {}
+ ~EmMenu (void) {}
+
+ unsigned long GetChangeCount (void) { return fChangeCount; };
+ void SetChangeCount (unsigned long v) { fChangeCount = v; }
+
+ private:
+ unsigned long fChangeCount;
+};
+
+
+
+
+enum EmMenuID
+{
+ kMenuNone,
+
+ kMenuMenubarPreferred,
+ kMenuMenubarFull,
+ kMenuMenubarPartiallyBound,
+ kMenuMenubarFullyBound,
+
+ kMenuPopupMenuPreferred,
+ kMenuPopupMenuFull,
+ kMenuPopupMenuPartiallyBound,
+ kMenuPopupMenuFullyBound
+};
+
+void MenuInitialize (Bool alternateLayout);
+EmMenu* MenuFindMenu (EmMenuID);
+EmMenuItem* MenuFindMenuItemByCommandID (EmMenuItemList&, EmCommandID, Bool recurse);
+EmMenuItemList* MenuFindMenuContainingCommandID (EmMenuItemList&, EmCommandID);
+void MenuUpdateMruMenus (EmMenu&);
+void MenuUpdateMenuItemStatus (EmMenuItemList&);
+
+#endif // EmMenus_h
diff --git a/SrcShared/EmMinimize.cpp b/SrcShared/EmMinimize.cpp
new file mode 100644
index 0000000..16ce4e6
--- /dev/null
+++ b/SrcShared/EmMinimize.cpp
@@ -0,0 +1,1310 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmMinimize.h"
+
+#include "EmApplication.h" // gApplication->ScheduleQuit
+#include "EmDlg.h" // MinimizeProgressOpen, DoCommonDialog
+#include "EmEventPlayback.h" // EnableEvents, DisableEvents
+#include "EmPalmOS.h" // EmPalmOS::GenerateStackCrawl
+#include "EmSession.h" // gSession
+#include "Logging.h" // LogAppendMsg
+#include "ROMStubs.h" // DmDatabaseInfo
+#include "Startup.h" // Startup::MinimizeQuitWhenDone
+#include "EmEventOutput.h" // StartGatheringInfo, GatherInfo, OutputEvents
+
+#include "ChunkFile.h" // ChunkFile
+#include "EmStreamFile.h" // EmStreamFile
+#include "SessionFile.h" // SessionFile
+
+#include <math.h> // pow
+#include <strstream> // strstream
+
+/*
+ Minimization Overview
+
+ A Gremlin run may terminate in error after any number of events.
+ However, experience has shown that not all events created by the
+ Gremlin are necessary to reproduce the error. Through minimization,
+ the Palm OS Emulator attempts to find the minimal set of events that
+ will cause an error. The use of "an" rather than "the" is
+ intentional, as we can have no assurance that any error that occurs
+ when intermediate events are cut out is the same error that
+ initially occurred. The distinction is likely academic; what matters
+ is that, given a file describing events that were generated by a
+ Gremlin during a run, minimization will separate the wheat from the
+ chaff, so to speak, by cutting out those events that do not
+ contribute to the error.
+
+ Theory
+
+ Each event generated by a Gremlin can be viewed as a vertex in a
+ directed graph. Each of these events relies on a particular context
+ for its action to be relevant. For example, the first event relies
+ on the root state to be loaded, and nothing else. The vertex or
+ vertices that are responsible for bringing about a context (such as
+ bringing up the Find dialog) have directed edges to all vertices
+ representing actions within this context. If a particular vertex
+ relies on no prior vertices for its context (the first vertex being
+ a prime example), then the only vertex with an edge to it is the
+ vertex representing the root state, which is noteworthy because it
+ is the only vertex with no incoming edges.
+
+ Viewed in this way, it becomes apparent that the problem of
+ minimization is nothing more than finding the minimal set of
+ vertices such that there is an unbroken string of directed edges
+ between said vertices, and that the vertices representing the root
+ state and the error-causing event are both within this set.
+
+ In an alternate interpretation, events are once again vertices, and
+ there are causal directed edges between events; the difference lies
+ in that an edge is present iff the events represented by its
+ endpoints are necessary to cause the error. Then the problem of
+ minmization becomes a vertex cover problem: for reference, see:
+ <http://www.cs.sunysb.edu/~algorith/files/vertex-cover.shtml>.
+
+ Algorithm choice
+
+ Vertex cover is an NP-complete problem, so it is not surprising that
+ we cannot find a polynomial-time (in the number of events) algorithm
+ to find the minimal set of events that will cause an error. Instead,
+ I settle for an algorithm of order O(n^2 log n) -- in the worst
+ case, it may have to make n log n passes, each O(n) because there
+ are n events. This algorithm, while superficially resembling a
+ divide-and-conquer algorithm, really is just a blind uninformed
+ search algorithm that happens to narrow its scope by a factor of 2
+ each time that it cuts out too many events. (Incidentally, I
+ implemented a true divide-and-conquer algorithm as well, of nominal
+ complexity O(n log n), which turned out to be slower on average than
+ this algorithm, because of the sparse nature of this problem space
+ since relatively few events typically contribute to an error.)
+
+ Initially, the algorithm sub-divides the original event ranges into
+ two or more smaller ranges, each range smaller than some hard- coded
+ value (1024 in this implementation). Each range is then considered
+ one at a time by. The range is cast out, and then the remaining
+ events are replayed to see if the crash still occurs. If not, then
+ the "cast out" range is considered non-essential and is permanently
+ removed. If the error no longer occurs, then some event is that
+ range is considered crucial to producing the crash. The range is the
+ sub-divided in an effort to narrow in on which event or events are
+ required. Sub-division continues to the single event level.
+
+ After each of the initial sub-disivisions has been examined in this
+ fashion, Poser checks to see if any events have been permanently
+ removed. If so, the remaining set of events is saved to their own
+ .pev file, and the process begins again with this reduced set of
+ events. Minimization proceeds with this iteration until it has a
+ set of events it can no longer reduce.
+
+ Implementation
+
+ Since the structure of Palm OS Emulator does not allow for a
+ recursive function that controls the entire process of minimization
+ (as would ideally be the case), more novel means are used instead.
+ As noted in the example below, the minimization process works by
+ taking an event range, splitting it in two, and then testing each
+ side to see if it is necessary for an error to occur. If so, then
+ we permanently disable that range of events and try the other half.
+ But if the error did not occur, then we need to split the sub-range
+ in two again and try again.
+
+ The state for the process of splitting event ranges is stored in the
+ fgState member. This variable contains an fLevels member, which is
+ a stack of event ranges. The oldest item on the stack contains the
+ entire event range. The next items on the stack contain the left
+ and right ranges after bisecting the initial range. Each subsequent
+ element on the stack is a further splitting of a range of the
+ previous element.
+
+ Example
+
+ Let us imagine that we have a 8-event Gremlin run that terminates in
+ an error that we wish to minimize. Of these 8 events, numbered
+ 0-indexed from 0-7, only events 0 and 7 are necessary. What these
+ events actually are is inconsequential.
+
+ This is the sequence of events that would transpire:
+
+ LoadEvents would load the .pev file, initializing the event history
+ vector. In Start, an initial event range, whose span is the whole
+ range of events (0-7) would be created. Since I make the (relatively
+ safe) assumption that one cannot eliminate all of the events in a
+ Gremlin run (save for the penultimate and ultimate events) and still
+ hope to encounter the error, the root range's events are not turned
+ off, and instead it spawns two sub-ranges. These two child ranges
+ cover the ranges (0-3) and (4-7), respectively. First the (0-3)
+ range would be selected (this in Start -- for all other selections,
+ NextSubRange is the locale), and events 0-3 turned off by setting
+ appropriate bits in a mask to false. The mask at this point would
+ look like this: f-f-f-f-t-t-t-t. Since event 0 is necessary to
+ reproduce the error, we would reach NoErrorOccurred. This means
+ that we now knew that something in the range (0-3) was important,
+ and that we needed to further examine that range. Thus, we end up
+ calling SplitAndStartAgain.
+
+ In NoErrorOccurred, (0-3) would have its events turned on, and then
+ SplitAndStartAgain would sub-divide the range into (0-1) and (2-3).
+ The event mask of (0-1) would then be masked (ie, the events would
+ not be replayed). At this point the event mask would look like this:
+ f-f-t-t-t-t-t-t. Again, we would not find the error, since event 0
+ would still not be replayed. The process would then be repeated,
+ with the ramge (0-1) spawning two sub-ranges of (0-0) and (1-1). The
+ left child of (0-1), (0-0) would be selected to run next. The event
+ mask would look like this: f-t-t-t-t-t-t-t.
+
+ This time, since we would be playing back all events except for 0,
+ the run would again not terminate in error. At this point we will
+ have hit our depth limit, so in NoErrorOccurred, the events in the
+ current range (only event 0) would be turned on. Then, in
+ SplitAndStartAgain, we would realize that we could no longer split
+ the event range. We would then call NextSubRange, which would
+ select (1-1) from the stack of event ranges still left to examine.
+ The event mask at this point would look like this: t-f-t-t-t-t-t-t.
+ Its run would terminate in error, so from
+ ErrorHandling::HandleDialog, ErrorOccurred would be called, not
+ NoErrorOccurred. This means that the range (1-1) will not spawn
+ children of its own, or have the events within its range turned back
+ on. Instead, ErrorOccurred will climb up the stack to (2-3). Its
+ events would be turned off, making the event mask look like this:
+ t-f-f-f-t-t-t-t.
+
+ Since events 0 and 7 are both turned on, this run would terminate in
+ error. In ErrorOccurred, event range (4-7) would be the next set of
+ events to examine. When (4-7)'s events are turned off, event 7 would
+ be turned off, and the error would no longer occur. The process
+ would then continue until events 0 and 7 were the only events
+ remaining, where the event mask is t-f-f-f-f-f-f-t. This run would
+ terminate in error, since events 0 and 7 would be played back.
+
+ In ErrorOccurred, we'd see that the event range stack would be
+ exhausted. We'd then save out the remaining events (0 and 7) to a
+ .pev file and run the whole process over again to see if any further
+ progress could be made. In our hypothetical situation, we'd find
+ that events 0 and 7 would still be needed.
+
+ Next, we would make one last pass over the remaining events. This
+ time, it's not to see if any events can be removed. Instead, it's
+ to collect contextual information useful in creating an English
+ report for the user. In particular, we'd find out what, if any
+ objects on the screen were hit by pen events so that we could report
+ then instead of telling the user to tap at, say, screen location 53,
+ 112.
+
+ Finally, the ultimate minimal set of events is written to a .pev
+ file suitable for replaying, and are are converted into a set of
+ English instructions that, when followed by a human, should result
+ in the same crash as replaying the events file does.
+
+ Improvements
+
+ The current algorithm, while useful, could still be improved in many
+ ways. Following are some ideas that occur to us, in case some
+ developer feels the need to implement them for us. :-)
+
+ * Semantic subdivision
+
+ Currently, the algorithm makes little distinction as to where it
+ decides to sub-divide event ranges. Other than the initial set of
+ ranges (where Poser keeps dividing until each sub-range is fewer
+ than some fairly arbitrary upper limit) and the single-event ranges
+ (where Poser gives pen-up events special treatment), Poser merely
+ takes an event range and divides it in two.
+
+ Instead, it would be good to first scope out the set of events and
+ mark out good division points. At the first level, Poser would find
+ all places where application switches take place and set division
+ points at those events. The theory here is that if the Address Book
+ crashes, what previously occurred in the Calculator application is
+ of little consequence. A pass over the events would then be made,
+ attempting to cast out events that occur between app switch events.
+
+ Next, the algorithm would attempt the same thing with forms. Again,
+ the theory is that if you crash in Form B, what just occurred in
+ Form A has a good chance of being irrelevent. Of course, this is
+ not a universally true statement, but that's why we perform our
+ tests and see what happens. For the cases where Forms A and B are
+ not strongly connected, we can cut out a whole swath of events at
+ one blow.
+
+ Next, we examine events at a key and pen sequence level. For key
+ sequences, we assume that there's little difference between one key
+ event and many key events. Therefore, we trim down any key
+ sequences to just the first key and try a run with just that event.
+ If the crash still occurs, we've just made a big win. Similarly,
+ with pen sequences, if there are three or more pen-down events
+ before the final pen-up event, we can try to remove all events
+ between the first and last pen down events. The idea here is that
+ only the initial pen down location and the final pen up location are
+ likely to be important, and that cutting out everything in between
+ would probably be OK.
+
+ Finally, we can make a pass using the current algorithm that slices
+ and dices down to the single event level. At this point, we
+ probably won't be removing too many events, but should also have
+ relatively few, so the slice and dice process shouldn't take very
+ long.
+
+ * Menu descriptions
+
+ Currently, taps on menu items are reported as "Tap at x,y". Where
+ possibly, this is annotated with the name of the dialog that is
+ brought up because of that menu selection. But it would ultimately
+ be better to provide the text of the menu and menu item.
+
+ * HTML output
+
+ Currently, the English translation is provided in a plain text file.
+ What might be nicer is an HTML file that can reference screen shots
+ showing what's going on at particular points. For instance,
+ sometimes saying "Tap on control "Foo"" is not enough -- sometimes
+ it's important to know where on "Foo" was tapped if it were a
+ multipart control. Being able to see a screen shot with cross-hairs
+ at the point where the user is supposed to tap would be a big help.
+
+ * Tap-drag
+
+ A sequence of pen-down events followed by a pen-up event are
+ currently reported as a series of "Tap at x,y" messages. Instead,
+ they should be reported as "Tap at x,y", "Drag to x,y", etc.
+ messages.
+*/
+
+
+#if _DEBUG
+#define LOG_MINIMIZATION 1
+#else
+#define LOG_MINIMIZATION 0
+#endif
+
+#define PRINTF if (!LOG_MINIMIZATION) ; else LogAppendMsg
+
+static const int kMaxRange = 1024; // Don't handle any ranges larger than this.
+static const int kLastPass = 0; // Indicates we're making a last pass
+
+omni_mutex EmMinimize::fgMutex;
+EmMinimize::EmMinimizeState EmMinimize::fgState;
+Bool EmMinimize::fgIsOn;
+uint32 EmMinimize::fgStartTime;
+long EmMinimize::fgInitialNumberOfEvents;
+long EmMinimize::fgDiscardedNumberOfEvents;
+long EmMinimize::fgPassNumber;
+Bool EmMinimize::fgPassEndedInError;
+StringList EmMinimize::fgLastStackCrawl;
+
+
+static inline Bool PrvIsPenUp (const PointType& pt)
+{
+ return (pt.x == -1) && (pt.y == -1);
+}
+
+static inline Bool PrvIsPenDown (const PointType& pt)
+{
+ return !::PrvIsPenUp (pt);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Initialize
+// ---------------------------------------------------------------------------
+
+void EmMinimize::Initialize (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Reset
+// ---------------------------------------------------------------------------
+
+void EmMinimize::Reset (void)
+{
+ EmMinimize::TurnOn (false);
+ fgState.fLevels.clear ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Save
+// ---------------------------------------------------------------------------
+
+void EmMinimize::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Load
+// ---------------------------------------------------------------------------
+
+void EmMinimize::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Dispose
+// ---------------------------------------------------------------------------
+
+void EmMinimize::Dispose (void)
+{
+ EmMinimize::TurnOn (false);
+ fgState.fLevels.clear ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Start
+// ---------------------------------------------------------------------------
+// Startup the entire minimization process. Called after a document is loaded
+// with the intent of minimizaing the events stored with it.
+
+void EmMinimize::Start (void)
+{
+ // Load the events. Events are not loaded by default when the rest of
+ // the session loads. See comments for EmEventPlayback::Load ().
+
+ EmMinimize::LoadEvents ();
+
+ // Enable all events
+
+ EmEventPlayback::EnableEvents ();
+
+ // Check that this is a stream that ended in error.
+
+ fgInitialNumberOfEvents = EmMinimize::FindFirstError ();
+ if (fgInitialNumberOfEvents < 0)
+ {
+ EmDlg::DoCommonDialog ("Could not find an error.", kDlgFlags_OK);
+ return;
+ }
+
+ // Get rid of the error event and all events after it. The error event
+ // will be returned at the end of the minimization process, but for now,
+ // it just get's in the way.
+
+ EmEventPlayback::DisableEvents (fgInitialNumberOfEvents);
+ EmEventPlayback::CullEvents ();
+
+ // Re-update fgInitialNumberOfEvents; the number of events could have been
+ // decreased further than expected if there were consecutive pen-up events
+ // in the stream (Gremlins *can* generate that).
+
+ fgInitialNumberOfEvents = EmEventPlayback::CountNumEvents ();
+
+ // Initialize the minimization routines.
+
+ fgState.fLevels.clear ();
+ fgStartTime = Platform::GetMilliseconds ();
+ fgDiscardedNumberOfEvents = 0;
+ fgPassNumber = 1;
+
+ EmMinimize::TurnOn (true);
+ EmMinimize::InitialLevel ();
+ EmMinimize::SplitAndStartAgain ();
+
+ // Open the progress dialog.
+
+ EmDlg::MinimizeProgressOpen ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::Stop
+// ---------------------------------------------------------------------------
+// Stop the entire minimization process. Called when the user presses the
+// "Stop" button in the Minimization Control dialog.
+
+void EmMinimize::Stop (void)
+{
+ EmMinimize::TurnOn (false);
+ EmEventPlayback::ReplayEvents (false);
+ EmEventOutput::GatherInfo (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::TurnOn
+// ---------------------------------------------------------------------------
+
+void EmMinimize::TurnOn (Bool newState)
+{
+ fgIsOn = newState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::IsOn
+// ---------------------------------------------------------------------------
+
+Bool EmMinimize::IsOn (void)
+{
+ return fgIsOn /* && EmEventPlayBack::ReplayingEvents () ? */;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::NoErrorOccurred
+// ---------------------------------------------------------------------------
+// The current set of events were replayed with no error occurring.
+// Therefore, we need to turn the most recent set of events back on, split
+// it, and try again.
+
+void EmMinimize::NoErrorOccurred (void)
+{
+ PRINTF ("EmMinimize::NoErrorOccurred:");
+
+ fgPassEndedInError = false;
+
+ // Turn current set of events back on.
+
+ long begin, end;
+ EmMinimize::CurrentRange (begin, end);
+ PRINTF ("EmMinimize::NoErrorOccurred: re-enabling events %ld - %ld.", begin, end - 1);
+
+ EmEventPlayback::EnableEvents (begin, end);
+
+ // If we were doing the "last pass" and got here anyway, we're pretty
+ // messed up. The "last pass" was supposed to be guaranteed to end in an
+ // error, but it didn't. Oh well. Finish up and tell the user what
+ // happened as best as we can.
+
+ if (EmMinimize::fgPassNumber == kLastPass)
+ {
+ fgState.fLevels.clear ();
+ EmMinimize::MinimizationPassComplete ();
+ return;
+ }
+
+ // Set the bit that says we examined this range and found it interesting.
+
+ fgState.fLevels.back ().fChecked = true;
+
+ // Split the current range and try again.
+
+ EmMinimize::SplitAndStartAgain ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::ErrorOccurred
+// ---------------------------------------------------------------------------
+// The current set of events resulted in an error occurring. Therefore, we
+// can keep the current set of events turned off, and try to find others to
+// turn off.
+
+void EmMinimize::ErrorOccurred (void)
+{
+ PRINTF ("EmMinimize::ErrorOccurred:");
+
+ fgPassEndedInError = true;
+
+ // Capture the current stack crawl in case we need it when reporting
+ // failure on the last pass to produce an error.
+
+ EmMinimize::GenerateStackCrawl (fgLastStackCrawl);
+
+ // Keep the current set of events turned off.
+
+ long begin, end;
+ EmMinimize::CurrentRange (begin, end);
+ PRINTF ("EmMinimize::ErrorOccurred: discarding events %ld - %ld.", begin, end - 1);
+
+ // Update the number of events we've discarded. Note that we update this
+ // value by calling CountEnabledEvents instead of adjusting by (end -
+ // begin). That's because some events are not discarded even though we've
+ // asked them to because they are too important to discard (e.g. pen up
+ // events).
+
+ fgDiscardedNumberOfEvents = fgInitialNumberOfEvents - EmEventPlayback::CountEnabledEvents ();
+
+ // If the error occurred before the last event was played, then let's
+ // disable all subsequent events and start afresh.
+
+ long currentEvent = EmEventPlayback::GetCurrentEvent ();
+ long numEvents = EmEventPlayback::GetNumEvents ();
+
+ if (currentEvent < numEvents)
+ {
+ PRINTF ("EmMinimize::ErrorOccurred: error occurred at event %ld of %ld.",
+ currentEvent, numEvents);
+
+ omni_mutex_lock lock (fgMutex);
+
+ // Disable all events past the one that just caused the error.
+
+ EmEventPlayback::DisableEvents (currentEvent);
+
+ // Clear the event range stack so that we can start a new pass.
+
+ fgState.fLevels.clear ();
+
+ // Start a new pass. This will also cull the events we just disabled.
+
+ EmMinimize::MinimizationPassComplete ();
+
+ return;
+ }
+
+ // Pop the current range and try the next one.
+
+ EmMinimize::NextSubRange ();
+}
+
+
+#pragma mark -
+
+uint32 EmMinimize::GetPassNumber (void)
+{
+ return fgPassNumber;
+}
+
+
+uint32 EmMinimize::GetElapsedTime (void)
+{
+ return Platform::GetMilliseconds () - fgStartTime;
+}
+
+
+void EmMinimize::GetCurrentRange (uint32& ubegin, uint32& uend)
+{
+ long begin, end;
+ EmMinimize::CurrentRange (begin, end);
+
+ ubegin = begin;
+ uend = end;
+}
+
+
+uint32 EmMinimize::GetNumDiscardedEvents (void)
+{
+ return fgDiscardedNumberOfEvents;
+}
+
+
+uint32 EmMinimize::GetNumInitialEvents (void)
+{
+ return fgInitialNumberOfEvents;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::MinimizationPassComplete
+// ---------------------------------------------------------------------------
+// We've finished splitting and replaying events. Examine the results to see
+// if we're done, or if we need to make another Minimization passing using the
+// remaining events.
+
+void EmMinimize::MinimizationPassComplete (void)
+{
+ // Get the initial number of events, remove the masked-out events, and
+ // then get the remaining number of events.
+
+ long oldNumEvents = EmEventPlayback::GetNumEvents ();
+
+ EmEventPlayback::CullEvents ();
+
+ long newNumEvents = EmEventPlayback::GetNumEvents ();
+
+ // If significant culling occurred, then let's make another pass.
+
+ if (EmMinimize::MakeAnotherPass (oldNumEvents, newNumEvents))
+ {
+ PRINTF ("EmMinimize::MinimizationPassComplete: making another pass.");
+ PRINTF (" oldNumEvents = %ld", oldNumEvents);
+ PRINTF (" newNumEvents = %ld", newNumEvents);
+
+ ++fgPassNumber;
+
+ EmMinimize::InitialLevel ();
+ EmMinimize::SplitAndStartAgain ();
+ }
+
+ // Make a final pass in order to collect context information
+
+ else if (fgPassNumber != kLastPass)
+ {
+ PRINTF ("EmMinimize::MinimizationPassComplete: making last pass.");
+ PRINTF (" oldNumEvents = %ld", oldNumEvents);
+ PRINTF (" newNumEvents = %ld", newNumEvents);
+
+ fgPassNumber = kLastPass;
+
+ // Tell EmEventOutput to wake up and start paying attention.
+
+ EmEventOutput::StartGatheringInfo ();
+
+ EmMinimize::InitialLevel ();
+ EmMinimize::StartAgain ();
+ }
+
+ // Otherwise, we are done!
+
+ else
+ {
+ PRINTF ("EmMinimize::MinimizationPassComplete: DONE.");
+ PRINTF (" oldNumEvents = %ld", oldNumEvents);
+ PRINTF (" newNumEvents = %ld", newNumEvents);
+
+ EmMinimize::MinimizationComplete ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::MinimizationComplete
+// ---------------------------------------------------------------------------
+// Minimization is completely done. Save the results, write out a text
+// version of the events, and tell the user.
+
+void EmMinimize::MinimizationComplete (void)
+{
+ PRINTF ("EmMinimize::MinimizationComplete: DONE.");
+
+ // Stop the presses.
+
+ EmMinimize::TurnOn (false);
+ EmEventPlayback::ReplayEvents (false);
+ EmEventOutput::GatherInfo (false);
+
+ // Save the minimal set of events.
+
+ EmMinimize::SaveMinimalEvents ();
+
+ // Convert the events to an English description.
+
+ EmMinimize::OutputEventsAsEnglish ();
+
+ // Reset to our initial state (as opposed to the error state we're
+ // currently in).
+
+ EmMinimize::LoadInitialState ();
+
+ if (Startup::MinimizeQuitWhenDone ())
+ {
+ gApplication->ScheduleQuit ();
+ }
+ else
+ {
+ // Show a dialog telling the user about the results.
+
+ char buffer[200];
+ sprintf (buffer, "Minimization has been completed. %ld of %ld events discarded.",
+ fgDiscardedNumberOfEvents, fgInitialNumberOfEvents);
+
+ EmDlg::DoCommonDialog (buffer, kDlgFlags_OK);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::SaveMinimalEvents
+// ---------------------------------------------------------------------------
+
+void EmMinimize::SaveMinimalEvents (void)
+{
+ // Get the original event file. We'll save the events in the same
+ // directory but with a modified name.
+
+ EmFileRef oldEventRef = gSession->GetFile ();
+ string oldEventName = oldEventRef.GetName ();
+
+ // Convert the name from <Foo>.pev to <Foo>_Min.pev.
+
+ string newEventName = oldEventName;
+
+ if (::EndsWith (newEventName.c_str (), ".pev"))
+ {
+ newEventName = newEventName.substr (0, newEventName.size () - 4);
+ }
+
+ newEventName += "_Min.pev";
+
+ // Copy the old session file to the new one that will hold the minimized
+ // event set.
+
+ EmFileRef newEventRef (oldEventRef.GetParent (), newEventName);
+
+ EmStreamFile oldEventStream (oldEventRef, kOpenExistingForRead,
+ kFileCreatorEmulator, kFileTypeEvents);
+ EmStreamFile newEventStream (newEventRef, kCreateOrEraseForWrite,
+ kFileCreatorEmulator, kFileTypeEvents);
+
+ ChunkFile oldEventChunkFile (oldEventStream);
+ ChunkFile newEventChunkFile (newEventStream);
+
+ int index = 0;
+ ChunkFile::Tag tag;
+ Chunk chunk;
+
+ while (oldEventChunkFile.ReadChunk (index, tag, chunk))
+ {
+ // Copy all chunks except the previous (pre-minimized) event set.
+ // We'll be adding the minimized event set to the file later.
+
+ if (tag != /*SessionFile::kGremlinHistory*/ 'hist')
+ {
+ newEventChunkFile.WriteChunk (tag, chunk);
+ }
+
+ ++index;
+ }
+
+ // When starting minimization, we removed all events beyond and including
+ // the terminating error event. Before saving out the new event set, add
+ // back the error event.
+
+ EmEventPlayback::RecordEvents (true);
+ EmEventPlayback::RecordErrorEvent ();
+ EmEventPlayback::RecordEvents (false);
+
+ // Now write the final event set.
+
+ SessionFile newEventSessionFile (newEventChunkFile);
+ EmEventPlayback::SaveEvents (newEventSessionFile);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::OutputEventsAsEnglish
+// ---------------------------------------------------------------------------
+
+void EmMinimize::OutputEventsAsEnglish (void)
+{
+ EmEventPlayback::LogEvents ();
+
+ // Create a string stream to which we will write out results. After we
+ // completely buffer the output, we'll write it to a file. We don't write
+ // directly to the file so that we can take advantage of the
+ // integer-to-text conversion facilities of ostream.
+
+ strstream stream;
+
+ // Write out our initial message.
+
+ EmFileRef ref = gSession->GetFile ();
+ string path = ref.GetFullPath ();
+
+ stream << "=== Minimal Events: (" << path << ")" << endl;
+
+ // Write out events.
+
+ EmEventOutput::OutputEvents (stream);
+
+ // If the last pass managed to fail to produce an error, tell the user
+ // about it, and show them the competing stack crawls.
+
+ if (!EmMinimize::fgPassEndedInError)
+ {
+ StringList currentStackCrawl;
+ EmMinimize::GenerateStackCrawl (currentStackCrawl);
+
+ stream << endl;
+ stream << "WARNING WARNING WARNING" << endl;
+ stream << endl;
+ stream << "After the minimization process produces a minimal set of events" << endl;
+ stream << "leading to a crash, it makes one last run through the events," << endl;
+ stream << "collecting context information used to create the descriptions" << endl;
+ stream << "above. However, on this last pass, no error occurred. Following" << endl;
+ stream << "are the current stack crawl and the stack crawl captured the last" << endl;
+ stream << "time a crash occurred." << endl;
+ stream << endl;
+
+ stream << "Current call stack:" << endl;
+ EmEventOutput::OutputStack (stream, currentStackCrawl);
+ stream << endl;
+
+ stream << "Last error-producing call stack:" << endl;
+ EmEventOutput::OutputStack (stream, fgLastStackCrawl);
+ stream << endl;
+ }
+
+ // Write out final message.
+
+ stream << "=== Event listing complete." << endl;
+
+ // Get the original event file. We'll save the events in the same
+ // directory but with a modified name.
+
+ // Convert the name from <Foo>.pev to <Foo>_Min.pev.
+
+ string textEventName = ref.GetName ();
+
+ if (::EndsWith (textEventName.c_str (), ".pev"))
+ {
+ textEventName = textEventName.substr (0, textEventName.size () - 4);
+ }
+
+ textEventName += "_Min.txt";
+
+ // Create the output file.
+
+ EmFileRef textEventRef (ref.GetParent (), textEventName);
+ EmStreamFile textEventStream (textEventRef, kCreateOrEraseForWrite | kOpenText,
+ kFileCreatorCodeWarrior, kFileTypeText);
+
+ // Write the event text to it.
+
+ textEventStream.PutBytes (stream.str (), stream.pcount ());
+
+ // Unfreeze the stream, or else its storage will be leaked.
+
+ stream.freeze (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::MakeAnotherPass
+// ---------------------------------------------------------------------------
+// Return whether or not we feel that a significant amount of event culling
+// had occurred in the pass. If so, we'll want to make another pass.
+
+Bool EmMinimize::MakeAnotherPass (long oldNumEvents, long newNumEvents)
+{
+ // Make another pass if we've reduced the number of events in the previous
+ // pass by more than 10%.
+
+ return newNumEvents < oldNumEvents;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::CurrentRange
+// ---------------------------------------------------------------------------
+// Return the current event range that we are examining.
+
+void EmMinimize::CurrentRange (long& begin, long& end)
+{
+ omni_mutex_lock lock (fgMutex);
+
+ if (fgState.fLevels.size () > 0)
+ {
+ begin = fgState.fLevels.back ().fBegin;
+ end = fgState.fLevels.back ().fEnd;
+ }
+ else
+ {
+ begin = 0;
+ end = 0;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::InitialLevel
+// ---------------------------------------------------------------------------
+// Set up our "fLevels" member with the initial left/right event sub-ranges.
+
+void EmMinimize::InitialLevel (void)
+{
+ EmAssert (fgState.fLevels.size () == 0);
+
+ // Establish the initial event range.
+
+ EmMinimizeLevel newLevel;
+
+ newLevel.fBegin = 0;
+ newLevel.fEnd = EmEventPlayback::GetNumEvents ();
+ newLevel.fChecked = false;
+
+ omni_mutex_lock lock (fgMutex);
+
+ fgState.fLevels.push_back (newLevel);
+
+#if LOG_MINIMIZATION
+ {
+ PRINTF ("EmMinimize::InitialLevel: Added first level.");
+
+ EmMinimizeLevelList::iterator iter = fgState.fLevels.begin ();
+
+ while (iter != fgState.fLevels.end ())
+ {
+ PRINTF (" %ld:", iter - fgState.fLevels.begin ());
+ PRINTF (" fBegin: %ld", iter->fBegin);
+ PRINTF (" fEnd: %ld", iter->fEnd);
+ PRINTF (" fChecked: %s", iter->fChecked ? "TRUE" : "FALSE");
+
+ ++iter;
+ }
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::SplitCurrentLevel
+// ---------------------------------------------------------------------------
+// Create a new level based on the given range. The given range is split in
+// two, records are created holding those two sub-ranges, and the records are
+// pushed onto our stack. Returns false if it was unable to create the two
+// new ranges (either because the current range is too narrow or too deep).
+
+Bool EmMinimize::SplitCurrentLevel (void)
+{
+ omni_mutex_lock lock (fgMutex);
+
+ EmAssert (fgState.fLevels.size () > 0);
+
+ // Split the next event range until it's of a manageable size.
+
+ while (1)
+ {
+ EmMinimizeLevel prevLevel = fgState.fLevels.back ();
+ long prevRange = prevLevel.fEnd - prevLevel.fBegin;
+
+ // If we're at the smallest range, leave and say we can't split this
+ // atom.
+
+ if (prevRange <= 1)
+ return false;
+
+ // Pop the top event range, split it, and put it back.
+
+ long midpoint = (prevLevel.fBegin + prevLevel.fEnd) / 2;
+
+ EmAssert (prevLevel.fBegin < midpoint);
+ EmAssert (midpoint < prevLevel.fEnd);
+
+ fgState.fLevels.pop_back ();
+
+ EmMinimizeLevel newLevel;
+
+ newLevel.fBegin = midpoint;
+ newLevel.fEnd = prevLevel.fEnd;
+ newLevel.fChecked = prevLevel.fChecked && (newLevel.fEnd - newLevel.fBegin) > 1;
+
+ fgState.fLevels.push_back (newLevel);
+
+ newLevel.fBegin = prevLevel.fBegin;
+ newLevel.fEnd = midpoint;
+ newLevel.fChecked = prevLevel.fChecked && (newLevel.fEnd - newLevel.fBegin) > 1;
+
+ fgState.fLevels.push_back (newLevel);
+
+ // If the range is now small enough, leave and say we have new ranges
+ // to deal with.
+
+ if (newLevel.fEnd - newLevel.fBegin <= kMaxRange)
+ break;
+ }
+
+#if LOG_MINIMIZATION
+ {
+ EmMinimizeLevelList::iterator iter = fgState.fLevels.begin ();
+
+ while (iter != fgState.fLevels.end ())
+ {
+ PRINTF (" %ld:", iter - fgState.fLevels.begin ());
+ PRINTF (" fBegin: %ld", iter->fBegin);
+ PRINTF (" fEnd: %ld", iter->fEnd);
+ PRINTF (" fChecked: %s", iter->fChecked ? "TRUE" : "FALSE");
+
+ ++iter;
+ }
+ }
+#endif
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::StartAgain
+// ---------------------------------------------------------------------------
+// Queue things up to start again. Start the playback mechanism, and reload
+// the initial state.
+
+void EmMinimize::StartAgain (void)
+{
+ PRINTF ("EmMinimize::StartAgain: starting over.");
+
+ EmEventPlayback::ReplayEvents (true);
+ EmMinimize::LoadInitialState ();
+
+ LogDump ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::SplitAndStartAgain
+// ---------------------------------------------------------------------------
+// Queue things up to start again. Start the playback mechanism, and reload
+// the initial state.
+
+void EmMinimize::SplitAndStartAgain (void)
+{
+ // Try to split the range. We may not be able to do that if the range is
+ // too narrow or we've split too many times already.
+
+ if (EmMinimize::SplitCurrentLevel ())
+ {
+ PRINTF ("EmMinimize::SplitAndStartAgain: split current range.");
+
+ // Attempt to disable the current range and start again. This may
+ // fail if we try to do something like disable a solitary pen-up
+ // event, in which case we'll move to the NextSubRange.
+
+ EmMinimize::DisableAndStartAgain ();
+ }
+ else
+ {
+ // We weren't able to split the current event range. That must mean
+ // that the event(s) in this range were important, and that we may
+ // have found the reason that the initial range we started subdivided
+ // is interesting. Assuming that, clear the fChecked bit on all
+ // entries on our stack, forcing us to retest them before splitting
+ // them.
+
+ {
+ omni_mutex_lock lock (fgMutex);
+
+ EmMinimizeLevelList::iterator iter = fgState.fLevels.begin ();
+ while (iter != fgState.fLevels.end ())
+ {
+ iter->fChecked = false;
+ ++iter;
+ }
+ }
+
+ // Pop the current range off and work with the next one.
+
+#if LOG_MINIMIZATION
+ EmMinimizeLevel level = fgState.fLevels.back ();
+
+ PRINTF ("EmMinimize::SplitAndStartAgain: too deep or narrow -- moving along.");
+ PRINTF (" begin: %ld", level.fBegin);
+ PRINTF (" end: %ld", level.fEnd);
+ PRINTF (" checked: %s", level.fChecked ? "TRUE" : "FALSE");
+#endif
+
+ EmMinimize::NextSubRange ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::DisableAndStartAgain
+// ---------------------------------------------------------------------------
+// Attempt to disable the current range and start again. This may fail if we
+// try to do something like disable a solitary pen-up event, in which case
+// we'll move to the NextSubRange.
+
+void EmMinimize::DisableAndStartAgain (void)
+{
+ long begin, end;
+ EmMinimize::CurrentRange (begin, end);
+
+ PRINTF ("EmMinimize::DisableAndStartAgain: disabling events %ld - %ld.", begin, end - 1);
+
+ // Don't try disabling pen-up events. If the pen-up event is preceded by
+ // one or more pen-down events, then EmEventPlayback won't let it be
+ // disabled. If the pen-up event is not preceded by a pen-down event,
+ // then EmEventPlayback will have already filtered it out. Either way, we
+ // don't get anything by trying to disable such an event and replaying the
+ // event stream all over again.
+
+ if (end - begin == 1)
+ {
+ EmRecordedEvent event;
+ EmEventPlayback::GetEvent (begin, event);
+
+ if (event.eType == kRecordedPenEvent && ::PrvIsPenUp (event.penEvent.coords))
+ {
+ PRINTF ("EmMinimize::DisableAndStartAgain: not disabling pen up event.");
+ NextSubRange ();
+ return;
+ }
+ }
+
+ // Turn off the events in the current sub-range.
+
+ EmEventPlayback::DisableEvents (begin, end);
+
+ // Start again.
+
+ EmMinimize::StartAgain ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::NextSubRange
+// ---------------------------------------------------------------------------
+// Pop an event range off of the stack and start working with the previous
+// range that's now on the top of the stack.
+
+void EmMinimize::NextSubRange (void)
+{
+ {
+ omni_mutex_lock lock (fgMutex);
+
+ PRINTF ("EmMinimize::NextSubRange: popping a level.");
+
+ EmAssert (fgState.fLevels.size () > 0);
+
+ fgState.fLevels.pop_back ();
+ }
+
+ // If there are no more ranges, we are done with this pass. Check the
+ // results to see if we'd like to make another pass.
+
+ if (fgState.fLevels.size () == 0)
+ {
+ EmMinimize::MinimizationPassComplete ();
+ return;
+ }
+
+ // Determine what to do with the range that's now at the top of the stack.
+ // Either we start testing it directly, or we see if we can skip that
+ // step and start splitting it. If we guess correctly, we can save a lot
+ // of time. If we assume we don't have to split this range first, then
+ // testing it in toto may show that we can get rid of it all right now.
+ // Otherwise, we'd end up splitting it down to the single event level
+ // before we discovered we didn't need any of the events. On the other
+ // hand, if we're fairly sure that we need to closely examine this range,
+ // we save time by not testing it in toto first, and proceed directly to
+ // splitting it.
+ //
+ // We maintain a Boolean flag that tells us whether or not to test the
+ // entire range before splitting or to split before testing each half. As
+ // well, we split any range that is larger than our hardcoded upper limit
+ // on event ranges.
+
+ EmMinimizeLevel currLevel = fgState.fLevels.back ();
+
+ if (currLevel.fChecked || ((currLevel.fEnd - currLevel.fBegin) > kMaxRange))
+ {
+ EmMinimize::SplitAndStartAgain ();
+ }
+ else
+ {
+ PRINTF ("EmMinimize::NextSubRange: disabling events %ld - %ld.",
+ currLevel.fBegin, currLevel.fEnd - 1);
+
+ // Attempt to disable the current range and start again. This may
+ // fail if we try to do something like disable a solitary pen-up
+ // event, in which case we'll move to the NextSubRange.
+
+ EmMinimize::DisableAndStartAgain ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::LoadInitialState
+// ---------------------------------------------------------------------------
+// Reload the current file so that we can start pelting it with events again.
+
+void EmMinimize::LoadInitialState (void)
+{
+ // Queue up a call to RealLoadInitialState.
+
+ gSession->ScheduleMinimizeLoadState ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::RealLoadInitialState
+// ---------------------------------------------------------------------------
+// Reload the current file so that we can start pelting it with events again.
+
+void EmMinimize::RealLoadInitialState (void)
+{
+ ErrCode result = errNone;
+
+ try
+ {
+ EmAssert (gSession);
+ gSession->Load (gSession->GetFile ());
+
+ PRINTF ("EmMinimize::RealLoadInitialState: Reloaded initial state.");
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // !!! Should probably do something on failure!
+
+// return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::LoadEvents
+// ---------------------------------------------------------------------------
+
+void EmMinimize::LoadEvents (void)
+{
+ EmAssert (gSession);
+
+ EmEventPlayback::LoadEvents (gSession->GetFile ());
+
+ PRINTF ("EmMinimize::LoadEvents: loaded %d events.", EmEventPlayback::GetNumEvents ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMinimize::FindFirstError
+// ---------------------------------------------------------------------------
+// Return the index of the first error event record. Return -1 if one could
+// not be found.
+
+long EmMinimize::FindFirstError (void)
+{
+ // The actual implementation for this function is over in EmEventPlayback
+ // for now. The current EmEventPlayback interface and implementation
+ // doesn't support the efficient retrieval of arbitrary events, so we put
+ // the whole FindFirstError implementation over there.
+
+ return EmEventPlayback::FindFirstError ();
+
+/*
+ EmRecordedEvent event;
+ long numEvents = EmEventPlayback::GetNumEvents ();
+
+ for (long ii = 0; ii < numEvents; ++ii)
+ {
+ EmEventPlayback::GetEvent (ii, event);
+
+ if (event.eType == kRecordedErrorEvent)
+ {
+ PRINTF ("EmMinimize::FindFirstError: found an error event.");
+ return ii;
+ }
+ }
+
+ PRINTF ("EmMinimize::FindFirstError: failed to find an error event.");
+ return -1;
+*/
+}
+
+void EmMinimize::GenerateStackCrawl (StringList& stackCrawl)
+{
+ // Capture the stack crawl.
+
+ EmStackFrameList stackFrames;
+ EmPalmOS::GenerateStackCrawl (stackFrames);
+
+ // Generate a full stack crawl.
+
+ ::StackCrawlStrings (stackFrames, stackCrawl);
+}
diff --git a/SrcShared/EmMinimize.h b/SrcShared/EmMinimize.h
new file mode 100644
index 0000000..44fe788
--- /dev/null
+++ b/SrcShared/EmMinimize.h
@@ -0,0 +1,133 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmMinimize_h
+#define EmMinimize_h
+
+#include "EmStructs.h" // GremlinEvent
+
+#include "omnithread.h" // omni_mutex
+
+#include <vector> // vector
+
+class SessionFile;
+
+class EmMinimize
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void Start (void);
+ static void Stop (void);
+ static void TurnOn (Bool);
+ static Bool IsOn (void);
+
+ static void NoErrorOccurred (void);
+ static void ErrorOccurred (void);
+
+ static uint32 GetPassNumber (void);
+ static uint32 GetElapsedTime (void);
+ static void GetCurrentRange (uint32&, uint32&);
+ static uint32 GetNumDiscardedEvents (void);
+ static uint32 GetNumInitialEvents (void);
+
+ private:
+ static void MinimizationPassComplete(void);
+ static void MinimizationComplete (void);
+ static void SaveMinimalEvents (void);
+ static void OutputEventsAsEnglish (void);
+ static Bool MakeAnotherPass (long oldNumEvents, long newNumEvents);
+ static void CurrentRange (long& begin, long& end);
+ static void InitialLevel (void);
+ static Bool SplitCurrentLevel (void);
+ static void StartAgain (void);
+ static void SplitAndStartAgain (void);
+ static void DisableAndStartAgain (void);
+ static void NextSubRange (void);
+ static void LoadInitialState (void);
+
+ public:
+ static void RealLoadInitialState (void);
+
+ private:
+ static void LoadEvents (void);
+ static long FindFirstError (void);
+ static void GenerateStackCrawl (StringList&);
+
+
+ private:
+ struct EmMinimizeLevel
+ {
+ long fBegin;
+ long fEnd;
+
+ // The following Boolean is used to indicate that the above range
+ // has already been checked in some fashion and that we know or
+ // strongly suspect that a needed event is in here somewhere. The
+ // practical effect of this is that when finish with one event
+ // range and are popping to this event range (as opposed to
+ // splitting the range we just finished and testing each of the
+ // split ranges), then should we split this new range, too, or
+ // should we test the whole thing first. Knowing whether or not
+ // to split a range that we're considering is important, since it
+ // reduces the overall number of passes we have to make.
+ //
+ // fChecked is managed as follows: When the initial event ranges
+ // are determined and pushed onto the fLevels stack, fChecked is
+ // clear. This means that each range is checked before
+ // determining to keep it or split it and check it further. If we
+ // test a range and find that we don't need it, we discard that
+ // range and don't consider it any further. If, however, we find
+ // that we need a range (because removing it cause the crash to go
+ // away), then we set fChecked for that range, subdivide it, and
+ // start checking the new sub-ranges. When we create the new
+ // sub-ranges, we copy the fChecked setting for the child ranges.
+ // For as long as we subdivide and retest subranges, we copy that
+ // bit to the new sub ranges.
+ //
+ // However, as soon as we get down to the single event level and
+ // determine that we need a particular event and can't subdivide
+ // any longer, we walk up the stack and clear all fChecked
+ // Booleans. The idea here is that if there was just a single
+ // event in the range that we needed to find and mark as
+ // important, then we just found it. We can no longer assume that
+ // any other events in the initial range that we've been
+ // subdividing are important, and so we need to clear the bit that
+ // means that there's an important event within them.
+
+ Bool fChecked;
+ };
+
+ typedef vector<EmMinimizeLevel> EmMinimizeLevelList;
+
+ struct EmMinimizeState
+ {
+ EmMinimizeLevelList fLevels;
+ };
+
+ static omni_mutex fgMutex;
+ static EmMinimizeState fgState;
+ static Bool fgIsOn;
+ static uint32 fgStartTime;
+ static long fgInitialNumberOfEvents;
+ static long fgDiscardedNumberOfEvents;
+ static long fgPassNumber;
+ static Bool fgPassEndedInError;
+ static StringList fgLastStackCrawl;
+};
+
+#endif // EmMinimize_h
diff --git a/SrcShared/EmPalmFunction.cpp b/SrcShared/EmPalmFunction.cpp
new file mode 100644
index 0000000..03d9b04
--- /dev/null
+++ b/SrcShared/EmPalmFunction.cpp
@@ -0,0 +1,2046 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPalmFunction.h"
+
+#include "EmBankROM.h" // EmBankROM::GetMemoryStart
+#include "EmLowMem.h" // LowMem_GetGlobal
+#include "EmMemory.h" // CEnableFullAccess, EmMem_strcpy, EmMem_memcmp
+#include "EmPalmHeap.h" // EmPalmHeap
+#include "EmPatchState.h" // EmPatchState::OSMajorVersion
+#include "Miscellaneous.h" // FindFunctionName
+#include "Platform.h" // Platform::GetString
+#include "Strings.r.h" // kStr_INetLibTrapBase
+
+#include <ctype.h> // isalnum, toupper
+
+const UInt16 kMagicRefNum = 0x666; // See comments in HtalLibSendReply.
+
+const uint16 kOpcode_ADD = 0x0697; // ADD.L X, (A7)
+const uint16 kOpcode_LINK = 0x4E50;
+const uint16 kOpcode_RTE = 0x4E73;
+const uint16 kOpcode_RTD = 0x4E74;
+const uint16 kOpcode_RTS = 0x4E75;
+const uint16 kOpcode_JMP = 0x4ED0;
+
+const uint16 kOpcode_CMPW = 0xB47C; // CMP.W #$xxxx,D2
+const uint16 kOpcode_ADDW = 0xD442; // ADD.W D2,D2
+const uint32 kOpcode_JMPPC = 0x4EFB2002; // JMP *+$0004(D2.W)
+const uint16 kOpcode_JMPREL = 0x4EFA; // JMP *+$xxxx
+const uint16 kOpcode_MOVEL = 0x2038; // MOVE.L $xxxxxxxx,D0
+
+// This table should match up with gResourceBases in ErrorHandling.cpp.
+static const char* gPalmOSLibraries [] =
+{
+ "INet.lib",
+ "IrDA Library", // Also includes Exchange Lib
+ "Security.lib",
+ "Web.lib",
+// serIrCommLibNameP, // ???SerIrCommLib.h doesn't declare the functions as SYSTRAPs!
+ "Debugger Comm",
+ "IrSerial Library",
+ "Net.lib",
+ "PADHTAL.lib",
+ "Rail I/O Library",
+ "RMP NetPlugIn.lib",
+ "Serial Lib68681",
+ "Serial Library",
+ "TCPHTAL.lib",
+
+ NULL
+};
+
+
+const uint8 kCerticomMemCpyPattern [] =
+{
+ 0x20, 0x6F, 0x00, 0x04, // 080B3CE2 MOVEA.L $0004(A7),A0 | 206F 0004
+ 0x22, 0x6F, 0x00, 0x08, // 080B3CE6 MOVEA.L $0008(A7),A1 | 226F 0008
+ 0x30, 0x2F, 0x00, 0x0C, // 080B3CEA MOVE.W $000C(A7),D0 | 302F 000C
+ 0x60, 0x02, // 080B3CEE BRA.S *+$0004 ; 080B3CF2 | 6002
+ 0x10, 0xD9, // 080B3CF0 MOVE.B (A1)+,(A0)+ | 10D9
+ 0x51, 0xC8, 0xFF, 0xFC, // 080B3CF2 DBF D0,*-$0002 ; 080B3CF0 | 51C8 FFFC
+ 0x4E, 0x75 // 080B3CF6 RTS | 4E75
+};
+
+
+class EmFunctionRange
+{
+ public:
+ EmFunctionRange (const char* functionName);
+
+ Bool InRange (emuptr = gCPU->GetPC ());
+ void Reset (void);
+
+ Bool HasRange (void) { return fBegin != EmMemNULL; }
+
+ private:
+ void GetRange (emuptr addr);
+
+ const char* fName;
+ emuptr fBegin;
+ emuptr fEnd;
+
+ EmFunctionRange* fNext;
+ static EmFunctionRange* fgRoot;
+};
+
+EmFunctionRange* EmFunctionRange::fgRoot;
+
+// Define a bunch of EmFunctionRange objects to search for and
+// cache function ranges.
+
+#define DEFINE_OBJECT(fn_name) \
+ static EmFunctionRange g##fn_name (#fn_name);
+
+FOR_EACH_FUNCTION(DEFINE_OBJECT)
+
+// Define all the InFoo functions declared in EmPalmFunction.h.
+
+#define DEFINE_FUNCTION(fn_name) \
+ Bool In##fn_name (emuptr addr) { return g##fn_name.InRange (addr); }
+
+FOR_EACH_FUNCTION(DEFINE_FUNCTION)
+
+
+static string PrvGetShortName (const char*, int len);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFunctionRangeInit
+ *
+ * DESCRIPTION: Reset all our objects that track where certain Palm
+ * functions exist in memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmFunctionInit (void)
+{
+#define RESET_OBJECT(fn_name) \
+ g##fn_name.Reset ();
+
+FOR_EACH_FUNCTION(RESET_OBJECT)
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFunctionRange::EmFunctionRange
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: functionName - name of function to track. Storage is
+ * not owned by this object, so clients should make
+ * sure it exists for the life of this object. The
+ * function name is typically provided as a string
+ * constant in global space.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmFunctionRange::EmFunctionRange (const char* functionName) :
+ fName (functionName),
+ fBegin (EmMemNULL),
+ fEnd (EmMemNULL),
+ fNext (fgRoot)
+{
+ fgRoot = this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFunctionRange::InRange
+ *
+ * DESCRIPTION: Determine whether or not the given address is within
+ * the function managed by this object.
+ *
+ * PARAMETERS: addr - address to test.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmFunctionRange::InRange (emuptr addr)
+{
+ // It's not in our range if it's in someone else's.
+ // This is an optimization.
+
+ static Bool walkingChain;
+
+ if (!walkingChain)
+ {
+ walkingChain = true;
+
+ EmFunctionRange* range = fgRoot;
+ while (range)
+ {
+ if (range != this && range->HasRange () && range->InRange (addr))
+ {
+ walkingChain = false;
+ return false;
+ }
+
+ range = range->fNext;
+ }
+
+ walkingChain = false;
+ }
+
+ // If we haven't determine the range of the function for which we're
+ // responsible, see if given address is in that function. If so,
+ // remember the range of that function.
+
+ if (!this->HasRange ())
+ {
+ this->GetRange (addr);
+ }
+
+ // If we know the range of the function for which we are responsible,
+ // test the address against that range.
+
+ if (this->HasRange () && (addr >= fBegin) && (addr < fEnd))
+ {
+ // We may not want to cache the range if it's in RAM.
+
+ EmMemGetFunc func = EmMemGetBank(addr).lget;
+ if ((func != &EmBankROM::GetLong) && (func != &EmBankFlash::GetLong))
+ {
+ this->Reset ();
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFunctionRange::Reset
+ *
+ * DESCRIPTION: If we've determined and remembered where the managed
+ * function exists, forget that information. This method
+ * is typically called so that this object can be reused
+ * after a new ROM image has been loaded.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmFunctionRange::Reset (void)
+{
+ fBegin = EmMemNULL;
+ fEnd = EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFunctionRange::GetRange
+ *
+ * DESCRIPTION: Find the name of the function containing the given
+ * address. If it's our managed function, remember the
+ * range of the function.
+ *
+ * PARAMETERS: addr - probe address.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmFunctionRange::GetRange (emuptr addr)
+{
+ char name[80];
+ emuptr startAddr;
+ emuptr endAddr;
+
+ ::FindFunctionName (addr, name, &startAddr, &endAddr, 80);
+
+ string shortName = ::PrvGetShortName (fName, 8);
+
+ // See if the function has the name as specified in fName.
+
+ if (strncmp (name, fName, 79) == 0)
+ {
+ fBegin = startAddr;
+ fEnd = endAddr;
+ }
+
+ // If not, see if the function name is the same as the "fixed 8"
+ // format of the Macsbug name.
+
+ else if (strcmp (name, shortName.c_str ()) == 0)
+ {
+ fBegin = startAddr;
+ fEnd = endAddr;
+ }
+
+ // Check to see if it looks like this is the function the Certicom
+ // Encryption library uses to copy "random" data. There's no
+ // Macsbug name, so we have to go with some other signature.
+
+ else if (strcmp ("_CerticomMemCpy", fName) == 0)
+ {
+ if (endAddr - startAddr != 0x16)
+ return;
+
+ if (EmMem_memcmp (startAddr, (void*) kCerticomMemCpyPattern, endAddr - startAddr) != 0)
+ return;
+
+ fBegin = startAddr;
+ fEnd = endAddr;
+ }
+}
+
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvProscribedFunction
+ *
+ * DESCRIPTION: Return whether or not the user should be warned about
+ * calling this function.
+ *
+ * PARAMETERS: context - information about the system call context.
+ *
+ * RETURNED: True if this function is proscribed and should not be
+ * called; false if it's OK for applications to call it.
+ *
+ ***********************************************************************/
+// *****************************************************************
+// * New Serial Manager trap selectors
+// *****************************************************************
+
+// The numbering of these #defines *MUST* match the order in SerialMgr.c
+
+#define sysSerialInstall 0
+#define sysSerialOpen 1
+#define sysSerialOpenBkgnd 2
+#define sysSerialClose 3
+#define sysSerialSleep 4
+#define sysSerialWake 5
+#define sysSerialGetDeviceCount 6
+#define sysSerialGetDeviceInfo 7
+#define sysSerialGetStatus 8
+#define sysSerialClearErr 9
+#define sysSerialControl 10
+#define sysSerialSend 11
+#define sysSerialSendWait 12
+#define sysSerialSendCheck 13
+#define sysSerialSendFlush 14
+#define sysSerialReceive 15
+#define sysSerialReceiveWait 16
+#define sysSerialReceiveCheck 17
+#define sysSerialReceiveFlush 18
+#define sysSerialSetRcvBuffer 19
+#define sysSerialRcvWindowOpen 20
+#define sysSerialRcvWindowClose 21
+#define sysSerialSetWakeupHandler 22
+#define sysSerialPrimeWakeupHandler 23
+#define sysSerialOpenV4 24
+#define sysSerialOpenBkgndV4 25
+#define sysSerialCustomControl 26
+
+
+// Selectors for routines found in the international manager. The order
+// of these selectors MUST match the jump table in IntlDispatch.c.
+
+#define intlIntlInit 0
+#define intlTxtByteAttr 1
+#define intlTxtCharAttr 2
+#define intlTxtCharXAttr 3
+#define intlTxtCharSize 4
+#define intlTxtGetPreviousChar 5
+#define intlTxtGetNextChar 6
+#define intlTxtGetChar 7
+#define intlTxtSetNextChar 8
+#define intlTxtCharBounds 9
+#define intlTxtPrepFindString 10
+#define intlTxtFindString 11
+#define intlTxtReplaceStr 12
+#define intlTxtWordBounds 13
+#define intlTxtCharEncoding 14
+#define intlTxtStrEncoding 15
+#define intlTxtEncodingName 16
+#define intlTxtMaxEncoding 17
+#define intlTxtTransliterate 18
+#define intlTxtCharIsValid 19
+#define intlTxtCompare 20
+#define intlTxtCaselessCompare 21
+#define intlTxtCharWidth 22
+#define intlTxtGetTruncationOffset 23
+#define intlIntlGetRoutineAddress 24
+#define intlIntlHandleEvent 25 // New for Palm OS 3.5
+#define intlTxtParamString 26
+#define intlTxtConvertEncodingV35 27 // Patched for Palm OS 3.5.2
+#define intlTxtConvertEncoding 28 // New for Palm OS 4.0
+#define intlIntlSetRoutineAddress 29
+#define intlTxtGetWordWrapOffset 30
+#define intlTxtNameToEncoding 31
+#define intlIntlStrictChecks 32
+
+
+// Selectors used for getting to the right Overlay Manager routine via
+// the OmDispatch trap.
+
+#define omInit 0
+#define omOpenOverlayDatabase 1
+#define omLocaleToOverlayDBName 2
+#define omOverlayDBNameToLocale 3
+#define omGetCurrentLocale 4
+#define omGetIndexedLocale 5
+#define omGetSystemLocale 6
+#define omSetSystemLocale 7
+#define omGetRoutineAddress 8
+#define omGetNextSystemLocale 9
+
+
+struct EmProscribedFunction
+{
+ uint16 fTrapWord;
+ int fReason;
+};
+
+
+static const EmProscribedFunction kProscribedFunctionTrapWords [] =
+{
+ // Entries marked with "//*" are supported in PACE because Palm
+ // apps, test apps, or Palm Debugger needs them, but developers
+ // should probably still be warned that they should not be using
+ // them. Additionally, the Fpl functions are marked this way
+ // because many applications call them, but we'd like to warn
+ // them to use the Flp functions.
+
+/*
+ 6 Appendix B - Unsupported Palm OS APIs
+
+ The following is a list of Palm OS traps that are not supported
+ by the Timulator. The list is broken into a number of different
+ groups (which more or less explains why the trap was not implemented).
+
+ 6.1.1 Documented 'System Use Only' Traps
+
+ These traps are documented as "System Use Only" in the "Palm OS
+ Reference Manual".
+*/
+
+ { sysTrapAlmAlarmCallback, kProscribedDocumentedSystemUseOnly },
+ { sysTrapAlmCancelAll, kProscribedDocumentedSystemUseOnly },
+ { sysTrapAlmDisplayAlarm, kProscribedDocumentedSystemUseOnly },
+ { sysTrapAlmEnableNotification, kProscribedDocumentedSystemUseOnly }, //* supported
+ { sysTrapAlmInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapAlmTimeChange, kProscribedDocumentedSystemUseOnly },
+ { sysTrapDmInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapEvtDequeueKeyEvent, kProscribedDocumentedSystemUseOnly },
+ { sysTrapEvtGetSysEvent, kProscribedDocumentedSystemUseOnly }, //* pseudo supported
+ { sysTrapEvtInitialize, kProscribedDocumentedSystemUseOnly },
+ { sysTrapEvtSetKeyQueuePtr, kProscribedDocumentedSystemUseOnly },
+ { sysTrapEvtSetPenQueuePtr, kProscribedDocumentedSystemUseOnly },
+ { sysTrapEvtSysInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapExgInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapFrmAddSpaceForObject, kProscribedDocumentedSystemUseOnly },
+ { sysTrapFtrInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapGrfFree, kProscribedDocumentedSystemUseOnly },
+ { sysTrapGrfInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapInsPtCheckBlink, kProscribedDocumentedSystemUseOnly },
+ { sysTrapInsPtInitialize, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemCardFormat, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemHandleFlags, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemHandleOwner, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemHandleResetLock, kProscribedDocumentedSystemUseOnly }, //* supported for release ROMs
+ { sysTrapMemHeapFreeByOwnerID, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemHeapInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemInitHeapTable, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemKernelInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemPtrFlags, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemPtrOwner, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemPtrResetLock, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemStoreInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapMemStoreSetInfo, kProscribedDocumentedSystemUseOnly },
+ { sysTrapPenClose, kProscribedDocumentedSystemUseOnly },
+ { sysTrapPenGetRawPen, kProscribedDocumentedSystemUseOnly },
+ { sysTrapPenOpen, kProscribedDocumentedSystemUseOnly },
+ { sysTrapPenRawToScreen, kProscribedDocumentedSystemUseOnly },
+ { sysTrapPenScreenToRaw, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrCompressScanLine, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrCopyRectangle, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrDeCompressScanLine, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrDrawChars, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrDrawNotify, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrLineRoutine, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrRectangleRoutine, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrScreenInfo, kProscribedDocumentedSystemUseOnly },
+ { sysTrapScrSendUpdateArea, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSlkProcessRPC, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSlkSysPktDefaultResponse, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSndInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysBatteryDialog, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysColdBoot, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysDoze, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysLaunchConsole, kProscribedDocumentedSystemUseOnly }, //* supported
+ { sysTrapSysNewOwnerID, kProscribedDocumentedSystemUseOnly },
+// { sysTrapSysReserved10Trap1, kProscribedDocumentedSystemUseOnly },
+// { sysTrapSysReserved31Trap1, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysSemaphoreSet, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysUILaunch, kProscribedDocumentedSystemUseOnly },
+ { sysTrapSysWantEvent, kProscribedDocumentedSystemUseOnly },
+ { sysTrapTimInit, kProscribedDocumentedSystemUseOnly },
+ { sysTrapUIInitialize, kProscribedDocumentedSystemUseOnly },
+ { sysTrapUIReset, kProscribedDocumentedSystemUseOnly },
+ { sysTrapWinAddWindow, kProscribedDocumentedSystemUseOnly },
+ { sysTrapWinRemoveWindow, kProscribedDocumentedSystemUseOnly },
+
+/*
+ 6.1.2 Undocumented 'System Use Only' or 'HAL Use Only' Traps
+
+ These traps are routines in the HAL, documented in headers to be
+ called by Palm OS only, or I have spoken with the authors of those
+ traps who identified them as internal traps.
+*/
+
+ { sysTrapAttnAllowClose, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnDoEmergencySpecialEffects, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapAttnEffectOfEvent, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapAttnEnableNotification, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnHandleEvent, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapAttnIndicatorAllow, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnIndicatorAllowed, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnIndicatorCheckBlink, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapAttnIndicatorGetBlinkPattern, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnIndicatorSetBlinkPattern, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapAttnIndicatorTicksTillNextBlink, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapAttnInitialize, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltCopyRectangle, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltDrawChars, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltFindIndexes, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltGetPixel, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltLineRoutine, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltPaintPixel, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltPaintPixels, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltRectangleRoutine, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltRoundedRectangle, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapBltRoundedRectangleFill, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDayHandleEvent, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgControl, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvClose, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvControl, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvOpen, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvReadChar, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvStatus, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapDbgSerDrvWriteChar, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapFlashInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapFntPrvGetFontList, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrBacklightV33, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrBattery, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrBatteryLevel, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrCalcDynamicHeapSize, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrCursorV33, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrCustom, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDebuggerEnter, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDebuggerExit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDebugSelect, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplayDoze, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplayDrawBootScreen, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplayInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplayPalette, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplaySleep, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDisplayWake, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDockSignals, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrDockStatus, kProscribedUndocumentedSystemUseOnly }, //* supported
+ { sysTrapHwrDoze, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrFlashWrite, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrGetRAMMapping, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrGetSilkscreenID, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIdentifyFeatures, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrInterruptsInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ1Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ2Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ3Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ4Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ5Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrIRQ6Handler, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrLCDBaseAddrV33, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrLCDContrastV33, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrLCDGetDepthV33, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrModelInitStage2, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrModelInitStage3, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrModelSpecificInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrNVPrefGet, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrNVPrefSet, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrPluggedIn, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrPostDebugInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrPreDebugInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrResetNMI, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrResetPWM, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrSetCPUDutyCycle, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrSetSystemClock, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrSleep, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrSoundOff, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrSoundOn, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrTimerInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapHwrWake, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapKeyBootKeys, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapKeyHandleInterrupt, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapKeyInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapMemHeapPtr, kProscribedUndocumentedSystemUseOnly }, //* supported (PalmDebugger)
+ { sysTrapMemStoreSearch, kProscribedUndocumentedSystemUseOnly },
+// { sysTrapOEMDispatch2, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapPalmPrivate3, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrCompress, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrDecompress, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrGetColortable, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrGetGrayPat, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrPalette, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrScreenInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrScreenLock, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrScreenUnlock, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapScrUpdateScreenBitmap, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSndInterruptSmfIrregardless, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSndPlaySmfIrregardless, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSndPlaySmfResourceIrregardless, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSysFatalAlertInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSysKernelClockTick, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSysNotifyBroadcastFromInterrupt, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSysNotifyInit, kProscribedUndocumentedSystemUseOnly },
+// { sysTrapSysReserved30Trap1, kProscribedUndocumentedSystemUseOnly },
+// { sysTrapSysReserved30Trap2, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapSysUnimplemented, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapTimGetAlarm, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapTimSetAlarm, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapUIColorInit, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapWinGetFirstWindow, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapWinMoveWindowAddr, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapWinPrvInitCanvas, kProscribedUndocumentedSystemUseOnly },
+ { sysTrapWinScreenInit, kProscribedUndocumentedSystemUseOnly },
+
+/*
+ 6.1.3 Kernel Traps
+
+ These traps are not implemented because 68K applications do not have
+ access to the kernel APIs.
+*/
+
+ { sysTrapSysEvGroupCreate, kProscribedKernelUseOnly },
+ { sysTrapSysEvGroupRead, kProscribedKernelUseOnly },
+ { sysTrapSysEvGroupSignal, kProscribedKernelUseOnly },
+ { sysTrapSysEvGroupWait, kProscribedKernelUseOnly },
+ { sysTrapSysKernelInfo, kProscribedKernelUseOnly },
+ { sysTrapSysMailboxCreate, kProscribedKernelUseOnly },
+ { sysTrapSysMailboxDelete, kProscribedKernelUseOnly },
+ { sysTrapSysMailboxFlush, kProscribedKernelUseOnly },
+ { sysTrapSysMailboxSend, kProscribedKernelUseOnly },
+ { sysTrapSysMailboxWait, kProscribedKernelUseOnly },
+ { sysTrapSysResSemaphoreCreate, kProscribedKernelUseOnly },
+ { sysTrapSysResSemaphoreDelete, kProscribedKernelUseOnly },
+ { sysTrapSysResSemaphoreRelease, kProscribedKernelUseOnly },
+ { sysTrapSysResSemaphoreReserve, kProscribedKernelUseOnly },
+ { sysTrapSysSemaphoreCreate, kProscribedKernelUseOnly },
+ { sysTrapSysSemaphoreDelete, kProscribedKernelUseOnly },
+ { sysTrapSysSemaphoreSignal, kProscribedKernelUseOnly },
+ { sysTrapSysSemaphoreWait, kProscribedKernelUseOnly },
+ { sysTrapSysTaskCreate, kProscribedKernelUseOnly },
+ { sysTrapSysTaskDelete, kProscribedKernelUseOnly },
+ { sysTrapSysTaskID, kProscribedKernelUseOnly },
+ { sysTrapSysTaskResume, kProscribedKernelUseOnly },
+ { sysTrapSysTaskSetTermProc, kProscribedKernelUseOnly },
+ { sysTrapSysTaskSuspend, kProscribedKernelUseOnly },
+ { sysTrapSysTaskSwitching, kProscribedKernelUseOnly },
+ { sysTrapSysTaskTrigger, kProscribedKernelUseOnly },
+ { sysTrapSysTaskUserInfoPtr, kProscribedKernelUseOnly },
+ { sysTrapSysTaskWait, kProscribedKernelUseOnly },
+ { sysTrapSysTaskWaitClr, kProscribedKernelUseOnly },
+ { sysTrapSysTaskWake, kProscribedKernelUseOnly },
+ { sysTrapSysTimerCreate, kProscribedKernelUseOnly },
+ { sysTrapSysTimerDelete, kProscribedKernelUseOnly },
+ { sysTrapSysTimerRead, kProscribedKernelUseOnly },
+ { sysTrapSysTimerWrite, kProscribedKernelUseOnly },
+ { sysTrapSysTranslateKernelErr, kProscribedKernelUseOnly },
+
+/*
+ 6.1.4 Obsolete Traps
+
+ These traps are not implemented because they are obsolete Palm OS
+ 1.0 traps (or an esoteric obsolete trap such as WiCmdV32).
+*/
+
+ { sysTrapFplAdd, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplAToF, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplBase10Info, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplDiv, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplFloatToLong, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplFloatToULong, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplFToA, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplLongToFloat, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplMul, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapFplSub, kProscribedObsolete }, //* supported (release ROM only)
+ { sysTrapWiCmdV32, kProscribedObsolete },
+
+/*
+ 6.1.5 Ghost Traps
+
+ These traps were never implemented in Palm OS (although they appear
+ in CoreTraps.h), but they are listed for completeness. One of the
+ traps in this group, MenuEraseMenu, was implemented but should be
+ unknown to developers, as it does not appear in any public header file.
+*/
+
+ { sysTrapClipboardCheckIfItemExist, kProscribedGhost },
+ { sysTrapCtlValidatePointer, kProscribedGhost },
+ { sysTrapFrmSetCategoryTrigger, kProscribedGhost },
+ { sysTrapFrmSetLabel, kProscribedGhost },
+ { sysTrapMenuEraseMenu, kProscribedGhost },
+ { sysTrapSysUICleanup, kProscribedGhost },
+ { sysTrapWinDrawArc, kProscribedGhost },
+ { sysTrapWinDrawPolygon, kProscribedGhost },
+ { sysTrapWinEraseArc, kProscribedGhost },
+ { sysTrapWinErasePolygon, kProscribedGhost },
+ { sysTrapWinFillArc, kProscribedGhost },
+ { sysTrapWinFillPolygon, kProscribedGhost },
+ { sysTrapWinInvertArc, kProscribedGhost },
+ { sysTrapWinInvertPolygon, kProscribedGhost },
+ { sysTrapWinPaintArc, kProscribedGhost },
+ { sysTrapWinPaintPolygon, kProscribedGhost },
+
+/*
+ 6.1.6 Unimplemented NOP Traps
+
+ These traps should not be called by applications. Some third-party
+ applications call these traps and it is safer to treat them as NOPs
+ for backwards compatibility.
+*/
+
+ { sysTrapFplFree, kProscribedSystemUseOnlyAnyway }, //* supported (release ROM only)
+ { sysTrapFplInit, kProscribedSystemUseOnlyAnyway }, //* supported (release ROM only)
+ { sysTrapHwrTimerSleep, kProscribedSystemUseOnlyAnyway },
+ { sysTrapHwrTimerWake, kProscribedSystemUseOnlyAnyway },
+ { sysTrapPenSleep, kProscribedSystemUseOnlyAnyway },
+ { sysTrapPenWake, kProscribedSystemUseOnlyAnyway },
+ { sysTrapSerReceiveISP, kProscribedSystemUseOnlyAnyway },
+// { sysTrapSrmSleep, kProscribedSystemUseOnlyAnyway }, // sysTrapSerialDispatch
+// { sysTrapSrmWake, kProscribedSystemUseOnlyAnyway }, // sysTrapSerialDispatch
+ { sysTrapSysDisableInts, kProscribedSystemUseOnlyAnyway },
+ { sysTrapSysRestoreStatus, kProscribedSystemUseOnlyAnyway },
+ { sysTrapTimHandleInterrupt, kProscribedSystemUseOnlyAnyway },
+ { sysTrapTimSleep, kProscribedSystemUseOnlyAnyway },
+ { sysTrapTimWake, kProscribedSystemUseOnlyAnyway },
+ { sysTrapWinDisableWindow, kProscribedSystemUseOnlyAnyway },
+ { sysTrapWinEnableWindow, kProscribedSystemUseOnlyAnyway },
+ { sysTrapWinInitializeWindow, kProscribedSystemUseOnlyAnyway },
+
+/*
+ 6.1.7 Unimplemented Rare Traps
+
+ These traps all seem like traps that are only used internally by
+ Palm OS or by serial drivers or by OEM extensions, etc. In other
+ words, these are traps that an application would not use.
+*/
+
+ { sysTrapConGetS, kProscribedRare },
+ { sysTrapConPutS, kProscribedRare },
+ { sysTrapDayDrawDays, kProscribedRare },
+ { sysTrapDayDrawDaySelector, kProscribedRare },
+ { sysTrapDbgCommSettings, kProscribedRare },
+ { sysTrapDbgGetMessage, kProscribedRare },
+// { sysTrapDlkControl, kProscribedRare }, //* supports sysAppLaunchCmdHandleSyncCallApp
+ { sysTrapDlkDispatchRequest, kProscribedRare }, //* sort of, returns dlkErrNoSession err
+ { sysTrapDlkStartServer, kProscribedRare }, //* sort of, returns dlkErrNoSession err
+ { sysTrapDmMoveOpenDBContext, kProscribedRare },
+ { sysTrapDmOpenDBWithLocale, kProscribedRare },
+ { sysTrapFlashCompress, kProscribedRare },
+ { sysTrapFlashErase, kProscribedRare },
+ { sysTrapFlashProgram, kProscribedRare },
+ { sysTrapMemGetRomNVParams, kProscribedRare },
+ { sysTrapMemNVParams, kProscribedRare },
+ { sysTrapResLoadForm, kProscribedRare },
+ { sysTrapSlkSetSocketListener, kProscribedRare },
+ { sysTrapSysNotifyDatabaseAdded, kProscribedRare },
+ { sysTrapSysNotifyDatabaseRemoved, kProscribedRare },
+ { sysTrapSysSetTrapAddress, kProscribedRare }
+};
+
+static Bool gProscribedTrapInitialized;
+static Bool gProscribedTrap[sysNumTraps];
+
+Bool ProscribedFunction (const SystemCallContext& context)
+{
+ // Build up our table that allows this function to operate quickly.
+ // We turn a table of the system function dispatch numbers we want
+ // to warn about into a sparse array of booleans, where the index
+ // into the table is the trap index number, and each entry says
+ // whether or not to warn about the call.
+
+ if (!gProscribedTrapInitialized)
+ {
+ gProscribedTrapInitialized = true;
+
+ for (size_t ii = 0; ii < countof (kProscribedFunctionTrapWords); ++ii)
+ {
+ gProscribedTrap[::SysTrapIndex (kProscribedFunctionTrapWords[ii].fTrapWord)] = true;
+ }
+ }
+
+ // Handle system functions (as opposed to library functions).
+
+ if (::IsSystemTrap (context.fTrapWord))
+ {
+ // If this trap number is not on our list, let it pass.
+
+ if (gProscribedTrap[context.fTrapIndex])
+ return true;
+
+ // Some system functions are sub-dispatched with a sub-dispatch
+ // number in register D2. We can find this number in context.fExtra.
+ // Look at the combination to see if they represent proscribed
+ // functions.
+
+ if (context.fTrapWord == sysTrapSerialDispatch)
+ {
+ if (context.fExtra == sysSerialSleep ||
+ context.fExtra == sysSerialWake)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Looks like an OK function, so don't warn.
+
+ return false;
+}
+
+int GetProscribedReason (const SystemCallContext& context)
+{
+ // Handle system functions (as opposed to library functions).
+
+ if (::IsSystemTrap (context.fTrapWord))
+ {
+ // If this trap number is on our list, return the reason.
+
+ for (size_t ii = 0; ii < countof (kProscribedFunctionTrapWords); ++ii)
+ {
+ if (kProscribedFunctionTrapWords[ii].fTrapWord == context.fTrapWord)
+ {
+ return kProscribedFunctionTrapWords[ii].fReason;
+ }
+ }
+
+ // Some system functions are sub-dispatched with a sub-dispatch
+ // number in register D2. We can find this number in context.fExtra.
+ // Look at the combination to see if they represent proscribed
+ // functions.
+
+ if (context.fTrapWord == sysTrapSerialDispatch)
+ {
+ if (context.fExtra == sysSerialSleep ||
+ context.fExtra == sysSerialWake)
+ {
+ return kProscribedSystemUseOnlyAnyway;
+ }
+ }
+ }
+
+ EmAssert (false);
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetFunctionAddress
+ *
+ * DESCRIPTION: Determines the address of a system function,
+ *
+ * PARAMETERS: trapWord - the dispatch number used to invoke the
+ * function(the number after the TRAP $F opocde)
+ *
+ * extra - an optional extra parameter. This parameter can
+ * be something like a library reference number, or a
+ * register to be used in a sub-dispatcher.
+ *
+ * digDeep - a boolean saying how hard we should look for
+ * the function address. If false, we just return the
+ * address generated by the ROM TrapDispatcher
+ * function. Otherwise, for certain special ROM
+ * routines (like the Floating Point Manager entry
+ * point), we look deeper.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetFunctionAddress (uint16 trapWord, uint32 extra, Bool digDeep)
+{
+ // Ensure that it's in canonical format.
+
+ trapWord = ::SysTrapIndex (trapWord) | sysTrapBase;
+
+ // If it's a regular system function (0xA000-0xA7FFF), handle it.
+
+ if (::IsSystemTrap (trapWord))
+ return ::GetSysFunctionAddress (trapWord, extra, digDeep);
+
+ // Assume it's a library function call.
+
+ return ::GetLibFunctionAddress (trapWord, (UInt16) extra, digDeep);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetLibFunctionAddress
+ *
+ * DESCRIPTION: Determines the address of a library function,
+ *
+ * PARAMETERS: trapWord - the dispatch number used to invoke the
+ * function(the number after the TRAP $F opocde)
+ *
+ * extra - an optional extra parameter. This parameter can
+ * be something like a library reference number, or a
+ * register to be used in a sub-dispatcher.
+ *
+ * digDeep - a boolean saying how hard we should look for
+ * the function address. If false, we just return the
+ * address generated by the ROM TrapDispatcher
+ * function. Otherwise, for certain special ROM
+ * routines (like the Floating Point Manager entry
+ * point), we look deeper.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetLibFunctionAddress (uint16 trapWord, UInt16 refNum, Bool digDeep)
+{
+ if (refNum == sysInvalidRefNum || refNum == 0)
+ throw EmInvalidRefNumException (0);
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ /*
+ The System Library Table (sysLibTableP) is an array of
+ sysLibTableEntries entries. Each entry has the following
+ format:
+
+ Ptr* dispatchTblP; // pointer to library dispatch table
+ void* globalsP; // Library globals
+ LocalID dbID; // database id of the library
+ VoidPtr codeRscH; // library code resource handle for RAM-based libraries
+
+ The latter two fields are present only in Palm OS 2.0 and
+ later. So our first steps are to (a) get the pointer to
+ the array, (b) make sure that the index into the array (the
+ refNum passed as the first parameter to all library calls)
+ is within range, (c) get a pointer to the right entry,
+ taking into account the Palm OS version, and (d) getting the
+ dispatchTblP field.
+
+ The "library dispatch table" is an array of 16-bit offsets. The
+ values are all relative to the beginning of the table (dispatchTblP).
+ The first entry in the array corresponds to the library name. All
+ subsequent entries are offsets to the various library functions,
+ starting with the required four: sysLibTrapOpen, sysLibTrapClose,
+ sysLibTrapSleep, and sysLibTrapWake.
+ */
+
+ uint32 sysLibTableP = EmLowMem_GetGlobal (sysLibTableP);
+ UInt16 sysLibTableEntries = EmLowMem_GetGlobal (sysLibTableEntries);
+
+ if (sysLibTableP == EmMemNULL)
+ {
+ // !!! No library table!
+ EmAssert (false);
+ return EmMemNULL;
+ }
+
+ if (refNum >= sysLibTableEntries)
+ {
+ // See comments in HtalLibHeadpatch::HtalLibSendReply.
+ if (refNum == kMagicRefNum)
+ {
+ return 1;
+ }
+
+ // RefNum out of range.
+
+ throw EmInvalidRefNumException (0, sysLibTableEntries);
+ }
+
+ emuptr libEntry;
+ emuptr dispatchTblP;
+
+ if (EmPatchState::OSMajorVersion () > 1)
+ {
+ libEntry = sysLibTableP + refNum * sizeof (SysLibTblEntryType);
+ dispatchTblP = EmMemGet32 (libEntry + offsetof (SysLibTblEntryType, dispatchTblP));
+ }
+ else
+ {
+ libEntry = sysLibTableP + refNum * sizeof (SysLibTblEntryTypeV10);
+ dispatchTblP = EmMemGet32 (libEntry + offsetof (SysLibTblEntryTypeV10, dispatchTblP));
+ }
+
+ // Validate the dispatch number. See if the library is one that
+ // we know about. If so, compare the dispatch number against
+ // the list of known dispatch number limits.
+
+ // The first entry in the table is always the offset from the
+ // start of the table to the library name. Use this information
+ // get the library name.
+
+ int16 offset = EmMemGet16 (dispatchTblP + ::LibTrapIndex (sysLibTrapName) * 2);
+ emuptr libNameP = dispatchTblP + offset;
+ char libName[256];
+ EmMem_strcpy (libName, libNameP);
+
+ // Iterate over our list of Palm OS-supplied libraries to see
+ // if this is one of them. If so, the library is known to follow
+ // a format that allows us to determine the size of the table.
+
+ const char** knownLibNameP = gPalmOSLibraries;
+
+ while (*knownLibNameP)
+ {
+ if (strcmp (*knownLibNameP, libName) != 0)
+ {
+ knownLibNameP++;
+ continue;
+ }
+
+ // OK, it's one of our libraries. Now get the *second*
+ // entry in the table. This is the offset from the start
+ // of the table to the entry point for the standard
+ // "library open" function. All Palm OS libraries follow
+ // the convention where this offset points to a JMP
+ // instruction immediately following the function table.
+ // We can use this information to calculate the size of
+ // the table.
+
+ offset = EmMemGet16 (dispatchTblP + LibTrapIndex (sysLibTrapOpen) * 2);
+
+ if (::LibTrapIndex (trapWord) < (offset / 2))
+ {
+ // It's a known library, and the offset is in range,
+ // so break out of here so that we can get one with
+ // actually calling the function.
+ break;
+ }
+
+ // It's a known library, but the offset is out of range,
+ // so report a problem.
+
+ throw EmUnimplementedFunctionException (knownLibNameP - gPalmOSLibraries);
+ }
+
+ // Either we didn't know about that library, or we did and the
+ // version test passed. So go ahead and jump.
+
+ offset = EmMemGet16 (dispatchTblP + LibTrapIndex (trapWord) * 2);
+ emuptr result = dispatchTblP + offset;
+
+ if (digDeep && EmMemGet16 (result) == kOpcode_JMPREL)
+ {
+ result += 2;
+ result += (int16) EmMemGet16 (result);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetSysFunctionAddress
+ *
+ * DESCRIPTION: Determines the address of a non-library function,
+ *
+ * PARAMETERS: trapWord - the dispatch number used to invoke the
+ * function(the number after the TRAP $F opocde)
+ *
+ * extra - an optional extra parameter. This parameter can
+ * be something like a library reference number, or a
+ * register to be used in a sub-dispatcher.
+ *
+ * digDeep - a boolean saying how hard we should look for
+ * the function address. If false, we just return the
+ * address generated by the ROM TrapDispatcher
+ * function. Otherwise, for certain special ROM
+ * routines (like the Floating Point Manager entry
+ * point), we look deeper.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetSysFunctionAddress (uint16 trapWord, uint32 extra, Bool digDeep)
+{
+ emuptr unimplementedAddress = EmLowMem::GetTrapAddress (sysTrapSysUnimplemented);
+ emuptr result = EmLowMem::GetTrapAddress (trapWord);
+
+ if (result == EmMemNULL ||
+ ((result == unimplementedAddress) && (trapWord != sysTrapSysUnimplemented)))
+ {
+ // sysTrapHostControl is always implemented, so make sure we
+ // don't return a NULL address.
+
+ if (::SysTrapIndex (trapWord) == ::SysTrapIndex (sysTrapHostControl))
+ {
+ return 0x12345678;
+ }
+
+ throw EmUnimplementedFunctionException ();
+ }
+
+ if (digDeep)
+ {
+ emuptr result2 = EmMemNULL;
+
+ if (trapWord == sysTrapIntlDispatch)
+ {
+ result2 = ::GetIntlDispatchAddress (result, extra);
+ }
+
+ else if (
+ trapWord == sysTrapOmDispatch ||
+ trapWord == sysTrapTsmDispatch ||
+ trapWord == sysTrapFlpDispatch ||
+ trapWord == sysTrapSerialDispatch)
+ {
+ result2 = ::GetStdDispatchAddress (result, extra);
+ }
+
+ else if (trapWord == sysTrapFlpEmDispatch)
+ {
+ result2 = ::GetFlpEmDispatchAddress (result, extra);
+ }
+
+ if (result2)
+ result = result2;
+ }
+
+ if (!result)
+ throw EmUnimplementedFunctionException ();
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetStdDispatchAddress
+ *
+ * DESCRIPTION: Determine the address of a function that is reached
+ * via a sub-dispatcher.
+ *
+ * PARAMETERS: entryPt - the entry point of the sub-dispatch function.
+ *
+ * regD2 - sub-dispatch selector.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetStdDispatchAddress (emuptr entryPt, uint32 regD2)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ /*
+ The standard dispatch routine code looks like this...
+
+ +$0000 10D5D7FE *CMP.W #$0018,D2 | B47C 0018
+ +$0004 10D5D802 BHI.S @error | 626C
+ +$0006 10D5D804 ADD.W D2,D2 | D442
+ +$0008 10D5D806 ADD.W D2,D2 | D442
+ +$000A 10D5D808 JMP *+$0004(D2.W) | 4EFB 2002
+
+ +$000E 10D5D80C JMP function1 | 4EFA F732
+ +$0012 10D5D810 JMP function2 | 4EFA 0AB8
+ ...
+ */
+
+ // check for expected opcodes
+
+ if (EmMemGet16 (entryPt + 0x00) != kOpcode_CMPW ||
+ EmMemGet16 (entryPt + 0x06) != kOpcode_ADDW ||
+ EmMemGet16 (entryPt + 0x08) != kOpcode_ADDW ||
+ EmMemGet32 (entryPt + 0x0A) != kOpcode_JMPPC)
+ {
+ return EmMemNULL;
+ }
+
+ // load the max selector value, and compare to D2.W
+
+ uint16 maxSelector = EmMemGet16 (entryPt + 2);
+
+ if ((regD2 & 0x0000FFFF) > maxSelector)
+ {
+ return EmMemNULL;
+ }
+
+ // point to appropriate JMP xxx instruction.
+
+ emuptr result = entryPt + 14 + (regD2 * 4);
+
+ if (EmMemGet16 (result) != kOpcode_JMPREL)
+ {
+ return EmMemNULL;
+ }
+
+ result += 2;
+ result += (int16) EmMemGet16 (result);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetFlpEmDispatchAddress
+ *
+ * DESCRIPTION: Determine the address of a function that is reached
+ * via a sub-dispatcher.
+ *
+ * PARAMETERS: entryPt - the entry point of the sub-dispatch function.
+ *
+ * regD2 - sub-dispatch selector.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetFlpEmDispatchAddress (emuptr entryPt, uint32 regD2)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ /*
+ The FlpEm dispatch routine code looks like this...
+
+ +$0000 10D5D804 ADD.W D2,D2 | D442
+ +$0002 10D5D806 ADD.W D2,D2 | D442
+ +$0004 10D5D808 JMP *+$0004(D2.W) | 4EFB 2002
+
+ +$0008 10D5D80C JMP _fp_round | 4EFA F732
+ +$000A 10D5D810 JMP _fp_get_fpscr | 4EFA 0AB8
+ ...
+ */
+
+ // check for expected opcodes
+
+ if (EmMemGet16 (entryPt + 0x00) != kOpcode_ADDW ||
+ EmMemGet16 (entryPt + 0x02) != kOpcode_ADDW ||
+ EmMemGet32 (entryPt + 0x04) != kOpcode_JMPPC)
+ {
+ return EmMemNULL;
+ }
+
+ // point to appropriate JMP xxx instruction.
+
+ emuptr result = entryPt + 8 + (regD2 * 4);
+
+ if (EmMemGet16 (result) != kOpcode_JMPREL)
+ {
+ return EmMemNULL;
+ }
+
+ result += 2;
+ result += (int16) EmMemGet16 (result);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetIntlDispatchAddress
+ *
+ * DESCRIPTION: Determine the address of an IntlDispatch function that
+ * is reached via a sub-dispatcher.
+ *
+ * PARAMETERS: entryPt - the entry point of the sub-dispatch function.
+ *
+ * regD2 - sub-dispatch selector.
+ *
+ * RETURNED: The function's address, or EmMemNULL if it could not
+ * be determined.
+ *
+ ***********************************************************************/
+
+emuptr GetIntlDispatchAddress (emuptr entryPt, uint32 regD2)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ /*
+ The original IntlDispatch routine code looks like this...
+
+ +$0000 10D5D7FE *CMP.W #$0018,D2 | B47C 0018
+ +$0004 10D5D802 BHI.S @error | 626C
+ +$0006 10D5D804 ADD.W D2,D2 | D442
+ +$0008 10D5D806 ADD.W D2,D2 | D442
+ +$000A 10D5D808 JMP *+$0004(D2.W) | 4EFB 2002
+
+ +$000E 10D5D80C JMP IntlInit | 4EFA F732
+ +$0012 10D5D810 JMP TxtByteAttr | 4EFA 0AB8
+ ...
+
+ In 4.0, the IntlDispatch routine code looks like this...
+
+ +$0000 10C1AE18 CMP.W #$001B,D2 | B47C 001B
+ +$0004 10C1AE1C BHI.S @error | 6212
+ +$0006 10C1AE1E ADD.W D2,D2 | D442
+ +$0008 10C1AE20 ADD.W D2,D2 | D442
+ +$000A 10C1AE22 MOVE.L $00000350,D0 | 2038 0350
+ +$000E 10C1AE26 BEQ.S @standard | 670E
+
+ +$0010 10C1AE28 MOVE.L D0,A0 | 2040
+ +$0012 10C1AE2A MOVE.L $00(A0,D2.W),A0 | 2070 2000
+ +$0016 10C1AE2E JMP (A0) | 4ED0
+
+ @error:
+ +$0018 10C1AE30 MOVE.W D2,-(A7) | 3F02
+ +$001A 10C1AE32 JMP selectorError | 4EFA 0086
+
+ @standard:
+ +$001E 10C1AE36 JMP *+$0004(D2.W) | 4EFB 2002
+
+ +$0022 10C1AE3A JMP IntlInit | 4EFA 0260
+ +$0022 10C1AE3E JMP TxtByteAttr | 4EFA EB60
+ ...
+ */
+
+ // check for expected opcodes
+
+ Bool newDispatch;
+
+ if (EmMemGet16 (entryPt + 0x00) != kOpcode_CMPW ||
+ EmMemGet16 (entryPt + 0x06) != kOpcode_ADDW ||
+ EmMemGet16 (entryPt + 0x08) != kOpcode_ADDW)
+ {
+ return EmMemNULL;
+ }
+
+ if (EmMemGet16 (entryPt + 0x0A) == kOpcode_JMPPC)
+ {
+ newDispatch = false;
+ }
+ else if (EmMemGet16 (entryPt + 0x0A) == kOpcode_MOVEL)
+ {
+ newDispatch = true;
+ }
+ else
+ {
+ return EmMemNULL;
+ }
+
+
+ // load the max selector value, and compare to D2.W
+
+ uint16 maxSelector = EmMemGet16 (entryPt + 2);
+
+ if ((regD2 & 0x0000FFFF) > maxSelector)
+ {
+ return EmMemNULL;
+ }
+
+ emuptr result;
+ if (newDispatch)
+ {
+ // figure out if low memory pointer exists.
+ emuptr lowMemPtr = EmMemGet16 (entryPt + 0x0C);
+ result = EmMemGet32 (lowMemPtr);
+
+ if (result == EmMemNULL)
+ {
+ newDispatch = false;
+ // point to start of dispatch table.
+ result = entryPt + 34;
+ }
+ }
+ else
+ {
+ // point to start of dispatch table.
+ result = entryPt + 14;
+ }
+
+ if (newDispatch)
+ {
+ // result points to table of routine addresses.
+ result = EmMemGet32 (result + (regD2 * 4));
+ }
+ else
+ {
+ // point to appropriate JMP xxx instruction.
+ result += (regD2 * 4);
+
+ if (EmMemGet16 (result) != kOpcode_JMPREL)
+ {
+ return EmMemNULL;
+ }
+
+ result += 2;
+ result += (int16) EmMemGet16 (result);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetTrapName
+ *
+ * DESCRIPTION: Returns a pointer to a string appropriate for
+ * identifying a function. If the function has a Macsbug
+ * name, that name is returned. If the function is a
+ * known Palm OS function, that name is looked up in a
+ * string resource list. Otherwise, a default "unknown"
+ * string is returned.
+ *
+ * PARAMETERS: context - structure describing the function.
+ *
+ * trapWord - the dispatch number used to invoke the
+ * function(the number after the TRAP $F opocde).
+ *
+ * extra - an optional extra parameter. This parameter can
+ * be something like a library reference number, or a
+ * register to be used in a sub-dispatcher.
+ *
+ * digDeep - a boolean saying how hard we should look for
+ * the function address. If false, we just return the
+ * address generated by the ROM TrapDispatcher
+ * function. Otherwise, for certain special ROM
+ * routines (like the Floating Point Manager entry
+ * point), we look deeper.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+char* GetTrapName (const SystemCallContext& context, Bool digDeep)
+{
+ return ::GetTrapName (context.fTrapWord, context.fExtra, digDeep);
+}
+
+
+char* GetTrapName (uint16 trapWord, uint32 extra, Bool digDeep)
+{
+ static char name[sysPktMaxNameLen];
+
+ try
+ {
+ name[0] = 0;
+ ::FindTrapName (trapWord, name, extra, digDeep);
+ }
+ catch (...)
+ {
+ }
+
+ if (strlen (name) == 0)
+ {
+ strcpy (name, ">>> Unknown function name <<<");
+
+ if (::IsSystemTrap (trapWord))
+ {
+ string knownName = Platform::GetString (kStr_SysTrapBase + SysTrapIndex (trapWord));
+ if (knownName[0] != '<')
+ {
+ strcpy (name, knownName.c_str ());
+ }
+ }
+ }
+
+ return name;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FindTrapName
+ *
+ * DESCRIPTION: Finds the Macsbug name for the given function. If the
+ * name cannot be found, an empty string is returned.
+ *
+ * PARAMETERS: trapWord - the dispatch number used to invoke the
+ * function(the number after the TRAP $F opocde)
+ *
+ * nameP - buffer to receive the function name.
+ *
+ * extra - an optional extra parameter. This parameter can
+ * be something like a library reference number, or a
+ * register to be used in a sub-dispatcher.
+ *
+ * digDeep - a boolean saying how hard we should look for
+ * the function address. If false, we just return the
+ * address generated by the ROM TrapDispatcher
+ * function. Otherwise, for certain special ROM
+ * routines (like the Floating Point Manager entry
+ * point), we look deeper.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void FindTrapName (uint16 trapWord, char* nameP, uint32 extra, Bool digDeep)
+{
+ emuptr addr = ::GetFunctionAddress (trapWord, extra, digDeep);
+
+ if (addr)
+ ::FindFunctionName (addr, nameP);
+ else
+ nameP[0] = '\0';
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FindFunctionName
+ *
+ * DESCRIPTION: Returns information about the function containing the
+ * the given memory address, including the function's
+ * start (the LINK instruction, usually), the function's
+ * end (just after the RTS, usually), and the function's
+ * name (that follows the function).
+ *
+ * PARAMETERS: addr - address contained within the function.
+ *
+ * nameP - storage for the returned function name. Must
+ * be at least 32 characters.
+ *
+ * startAddrP - storage for the returned function start.
+ *
+ * endAddrP - storage for the returned function end.
+ *
+ * nameCapacity - bytes of storage available at nameP
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+// Llamagraphics, Inc: Added nameCapacity argument so that callers
+// can retrieve more than 31 character function names. The default
+// capacity is 32, so callers that don't provide the extra argument
+// will get the same result as before.
+
+void FindFunctionName (emuptr addr, char* nameP,
+ emuptr* startAddrP, emuptr* endAddrP,
+ long nameCapacity)
+{
+ // Get the start address only if requested.
+
+ if (startAddrP)
+ *startAddrP = ::FindFunctionStart (addr);
+
+ // Get the end address if requested or if we need it to
+ // get the Macsbug name.
+
+ if (nameP || endAddrP)
+ {
+ emuptr endAddr = ::FindFunctionEnd (addr);
+
+ // Return the end address if requested.
+
+ if (endAddrP)
+ *endAddrP = endAddr;
+
+ // Return the Macsbug name if requested.
+
+ if (nameP)
+ {
+ if (endAddr)
+ ::GetMacsbugInfo (endAddr, nameP, nameCapacity, NULL);
+ else
+ nameP[0] = '\0';
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FindFunctionStart
+ *
+ * DESCRIPTION: Find the start of the function containing the given
+ * address. The start of the function is determined
+ * by looking backwards for the end of the previous
+ * function and then scooting forward to the beginning
+ * of this function.
+ *
+ * PARAMETERS: addr - the probe address.
+ *
+ * RETURNED: Start of the function. EmMemNULL if not found.
+ *
+ ***********************************************************************/
+
+emuptr FindFunctionStart (emuptr addr)
+{
+ emuptr beginAddr = addr - 0x02000; // Set a default value.
+
+ // Try finding the distance from the given address to the beginning
+ // of the chunk it's in, and use that as maxLength.
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (addr);
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkContaining (addr);
+ if (chunk)
+ {
+ beginAddr = chunk->BodyStart ();
+ }
+ }
+
+ while ((addr -= 2) >= beginAddr)
+ {
+ // Make sure the address is valid.
+
+ if (!EmMemCheckAddress (addr, 2))
+ {
+ return EmMemNULL;
+ }
+
+ if (::EndOfFunctionSequence (addr))
+ {
+ addr += 2; // skip past the final RTS (or whatever).
+
+ // Skip over the Macsbug name (and any constant data).
+
+ ::GetMacsbugInfo (addr, NULL, 0, &addr);
+
+ return addr;
+ }
+ }
+
+ // !!! TBD: if we got here, it's because we couldn't find the
+ // EOF sequence of a previous function. That might be because
+ // the function we're probing is the first in the chunk. In
+ // that case, return chunk->Start() or chunk->Start() + 2 as
+ // the beginning of the function. I'm not doing that now because
+ // I'm not sure which is right, or if there are other conditions
+ // to take into account.
+
+ return EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FindFunctionEnd
+ *
+ * DESCRIPTION: Find the end of the function containing the given
+ * address. The end of the function is determined by
+ * testing the given address for an end-of-function
+ * sequence, and then scooting forward by two bytes
+ * if the test fails.
+ *
+ * PARAMETERS: addr - the probe address.
+ *
+ * RETURNED: End of the function. EmMemNULL if not found.
+ *
+ ***********************************************************************/
+
+emuptr FindFunctionEnd (emuptr addr)
+{
+ emuptr endAddr = addr + 0x02000; // Set a default value.
+
+ // Try finding the distance from the given address to the end
+ // of the chunk it's in, and use that as maxLength.
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (addr);
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkContaining (addr);
+ if (chunk)
+ {
+ endAddr = chunk->BodyEnd ();
+ }
+ }
+
+ while (addr < endAddr)
+ {
+ // Make sure the address is valid.
+
+ if (!EmMemCheckAddress (addr, 2))
+ {
+ return EmMemNULL;
+ }
+
+ if (::EndOfFunctionSequence (addr))
+ {
+ return addr + 2;
+ }
+
+ addr += 2;
+ }
+
+ return EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EndOfFunctionSequence
+ *
+ * DESCRIPTION: Test the given memory location to see if it contains
+ * a valid-looking end of function sequence. A valid
+ * end of function sequence is an RTE, JMP (A0), RTD, or
+ * RTS (as long as it doesn't look like the sequnce
+ * CodeWarrior uses for 32-bit jumps).
+ *
+ * PARAMETERS: addr - memory location to test.
+ *
+ * RETURNED: True if it looks like this is an end of function
+ * sequence.
+ *
+ ***********************************************************************/
+
+Bool EndOfFunctionSequence (emuptr addr)
+{
+ uint16 opcode = EmMemGet16 (addr);
+
+ // Look for the special 32-bit relative jumps which
+ // CodeWarrior puts in. These are of the following form:
+ //
+ // +$0022 10CD3C2A PEA *+$0010 ; 10CD3C3A | 487A 000E
+ // +$0026 10CD3C2E PEA *+$0006 ; 10CD3C34 | 487A 0004
+ // +$002A 10CD3C32 ADDI.L #$00000CD2,(A7) ; '....' | 0697 0000 0CD2
+ // +$0030 10CD3C38 RTS | 4E75
+
+ if (opcode == kOpcode_RTS &&
+ EmMemGet16 (addr - 6) != kOpcode_ADD)
+ {
+ return true;
+ }
+
+ if (opcode == kOpcode_RTE ||
+ opcode == kOpcode_JMP || // JMP (A0)
+ opcode == kOpcode_RTD)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetMacsbugInfo
+ *
+ * DESCRIPTION: Return any eof-of-function information. This includes
+ * the (validated) Macsbug name and the address following
+ * all end-of-function information (presumably the start
+ * of the next function).
+ *
+ * PARAMETERS: eof - pointer to the end of the function (that is, the
+ * byte after the eof sequence).
+ *
+ * name - pointer to buffer to receive the name.
+ *
+ * nameCapacity - size of buffer pointed to by "name".
+ *
+ * sof - receives the start of the next function.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void GetMacsbugInfo (emuptr eof, char* name, long nameCapacity, emuptr* sof)
+{
+ uint8 length;
+ Bool isFixed;
+ emuptr namePtr;
+
+ ::MacsbugNameLength (eof, &length, &isFixed, &namePtr);
+
+ // Determine the address of the following function. Start by
+ // determining the address past the end of the string.
+
+ if (sof)
+ {
+ *sof = namePtr + length;
+
+ if (isFixed)
+ {
+ // Assert that we're word aligned.
+
+ EmAssert ((*sof & 0x01) == 0);
+ }
+ else
+ {
+ // Make sure the address is word aligned.
+
+ *sof = (*sof + 1) & ~0x01;
+
+ // Get the size of any following constant data and add that to
+ // the address we return as the start of the next function.
+ // Make sure the address remains word aligned.
+
+ uint16 constDataSize = EmMemGet16 (*sof);
+ *sof = (*sof + constDataSize + 2 + 1) & ~0x01;
+ }
+ }
+
+ // Copy the string, validating it as we go. Note that we have
+ // to go through this loop even if "name" is NULL so that we
+ // can validate all of the characters.
+
+ char* dest = name;
+ while (length--)
+ {
+ uint8 ch = EmMemGet8 (namePtr++) & 0x7F;
+
+ // If we're dealing with fixed format and we've encountered
+ // a space, make sure that all remaining characters are
+ // also spaces.
+
+ if (isFixed && ch == ' ')
+ {
+ while (length--)
+ {
+ ch = EmMemGet8 (namePtr++) & 0x7F;
+
+ if (ch != ' ')
+ {
+ goto Error;
+ }
+ }
+
+ break;
+ }
+
+ if (!::ValidMacsbugChar (ch))
+ {
+ goto Error;
+ }
+
+ // If there's room in the output buffer, store the character.
+ // Do it this way (as opposed to altering "length" if it's
+ // larger than nameCapacity) so that we can test all characters.
+
+ if (dest && ((dest - name) < (nameCapacity - 1)))
+ {
+ *dest++ = (char) ch;
+ }
+ }
+
+ // Terminate the string.
+
+ if (dest)
+ *dest = 0;
+
+ return;
+
+Error:
+ // All bets are off.
+
+ if (name)
+ *name = 0;
+
+ if (sof)
+ *sof = eof;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MascsbugNameLength
+ *
+ * DESCRIPTION: Returns the length of the Macsbug symbol starting at
+ * the given memory location.
+ *
+ * Note that NO validation of the symbol is performed.
+ * That is, if there is NO symbol after the function and
+ * the word immediately after the end of the function is
+ * the first opcode of the following function, the
+ * result of this function is meaningless.
+ *
+ * PARAMETERS: addr - start of the Macsbug symbol. Should contain
+ * the symbol's length byte or bytes.
+ *
+ * length - receives the length of the Macsbug symbol.
+ *
+ * isFixed - receives a boolean indicating if this name
+ * is in "fixed" or "variable" format. If the former,
+ * the name is padded with spaces which need to be
+ * accounted for. If the latter, spaces are not
+ * allowed at all. Also, variable-length names are
+ * followed by a word containing the length of a
+ * chunk of "local data".
+ *
+ * newAddr - receives the address of the first character
+ * of the Macsbug name. This address is addr, addr+1,
+ * or addr+2, depending on the symbol format.
+ *
+ * RETURNED: The symbol length (zero on error).
+ *
+ ***********************************************************************/
+
+void MacsbugNameLength (emuptr addr, uint8* length, Bool* isFixed, emuptr* namePtr)
+{
+ /*
+ The Macsbug name can be in one of three forms:
+
+ Variable length:
+ The first byte is in the range $80 to $9F and is a length
+ in the range 0 to $1F. The high order bit must be set. A
+ length of 0 implies the second byte is the actual length
+ in the range $01 thru $FF. The length byte(s) and name
+ may be an odd number of bytes. However, the data after
+ the name is word aligned.
+
+ Fixed length 8:
+ The first byte is in the range $20 to $7F and is an ASCII
+ character. The high order bit may be set but is not
+ required to be.
+
+ Fixed length 16:
+ The first byte is in the range $20 to $7F and is an ASCII
+ character. The high order bit may be set but is not
+ required to be. The high order bit in the second byte is
+ required to be set. This distinguishes the two types of
+ fixed names.
+ */
+
+ *length = EmMemGet8 (addr);
+
+ // If < 0x20, there is no name.
+
+ if (*length < 0x20)
+ {
+ *length = 0;
+ *isFixed = true;
+ }
+ else
+ {
+ // If < 0x20 (after stripping), it is in variable-length format.
+ // If >= 0x20 (after stripping), it is in 8- or 16-byte fixed format.
+
+ *length &= 0x7F;
+ *isFixed = (*length >= 0x20);
+
+ if (*isFixed)
+ {
+ if (EmMemGet8 (addr + 1) < 0x80)
+ *length = 8;
+ else
+ *length = 16;
+ }
+ else
+ {
+ addr++;
+
+ if (*length == 0)
+ *length = EmMemGet8 (addr++);
+ }
+ }
+
+ *namePtr = addr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ValidMacsbugChar
+ *
+ * DESCRIPTION: Returns whether or not the given character is a
+ * character in a valid Macsbug symbol. Valid characters
+ * are: [a-zA-Z0-9_%.]
+ *
+ * PARAMETERS: ch - the character to test
+ *
+ * RETURNED: True if the character is valid.
+ *
+ ***********************************************************************/
+
+Bool ValidMacsbugChar (uint8 ch)
+{
+ static Bool initialized = false;
+ static Bool validChar[128];
+
+ if (!initialized)
+ {
+ initialized = true;
+
+ memset (validChar, false, sizeof (validChar));
+
+ validChar ['_'] = true;
+ validChar ['%'] = true;
+ validChar ['.'] = true;
+
+ uint8 ii;
+
+ for (ii = 'a'; ii <= 'z'; ++ii)
+ validChar [ii] = true;
+
+ for (ii = 'A'; ii <= 'Z'; ++ii)
+ validChar [ii] = true;
+
+ for (ii = '0'; ii <= '9'; ++ii)
+ validChar [ii] = true;
+ }
+
+ EmAssert (ch < 128);
+
+ return validChar [ch];
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetShortName
+ *
+ * DESCRIPTION: Returns whether or not the given character is a
+ * character in a valid Macsbug symbol. Valid characters
+ * are: [a-zA-Z0-9_%.]
+ *
+ * PARAMETERS: ch - the character to test
+ *
+ * RETURNED: True if the character is valid.
+ *
+ ***********************************************************************/
+
+string PrvGetShortName (const char* srcName, int destLen)
+{
+ string result (destLen, ' '); // Create space-filled string of right length.
+
+ int iDest = 0;
+ int iSrc = 0;
+ int srcLen = strlen (srcName);
+
+ while (iDest < destLen && iSrc < srcLen)
+ {
+ char c = srcName[iSrc++];
+ if (isalnum (c))
+ {
+ result[iDest++] = toupper (c);
+ }
+ }
+
+ return result;
+}
diff --git a/SrcShared/EmPalmFunction.h b/SrcShared/EmPalmFunction.h
new file mode 100644
index 0000000..4235a50
--- /dev/null
+++ b/SrcShared/EmPalmFunction.h
@@ -0,0 +1,188 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPalmFunction_h
+#define EmPalmFunction_h
+
+#include "EmCPU.h" // GetPC
+
+struct SystemCallContext;
+
+void EmPalmFunctionInit (void);
+
+#define FOR_EACH_FUNCTION(DO_TO_FUNCTION) \
+ DO_TO_FUNCTION(cj_kptkdelete) \
+ DO_TO_FUNCTION(dns_decode_name) \
+ DO_TO_FUNCTION(BackspaceChar) \
+ DO_TO_FUNCTION(Crc16CalcBlock) \
+ DO_TO_FUNCTION(DmWrite) \
+ DO_TO_FUNCTION(ECValidateField) \
+ DO_TO_FUNCTION(EggOfInfiniteWisdom) \
+ DO_TO_FUNCTION(ExpInit) \
+ DO_TO_FUNCTION(FindShowResults) \
+ DO_TO_FUNCTION(FindSaveFindStr) \
+ DO_TO_FUNCTION(FldDelete) \
+ DO_TO_FUNCTION(FntDefineFont) \
+ DO_TO_FUNCTION(GrfProcessStroke) \
+ DO_TO_FUNCTION(HsPrvInit) \
+ DO_TO_FUNCTION(HsPrvInitCard) \
+ DO_TO_FUNCTION(MemMove) \
+ DO_TO_FUNCTION(MenuHandleEvent) \
+ DO_TO_FUNCTION(NetLibBitMove) \
+ DO_TO_FUNCTION(NetPrvSettingSet) \
+ DO_TO_FUNCTION(NetPrvTaskMain) \
+ DO_TO_FUNCTION(PrvCompressedInnerBitBlt)\
+ DO_TO_FUNCTION(PrvConvertDepth1To2BW) \
+ DO_TO_FUNCTION(PrvDrawSliderControl) \
+ DO_TO_FUNCTION(PrvFindMemoryLeaks) \
+ DO_TO_FUNCTION(PrvGetExpGlobals) \
+ DO_TO_FUNCTION(PrvGetVFSGlobals) \
+ DO_TO_FUNCTION(PrvGetIntlMgrGlobalsP) \
+ DO_TO_FUNCTION(PrvSetIntlMgrGlobalsP) \
+ DO_TO_FUNCTION(PrvMisAlignedForwardInnerBitBlt) \
+ DO_TO_FUNCTION(PrvMisAlignedBackwardInnerBitBlt) \
+ DO_TO_FUNCTION(PrvSystemTimerProc) \
+ DO_TO_FUNCTION(PrvReleaseExpGlobals) \
+ DO_TO_FUNCTION(PrvReleaseVFSGlobals) \
+ DO_TO_FUNCTION(SecPrvRandomSeed) \
+ DO_TO_FUNCTION(SysAppExit) \
+ DO_TO_FUNCTION(SysLaunch) \
+ DO_TO_FUNCTION(TsmGlueGetFepGlobals) \
+ DO_TO_FUNCTION(VFSInit) \
+ DO_TO_FUNCTION(_CerticomMemCpy) \
+
+
+// Declare a bunch of InFoo(emuptr) functions that can be used
+// to determine if a memory location is within a particular
+// Palm OS function.
+//
+// Note that the following macro used to declare just one function
+// that took a default emuptr parameter set to gCPU->GetPC ().
+// However, gcc 2.95.x and 2.96.x ran into internal compiler errors
+// trying to compile it (egcs 1.1.x and gcc 3.0 appear to be OK).
+// So the single function was broken into two, avoiding the error.
+
+#ifdef BROKEN_VIRTUAL_DEFAULT_ARGUMENTS
+
+#define DECLARE_FUNCTION(fn_name) \
+ Bool In##fn_name (emuptr); \
+ inline Bool In##fn_name () { return In##fn_name (gCPU->GetPC ()); }
+
+#else
+
+#define DECLARE_FUNCTION(fn_name) \
+ Bool In##fn_name (emuptr = gCPU->GetPC ());
+
+#endif
+
+
+FOR_EACH_FUNCTION(DECLARE_FUNCTION)
+
+#undef DECLARE_FUNCTION
+
+
+// Inline function to turn a trap word (0xA###) into an index into the
+// trap table. The method used here (masking off the uppermost nybble
+// instead of, say, subtracting sysTrapBase) matches the ROM.
+
+inline uint16 SysTrapIndex (uint16 trapWord)
+{
+ return (uint16) (trapWord & ~0xF000);
+}
+
+inline uint16 LibTrapIndex (uint16 trapWord)
+{
+ return (uint16) (SysTrapIndex (trapWord) - SysTrapIndex (sysLibTrapBase));
+}
+
+inline Bool IsSystemTrap (uint16 trapWord)
+{
+ return SysTrapIndex (trapWord) < SysTrapIndex (sysLibTrapBase);
+}
+
+inline Bool IsLibraryTrap (uint16 trapWord)
+{
+ return !IsSystemTrap (trapWord);
+}
+
+#define kProscribedDocumentedSystemUseOnly 1
+#define kProscribedUndocumentedSystemUseOnly 2
+#define kProscribedKernelUseOnly 3
+#define kProscribedObsolete 4
+#define kProscribedGhost 5
+#define kProscribedSystemUseOnlyAnyway 6
+#define kProscribedRare 7
+
+Bool ProscribedFunction (const SystemCallContext& context);
+int GetProscribedReason (const SystemCallContext& context);
+
+emuptr GetFunctionAddress (uint16 trapWord, uint32 extra = sysInvalidRefNum, Bool digDeep = false);
+emuptr GetLibFunctionAddress (uint16 trapWord, UInt16 refNum, Bool digDeep);
+emuptr GetSysFunctionAddress (uint16 trapWord, uint32 extra, Bool digDeep);
+emuptr GetStdDispatchAddress (emuptr entryPt, uint32 regD2);
+emuptr GetFlpEmDispatchAddress (emuptr entryPt, uint32 regD2);
+emuptr GetIntlDispatchAddress (emuptr entryPt, uint32 regD2);
+
+
+class EmUnimplementedFunctionException
+{
+ public:
+ EmUnimplementedFunctionException (long n = 0) :
+ fLibIndex (n)
+ {
+ }
+
+ long fLibIndex;
+};
+
+class EmInvalidRefNumException
+{
+ public:
+ EmInvalidRefNumException (long n = 0, long m = sysInvalidRefNum) :
+ fLibIndex (n),
+ fMaxRefNum (m)
+ {
+ }
+
+ long fLibIndex;
+ long fMaxRefNum;
+};
+
+char* GetTrapName (const SystemCallContext&, Bool digDeep = false);
+char* GetTrapName (uint16 trapWord, uint32 extra = sysInvalidRefNum, Bool digDeep = false);
+void FindTrapName (uint16 trapWord, char* nameP, uint32 extra = sysInvalidRefNum, Bool digDeep = false);
+
+// Llamagraphics, Inc: Added nameCapacity argument so that callers
+// can retrieve more than 31 character function names. The default
+// capacity is 32, so callers that don't provide the extra argument
+// will get the same result as before.
+
+void FindFunctionName (emuptr addr,
+ char* nameP,
+ emuptr* startAddrP = NULL,
+ emuptr* endAddrP = NULL,
+ long nameCapacity = 32);
+emuptr FindFunctionStart (emuptr addr);
+emuptr FindFunctionEnd (emuptr addr);
+Bool EndOfFunctionSequence (emuptr addr);
+
+// Llamagraphics, Inc: Added nameCapacity argument so that callers
+// can retrieve more than 31 character function names. The default
+// capacity is 32, so callers that don't provide the extra argument
+// will get the same result as before.
+
+void GetMacsbugInfo (emuptr eof, char* name, long nameCapacity, emuptr* sof);
+void MacsbugNameLength (emuptr addr, uint8* length, Bool* isFixed, emuptr* namePtr);
+Bool ValidMacsbugChar (uint8 ch);
+
+#endif /* EmPalmFunction_h */
diff --git a/SrcShared/EmPalmHeap.cpp b/SrcShared/EmPalmHeap.cpp
new file mode 100644
index 0000000..6745edc
--- /dev/null
+++ b/SrcShared/EmPalmHeap.cpp
@@ -0,0 +1,2263 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPalmHeap.h"
+
+#include "ChunkFile.h" // Chunk, EmStreamChunk
+#include "EmErrCodes.h" // kError_CorruptedHeap_Foo
+#include "EmMemory.h" // CEnableFullAccess, EmMemGet32, EmMemGet16, EmMemGet8
+#include "ErrorHandling.h" // Errors::ReportErrCorruptedHeap
+#include "ROMStubs.h" // MemNumHeaps, MemHeapID, MemHeapPtr
+#include "SessionFile.h" // SessionFile
+
+#include <stdio.h> // sprintf
+
+
+// ===========================================================================
+// ¥ EmPalmHeap
+// ===========================================================================
+
+EmPalmHeapList EmPalmHeap::fgHeapList;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Initialize [ STATIC ]
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Initialize (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Reset [ STATIC ]
+ *
+ * DESCRIPTION: Re-initializes the PalmHeap sub-system. This function
+ * is called when the ROM is "rebooted" (which includes
+ * the initial boot-up after a ROM is loaded).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Reset (void)
+{
+ fgHeapList.clear ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Save [ STATIC ]
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Save (SessionFile& f)
+{
+ const long kCurrentVersion = 1;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ s << fgHeapList;
+
+ f.WriteHeapInfo (chunk);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Load [ STATIC ]
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Load (SessionFile& f)
+{
+ Chunk chunk;
+ if (f.ReadHeapInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> fgHeapList;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false); // Need to reboot
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Dispose [ STATIC ]
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Dispose (void)
+{
+ fgHeapList.clear ();
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapListBegin [ STATIC ]
+ *
+ * DESCRIPTION: Return an iterator representing the beginning of our
+ * list of heap objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmHeapList::const_iterator EmPalmHeap::GetHeapListBegin (void)
+{
+ return fgHeapList.begin ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapListEnd [ STATIC ]
+ *
+ * DESCRIPTION: Return an iterator representing the end of our
+ * list of heap objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmHeapList::const_iterator EmPalmHeap::GetHeapListEnd (void)
+{
+ return fgHeapList.end ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapByID [ STATIC ]
+ *
+ * DESCRIPTION: Find a heap based on its ID.
+ *
+ * PARAMETERS: heapID - the ID to test.
+ *
+ * RETURNED: The pointer to the heap object. If no heap object
+ * has that ID, NULL is returned.
+ *
+ ***********************************************************************/
+
+const EmPalmHeap* EmPalmHeap::GetHeapByID (UInt16 heapID)
+{
+ EmPalmHeapList::iterator iter = fgHeapList.begin ();
+
+ while (iter != fgHeapList.end ())
+ {
+ if (iter->fHeapID == heapID)
+ {
+ return &*iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapByPtr [ STATIC ]
+ *
+ * DESCRIPTION: Find a heap based on a pointer.
+ *
+ * PARAMETERS: p - the pointer to test.
+ *
+ * RETURNED: The pointer to the heap object. If no heap object
+ * contains the pointer, NULL is returned.
+ *
+ ***********************************************************************/
+
+const EmPalmHeap* EmPalmHeap::GetHeapByPtr (emuptr p)
+{
+ return GetHeapByPtr ((MemPtr) p);
+}
+
+const EmPalmHeap* EmPalmHeap::GetHeapByPtr (MemPtr p)
+{
+ // !!! Could do a binary search here, if needed.
+
+ EmPalmHeapList::iterator iter = fgHeapList.begin ();
+
+ while (iter != fgHeapList.end ())
+ {
+ if (iter->Contains ((emuptr) p))
+ {
+ return &*iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapByHdl [ STATIC ]
+ *
+ * DESCRIPTION: Find a heap based on a handle.
+ *
+ * PARAMETERS: h - the handle to test.
+ *
+ * RETURNED: The pointer to the heap object. If no heap object
+ * contains the handle, NULL is returned.
+ *
+ * !!! What to do when the handle and pointer aren't in the same heap?
+ *
+ ***********************************************************************/
+
+const EmPalmHeap* EmPalmHeap::GetHeapByHdl (MemHandle h)
+{
+ MemPtr p = DerefHandle (h);
+
+ if (p)
+ return GetHeapByPtr (p);
+
+ return NULL;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::MemInitHeapTable [ STATIC ]
+ *
+ * DESCRIPTION: All new heaps have been created. Create objects to
+ * represent those heaps and add them to our list of heaps.
+ *
+ * PARAMETERS: Parameters passed to MemInitHeapTable
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::MemInitHeapTable (UInt16 cardNo)
+{
+ UInt16 numHeaps = ::MemNumHeaps (cardNo);
+
+ for (UInt16 heapIndex = 0; heapIndex < numHeaps; ++heapIndex)
+ {
+ UInt16 heapID = ::MemHeapID (cardNo, heapIndex);
+
+ // Add the heap, as long as it's not the dynamic heap. During
+ // bootup, the memory initialization sequence goes like:
+ //
+ // if hard reset required:
+ // MemCardFormat
+ // lay out the card
+ // MemStoreInit
+ // for each heap
+ // MemHeapInit
+ // MemInit
+ // for each card:
+ // MemInitHeapTable
+ // for each dynamic heap:
+ // MemHeapInit
+ // for each RAM heap:
+ // Unlock all chunks
+ // Compact
+ //
+ // Which means that if there's no hard reset, MemHeapInit
+ // has not been called on the dynamic heap at the time
+ // MemInitHeapTable is called. And since the dynamic heap
+ // is currently in a corrupted state (because the boot stack
+ // and initial LCD buffer have been whapped over it), we
+ // can't perform the heap walk we'd normally do when adding
+ // a heap object.
+
+ if (heapID != 0)
+ AddHeap (heapID);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::MemHeapInit [ STATIC ]
+ *
+ * DESCRIPTION: A new heap has been created. Create an object to
+ * represent that heap and add it to our list of heaps.
+ *
+ * PARAMETERS: Parameters passed to MemHeapInit
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::MemHeapInit (UInt16 heapID, Int16, Boolean)
+{
+ AddHeap (heapID);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::MemHeapCompact [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHeapFreeByOwnerID [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHeapScramble [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemChunkNew [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemChunkFree [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemPtrNew [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemPtrResize [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleNew [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleResize [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleFree [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemLocalIDToLockedPtr [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleLock [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleUnlock [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemHandleResetLock [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemPtrResetLock [ STATIC ]
+ * FUNCTION: EmPalmHeap::MemPtrUnlock [ STATIC ]
+ *
+ * DESCRIPTION: All of these functions alter the heap in some way.
+ * Resync our notion of the state of the heap with reality.
+ *
+ * PARAMETERS: Parameters to the Memory Manager functions that altered
+ * the heap.
+ *
+ * RETURNED: The chunks that cover the altered range of the heap
+ * are returned in the "delta" collection.
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::MemHeapCompact (UInt16 heapID, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (heapID));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemHeapFreeByOwnerID (UInt16 heapID, UInt16, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (heapID));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemHeapScramble (UInt16 heapID, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (heapID));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemChunkNew (UInt16 heapID, MemPtr p, UInt16 attr, EmPalmChunkList* delta)
+{
+ UNUSED_PARAM (p);
+ UNUSED_PARAM (attr);
+
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (heapID));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemChunkFree (EmPalmHeap* heap, EmPalmChunkList* delta)
+{
+// EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemPtrNew (MemPtr p, EmPalmChunkList* delta)
+{
+ UNUSED_PARAM (p);
+// EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (0));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemPtrResize (MemPtr p, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemHandleNew (MemHandle h, EmPalmChunkList* delta)
+{
+ UNUSED_PARAM (h);
+// EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByID (0));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemHandleResize (MemHandle h, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemHandleFree (EmPalmHeap* heap, EmPalmChunkList* delta)
+{
+// EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+
+ if (heap)
+ heap->ResyncAll (delta);
+}
+
+void EmPalmHeap::MemLocalIDToLockedPtr (MemPtr p, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncPtr (p, delta);
+}
+
+void EmPalmHeap::MemHandleLock (MemHandle h, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+
+ if (heap)
+ heap->ResyncHdl (h, delta);
+}
+
+void EmPalmHeap::MemHandleUnlock (MemHandle h, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+
+ if (heap)
+ heap->ResyncHdl (h, delta);
+}
+
+void EmPalmHeap::MemHandleResetLock (MemHandle h, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByHdl (h));
+
+ if (heap)
+ heap->ResyncHdl (h, delta);
+}
+
+void EmPalmHeap::MemPtrResetLock (MemPtr p, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncPtr (p, delta);
+}
+
+void EmPalmHeap::MemPtrUnlock (MemPtr p, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncPtr (p, delta);
+}
+
+void EmPalmHeap::MemPtrSetOwner (MemPtr p, EmPalmChunkList* delta)
+{
+ EmPalmHeap* heap = const_cast <EmPalmHeap*> (GetHeapByPtr (p));
+
+ if (heap)
+ heap->ResyncPtr (p, delta);
+}
+
+void EmPalmHeap::ValidateAllHeaps (void)
+{
+ EmPalmHeapList::iterator iter = fgHeapList.begin ();
+
+ while (iter != fgHeapList.end ())
+ {
+ (*iter).Validate ();
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::AddHeap [ STATIC ]
+ *
+ * DESCRIPTION: Add a heap based on its ID.
+ *
+ * PARAMETERS: heapID - the ID of the heap to add.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::AddHeap (UInt16 heapID)
+{
+ // Get information on the newly-created heap.
+
+ EmPalmHeap heap (heapID);
+
+ // Find where to add this heap to our list of heaps. We keep this
+ // list sorted by heap location for easy lookup on that basis.
+
+ EmPalmHeapList::iterator iter = fgHeapList.begin ();
+
+ while (iter != fgHeapList.end ())
+ {
+ // If we already had an entry for this heap, replace it.
+
+ if (iter->Start () == heap.Start ())
+ {
+ *iter = heap;
+ break;
+ }
+
+ // Found a place to insert this heap.
+
+ if (iter->Start () > heap.Start ())
+ {
+ fgHeapList.insert (iter, heap);
+ break;
+ }
+
+ ++iter;
+ }
+
+ // If the new heap couldn't be inserted before a currently existing
+ // heap, then add it to the end.
+
+ if (iter == fgHeapList.end ())
+ {
+ fgHeapList.push_back (heap);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::DerefHandle [ STATIC ]
+ *
+ * DESCRIPTION: Dereferences a handle and returns the pointer
+ *
+ * PARAMETERS: h - the handle to dereference
+ *
+ * RETURNED: The pointer associated with the handle.
+ *
+ ***********************************************************************/
+
+MemPtr EmPalmHeap::DerefHandle (MemHandle h)
+{
+ if (!h)
+ return NULL;
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ emuptr pp = (emuptr) memHandleUnProtect(h);
+ return (MemPtr) EmMemGet32 (pp);
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::RecoverHandle [ STATIC ]
+ *
+ * DESCRIPTION: Finds a handle given a pointer.
+ *
+ * Note that MemPtrRecoverHandle calls memHandleProtect on
+ * the result even if it's NULL; we don't do that here.
+ *
+ * PARAMETERS: p - the pointer whose handle we want to find
+ *
+ * RETURNED: The handle associated with the pointer. NULL if the
+ * chunk was not allocated as a relocatable chunk or if
+ * it's a free chunk.
+ *
+ ***********************************************************************/
+
+MemHandle EmPalmHeap::RecoverHandle (MemPtr p)
+{
+ MemHandle h = NULL;
+
+ if (p)
+ {
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (p);
+
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkBodyContaining ((emuptr) p);
+
+ if (chunk && !chunk->Free () && chunk->HOffset ())
+ {
+ h = (MemHandle) (((emuptr) p) - chunk->HOffset () * 2 - chunk->HeaderSize ());
+
+#if _DEBUG
+ CEnableFullAccess munge; // Remove blocks on memory access.
+ EmAssert (EmMemGet32 ((emuptr) h) == (emuptr) p);
+#endif
+
+ h = memHandleProtect (h);
+ }
+ }
+ }
+
+ return h;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapVersion [ STATIC ]
+ *
+ * DESCRIPTION: Determine and return the version number of the given
+ * heap.
+ *
+ * PARAMETERS: heapPtr - a pointer to the header for the heap whose
+ * version is to be determined.
+ *
+ * RETURNED: The version number of the heap. Currently, these values
+ * are 1 (original heap format), 2 (allows for >64K heaps),
+ * and 3 (uses a free list for faster allocations).
+ *
+ ***********************************************************************/
+
+long EmPalmHeap::GetHeapVersion (emuptr heapHdr)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ long heapVersion = kVersionUnknown;
+
+ // Get the heap version. If bit 14 is set, it's a version 3 heap.
+ // If bit 15 is set, it's a version 2 heap. Otherwise, it's a
+ // version 1 heap.
+
+ uint16 flags = EmMemGet16 (heapHdr);
+
+ if ((flags & memHeapFlagVers4) != 0)
+ {
+ heapVersion = kVersion4; // free MP's on a list
+ }
+ else if ((flags & memHeapFlagVers3) != 0)
+ {
+ heapVersion = kVersion3; // has free list
+ }
+ else if ((flags & memHeapFlagVers2) != 0)
+ {
+ heapVersion = kVersion2; // > 64K
+ }
+ else
+ {
+ heapVersion = kVersion1; // original
+ }
+
+ return heapVersion;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap::EmPalmHeap (void) :
+ fVersion (kVersionUnknown),
+ fHeapID (-1),
+ fHeapHdrStart (0),
+ fHeapHdrSize (0),
+ fFirstChunk (0),
+ fFlags (0),
+ fSize (0),
+ fFirstFree (0),
+ fChunkHdrSize (0),
+ fChunkList (),
+ fMPTList ()
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: heapID - Palm OS ID for the heap we're to track.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap::EmPalmHeap (UInt16 heapID) :
+ fVersion (kVersionUnknown),
+ fHeapID (heapID),
+ fHeapHdrStart (0),
+ fHeapHdrSize (0),
+ fFirstChunk (0),
+ fFlags (0),
+ fSize (0),
+ fFirstFree (0),
+ fChunkHdrSize (0),
+ fChunkList (),
+ fMPTList ()
+{
+ this->GetHeapHeaderInfo (heapID);
+ this->ResyncAll (NULL);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * Note: this version of the constructor doesn't work too
+ * well, since it doesn't determine the Palm OS heap ID.
+ *
+ * PARAMETERS: heapHdr - pointer to the heap header of the heap we're
+ * to track.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap::EmPalmHeap (emuptr heapHdr) :
+ fVersion (kVersionUnknown),
+ fHeapID (-1),
+ fHeapHdrStart (0),
+ fHeapHdrSize (0),
+ fFirstChunk (0),
+ fFlags (0),
+ fSize (0),
+ fFirstFree (0),
+ fChunkHdrSize (0),
+ fChunkList (),
+ fMPTList ()
+{
+ this->GetHeapHeaderInfo (heapHdr);
+ this->ResyncAll (NULL);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap copy constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: other - EmPalmHeap object we're to clone.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap::EmPalmHeap (const EmPalmHeap& other) :
+ fVersion (other.fVersion),
+ fHeapID (other.fHeapID),
+ fHeapHdrStart (other.fHeapHdrStart),
+ fHeapHdrSize (other.fHeapHdrSize),
+ fFirstChunk (other.fFirstChunk),
+ fFlags (other.fFlags),
+ fSize (other.fSize),
+ fFirstFree (other.fFirstFree),
+ fChunkHdrSize (other.fChunkHdrSize),
+ fChunkList (other.fChunkList),
+ fMPTList (other.fMPTList)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::~EmPalmHeap
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap::~EmPalmHeap (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetChunkListBegin
+ *
+ * DESCRIPTION: Return an iterator representing the beginning of our
+ * list of chunk objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmChunkList::const_iterator EmPalmHeap::GetChunkListBegin (void) const
+{
+ return fChunkList.begin ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetChunkListEnd
+ *
+ * DESCRIPTION: Return an iterator representing the end of our
+ * list of chunk objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmChunkList::const_iterator EmPalmHeap::GetChunkListEnd (void) const
+{
+ return fChunkList.end ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetChunkReferencedBy
+ *
+ * DESCRIPTION: Iterate over our list of chunks, finding the one
+ * referenced by the given handle.
+ *
+ * PARAMETERS: h - test handle
+ *
+ * RETURNED: Pointer to chunk object containing the probe address.
+ * NULL if not found.
+ *
+ ***********************************************************************/
+
+const EmPalmChunk* EmPalmHeap::GetChunkReferencedBy (MemHandle h) const
+{
+ // !!! Could do a binary search here, if needed.
+
+ emuptr p = (emuptr) EmPalmHeap::DerefHandle (h);
+
+ ITERATE_CHUNKS (*this, iter, end)
+ {
+ if (iter->Contains (p))
+ {
+ return &*iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetChunkContaining
+ *
+ * DESCRIPTION: Iterate over our list of chunks, finding the one
+ * containing the given pointer. The range includes the
+ * chunk header and trailer.
+ *
+ * PARAMETERS: p - probe address
+ *
+ * RETURNED: Pointer to chunk object containing the probe address.
+ * NULL if not found.
+ *
+ ***********************************************************************/
+
+const EmPalmChunk* EmPalmHeap::GetChunkContaining (emuptr p) const
+{
+ // !!! Could do a binary search here, if needed.
+
+ ITERATE_CHUNKS (*this, iter, end)
+ {
+ if (iter->Contains (p))
+ {
+ return &*iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetChunkBodyContaining
+ *
+ * DESCRIPTION: Iterate over our list of chunks, finding the one
+ * containing the given pointer. The range does not
+ * include the chunk header or trailer.
+ *
+ * PARAMETERS: p - probe address
+ *
+ * RETURNED: Pointer to chunk object containing the probe address.
+ * NULL if not found.
+ *
+ ***********************************************************************/
+
+const EmPalmChunk* EmPalmHeap::GetChunkBodyContaining (emuptr p) const
+{
+ // !!! Could do a binary search here, if needed.
+
+ ITERATE_CHUNKS (*this, iter, end)
+ {
+ if (iter->BodyContains (p))
+ {
+ return &*iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetMPTListBegin
+ *
+ * DESCRIPTION: Return an iterator representing the beginning of our
+ * list of master pointer table objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmMPTList::const_iterator EmPalmHeap::GetMPTListBegin (void) const
+{
+ return fMPTList.begin ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetMPTListEnd
+ *
+ * DESCRIPTION: Return an iterator representing the end of our
+ * list of master pointer table objects.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The iterator.
+ *
+ ***********************************************************************/
+
+EmPalmMPTList::const_iterator EmPalmHeap::GetMPTListEnd (void) const
+{
+ return fMPTList.end ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Tracked
+ *
+ * DESCRIPTION: Return whether or not we should track the contents of
+ * this heap. For performance reasons, we currently
+ * track only the dynamic heap.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if we track this heap's contents.
+ *
+ ***********************************************************************/
+
+Bool EmPalmHeap::Tracked (void) const
+{
+ return this->Dynamic ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ReadOnly
+ *
+ * DESCRIPTION: Return whether or not this heap is read-only
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmPalmHeap::ReadOnly (void) const
+{
+ return (fFlags & memHeapFlagReadOnly) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Dynamic
+ *
+ * DESCRIPTION: Return whether or not this heap is the (a?) dynamic heap.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmPalmHeap::Dynamic (void) const
+{
+ // This is probably the wrong test. I think there's a Palm OS call
+ // that indicates which heap(s) is/are dynamic.
+
+ return fHeapID == 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::Validate
+ *
+ * DESCRIPTION: Check to see that our chunk collection matches what's
+ * actually there.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::Validate (void)
+{
+ if (!this->Tracked ())
+ return;
+
+ EmPalmChunkList newList;
+ emuptr chunkHdr = this->DataStart ();
+
+ while (1)
+ {
+ // Get information about the current chunk.
+
+ EmPalmChunk chunk (*this, chunkHdr);
+
+ // If the size is zero, we've reached the sentinel at the end.
+
+ if (chunk.Size () == 0)
+ {
+ break;
+ }
+
+ // See if this chunk looks valid. An exception is thrown if not.
+
+ chunk.Validate (*this);
+
+ // Push this guy onto our list.
+
+ newList.push_back (chunk);
+
+ // Go on to next chunk.
+
+ chunkHdr += chunk.Size ();
+ }
+
+ EmPalmChunkList delta;
+ this->GenerateDeltas (newList, fChunkList, delta);
+ EmAssert (delta.size () == 0);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapHeaderInfo
+ *
+ * DESCRIPTION: Scarf information out of the heap header.
+ *
+ * PARAMETERS: heapID - the heapID of the heap to query.
+ *
+ * RETURNED: Nothing, but many data members are filled in.
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::GetHeapHeaderInfo (UInt16 heapID)
+{
+ MemPtr heapHdr = MemHeapPtr (heapID);
+ if (heapHdr)
+ this->GetHeapHeaderInfo ((emuptr) heapHdr);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GetHeapHeaderInfo
+ *
+ * DESCRIPTION: Scarf up information about the managed heap.
+ *
+ * PARAMETERS: heapHdr - the pointer to the heap to query.
+ *
+ * RETURNED: Nothing, but many data members are filled in.
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::GetHeapHeaderInfo (emuptr heapHdr)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+
+ // Save the pointer to the beginning of the heap. This pointer
+ // points to a struct, the definition of which changes depending
+ // on the heap version.
+
+ fHeapHdrStart = heapHdr;
+
+
+ // Get the heap version so we know the layout of the header.
+
+ fVersion = GetHeapVersion (fHeapHdrStart);
+
+
+ /*
+ Heap layout
+
+ flags: // Always here, always 2 bytes
+ size // 2 bytes in V1, 4 otherwise
+ firstFreeChunkOffset // Only in V3
+ mstrPtrTbl
+ numEntries // always 2 bytes long
+ nextTblOffset // 2 bytes in V1, 4 otherwise
+ mstrP [numEntries]
+ ...chunks...
+ */
+
+
+ switch (fVersion)
+ {
+ case kVersion1:
+ {
+ fFlags = EmMemGet16 (fHeapHdrStart);
+ fSize = EmMemGet16 (fHeapHdrStart + offsetof (Mem1HeapHeaderType, size));
+ fFirstFree = EmMemNULL;
+ fChunkHdrSize = sizeof (Mem1ChunkHeaderType);
+ fHeapHdrSize = offsetof (Mem1HeapHeaderType, mstrPtrTbl);
+
+ EmPalmMPT mpt (*this, this->MptStart ());
+ fFirstChunk = this->MptStart () + mpt.Size ();
+
+ // In version 1 heaps, a zero in the size field means 64K.
+
+ if (fSize == 0)
+ {
+ fSize = 64 * 1024L;
+ }
+ break;
+ }
+
+ case kVersion2:
+ {
+ fFlags = EmMemGet16 (fHeapHdrStart);
+ fSize = EmMemGet32 (fHeapHdrStart + offsetof (Mem2HeapHeaderType, size));
+ fFirstFree = EmMemNULL;
+ fChunkHdrSize = sizeof (MemChunkHeaderType);
+ fHeapHdrSize = offsetof (Mem2HeapHeaderType, mstrPtrTbl);
+
+ EmPalmMPT mpt (*this, this->MptStart ());
+ fFirstChunk = this->MptStart () + mpt.Size ();
+ break;
+ }
+
+ case kVersion3:
+ case kVersion4:
+ {
+ fFlags = EmMemGet16 (fHeapHdrStart);
+ fSize = EmMemGet32 (fHeapHdrStart + offsetof (MemHeapHeaderType, size));
+ fFirstFree = EmMemGet32 (fHeapHdrStart + offsetof (MemHeapHeaderType, firstFreeChunkOffset));
+ fChunkHdrSize = sizeof (MemChunkHeaderType);
+ fHeapHdrSize = offsetof (MemHeapHeaderType, mstrPtrTbl);
+
+ EmPalmMPT mpt (*this, this->MptStart ());
+ fFirstChunk = this->MptStart () + mpt.Size ();
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ break;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ResyncAll
+ *
+ * DESCRIPTION: Resynchronize our notion about the contents of the heap
+ * this object wraps up.
+ *
+ * PARAMETERS: delta - optional collection to receive the list of
+ * chunks that are different between the current and
+ * previous states of the heap. This collection is
+ * used when remarking what parts of the heap can be
+ * accessed by different processes.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::ResyncAll (EmPalmChunkList* delta)
+{
+ this->ResyncMPTList ();
+ this->ResyncChunkList (delta);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ResyncMPTList
+ *
+ * DESCRIPTION: Resynchronize our notion of what master pointer tables
+ * exist in this heap. Does nothing if this heap is
+ * not a "tracked" heap (see the Tracked method).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::ResyncMPTList (void)
+{
+ if (!this->Tracked ())
+ return;
+
+ emuptr p = this->MptStart ();
+
+ fMPTList.clear ();
+
+ while (1)
+ {
+ EmPalmMPT mpt (*this, p);
+
+ // See if this table looks valid. An exception is thrown if not.
+
+ mpt.Validate (*this);
+
+ fMPTList.push_back (mpt);
+
+ if (mpt.NextTableOffset () == 0)
+ break;
+
+ p = this->fHeapHdrStart + mpt.NextTableOffset ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ResyncChunkList
+ *
+ * DESCRIPTION: Resynchronize our notion of what memory chunks
+ * exist in this heap. Does nothing if this heap is
+ * not a "tracked" heap (see the Tracked method).
+ *
+ * PARAMETERS: delta - optional collection to receive the list of
+ * chunks that are different between the current and
+ * previous states of the heap. This collection is
+ * used when remarking what parts of the heap can be
+ * accessed by different processes.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::ResyncChunkList (EmPalmChunkList* delta)
+{
+ if (!this->Tracked ())
+ return;
+
+ EmPalmChunkList oldList;
+
+ if (delta)
+ oldList = fChunkList;
+
+ emuptr chunkHdr = this->DataStart ();
+
+ fChunkList.clear ();
+
+ while (1)
+ {
+ // Get information about the current chunk.
+
+ EmPalmChunk chunk (*this, chunkHdr);
+
+ // If the size is zero, we've reached the sentinel at the end.
+
+ if (chunk.Size () == 0)
+ {
+ break;
+ }
+
+ // See if this chunk looks valid. An exception is thrown if not.
+
+ chunk.Validate (*this);
+
+ // Push this guy onto our list.
+
+ fChunkList.push_back (chunk);
+
+ // Go on to next chunk.
+
+ chunkHdr += chunk.Size ();
+ }
+
+ if (delta)
+ this->GenerateDeltas (oldList, fChunkList, *delta);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ResyncPtr
+ *
+ * DESCRIPTION: Resynchronize information about a single particular
+ * chunk. This routine works by assuming that (a) the
+ * chunk already exists in the chunk list and that (b)
+ * only minor changes have been made to the chunk (like
+ * its lockcount having been changed). This routine
+ * should not be called if the chunk has been moved or
+ * resized, since by implication that means that more
+ * than one chunk has changed.
+ *
+ * Does nothing if the heap is not "tracked".
+ *
+ * PARAMETERS: p - pointer to the body of the chunk that changed.
+ *
+ * delta - optional collection to receive the list of
+ * chunks that are different between the current and
+ * previous states of the heap. This collection is
+ * used when remarking what parts of the heap can be
+ * accessed by different processes.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::ResyncPtr (MemPtr p, EmPalmChunkList* delta)
+{
+ if (!this->Tracked ())
+ return;
+
+ EmPalmChunkList::iterator iter = fChunkList.begin ();
+
+ emuptr chunkStart = ((emuptr) p) - fChunkHdrSize;
+
+ while (iter != fChunkList.end ())
+ {
+ if (iter->HeaderStart () == chunkStart)
+ {
+ *iter = EmPalmChunk (*this, chunkStart);
+
+ if (delta)
+ delta->push_back (*iter);
+
+ return;
+ }
+
+ ++iter;
+ }
+
+ EmAssert (false);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::ResyncHdl
+ *
+ * DESCRIPTION: Resynchronize information about a single particular
+ * chunk. This routine works by assuming that (a) the
+ * chunk already exists in the chunk list and that (b)
+ * only minor changes have been made to the chunk (like
+ * its lockcount having been changed). This routine
+ * should not be called if the chunk has been moved or
+ * resized, since by implication that means that more
+ * than one chunk has changed.
+ *
+ * Does nothing if the heap is not "tracked".
+ *
+ * PARAMETERS: h - handle of the chunk that changed.
+ *
+ * delta - optional collection to receive the list of
+ * chunks that are different between the current and
+ * previous states of the heap. This collection is
+ * used when remarking what parts of the heap can be
+ * accessed by different processes.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::ResyncHdl (MemHandle h, EmPalmChunkList* delta)
+{
+ if (!this->Tracked ())
+ return;
+
+ MemPtr p = DerefHandle (h);
+
+ if (p)
+ ResyncPtr (p, delta);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmHeap::GenerateDeltas
+ *
+ * DESCRIPTION: Given the current heap state and a previous heap state,
+ * generate the list of chunks that have changed between
+ * the two states.
+ *
+ * PARAMETERS: oldList - a previous heap state.
+ * newList - the current heap state.
+ * delta - container for changed chunks.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmHeap::GenerateDeltas (const EmPalmChunkList& oldList,
+ const EmPalmChunkList& newList,
+ EmPalmChunkList& delta)
+{
+ // Get iterators for the "before" and "after" chunk lists.
+
+ bool alreadyPushed = false;
+ EmPalmChunkList::const_iterator oldIter = oldList.begin ();
+ EmPalmChunkList::const_iterator newIter = newList.begin ();
+
+ // Clear out the containing receiving the results.
+
+ delta.clear ();
+
+ // Iterate over the "before" and "after" chunk lists until
+ // we reach the end of one of them.
+
+ while (oldIter != oldList.end () && newIter != newList.end ())
+ {
+ // If the two chunks currently being examined are the same,
+ // then the heaps are in sync at this point; proceed to the
+ // next chunks in both heap lists.
+
+ if (oldIter->CompareForDelta (*newIter))
+ {
+ ++oldIter;
+ ++newIter;
+ alreadyPushed = false;
+ continue;
+ }
+
+ // There is a difference between the two chunks. If we haven't
+ // already done so, record the difference by pushing the chunk
+ // from the "after" chunk list onto "delta".
+
+ if (!alreadyPushed)
+ {
+ delta.push_back (*newIter);
+ alreadyPushed = true;
+ }
+
+ // Try to find where the heap sync up again. If we increment
+ // the "after" iterator, make sure we invalid the flag that
+ // says we already added that chunk to the "delta" list.
+
+ if (oldIter->HeaderStart () < newIter->HeaderStart ())
+ {
+ ++oldIter;
+ }
+ else if (oldIter->HeaderStart () > newIter->HeaderStart ())
+ {
+ ++newIter;
+ alreadyPushed = false;
+ }
+ else
+ {
+ ++oldIter;
+ ++newIter;
+ alreadyPushed = false;
+ }
+ }
+
+ // If we reached the end of the "before" list, any remaining
+ // chunks on the "after" list are differences that need to be
+ // added to the "delta" container.
+
+ while (newIter != newList.end ())
+ {
+ delta.push_back (*newIter);
+ ++newIter;
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmMPT::EmPalmMPT (void) :
+ fVersion (kVersionUnknown),
+ fMptHdrStart (0),
+ fMptHdrSize (0),
+ fSize (0),
+ fNumEntries (0),
+ fNextTblOffset (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: heap - heap wrapper object containing this MPT.
+ * mptHdr - pointer to the master pointer table.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmMPT::EmPalmMPT (const EmPalmHeap& heap, emuptr mptHdr) :
+ fVersion (kVersionUnknown),
+ fMptHdrStart (0),
+ fMptHdrSize (0),
+ fSize (0),
+ fNumEntries (0),
+ fNextTblOffset (0)
+{
+ this->GetMPTInfo (heap, mptHdr);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT copy constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: other - MPT object we're to clone.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmMPT::EmPalmMPT (const EmPalmMPT& other) :
+ fVersion (other.fVersion),
+ fMptHdrStart (other.fMptHdrStart),
+ fMptHdrSize (other.fMptHdrSize),
+ fSize (other.fSize),
+ fNumEntries (other.fNumEntries),
+ fNextTblOffset (other.fNextTblOffset)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT::~EmPalmMPT
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmMPT::~EmPalmMPT (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT::Validate
+ *
+ * DESCRIPTION: Validate that the master pointer table looks valid.
+ *
+ * PARAMETERS: heap - heap containing the master pointe table
+ *
+ * RETURNED: Nothing (an exception is thrown on error).
+ *
+ ***********************************************************************/
+
+void EmPalmMPT::Validate (const EmPalmHeap& /*heap*/) const
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmMPT::GetMPTInfo
+ *
+ * DESCRIPTION: Scarf up information about the managed master pointer
+ * table.
+ *
+ * PARAMETERS: heap - heap object containing this master pointer table.
+ * mptHdr - pointer to the master pointer table contained
+ * in the heap.
+ *
+ * RETURNED: Nothing, but many data members are filled in.
+ *
+ ***********************************************************************/
+
+void EmPalmMPT::GetMPTInfo (const EmPalmHeap& heap, emuptr mptHdr)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ switch (heap.Version ())
+ {
+ case EmPalmHeap::kVersion1:
+ fVersion = kVersion1;
+
+ fMptHdrStart = mptHdr;
+ fMptHdrSize = sizeof (Mem1MstrPtrTableType);
+
+ fNumEntries = EmMemGet16 (mptHdr + offsetof (Mem1MstrPtrTableType, numEntries));
+ fNextTblOffset = EmMemGet16 (mptHdr + offsetof (Mem1MstrPtrTableType, nextTblOffset));
+ break;
+
+ case EmPalmHeap::kVersion2:
+ case EmPalmHeap::kVersion3:
+ case EmPalmHeap::kVersion4:
+ fVersion = kVersion2;
+
+ fMptHdrStart = mptHdr;
+ fMptHdrSize = sizeof (MemMstrPtrTableType);
+
+ fNumEntries = EmMemGet16 (mptHdr + offsetof (MemMstrPtrTableType, numEntries));
+ fNextTblOffset = EmMemGet32 (mptHdr + offsetof (MemMstrPtrTableType, nextTblOffset));
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ fSize = fMptHdrSize + fNumEntries * sizeof (MemPtr);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmChunk::EmPalmChunk (void) :
+ fVersion (kVersionUnknown),
+ fChunkHdrStart (0),
+ fChunkHdrSize (0),
+ fFree (0),
+ fMoved (0),
+ fUnused2 (0),
+ fUnused3 (0),
+ fSizeAdj (0),
+ fSize (0),
+ fLockCount (0),
+ fOwner (0),
+ fHOffset (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: heap - heap wrapper object containing this chunk.
+ * chunkHdr - pointer to the header of the chunk we're to
+ * wrap up.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmChunk::EmPalmChunk (const EmPalmHeap& heap, emuptr chunkHdr) :
+ fVersion (kVersionUnknown),
+ fChunkHdrStart (0),
+ fChunkHdrSize (0),
+ fFree (0),
+ fMoved (0),
+ fUnused2 (0),
+ fUnused3 (0),
+ fSizeAdj (0),
+ fSize (0),
+ fLockCount (0),
+ fOwner (0),
+ fHOffset (0)
+{
+ this->GetChunkInfo (heap, chunkHdr);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk copy constructor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: other - chunk object we're to clone.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmChunk::EmPalmChunk (const EmPalmChunk& other) :
+ fVersion (other.fVersion),
+ fChunkHdrStart (other.fChunkHdrStart),
+ fChunkHdrSize (other.fChunkHdrSize),
+ fFree (other.fFree),
+ fMoved (other.fMoved),
+ fUnused2 (other.fUnused2),
+ fUnused3 (other.fUnused3),
+ fSizeAdj (other.fSizeAdj),
+ fSize (other.fSize),
+ fLockCount (other.fLockCount),
+ fOwner (other.fOwner),
+ fHOffset (other.fHOffset)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk destructor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmPalmChunk::~EmPalmChunk (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk::Validate
+ *
+ * DESCRIPTION: Validate that the chunk looks valid.
+ *
+ * PARAMETERS: heap - heap containing the master pointe table
+ *
+ * RETURNED: Nothing (an exception is thrown on error).
+ *
+ ***********************************************************************/
+
+void EmPalmChunk::Validate (const EmPalmHeap& heap) const
+{
+ try
+ {
+ // Make sure the chunk is in the heap (this should always be true).
+ // !!! It's not...determine why and document.
+
+ if (!heap.Contains (fChunkHdrStart))
+ {
+ throw (kError_CorruptedHeap_ChunkNotInHeap);
+ }
+
+ // Check the size.
+
+ if (this->End () > heap.End ())
+ {
+ char buffer[20];
+
+ // !!! There's a problem here. These variables are set before the
+ // variable that uses them. Thus, replacements based on these variables
+ // are made before they're ready. The result is that %chunk_size and
+ // %chunk_max still appear in the final message. I'm not sure how, but
+ // this needs to be addressed and fixed...
+
+ sprintf (buffer, "%0x08X", (int) this->Size ());
+ Errors::SetParameter ("%chunk_size", buffer);
+
+ sprintf (buffer, "%0x08X", (int) heap.Size ());
+ Errors::SetParameter ("%chunk_max", buffer);
+
+ throw (kError_CorruptedHeap_ChunkTooLarge);
+ }
+
+ // These bits should not be set.
+
+ if (fUnused2 || fUnused3)
+ {
+ throw (kError_CorruptedHeap_InvalidFlags);
+ }
+
+ if (!fFree)
+ {
+ // If it's a movable chunk, validate that the handle offset
+ // references the handle that points back to the chunk.
+
+ if (fHOffset)
+ {
+ // Get the master pointer to this block. If hOffset is bogus, then
+ // this pointer may be bogus, too.
+
+ emuptr h = fChunkHdrStart - fHOffset * 2;
+
+ // Make sure it is in a master pointer block.
+
+ ITERATE_MPTS(heap, iter, end)
+ {
+ // See if "h" is in this array. If so, break from the loop.
+
+ if (iter->TableContains (h))
+ {
+ break;
+ }
+
+ ++iter;
+ }
+
+ if (iter == end)
+ {
+ throw (kError_CorruptedHeap_HOffsetNotInMPT);
+ }
+
+ // "h" is in a master pointer table. Make sure "h" points back
+ // to the block it's supposed to.
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ if (EmMemGet32 (h) != this->BodyStart())
+ {
+ throw (kError_CorruptedHeap_HOffsetNotBackPointing);
+ }
+ }
+
+ // If it's not a movable chunk, it must have a max lock count.
+
+ else
+ {
+ if (fLockCount != memPtrLockCount)
+ {
+ throw (kError_CorruptedHeap_InvalidLockCount);
+ }
+ }
+ }
+
+ // !!! Walk the heap and make sure that fChunkHdrStart is found?
+ }
+ catch (ErrCode err)
+ {
+ // This will throw an EmExceptionReset object.
+
+ Errors::ReportErrCorruptedHeap (err, this->fChunkHdrStart);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk::CompareForDelta
+ *
+ * DESCRIPTION: Compare two chunks to see if they're "close enough"
+ * when determining if something significant has changed.
+ *
+ * PARAMETERS: lhs - chunk to compare "*this" to.
+ *
+ * RETURNED: True if the two chunks are "equal enough".
+ *
+ ***********************************************************************/
+
+Bool EmPalmChunk::CompareForDelta (const EmPalmChunk& lhs) const
+{
+ return
+ fVersion == lhs.fVersion &&
+ fChunkHdrStart == lhs.fChunkHdrStart &&
+ fChunkHdrSize == lhs.fChunkHdrSize &&
+ fFree == lhs.fFree &&
+ fMoved == lhs.fMoved &&
+// fUnused2 == lhs.fUnused2 &&
+// fUnused3 == lhs.fUnused3 &&
+ fSizeAdj == lhs.fSizeAdj &&
+ fSize == lhs.fSize &&
+ (fLockCount > 0) == (lhs.fLockCount > 0) &&
+// fOwner == lhs.fOwner &&
+ fHOffset == lhs.fHOffset;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmChunk::GetChunkInfo
+ *
+ * DESCRIPTION: Scarf up information about the managed chunk.
+ *
+ * PARAMETERS: heapHdr - the pointer to the heap to query.
+ * chunkHdr - pointer to the header of the chunk in the
+ * heap we're to query.
+ *
+ * RETURNED: Nothing, but many data members are filled in.
+ *
+ ***********************************************************************/
+
+void EmPalmChunk::GetChunkInfo (const EmPalmHeap& heap, emuptr chunkHdr)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ switch (heap.Version ())
+ {
+ case EmPalmHeap::kVersion1:
+ {
+ fVersion = kVersion1;
+ fChunkHdrStart = chunkHdr;
+ fChunkHdrSize = sizeof (Mem1ChunkHeaderType);
+
+ UInt16 size = EmMemGet16 (chunkHdr + offsetof (Mem1ChunkHeaderType, size));
+
+ if (size == 0)
+ {
+ // Leave now. We're at the end of the heap. If we're at the end of RAM,
+ // too, attempts to access subsequent fields will cause a bus error.
+
+ break;
+ }
+
+ UInt8 lockOwner = EmMemGet8 (chunkHdr + offsetof (Mem1ChunkHeaderType, lockOwner));
+ UInt8 flags = EmMemGet8 (chunkHdr + offsetof (Mem1ChunkHeaderType, flags));
+ Int16 hOffset = EmMemGet16 (chunkHdr + offsetof (Mem1ChunkHeaderType, hOffset));
+
+ fFree = (flags & memChunkFlagFree) != 0;
+ fMoved = (flags & memChunkFlagUnused1) != 0;
+ fUnused2 = (flags & memChunkFlagUnused2) != 0;
+ fUnused3 = (flags & memChunkFlagUnused3) != 0;
+ fSizeAdj = (flags & mem1ChunkFlagSizeAdj);
+ fSize = size;
+ fLockCount = (lockOwner & mem1ChunkLockMask) >> 4;
+ fOwner = (lockOwner & mem1ChunkOwnerMask);
+ fHOffset = hOffset;
+
+ break;
+ }
+
+ case EmPalmHeap::kVersion2:
+ case EmPalmHeap::kVersion3:
+ case EmPalmHeap::kVersion4:
+ {
+ fVersion = kVersion2;
+ fChunkHdrStart = chunkHdr;
+ fChunkHdrSize = sizeof (MemChunkHeaderType);
+
+ UInt32 part1 = EmMemGet32 (chunkHdr);
+ UInt32 part2 = 0;
+
+ if ((part1 & 0x00FFFFFF) != 0)
+ {
+ part2 = EmMemGet32 (chunkHdr + 4);
+ }
+
+ fFree = (part1 & 0x80000000) != 0;
+ fMoved = (part1 & 0x40000000) != 0;
+ fUnused2 = (part1 & 0x20000000) != 0;
+ fUnused3 = (part1 & 0x10000000) != 0;
+ fSizeAdj = (part1 & 0x0F000000) >> 24;
+ fSize = (part1 & 0x00FFFFFF);
+ fLockCount = (part2 & 0xF0000000) >> 28;
+ fOwner = (part2 & 0x0F000000) >> 24;
+ fHOffset = (part2 & 0x00FFFFFF);
+
+ // hOffset is a signed value; make sure we keep it that way
+ // when we extract it by hand.
+
+ if ((fHOffset & 0x00800000) != 0)
+ {
+ fHOffset |= 0xFF000000;
+ }
+
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, EmPalmChunk&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& s, const EmPalmChunk& chunk)
+{
+ const long kVersion = 1;
+
+ s << kVersion;
+
+ s << chunk.fVersion;
+
+ s << chunk.fChunkHdrStart;
+ s << chunk.fChunkHdrSize;
+
+ s << chunk.fFree;
+ s << chunk.fMoved;
+ s << chunk.fUnused2;
+ s << chunk.fUnused3;
+ s << chunk.fSizeAdj;
+ s << chunk.fSize;
+
+ s << chunk.fLockCount;
+ s << chunk.fOwner;
+ s << chunk.fHOffset;
+
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, EmPalmChunk&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& s, EmPalmChunk& chunk)
+{
+ long version;
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> chunk.fVersion;
+
+ s >> chunk.fChunkHdrStart;
+ s >> chunk.fChunkHdrSize;
+
+ s >> chunk.fFree;
+ s >> chunk.fMoved;
+ s >> chunk.fUnused2;
+ s >> chunk.fUnused3;
+ s >> chunk.fSizeAdj;
+ s >> chunk.fSize;
+
+ s >> chunk.fLockCount;
+ s >> chunk.fOwner;
+ s >> chunk.fHOffset;
+ }
+
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, EmPalmMPT&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& s, const EmPalmMPT& mpt)
+{
+ const long kVersion = 1;
+
+ s << kVersion;
+
+ s << mpt.fVersion;
+
+ s << mpt.fMptHdrStart;
+ s << mpt.fMptHdrSize;
+ s << mpt.fSize;
+
+ s << mpt.fNumEntries;
+ s << mpt.fNextTblOffset;
+
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, EmPalmMPT&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& s, EmPalmMPT& mpt)
+{
+ long version;
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> mpt.fVersion;
+
+ s >> mpt.fMptHdrStart;
+ s >> mpt.fMptHdrSize;
+ s >> mpt.fSize;
+
+ s >> mpt.fNumEntries;
+ s >> mpt.fNextTblOffset;
+ }
+
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, EmPalmHeap&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& s, const EmPalmHeap& heap)
+{
+ const long kVersion = 1;
+
+ s << kVersion;
+
+ s << heap.fVersion;
+ s << heap.fHeapID;
+
+ s << heap.fHeapHdrStart;
+ s << heap.fHeapHdrSize;
+ s << heap.fFirstChunk;
+
+ s << heap.fFlags;
+ s << heap.fSize;
+ s << heap.fFirstFree;
+ s << heap.fChunkHdrSize;
+
+ s << heap.fChunkList;
+ s << heap.fMPTList;
+
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, EmPalmHeap&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& s, EmPalmHeap& heap)
+{
+ long version;
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> heap.fVersion;
+ s >> heap.fHeapID;
+
+ s >> heap.fHeapHdrStart;
+ s >> heap.fHeapHdrSize;
+ s >> heap.fFirstChunk;
+
+ s >> heap.fFlags;
+ s >> heap.fSize;
+ s >> heap.fFirstFree;
+ s >> heap.fChunkHdrSize;
+
+ s >> heap.fChunkList;
+ s >> heap.fMPTList;
+ }
+
+ return s;
+}
+
diff --git a/SrcShared/EmPalmHeap.h b/SrcShared/EmPalmHeap.h
new file mode 100644
index 0000000..1ccaae1
--- /dev/null
+++ b/SrcShared/EmPalmHeap.h
@@ -0,0 +1,373 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPalmHeap_h
+#define EmPalmHeap_h
+
+#include <vector>
+
+class SessionFile;
+
+class EmPalmChunk;
+class EmPalmMPT;
+class EmPalmHeap;
+
+typedef vector<EmPalmChunk> EmPalmChunkList;
+typedef vector<EmPalmMPT> EmPalmMPTList;
+typedef vector<EmPalmHeap> EmPalmHeapList;
+
+class EmStream;
+EmStream& operator << (EmStream&, const EmPalmChunk&);
+EmStream& operator >> (EmStream&, EmPalmChunk&);
+
+EmStream& operator << (EmStream&, const EmPalmMPT&);
+EmStream& operator >> (EmStream&, EmPalmMPT&);
+
+EmStream& operator << (EmStream&, const EmPalmHeap&);
+EmStream& operator >> (EmStream&, EmPalmHeap&);
+
+
+class EmPalmHeap
+{
+// ===== Static member functions =====
+
+ public:
+
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static EmPalmHeapList::const_iterator
+ GetHeapListBegin (void);
+ static EmPalmHeapList::const_iterator
+ GetHeapListEnd (void);
+
+ static const EmPalmHeap*
+ GetHeapByID (UInt16);
+ static const EmPalmHeap*
+ GetHeapByPtr (emuptr);
+ static const EmPalmHeap*
+ GetHeapByPtr (MemPtr);
+ static const EmPalmHeap*
+ GetHeapByHdl (MemHandle);
+
+ static void MemInitHeapTable (UInt16 cardNo);
+ static void MemHeapInit (UInt16 heapID,
+ Int16 numHandles,
+ Boolean initContents);
+ static void MemHeapCompact (UInt16 heapID,
+ EmPalmChunkList* = NULL);
+ static void MemHeapFreeByOwnerID (UInt16 heapID,
+ UInt16 ownerID,
+ EmPalmChunkList* = NULL);
+ static void MemHeapScramble (UInt16 heapID,
+ EmPalmChunkList* = NULL);
+
+ static void MemChunkNew (UInt16 heapID,
+ MemPtr,
+ UInt16 attributes,
+ EmPalmChunkList* = NULL);
+ static void MemChunkFree (EmPalmHeap* heap,
+ EmPalmChunkList* = NULL);
+
+ static void MemPtrNew (MemPtr,
+ EmPalmChunkList* = NULL);
+ static void MemPtrResize (MemPtr,
+ EmPalmChunkList* = NULL);
+
+ static void MemHandleNew (MemHandle,
+ EmPalmChunkList* = NULL);
+ static void MemHandleResize (MemHandle,
+ EmPalmChunkList* = NULL);
+ static void MemHandleFree (EmPalmHeap* heap,
+ EmPalmChunkList* = NULL);
+
+ static void MemLocalIDToLockedPtr (MemPtr,
+ EmPalmChunkList* = NULL);
+ static void MemHandleLock (MemHandle,
+ EmPalmChunkList* = NULL);
+ static void MemHandleUnlock (MemHandle,
+ EmPalmChunkList* = NULL);
+ static void MemHandleResetLock (MemHandle,
+ EmPalmChunkList* = NULL);
+ static void MemPtrResetLock (MemPtr,
+ EmPalmChunkList* = NULL);
+ static void MemPtrUnlock (MemPtr,
+ EmPalmChunkList* = NULL);
+ static void MemPtrSetOwner (MemPtr,
+ EmPalmChunkList* = NULL);
+
+ static void ValidateAllHeaps (void);
+
+ static MemPtr DerefHandle (MemHandle h);
+ static MemHandle RecoverHandle (MemPtr p);
+
+ private:
+ static void AddHeap (UInt16 heapID);
+ static long GetHeapVersion (emuptr heapHdr);
+
+ private:
+
+ static EmPalmHeapList fgHeapList;
+
+
+// ===== Object member functions =====
+
+ public:
+
+ EmPalmHeap (void);
+ EmPalmHeap (UInt16 heapID);
+ EmPalmHeap (emuptr heapHdr);
+ EmPalmHeap (const EmPalmHeap&);
+ ~EmPalmHeap (void);
+
+ EmPalmChunkList::const_iterator
+ GetChunkListBegin (void) const;
+ EmPalmChunkList::const_iterator
+ GetChunkListEnd (void) const;
+
+ const EmPalmChunk* GetChunkReferencedBy (MemHandle) const;
+ const EmPalmChunk* GetChunkContaining (emuptr) const;
+ const EmPalmChunk* GetChunkBodyContaining (emuptr) const;
+
+ EmPalmMPTList::const_iterator
+ GetMPTListBegin (void) const;
+ EmPalmMPTList::const_iterator
+ GetMPTListEnd (void) const;
+
+ Bool Tracked (void) const;
+ Bool ReadOnly (void) const;
+ Bool Dynamic (void) const;
+
+ emuptr Start (void) const { return fHeapHdrStart; }
+ emuptr End (void) const { return fHeapHdrStart + fSize; }
+ uint32 Size (void) const { return End () - Start (); }
+ Bool Contains (emuptr p) const { return ((p >= Start ()) && (p < End ())); }
+
+ emuptr HeaderStart (void) const { return fHeapHdrStart; }
+ emuptr HeaderEnd (void) const { return fHeapHdrStart + fHeapHdrSize; }
+ uint32 HeaderSize (void) const { return HeaderEnd () - HeaderStart (); }
+ Bool HeaderContains (emuptr p) const { return ((p >= HeaderStart ()) && (p < HeaderEnd ())); }
+
+ emuptr MptStart (void) const { return fHeapHdrStart + fHeapHdrSize; }
+ emuptr MptEnd (void) const { return fFirstChunk; }
+ uint32 MptSize (void) const { return MptEnd () - MptStart (); }
+ Bool MptContains (emuptr p) const { return ((p >= MptStart ()) && (p < MptEnd ())); }
+
+ emuptr DataStart (void) const { return fFirstChunk; }
+ emuptr DataEnd (void) const { return fHeapHdrStart + fSize; }
+ uint32 DataSize (void) const { return DataEnd () - DataStart (); }
+ Bool DataContains (emuptr p) const { return ((p >= DataStart ()) && (p < DataEnd ())); }
+
+ enum
+ {
+ kVersionUnknown,
+ kVersion1, // 1 = original
+ kVersion2, // 2 = >64K
+ kVersion3, // 3 = has free chunk list
+ kVersion4 // 4 = has free master pointer list
+ };
+
+ long Version (void) const { return fVersion; }
+ long HeapID (void) const { return fHeapID; }
+ long ChunkHeaderSize (void) const { return fChunkHdrSize; }
+
+ void Validate (void);
+
+ private:
+
+ void GetHeapHeaderInfo (UInt16 heapID);
+ void GetHeapHeaderInfo (emuptr heapHdr);
+
+ void ResyncAll (EmPalmChunkList* delta);
+ void ResyncMPTList (void);
+ void ResyncChunkList (EmPalmChunkList* delta);
+ void ResyncPtr (MemPtr,
+ EmPalmChunkList* delta);
+ void ResyncHdl (MemHandle,
+ EmPalmChunkList* delta);
+
+ void GenerateDeltas (const EmPalmChunkList& oldList,
+ const EmPalmChunkList& newList,
+ EmPalmChunkList& delta);
+
+
+ private:
+ friend EmStream& operator << (EmStream&, const EmPalmHeap&);
+ friend EmStream& operator >> (EmStream&, EmPalmHeap&);
+
+ long fVersion;
+ long fHeapID;
+
+ emuptr fHeapHdrStart;
+ uint32 fHeapHdrSize; // Up to the master pointer table struct
+ emuptr fFirstChunk; // Just after the end of the master pointer table
+
+ UInt16 fFlags;
+ UInt32 fSize;
+ UInt32 fFirstFree;
+ UInt16 fChunkHdrSize;
+
+ EmPalmChunkList fChunkList;
+ EmPalmMPTList fMPTList;
+};
+
+
+// Handy macros for dealing with the rather unwieldy iteration functions.
+
+#define ITERATE_HEAPS(iter1, iter2) \
+ EmPalmHeapList::const_iterator iter1 = EmPalmHeap::GetHeapListBegin (); \
+ EmPalmHeapList::const_iterator iter2 = EmPalmHeap::GetHeapListEnd (); \
+ while (iter1 != iter2)
+
+#define ITERATE_MPTS(heap, iter1, iter2) \
+ EmPalmMPTList::const_iterator iter1 = (heap).GetMPTListBegin (); \
+ EmPalmMPTList::const_iterator iter2 = (heap).GetMPTListEnd (); \
+ while (iter1 != iter2)
+
+#define ITERATE_CHUNKS(heap, iter1, iter2) \
+ EmPalmChunkList::const_iterator iter1 = (heap).GetChunkListBegin (); \
+ EmPalmChunkList::const_iterator iter2 = (heap).GetChunkListEnd (); \
+ while (iter1 != iter2)
+
+
+class EmPalmMPT
+{
+ public:
+ EmPalmMPT (void);
+ EmPalmMPT (const EmPalmHeap&,
+ emuptr mptHdr);
+ EmPalmMPT (const EmPalmMPT&);
+ ~EmPalmMPT (void);
+
+ void Validate (const EmPalmHeap& heap) const;
+
+ emuptr Start (void) const { return fMptHdrStart; }
+ emuptr End (void) const { return fMptHdrStart + fSize; }
+ uint32 Size (void) const { return End () - Start (); }
+ Bool Contains (emuptr p) const { return ((p >= Start ()) && (p < End ())); }
+
+ emuptr HeaderStart (void) const { return fMptHdrStart; }
+ emuptr HeaderEnd (void) const { return fMptHdrStart + fMptHdrSize; }
+ uint32 HeaderSize (void) const { return HeaderEnd () - HeaderStart (); }
+ Bool HeaderContains (emuptr p) const { return ((p >= HeaderStart ()) && (p < HeaderEnd ())); }
+
+ emuptr TableStart (void) const { return fMptHdrStart + fMptHdrSize; }
+ emuptr TableEnd (void) const { return fMptHdrStart + fSize; }
+ uint32 TableSize (void) const { return TableEnd () - TableStart (); }
+ Bool TableContains (emuptr p) const { return ((p >= TableStart ()) && (p < TableEnd ())); }
+
+ enum
+ {
+ kVersionUnknown,
+ kVersion1, // 1 = original
+ kVersion2 // 2 = >64K
+ };
+
+ long Version (void) const { return fVersion; }
+ UInt32 NextTableOffset (void) const { return fNextTblOffset; }
+
+ private:
+ void GetMPTInfo (const EmPalmHeap&,
+ emuptr mptHdr);
+
+ private:
+ friend EmStream& operator << (EmStream&, const EmPalmMPT&);
+ friend EmStream& operator >> (EmStream&, EmPalmMPT&);
+
+ long fVersion;
+
+ emuptr fMptHdrStart;
+ uint32 fMptHdrSize; // Up to the array of master pointers
+ uint32 fSize; // Entire size
+
+ UInt16 fNumEntries;
+ UInt32 fNextTblOffset;
+};
+
+
+class EmPalmChunk
+{
+ public:
+ EmPalmChunk (void);
+ EmPalmChunk (const EmPalmHeap&,
+ emuptr chunkHdr);
+ EmPalmChunk (const EmPalmChunk&);
+ ~EmPalmChunk (void);
+
+ void Validate (const EmPalmHeap& heap) const;
+ Bool CompareForDelta (const EmPalmChunk& lhs) const;
+
+ emuptr Start (void) const { return fChunkHdrStart; }
+ emuptr End (void) const { return fChunkHdrStart + fSize; }
+ uint32 Size (void) const { return End () - Start (); }
+ Bool Contains (emuptr p) const { return ((p >= Start ()) && (p < End ())); }
+
+ emuptr HeaderStart (void) const { return fChunkHdrStart; }
+ emuptr HeaderEnd (void) const { return fChunkHdrStart + fChunkHdrSize; }
+ uint32 HeaderSize (void) const { return HeaderEnd () - HeaderStart (); }
+ Bool HeaderContains (emuptr p) const { return ((p >= HeaderStart ()) && (p < HeaderEnd ())); }
+
+ emuptr BodyStart (void) const { return fChunkHdrStart + fChunkHdrSize; }
+ emuptr BodyEnd (void) const { return fChunkHdrStart + fSize - fSizeAdj; }
+ uint32 BodySize (void) const { return BodyEnd () - BodyStart (); }
+ Bool BodyContains (emuptr p) const { return ((p >= BodyStart ()) && (p < BodyEnd ())); }
+
+ emuptr TrailerStart (void) const { return fChunkHdrStart + fSize - fSizeAdj; }
+ emuptr TrailerEnd (void) const { return fChunkHdrStart + fSize; }
+ uint32 TrailerSize (void) const { return TrailerEnd () - TrailerStart (); }
+ Bool TrailerContains (emuptr p) const { return ((p >= TrailerStart ()) && (p < TrailerEnd ())); }
+
+ enum
+ {
+ kVersionUnknown,
+ kVersion1, // 1 = original
+ kVersion2 // 2 = >64K
+ };
+
+ long Version (void) const { return fVersion; }
+ Bool Free (void) const { return fFree; }
+ uint8 LockCount (void) const { return fLockCount; }
+ uint8 Owner (void) const { return fOwner; }
+ int32 HOffset (void) const { return fHOffset; }
+
+ private:
+ void GetChunkInfo (const EmPalmHeap&,
+ emuptr chunkHdr);
+
+ private:
+ friend EmStream& operator << (EmStream&, const EmPalmChunk&);
+ friend EmStream& operator >> (EmStream&, EmPalmChunk&);
+
+ long fVersion;
+
+ emuptr fChunkHdrStart;
+ uint32 fChunkHdrSize;
+
+ bool fFree; // set if free chunk
+ bool fMoved; // used by MemHeapScramble
+ bool fUnused2; // unused
+ bool fUnused3; // unused
+ uint8 fSizeAdj; // size adjustment
+ uint32 fSize; // actual size of chunk
+
+ uint8 fLockCount; // lock count
+ uint8 fOwner; // owner ID
+ int32 fHOffset; // signed handle offset/2
+ // used in free chunks to point to next free chunk
+
+};
+
+#endif /* EmPalmHeap_h */
diff --git a/SrcShared/EmPalmOS.cpp b/SrcShared/EmPalmOS.cpp
new file mode 100644
index 0000000..dcb260f
--- /dev/null
+++ b/SrcShared/EmPalmOS.cpp
@@ -0,0 +1,1752 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPalmOS.h"
+
+#include "EmBankDRAM.h" // EmBankDRAM::SetLong
+#include "EmBankMapped.h" // EmBankMapped::SetLong
+#include "EmBankROM.h" // EmBankROM::SetLong
+#include "EmBankSRAM.h" // EmBankSRAM::SetLong
+
+
+#include "DebugMgr.h" // Debug::HandleSystemCall
+#include "EmCPU68K.h" // gCPU68K, gStackHigh, etc.
+#include "EmErrCodes.h" // kError_UnimplementedTrap, kError_InvalidLibraryRefNum
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmPalmHeap.h" // EmPalmHeap, GetHeapByPtr
+#include "EmPalmFunction.h" // ProscribedFunction
+#include "EmPalmStructs.h" // EmAliasCardHeaderType
+#include "EmPatchMgr.h" // EmPatchMgr
+#include "EmPatchState.h" // EmPatchState
+#include "EmSession.h" // gSession->Reset
+#include "ErrorHandling.h" // Errors::ReportInvalidPC
+#include "Logging.h" // LogSystemCalls
+#include "MetaMemory.h" // MetaMemory::InRAMOSComponent
+#include "Miscellaneous.h" // GetSystemCallContext
+#include "Profiling.h" // gProfilingEnabled
+#include "ROMStubs.h" // IntlSetStrictChecks
+#include "UAE.h" // CHECK_STACK_POINTER_DECREMENT
+
+#include "EmEventPlayback.h" // EmEventPlayback::Initialize ();
+#include "EmLowMem.h" // EmLowMem::Initialize ();
+#include "EmPalmFunction.h" // EmPalmFunctionInit ();
+#include "EmPalmHeap.h" // EmPalmHeap::Initialize ();
+#include "EmPatchMgr.h" // EmPatchMgr::Initialize ();
+#include "Hordes.h" // Hordes::Initialize ();
+#include "Platform_NetLib.h" // Platform_NetLib::Initialize();
+
+#define LOG_FUNCTION_CALLS 0
+
+static StackList gStackList;
+static StackRange gBootStack;
+static StackRange gKernelStack;
+static StackRange gInterruptStack;
+
+static emuptr gBigROMEntry;
+
+static const uint32 CJ_TAGAMX = 0x414D5800;
+static const uint32 CJ_TAGFENCE = 0x55555555;
+
+// Subtract 34 bytes from the size of the stack. That's because
+// if an interrupt occurs, 34 bytes are pushed onto the stack before
+// the OS switches over to the interrupt stack.
+//
+// Exception 6 bytes // Old SR and old PC
+// LINK 4 bytes // Old A6
+// MOVEM.L 20 bytes // Old D0, D1, D2, A0, A1
+// MOVE A0, -(SP) 4 bytes // Old A0 (again)
+// ---------------------------------------------------------
+// Total 34 bytes
+
+static const int kInterruptOverhead = 34;
+static emuptr gStackLowWaterMark = 0;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::Initialize (void)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->InstallHookException (kException_SysCall, HandleTrap15);
+
+ gCPU68K->InstallHookJSR (HandleJSR);
+ gCPU68K->InstallHookJSR_Ind (HandleJSR_Ind);
+ gCPU68K->InstallHookLINK (HandleLINK);
+ gCPU68K->InstallHookRTE (HandleRTE);
+ gCPU68K->InstallHookRTS (HandleRTS);
+ gCPU68K->InstallHookNewPC (HandleNewPC);
+ gCPU68K->InstallHookNewSP (HandleNewSP);
+
+ gBigROMEntry = EmMemNULL;
+
+ // Add a notification for IntlStrictChecks
+
+ gPrefs->AddNotification (&EmPalmOS::PrefsChanged, kPrefKeyReportStrictIntlChecks);
+ gPrefs->AddNotification (&EmPalmOS::PrefsChanged, kPrefKeyReportOverlayErrors);
+
+ Hordes::Initialize ();
+ EmEventPlayback::Initialize ();
+ EmPatchMgr::Initialize ();
+ Platform_NetLib::Initialize ();
+ EmPalmHeap::Initialize ();
+ EmLowMem::Initialize ();
+ EmPalmFunctionInit ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::Reset (void)
+{
+ gStackList.clear ();
+
+ gBootStack = StackRange ();
+ gKernelStack = StackRange ();
+ gInterruptStack = StackRange ();
+
+ gKernelStackOverflowed = 0;
+
+ Hordes::Reset ();
+ EmEventPlayback::Reset ();
+ EmPatchMgr::Reset ();
+ Platform_NetLib::Reset ();
+ EmPalmHeap::Reset ();
+ EmLowMem::Reset ();
+
+ // If the appropriate modifier key is down, install a temporary breakpoint
+ // at the start of the Big ROM.
+
+ if (Platform::StopOnResetKeyDown ())
+ {
+ emuptr romStart = EmBankROM::GetMemoryStart ();
+ emuptr headerVersion = EmMemGet32 (romStart + offsetof (CardHeaderType, hdrVersion));
+ long bigROMOffset = 0x03000;
+
+ if (headerVersion > 1)
+ {
+ bigROMOffset = EmMemGet32 (romStart + offsetof (CardHeaderType, bigROMOffset));
+ bigROMOffset &= 0x000FFFFF; // Allows for 1 Meg offset.
+ }
+
+ emuptr resetVector = EmMemGet32 (romStart + bigROMOffset + offsetof (CardHeaderType, resetVector));
+
+ Debug::SetBreakpoint (dbgTempBPIndex, resetVector, NULL);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::Save (SessionFile& f)
+{
+ Hordes::Save (f);
+ EmEventPlayback::Save (f);
+ EmPatchMgr::Save (f);
+ Platform_NetLib::Save (f);
+ EmPalmHeap::Save (f);
+ EmLowMem::Save (f);
+
+ const long kCurrentVersion = 2;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ s << gStackList;
+ s << gBootStack;
+ s << gKernelStack;
+ s << gInterruptStack;
+
+ s << gStackHigh;
+ s << gStackLowWaterMark;
+ s << gStackLowWarn;
+ s << gStackLow;
+
+ s << gKernelStackOverflowed;
+
+ f.WriteStackInfo (chunk);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::Load (SessionFile& f)
+{
+ Hordes::Load (f);
+ EmEventPlayback::Load (f);
+ EmPatchMgr::Load (f);
+ Platform_NetLib::Load (f);
+ EmPalmHeap::Load (f);
+ EmLowMem::Load (f);
+
+ Chunk chunk;
+ if (f.ReadStackInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> gStackList;
+ s >> gBootStack;
+ s >> gKernelStack;
+ s >> gInterruptStack;
+
+ s >> gStackHigh;
+ s >> gStackLowWaterMark;
+ s >> gStackLowWarn;
+ s >> gStackLow;
+ }
+
+ if (version >= 2)
+ {
+ s >> gKernelStackOverflowed;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false); // Need to reboot
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::Dispose (void)
+{
+ EmLowMem::Dispose ();
+ EmPalmHeap::Dispose ();
+ Platform_NetLib::Dispose ();
+ EmPatchMgr::Dispose ();
+ EmEventPlayback::Dispose ();
+ Hordes::Dispose ();
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::CheckStackPointerAssignment
+ *
+ * DESCRIPTION: !!! This operation slows down Gremlins by about 10%; it
+ * should be sped up or made an option.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::CheckStackPointerAssignment (void)
+{
+ // If it was a "drastic" change, assume that we're *setting* the
+ // stack pointer to a new stack. Scarf up information about that
+ // block of memory and treat that block as a stack.
+
+ // See if we already know about this stack.
+
+ emuptr curA7 = gCPU->GetSP ();
+ StackList::iterator iter = gStackList.begin ();
+
+ while (iter != gStackList.end ())
+ {
+ if ((curA7 >= (*iter).fBottom) && (curA7 <= (*iter).fTop))
+ {
+ // If so, switch to it.
+ SetCurrentStack (*iter);
+ return;
+ }
+
+ ++iter;
+ }
+
+ // If not, get some information about it and save it off.
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (curA7);
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkBodyContaining (curA7);
+ if (chunk)
+ {
+ // The second time we switch stacks, we're switching from the
+ // boot stack to the kernel stack. In that case, forget any
+ // notion of the boot stack.
+
+ if (gBootStack.fBottom != EmMemNULL)
+ {
+ ForgetStack (gBootStack.fBottom);
+ }
+
+ // See if this looks like the AMX kernel stack.
+ // We detect this by seeing (a) if the stack pointer
+ // is being set to a value not too close to the end
+ // of the chunk it's in (indicating that the stack is
+ // embedded in some other data, as is the AMX stack)
+ // and (b) if the values the stack pointer points to
+ // are the appropriate tags.
+
+ CEnableFullAccess munge;
+ if (curA7 <= (chunk->BodyEnd () - 8) &&
+ EmMemGet32 (curA7) == CJ_TAGAMX &&
+ EmMemGet32 (curA7 + 4) == CJ_TAGFENCE)
+ {
+ RememberKernelStack ();
+
+ // Remember this stack as the "current" stack.
+
+ SetCurrentStack (gKernelStack);
+ }
+ else
+ {
+ RememberStackChunk (*chunk);
+
+ // Remember this stack as the "current" stack.
+
+ StackRange range (chunk->BodyStart (),
+ chunk->BodyStart () + chunk->BodySize ());
+ SetCurrentStack (range);
+ }
+ }
+ else
+ {
+ // !!!
+ }
+ }
+ else
+ {
+ if (gStackList.size () == 0)
+ {
+ // We're switching from the reset stack to the boot stack.
+
+ RememberBootStack ();
+
+ // Remember this stack as the "current" stack.
+
+ SetCurrentStack (gBootStack);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::CheckStackPointerDecrement
+ *
+ * DESCRIPTION: !!! This operation slows down Gremlins by about 10%; it
+ * should be sped up or made an option.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::CheckStackPointerDecrement (void)
+{
+ // If it was an "incremental" change, make sure that A7 is not
+ // now outside the stack it used to be in (as indicated by oldA7).
+
+ // Test for "close to the end" (in which case we display a warning), and
+ // "past the end" (in which case we print a fatal error).
+
+ if (gKernelStackOverflowed)
+ return;
+
+ emuptr curA7 = gCPU->GetSP ();
+ Bool warning = curA7 < gStackLowWarn;
+ Bool fatal = curA7 < gStackLow;
+
+ if (gStackLowWaterMark > curA7)
+ gStackLowWaterMark = curA7;
+
+ if (warning)
+ {
+ // Special hack for the kernel stack overflowing into the
+ // interrupt stack. If there was a stack overflow and the
+ // current stack is the kernel stack, then ignore the error.
+ // Also, try limiting this hack to older Palm OS's by looking
+ // at the stack size. Newer ROMs will have larger stacks and
+ // should not be allowed to have this bug.
+
+ if (fatal && gKernelStack.fTop == gStackHigh &&
+ gKernelStack.fTop - gKernelStack.fBottom <= 0x2F4)
+ {
+ gKernelStackOverflowed = 1;
+ return;
+ }
+
+ if (fatal)
+ {
+ Errors::ReportErrStackOverflow ();
+ }
+ else
+ {
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (new EmDeferredErrStackFull);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::CheckKernelStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::CheckKernelStack (void)
+{
+ EmAssert (gKernelStackOverflowed);
+
+ emuptr curA7 = gCPU->GetSP ();
+
+ if (curA7 <= gStackHigh && curA7 >= gStackLow)
+ {
+ gKernelStackOverflowed = 0;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::RememberStackChunk
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::RememberStackChunk (const EmPalmChunk& chunk)
+{
+ // Create a range object for the chunk.
+
+ StackRange range (chunk.BodyStart (), chunk.BodyEnd ());
+
+ // Remember it for later.
+
+ RememberStackRange (range);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::RememberBootStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::RememberBootStack (void)
+{
+ /*
+ There's a constant in SystemPrv.h that indicates that the boot
+ stack should be 4K long. However, that 4K is relative to the
+ start of the dynamic heap, which is used while the boot stack
+ is in effect. As the system boots up, blocks are allocated and
+ de-allocated in the stack range. We have a check in ForgetStack
+ that checks to see if a MemFooFree operation is taking place
+ within a stack -- normally a dubious operation -- and it's
+ noticing this situation.
+
+ For now, it looks like we only use 0x438 bytes* of the boot
+ stack, so I'll allow 0x500. This should prevent the overlap of
+ the boot stack with any allocated chunks.
+
+ * This was against one particular ROM, but I don't remember
+ which. Checking a Palm IIIc 4.0 Debug ROM just now, I see
+ it using 0x308 bytes.
+ */
+
+// const int kBootStackSize = 0x1000; // Per SystemPrv.h
+ const int kBootStackSize = 0x0500; // Per experimentation
+
+ gBootStack = StackRange (
+ gCPU->GetSP () - kBootStackSize,
+ gCPU->GetSP ());
+
+ RememberStackRange (gBootStack);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::RememberKernelStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::RememberKernelStack (void)
+{
+ // Scan down for the bottom of stack marker.
+
+ CEnableFullAccess munge;
+
+ emuptr ksp = gCPU->GetSP ();
+ while (EmMemGet32 (ksp) != CJ_TAGFENCE)
+ ksp -= 2;
+
+ emuptr isp = ksp - 4;
+ while (EmMemGet32 (isp) != CJ_TAGFENCE)
+ isp -= 2;
+
+ // Add the two stacks. Add the interrupt stack first, and the
+ // kernel stack second. That way, the last added stack -- the
+ // kernel stack -- is remembered as the "current" stack.
+
+ gInterruptStack = StackRange (isp + 4, ksp);
+ RememberStackRange (gInterruptStack);
+
+ gKernelStack = StackRange (ksp + 4, gCPU->GetSP ());
+ RememberStackRange (gKernelStack);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::RememberStackRange
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::RememberStackRange (const StackRange& range)
+{
+#if _DEBUG
+ // Make sure this range doesn't overlap any other stack in our list.
+
+ StackList::iterator iter = gStackList.begin ();
+
+ while (iter != gStackList.end ())
+ {
+ if (range.fBottom >= iter->fBottom && range.fBottom < iter->fTop)
+ EmAssert (false);
+
+ if (range.fTop > iter->fBottom && range.fTop <= iter->fTop)
+ EmAssert (false);
+
+ ++iter;
+ }
+#endif
+
+ // Add the range to the list.
+
+ gStackList.push_back (range);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::SetCurrentStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::SetCurrentStack (const StackRange& range)
+{
+ // Record the low-water mark of the previous stack.
+
+ StackList::iterator iter = gStackList.begin ();
+
+ while (iter != gStackList.end ())
+ {
+ if (gStackHigh == iter->fTop)
+ {
+ iter->fLowWaterMark = gStackLowWaterMark;
+
+ if (gStackHigh == gBootStack.fTop)
+ gBootStack.fLowWaterMark = gStackLowWaterMark;
+
+ if (gStackHigh == gKernelStack.fTop)
+ gKernelStack.fLowWaterMark = gStackLowWaterMark;
+
+ if (gStackHigh == gInterruptStack.fTop)
+ gInterruptStack.fLowWaterMark = gStackLowWaterMark;
+
+ break;
+ }
+
+ ++iter;
+ }
+
+ // Determine the amount to test against when determining if we are
+ // close to overflowing the stack. For applications, let's set this
+ // to 50 bytes. For the kernel stack, set it to zero; some Palm OS's
+ // get damn close to the end of the kernel stack (the Palm VII ROM gets
+ // within 8 bytes!).
+
+ const int kAppStackSlush = 50;
+ const int kKernelStackSlush = 0;
+
+ int stackSlush = kAppStackSlush;
+
+ if (range == gKernelStack)
+ stackSlush = kKernelStackSlush;
+
+ gStackHigh = range.fTop;
+ gStackLowWaterMark = range.fLowWaterMark;
+ gStackLowWarn = range.fBottom + kInterruptOverhead + stackSlush;
+ gStackLow = range.fBottom + kInterruptOverhead;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::ForgetStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::ForgetStack (emuptr stackBottom)
+{
+ StackList::iterator iter = gStackList.begin ();
+
+ while (iter != gStackList.end ())
+ {
+ // If the pointer is in the *middle* of a stack, that's not good.
+
+ if (stackBottom > iter->fBottom && stackBottom < iter->fTop)
+ EmAssert (false);
+
+ // If the pointer is to the beginning of the stack, we've found
+ // the one we want to remove.
+
+ if (stackBottom == iter->fBottom)
+ {
+ gStackList.erase (iter);
+
+ if (stackBottom == gBootStack.fBottom)
+ {
+#define TRACK_BOOT_ALLOCATION 0
+#if TRACK_BOOT_ALLOCATION
+ LogAppendMsg ("===== Forgetting Boot Stack, top = 0x%08X, low water mark: 0x%08X =====",
+ gBootStack.fTop, gBootStack.fLowWaterMark);
+#endif
+
+ gBootStack = StackRange ();
+ }
+
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::ForgetStacksIn
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::ForgetStacksIn (emuptr start, uint32 range)
+{
+ StackList::iterator iter = gStackList.begin ();
+
+ while (iter != gStackList.end ())
+ {
+ if ((iter->fBottom >= start) && (iter->fTop <= (start + range)))
+ {
+ gStackList.erase (iter);
+
+ if (start == gBootStack.fBottom)
+ {
+#define TRACK_BOOT_ALLOCATION 0
+#if TRACK_BOOT_ALLOCATION
+ LogAppendMsg ("===== Forgetting Boot Stack, top = 0x%08X, low water mark: 0x%08X =====",
+ gBootStack.fTop, gBootStack.fLowWaterMark);
+#endif
+
+ gBootStack = StackRange ();
+ }
+
+ // We munged the collection; start over.
+
+ iter = gStackList.begin ();
+ continue;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::GetBootStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+StackRange EmPalmOS::GetBootStack (void)
+{
+ return gBootStack;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::IsInStack
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::IsInStack (emuptr addr)
+{
+ return addr >= gStackLow && addr < gStackHigh;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::IsInStackBlock
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::IsInStackBlock (emuptr addr)
+{
+ return addr >= gCPU->GetSP () && addr < gStackHigh;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::GenerateStackCrawl
+ *
+ * DESCRIPTION: Starting with the current PC and A6, generate a list
+ * of active functions.
+ *
+ * PARAMETERS: frameList - reference to the collection to receive
+ * the results.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmPalmOS::GenerateStackCrawl (EmStackFrameList& frameList)
+{
+ // Make sure we have access to all of memory, in case A6 is bogus
+ // or used for some purpose other than frame links.
+
+ CEnableFullAccess munge;
+
+ // Clear out the stack crawl list.
+
+ frameList.clear ();
+
+ // Push the initial stack frame onto the stack. This consists
+ // of the current PC and A6 values.
+
+ EmStackFrame frame;
+
+ frame.fAddressInFunction = m68k_getpc ();
+ frame.fA6 = m68k_areg (regs, 6);
+
+ frameList.push_back (frame);
+
+ // If A6 is odd or not in the current stack, stop the stack crawl.
+
+ if (::IsOdd (frame.fA6) || !EmPalmOS::IsInStack (frame.fA6))
+ return;
+
+ while (1)
+ {
+ emuptr oldA6 = frame.fA6;
+
+ // Get the previous A6 and function from the stack.
+
+ frame.fAddressInFunction = EmMemGet32 (oldA6 + 4);
+ frame.fA6 = EmMemGet32 (oldA6);
+
+ // If A6 is odd or not in the current stack, stop the stack crawl.
+
+ if (::IsOdd (frame.fA6) || !EmPalmOS::IsInStack (frame.fA6))
+ return;
+
+ // If the new A6 is not greater than the old A6, stop
+ // the stack crawl.
+
+ if (frame.fA6 <= oldA6)
+ return;
+
+ // If the return address is not valid, let's take a chance
+ // that what's on the stack is <A6> <SR> <return address>.
+ // We'd see this sequence if an exception has occurred and
+ // and exception frame is on the stack.
+
+ if (!EmMemCheckAddress (frame.fAddressInFunction, 2))
+ {
+ frame.fAddressInFunction = EmMemGet32 (oldA6 + 6);
+
+ // If the return address still doesn't look valid,
+ // stop the stack crawl.
+
+ if (!EmMemCheckAddress (frame.fAddressInFunction, 2))
+ {
+ return;
+ }
+ }
+
+ // Everything looks OK, push this information onto our stack.
+
+ frameList.push_back (frame);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmPalmOS::PrefsChanged
+// ---------------------------------------------------------------------------
+// Respond to a preference change.
+
+static void PrvRespondToPrefsChange (PrefKeyType prefKey)
+{
+ if (EmPatchState::UIInitialized ())
+ {
+ if (::PrefKeysEqual (prefKey, kPrefKeyReportStrictIntlChecks) && EmPatchMgr::IntlMgrAvailable ())
+ {
+ Preference<Bool> pref (kPrefKeyReportStrictIntlChecks, false);
+ ::IntlSetStrictChecks (*pref);
+ }
+
+ if (::PrefKeysEqual (prefKey, kPrefKeyReportOverlayErrors))
+ {
+ Preference<Bool> pref (kPrefKeyReportOverlayErrors, false);
+ (void) ::FtrSet (omFtrCreator, omFtrShowErrorsFlag, *pref);
+ }
+ }
+}
+
+
+void EmPalmOS::PrefsChanged (PrefKeyType prefKey, void*)
+{
+ if (gSession)
+ {
+#if HAS_OMNI_THREAD
+ if (gSession->InCPUThread ())
+ {
+ ::PrvRespondToPrefsChange (prefKey);
+ }
+ else
+#endif
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+
+ ::PrvRespondToPrefsChange (prefKey);
+ }
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleTrap15
+ *
+ * DESCRIPTION: Handle a trap. Traps are of the format TRAP $F / $Axxx.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleTrap15 (ExceptionNumber)
+{
+ return EmPalmOS::HandleSystemCall (true);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Software::HandleJSR
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleJSR (emuptr oldpc, emuptr dest)
+{
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ StDisableMemoryCycleCounting stopper;
+ Boolean skipProfiling = false;
+
+ // In multi-segmented application generated by CodeWarrior,
+ // inter-segment function calls are implemented by JSR'ing
+ // to a jump table entry. This jump table entry contains
+ // a JMP to the final location. Detect this case and emit
+ // a function entry record for the final location, not the
+ // jump table entry.
+
+ const uint16 kOpcode_JMP_Abs32 = 0x4EF9;
+ uint8* realMem = EmMemGetRealAddress (dest);
+
+ if (EmMemDoGet16 (realMem) == kOpcode_JMP_Abs32)
+ {
+ dest = EmMemDoGet32 (realMem + 2);
+ }
+ else
+ {
+ //---------------------------------------------------------------------
+ // We don't want to process JSRs to a switch statement. Currently
+ // CodeWarrior generates a switch statement block like this:
+ // MOVE.L (A7)+,A0 | 205F
+ // MOVE.L A0,A1 | 2248
+ // ADD.W (A0)+,A1 | D2D8
+ // CMP.W (A0)+,D0 | B058
+ // BGE.S *+$0004 ; 10C20F5C | 6C02
+ // JMP (A1) | 4ED1
+ // CMP.W (A0)+,D0 | B058
+ // BLE.S *+$0004 ; 10C20F62 | 6F02
+ // JMP (A1) | 4ED1
+ // MOVE.W (A0)+,D1 | 3218
+ // CMP.W (A0)+,D0 | B058
+ // BNE.S *+$0006 ; 10C20F6C | 6604
+ // ADD.W (A0),A0 | D0D0
+ // JMP (A0) | 4ED0
+ // ADDQ.W #$02,A0 | 5448
+ // DBF D1,*-$000A ; 10C20F64 | 51C9 FFF4
+ // JMP (A1) | 4ED1
+ //---------------------------------------------------------------------
+ skipProfiling = (EmMemDoGet32 (realMem) == 0x205F2248)
+ && (EmMemDoGet32 (realMem + 4) == 0xD2D8B058)
+ && (EmMemDoGet32 (realMem + 8) == 0x6C024ED1);
+ }
+
+ if (!skipProfiling)
+ {
+ ProfileFnEnter (dest, oldpc);
+ }
+ }
+#endif
+
+#if LOG_FUNCTION_CALLS
+// char fromName[80];
+ char toName[80];
+
+// ::FindFunctionName (oldpc, fromName, NULL, NULL, 80);
+ ::FindFunctionName (dest, toName, NULL, NULL, 80);
+
+ EmStackFrameList stackCrawl;
+ EmPalmOS::GenerateStackCrawl (stackCrawl);
+
+ string dots ("|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-");
+ dots.resize (stackCrawl.size ());
+
+// LogAppendMsg (">>> %s --> %s", fromName, toName);
+// LogAppendMsg ("--- System Call 0xA08D: %s", fromName, toName);
+ LogAppendMsg ("--- Function Call: %s%s", dots.c_str (), toName);
+#endif
+
+ return false; // We didn't completely handle it; do default handling.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleJSR_Ind
+ *
+ * DESCRIPTION: Check for SYS_TRAP_FAST calls.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleJSR_Ind (emuptr oldpc, emuptr dest)
+{
+ Bool handledIt = false; // Default to calling ROM.
+
+ // inline asm SysTrapFast(Int trapNum)
+ // {
+ // MOVE.L struct(LowMemType.fixed.globals.sysDispatchTableP), A1
+ // MOVE.L ((trapNum-sysTrapBase)*4)(A1), A1
+ // JSR (A1) // call it
+ // }
+ //
+ // #define SYS_TRAP_FAST(trapNum)
+ // FIVEWORD_INLINE(
+ // 0x2278, 0x0122,
+ // 0x2269, (trapNum-sysTrapBase)*4,
+ // 0x4e91)
+
+ uint8* realMem = EmMemGetRealAddress (oldpc);
+ if (EmMemDoGet16 (realMem) == 0x4e91 &&
+ EmMemDoGet16 (realMem - 4) == 0x2269 &&
+ EmMemDoGet16 (realMem - 8) == 0x2278)
+ {
+ handledIt = EmPalmOS::HandleSystemCall (false);
+ }
+ else
+ {
+ if (gBigROMEntry == EmMemNULL)
+ {
+ emuptr base = EmBankROM::GetMemoryStart ();
+
+ // Check every romDelta (4K) for up to maxBigROMOffset
+ //(256K) till we find the "Big" ROM
+
+ const UInt32 romDelta = 4 * 1024L; // BigROM starts on a 4K boundary
+ const UInt32 maxBigROMOffset = 256 * 1024L; // Give up looking past here
+ UInt16 loops = maxBigROMOffset / romDelta; // How many loops to do
+ emuptr bP = base + romDelta;
+
+ while (loops--)
+ {
+ // Ignore older card headers that might have been
+ // programmed in at a lower address (hdrVersion < 3)
+
+ EmAliasCardHeaderType<PAS> cardHdr (bP);
+
+ UInt32 signature = cardHdr.signature;
+ UInt16 hdrVersion = cardHdr.hdrVersion;
+
+ if (signature == sysCardSignature && hdrVersion >= 3)
+ {
+ gBigROMEntry = cardHdr.resetVector;
+ break;
+ }
+
+ bP += romDelta;
+ }
+
+ // See if we found it (may have hdrVersion < 3)
+
+ if (gBigROMEntry == EmMemNULL)
+ {
+ EmAliasCardHeaderType<PAS> smallCardHdr (base);
+ UInt32 bigROMOffset;
+
+ if (smallCardHdr.hdrVersion == 2)
+ {
+ bigROMOffset = smallCardHdr.bigROMOffset & 0x000FFFFF;
+ }
+ else
+ {
+ bigROMOffset = 0x3000;
+ }
+
+ EmAliasCardHeaderType<PAS> bigCardHdr (base + bigROMOffset);
+ gBigROMEntry = bigCardHdr.resetVector;
+ }
+ }
+
+ if (dest == gBigROMEntry)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleReset (kResetSys);
+ }
+ }
+
+ return handledIt;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleLINK
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::HandleLINK (int /*linkSize*/)
+{
+#if 0
+ Preference<bool> pref (kPrefKeyFillStack);
+ if (*pref && linkSize < 0)
+ {
+ uae_memset (gCPU->GetSP (), 0xD5, -linkSize);
+ }
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleRTS
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleRTS (emuptr dest)
+{
+ UNUSED_PARAM (dest);
+
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ StDisableMemoryCycleCounting stopper;
+
+ ProfileFnExit (dest, gCPU->GetPC () + 2);
+ }
+#endif
+
+#if LOG_FUNCTION_CALLS
+ char fromName[80];
+ char toName[80];
+
+ ::FindFunctionName (gCPU->GetPC(), fromName, NULL, NULL, 80);
+ ::FindFunctionName (dest, toName, NULL, NULL, 80);
+
+ LogAppendMsg ("<<< %s --> %s", fromName, toName);
+#endif
+
+#if 0
+ char fromName[80];
+ ::FindFunctionName (gCPU->GetPC(), fromName, NULL, NULL, 80);
+
+ if (strcmp (fromName, "HwrADC") == 0)
+ {
+ // A7 points to return address
+ // A7 + 4 points to UInt16 (command)
+ // A7 + 6 points to pointer to result
+
+ enum hwrADCCmdEnum
+ {
+ hwrADCCmdReadXYPos=0, // Read Digitizer X & Y Positions
+ hwrADCCmdReadBatt, // Read Battery Level
+ hwrADCCmdReadAux, // Read Battery Level
+ hwrADCCmdReadTemp, // Read Temperature
+ hwrADCCmdReadXPos, // Read Digitizer X Position
+ hwrADCCmdReadYPos, // Read Digitizer Y Position
+ hwrADCCmdReadZPos, // Read Digitizer Z Position (Pressure)
+ hwrADCCmdReadXYZPos, // Read Digitizer X, Y & Z Positions
+ hwrADCCmdPenIRQOn // Enable Pen IRQ
+ } ;
+
+ struct HwrADCReadResultType
+ {
+ UInt16 reserved1; //mVolts; // level in millivolts (2500 = 2.5 volts)
+ UInt16 abs; // absolute level (0 -> 255)
+ UInt16 aux; // absolute level (0 -> 255)
+ };
+
+ const char* text[] =
+ {
+ "hwrADCCmdReadXYPos",
+ "hwrADCCmdReadBatt",
+ "hwrADCCmdReadAux",
+ "hwrADCCmdReadTemp",
+ "hwrADCCmdReadXPos",
+ "hwrADCCmdReadYPos",
+ "hwrADCCmdReadZPos",
+ "hwrADCCmdReadXYZPos",
+ "hwrADCCmdPenIRQOn",
+ "unknown"
+ };
+
+ UInt16 cmd = EmMemGet16 (gCPU->GetSP () + 4);
+ emuptr ptr = EmMemGet32 (gCPU->GetSP () + 6);
+ UInt16 reserved1 = EmMemGet16 (ptr + 0);
+ UInt16 abs = EmMemGet16 (ptr + 2);
+ UInt16 aux = EmMemGet16 (ptr + 4);
+
+ LogAppendMsg ("HwrADC (%s), reserved1 = 0x%04X, abs = 0x%04X, aux = 0x%04X",
+ text[cmd], (int) reserved1, (int) abs, (int) aux);
+ }
+ else if (strcmp (fromName, "HwrDockStatus") == 0)
+ {
+ UInt16 result = m68k_dreg (regs, 0);
+ LogAppendMsg ("HwrDockStatus result = 0x%04X",(int) result);
+ }
+#endif
+
+ return false; // We didn't completely handle it; do default handling.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleRTE
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleRTE (emuptr dest)
+{
+ UNUSED_PARAM (dest);
+
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ ProfileInterruptExit (dest);
+ }
+#endif
+
+#if LOG_FUNCTION_CALLS
+ char fromName[80];
+ char toName[80];
+
+ ::FindFunctionName (gCPU->GetPC(), fromName, NULL, NULL, 80);
+ ::FindFunctionName (dest, toName, NULL, NULL, 80);
+
+ LogAppendMsg ("<<< %s --> %s", fromName, toName);
+#endif
+
+ return false; // We didn't completely handle it; do default handling.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleNewPC
+ *
+ * DESCRIPTION: The PC is about to be changed via a JSR, BSR, RTS, or
+ * RTE. Check that the new address appears to be valid.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::HandleNewPC (emuptr dest)
+{
+ // If the address is odd, then it's bad.
+
+ if ((dest & 1) != 0)
+ Errors::ReportErrInvalidPC (dest, kOddAddress);
+
+// if (!EmPatchState::UIInitialized ())
+// return;
+
+ // Ensure that the PC is in ROM or RAM.
+
+ EmMemPutFunc longSetter = EmMemGetBank (dest).lput;
+
+ if (longSetter == EmBankROM::SetLong || longSetter == EmBankFlash::SetLong)
+ {
+ if (!EmBankROM::ValidAddress (dest, 2))
+ {
+ Errors::ReportErrInvalidPC (dest, kNotInCodeSegment);
+ }
+ }
+ else if (longSetter == EmBankSRAM::SetLong)
+ {
+ }
+ else if (longSetter == EmBankDRAM::SetLong)
+ {
+ if (dest < (256 + 693 * 4) /*MetaMemory::GetSysGlobalsEnd ()*/)
+ {
+ Errors::ReportErrInvalidPC (dest, kNotInCodeSegment);
+ }
+ }
+ else if (longSetter == EmBankMapped::SetLong)
+ {
+ if (!EmBankMapped::ValidAddress (dest, 2))
+ {
+ Errors::ReportErrInvalidPC (dest, kUnmappedAddress);
+ }
+ }
+ else
+ {
+ Errors::ReportErrInvalidPC (dest, kUnmappedAddress);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleNewSP
+ *
+ * DESCRIPTION: !!! This operation slows down Gremlins by about 10%; it
+ * should be sped up or made an option.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPalmOS::HandleNewSP (EmStackChangeType type)
+{
+ if (type == kStackPointerChanged)
+ {
+ CheckStackPointerAssignment ();
+ }
+ else if (type == kStackPointerDecremented)
+ {
+ CheckStackPointerDecrement ();
+ }
+ else if (type == kStackPointerKernelStackHack)
+ {
+ CheckKernelStack ();
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPalmOS::HandleSystemCall
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmPalmOS::HandleSystemCall (Bool fromTrap)
+{
+ // ======================================================================
+ // First things first: if we need to break execution on the next call
+ // to a system function, make sure that happens.
+ // ======================================================================
+
+ EmAssert (gSession);
+ EmAssert (gCPU68K);
+
+#if HAS_PROFILING
+ int oldProfilingCounted = gProfilingCounted;
+ gProfilingCounted = false;
+#endif
+
+ // If the system call is being made by a TRAP $F, the PC has already
+ // been bumped past the opcode. If being made with a JSR via the
+ // SYS_TRAP_FAST macro, the PC has not been adjusted. Determine a
+ // "pcAdjust" value that allows us to get back to the start of the
+ // instruction that got us here.
+
+ int pcAdjust = fromTrap ? 2 : 0;
+
+ if (!gSession->IsNested () && gSession->GetBreakOnSysCall ())
+ {
+ CEnableFullAccess munge;
+
+ // Check the memory manager semaphore. If we're stopping on a
+ // system call, it's most likely that we want to make some nested
+ // Palm OS calls. Some of those calls may try to acquire the
+ // memory manager semaphore. Therefore, make sure it's available.
+
+ UInt32 memSemaphoreIDP = EmLowMem_GetGlobal (memSemaphoreID);
+ EmAliascj_xsmb<PAS> memSemaphoreID (memSemaphoreIDP);
+
+ if (memSemaphoreID.xsmuse == 0)
+ {
+ // Check the current task. We don't want to break on a system
+ // call if we're in the background. If we're breaking on a
+ // system call, it's likely because some other part of Poser
+ // wants to make OS calls. Occassionally, those OS calls result
+ // in trying to switch to the UI task (see, for example,
+ // PrvEditCardOptionsOK). If we're already in the UI task, then
+ // that's OK, but if we're in a background task, an attempted
+ // switch to the UI task will fail, due to Poser turning off
+ // interrupts when it makes OS calls.
+
+ SysKernelInfoType taskInfo;
+ taskInfo.selector = sysKernelInfoSelCurTaskInfo;
+
+ Err err = ::SysKernelInfo (&taskInfo);
+ if (err == errNone)
+ {
+ if (taskInfo.param.task.tag == 'psys')
+ {
+ gCPU->SetPC (gCPU->GetPC () - pcAdjust);
+ gSession->ScheduleSuspendSysCall ();
+
+#if HAS_PROFILING
+ gProfilingCounted = oldProfilingCounted;
+#endif
+
+ // Return true to say that everything has been handled.
+
+ return true;
+ }
+
+ // If we took a stab at this and didn't find that we were
+ // in the UI task, then call EvtWakeup. If our context is
+ // one where an application has called EvtGetEvent with a
+ // "sleep forever" timeout, then the current task will be
+ // 'AMX ', and will stay that way. Calling EvtWakeup will
+ // force an eventual switch to the UI task.
+ //
+ // Note that we wake-up the UI thread only if we're in the
+ // root AMX thread. This prevents us from trying to call
+ // it when the Palm context is one where a background task
+ // is the current task. It's possible for that task to be
+ // sleeping or something (the example we ran into was with
+ // a background task calling SysDelay). EvtWakeup will try
+ // to switch to the UI task, but will not return until the
+ // UI task switches back to the background task. That will
+ // never happen because interrupts are turned off during
+ // all Poser calls into the OS (such as the call to
+ // EvtWakeup). Thus, the only safe places to call
+ // EvtWakeup are in the UI or AMX tasks.
+
+ else if (taskInfo.param.task.tag == 0x414d5800)
+ {
+ ::EvtWakeup ();
+ }
+ }
+ }
+ }
+
+
+ // ======================================================================
+ // Determine what ROM function is about to be called, and determine
+ // the method by which it is being called.
+ // ======================================================================
+
+ SystemCallContext context;
+ Bool gotFunction = GetSystemCallContext (
+ gCPU->GetPC () - pcAdjust, context);
+
+
+ // ======================================================================
+ // Validate the address for the ROM function we're about to call.
+ // ======================================================================
+
+ if (!gotFunction)
+ {
+#if HAS_PROFILING
+ gProfilingCounted = oldProfilingCounted;
+#endif
+
+ if (context.fError == kError_UnimplementedTrap)
+ {
+ Errors::ReportErrUnimplementedTrap (context);
+ }
+ else if (context.fError == kError_InvalidLibraryRefNum)
+ {
+ Errors::ReportErrInvalidRefNum (context);
+ }
+
+ // We should never get here. context.fError should always equal
+ // one of those two error codes, and those two functions we call
+ // should never return (they should throw exceptions).
+
+ EmAssert (false);
+ }
+
+
+ // ======================================================================
+ // Record what function we're calling.
+ // ======================================================================
+
+ if (!gSession->IsNested () && LogSystemCalls ())
+ {
+ char name [sysPktMaxNameLen];
+
+ strcpy (name, ::GetTrapName (context, true));
+
+ EmStackFrameList stackCrawl;
+ EmPalmOS::GenerateStackCrawl (stackCrawl);
+
+ string dots ("|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-");
+ dots.resize (stackCrawl.size ());
+
+ LogAppendMsg ("--- System Call 0x%04X: %s%s.", (long) context.fTrapWord, dots.c_str (), name);
+ }
+
+
+ // ======================================================================
+ // Let the debugger have a crack at it. It may want to do a "break
+ // on ATrap" thingy. If so, it will return true. Otherwise,
+ // if no action is necessary, it will return false.
+ // ======================================================================
+
+ if (!gSession->IsNested () && Debug::HandleSystemCall (context))
+ {
+ // Return true to say that everything has been handled.
+
+#if HAS_PROFILING
+ gProfilingCounted = oldProfilingCounted;
+#endif
+
+ return true;
+ }
+
+
+ // ======================================================================
+ // Check for functions unsupported on ARM. ProscribedFunction
+ // returns true if function is not supported.
+ // ======================================================================
+
+ if ((Memory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (context.fPC))
+ && ::ProscribedFunction (context))
+ {
+ gSession->ScheduleDeferredError (
+ new EmDeferredErrProscribedFunction (context));
+ }
+
+
+ // ======================================================================
+ // Tell the profiler that we're entering a function.
+ // ======================================================================
+#if HAS_PROFILING
+ // This ProfileFnEnter will show the function call within the trap handler
+ // exception, which gives us a nice breakdown of which traps are being
+ // called and frequency.
+
+ if (gProfilingEnabled && context.fViaTrap)
+ {
+ ProfileFnEnter (context.fTrapWord, context.fNextPC);
+ }
+#endif
+
+
+ // ======================================================================
+ // If this trap is patched, let the patch handler handle the patch.
+ // ======================================================================
+
+ CallROMType result = EmPatchMgr::HandleSystemCall (context);
+
+
+ // ======================================================================
+ // If we completely handled the function in head and tail patches, tell
+ // the profiler that we exited the function and get out of here.
+ // ======================================================================
+
+ if (result == kSkipROM)
+ {
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ ProfileFnExit (context.fNextPC, context.fTrapWord);
+ }
+#endif
+
+ // Set the PC to point past the instructions that got us here.
+
+ gCPU->SetPC (context.fNextPC);
+
+ // Return true to say that everything has been handled.
+
+#if HAS_PROFILING
+ gProfilingCounted = oldProfilingCounted;
+#endif
+
+ return true;
+ }
+
+
+ // ======================================================================
+ // If we're profiling, don't dispatch to the ROM function outselves.
+ // We want the ROM to do it so that we get accurate dispatch times.
+ // ======================================================================
+
+#if HAS_PROFILING
+ // Don't do native dispatching if the profiler is on!
+
+ if (gProfilingEnabled)
+ {
+ // Return false to do default exception handler processing.
+
+ gProfilingCounted = oldProfilingCounted;
+
+ return false;
+ }
+#endif
+
+#if HAS_PROFILING
+ gProfilingCounted = oldProfilingCounted;
+#endif
+
+ // ======================================================================
+ // Otherwise, let's run the trap dispatcher native. This gives
+ // us about a 10-20% speed-up.
+ // ======================================================================
+
+ // Push the return address onto the stack. Subtract 4 from the stack,
+ // and then store the appropriate return address.
+
+ gCPU->SetSP (gCPU->GetSP () - 4);
+ CHECK_STACK_POINTER_DECREMENT ();
+ EmMemPut32 (gCPU->GetSP (), context.fNextPC);
+
+ // Change to the new PC. If possible, use the fully dereferenced destination
+ // address. This speeds things up for libraries and sub-dispatched managers
+ // (like Floating Point, International, Text, and Overlay managers).
+
+ emuptr destPC = context.fDestPC2;
+ if (Debug::BreakpointInstalled ())
+ {
+ destPC = context.fDestPC1;
+ }
+
+ EmPalmOS::HandleNewPC (destPC);
+ gCPU->SetPC (destPC);
+
+ // Return true to say that everything has been handled.
+
+ return true;
+}
+
+
+
+
+EmStream& operator << (EmStream& s, const StackRange& range)
+{
+ s << range.fBottom;
+ s << range.fTop;
+ s << range.fLowWaterMark;
+
+ return s;
+}
+
+EmStream& operator >> (EmStream& s, StackRange& range)
+{
+ s >> range.fBottom;
+ s >> range.fTop;
+ s >> range.fLowWaterMark;
+
+ return s;
+}
diff --git a/SrcShared/EmPalmOS.h b/SrcShared/EmPalmOS.h
new file mode 100644
index 0000000..56f57ad
--- /dev/null
+++ b/SrcShared/EmPalmOS.h
@@ -0,0 +1,110 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPalmOS_h
+#define EmPalmOS_h
+
+#include "EmCPU68K.h" // ExceptionNumber
+#include "EmStructs.h" // EmStackFrameList
+#include "PreferenceMgr.h" // PrefKeyType
+
+#pragma mark StackRange
+
+struct StackRange
+{
+ StackRange () :
+ fTop (0),
+ fLowWaterMark (0),
+ fBottom (0)
+ {}
+ StackRange (const StackRange& other) :
+ fTop (other.fTop),
+ fLowWaterMark (other.fLowWaterMark),
+ fBottom (other.fBottom)
+ {}
+ StackRange (emuptr bottom, emuptr top) :
+ fTop (top),
+ fLowWaterMark (top),
+ fBottom (bottom)
+ {}
+
+ bool operator==(const StackRange& other) const
+ { return fBottom == other.fBottom; }
+
+ bool operator!=(const StackRange& other) const
+ { return fBottom != other.fBottom; }
+
+ bool operator<(const StackRange& other) const
+ { return fBottom < other.fBottom; }
+
+ bool operator>(const StackRange& other) const
+ { return fBottom > other.fBottom; }
+
+ // (Order these this way so that they look correct in a debugger)
+
+ emuptr fTop;
+ emuptr fLowWaterMark;
+ emuptr fBottom;
+};
+
+typedef vector<StackRange> StackList;
+
+class EmStream;
+EmStream& operator << (EmStream&, const StackRange&);
+EmStream& operator >> (EmStream&, StackRange&);
+
+class EmPalmChunk;
+class SessionFile;
+
+class EmPalmOS
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ public:
+ static void CheckStackPointerAssignment (void);
+ static void CheckStackPointerDecrement (void);
+ static void CheckKernelStack (void);
+ static void RememberStackChunk (const EmPalmChunk&);
+ static void RememberBootStack (void);
+ static void RememberKernelStack (void);
+ static void RememberStackRange (const StackRange&);
+ static void SetCurrentStack (const StackRange&);
+ static void ForgetStack (emuptr);
+ static void ForgetStacksIn (emuptr, uint32);
+ static StackRange GetBootStack (void);
+ static Bool IsInStack (emuptr);
+ static Bool IsInStackBlock (emuptr);
+ static void GenerateStackCrawl (EmStackFrameList& frameList);
+ static void PrefsChanged (PrefKeyType, void*);
+
+ protected:
+ static Bool HandleTrap15 (ExceptionNumber);
+ static Bool HandleJSR (emuptr oldPC, emuptr dest);
+ static Bool HandleJSR_Ind (emuptr oldPC, emuptr dest);
+ static void HandleLINK (int linkSize);
+ static Bool HandleRTE (emuptr dest);
+ static Bool HandleRTS (emuptr dest);
+ static void HandleNewPC (emuptr dest);
+ static void HandleNewSP (EmStackChangeType);
+
+ private:
+ static Bool HandleSystemCall (Bool fromTrap);
+};
+
+#endif /* EmPalmOS_h */
+
diff --git a/SrcShared/EmPalmStructs.cpp b/SrcShared/EmPalmStructs.cpp
new file mode 100644
index 0000000..112912e
--- /dev/null
+++ b/SrcShared/EmPalmStructs.cpp
@@ -0,0 +1,100 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPalmStructs.h"
+
+#if __profile__
+#pragma profile off
+#endif
+
+#undef INLINE_
+#define INLINE_
+
+#if !INLINE_SCALAR_IMPLEMENTATION
+
+FOR_EACH_SCALAR_1 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_2 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_3 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_4 (DEFINE_SCALAR_CLASSES)
+
+#endif
+
+FOR_EACH_STRUCT_1 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_2 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_3 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_4 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_5 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_6 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_7 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_8 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_9 (DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_10(DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_11(DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_12(DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_13(DEFINE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_14(DEFINE_STRUCT_CLASSES)
+
+/*
+ Note: Under VC++, the following INSTANTIATE macros cause the compiler to complain
+ that the <LAS> types are already instantiated, possibly beccause of the following
+ operators in the Proxy classes:
+
+ EmAlias##type<LAS> operator[] (int);
+ const EmAlias##type<LAS> operator[] (int) const;
+
+ However, merely taking out the "template class EmAlias##type<LAS>" results in a
+ lot of missing function errors during the link stage. Therefore, we inhibit the
+ compiler warnings with a #pragma in EmCommonWin.h.
+*/
+
+#define INSTANTIATE_SCALAR_CLASS(type, asType) \
+ template class EmAlias##type<LAS>; \
+ template class EmAlias##type<PAS>;
+
+#define INSTANTIATE_STRUCT_CLASS(type, size, FOR_EACH_FIELD) \
+ template class EmAlias##type<LAS>; \
+ template class EmAlias##type<PAS>;
+
+
+FOR_EACH_SCALAR_1 (INSTANTIATE_SCALAR_CLASS)
+FOR_EACH_SCALAR_2 (INSTANTIATE_SCALAR_CLASS)
+FOR_EACH_SCALAR_3 (INSTANTIATE_SCALAR_CLASS)
+FOR_EACH_SCALAR_4 (INSTANTIATE_SCALAR_CLASS)
+
+FOR_EACH_STRUCT_1 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_2 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_3 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_4 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_5 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_6 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_7 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_8 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_9 (INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_10(INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_11(INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_12(INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_13(INSTANTIATE_STRUCT_CLASS)
+FOR_EACH_STRUCT_14(INSTANTIATE_STRUCT_CLASS)
+
+
+int BadGetter (void)
+{
+ EmAssert (false);
+ return 0;
+}
+
+void BadSetter (void)
+{
+ EmAssert (false);
+}
diff --git a/SrcShared/EmPalmStructs.h b/SrcShared/EmPalmStructs.h
new file mode 100644
index 0000000..b066be4
--- /dev/null
+++ b/SrcShared/EmPalmStructs.h
@@ -0,0 +1,1136 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPalmStructs_h
+#define EmPalmStructs_h
+
+#include "EmMemory.h" // EmMemGet8, EmMemPut8, EmMem_memcpy, etc.
+#include "EmPalmStructs.i"
+#include "HostControl.h" // HostControlSelectorType, etc.
+
+#include <stddef.h> // ptrdiff_t
+
+/*
+ The Palm OS Emulator interacts closely with legacy Palm OS data
+ structures. These data structures are laid out by the compilers
+ designed for the Palm OS. However, the Palm OS Emulator -- which needs
+ to access these structures at times -- is NOT necessarily compiled with
+ a compiler that lays out the structures in a compatible fashion. Thus,
+ if the emulator needs to muck with, say, a variable of EventType, it
+ can't merely create one and have at it. Nor can it get a pointer to
+ one, cast it to an EventType*, and have at it. There's just no guarantee
+ that the compiler used to build Poser will put the fields in the same
+ places that the Palm OS expects it, or that the architecture will
+ support accessing fields in those places.
+
+ To solve this problem, for each Palm OS struct Poser wants to
+ manipulate, it creates two parallel "Rep" classes: an "Alias" class and
+ a "Proxy" class. These Rep classes appear and act as much as the
+ original struct as possible. However, behind the scenes C++ magic
+ allows Poser to access the data in a manner that is guaranteed to be
+ binary-compatible with the Palm OS structs, regardless of what platform
+ it's running on and what compiler it was built with.
+
+ Aliases and Proxies are very similar to each other in the way the user
+ interacts with them. The have fields which, when used as an lvalue,
+ will store the proferred data in the correct memory location and with
+ the correct endianness and, when used as an rvalue, will produce the
+ necessary value, fetching the data from the correct memory location and
+ byteswapping it if necessary.
+
+ Aliases and Proxies differ in their backing store. An Alias class is
+ initialized with a pointer to some buffer that already exists. This
+ buffer may exist as a Poser variable or as a buffer in the emulated Palm
+ OS space. All data accesses are made against that provided buffer.
+ When an Alias is created from another Alias, they both end up pointing
+ to the same space. If one Alias is used to modify the buffer, the
+ second Alias will also reflect that change.
+
+ Proxies, on the other hand, are more stand-alone. They provide their
+ own buffers as a backing store. Copying one Proxy to another or
+ creating one Proxy from another results in a new independent object.
+ After the copy has been made, modifying one object does not affect the
+ second.
+
+ Aliases are not only handy for wrapping a chunk of data that was
+ generated elsewhere, but they are also essential for providing an "array
+ operator" (that is, "operator[]") for both kinds of Rep classes. That
+ operator returns an Alias that points to the right location in memory.
+ If we didn't have Aliases -- for instance, we only had Proxies -- then
+ the Proxy returned by operator[] could not be used to modify the backing
+ store, since it's independent of the backing store used by the object
+ that created it.
+
+ Proxies, on the other hand, are handy when you need to treat an object
+ more like a real-live struct. Proxies can be copied and put into
+ STL-like collections without having to worry about the lifetime of the
+ object they were created from.
+
+ Let's look at the Alias class for EventType:
+
+ template <class A>
+ class EmAliasEventType
+ {
+ public:
+ typedef typename A::ptr_type ptr_type;
+
+ EmAliasEventType (ptr_type);
+ EmAliasEventType (const EmAliasEventType&);
+
+ ptr_type GetPtr (void) const;
+ static size_t GetSize (void);
+
+ EmAliasEventType<A>& operator= (const EmAliasEventType<A>&);
+ EmAliasEventType<A> operator[] (int);
+
+ private:
+ EmAliasEventType (void);
+
+ EmAliasEventType<A>& operator= (const bool);
+ EmAliasEventType<A>& operator= (const char);
+ EmAliasEventType<A>& operator= (const unsigned char);
+ EmAliasEventType<A>& operator= (const unsigned short);
+ EmAliasEventType<A>& operator= (const unsigned int);
+ EmAliasEventType<A>& operator= (const unsigned long);
+ EmAliasEventType<A>& operator= (const signed char);
+ EmAliasEventType<A>& operator= (const signed short);
+ EmAliasEventType<A>& operator= (const signed int);
+ EmAliasEventType<A>& operator= (const signed long);
+ EmAliasEventType<A>& operator= (const void*);
+
+ ptr_type fPtr;
+
+ public:
+ EmAliasInt16<A> eType;
+ EmAliasBoolean<A> penDown;
+ EmAliasUInt8<A> tapCount;
+ EmAliasInt16<A> screenX;
+ EmAliasInt16<A> screenY;
+ EmAliasEventTypeData<A> data;
+ };
+
+ This is a template class parameterized with a data accessor. This data
+ accessor has static methods for reading and writing 1-, 2-, and 4-byte
+ values. In this module, we define two such accessors. One, called LAS
+ for Local Address Space, accesses Big Endian values in Poser's address
+ space. The second, called PAS for Palm Address Space, accesses Big
+ Endian values in the emulated address space.
+
+ There are two constructors. The first constructor takes a pointer to an
+ appropriately-sized buffer that already exists -- all reads and write
+ take place against that buffer. The second constructor is the copy
+ constructor. It copies the pointer used by the original object. After
+ the copy, if the original object modifies the data in the backing store,
+ the copy with reflect that change, too.
+
+ GetPtr returns the pointer to the buffer backing the struct. The return
+ type of this function is based on the class the proxy class is
+ instantiated with. It is void* if used with LAS, and emuptr if used
+ with PAS.
+
+ GetSize returns the size of the represented struct, in this case
+ EventType, which is 24 bytes long.
+
+ An assignment operator is provided to perform a memberwise copy
+ operation.
+
+ An array operator is provided to return Alias objects that point to the
+ appropriately index location in memory.
+
+ Following these standard methods are the fields. These fields are also
+ Alias classes, initialized with the base pointer passed into the
+ EmAliasEventType constructor plus an appropriate offset.
+
+ Now let's take a look at a Proxy class:
+
+ class EmProxyEventType
+ {
+ public:
+ typedef void ptr_type;
+
+ EmProxyEventType (void);
+ EmProxyEventType (const EmProxyEventType&);
+
+ ptr_type GetPtr (void) const;
+ static size_t GetSize (void);
+
+ EmProxyEventType& operator= (const EmProxyEventType&);
+ EmAliasEventType<LAS> operator[] (int);
+
+ private:
+ EmProxyEventType& operator= (const bool);
+ EmProxyEventType& operator= (const char);
+ EmProxyEventType& operator= (const unsigned char);
+ EmProxyEventType& operator= (const unsigned short);
+ EmProxyEventType& operator= (const unsigned int);
+ EmProxyEventType& operator= (const unsigned long);
+ EmProxyEventType& operator= (const signed char);
+ EmProxyEventType& operator= (const signed short);
+ EmProxyEventType& operator= (const signed int);
+ EmProxyEventType& operator= (const signed long);
+ EmProxyEventType<& operator= (const void*);
+
+ char fLocalData[24];
+
+ public:
+ EmAliasInt16<LAS> eType;
+ EmAliasBoolean<LAS> penDown;
+ EmAliasUInt8<LAS> tapCount;
+ EmAliasInt16<LAS> screenX;
+ EmAliasInt16<LAS> screenY;
+ EmAliasEventTypeData<LAS> data;
+ };
+
+ As you can see, this Proxy class is almost the same as an Alias class.
+ However:
+
+ * Instead of having an fPtr field to hold the pointer to the data
+ buffer, it has an fLocalData field that holds the data itself.
+
+ * There is no constructor that accepts a pointer. Instead, there
+ is a public default constructor.
+
+ * It is not a template class. Since the data is local, it is
+ always accessed in a manner consistant with the LAS accessor.
+
+ * The copy constructor copies the data instead of the pointer.
+
+ There are two sorts of Rep classes: primitive and aggregate. Primitive
+ Rep classes are responsible for the management of simple scalar types.
+ Aggregate Rep classes represent structs, and are composed of other
+ primitive and aggregate Alias classes. The biggest difference between
+ primitive and aggregate Rep classes is the set of assignment operators
+ clients are allowed to call. For instance, you can assign integers to
+ primitive Rep classes, but not to aggregate Rep classes
+
+ EXAMPLE:
+
+ Say you wanted to call void EvtAddEventToQueue (EventType*).
+ You would use EmEventType as follows:
+
+ EmProxyEventType event; // Use local buffer
+
+ event.eType = penDownEvent;
+ event.penDown = true;
+ event.screenX = 100;
+ event.screenY = 100;
+
+ EvtAddEventToQueue((EventType*) event.GetPtr ());
+
+ EFFICIENCY:
+
+ There is some overhead using these classes instead of using structs
+ directly. At the very least, there's an additional level of
+ redirection, as the fields accessed contain pointers to the actual
+ data as opposed to the actual data itself. Additionally, on Little
+ Endian systems, there is the cost of byteswapping on every access.
+ Finally, there is the cost of calling and executing the proxy class
+ constructor.
+
+ In EmPalmStructs.cpp, there are two functions: Test1 and Test2. The
+ first accesses the struct SysPktRPC2Type using the proxy class, the
+ second using the struct directly.
+
+ On the Mac, using CW Pro 5.2 with optimizations on, Test1 is 88
+ bytes, calls an out-of-line constructor, and each field access takes
+ one additional level of indirection. Test2 is 64 bytes. The 24-byte
+ difference is taken up by an additional 4 bytes for each of the
+ assignments, and an additional 12 bytes to call the proxy class's
+ constructor.
+
+ LIMITATIONS:
+
+ * Can't take the adress of an EmFoo. Will get *its* address
+ instead of what you want (the address of the storage). Instead,
+ call GetPtr.
+
+ * Need explicit casts to extract the value in cases where the
+ type is ambigous. Classic case is "printf("%d", my_EmInt)". The
+ object will be pushed onto the stack, not the wrapped integer.
+
+ * Can't take the size of the object. Instead, call GetSize.
+
+ * Can't call offsetof to get field offsets. Instead, call
+ offsetof_<fieldName>. Note that this returns the offset of the most
+ immediate struct. That is, struct1.struct2.offsetof_field()
+ returns the offset from the beginning of struct2 to field.
+ Calling offsetof(StructType1, struct2.field) returns the offset
+ from the beginning of struct1 to the field.
+
+ * Need a way to copy between classes instantiated with different
+ address space objects.
+*/
+
+int BadGetter (void);
+void BadSetter (void);
+
+#if PLATFORM_MAC
+
+#define PUT_BE_LONG(p, v) *(uint32*) p = (v)
+#define PUT_BE_SHORT(p, v) *(uint16*) p = (v)
+#define PUT_BE_BYTE(p, v) *(uint8*) p = (v)
+
+#define GET_BE_LONG(p) (*(uint32*) p)
+#define GET_BE_SHORT(p) (*(uint16*) p)
+#define GET_BE_BYTE(p) (*(uint8*) p)
+
+#else
+
+#define PUT_BE_LONG(p, v) do { \
+ ((unsigned char*)(p))[0] = (unsigned char)(((unsigned long)(v)) >> 24); \
+ ((unsigned char*)(p))[1] = (unsigned char)(((unsigned long)(v)) >> 16); \
+ ((unsigned char*)(p))[2] = (unsigned char)(((unsigned long)(v)) >> 8); \
+ ((unsigned char*)(p))[3] = (unsigned char)(((unsigned long)(v)) >> 0); \
+ } while(0)
+
+#define PUT_BE_SHORT(p, v) do { \
+ ((unsigned char*)(p))[0] = (unsigned char)(((unsigned short)(v)) >> 8); \
+ ((unsigned char*)(p))[1] = (unsigned char)(((unsigned short)(v)) >> 0); \
+ } while(0)
+
+#define PUT_BE_BYTE(p, v) do { \
+ ((unsigned char*)(p))[0] = (unsigned char)(v); \
+ } while(0)
+
+#define GET_BE_LONG(p) (unsigned long)(\
+ (((unsigned long)((unsigned char*)(p))[0]) << 24) | \
+ (((unsigned long)((unsigned char*)(p))[1]) << 16) | \
+ (((unsigned long)((unsigned char*)(p))[2]) << 8) | \
+ (((unsigned long)((unsigned char*)(p))[3]) << 0) \
+ )
+
+#define GET_BE_SHORT(p) (unsigned short)(\
+ (((unsigned short)((unsigned char*)(p))[0]) << 8) | \
+ (((unsigned short)((unsigned char*)(p))[1]) << 0) \
+ )
+
+#define GET_BE_BYTE(p) (unsigned char)(\
+ (((unsigned char)((unsigned char*)(p))[0]) << 0) \
+ )
+
+#endif
+
+
+// Provide methods for getting and setting Big Endian data in Local Address Space
+
+class LAS
+{
+ public:
+ typedef void* ptr_type;
+
+ inline static uint8 GetByte (ptr_type p) { return (uint8) GET_BE_BYTE (p); }
+ inline static uint16 GetWord (ptr_type p) { return (uint16) GET_BE_SHORT (p); }
+ inline static uint32 GetLong (ptr_type p) { return (uint32) GET_BE_LONG (p); }
+ inline static void PutByte (ptr_type p, const uint8 v) { PUT_BE_BYTE (p, v); }
+ inline static void PutWord (ptr_type p, const uint16 v) { PUT_BE_SHORT (p, v); }
+ inline static void PutLong (ptr_type p, const uint32 v) { PUT_BE_LONG (p, v); }
+
+ inline static void BlockCopy (ptr_type d, ptr_type s, size_t len)
+ { memcpy (d, s, len); }
+
+ inline static ptr_type add (ptr_type p, ptrdiff_t diff)
+ { return (ptr_type)(((size_t)p) + diff); }
+ inline static ptrdiff_t diff (ptr_type a, ptr_type b)
+ { return (ptrdiff_t)(((ptrdiff_t)a) - (ptrdiff_t)b); }
+};
+
+
+// Provide methods for getting and setting Big Endian data in Palm Addres Space
+
+class PAS
+{
+ public:
+ typedef emuptr ptr_type;
+
+ inline static uint8 GetByte (ptr_type p) { return (uint8) EmMemGet8 (p); }
+ inline static uint16 GetWord (ptr_type p) { return (uint16) EmMemGet16 (p); }
+ inline static uint32 GetLong (ptr_type p) { return (uint32) EmMemGet32 (p); }
+ inline static void PutByte (ptr_type p, const uint8 v) { EmMemPut8 (p, v); }
+ inline static void PutWord (ptr_type p, const uint16 v) { EmMemPut16 (p, v); }
+ inline static void PutLong (ptr_type p, const uint32 v) { EmMemPut32 (p, v); }
+
+ inline static void BlockCopy (ptr_type d, ptr_type s, size_t len)
+ { EmMem_memcpy (d, s, len); }
+
+ inline static ptr_type add (ptr_type p, ptrdiff_t diff)
+ { return (ptr_type)(((size_t)p) + diff); }
+ inline static ptrdiff_t diff (ptr_type a, ptr_type b)
+ { return (ptrdiff_t)(((ptrdiff_t)a) - (ptrdiff_t)b); }
+};
+
+
+// ======================================================================
+// Macro for creating the class that wraps up simple types.
+// ======================================================================
+
+#define DECLARE_SCALAR_ALIAS(type, asType) \
+ \
+ template <class A> \
+ class EmAlias##type \
+ { \
+ public: \
+ typedef typename A::ptr_type ptr_type; \
+ \
+ EmAlias##type (ptr_type); \
+ EmAlias##type (const EmAlias##type<A>&); \
+ \
+ ptr_type GetPtr (void) const { return fPtr; } \
+ static size_t GetSize (void) { return sizeof (asType); } \
+ \
+ EmAlias##type<A>& operator= (const bool); \
+ EmAlias##type<A>& operator= (const char); \
+ \
+ EmAlias##type<A>& operator= (const unsigned char); \
+ EmAlias##type<A>& operator= (const unsigned short); \
+ EmAlias##type<A>& operator= (const unsigned int); \
+ EmAlias##type<A>& operator= (const unsigned long); \
+ \
+ EmAlias##type<A>& operator= (const signed char); \
+ EmAlias##type<A>& operator= (const signed short); \
+ EmAlias##type<A>& operator= (const signed int); \
+ EmAlias##type<A>& operator= (const signed long); \
+ \
+ EmAlias##type<A>& operator= (const void*); \
+ EmAlias##type<A>& operator= (const EmAlias##type<A>&); \
+ \
+ operator type (void) const; \
+ \
+ EmAlias##type<A> operator[] (int); \
+ const EmAlias##type<A> operator[] (int) const; \
+ \
+ private: \
+ EmAlias##type (void); \
+ \
+ ptr_type fPtr; \
+ };
+
+#define DECLARE_SCALAR_PROXY(type, asType) \
+ \
+ class EmProxy##type \
+ { \
+ public: \
+ typedef void* ptr_type; \
+ \
+ EmProxy##type (void); \
+ EmProxy##type (const EmProxy##type&); \
+ \
+ ptr_type GetPtr (void) const { return (ptr_type) &fLocalData; } \
+ static size_t GetSize (void) { return sizeof (asType); } \
+ \
+ EmProxy##type& operator= (const bool); \
+ EmProxy##type& operator= (const char); \
+ \
+ EmProxy##type& operator= (const unsigned char); \
+ EmProxy##type& operator= (const unsigned short); \
+ EmProxy##type& operator= (const unsigned int); \
+ EmProxy##type& operator= (const unsigned long); \
+ \
+ EmProxy##type& operator= (const signed char); \
+ EmProxy##type& operator= (const signed short); \
+ EmProxy##type& operator= (const signed int); \
+ EmProxy##type& operator= (const signed long); \
+ \
+ EmProxy##type& operator= (const void*); \
+ EmProxy##type& operator= (const EmProxy##type&); \
+ \
+ operator type (void) const; \
+ \
+ EmAlias##type<LAS> operator[] (int); \
+ const EmAlias##type<LAS> operator[] (int) const; \
+ \
+ private: \
+ struct { \
+ char _bytes[sizeof (asType)]; \
+ } fLocalData; \
+ };
+
+#define DECLARE_SCALAR_CLASSES(type, asType) \
+ DECLARE_SCALAR_ALIAS(type, asType) \
+ DECLARE_SCALAR_PROXY(type, asType)
+
+#define DEFINE_SCALAR_ALIAS(type, asType) \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (void) : \
+ fPtr ((ptr_type) NULL) \
+ { \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (ptr_type p) : \
+ fPtr (p) \
+ { \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (const EmAlias##type<A>& that) : \
+ fPtr (that.GetPtr ()) \
+ { \
+ } \
+ \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, bool) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, char) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, signed char) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, signed short) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, signed int) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, signed long) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, unsigned char) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, unsigned short) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, unsigned int) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, unsigned long) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, const void*) \
+ MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, const EmAlias##type<A>&)\
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::operator type (void) const \
+ { \
+ if (sizeof (asType) == 1) \
+ return (type) A::GetByte((ptr_type) fPtr); \
+ \
+ if (sizeof (asType) == 2) \
+ return (type) A::GetWord((ptr_type) fPtr); \
+ \
+ if (sizeof (asType) == 4) \
+ return (type) A::GetLong((ptr_type) fPtr); \
+ \
+ return (type) BadGetter (); \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A> EmAlias##type<A>::operator [] (int index) \
+ { \
+ return EmAlias##type<A> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ } \
+ \
+ template <class A> \
+ INLINE_ const EmAlias##type<A> EmAlias##type<A>::operator [] (int index) const \
+ { \
+ return EmAlias##type<A> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ }
+
+#define DEFINE_SCALAR_PROXY(type, asType) \
+ \
+ INLINE_ EmProxy##type::EmProxy##type (void) \
+ { \
+ } \
+ \
+ INLINE_ EmProxy##type::EmProxy##type (const EmProxy##type& that) \
+ { \
+ *this = (asType) (type) that; \
+ } \
+ \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, bool) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, char) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, signed char) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, signed short) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, signed int) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, signed long) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, unsigned char) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, unsigned short) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, unsigned int) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, unsigned long) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, const void*) \
+ MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, const EmProxy##type&) \
+ \
+ INLINE_ EmProxy##type::operator type (void) const \
+ { \
+ if (sizeof (asType) == 1) \
+ return (type) LAS::GetByte((ptr_type) &fLocalData); \
+ \
+ if (sizeof (asType) == 2) \
+ return (type) LAS::GetWord((ptr_type) &fLocalData); \
+ \
+ if (sizeof (asType) == 4) \
+ return (type) LAS::GetLong((ptr_type) &fLocalData); \
+ \
+ return (type) BadGetter (); \
+ } \
+ \
+ INLINE_ EmAlias##type<LAS> EmProxy##type::operator [] (int index) \
+ { \
+ return EmAlias##type<LAS> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ } \
+ \
+ INLINE_ const EmAlias##type<LAS> EmProxy##type::operator [] (int index) const \
+ { \
+ return EmAlias##type<LAS> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ }
+
+#define DEFINE_SCALAR_CLASSES(type, asType) \
+ DEFINE_SCALAR_ALIAS(type, asType) \
+ DEFINE_SCALAR_PROXY(type, asType)
+
+// Macro that creates the implementation for an assignment operator for simple types.
+
+#define MAKE_ONE_SCALAR_ALIAS_ASSIGNMENT_OPERATOR(type, asType, rhs_type) \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>& EmAlias##type<A>::operator= (rhs_type val) \
+ { \
+ if (sizeof (asType) == 1) A::PutByte (this->GetPtr (), (unsigned char) (asType) val); \
+ else if (sizeof (asType) == 2) A::PutWord (this->GetPtr (), (unsigned short) (asType) val); \
+ else if (sizeof (asType) == 4) A::PutLong (this->GetPtr (), (unsigned long) (asType) val); \
+ else BadSetter (); \
+ \
+ return *this; \
+ }
+
+#define MAKE_ONE_SCALAR_PROXY_ASSIGNMENT_OPERATOR(type, asType, rhs_type) \
+ \
+ INLINE_ EmProxy##type& EmProxy##type::operator= (rhs_type val) \
+ { \
+ if (sizeof (asType) == 1) LAS::PutByte (this->GetPtr (), (unsigned char) (asType) val); \
+ else if (sizeof (asType) == 2) LAS::PutWord (this->GetPtr (), (unsigned short) (asType) val); \
+ else if (sizeof (asType) == 4) LAS::PutLong (this->GetPtr (), (unsigned long) (asType) val); \
+ else BadSetter (); \
+ \
+ return *this; \
+ }
+
+
+// ======================================================================
+// Macro for creating the class that wraps up aggregate types.
+// ======================================================================
+
+#define DECLARE_STRUCT_ALIAS(type, size, FOR_EACH_FIELD) \
+ \
+ template <class A> \
+ class EmAlias##type \
+ { \
+ public: \
+ typedef typename A::ptr_type ptr_type; \
+ \
+ EmAlias##type (ptr_type); \
+ EmAlias##type (const EmAlias##type&); \
+ \
+ ptr_type GetPtr (void) const { return fPtr; } \
+ static size_t GetSize (void) { return size; } \
+ \
+ EmAlias##type<A>& operator= (const EmAlias##type<A>&); \
+ \
+ EmAlias##type<A> operator[] (int); \
+ const EmAlias##type<A> operator[] (int) const; \
+ \
+ private: \
+ EmAlias##type (void); \
+ \
+ ptr_type fPtr; \
+ \
+ public: \
+ FOR_EACH_FIELD(DECLARE_FIELD_ALIAS) \
+ FOR_EACH_FIELD(DECLARE_FIELD_OFFSET) \
+ };
+
+#define DECLARE_STRUCT_PROXY(type, size, FOR_EACH_FIELD) \
+ \
+ class EmProxy##type \
+ { \
+ public: \
+ typedef void* ptr_type; \
+ \
+ EmProxy##type (void); \
+ EmProxy##type (const EmProxy##type&); \
+ \
+ ptr_type GetPtr (void) const { return (ptr_type) &fLocalData; } \
+ static size_t GetSize (void) { return size; } \
+ \
+ EmProxy##type& operator= (const EmProxy##type&); \
+ \
+ EmAlias##type<LAS> operator[] (int); \
+ const EmAlias##type<LAS> operator[] (int) const; \
+ \
+ private: \
+ struct { \
+ char _bytes[size]; \
+ } fLocalData; \
+ \
+ public: \
+ FOR_EACH_FIELD(DECLARE_FIELD_PROXY) \
+ FOR_EACH_FIELD(DECLARE_FIELD_OFFSET) \
+ };
+
+#define DECLARE_STRUCT_CLASSES(type, size, FOR_EACH_FIELD) \
+ DECLARE_STRUCT_ALIAS(type, size, FOR_EACH_FIELD) \
+ DECLARE_STRUCT_PROXY(type, size, FOR_EACH_FIELD)
+
+#define DEFINE_STRUCT_ALIAS(type, size, FOR_EACH_FIELD) \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (void) : \
+ fPtr ((ptr_type) NULL) \
+ FOR_EACH_FIELD(MAKE_MEMBER_INITIALIZER_ALIAS) \
+ { \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (ptr_type p) : \
+ fPtr (p) \
+ FOR_EACH_FIELD(MAKE_MEMBER_INITIALIZER_ALIAS) \
+ { \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>::EmAlias##type (const EmAlias##type<A>& that) : \
+ fPtr (that.fPtr) \
+ FOR_EACH_FIELD(MAKE_MEMBER_INITIALIZER_ALIAS) \
+ { \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A>& EmAlias##type<A>::operator= (const EmAlias##type<A>& val) \
+ { \
+ if (this != &val) \
+ { \
+ A::BlockCopy (this->GetPtr (), val.GetPtr (), this->GetSize ()); \
+ } \
+ \
+ return *this; \
+ } \
+ \
+ template <class A> \
+ INLINE_ EmAlias##type<A> EmAlias##type<A>::operator [] (int index) \
+ { \
+ return EmAlias##type<A> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ } \
+ \
+ template <class A> \
+ INLINE_ const EmAlias##type<A> EmAlias##type<A>::operator [] (int index) const \
+ { \
+ return EmAlias##type<A> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ }
+
+#define DEFINE_STRUCT_PROXY(type, size, FOR_EACH_FIELD) \
+ \
+ INLINE_ EmProxy##type::EmProxy##type (void) : \
+ fLocalData () \
+ FOR_EACH_FIELD(MAKE_MEMBER_INITIALIZER_PROXY) \
+ { \
+ } \
+ \
+ INLINE_ EmProxy##type::EmProxy##type (const EmProxy##type& that) : \
+ fLocalData () \
+ FOR_EACH_FIELD(MAKE_MEMBER_INITIALIZER_PROXY) \
+ { \
+ *this = that; \
+ } \
+ \
+ INLINE_ EmProxy##type& EmProxy##type::operator= (const EmProxy##type& val) \
+ { \
+ if (this != &val) \
+ { \
+ LAS::BlockCopy (this->GetPtr (), val.GetPtr (), this->GetSize ()); \
+ } \
+ \
+ return *this; \
+ } \
+ \
+ INLINE_ EmAlias##type<LAS> EmProxy##type::operator [] (int index) \
+ { \
+ return EmAlias##type<LAS> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ } \
+ \
+ INLINE_ const EmAlias##type<LAS> EmProxy##type::operator [] (int index) const \
+ { \
+ return EmAlias##type<LAS> ((ptr_type) (((char*) this->GetPtr ()) + index * this->GetSize ())); \
+ }
+
+#define DEFINE_STRUCT_CLASSES(type, size, FOR_EACH_FIELD) \
+ DEFINE_STRUCT_ALIAS(type, size, FOR_EACH_FIELD) \
+ DEFINE_STRUCT_PROXY(type, size, FOR_EACH_FIELD)
+
+// Macro for creating the data member that acts as a proxy for the data
+// we're wrapping up.
+
+#define DECLARE_FIELD_ALIAS(field_offset, field_type, field_name) \
+ \
+ EmAlias##field_type<A> field_name;
+
+
+#define DECLARE_FIELD_PROXY(field_offset, field_type, field_name) \
+ \
+ EmAlias##field_type<LAS> field_name;
+
+
+#define DECLARE_FIELD_OFFSET(field_offset, field_type, field_name) \
+ \
+ static size_t offsetof_##field_name (void) { return field_offset; }
+
+
+// Macros for creating the data member initializers in the constructors
+
+#define MAKE_MEMBER_INITIALIZER_ALIAS(field_offset, field_type, field_name) \
+ \
+ , field_name((ptr_type) (((char*) fPtr) + field_offset))
+
+
+#define MAKE_MEMBER_INITIALIZER_PROXY(field_offset, field_type, field_name) \
+ \
+ , field_name((ptr_type) (((char*) this->GetPtr ()) + field_offset))
+
+
+
+
+typedef uint8 UIOptionsType;
+typedef uint8 ScrOperation;
+
+#define FOR_EACH_SCALAR_1(DO_TO_SCALAR) \
+ DO_TO_SCALAR (char, char) \
+ DO_TO_SCALAR (Int8, Int8) \
+ DO_TO_SCALAR (UInt8, UInt8) \
+ DO_TO_SCALAR (Int16, Int16) \
+ DO_TO_SCALAR (UInt16, UInt16) \
+ DO_TO_SCALAR (Int32, Int32) \
+ DO_TO_SCALAR (UInt32, UInt32) \
+
+
+#define FOR_EACH_SCALAR_2(DO_TO_SCALAR) \
+ DO_TO_SCALAR (Boolean, uint8) \
+ DO_TO_SCALAR (Char, uint8) \
+ DO_TO_SCALAR (ControlStyleType, uint8) \
+ DO_TO_SCALAR (Coord, uint16) \
+ DO_TO_SCALAR (DmResID, uint16) \
+ DO_TO_SCALAR (emuptr, emuptr) \
+ DO_TO_SCALAR (Err, uint16) \
+ DO_TO_SCALAR (FontID, uint8) \
+ DO_TO_SCALAR (FormObjectKind, uint8) \
+ DO_TO_SCALAR (LocalID, uint32) \
+
+
+#define FOR_EACH_SCALAR_3(DO_TO_SCALAR) \
+ DO_TO_SCALAR (NetIPAddr, uint32) \
+ DO_TO_SCALAR (PatternType, uint8) \
+ DO_TO_SCALAR (ScrOperation, uint8) \
+ DO_TO_SCALAR (SlkPktHeaderChecksum, uint8) \
+ DO_TO_SCALAR (UnderlineModeType, uint8) \
+ DO_TO_SCALAR (UndoMode, uint8) \
+ DO_TO_SCALAR (UIOptionsType, uint8) \
+ DO_TO_SCALAR (WChar, uint16) \
+
+
+#define FOR_EACH_SCALAR_4(DO_TO_SCALAR) \
+ DO_TO_SCALAR (HostControlSelectorType, uint16) \
+ DO_TO_SCALAR (HostBoolType, int32) \
+ DO_TO_SCALAR (HostClockType, int32) \
+ DO_TO_SCALAR (HostErrType, int32) \
+ DO_TO_SCALAR (HostIDType, int32) \
+ DO_TO_SCALAR (HostPlatformType, int32) \
+ DO_TO_SCALAR (HostSignalType, int32) \
+ DO_TO_SCALAR (HostSizeType, int32) \
+ DO_TO_SCALAR (HostTimeType, int32) \
+
+
+#define FOR_EACH_STRUCT_1(DO_TO_STRUCT) \
+ FOR_AbsRectType_STRUCT (DO_TO_STRUCT) \
+ FOR_PointType_STRUCT (DO_TO_STRUCT) \
+ FOR_RectangleType_STRUCT (DO_TO_STRUCT) \
+ FOR_RGBColorType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_2(DO_TO_STRUCT) \
+ FOR_BreakpointType_STRUCT (DO_TO_STRUCT) \
+ FOR_M68KRegsType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_UsbHwrType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrBatCmdReadType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrJerryPLDType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrLAPType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrMediaQ11xxType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrPalmI705PLDType_STRUCT (DO_TO_STRUCT) \
+ FOR_HwrSymbolASICType_STRUCT (DO_TO_STRUCT) \
+ FOR_SED1375RegsType_STRUCT (DO_TO_STRUCT) \
+ FOR_SED1376RegsType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_SysBatteryDataStructV1_STRUCT (DO_TO_STRUCT) \
+ FOR_SysBatteryDataStructV2_STRUCT (DO_TO_STRUCT) \
+ FOR_SysBatteryDataStructV3_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_SysNVParamsType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_3(DO_TO_STRUCT) \
+ FOR_ClipboardItem_STRUCT (DO_TO_STRUCT) \
+ FOR_FieldUndoType_STRUCT (DO_TO_STRUCT) \
+ FOR_GraphicStateTypeV1_STRUCT (DO_TO_STRUCT) \
+ FOR_GraphicStateTypeV2_STRUCT (DO_TO_STRUCT) \
+ FOR_GraphicStateTypeV3_STRUCT (DO_TO_STRUCT) \
+ FOR_UIColorStateType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_4(DO_TO_STRUCT) \
+ FOR_UIGlobalsType_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeCommon_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV1_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV2_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV3_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV31_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV32_STRUCT (DO_TO_STRUCT) \
+ FOR_UIGlobalsTypeV35_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_5(DO_TO_STRUCT) \
+ FOR_M68KExcTableType_STRUCT (DO_TO_STRUCT) \
+ FOR_FixedGlobalsType_STRUCT (DO_TO_STRUCT) \
+ FOR_LowMemHdrType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysAppInfoType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysLibTblEntryType_STRUCT (DO_TO_STRUCT) \
+ FOR_PenBtnInfoType_STRUCT (DO_TO_STRUCT) \
+ FOR_SndCommandType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_kernel_info_task_STRUCT (DO_TO_STRUCT) \
+ FOR_kernel_info_semaphore_STRUCT (DO_TO_STRUCT) \
+ FOR_kernel_info_timer_STRUCT (DO_TO_STRUCT) \
+ FOR_SysKernelInfoType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_6(DO_TO_STRUCT) \
+ FOR_SlkPktFooterType_STRUCT (DO_TO_STRUCT) \
+ FOR_SlkPktHeaderType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_SysPktRPCParamType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_SysPktBodyType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktContinueCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktDbgBreakToggleCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktDbgBreakToggleRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktFindCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktFindRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktGetBreakpointsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktEmptyRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktGetBreakpointsRspType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_7(DO_TO_STRUCT) \
+ FOR_SysPktGetTrapBreaksCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktGetTrapBreaksRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktGetTrapConditionsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktGetTrapConditionsRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktReadMemCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktReadMemRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktReadRegsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktReadRegsRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktRPC2Type_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktRPCType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktRtnNameCmdType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_8(DO_TO_STRUCT) \
+ FOR_SysPktRtnNameRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktSetBreakpointsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktSetBreakpointsRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktSetTrapBreaksCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktSetTrapConditionsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktSetTrapConditionsRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktStateCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktStateRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktWriteMemCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktWriteMemRspType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktWriteRegsCmdType_STRUCT (DO_TO_STRUCT) \
+ FOR_SysPktWriteRegsRspType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_9(DO_TO_STRUCT) \
+ FOR_RecordEntryType_STRUCT (DO_TO_STRUCT) \
+ FOR_RsrcEntryType_STRUCT (DO_TO_STRUCT) \
+ FOR_RecordListType_STRUCT (DO_TO_STRUCT) \
+ FOR_DatabaseHdrType_STRUCT (DO_TO_STRUCT) \
+ FOR_DatabaseDirEntryType_STRUCT (DO_TO_STRUCT) \
+ FOR_DatabaseDirType_STRUCT (DO_TO_STRUCT) \
+ FOR_DmOpenInfoType_STRUCT(DO_TO_STRUCT) \
+ FOR_DmAccessType_STRUCT(DO_TO_STRUCT) \
+ FOR_DmSearchStateType_STRUCT(DO_TO_STRUCT) \
+ \
+ FOR_CardHeaderType_STRUCT(DO_TO_STRUCT) \
+ FOR_CardInfoType_STRUCT(DO_TO_STRUCT) \
+ FOR_StorageHeaderType_STRUCT(DO_TO_STRUCT) \
+ \
+ FOR_ExgGoToType_STRUCT (DO_TO_STRUCT) \
+ FOR_ExgSocketType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_DlkDBCreatorList_STRUCT (DO_TO_STRUCT) \
+ FOR_DlkServerSessionType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_10(DO_TO_STRUCT) \
+ FOR_generic_STRUCT (DO_TO_STRUCT) \
+ FOR_penUp_STRUCT (DO_TO_STRUCT) \
+ FOR_keyDown_STRUCT (DO_TO_STRUCT) \
+ FOR_winEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_winExit_STRUCT (DO_TO_STRUCT) \
+ FOR_tsmConfirm_STRUCT (DO_TO_STRUCT) \
+ FOR_tsmFepButton_STRUCT (DO_TO_STRUCT) \
+ FOR_tsmFepMode_STRUCT (DO_TO_STRUCT) \
+ FOR_ctlEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_ctlSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_ctlRepeat_STRUCT (DO_TO_STRUCT) \
+ FOR_ctlExit_STRUCT (DO_TO_STRUCT) \
+ FOR_fldEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_fldHeightChanged_STRUCT (DO_TO_STRUCT) \
+ FOR_fldChanged_STRUCT (DO_TO_STRUCT) \
+ FOR_fldExit_STRUCT (DO_TO_STRUCT) \
+ FOR_lstEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_lstExit_STRUCT (DO_TO_STRUCT) \
+ FOR_lstSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_tblEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_tblExit_STRUCT (DO_TO_STRUCT) \
+ FOR_tblSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_frmLoad_STRUCT (DO_TO_STRUCT) \
+ FOR_frmOpen_STRUCT (DO_TO_STRUCT) \
+ FOR_frmGoto_STRUCT (DO_TO_STRUCT) \
+ FOR_frmClose_STRUCT (DO_TO_STRUCT) \
+ FOR_frmUpdate_STRUCT (DO_TO_STRUCT) \
+ FOR_frmTitleEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_frmTitleSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_attnIndicatorEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_attnIndicatorSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_daySelect_STRUCT (DO_TO_STRUCT) \
+ FOR_menu_STRUCT (DO_TO_STRUCT) \
+ FOR_popSelect_STRUCT (DO_TO_STRUCT) \
+ FOR_sclEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_sclExit_STRUCT (DO_TO_STRUCT) \
+ FOR_sclRepeat_STRUCT (DO_TO_STRUCT) \
+ FOR_menuCmdBarOpen_STRUCT (DO_TO_STRUCT) \
+ FOR_menuOpen_STRUCT (DO_TO_STRUCT) \
+ FOR_gadgetEnter_STRUCT (DO_TO_STRUCT) \
+ FOR_gadgetMisc_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_EventTypeData_STRUCT (DO_TO_STRUCT) \
+ FOR_EventType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_11(DO_TO_STRUCT) \
+ FOR_ROMDBRecordHeader1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMDBResourceHeader1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMDBHeader1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMCardHeader5Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMStoreHeader4Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMHeapHeader1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMHeapHeader2Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMHeapHeader3Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMDBDir1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMHeapChunkHdr2Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMHeapChunkHdr1Type_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMFtrFeatureType_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMFtrCreatorType_STRUCT (DO_TO_STRUCT) \
+ FOR_ROMFtrTableType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_12(DO_TO_STRUCT) \
+ FOR_ControlAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_ControlType_STRUCT (DO_TO_STRUCT) \
+ FOR_GraphicControlType_STRUCT (DO_TO_STRUCT) \
+ FOR_SliderControlType_STRUCT (DO_TO_STRUCT) \
+ FOR_BitmapTypeV2_STRUCT (DO_TO_STRUCT) \
+ FOR_BitmapTypeV3_STRUCT (DO_TO_STRUCT) \
+ FOR_FrameBitsType_STRUCT (DO_TO_STRUCT) \
+ FOR_WindowFlagsType_STRUCT (DO_TO_STRUCT) \
+ FOR_WindowType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormObjListType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_cjxln_STRUCT (DO_TO_STRUCT) \
+ FOR_cj_xgbh_STRUCT (DO_TO_STRUCT) \
+ FOR_cj_xsmb_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_13(DO_TO_STRUCT) \
+ FOR_TimGlobalsType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_FormObjAttrType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_FormBitmapType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormLineType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormFrameType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormRectangleType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormTitleType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormPopupType_STRUCT (DO_TO_STRUCT) \
+ FOR_FrmGraffitiStateType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_ScrollBarAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_ScrollBarType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_FormGadgetAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_FormGadgetType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_FormLabelType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_FieldAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_FieldType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_ListAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_ListType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_TableAttrType_STRUCT (DO_TO_STRUCT) \
+ FOR_TableType_STRUCT (DO_TO_STRUCT) \
+
+
+#define FOR_EACH_STRUCT_14(DO_TO_STRUCT) \
+ FOR_HostDirEntType_STRUCT (DO_TO_STRUCT) \
+ FOR_HostGremlinInfoType_STRUCT (DO_TO_STRUCT) \
+ FOR_HostStatType_STRUCT (DO_TO_STRUCT) \
+ FOR_HostTmType_STRUCT (DO_TO_STRUCT) \
+ FOR_HostUTimeType_STRUCT (DO_TO_STRUCT) \
+ \
+ FOR_NetHostInfoType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetHostInfoBufType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetIOParamType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetIOVecType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetServInfoType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetServInfoBufType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetSocketAddrINType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetSocketAddrRawType_STRUCT (DO_TO_STRUCT) \
+ FOR_NetSocketAddrType_STRUCT (DO_TO_STRUCT) \
+
+
+#if PLATFORM_MAC
+ #define INLINE_SCALAR_IMPLEMENTATION 1
+#else
+ #define INLINE_SCALAR_IMPLEMENTATION 0
+#endif
+
+FOR_EACH_SCALAR_1 (DECLARE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_2 (DECLARE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_3 (DECLARE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_4 (DECLARE_SCALAR_CLASSES)
+
+#if INLINE_SCALAR_IMPLEMENTATION
+
+#undef INLINE_
+#define INLINE_ inline
+
+FOR_EACH_SCALAR_1 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_2 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_3 (DEFINE_SCALAR_CLASSES)
+FOR_EACH_SCALAR_4 (DEFINE_SCALAR_CLASSES)
+
+#undef INLINE_
+#define INLINE_
+
+#endif
+
+FOR_EACH_STRUCT_1 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_2 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_3 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_4 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_5 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_6 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_7 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_8 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_9 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_10 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_11 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_12 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_13 (DECLARE_STRUCT_CLASSES)
+FOR_EACH_STRUCT_14 (DECLARE_STRUCT_CLASSES)
+
+#endif // EmPalmStructs_h
diff --git a/SrcShared/EmPalmStructs.i b/SrcShared/EmPalmStructs.i
new file mode 100644
index 0000000..728d945
--- /dev/null
+++ b/SrcShared/EmPalmStructs.i
@@ -0,0 +1,3709 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// This file contains the macros that define the fields of structs in a
+// way that allows us to create wrapper classes that access those fields
+// in a binary-compatible, cross-platform fashion.
+//
+// This file is #included by EmPalmStructs.h. The macros are stored in
+// this separate .i file merely because of problems trying to edit them
+// if they're stored in EmPalmStructs.h. Visual Studio's editor seems
+// to get bogged down when trying to edit a source file containing many
+// large macros. It frequently "goes to lunch" for a second or so,
+// making editing, selecting, scrolling, etc., very frustrating. Placing
+// the macros in a .i file -- which the editor doesn't seem to try to
+// parse -- eliminates this problem.
+
+
+// Define macros that allow us to iterate over all the fields in a struct.
+// The various columns are:
+//
+// 1: field offset
+// 2: field type
+// 3: field name
+
+/*
+ # Format the first column
+ find ¥; replace -c ° /(¶tDO_TO_FIELD ¶([0-9]Ç1,1È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¨2"
+ find ¥; replace -c ° /(¶tDO_TO_FIELD ¶([0-9]Ç2,4È,)¨1[¶t]+(Å)¨2/ "¨1¶t¨2"
+
+ # Format the second column
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç1,2È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¶t¶t¶t¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç3,6È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¶t¶t¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç7,10È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¶t¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç11,14È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç15,18È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç19,22È,)¨1[¶t]+(Å)¨2/ "¨1¶t¶t¨2"
+ find ¥; replace -c ° /(Å,[¶t]+[_a-z0-9]Ç23,99È,)¨1[¶t]+(Å)¨2/ "¨1¶t¨2"
+
+ # Format the third column
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç1,2ȶ))¨5[¶t]+\/ "¨5¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç3,6ȶ))¨5[¶t]+\/ "¨5¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç7,10ȶ))¨5[¶t]+\/ "¨5¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç11,14ȶ))¨5[¶t]+\/ "¨5¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç15,18ȶ))¨5[¶t]+\/ "¨5¶t¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç19,22ȶ))¨5[¶t]+\/ "¨5¶t¶t\"
+ find ¥; replace -c ° /(,[¶t]+[_a-z0-9]Ç23,99ȶ))¨5[¶t]+\/ "¨5¶t\"
+
+ # Format the #define lines
+ find ¥; replace -c ° /(¶#define [¶t]Ç1,3È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç4,7È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç8,11È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç12,15È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç16,19È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç20,23È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç24,27È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç28,31È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç32,35È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç36,39È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç40,43È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç44,47È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç48,51È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç52,55È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç56,59È)¨1[¶t]+\/ "¨1¶t¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç60,63È)¨1[¶t]+\/ "¨1¶t¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç64,67È)¨1[¶t]+\/ "¨1¶t¶t\"
+ find ¥; replace -c ° /(¶#define [¶t]Ç68,99È)¨1[¶t]+\/ "¨1¶t\"
+*/
+
+// ========================================
+// ===== generic =====
+// ========================================
+
+#define FOR_generic_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (generic, 16, FOR_generic_FIELDS)
+
+#define FOR_generic_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, datum) \
+
+
+// ========================================
+// ===== penUp =====
+// ========================================
+
+#define FOR_penUp_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (penUp, 8, FOR_penUp_FIELDS)
+
+#define FOR_penUp_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, PointType, start) \
+ DO_TO_FIELD (4, PointType, end) \
+
+
+// ========================================
+// ===== keyDown =====
+// ========================================
+
+#define FOR_keyDown_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (keyDown, 6, FOR_keyDown_FIELDS)
+
+#define FOR_keyDown_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, WChar, chr) \
+ DO_TO_FIELD (2, UInt16, keyCode) \
+ DO_TO_FIELD (4, UInt16, modifiers) \
+
+
+// ========================================
+// ===== winEnter =====
+// ========================================
+
+#define FOR_winEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (winEnter, 8, FOR_winEnter_FIELDS)
+
+#define FOR_winEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, enterWindow) \
+ DO_TO_FIELD (4, emuptr, exitWindow) \
+
+
+// ========================================
+// ===== winExit =====
+// ========================================
+
+#define FOR_winExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (winExit, 8, FOR_winExit_FIELDS)
+
+#define FOR_winExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, enterWindow) \
+ DO_TO_FIELD (4, emuptr, exitWindow) \
+
+
+// ========================================
+// ===== tsmConfirm =====
+// ========================================
+
+#define FOR_tsmConfirm_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tsmConfirm, 6, FOR_tsmConfirm_FIELDS)
+
+#define FOR_tsmConfirm_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, yomiText) \
+ DO_TO_FIELD (4, UInt16, formID) \
+
+
+// ========================================
+// ===== tsmFepButton =====
+// ========================================
+
+#define FOR_tsmFepButton_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tsmFepButton, 2, FOR_tsmFepButton_FIELDS)
+
+#define FOR_tsmFepButton_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, buttonID) \
+
+
+// ========================================
+// ===== tsmFepMode =====
+// ========================================
+
+#define FOR_tsmFepMode_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tsmFepMode, 2, FOR_tsmFepMode_FIELDS)
+
+#define FOR_tsmFepMode_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, mode) \
+
+
+// ========================================
+// ===== ctlEnter =====
+// ========================================
+
+#define FOR_ctlEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ctlEnter, 6, FOR_ctlEnter_FIELDS)
+
+#define FOR_ctlEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, controlID) \
+ DO_TO_FIELD (2, emuptr, pControl) \
+
+
+// ========================================
+// ===== ctlSelect =====
+// ========================================
+
+#define FOR_ctlSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ctlSelect, 10, FOR_ctlSelect_FIELDS)
+
+#define FOR_ctlSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, controlID) \
+ DO_TO_FIELD (2, emuptr, pControl) \
+ DO_TO_FIELD (6, Boolean, on) \
+ DO_TO_FIELD (7, UInt8, reserved1) \
+ DO_TO_FIELD (8, UInt16, value) \
+
+
+// ========================================
+// ===== ctlRepeat =====
+// ========================================
+
+#define FOR_ctlRepeat_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ctlRepeat, 12, FOR_ctlRepeat_FIELDS)
+
+#define FOR_ctlRepeat_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, controlID) \
+ DO_TO_FIELD (2, emuptr, pControl) \
+ DO_TO_FIELD (6, UInt32, time) \
+ DO_TO_FIELD (10, UInt16, value) \
+
+
+// ========================================
+// ===== ctlExit =====
+// ========================================
+
+#define FOR_ctlExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ctlExit, 6, FOR_ctlExit_FIELDS)
+
+#define FOR_ctlExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, controlID) \
+ DO_TO_FIELD (2, emuptr, pControl) \
+
+
+// ========================================
+// ===== fldEnter =====
+// ========================================
+
+#define FOR_fldEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (fldEnter, 6, FOR_fldEnter_FIELDS)
+
+#define FOR_fldEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, fieldID) \
+ DO_TO_FIELD (2, emuptr, pField) \
+
+
+// ========================================
+// ===== fldHeightChanged =====
+// ========================================
+
+#define FOR_fldHeightChanged_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (fldHeightChanged, 10, FOR_fldHeightChanged_FIELDS)
+
+#define FOR_fldHeightChanged_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, fieldID) \
+ DO_TO_FIELD (2, emuptr, pField) \
+ DO_TO_FIELD (6, Int16, newHeight) \
+ DO_TO_FIELD (8, UInt16, currentPos) \
+
+
+// ========================================
+// ===== fldChanged =====
+// ========================================
+
+#define FOR_fldChanged_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (fldChanged, 6, FOR_fldChanged_FIELDS)
+
+#define FOR_fldChanged_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, fieldID) \
+ DO_TO_FIELD (2, emuptr, pField) \
+
+
+// ========================================
+// ===== fldExit =====
+// ========================================
+
+#define FOR_fldExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (fldExit, 6, FOR_fldExit_FIELDS)
+
+#define FOR_fldExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, fieldID) \
+ DO_TO_FIELD (2, emuptr, pField) \
+
+
+// ========================================
+// ===== lstEnter =====
+// ========================================
+
+#define FOR_lstEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (lstEnter, 8, FOR_lstEnter_FIELDS)
+
+#define FOR_lstEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, listID) \
+ DO_TO_FIELD (2, emuptr, pList) \
+ DO_TO_FIELD (6, Int16, selection) \
+
+
+// ========================================
+// ===== lstExit =====
+// ========================================
+
+#define FOR_lstExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (lstExit, 6, FOR_lstExit_FIELDS)
+
+#define FOR_lstExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, listID) \
+ DO_TO_FIELD (2, emuptr, pList) \
+
+
+// ========================================
+// ===== lstSelect =====
+// ========================================
+
+#define FOR_lstSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (lstSelect, 8, FOR_lstSelect_FIELDS)
+
+#define FOR_lstSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, listID) \
+ DO_TO_FIELD (2, emuptr, pList) \
+ DO_TO_FIELD (6, Int16, selection) \
+
+
+// ========================================
+// ===== tblEnter =====
+// ========================================
+
+#define FOR_tblEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tblEnter, 10, FOR_tblEnter_FIELDS)
+
+#define FOR_tblEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, tableID) \
+ DO_TO_FIELD (2, emuptr, pTable) \
+ DO_TO_FIELD (6, Int16, row) \
+ DO_TO_FIELD (8, Int16, column) \
+
+
+// ========================================
+// ===== tblExit =====
+// ========================================
+
+#define FOR_tblExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tblExit, 10, FOR_tblExit_FIELDS)
+
+#define FOR_tblExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, tableID) \
+ DO_TO_FIELD (2, emuptr, pTable) \
+ DO_TO_FIELD (6, Int16, row) \
+ DO_TO_FIELD (8, Int16, column) \
+
+
+// ========================================
+// ===== tblSelect =====
+// ========================================
+
+#define FOR_tblSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (tblSelect, 10, FOR_tblSelect_FIELDS)
+
+#define FOR_tblSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, tableID) \
+ DO_TO_FIELD (2, emuptr, pTable) \
+ DO_TO_FIELD (6, Int16, row) \
+ DO_TO_FIELD (8, Int16, column) \
+
+
+// ========================================
+// ===== frmLoad =====
+// ========================================
+
+#define FOR_frmLoad_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmLoad, 2, FOR_frmLoad_FIELDS)
+
+#define FOR_frmLoad_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== frmOpen =====
+// ========================================
+
+#define FOR_frmOpen_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmOpen, 2, FOR_frmOpen_FIELDS)
+
+#define FOR_frmOpen_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== frmGoto =====
+// ========================================
+
+#define FOR_frmGoto_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmGoto, 14, FOR_frmGoto_FIELDS)
+
+#define FOR_frmGoto_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+ DO_TO_FIELD (2, UInt16, recordNum) \
+ DO_TO_FIELD (4, UInt16, matchPos) \
+ DO_TO_FIELD (6, UInt16, matchLen) \
+ DO_TO_FIELD (8, UInt16, matchFieldNum) \
+ DO_TO_FIELD (10, UInt32, matchCustom) \
+
+
+// ========================================
+// ===== frmClose =====
+// ========================================
+
+#define FOR_frmClose_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmClose, 2, FOR_frmClose_FIELDS)
+
+#define FOR_frmClose_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== frmUpdate =====
+// ========================================
+
+#define FOR_frmUpdate_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmUpdate, 4, FOR_frmUpdate_FIELDS)
+
+#define FOR_frmUpdate_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+ DO_TO_FIELD (2, UInt16, updateCode) \
+
+
+// ========================================
+// ===== frmTitleEnter =====
+// ========================================
+
+#define FOR_frmTitleEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmTitleEnter, 2, FOR_frmTitleEnter_FIELDS)
+
+#define FOR_frmTitleEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== frmTitleSelect =====
+// ========================================
+
+#define FOR_frmTitleSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (frmTitleSelect, 2, FOR_frmTitleSelect_FIELDS)
+
+#define FOR_frmTitleSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== attnIndicatorEnter =====
+// ========================================
+
+#define FOR_attnIndicatorEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (attnIndicatorEnter, 2, FOR_attnIndicatorEnter_FIELDS)
+
+#define FOR_attnIndicatorEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== attnIndicatorSelect =====
+// ========================================
+
+#define FOR_attnIndicatorSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (attnIndicatorSelect, 2, FOR_attnIndicatorSelect_FIELDS)
+
+#define FOR_attnIndicatorSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, formID) \
+
+
+// ========================================
+// ===== daySelect =====
+// ========================================
+
+#define FOR_daySelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (daySelect, 8, FOR_daySelect_FIELDS)
+
+#define FOR_daySelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, pSelector) \
+ DO_TO_FIELD (4, Int16, selection) \
+ DO_TO_FIELD (6, Boolean, useThisDate) \
+ DO_TO_FIELD (7, UInt8, reserved1) \
+
+
+// ========================================
+// ===== menu =====
+// ========================================
+
+#define FOR_menu_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (menu, 2, FOR_menu_FIELDS)
+
+#define FOR_menu_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, itemID) \
+
+
+// ========================================
+// ===== popSelect =====
+// ========================================
+
+#define FOR_popSelect_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (popSelect, 16, FOR_popSelect_FIELDS)
+
+#define FOR_popSelect_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, controlID) \
+ DO_TO_FIELD (2, emuptr, controlP) \
+ DO_TO_FIELD (6, UInt16, listID) \
+ DO_TO_FIELD (8, emuptr, listP) \
+ DO_TO_FIELD (12, Int16, selection) \
+ DO_TO_FIELD (14, Int16, priorSelection) \
+
+
+// ========================================
+// ===== sclEnter =====
+// ========================================
+
+#define FOR_sclEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (sclEnter, 6, FOR_sclEnter_FIELDS)
+
+#define FOR_sclEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, scrollBarID) \
+ DO_TO_FIELD (2, emuptr, pScrollBar) \
+
+
+// ========================================
+// ===== sclExit =====
+// ========================================
+
+#define FOR_sclExit_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (sclExit, 10, FOR_sclExit_FIELDS)
+
+#define FOR_sclExit_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, scrollBarID) \
+ DO_TO_FIELD (2, emuptr, pScrollBar) \
+ DO_TO_FIELD (6, Int16, value) \
+ DO_TO_FIELD (8, Int16, newValue) \
+
+
+// ========================================
+// ===== sclRepeat =====
+// ========================================
+
+#define FOR_sclRepeat_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (sclRepeat, 14, FOR_sclRepeat_FIELDS)
+
+#define FOR_sclRepeat_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, scrollBarID) \
+ DO_TO_FIELD (2, emuptr, pScrollBar) \
+ DO_TO_FIELD (6, Int16, value) \
+ DO_TO_FIELD (8, Int16, newValue) \
+ DO_TO_FIELD (10, Int32, time) \
+
+
+// ========================================
+// ===== menuCmdBarOpen =====
+// ========================================
+
+#define FOR_menuCmdBarOpen_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (menuCmdBarOpen, 2, FOR_menuCmdBarOpen_FIELDS)
+
+#define FOR_menuCmdBarOpen_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Boolean, preventFieldButtons) \
+ DO_TO_FIELD (1, UInt8, reserved) \
+
+
+// ========================================
+// ===== menuOpen =====
+// ========================================
+
+#define FOR_menuOpen_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (menuOpen, 4, FOR_menuOpen_FIELDS)
+
+#define FOR_menuOpen_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, menuRscID) \
+ DO_TO_FIELD (2, Int16, cause) \
+
+
+// ========================================
+// ===== gadgetEnter =====
+// ========================================
+
+#define FOR_gadgetEnter_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (gadgetEnter, 6, FOR_gadgetEnter_FIELDS)
+
+#define FOR_gadgetEnter_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, gadgetID) \
+ DO_TO_FIELD (2, emuptr, gadgetP) \
+
+
+// ========================================
+// ===== gadgetMisc =====
+// ========================================
+
+#define FOR_gadgetMisc_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (gadgetMisc, 12, FOR_gadgetMisc_FIELDS)
+
+#define FOR_gadgetMisc_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, gadgetID) \
+ DO_TO_FIELD (2, emuptr, gadgetP) \
+ DO_TO_FIELD (6, UInt16, selector) \
+ DO_TO_FIELD (8, emuptr, dataP) \
+
+
+// ========================================
+// ===== AbsRectType =====
+// ========================================
+
+#define FOR_AbsRectType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (AbsRectType, 8, FOR_AbsRectType_FIELDS)
+
+#define FOR_AbsRectType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Coord, left) \
+ DO_TO_FIELD (2, Coord, top) \
+ DO_TO_FIELD (4, Coord, right) \
+ DO_TO_FIELD (6, Coord, bottom) \
+
+
+// ========================================
+// ===== BitmapTypeV2 =====
+// ========================================
+
+#define FOR_BitmapTypeV2_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (BitmapTypeV2, 16, FOR_BitmapTypeV2_FIELDS)
+
+#define FOR_BitmapTypeV2_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, width) \
+ DO_TO_FIELD (2, Int16, height) \
+ DO_TO_FIELD (4, UInt16, rowBytes) \
+ DO_TO_FIELD (6, UInt16, flags) \
+ DO_TO_FIELD (8, UInt8, pixelSize) \
+ DO_TO_FIELD (9, UInt8, version) \
+ DO_TO_FIELD (10, UInt16, nextDepthOffset) \
+ DO_TO_FIELD (12, UInt8, transparentIndex) \
+ DO_TO_FIELD (13, UInt8, compressionType) \
+ DO_TO_FIELD (14, UInt16, reserved) \
+
+
+// ========================================
+// ===== BitmapTypeV3 =====
+// ========================================
+
+#define FOR_BitmapTypeV3_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (BitmapTypeV3, 24, FOR_BitmapTypeV3_FIELDS)
+
+#define FOR_BitmapTypeV3_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, width) \
+ DO_TO_FIELD (2, Int16, height) \
+ DO_TO_FIELD (4, UInt16, rowBytes) \
+ DO_TO_FIELD (6, UInt16, flags) \
+ DO_TO_FIELD (8, UInt8, pixelSize) \
+ DO_TO_FIELD (9, UInt8, version) \
+ DO_TO_FIELD (10, UInt8, size) \
+ DO_TO_FIELD (11, UInt8, pixelFormat) \
+ DO_TO_FIELD (12, UInt8, unused) \
+ DO_TO_FIELD (13, UInt8, compressionType) \
+ DO_TO_FIELD (14, UInt16, density) \
+ DO_TO_FIELD (16, UInt32, transparentValue) \
+ DO_TO_FIELD (20, UInt32, nextDepthOffset) \
+
+
+// ========================================
+// ===== BreakpointType =====
+// ========================================
+
+#define FOR_BreakpointType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (BreakpointType, 6, FOR_BreakpointType_FIELDS)
+
+#define FOR_BreakpointType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, addr) \
+ DO_TO_FIELD (4, Boolean, enabled) \
+ DO_TO_FIELD (5, Boolean, installed) \
+
+
+// ========================================
+// ===== CardHeaderType =====
+// ========================================
+
+#define FOR_CardHeaderType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (CardHeaderType, 256, FOR_CardHeaderType_FIELDS)
+
+#define FOR_CardHeaderType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, initStack) \
+ DO_TO_FIELD (4, UInt32, resetVector) \
+ DO_TO_FIELD (8, UInt32, signature) \
+ DO_TO_FIELD (12, UInt16, hdrVersion) \
+ DO_TO_FIELD (14, UInt16, flags) \
+ DO_TO_FIELD (16, UInt8, name) \
+ DO_TO_FIELD (48, UInt8, manuf) \
+ DO_TO_FIELD (80, UInt16, version) \
+ DO_TO_FIELD (82, UInt32, creationDate) \
+ DO_TO_FIELD (86, UInt16, numRAMBlocks) \
+ DO_TO_FIELD (88, UInt32, blockListOffset) \
+ DO_TO_FIELD (92, UInt32, readWriteParmsOffset) \
+ DO_TO_FIELD (96, UInt32, readWriteParmsSize) \
+ DO_TO_FIELD (100, UInt32, readOnlyParmsOffset) \
+ DO_TO_FIELD (104, UInt32, bigROMOffset) \
+ DO_TO_FIELD (108, UInt32, checksumBytes) \
+ DO_TO_FIELD (112, UInt16, checksumValue) \
+ DO_TO_FIELD (114, UInt32, readWriteWorkingOffset) \
+ DO_TO_FIELD (118, UInt32, readWriteWorkingSize) \
+ DO_TO_FIELD (122, UInt32, halCodeOffset) \
+
+
+// ========================================
+// ===== CardInfoType =====
+// ========================================
+
+#define FOR_CardInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (CardInfoType, 48, FOR_CardInfoType_FIELDS)
+
+#define FOR_CardInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, baseP) \
+ DO_TO_FIELD (4, UInt32, size) \
+ DO_TO_FIELD (8, UInt32, firstRAMBlockSize) \
+ DO_TO_FIELD (12, UInt32, targetROMShift) \
+ DO_TO_FIELD (16, UInt32, cardHeaderOffset) \
+ DO_TO_FIELD (20, UInt32, rsvSpace) \
+ DO_TO_FIELD (24, UInt32, dynHeapSpace) \
+ DO_TO_FIELD (28, emuptr, ramStoreP) \
+ DO_TO_FIELD (32, UInt16, numRAMHeaps) \
+ DO_TO_FIELD (34, emuptr, ramHeapOffsetsP) \
+ DO_TO_FIELD (38, UInt16, numROMHeaps) \
+ DO_TO_FIELD (40, emuptr, romHeapOffsetsP) \
+ DO_TO_FIELD (44, UInt32, cardOffsetMask) \
+
+
+// ========================================
+// ===== ClipboardItem =====
+// ========================================
+
+#define FOR_ClipboardItem_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ClipboardItem, 6, FOR_ClipboardItem_FIELDS)
+
+#define FOR_ClipboardItem_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, item) \
+ DO_TO_FIELD (4, UInt16, length) \
+
+
+// ========================================
+// ===== ControlAttrType =====
+// ========================================
+
+#define FOR_ControlAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ControlAttrType, 2, FOR_ControlAttrType_FIELDS)
+
+#define FOR_ControlAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, flags) \
+
+
+// ========================================
+// ===== ControlType =====
+// ========================================
+
+#define FOR_ControlType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ControlType, 20, FOR_ControlType_FIELDS)
+
+#define FOR_ControlType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, id) \
+ DO_TO_FIELD (2, RectangleType, bounds) \
+ DO_TO_FIELD (10, emuptr, text) \
+ DO_TO_FIELD (14, ControlAttrType, attr) \
+ DO_TO_FIELD (16, ControlStyleType, style) \
+ DO_TO_FIELD (17, FontID, font) \
+ DO_TO_FIELD (18, UInt8, group) \
+ DO_TO_FIELD (19, UInt8, reserved) \
+
+
+// ========================================
+// ===== DatabaseDirEntryType =====
+// ========================================
+
+#define FOR_DatabaseDirEntryType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DatabaseDirEntryType, 4, FOR_DatabaseDirEntryType_FIELDS)
+
+#define FOR_DatabaseDirEntryType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, LocalID, baseID) \
+
+
+// ========================================
+// ===== DatabaseDirType =====
+// ========================================
+
+#define FOR_DatabaseDirType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DatabaseDirType, 10, FOR_DatabaseDirType_FIELDS)
+
+#define FOR_DatabaseDirType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, LocalID, nextDatabaseListID) \
+ DO_TO_FIELD (4, UInt16, numDatabases) \
+ DO_TO_FIELD (6, DatabaseDirEntryType, databaseID) \
+
+
+// ========================================
+// ===== DatabaseHdrType =====
+// ========================================
+
+#define FOR_DatabaseHdrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DatabaseHdrType, 78, FOR_DatabaseHdrType_FIELDS)
+
+#define FOR_DatabaseHdrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, name) \
+ DO_TO_FIELD (32, UInt16, attributes) \
+ DO_TO_FIELD (34, UInt16, version) \
+ DO_TO_FIELD (36, UInt32, creationDate) \
+ DO_TO_FIELD (40, UInt32, modificationDate) \
+ DO_TO_FIELD (44, UInt32, lastBackupDate) \
+ DO_TO_FIELD (48, UInt32, modificationNumber) \
+ DO_TO_FIELD (52, LocalID, appInfoID) \
+ DO_TO_FIELD (56, LocalID, sortInfoID) \
+ DO_TO_FIELD (60, UInt32, type) \
+ DO_TO_FIELD (64, UInt32, creator) \
+ DO_TO_FIELD (68, UInt32, uniqueIDSeed) \
+ DO_TO_FIELD (72, RecordListType, recordList) \
+
+
+// ========================================
+// ===== DlkDBCreatorList =====
+// ========================================
+
+#define FOR_DlkDBCreatorList_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DlkDBCreatorList, 6, FOR_DlkDBCreatorList_FIELDS)
+
+#define FOR_DlkDBCreatorList_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, count) \
+ DO_TO_FIELD (2, emuptr, listH) \
+
+
+// ========================================
+// ===== DlkServerSessionType =====
+// ========================================
+
+#define FOR_DlkServerSessionType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DlkServerSessionType, 146, FOR_DlkServerSessionType_FIELDS)
+
+#define FOR_DlkServerSessionType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, htalLibRefNum) \
+ DO_TO_FIELD (2, UInt32, maxHtalXferSize) \
+ DO_TO_FIELD (6, emuptr, eventProcP) \
+ DO_TO_FIELD (10, UInt32, eventRef) \
+ DO_TO_FIELD (14, emuptr, canProcP) \
+ DO_TO_FIELD (18, UInt32, canRef) \
+ DO_TO_FIELD (22, emuptr, condFilterH) \
+ DO_TO_FIELD (26, UInt8, dlkDBID) \
+ DO_TO_FIELD (27, UInt8, reserved1) \
+ DO_TO_FIELD (28, emuptr, dbR) \
+ DO_TO_FIELD (32, UInt16, cardNo) \
+ DO_TO_FIELD (34, UInt32, dbCreator) \
+ DO_TO_FIELD (38, Char, dbName) \
+ DO_TO_FIELD (70, UInt16, dbOpenMode) \
+ DO_TO_FIELD (72, Boolean, created) \
+ DO_TO_FIELD (73, Boolean, isResDB) \
+ DO_TO_FIELD (74, Boolean, ramBased) \
+ DO_TO_FIELD (75, Boolean, readOnly) \
+ DO_TO_FIELD (76, LocalID, dbLocalID) \
+ DO_TO_FIELD (80, UInt32, initialModNum) \
+ DO_TO_FIELD (84, UInt32, curRecIndex) \
+ DO_TO_FIELD (88, DlkDBCreatorList, creatorList) \
+ DO_TO_FIELD (94, UInt8, syncState) \
+ DO_TO_FIELD (95, Boolean, complete) \
+ DO_TO_FIELD (96, Boolean, conduitOpened) \
+ DO_TO_FIELD (97, Boolean, logCleared) \
+ DO_TO_FIELD (98, Boolean, resetPending) \
+ DO_TO_FIELD (99, Boolean, gotCommand) \
+ DO_TO_FIELD (100, UInt8, cmdTID) \
+ DO_TO_FIELD (101, UInt8, reserved2) \
+ DO_TO_FIELD (102, UInt16, cmdLen) \
+ DO_TO_FIELD (104, emuptr, cmdP) \
+ DO_TO_FIELD (108, emuptr, cmdH) \
+ DO_TO_FIELD (112, UInt16, wStateFlags) \
+ DO_TO_FIELD (114, DmSearchStateType, dbSearchState) \
+
+
+// ========================================
+// ===== DmAccessType =====
+// ========================================
+
+#define FOR_DmAccessType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DmAccessType, 16, FOR_DmAccessType_FIELDS)
+
+#define FOR_DmAccessType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, next) \
+ DO_TO_FIELD (4, UInt16, mode) \
+ DO_TO_FIELD (6, emuptr, openP) \
+ DO_TO_FIELD (10, UInt32, savedModNum) \
+ DO_TO_FIELD (14, UInt8, openType) \
+ DO_TO_FIELD (15, UInt8, reserved) \
+
+
+// ========================================
+// ===== DmOpenInfoType =====
+// ========================================
+
+#define FOR_DmOpenInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DmOpenInfoType, 36, FOR_DmOpenInfoType_FIELDS)
+
+#define FOR_DmOpenInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, next) \
+ DO_TO_FIELD (4, UInt16, openCount) \
+ DO_TO_FIELD (6, UInt32, ownerTaskID) \
+ DO_TO_FIELD (10, UInt16, flags) \
+ DO_TO_FIELD (12, LocalID, hdrID) \
+ DO_TO_FIELD (16, emuptr, hdrH) \
+ DO_TO_FIELD (20, emuptr, hdrP) \
+ DO_TO_FIELD (24, UInt16, cardNo) \
+ DO_TO_FIELD (26, UInt16, numRecords) \
+ DO_TO_FIELD (28, emuptr, hdrMasterP) \
+ DO_TO_FIELD (32, emuptr, handleTableP) \
+
+
+// ========================================
+// ===== DmSearchStateType =====
+// ========================================
+
+#define FOR_DmSearchStateType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (DmSearchStateType, 32, FOR_DmSearchStateType_FIELDS)
+
+#define FOR_DmSearchStateType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, info) \
+
+
+// ========================================
+// ===== EventTypeData =====
+// ========================================
+
+#define FOR_EventTypeData_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (EventTypeData, 16, FOR_EventTypeData_FIELDS)
+
+#define FOR_EventTypeData_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, generic, generic) \
+ DO_TO_FIELD (0, penUp, penUp) \
+ DO_TO_FIELD (0, keyDown, keyDown) \
+ DO_TO_FIELD (0, winEnter, winEnter) \
+ DO_TO_FIELD (0, winExit, winExit) \
+ DO_TO_FIELD (0, tsmConfirm, tsmConfirm) \
+ DO_TO_FIELD (0, tsmFepButton, tsmFepButton) \
+ DO_TO_FIELD (0, tsmFepMode, tsmFepMode) \
+ DO_TO_FIELD (0, ctlEnter, ctlEnter) \
+ DO_TO_FIELD (0, ctlSelect, ctlSelect) \
+ DO_TO_FIELD (0, ctlRepeat, ctlRepeat) \
+ DO_TO_FIELD (0, ctlExit, ctlExit) \
+ DO_TO_FIELD (0, fldEnter, fldEnter) \
+ DO_TO_FIELD (0, fldHeightChanged, fldHeightChanged) \
+ DO_TO_FIELD (0, fldChanged, fldChanged) \
+ DO_TO_FIELD (0, fldExit, fldExit) \
+ DO_TO_FIELD (0, lstEnter, lstEnter) \
+ DO_TO_FIELD (0, lstExit, lstExit) \
+ DO_TO_FIELD (0, lstSelect, lstSelect) \
+ DO_TO_FIELD (0, tblEnter, tblEnter) \
+ DO_TO_FIELD (0, tblExit, tblExit) \
+ DO_TO_FIELD (0, tblSelect, tblSelect) \
+ DO_TO_FIELD (0, frmLoad, frmLoad) \
+ DO_TO_FIELD (0, frmOpen, frmOpen) \
+ DO_TO_FIELD (0, frmGoto, frmGoto) \
+ DO_TO_FIELD (0, frmClose, frmClose) \
+ DO_TO_FIELD (0, frmUpdate, frmUpdate) \
+ DO_TO_FIELD (0, frmTitleEnter, frmTitleEnter) \
+ DO_TO_FIELD (0, frmTitleSelect, frmTitleSelect) \
+ DO_TO_FIELD (0, attnIndicatorEnter, attnIndicatorEnter) \
+ DO_TO_FIELD (0, attnIndicatorSelect, attnIndicatorSelect) \
+ DO_TO_FIELD (0, daySelect, daySelect) \
+ DO_TO_FIELD (0, menu, menu) \
+ DO_TO_FIELD (0, popSelect, popSelect) \
+ DO_TO_FIELD (0, sclEnter, sclEnter) \
+ DO_TO_FIELD (0, sclExit, sclExit) \
+ DO_TO_FIELD (0, sclRepeat, sclRepeat) \
+ DO_TO_FIELD (0, menuCmdBarOpen, menuCmdBarOpen) \
+ DO_TO_FIELD (0, menuOpen, menuOpen) \
+ DO_TO_FIELD (0, gadgetEnter, gadgetEnter) \
+ DO_TO_FIELD (0, gadgetMisc, gadgetMisc) \
+
+
+// ========================================
+// ===== EventType =====
+// ========================================
+
+#define FOR_EventType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (EventType, 24, FOR_EventType_FIELDS)
+
+#define FOR_EventType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, eType) \
+ DO_TO_FIELD (2, Boolean, penDown) \
+ DO_TO_FIELD (3, UInt8, tapCount) \
+ DO_TO_FIELD (4, Int16, screenX) \
+ DO_TO_FIELD (6, Int16, screenY) \
+ DO_TO_FIELD (8, EventTypeData, data) \
+
+
+// ========================================
+// ===== ExgGoToType =====
+// ========================================
+
+#define FOR_ExgGoToType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ExgGoToType, 16, FOR_ExgGoToType_FIELDS)
+
+#define FOR_ExgGoToType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, dbCardNo) \
+ DO_TO_FIELD (2, LocalID, dbID) \
+ DO_TO_FIELD (6, UInt16, recordNum) \
+ DO_TO_FIELD (8, UInt32, uniqueID) \
+ DO_TO_FIELD (12, UInt32, matchCustom) \
+
+
+// ========================================
+// ===== ExgSocketType =====
+// ========================================
+
+#define FOR_ExgSocketType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ExgSocketType, 60, FOR_ExgSocketType_FIELDS)
+
+#define FOR_ExgSocketType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, libraryRef) \
+ DO_TO_FIELD (2, UInt32, socketRef) \
+ DO_TO_FIELD (6, UInt32, target) \
+ DO_TO_FIELD (10, UInt32, count) \
+ DO_TO_FIELD (14, UInt32, length) \
+ DO_TO_FIELD (18, UInt32, time) \
+ DO_TO_FIELD (22, UInt32, appData) \
+ DO_TO_FIELD (26, UInt32, goToCreator) \
+ DO_TO_FIELD (30, ExgGoToType, goToParams) \
+ DO_TO_FIELD (46, UInt16, flags) \
+ DO_TO_FIELD (48, emuptr, description) \
+ DO_TO_FIELD (52, emuptr, type) \
+ DO_TO_FIELD (56, emuptr, name) \
+
+
+// ========================================
+// ===== FieldUndoType =====
+// ========================================
+
+#define FOR_FieldUndoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FieldUndoType, 12, FOR_FieldUndoType_FIELDS)
+
+#define FOR_FieldUndoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UndoMode, mode) \
+ DO_TO_FIELD (1, UInt8, reserved) \
+ DO_TO_FIELD (2, UInt16, start) \
+ DO_TO_FIELD (4, UInt16, end) \
+ DO_TO_FIELD (6, UInt16, bufferLen) \
+ DO_TO_FIELD (8, emuptr, buffer) \
+
+
+// ========================================
+// ===== FixedGlobalsType =====
+// ========================================
+
+#undef memCardInfoP
+
+#define FOR_FixedGlobalsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FixedGlobalsType, 650, FOR_FixedGlobalsType_FIELDS)
+
+#define FOR_FixedGlobalsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, memCardSlots) \
+ DO_TO_FIELD (1, UInt8, dbgWasEntered) \
+ DO_TO_FIELD (2, emuptr, memCardInfoP) \
+ DO_TO_FIELD (6, UInt32, memSemaphoreID) \
+ DO_TO_FIELD (10, UInt16, memDebugMode) \
+ DO_TO_FIELD (12, emuptr, dmOpenList) \
+ DO_TO_FIELD (16, UInt8, dbgInDebugger) \
+ DO_TO_FIELD (17, UInt8, dbgTracing) \
+ DO_TO_FIELD (18, emuptr, dbgGlobalsP) \
+ DO_TO_FIELD (22, emuptr, dbgSerGlobalsP) \
+ DO_TO_FIELD (26, emuptr, sysAppInfoP) \
+ DO_TO_FIELD (30, emuptr, sysKernelDataP) \
+ DO_TO_FIELD (34, emuptr, sysDispatchTableP) \
+ DO_TO_FIELD (38, UInt32, sysOwnerIDsInUse) \
+ DO_TO_FIELD (42, emuptr, sysAMXAppInfoP) \
+ DO_TO_FIELD (46, UInt32, sysClockFreq) \
+ DO_TO_FIELD (50, emuptr, sysHardKeyCreators) \
+ DO_TO_FIELD (54, Int16, sysBatteryCheckTimer) \
+ DO_TO_FIELD (56, UInt8, sysBatteryMinThreshold) \
+ DO_TO_FIELD (57, UInt8, hwrBatteryLevel) \
+ DO_TO_FIELD (58, UInt16, sysNextBatteryAlertTimer) \
+ DO_TO_FIELD (60, UInt8, sysBatteryWarnThreshold) \
+ DO_TO_FIELD (61, UInt8, sysDispatchTableRev) \
+ DO_TO_FIELD (62, UInt16, sysDispatchTableSize) \
+ DO_TO_FIELD (64, emuptr, sysLibTableP) \
+ DO_TO_FIELD (68, UInt16, sysLibTableEntries) \
+ DO_TO_FIELD (70, emuptr, sysConsoleStackChunkP) \
+ DO_TO_FIELD (74, emuptr, sysUIShellAppInfoP) \
+ DO_TO_FIELD (78, UInt32, sysTimerID) \
+ DO_TO_FIELD (82, UInt32, sysAutoOffEvtTicks) \
+ DO_TO_FIELD (86, UInt16, sysAutoOffSeconds) \
+ DO_TO_FIELD (88, Int32, sysRandomSeed) \
+ DO_TO_FIELD (92, emuptr, slkGlobalsP) \
+ DO_TO_FIELD (96, emuptr, serGlobalsP) \
+ DO_TO_FIELD (100, emuptr, scrGlobalsP) \
+ DO_TO_FIELD (104, emuptr, fplGlobalsP) \
+ DO_TO_FIELD (108, emuptr, penGlobalsP) \
+ DO_TO_FIELD (112, emuptr, sysEvtMgrGlobalsP) \
+ DO_TO_FIELD (116, emuptr, sndGlobalsP) \
+ DO_TO_FIELD (120, emuptr, timGlobalsP) \
+ DO_TO_FIELD (124, emuptr, almGlobalsP) \
+ DO_TO_FIELD (128, emuptr, ftrGlobalsP) \
+ DO_TO_FIELD (132, emuptr, grfGlobalsP) \
+ DO_TO_FIELD (136, emuptr, keyGlobalsP) \
+ \
+ DO_TO_FIELD (140, UIGlobalsType, uiGlobals) \
+ DO_TO_FIELD (140, UIGlobalsTypeCommon, uiGlobalsCommon) \
+ DO_TO_FIELD (140, UIGlobalsTypeV1, uiGlobalsV1) \
+ DO_TO_FIELD (140, UIGlobalsTypeV2, uiGlobalsV2) \
+ DO_TO_FIELD (140, UIGlobalsTypeV3, uiGlobalsV3) \
+ DO_TO_FIELD (140, UIGlobalsTypeV31, uiGlobalsV31) \
+ DO_TO_FIELD (140, UIGlobalsTypeV32, uiGlobalsV32) \
+ DO_TO_FIELD (140, UIGlobalsTypeV35, uiGlobalsV35) \
+ \
+ DO_TO_FIELD (316, emuptr, uiExtensionsP) \
+ DO_TO_FIELD (320, emuptr, curUIAppInfoP) \
+ DO_TO_FIELD (324, UInt32, nextUIAppDBID) \
+ DO_TO_FIELD (328, UInt16, nextUIAppCmd) \
+ DO_TO_FIELD (330, emuptr, nextUIAppCmdPBP) \
+ DO_TO_FIELD (334, UInt8, nextUIAppCardNo) \
+ DO_TO_FIELD (335, Int8, memDataWELevel) \
+ DO_TO_FIELD (336, UInt16, hwrWakeUp) \
+ DO_TO_FIELD (338, UInt8, hwrCPUDutyCycle) \
+ DO_TO_FIELD (339, UInt8, hwrPenDown) \
+ DO_TO_FIELD (340, UInt32, hwrCurTicks) \
+ DO_TO_FIELD (344, UInt32, hwrTotalRAMSize) \
+ DO_TO_FIELD (348, UInt32, hwrDozeSubTicks) \
+ DO_TO_FIELD (352, UInt32, sndOffTicks) \
+ DO_TO_FIELD (356, UInt8, sysResetFlags) \
+ DO_TO_FIELD (357, UInt8, sysBatteryKind) \
+ DO_TO_FIELD (358, UInt32, memMinDynHeapFree) \
+ DO_TO_FIELD (362, UInt16, sysPrefFlags) \
+ DO_TO_FIELD (364, emuptr, sysGlobalsP) \
+ DO_TO_FIELD (368, UInt16, sysMiscFlags) \
+ DO_TO_FIELD (370, UInt16, sysLibNet) \
+ DO_TO_FIELD (372, emuptr, netPktFreeQ) \
+ DO_TO_FIELD (376, UInt32, sysEvGroupID) \
+ DO_TO_FIELD (380, emuptr, irq3GlobalsP) \
+ DO_TO_FIELD (384, UInt32, sysLastBatteryWarning) \
+ DO_TO_FIELD (388, UInt32, sysLowMemChecksum) \
+ DO_TO_FIELD (392, UInt16, hwrHardwareRev) \
+ DO_TO_FIELD (394, emuptr, dmProtectListH) \
+ DO_TO_FIELD (398, UInt16, hwrMiscFlags) \
+ DO_TO_FIELD (400, UInt32, sysProfileRefcon) \
+ DO_TO_FIELD (404, emuptr, sysProfileProcP) \
+ DO_TO_FIELD (408, UInt32, flpSoftFPSCR) \
+ DO_TO_FIELD (412, emuptr, irLibGlobalsP) \
+ DO_TO_FIELD (416, UInt16, exgActiveLib) \
+ DO_TO_FIELD (418, UInt16, uiBusyCount) \
+ DO_TO_FIELD (420, emuptr, irq1GlobalsP) \
+ DO_TO_FIELD (424, emuptr, irq2GlobalsP) \
+ DO_TO_FIELD (428, emuptr, irq6GlobalsP) \
+ DO_TO_FIELD (432, emuptr, intlMgrGlobalsP) \
+ DO_TO_FIELD (436, UInt16, inlineStart) \
+ DO_TO_FIELD (438, UInt16, inlineEnd) \
+ DO_TO_FIELD (440, Boolean, inlineActive) \
+ DO_TO_FIELD (441, UInt8, inlineDefTerm) \
+ DO_TO_FIELD (442, emuptr, tsmFepLibStatusP) \
+ DO_TO_FIELD (446, UInt16, tsmFepLibRefNum) \
+ DO_TO_FIELD (448, UInt16, inlineHighlightLen) \
+ DO_TO_FIELD (450, emuptr, sysBatteryDataP) \
+ DO_TO_FIELD (454, emuptr, sysBatteryValidKindsP) \
+ DO_TO_FIELD (458, Boolean, sysInShutdown) \
+ DO_TO_FIELD (459, UInt8, sysMinWakeupThreshold) \
+ DO_TO_FIELD (460, UInt32, hwrMiscFlagsExt) \
+ DO_TO_FIELD (464, Boolean, sysUseCritWarnTimer) \
+ DO_TO_FIELD (465, Boolean, sysCritWarnTimerRunning) \
+ DO_TO_FIELD (466, Int16, sysCritWarnRTCDayStarted) \
+ DO_TO_FIELD (468, Int32, sysCritWarnTickTimer) \
+ DO_TO_FIELD (472, UInt32, sysCritWarnLastTick) \
+ DO_TO_FIELD (476, Boolean, sysCharging) \
+ DO_TO_FIELD (477, Boolean, sysUpdateVoltageLevel) \
+ DO_TO_FIELD (478, emuptr, notifyGlobalsH) \
+ DO_TO_FIELD (482, UInt32, expGlobalsP) \
+ DO_TO_FIELD (486, UInt32, vfsGlobalsP) \
+ DO_TO_FIELD (490, UInt32, sysReserved31DWord3) \
+ DO_TO_FIELD (494, UInt32, sysReserved31DWord4) \
+ DO_TO_FIELD (498, emuptr, ramGlobalsP) \
+ DO_TO_FIELD (502, emuptr, hwrBatteryGlobalsP) \
+ DO_TO_FIELD (506, UInt8, hwrBatteryPercent) \
+ DO_TO_FIELD (507, UInt8, commActivityFlags) \
+ DO_TO_FIELD (508, emuptr, uart328GlobalsP) \
+ DO_TO_FIELD (512, UInt32, sysOEMGlobal1) \
+ DO_TO_FIELD (516, UInt32, sysOEMGlobal2) \
+ DO_TO_FIELD (520, UInt16, hwrBatteryStepsPerVolt) \
+ DO_TO_FIELD (522, emuptr, sysPendingStackFrees) \
+ DO_TO_FIELD (526, UInt16, sysDayCounter) \
+ DO_TO_FIELD (528, Int16, sysBatteryCheckPeriod) \
+ DO_TO_FIELD (530, UInt16, hwrJerryPldShadow) \
+ DO_TO_FIELD (532, emuptr, radioGlobalsP) \
+ DO_TO_FIELD (536, emuptr, fatalAlertTemplateP) \
+ DO_TO_FIELD (540, UInt16, fatalAlertBtnWidth) \
+ DO_TO_FIELD (542, emuptr, silkscreenInfoP) \
+ DO_TO_FIELD (546, UInt16, inlineDefChecksum) \
+ DO_TO_FIELD (548, emuptr, inlineDefField) \
+ DO_TO_FIELD (552, Boolean, notifyBroadcastPending) \
+ DO_TO_FIELD (553, UInt8, sysReserved35Byte1) \
+ DO_TO_FIELD (554, UInt32, hwrOEMCompanyID) \
+ DO_TO_FIELD (558, UInt32, hwrOEMDeviceID) \
+ DO_TO_FIELD (562, UInt32, hwrOEMHALID) \
+ DO_TO_FIELD (566, emuptr, sysUpdateGlobalsP) \
+ DO_TO_FIELD (570, UInt16, smallROMChecksum) \
+ DO_TO_FIELD (572, emuptr, sysNotifyInterruptGlobalsP) \
+ DO_TO_FIELD (576, emuptr, sysAppSubFontListPtr) \
+ DO_TO_FIELD (580, UInt16, sysUSBConfiguration) \
+ DO_TO_FIELD (582, emuptr, intlDispatchTableP) \
+ DO_TO_FIELD (586, Boolean, sysAutoLockUponPowerOff) \
+ DO_TO_FIELD (588, UInt32, sysHardPowerEvtTicks) \
+ DO_TO_FIELD (592, UInt32, sysAutoLockTimeoutSecs) \
+ DO_TO_FIELD (596, emuptr, attnGlobalsP) \
+ DO_TO_FIELD (600, emuptr, expVfsSharedGlobalsP) \
+ DO_TO_FIELD (604, emuptr, btExgLibGlobalsP) \
+ DO_TO_FIELD (608, emuptr, testHarnessGlobalsP) \
+ DO_TO_FIELD (612, emuptr, pwrManagerGlobalsP) \
+ DO_TO_FIELD (616, UInt16, inlineClauseOffset) \
+ DO_TO_FIELD (618, emuptr, btLibGlobalsP) \
+ DO_TO_FIELD (622, Boolean, sysSetPwdTimeoutAllowed) \
+ DO_TO_FIELD (624, UInt32, sysSetPwdTimeoutSecs) \
+ DO_TO_FIELD (628, UInt32, sysSetPwdTimeoutTicks) \
+ DO_TO_FIELD (632, UInt16, dbgLockout) \
+ DO_TO_FIELD (634, UInt32, sysReserved40DWord1) \
+ DO_TO_FIELD (638, UInt32, sysReserved40DWord2) \
+ DO_TO_FIELD (642, UInt32, sysReserved40DWord3) \
+ DO_TO_FIELD (646, UInt32, sysReserved40DWord4) \
+
+
+// ========================================
+// ===== FieldAttrType =====
+// ========================================
+
+#define FOR_FieldAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FieldAttrType, 2, FOR_FieldAttrType_FIELDS)
+
+#define FOR_FieldAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== FieldType =====
+// ========================================
+
+#define FOR_FieldType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FieldType, 40, FOR_FieldType_FIELDS)
+
+#define FOR_FieldType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, RectangleType, rect) \
+ DO_TO_FIELD (10, FieldAttrType, attr) \
+ DO_TO_FIELD (12, emuptr, text) \
+ DO_TO_FIELD (16, emuptr, textHandle) \
+ DO_TO_FIELD (20, emuptr, lines) \
+ DO_TO_FIELD (24, UInt16, textLen) \
+ DO_TO_FIELD (26, UInt16, textBlockSize) \
+ DO_TO_FIELD (28, UInt16, maxChars) \
+ DO_TO_FIELD (30, UInt16, selFirstPos) \
+ DO_TO_FIELD (32, UInt16, selLastPos) \
+ DO_TO_FIELD (34, UInt16, insPtXPos) \
+ DO_TO_FIELD (36, UInt16, insPtYPos) \
+ DO_TO_FIELD (38, FontID, fontID) \
+ DO_TO_FIELD (39, UInt16, maxVisibleLines) \
+
+
+// ========================================
+// ===== FormBitmapType =====
+// ========================================
+
+#define FOR_FormBitmapType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormBitmapType, 8, FOR_FormBitmapType_FIELDS)
+
+#define FOR_FormBitmapType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, FormObjAttrType, attr) \
+ DO_TO_FIELD (2, PointType, pos) \
+ DO_TO_FIELD (6, UInt16, rscID) \
+
+
+// ========================================
+// ===== FormFrameType =====
+// ========================================
+
+#define FOR_FormFrameType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormFrameType, 14, FOR_FormFrameType_FIELDS)
+
+#define FOR_FormFrameType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, FormObjAttrType, attr) \
+ DO_TO_FIELD (4, RectangleType, rect) \
+ DO_TO_FIELD (12, UInt16, frameType) \
+
+
+// ========================================
+// ===== FormGadgetAttrType =====
+// ========================================
+
+#define FOR_FormGadgetAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormGadgetAttrType, 2, FOR_FormGadgetAttrType_FIELDS)
+
+#define FOR_FormGadgetAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== FormGadgetType =====
+// ========================================
+
+#define FOR_FormGadgetType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormGadgetType, 20, FOR_FormGadgetType_FIELDS)
+
+#define FOR_FormGadgetType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, FormGadgetAttrType, attr) \
+ DO_TO_FIELD (4, RectangleType, rect) \
+ DO_TO_FIELD (12, emuptr, data) \
+ DO_TO_FIELD (16, emuptr, handler) \
+
+
+// ========================================
+// ===== FormLabelType =====
+// ========================================
+
+#define FOR_FormLabelType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormLabelType, 14, FOR_FormLabelType_FIELDS)
+
+#define FOR_FormLabelType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, PointType, pos) \
+ DO_TO_FIELD (6, FormObjAttrType, attr) \
+ DO_TO_FIELD (8, FontID, fontID) \
+ DO_TO_FIELD (9, UInt8, reserved) \
+ DO_TO_FIELD (10, emuptr, text) \
+
+
+// ========================================
+// ===== FormLineType =====
+// ========================================
+
+#define FOR_FormLineType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormLineType, 10, FOR_FormLineType_FIELDS)
+
+#define FOR_FormLineType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, attr) \
+ DO_TO_FIELD (2, PointType, point1) \
+ DO_TO_FIELD (6, PointType, point2) \
+
+
+// ========================================
+// ===== FormObjAttrType =====
+// ========================================
+
+#define FOR_FormObjAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormObjAttrType, 2, FOR_FormObjAttrType_FIELDS)
+
+#define FOR_FormObjAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== FormObjListType =====
+// ========================================
+
+#define FOR_FormObjListType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormObjListType, 6, FOR_FormObjListType_FIELDS)
+
+#define FOR_FormObjListType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, FormObjectKind, objectType) \
+ DO_TO_FIELD (1, UInt8, reserved) \
+ DO_TO_FIELD (2, emuptr, object) \
+
+
+// ========================================
+// ===== FormPopupType =====
+// ========================================
+
+#define FOR_FormPopupType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormPopupType, 4, FOR_FormPopupType_FIELDS)
+
+#define FOR_FormPopupType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, controlID) \
+ DO_TO_FIELD (2, UInt16, listID) \
+
+
+// ========================================
+// ===== FormRectangleType =====
+// ========================================
+
+#define FOR_FormRectangleType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormRectangleType, 10, FOR_FormRectangleType_FIELDS)
+
+#define FOR_FormRectangleType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, FormObjAttrType, attr) \
+ DO_TO_FIELD (2, RectangleType, rect) \
+
+
+// ========================================
+// ===== FormTitleType =====
+// ========================================
+
+#define FOR_FormTitleType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormTitleType, 12, FOR_FormTitleType_FIELDS)
+
+#define FOR_FormTitleType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, RectangleType, rect) \
+ DO_TO_FIELD (8, emuptr, text) \
+
+
+// ========================================
+// ===== FormType =====
+// ========================================
+
+#define FOR_FormType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormType, 68, FOR_FormType_FIELDS)
+
+#define FOR_FormType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, WindowType, window) \
+ DO_TO_FIELD (40, UInt16, formId) \
+ DO_TO_FIELD (42, FormAttrType, attr) \
+ DO_TO_FIELD (46, emuptr, bitsBehindForm) \
+ DO_TO_FIELD (50, emuptr, handler) \
+ DO_TO_FIELD (54, UInt16, focus) \
+ DO_TO_FIELD (56, UInt16, defaultButton) \
+ DO_TO_FIELD (58, UInt16, helpRscId) \
+ DO_TO_FIELD (60, UInt16, menuRscId) \
+ DO_TO_FIELD (62, UInt16, numObjects) \
+ DO_TO_FIELD (64, emuptr, objects) \
+
+
+// ========================================
+// ===== FrameBitsType =====
+// ========================================
+
+#define FOR_FrameBitsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FrameBitsType, 2, FOR_FrameBitsType_FIELDS)
+
+#define FOR_FrameBitsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== FrmGraffitiStateType =====
+// ========================================
+
+#define FOR_FrmGraffitiStateType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FrmGraffitiStateType, 4, FOR_FrmGraffitiStateType_FIELDS)
+
+#define FOR_FrmGraffitiStateType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, PointType, pos) \
+
+
+// ========================================
+// ===== GraphicControlType =====
+// ========================================
+
+#define FOR_GraphicControlType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (GraphicControlType, 20, FOR_GraphicControlType_FIELDS)
+
+#define FOR_GraphicControlType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, RectangleType, bounds) \
+ DO_TO_FIELD (10, DmResID, bitmapID) \
+ DO_TO_FIELD (12, DmResID, selectedBitmapID) \
+ DO_TO_FIELD (14, ControlAttrType, attr) \
+ DO_TO_FIELD (16, ControlStyleType, style) \
+ DO_TO_FIELD (17, UInt8, unused) \
+ DO_TO_FIELD (18, UInt8, group) \
+ DO_TO_FIELD (19, UInt8, reserved) \
+
+
+// ========================================
+// ===== GraphicStateTypeV1 =====
+// ========================================
+// Used in Palm OS 1.0 - 2.0.
+
+#define FOR_GraphicStateTypeV1_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (GraphicStateTypeV1, 20, FOR_GraphicStateTypeV1_FIELDS)
+
+#define FOR_GraphicStateTypeV1_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, ScrOperation, grafMode) \
+ DO_TO_FIELD (1, Boolean, patternMode) \
+ DO_TO_FIELD (2, PatternType, pattern) \
+ DO_TO_FIELD (4, UInt16, customPtn) \
+ DO_TO_FIELD (12, FontID, fontId) \
+ DO_TO_FIELD (14, emuptr, font) \
+ DO_TO_FIELD (18, UnderlineModeType, underlineMode) \
+
+
+// ========================================
+// ===== GraphicStateTypeV2 =====
+// ========================================
+// Used in Palm OS 3.0 - 3.3.
+
+#define FOR_GraphicStateTypeV2_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (GraphicStateTypeV2, 28, FOR_GraphicStateTypeV2_FIELDS)
+
+#define FOR_GraphicStateTypeV2_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, ScrOperation, grafMode) \
+ DO_TO_FIELD (1, Boolean, patternMode) \
+ DO_TO_FIELD (2, PatternType, pattern) \
+ DO_TO_FIELD (4, UInt16, customPtn) \
+ DO_TO_FIELD (12, FontID, fontId) \
+ DO_TO_FIELD (14, emuptr, font) \
+ DO_TO_FIELD (18, UnderlineModeType, underlineMode) \
+ DO_TO_FIELD (20, RGBColorType, foreColor) \
+ DO_TO_FIELD (24, RGBColorType, backColor) \
+
+
+// ========================================
+// ===== GraphicStateTypeV3 =====
+// ========================================
+// Used in Palm OS 3.5 and later.
+
+#define FOR_GraphicStateTypeV3_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (GraphicStateTypeV3, 12, FOR_GraphicStateTypeV3_FIELDS)
+
+#define FOR_GraphicStateTypeV3_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, drawStateP) \
+ DO_TO_FIELD (4, emuptr, drawStateStackP) \
+ DO_TO_FIELD (8, Int16, drawStateIndex) \
+ DO_TO_FIELD (10, UInt16, screenLockCount) \
+
+
+// ========================================
+// ===== FormAttrType =====
+// ========================================
+
+#define FOR_FormAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (FormAttrType, 4, FOR_FormAttrType_FIELDS)
+
+#define FOR_FormAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, flags) \
+
+
+// ========================================
+// ===== HostDirEntType =====
+// ========================================
+
+#define FOR_HostDirEntType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HostDirEntType, 256, FOR_HostDirEntType_FIELDS)
+
+#define FOR_HostDirEntType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int8, d_name) \
+
+
+// ========================================
+// ===== HostGremlinInfoType =====
+// ========================================
+
+#define FOR_HostGremlinInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HostGremlinInfoType, 220, FOR_HostGremlinInfoType_FIELDS)
+
+#define FOR_HostGremlinInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int32, fFirstGremlin) \
+ DO_TO_FIELD (4, Int32, fLastGremlin) \
+ DO_TO_FIELD (8, Int32, fSaveFrequency) \
+ DO_TO_FIELD (12, Int32, fSwitchDepth) \
+ DO_TO_FIELD (16, Int32, fMaxDepth) \
+ DO_TO_FIELD (20, Int8, fAppNames) \
+
+
+// ========================================
+// ===== HostStatType =====
+// ========================================
+
+#define FOR_HostStatType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HostStatType, 56, FOR_HostStatType_FIELDS)
+
+#define FOR_HostStatType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int32, st_dev_) \
+ DO_TO_FIELD (4, Int32, st_ino_) \
+ DO_TO_FIELD (8, Int32, st_mode_) \
+ DO_TO_FIELD (12, Int32, st_nlink_) \
+ DO_TO_FIELD (16, Int32, st_uid_) \
+ DO_TO_FIELD (20, Int32, st_gid_) \
+ DO_TO_FIELD (24, Int32, st_rdev_) \
+ DO_TO_FIELD (28, HostTimeType, st_atime_) \
+ DO_TO_FIELD (32, HostTimeType, st_mtime_) \
+ DO_TO_FIELD (36, HostTimeType, st_ctime_) \
+ DO_TO_FIELD (40, Int32, st_size_) \
+ DO_TO_FIELD (44, Int32, st_blksize_) \
+ DO_TO_FIELD (48, Int32, st_blocks_) \
+ DO_TO_FIELD (52, Int32, st_flags_) \
+
+
+// ========================================
+// ===== HostTmType =====
+// ========================================
+
+#define FOR_HostTmType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HostTmType, 36, FOR_HostTmType_FIELDS)
+
+#define FOR_HostTmType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int32, tm_sec_) \
+ DO_TO_FIELD (4, Int32, tm_min_) \
+ DO_TO_FIELD (8, Int32, tm_hour_) \
+ DO_TO_FIELD (12, Int32, tm_mday_) \
+ DO_TO_FIELD (16, Int32, tm_mon_) \
+ DO_TO_FIELD (20, Int32, tm_year_) \
+ DO_TO_FIELD (24, Int32, tm_wday_) \
+ DO_TO_FIELD (28, Int32, tm_yday_) \
+ DO_TO_FIELD (32, Int32, tm_isdst_) \
+
+
+// ========================================
+// ===== HostUTimeType =====
+// ========================================
+
+#define FOR_HostUTimeType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HostUTimeType, 12, FOR_HostUTimeType_FIELDS)
+
+#define FOR_HostUTimeType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, HostTimeType, crtime_) \
+ DO_TO_FIELD (4, HostTimeType, actime_) \
+ DO_TO_FIELD (8, HostTimeType, modtime_) \
+
+
+// ========================================
+// ===== HwrBatCmdReadType =====
+// ========================================
+
+#define FOR_HwrBatCmdReadType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrBatCmdReadType, 4, FOR_HwrBatCmdReadType_FIELDS)
+
+#define FOR_HwrBatCmdReadType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, mVolts) \
+ DO_TO_FIELD (2, UInt16, abs) \
+
+
+// ========================================
+// ===== HwrJerryPLDType =====
+// ========================================
+
+#define FOR_HwrJerryPLDType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrJerryPLDType, 20, FOR_HwrJerryPLDType_FIELDS)
+
+#define FOR_HwrJerryPLDType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, dspOn) \
+ DO_TO_FIELD (1, UInt8, unused1) \
+ DO_TO_FIELD (2, UInt8, chargeOn) \
+ DO_TO_FIELD (3, UInt8, unused2) \
+ DO_TO_FIELD (4, UInt8, refOn) \
+ DO_TO_FIELD (5, UInt8, unused3) \
+ DO_TO_FIELD (6, UInt8, pipaBiasEnable) \
+ DO_TO_FIELD (7, UInt8, unused4) \
+ DO_TO_FIELD (8, UInt8, dspReset) \
+ DO_TO_FIELD (9, UInt8, unused5) \
+ DO_TO_FIELD (10, UInt8, ezToDsl) \
+ DO_TO_FIELD (11, UInt8, unused6) \
+ DO_TO_FIELD (12, UInt8, rs232Shdn) \
+ DO_TO_FIELD (13, UInt8, unused7) \
+ DO_TO_FIELD (14, UInt8, spareOut) \
+ DO_TO_FIELD (15, UInt8, unused8) \
+ DO_TO_FIELD (16, UInt16, dTo3Sln) \
+ DO_TO_FIELD (17, UInt16, iXtrnl2) \
+
+
+// ========================================
+// ===== HwrLAPType =====
+// ========================================
+
+#define FOR_HwrLAPType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrLAPType, 0x64, FOR_HwrLAPType_FIELDS)
+
+#define FOR_HwrLAPType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0x000, UInt32, control) \
+ DO_TO_FIELD (0x010, UInt32, status) \
+ DO_TO_FIELD (0x040, UInt32, timing0) \
+ DO_TO_FIELD (0x050, UInt32, timing1) \
+ DO_TO_FIELD (0x060, UInt32, timing2) \
+
+
+// ========================================
+// ===== HwrMediaQ11xxType =====
+// ========================================
+
+#define FOR_HwrMediaQ11xxType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrMediaQ11xxType, 0x2000, FOR_HwrMediaQ11xxType_FIELDS)
+
+#define FOR_HwrMediaQ11xxType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0x000, UInt32, ccREG) \
+ DO_TO_FIELD (0x080, UInt32, mmREG) \
+ DO_TO_FIELD (0x100, UInt32, inREG) \
+ DO_TO_FIELD (0x180, UInt32, gcREG) \
+ DO_TO_FIELD (0x200, UInt32, geREG) \
+ DO_TO_FIELD (0x280, UInt32, ssREG) \
+ DO_TO_FIELD (0x300, UInt32, spREG) \
+ DO_TO_FIELD (0x380, UInt32, dcREG) \
+ DO_TO_FIELD (0x400, UInt32, pcREG) \
+ DO_TO_FIELD (0x500, UInt32, uhREG) \
+ DO_TO_FIELD (0x600, UInt32, fpREG) \
+ DO_TO_FIELD (0x800, UInt32, cpREG) \
+ DO_TO_FIELD (0xC00, UInt32, sfREG) \
+ DO_TO_FIELD (0x1000,UInt32, udREG) \
+
+
+// ========================================
+// ===== HwrPalmI705PLDType =====
+// ========================================
+
+#define FOR_HwrPalmI705PLDType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrPalmI705PLDType, 42, FOR_HwrPalmI705PLDType_FIELDS)
+
+#define FOR_HwrPalmI705PLDType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, todsln3) \
+ DO_TO_FIELD (2, UInt16, green_led) \
+ DO_TO_FIELD (4, UInt16, pin_notify_enable) \
+ DO_TO_FIELD (6, UInt16, red_led) \
+ DO_TO_FIELD (8, UInt16, acpr) \
+ DO_TO_FIELD (10, UInt16, low_batt) \
+ DO_TO_FIELD (12, UInt16, dto3svc_irq) \
+ DO_TO_FIELD (14, UInt16, dsp_irq_enable) \
+ DO_TO_FIELD (16, UInt16, dsp_irq_polarity) \
+ DO_TO_FIELD (18, UInt16, charging_in_progress) \
+ DO_TO_FIELD (20, UInt16, charging_in_prog2) \
+ DO_TO_FIELD (22, UInt16, charging_in_prog_OE) \
+ DO_TO_FIELD (24, UInt16, twister_irq_wake) \
+ DO_TO_FIELD (26, UInt16, low_batt_mask) \
+ DO_TO_FIELD (28, UInt16, acpr_mask) \
+ DO_TO_FIELD (30, UInt16, acpr_polarity) \
+ DO_TO_FIELD (32, UInt16, usb_int) \
+ DO_TO_FIELD (34, UInt16, usb_int_mask) \
+ DO_TO_FIELD (36, UInt16, bullet_det) \
+ DO_TO_FIELD (38, UInt16, bullet_det_mask) \
+ DO_TO_FIELD (40, UInt16, bullet_det_pol) \
+
+
+// ========================================
+// ===== HwrSymbolASICType =====
+// ========================================
+
+#define FOR_HwrSymbolASICType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (HwrSymbolASICType, 256, FOR_HwrSymbolASICType_FIELDS)
+
+#define FOR_HwrSymbolASICType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, S24IO) \
+ DO_TO_FIELD (128, UInt8, S24Attribute) \
+ DO_TO_FIELD (160, UInt8, UART8251MacroSelect) \
+ DO_TO_FIELD (165, UInt8, ScannerDecoderControl) \
+ DO_TO_FIELD (247, UInt8, Control) \
+ DO_TO_FIELD (253, UInt8, GPIOData) \
+ DO_TO_FIELD (255, UInt8, GPIODirection) \
+
+
+// ========================================
+// ===== ListAttrType =====
+// ========================================
+
+#define FOR_ListAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ListAttrType, 2, FOR_ListAttrType_FIELDS)
+
+#define FOR_ListAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== ListType =====
+// ========================================
+
+#define FOR_ListType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ListType, 32, FOR_ListType_FIELDS)
+
+#define FOR_ListType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, RectangleType, bounds) \
+ DO_TO_FIELD (10, ListAttrType, attr) \
+ DO_TO_FIELD (12, emuptr, itemsText) \
+ DO_TO_FIELD (16, Int16, numItems) \
+ DO_TO_FIELD (18, Int16, currentItem) \
+ DO_TO_FIELD (20, Int16, topItem) \
+ DO_TO_FIELD (22, FontID, font) \
+ DO_TO_FIELD (23, UInt8, reserved) \
+ DO_TO_FIELD (24, emuptr, popupWin) \
+ DO_TO_FIELD (28, emuptr, drawItemsCallback) \
+
+
+// ========================================
+// ===== LowMemHdrType =====
+// ========================================
+
+#define FOR_LowMemHdrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (LowMemHdrType, 828, FOR_LowMemHdrType_FIELDS)
+
+#define FOR_LowMemHdrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, M68KExcTableType, vectors) \
+ DO_TO_FIELD (256, FixedGlobalsType, globals) \
+
+
+// ========================================
+// ===== M68KExcTableType =====
+// ========================================
+
+#define FOR_M68KExcTableType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (M68KExcTableType, 256, FOR_M68KExcTableType_FIELDS)
+
+#define FOR_M68KExcTableType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, initStack) \
+ DO_TO_FIELD (4, UInt32, initPC) \
+ DO_TO_FIELD (8, UInt32, busErr) \
+ DO_TO_FIELD (12, UInt32, addressErr) \
+ DO_TO_FIELD (16, UInt32, illegalInstr) \
+ DO_TO_FIELD (20, UInt32, divideByZero) \
+ DO_TO_FIELD (24, UInt32, chk) \
+ DO_TO_FIELD (28, UInt32, trap) \
+ DO_TO_FIELD (32, UInt32, privilege) \
+ DO_TO_FIELD (36, UInt32, trace) \
+ DO_TO_FIELD (40, UInt32, aTrap) \
+ DO_TO_FIELD (44, UInt32, fTrap) \
+ DO_TO_FIELD (48, UInt32, reserved12) \
+ DO_TO_FIELD (52, UInt32, coproc) \
+ DO_TO_FIELD (56, UInt32, formatErr) \
+ DO_TO_FIELD (60, UInt32, unitializedInt) \
+ DO_TO_FIELD (96, UInt32, spuriousInt) \
+ DO_TO_FIELD (100, UInt32, autoVec1) \
+ DO_TO_FIELD (104, UInt32, autoVec2) \
+ DO_TO_FIELD (108, UInt32, autoVec3) \
+ DO_TO_FIELD (112, UInt32, autoVec4) \
+ DO_TO_FIELD (116, UInt32, autoVec5) \
+ DO_TO_FIELD (120, UInt32, autoVec6) \
+ DO_TO_FIELD (124, UInt32, autoVec7) \
+
+
+// ========================================
+// ===== M68KRegsType =====
+// ========================================
+
+#define FOR_M68KRegsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (M68KRegsType, 74, FOR_M68KRegsType_FIELDS)
+
+#define FOR_M68KRegsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, d) \
+ DO_TO_FIELD (32, UInt32, a) \
+ DO_TO_FIELD (60, UInt32, usp) \
+ DO_TO_FIELD (64, UInt32, ssp) \
+ DO_TO_FIELD (68, UInt32, pc) \
+ DO_TO_FIELD (72, UInt16, sr) \
+
+
+// ========================================
+// ===== NetHostInfoBufType =====
+// ========================================
+
+#define FOR_NetHostInfoBufType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetHostInfoBufType, 568, FOR_NetHostInfoBufType_FIELDS)
+
+#define FOR_NetHostInfoBufType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, NetHostInfoType, hostInfo) \
+ DO_TO_FIELD (16, Char, name) \
+ DO_TO_FIELD (272, emuptr, aliasList) \
+ DO_TO_FIELD (280, Char, aliases) \
+ DO_TO_FIELD (536, emuptr, addressList) \
+ DO_TO_FIELD (552, NetIPAddr, address) \
+
+
+// ========================================
+// ===== NetHostInfoType =====
+// ========================================
+
+#define FOR_NetHostInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetHostInfoType, 16, FOR_NetHostInfoType_FIELDS)
+
+#define FOR_NetHostInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, nameP) \
+ DO_TO_FIELD (4, emuptr, nameAliasesP) \
+ DO_TO_FIELD (8, UInt16, addrType) \
+ DO_TO_FIELD (10, UInt16, addrLen) \
+ DO_TO_FIELD (12, emuptr, addrListP) \
+
+
+// ========================================
+// ===== NetIOParamType =====
+// ========================================
+
+#define FOR_NetIOParamType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetIOParamType, 18, FOR_NetIOParamType_FIELDS)
+
+#define FOR_NetIOParamType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, addrP) \
+ DO_TO_FIELD (4, UInt16, addrLen) \
+ DO_TO_FIELD (6, emuptr, iov) \
+ DO_TO_FIELD (10, UInt16, iovLen) \
+ DO_TO_FIELD (12, emuptr, accessRights) \
+ DO_TO_FIELD (16, UInt16, accessRightsLen) \
+
+
+// ========================================
+// ===== NetIOVecType =====
+// ========================================
+
+#define FOR_NetIOVecType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetIOVecType, 6, FOR_NetIOVecType_FIELDS)
+
+#define FOR_NetIOVecType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, bufP) \
+ DO_TO_FIELD (4, UInt16, bufLen) \
+
+
+// ========================================
+// ===== NetServInfoBufType =====
+// ========================================
+
+#define FOR_NetServInfoBufType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetServInfoBufType, 70, FOR_NetServInfoBufType_FIELDS)
+
+#define FOR_NetServInfoBufType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, NetServInfoType, servInfo) \
+ DO_TO_FIELD (14, Char, name) \
+ DO_TO_FIELD (30, emuptr, aliasList) \
+ DO_TO_FIELD (38, Char, aliases) \
+ DO_TO_FIELD (53, Char, protoName) \
+ DO_TO_FIELD (69, UInt8, reserved) \
+
+
+// ========================================
+// ===== NetServInfoType =====
+// ========================================
+
+#define FOR_NetServInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetServInfoType, 14, FOR_NetServInfoType_FIELDS)
+
+#define FOR_NetServInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, nameP) \
+ DO_TO_FIELD (4, emuptr, nameAliasesP) \
+ DO_TO_FIELD (8, UInt16, port) \
+ DO_TO_FIELD (10, emuptr, protoP) \
+
+
+// ========================================
+// ===== NetSocketAddrINType =====
+// ========================================
+
+#define FOR_NetSocketAddrINType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetSocketAddrINType, 8, FOR_NetSocketAddrINType_FIELDS)
+
+#define FOR_NetSocketAddrINType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, family) \
+ DO_TO_FIELD (2, UInt16, port) \
+ DO_TO_FIELD (4, NetIPAddr, addr) \
+
+
+// ========================================
+// ===== NetSocketAddrRawType =====
+// ========================================
+
+#define FOR_NetSocketAddrRawType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetSocketAddrRawType, 8, FOR_NetSocketAddrRawType_FIELDS)
+
+#define FOR_NetSocketAddrRawType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, family) \
+ DO_TO_FIELD (2, UInt16, ifInstance) \
+ DO_TO_FIELD (4, UInt32, ifCreator) \
+
+
+// ========================================
+// ===== NetSocketAddrType =====
+// ========================================
+
+#define FOR_NetSocketAddrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (NetSocketAddrType, 16, FOR_NetSocketAddrType_FIELDS)
+
+#define FOR_NetSocketAddrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, family) \
+ DO_TO_FIELD (2, UInt8, data) \
+
+
+// ========================================
+// ===== PenBtnInfoType =====
+// ========================================
+
+#define FOR_PenBtnInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (PenBtnInfoType, 14, FOR_PenBtnInfoType_FIELDS)
+
+#define FOR_PenBtnInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, RectangleType, boundsR) \
+ DO_TO_FIELD (8, WChar, asciiCode) \
+ DO_TO_FIELD (10, UInt16, keyCode) \
+ DO_TO_FIELD (12, UInt16, modifiers) \
+
+
+// ========================================
+// ===== PointType =====
+// ========================================
+
+#define FOR_PointType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (PointType, 4, FOR_PointType_FIELDS)
+
+#define FOR_PointType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Coord, x) \
+ DO_TO_FIELD (2, Coord, y) \
+
+
+// ========================================
+// ===== RecordEntryType =====
+// ========================================
+
+#define FOR_RecordEntryType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (RecordEntryType, 8, FOR_RecordEntryType_FIELDS)
+
+#define FOR_RecordEntryType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, LocalID, localChunkID) \
+ DO_TO_FIELD (4, UInt8, attributes) \
+ DO_TO_FIELD (5, UInt8, uniqueID) \
+
+
+// ========================================
+// ===== RecordListType =====
+// ========================================
+
+#define FOR_RecordListType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (RecordListType, 6, FOR_RecordListType_FIELDS)
+
+#define FOR_RecordListType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, LocalID, nextRecordListID) \
+ DO_TO_FIELD (4, UInt16, numRecords) \
+ DO_TO_FIELD (6, RecordEntryType, records) \
+ DO_TO_FIELD (6, RsrcEntryType, resources) \
+
+
+// ========================================
+// ===== RectangleType =====
+// ========================================
+
+#undef topLeft
+
+#define FOR_RectangleType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (RectangleType, 8, FOR_RectangleType_FIELDS)
+
+#define FOR_RectangleType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, PointType, topLeft) \
+ DO_TO_FIELD (4, PointType, extent) \
+
+
+// ========================================
+// ===== RGBColorType =====
+// ========================================
+
+#define FOR_RGBColorType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (RGBColorType, 6, FOR_RGBColorType_FIELDS)
+
+#define FOR_RGBColorType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, LocalID, index) \
+ DO_TO_FIELD (4, UInt8, r) \
+ DO_TO_FIELD (6, UInt8, g) \
+ DO_TO_FIELD (6, UInt8, b) \
+
+
+// ========================================
+// ===== RsrcEntryType =====
+// ========================================
+
+#define FOR_RsrcEntryType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (RsrcEntryType, 10, FOR_RsrcEntryType_FIELDS)
+
+#define FOR_RsrcEntryType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, type) \
+ DO_TO_FIELD (4, UInt16, id) \
+ DO_TO_FIELD (6, LocalID, localChunkID) \
+
+
+// ========================================
+// ===== ScrollBarAttrType =====
+// ========================================
+
+#define FOR_ScrollBarAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ScrollBarAttrType, 2, FOR_ScrollBarAttrType_FIELDS)
+
+#define FOR_ScrollBarAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== ScrollBarType =====
+// ========================================
+
+#define FOR_ScrollBarType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ScrollBarType, 24, FOR_ScrollBarType_FIELDS)
+
+#define FOR_ScrollBarType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, RectangleType, bounds) \
+ DO_TO_FIELD (8, UInt16, id) \
+ DO_TO_FIELD (10, ScrollBarAttrType, attr) \
+ DO_TO_FIELD (12, Int16, value) \
+ DO_TO_FIELD (14, Int16, minValue) \
+ DO_TO_FIELD (16, Int16, maxValue) \
+ DO_TO_FIELD (18, Int16, pageSize) \
+ DO_TO_FIELD (20, Int16, penPosInCar) \
+ DO_TO_FIELD (22, Int16, savePos) \
+
+
+// ========================================
+// ===== SED1375RegsType =====
+// ========================================
+
+#define FOR_SED1375RegsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SED1375RegsType, 32, FOR_SED1375RegsType_FIELDS)
+
+#define FOR_SED1375RegsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, productRevisionCode) \
+ DO_TO_FIELD (1, UInt8, mode0) \
+ DO_TO_FIELD (2, UInt8, mode1) \
+ DO_TO_FIELD (3, UInt8, mode2) \
+ DO_TO_FIELD (4, UInt8, horizontalPanelSize) \
+ DO_TO_FIELD (5, UInt8, verticalPanelSizeLSB) \
+ DO_TO_FIELD (6, UInt8, verticalPanelSizeMSB) \
+ DO_TO_FIELD (7, UInt8, FPLineStartPosition) \
+ DO_TO_FIELD (8, UInt8, horizontalNonDisplayPeriod) \
+ DO_TO_FIELD (9, UInt8, FPFRAMEStartPosition) \
+ DO_TO_FIELD (10, UInt8, verticalNonDisplayPeriod) \
+ DO_TO_FIELD (11, UInt8, MODRate) \
+ DO_TO_FIELD (12, UInt8, screen1StartAddressLSB) \
+ DO_TO_FIELD (13, UInt8, screen1StartAddressMSB) \
+ DO_TO_FIELD (14, UInt8, screen2StartAddressLSB) \
+ DO_TO_FIELD (15, UInt8, screen2StartAddressMSB) \
+ DO_TO_FIELD (16, UInt8, screen1StartAddressMSBit) \
+ DO_TO_FIELD (17, UInt8, memoryAddressOffset) \
+ DO_TO_FIELD (18, UInt8, screen1VerticalSizeLSB) \
+ DO_TO_FIELD (19, UInt8, screen1VerticalSizeMSB) \
+ DO_TO_FIELD (20, UInt8, unused1) \
+ DO_TO_FIELD (21, UInt8, lookUpTableAddress) \
+ DO_TO_FIELD (22, UInt8, unused2) \
+ DO_TO_FIELD (23, UInt8, lookUpTableData) \
+ DO_TO_FIELD (24, UInt8, GPIOConfigurationControl) \
+ DO_TO_FIELD (25, UInt8, GPIOStatusControl) \
+ DO_TO_FIELD (26, UInt8, scratchPad) \
+ DO_TO_FIELD (27, UInt8, portraitMode) \
+ DO_TO_FIELD (28, UInt8, lineByteCountRegister) \
+ DO_TO_FIELD (29, UInt8, unused3) \
+ DO_TO_FIELD (30, UInt8, unused4) \
+ DO_TO_FIELD (31, UInt8, unused5) \
+
+
+// ========================================
+// ===== SED1376RegsType =====
+// ========================================
+
+#define FOR_SED1376RegsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SED1376RegsType, 0xB4, FOR_SED1376RegsType_FIELDS)
+
+#define FOR_SED1376RegsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0x00, UInt8, productRevisionCode) \
+ DO_TO_FIELD (0x01, UInt8, displayBufferSize) \
+ DO_TO_FIELD (0x02, UInt8, configurationReadback) \
+ DO_TO_FIELD (0x04, UInt8, memoryClockConfiguration) \
+ DO_TO_FIELD (0x05, UInt8, pixelClockConfiguration) \
+ DO_TO_FIELD (0x08, UInt8, lutWriteBlue) \
+ DO_TO_FIELD (0x09, UInt8, lutWriteGreen) \
+ DO_TO_FIELD (0x0A, UInt8, lutWriteRed) \
+ DO_TO_FIELD (0x0B, UInt8, lutWriteAddress) \
+ DO_TO_FIELD (0x0C, UInt8, lutReadBlue) \
+ DO_TO_FIELD (0x0D, UInt8, lutReadGreen) \
+ DO_TO_FIELD (0x0E, UInt8, lutReadRed) \
+ DO_TO_FIELD (0x0F, UInt8, lutReadAddress) \
+ DO_TO_FIELD (0x10, UInt8, panelType) \
+ DO_TO_FIELD (0x11, UInt8, MODRate) \
+ DO_TO_FIELD (0x12, UInt8, horizontalTotal) \
+ DO_TO_FIELD (0x14, UInt8, horizontalPeriod) \
+ DO_TO_FIELD (0x16, UInt8, horizontalPeriodStart0) \
+ DO_TO_FIELD (0x17, UInt8, horizontalPeriodStart1) \
+ DO_TO_FIELD (0x18, UInt8, verticalTotal0) \
+ DO_TO_FIELD (0x19, UInt8, verticalTotal1) \
+ DO_TO_FIELD (0x1C, UInt8, verticalPeriod0) \
+ DO_TO_FIELD (0x1D, UInt8, verticalPeriod1) \
+ DO_TO_FIELD (0x1E, UInt8, verticalPeriodStart0) \
+ DO_TO_FIELD (0x1F, UInt8, verticalPeriodStart1) \
+ DO_TO_FIELD (0x20, UInt8, FPLINEPulseWidth) \
+ DO_TO_FIELD (0x22, UInt8, FPLINEPulseStart0) \
+ DO_TO_FIELD (0x23, UInt8, FPLINEPulseStart1) \
+ DO_TO_FIELD (0x24, UInt8, FPFRAMEPulseWidth) \
+ DO_TO_FIELD (0x26, UInt8, FPFRAMEPulseStart0) \
+ DO_TO_FIELD (0x27, UInt8, FPFRAMEPulseStart1) \
+ DO_TO_FIELD (0x28, UInt8, DTFD_GCPIndex) \
+ DO_TO_FIELD (0x2C, UInt8, DTFD_GCPData) \
+ DO_TO_FIELD (0x70, UInt8, displayMode) \
+ DO_TO_FIELD (0x71, UInt8, specialEffects) \
+ DO_TO_FIELD (0x74, UInt8, mainStartAddress0) \
+ DO_TO_FIELD (0x75, UInt8, mainStartAddress1) \
+ DO_TO_FIELD (0x76, UInt8, mainStartAddress2) \
+ DO_TO_FIELD (0x78, UInt8, mainLineAddressOffset0) \
+ DO_TO_FIELD (0x79, UInt8, mainLineAddressOffset1) \
+ DO_TO_FIELD (0x7C, UInt8, ovlyStartAddress0) \
+ DO_TO_FIELD (0x7D, UInt8, ovlyStartAddress1) \
+ DO_TO_FIELD (0x7E, UInt8, ovlyStartAddress2) \
+ DO_TO_FIELD (0x80, UInt8, ovlyLineAddressOffset0) \
+ DO_TO_FIELD (0x81, UInt8, ovlyLineAddressOffset1) \
+ DO_TO_FIELD (0x84, UInt8, ovlyStartXPosition0) \
+ DO_TO_FIELD (0x85, UInt8, ovlyStartXPosition1) \
+ DO_TO_FIELD (0x88, UInt8, ovlyStartYPosition0) \
+ DO_TO_FIELD (0x89, UInt8, ovlyStartYPosition1) \
+ DO_TO_FIELD (0x8C, UInt8, ovlyEndXPosition0) \
+ DO_TO_FIELD (0x8D, UInt8, ovlyEndXPosition1) \
+ DO_TO_FIELD (0x90, UInt8, ovlyEndYPosition0) \
+ DO_TO_FIELD (0x91, UInt8, ovlyEndYPosition1) \
+ DO_TO_FIELD (0xA0, UInt8, powerSaveConfiguration) \
+ DO_TO_FIELD (0xA1, UInt8, reserved) \
+ DO_TO_FIELD (0xA2, UInt8, SoftwareReset) \
+ DO_TO_FIELD (0xA4, UInt8, scratchPad0) \
+ DO_TO_FIELD (0xA5, UInt8, scratchPad1) \
+ DO_TO_FIELD (0xA8, UInt8, GPIOConfiguration0) \
+ DO_TO_FIELD (0xA9, UInt8, GPIOConfiguration1) \
+ DO_TO_FIELD (0xAC, UInt8, GPIOStatusControl0) \
+ DO_TO_FIELD (0xAD, UInt8, GPIOStatusControl1) \
+ DO_TO_FIELD (0xB0, UInt8, PWMClockCVPulseControl) \
+ DO_TO_FIELD (0xB1, UInt8, PWMClockCVPulseConfig) \
+ DO_TO_FIELD (0xB2, UInt8, CVPulseBurstLength) \
+ DO_TO_FIELD (0xB3, UInt8, PWMOutDutyCycle) \
+
+
+// ========================================
+// ===== SliderControlType =====
+// ========================================
+
+#define FOR_SliderControlType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SliderControlType, 30, FOR_SliderControlType_FIELDS)
+
+#define FOR_SliderControlType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, RectangleType, bounds) \
+ DO_TO_FIELD (10, DmResID, thumbID) \
+ DO_TO_FIELD (12, DmResID, backgroundID) \
+ DO_TO_FIELD (14, ControlAttrType, attr) \
+ DO_TO_FIELD (16, ControlStyleType, style) \
+ DO_TO_FIELD (17, UInt8, reserved) \
+ DO_TO_FIELD (18, UInt16, minValue) \
+ DO_TO_FIELD (20, UInt16, maxValue) \
+ DO_TO_FIELD (22, UInt16, pageSize) \
+ DO_TO_FIELD (24, UInt16, value) \
+ DO_TO_FIELD (26, emuptr, activeSliderP) \
+
+
+// ========================================
+// ===== SlkPktFooterType =====
+// ========================================
+
+#define FOR_SlkPktFooterType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SlkPktFooterType, 2, FOR_SlkPktFooterType_FIELDS)
+
+#define FOR_SlkPktFooterType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, crc16) \
+
+
+// ========================================
+// ===== SlkPktHeaderType =====
+// ========================================
+
+#define FOR_SlkPktHeaderType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SlkPktHeaderType, 10, FOR_SlkPktHeaderType_FIELDS)
+
+#define FOR_SlkPktHeaderType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, signature1) \
+ DO_TO_FIELD (2, UInt8, signature2) \
+ DO_TO_FIELD (3, UInt8, dest) \
+ DO_TO_FIELD (4, UInt8, src) \
+ DO_TO_FIELD (5, UInt8, type) \
+ DO_TO_FIELD (6, UInt16, bodySize) \
+ DO_TO_FIELD (8, UInt8, transId) \
+ DO_TO_FIELD (9, SlkPktHeaderChecksum, checksum) \
+
+
+// ========================================
+// ===== SndCommandType =====
+// ========================================
+
+#define FOR_SndCommandType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SndCommandType, 10, FOR_SndCommandType_FIELDS)
+
+#define FOR_SndCommandType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, cmd) \
+ DO_TO_FIELD (1, UInt8, reserved) \
+ DO_TO_FIELD (2, Int32, param1) \
+ DO_TO_FIELD (6, UInt16, param2) \
+ DO_TO_FIELD (8, UInt16, param3) \
+
+
+// ========================================
+// ===== StorageHeaderType =====
+// ========================================
+
+#define FOR_StorageHeaderType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (StorageHeaderType, 76, FOR_StorageHeaderType_FIELDS)
+
+#define FOR_StorageHeaderType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, signature) \
+ DO_TO_FIELD (4, UInt16, version) \
+ DO_TO_FIELD (6, UInt16, flags) \
+ DO_TO_FIELD (8, UInt8, name) \
+ DO_TO_FIELD (40, UInt32, creationDate) \
+ DO_TO_FIELD (44, UInt32, backupDate) \
+ DO_TO_FIELD (48, UInt32, heapListOffset) \
+ DO_TO_FIELD (52, UInt32, initCodeOffset1) \
+ DO_TO_FIELD (56, UInt32, initCodeOffset2) \
+ DO_TO_FIELD (60, LocalID, databaseDirID) \
+ DO_TO_FIELD (64, UInt32, rsvSpace) \
+ DO_TO_FIELD (68, UInt32, dynHeapSpace) \
+ DO_TO_FIELD (72, UInt32, firstRAMBlockSize) \
+
+
+// ========================================
+// ===== SysAppInfoType =====
+// ========================================
+
+#define FOR_SysAppInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysAppInfoType, 60, FOR_SysAppInfoType_FIELDS)
+
+#define FOR_SysAppInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Int16, cmd) \
+ DO_TO_FIELD (2, emuptr, cmdPBP) \
+ DO_TO_FIELD (6, UInt16, launchFlags) \
+ DO_TO_FIELD (8, UInt32, taskID) \
+ DO_TO_FIELD (12, emuptr, codeH) \
+ DO_TO_FIELD (16, emuptr, dbP) \
+ DO_TO_FIELD (20, emuptr, stackP) \
+ DO_TO_FIELD (24, emuptr, globalsChunkP) \
+ DO_TO_FIELD (28, UInt16, memOwnerID) \
+ DO_TO_FIELD (30, emuptr, dmAccessP) \
+ DO_TO_FIELD (34, Err, dmLastErr) \
+ DO_TO_FIELD (36, emuptr, errExceptionP) \
+ DO_TO_FIELD (40, emuptr, a5Ptr) \
+ DO_TO_FIELD (44, emuptr, stackEndP) \
+ DO_TO_FIELD (48, emuptr, globalEndP) \
+ DO_TO_FIELD (52, emuptr, rootP) \
+ DO_TO_FIELD (56, emuptr, extraP) \
+
+
+// ========================================
+// ===== SysBatteryDataStructV1 =====
+// ========================================
+
+#define FOR_SysBatteryDataStructV1_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysBatteryDataStructV1, 50, FOR_SysBatteryDataStructV1_FIELDS)
+
+#define FOR_SysBatteryDataStructV1_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, sysBattDataStructVersion) \
+ DO_TO_FIELD (2, UInt16, sysBattMildWrngVoltage) \
+ DO_TO_FIELD (4, UInt16, sysBattSevereWrngVoltage) \
+ DO_TO_FIELD (6, UInt16, sysBattShutdownEnVoltage) \
+ DO_TO_FIELD (8, UInt16, sysBattShutdownDisVoltage) \
+ DO_TO_FIELD (10, UInt16, sysBattMinIRVoltage) \
+ DO_TO_FIELD (12, UInt32, sysBattMildWrngTimeout) \
+ DO_TO_FIELD (16, UInt32, sysBattSevereWrngTimeout) \
+ DO_TO_FIELD (20, UInt16, sysBattCritWarnOffDays) \
+ DO_TO_FIELD (22, UInt32, sysBattCritWarnOnTicks) \
+ DO_TO_FIELD (26, UInt16, sysBattStepsPerVolt) \
+ DO_TO_FIELD (28, Int16, sysBattVoltageStepOffset) \
+ DO_TO_FIELD (30, UInt32, sysBattReserved1) \
+ DO_TO_FIELD (34, UInt32, sysBattReserved2) \
+ DO_TO_FIELD (38, UInt16, sysBattVoltageCurve) \
+
+
+// ========================================
+// ===== SysBatteryDataStructV2 =====
+// ========================================
+
+#define FOR_SysBatteryDataStructV2_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysBatteryDataStructV2, 54, FOR_SysBatteryDataStructV2_FIELDS)
+
+#define FOR_SysBatteryDataStructV2_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, sysBattDataStructVersion) \
+ DO_TO_FIELD (2, UInt16, sysBattMildWrngVoltage) \
+ DO_TO_FIELD (4, UInt16, sysBattSevereWrngVoltage) \
+ DO_TO_FIELD (6, UInt16, sysBattMildWrngPercent) \
+ DO_TO_FIELD (8, UInt16, sysBattSevereWrngPercent) \
+ DO_TO_FIELD (10, UInt16, sysBattShutdownEnVoltage) \
+ DO_TO_FIELD (12, UInt16, sysBattShutdownDisVoltage) \
+ DO_TO_FIELD (14, UInt16, sysBattMinIRVoltage) \
+ DO_TO_FIELD (16, UInt32, sysBattMildWrngTimeout) \
+ DO_TO_FIELD (20, UInt32, sysBattSevereWrngTimeout) \
+ DO_TO_FIELD (24, UInt16, sysBattCritWarnOffDays) \
+ DO_TO_FIELD (26, UInt32, sysBattCritWarnOnTicks) \
+ DO_TO_FIELD (30, UInt16, sysBattStepsPerVolt) \
+ DO_TO_FIELD (32, Int16, sysBattVoltageStepOffset) \
+ DO_TO_FIELD (34, UInt32, sysBattReserved1) \
+ DO_TO_FIELD (38, UInt32, sysBattReserved2) \
+ DO_TO_FIELD (42, UInt16, sysBattVoltageCurve) \
+
+
+// ========================================
+// ===== SysBatteryDataStructV3 =====
+// ========================================
+
+#define FOR_SysBatteryDataStructV3_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysBatteryDataStructV3, 38, FOR_SysBatteryDataStructV3_FIELDS)
+
+#define FOR_SysBatteryDataStructV3_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, sysBattDataStructVersion) \
+ DO_TO_FIELD (2, UInt16, sysBattShutdownEnVoltage) \
+ DO_TO_FIELD (4, UInt16, sysBattShutdownDisVoltage) \
+ DO_TO_FIELD (6, UInt16, sysBattTableFlags) \
+ DO_TO_FIELD (8, UInt16, sysBattCritWarnOffDays) \
+ DO_TO_FIELD (10, UInt32, sysBattCritWarnOnTicks) \
+ DO_TO_FIELD (14, UInt16, sysBattStepsPerVolt) \
+ DO_TO_FIELD (16, Int16, sysBattVoltageStepOffset) \
+ DO_TO_FIELD (18, UInt32, sysBattReserved1) \
+ DO_TO_FIELD (22, UInt32, sysBattReserved2) \
+ DO_TO_FIELD (26, UInt16, sysBattVoltageCurve) \
+
+
+// ========================================
+// ===== SysLibTblEntryType =====
+// ========================================
+
+#define FOR_SysLibTblEntryType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysLibTblEntryType, 10, FOR_SysLibTblEntryType_FIELDS)
+
+#define FOR_SysLibTblEntryType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, dispatchTblP) \
+ DO_TO_FIELD (4, emuptr, globalsP) \
+ DO_TO_FIELD (8, LocalID, dbID) \
+ DO_TO_FIELD (12, emuptr, codeRscH) \
+
+
+// ========================================
+// ===== SysKernelInfoType =====
+// ========================================
+
+#define FOR_SysKernelInfoType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysKernelInfoType, 62, FOR_SysKernelInfoType_FIELDS)
+
+#define FOR_SysKernelInfoType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, selector) \
+ DO_TO_FIELD (1, UInt8, reserved) \
+ DO_TO_FIELD (2, UInt32, id) \
+ DO_TO_FIELD (6, kernel_info_task, task) \
+ DO_TO_FIELD (6, kernel_info_semaphore, semaphore) \
+ DO_TO_FIELD (6, kernel_info_timer, timer) \
+
+
+// ========================================
+// ===== kernel_info_task =====
+// ========================================
+
+#define FOR_kernel_info_task_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (kernel_info_task, 56, FOR_kernel_info_task_FIELDS)
+
+#define FOR_kernel_info_task_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, id) \
+ DO_TO_FIELD (4, UInt32, nextID) \
+ DO_TO_FIELD (8, UInt32, tag) \
+ DO_TO_FIELD (12, UInt32, status) \
+ DO_TO_FIELD (16, UInt32, timer) \
+ DO_TO_FIELD (20, UInt32, timeSlice) \
+ DO_TO_FIELD (24, Int16, priority) \
+ DO_TO_FIELD (26, UInt32, attributes) \
+ DO_TO_FIELD (30, Int16, pendingCalls) \
+ DO_TO_FIELD (32, UInt32, senderTaskID) \
+ DO_TO_FIELD (36, UInt32, msgExchangeID) \
+ DO_TO_FIELD (40, UInt32, tcbP) \
+ DO_TO_FIELD (44, UInt32, stackP) \
+ DO_TO_FIELD (48, UInt32, stackStart) \
+ DO_TO_FIELD (52, UInt32, stackSize) \
+
+
+// ========================================
+// ===== kernel_info_semaphore =====
+// ========================================
+
+#define FOR_kernel_info_semaphore_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (kernel_info_semaphore, 22, FOR_kernel_info_semaphore_FIELDS)
+
+#define FOR_kernel_info_semaphore_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, id) \
+ DO_TO_FIELD (4, UInt32, nextID) \
+ DO_TO_FIELD (8, UInt32, tag) \
+ DO_TO_FIELD (12, Int16, initValue) \
+ DO_TO_FIELD (14, Int16, curValue) \
+ DO_TO_FIELD (16, Int16, nestLevel) \
+ DO_TO_FIELD (18, UInt32, ownerID) \
+
+
+// ========================================
+// ===== kernel_info_timer =====
+// ========================================
+
+#define FOR_kernel_info_timer_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (kernel_info_timer, 24, FOR_kernel_info_timer_FIELDS)
+
+#define FOR_kernel_info_timer_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, id) \
+ DO_TO_FIELD (4, UInt32, nextID) \
+ DO_TO_FIELD (8, UInt32, tag) \
+ DO_TO_FIELD (12, UInt32, ticksLeft) \
+ DO_TO_FIELD (16, UInt32, period) \
+ DO_TO_FIELD (20, UInt32, proc) \
+
+
+// ========================================
+// ===== SysNVParamsType =====
+// ========================================
+
+#define FOR_SysNVParamsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysNVParamsType, 30, FOR_SysNVParamsType_FIELDS)
+
+#define FOR_SysNVParamsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, rtcHours) \
+ DO_TO_FIELD (4, UInt32, rtcHourMinSecCopy) \
+ DO_TO_FIELD (8, UInt8, swrLCDContrastValue) \
+ DO_TO_FIELD (9, UInt8, swrLCDBrightnessValue) \
+ DO_TO_FIELD (10, emuptr, splashScreenPtr) \
+ DO_TO_FIELD (14, emuptr, hardResetScreenPtr) \
+ DO_TO_FIELD (18, UInt16, localeLanguage) \
+ DO_TO_FIELD (20, UInt16, localeCountry) \
+ DO_TO_FIELD (22, UInt32, sysNVOEMStorage1) \
+ DO_TO_FIELD (26, UInt32, sysNVOEMStorage2) \
+
+
+// ========================================
+// ===== SysPktBodyType =====
+// ========================================
+
+#define FOR_SysPktBodyType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktBodyType, sysPktMaxBodySize, FOR_SysPktBodyType_FIELDS)
+
+#define FOR_SysPktBodyType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt8, data) \
+
+
+// ========================================
+// ===== SysPktContinueCmdType =====
+// ========================================
+
+#define FOR_SysPktContinueCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktContinueCmdType, 90, FOR_SysPktContinueCmdType_FIELDS)
+
+#define FOR_SysPktContinueCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, M68KRegsType, regs) \
+ DO_TO_FIELD (76, Boolean, stepSpy) \
+ DO_TO_FIELD (77, UInt8, reserved) \
+ DO_TO_FIELD (78, UInt32, ssAddr) \
+ DO_TO_FIELD (82, UInt32, ssCount) \
+ DO_TO_FIELD (86, UInt32, ssCheckSum) \
+
+
+// ========================================
+// ===== SysPktDbgBreakToggleCmdType =====
+// ========================================
+
+#define FOR_SysPktDbgBreakToggleCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktDbgBreakToggleCmdType, 2, FOR_SysPktDbgBreakToggleCmdType_FIELDS)
+
+#define FOR_SysPktDbgBreakToggleCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktDbgBreakToggleRspType =====
+// ========================================
+
+#define FOR_SysPktDbgBreakToggleRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktDbgBreakToggleRspType, 4, FOR_SysPktDbgBreakToggleRspType_FIELDS)
+
+#define FOR_SysPktDbgBreakToggleRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, Boolean, newState) \
+ DO_TO_FIELD (3, UInt8, reserved) \
+
+
+// ========================================
+// ===== SysPktFindCmdType =====
+// ========================================
+
+#define FOR_SysPktFindCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktFindCmdType, sysPktMaxBodySize, FOR_SysPktFindCmdType_FIELDS)
+
+#define FOR_SysPktFindCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt32, firstAddr) \
+ DO_TO_FIELD (6, UInt32, lastAddr) \
+ DO_TO_FIELD (10, UInt16, numBytes) \
+ DO_TO_FIELD (12, Boolean, caseInsensitive) \
+ DO_TO_FIELD (13, UInt8, padding) \
+ DO_TO_FIELD (14, UInt8, data) \
+
+
+// ========================================
+// ===== SysPktFindRspType =====
+// ========================================
+
+#define FOR_SysPktFindRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktFindRspType, 8, FOR_SysPktFindRspType_FIELDS)
+
+#define FOR_SysPktFindRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, emuptr, addr) \
+ DO_TO_FIELD (6, UInt8, found) \
+ DO_TO_FIELD (7, UInt8, padding) \
+
+
+// ========================================
+// ===== SysPktGetBreakpointsCmdType =====
+// ========================================
+
+#define FOR_SysPktGetBreakpointsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetBreakpointsCmdType, 2, FOR_SysPktGetBreakpointsCmdType_FIELDS)
+
+#define FOR_SysPktGetBreakpointsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktEmptyRspType =====
+// ========================================
+
+#define FOR_SysPktEmptyRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktEmptyRspType, 2, FOR_SysPktEmptyRspType_FIELDS)
+
+#define FOR_SysPktEmptyRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktGetBreakpointsRspType =====
+// ========================================
+
+#define FOR_SysPktGetBreakpointsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetBreakpointsRspType, 38, FOR_SysPktGetBreakpointsRspType_FIELDS)
+
+#define FOR_SysPktGetBreakpointsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, BreakpointType, bp) \
+
+
+// ========================================
+// ===== SysPktGetTrapBreaksCmdType =====
+// ========================================
+
+#define FOR_SysPktGetTrapBreaksCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetTrapBreaksCmdType, 2, FOR_SysPktGetTrapBreaksCmdType_FIELDS)
+
+#define FOR_SysPktGetTrapBreaksCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktGetTrapBreaksRspType =====
+// ========================================
+
+#define FOR_SysPktGetTrapBreaksRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetTrapBreaksRspType, 12, FOR_SysPktGetTrapBreaksRspType_FIELDS)
+
+#define FOR_SysPktGetTrapBreaksRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapBP) \
+
+
+// ========================================
+// ===== SysPktGetTrapConditionsCmdType =====
+// ========================================
+
+#define FOR_SysPktGetTrapConditionsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetTrapConditionsCmdType, 2, FOR_SysPktGetTrapConditionsCmdType_FIELDS)
+
+#define FOR_SysPktGetTrapConditionsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktGetTrapConditionsRspType =====
+// ========================================
+
+#define FOR_SysPktGetTrapConditionsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktGetTrapConditionsRspType, 12, FOR_SysPktGetTrapConditionsRspType_FIELDS)
+
+#define FOR_SysPktGetTrapConditionsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapParam) \
+
+
+// ========================================
+// ===== SysPktReadMemCmdType =====
+// ========================================
+
+#define FOR_SysPktReadMemCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktReadMemCmdType, 8, FOR_SysPktReadMemCmdType_FIELDS)
+
+#define FOR_SysPktReadMemCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, emuptr, address) \
+ DO_TO_FIELD (6, UInt16, numBytes) \
+
+
+// ========================================
+// ===== SysPktReadMemRspType =====
+// ========================================
+
+#define FOR_SysPktReadMemRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktReadMemRspType, sysPktMaxBodySize, FOR_SysPktReadMemRspType_FIELDS)
+
+#define FOR_SysPktReadMemRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, char, data) \
+
+
+// ========================================
+// ===== SysPktReadRegsCmdType =====
+// ========================================
+
+#define FOR_SysPktReadRegsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktReadRegsCmdType, 2, FOR_SysPktReadRegsCmdType_FIELDS)
+
+#define FOR_SysPktReadRegsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktReadRegsRspType =====
+// ========================================
+
+#define FOR_SysPktReadRegsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktReadRegsRspType, 76, FOR_SysPktReadRegsRspType_FIELDS)
+
+#define FOR_SysPktReadRegsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, M68KRegsType, reg) \
+
+
+// ========================================
+// ===== SysPktRPC2Type =====
+// ========================================
+
+#define FOR_SysPktRPC2Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktRPC2Type, sysPktMaxBodySize, FOR_SysPktRPC2Type_FIELDS)
+
+#define FOR_SysPktRPC2Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapWord) \
+ DO_TO_FIELD (4, UInt32, resultD0) \
+ DO_TO_FIELD (8, UInt32, resultA0) \
+ DO_TO_FIELD (12, UInt16, resultException) \
+ DO_TO_FIELD (14, UInt8, DRegMask) \
+ DO_TO_FIELD (15, UInt8, ARegMask) \
+ DO_TO_FIELD (16, UInt32, Regs) \
+ DO_TO_FIELD (1, UInt16, numParams) \
+ DO_TO_FIELD (1, char, param) \
+
+
+// ========================================
+// ===== SysPktRPCParamType =====
+// ========================================
+
+#define FOR_SysPktRPCParamType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktRPCParamType, 6, FOR_SysPktRPCParamType_FIELDS)
+
+#define FOR_SysPktRPCParamType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, byRef) \
+ DO_TO_FIELD (1, UInt8, size) \
+ DO_TO_FIELD (2, UInt8, asByte) \
+ DO_TO_FIELD (2, UInt16, asShort) \
+ DO_TO_FIELD (2, UInt32, asLong) \
+
+
+// ========================================
+// ===== SysPktRPCType =====
+// ========================================
+
+#define FOR_SysPktRPCType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktRPCType, sysPktMaxBodySize, FOR_SysPktRPCType_FIELDS)
+
+#define FOR_SysPktRPCType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapWord) \
+ DO_TO_FIELD (4, UInt32, resultD0) \
+ DO_TO_FIELD (8, UInt32, resultA0) \
+ DO_TO_FIELD (12, UInt16, numParams) \
+ DO_TO_FIELD (14, char, param) \
+
+
+// ========================================
+// ===== SysPktRtnNameCmdType =====
+// ========================================
+
+#define FOR_SysPktRtnNameCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktRtnNameCmdType, 6, FOR_SysPktRtnNameCmdType_FIELDS)
+
+#define FOR_SysPktRtnNameCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, emuptr, address) \
+
+
+// ========================================
+// ===== SysPktRtnNameRspType =====
+// ========================================
+
+#define FOR_SysPktRtnNameRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktRtnNameRspType, (14 + sysPktMaxNameLen), FOR_SysPktRtnNameRspType_FIELDS)
+
+#define FOR_SysPktRtnNameRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, emuptr, address) \
+ DO_TO_FIELD (6, emuptr, startAddr) \
+ DO_TO_FIELD (10, emuptr, endAddr) \
+ DO_TO_FIELD (14, char, name) \
+
+
+// ========================================
+// ===== SysPktSetBreakpointsCmdType =====
+// ========================================
+
+#define FOR_SysPktSetBreakpointsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktSetBreakpointsCmdType, 38, FOR_SysPktSetBreakpointsCmdType_FIELDS)
+
+#define FOR_SysPktSetBreakpointsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, BreakpointType, bp) \
+
+
+// ========================================
+// ===== SysPktSetBreakpointsRspType =====
+// ========================================
+
+#define FOR_SysPktSetBreakpointsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktSetBreakpointsRspType, 2, FOR_SysPktSetBreakpointsRspType_FIELDS)
+
+#define FOR_SysPktSetBreakpointsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktSetTrapBreaksCmdType =====
+// ========================================
+
+#define FOR_SysPktSetTrapBreaksCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktSetTrapBreaksCmdType, 12, FOR_SysPktSetTrapBreaksCmdType_FIELDS)
+
+#define FOR_SysPktSetTrapBreaksCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapBP) \
+
+
+// ========================================
+// ===== SysPktSetTrapConditionsCmdType =====
+// ========================================
+
+#define FOR_SysPktSetTrapConditionsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktSetTrapConditionsCmdType, 12, FOR_SysPktSetTrapConditionsCmdType_FIELDS)
+
+#define FOR_SysPktSetTrapConditionsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, UInt16, trapParam) \
+
+
+// ========================================
+// ===== SysPktSetTrapConditionsRspType =====
+// ========================================
+
+#define FOR_SysPktSetTrapConditionsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktSetTrapConditionsRspType, 2, FOR_SysPktSetTrapConditionsRspType_FIELDS)
+
+#define FOR_SysPktSetTrapConditionsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktStateCmdType =====
+// ========================================
+
+#define FOR_SysPktStateCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktStateCmdType, 2, FOR_SysPktStateCmdType_FIELDS)
+
+#define FOR_SysPktStateCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktStateRspType =====
+// ========================================
+
+#define FOR_SysPktStateRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktStateRspType, 188, FOR_SysPktStateRspType_FIELDS)
+
+#define FOR_SysPktStateRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, Boolean, resetted) \
+ DO_TO_FIELD (3, UInt8, reserved1) \
+ DO_TO_FIELD (4, UInt16, exceptionId) \
+ DO_TO_FIELD (6, M68KRegsType, reg) \
+ DO_TO_FIELD (80, UInt16, inst) \
+ DO_TO_FIELD (110, BreakpointType, bp) \
+ DO_TO_FIELD (146, emuptr, startAddr) \
+ DO_TO_FIELD (150, emuptr, endAddr) \
+ DO_TO_FIELD (154, char, name) \
+ DO_TO_FIELD (186, UInt8, trapTableRev) \
+ DO_TO_FIELD (187, UInt8, reserved2) \
+
+
+// ========================================
+// ===== SysPktWriteMemCmdType =====
+// ========================================
+
+#define FOR_SysPktWriteMemCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktWriteMemCmdType, sysPktMaxBodySize, FOR_SysPktWriteMemCmdType_FIELDS)
+
+#define FOR_SysPktWriteMemCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, emuptr, address) \
+ DO_TO_FIELD (6, UInt16, numBytes) \
+ DO_TO_FIELD (8, char, data) \
+
+
+// ========================================
+// ===== SysPktWriteMemRspType =====
+// ========================================
+
+#define FOR_SysPktWriteMemRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktWriteMemRspType, 2, FOR_SysPktWriteMemRspType_FIELDS)
+
+#define FOR_SysPktWriteMemRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+// ========================================
+// ===== SysPktWriteRegsCmdType =====
+// ========================================
+
+#define FOR_SysPktWriteRegsCmdType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktWriteRegsCmdType, 76, FOR_SysPktWriteRegsCmdType_FIELDS)
+
+#define FOR_SysPktWriteRegsCmdType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+ DO_TO_FIELD (2, M68KRegsType, reg) \
+
+
+// ========================================
+// ===== SysPktWriteRegsRspType =====
+// ========================================
+
+#define FOR_SysPktWriteRegsRspType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (SysPktWriteRegsRspType, 2, FOR_SysPktWriteRegsRspType_FIELDS)
+
+#define FOR_SysPktWriteRegsRspType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, command) \
+ DO_TO_FIELD (1, UInt8, _filler) \
+
+
+/* Note: Several of the following structures have a numeral in their
+ name. These serve to distinguish the separate versions,
+ and are roughly related to the version of the ROM heap when
+ the particular variant was introduced. */
+
+
+// ========================================
+// ===== ROMCardHeader5Type =====
+// ========================================
+
+#define FOR_ROMCardHeader5Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMCardHeader5Type, 256, FOR_ROMCardHeader5Type_FIELDS)
+
+#define FOR_ROMCardHeader5Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, initStack) \
+ DO_TO_FIELD (4, UInt32, resetVector) \
+ DO_TO_FIELD (8, UInt32, signature) \
+ DO_TO_FIELD (12, UInt16, hdrVersion) \
+ DO_TO_FIELD (14, UInt16, flags) \
+ DO_TO_FIELD (16, char, cardName) \
+ DO_TO_FIELD (48, char, cardManuf) \
+ DO_TO_FIELD (80, UInt16, cardVersion) \
+ DO_TO_FIELD (82, UInt32, cardTime) \
+ DO_TO_FIELD (86, UInt16, unknown1) \
+ DO_TO_FIELD (88, UInt32, ramlist) \
+ DO_TO_FIELD (92, UInt32, rwoffset) \
+ DO_TO_FIELD (96, UInt32, rwlength) \
+ DO_TO_FIELD (100, UInt32, rooffset) \
+ DO_TO_FIELD (104, UInt32, bigrom) \
+ DO_TO_FIELD (108, UInt32, checksumLength) \
+ DO_TO_FIELD (112, UInt16, checksumValue) \
+ DO_TO_FIELD (114, UInt32, rwwoffset) \
+ DO_TO_FIELD (118, UInt32, rwwlength) \
+ DO_TO_FIELD (122, UInt32, halDispatch) \
+ DO_TO_FIELD (126, UInt32, companyID) \
+ DO_TO_FIELD (130, UInt32, halID) \
+ DO_TO_FIELD (134, UInt32, romVersionNumber) \
+ DO_TO_FIELD (138, char, romVersionString) \
+ DO_TO_FIELD (170, char, reserved) \
+
+
+// ========================================
+// ===== ROMStoreHeader4Type =====
+// ========================================
+
+#define FOR_ROMStoreHeader4Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMStoreHeader4Type, 256, FOR_ROMStoreHeader4Type_FIELDS)
+
+#define FOR_ROMStoreHeader4Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, signature) \
+ DO_TO_FIELD (4, UInt16, version) \
+ DO_TO_FIELD (6, UInt16, flags) \
+ DO_TO_FIELD (8, char, name) \
+ DO_TO_FIELD (40, UInt32, creationDate) \
+ DO_TO_FIELD (44, UInt32, backupDate) \
+ DO_TO_FIELD (48, UInt32, heapAddr) \
+ DO_TO_FIELD (52, UInt32, initAddr1) \
+ DO_TO_FIELD (56, UInt32, initAddr2) \
+ DO_TO_FIELD (60, UInt32, dbLID) \
+ DO_TO_FIELD (64, UInt32, reserved) \
+ DO_TO_FIELD (68, UInt32, heapSize) \
+ DO_TO_FIELD (72, UInt32, ramSize) \
+
+
+// ========================================
+// ===== ROMHeapHeader3Type =====
+// ========================================
+
+#define FOR_ROMHeapHeader3Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMHeapHeader3Type, 16, FOR_ROMHeapHeader3Type_FIELDS)
+
+#define FOR_ROMHeapHeader3Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+ DO_TO_FIELD (2, UInt32, size) \
+ DO_TO_FIELD (6, UInt32, freeChunk) \
+ DO_TO_FIELD (10, UInt16, masterPointers) \
+ DO_TO_FIELD (12, UInt32, nextMasterTable) \
+
+
+// ========================================
+// ===== ROMHeapHeader2Type =====
+// ========================================
+
+#define FOR_ROMHeapHeader2Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMHeapHeader2Type, 12, FOR_ROMHeapHeader2Type_FIELDS)
+
+#define FOR_ROMHeapHeader2Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+ DO_TO_FIELD (2, UInt32, size) \
+ DO_TO_FIELD (6, UInt16, masterPointers) \
+ DO_TO_FIELD (8, UInt32, nextMasterTable) \
+
+
+// ========================================
+// ===== ROMHeapHeader1Type =====
+// ========================================
+
+#define FOR_ROMHeapHeader1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMHeapHeader1Type, 8, FOR_ROMHeapHeader1Type_FIELDS)
+
+#define FOR_ROMHeapHeader1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+ DO_TO_FIELD (2, UInt16, size) \
+ DO_TO_FIELD (4, UInt16, masterPointers) \
+ DO_TO_FIELD (6, UInt16, nextMasterTable) \
+
+
+// ========================================
+// ===== ROMDBDir1Type =====
+// ========================================
+
+#define FOR_ROMDBDir1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMDBDir1Type, 6, FOR_ROMDBDir1Type_FIELDS)
+
+#define FOR_ROMDBDir1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, nextTable) \
+ DO_TO_FIELD (4, UInt16, count) \
+ DO_TO_FIELD (6, UInt32, dbLID) \
+
+
+// ========================================
+// ===== ROMDBRecordHeader1Type =====
+// ========================================
+
+#define FOR_ROMDBRecordHeader1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMDBRecordHeader1Type, 8, FOR_ROMDBRecordHeader1Type_FIELDS)
+
+#define FOR_ROMDBRecordHeader1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, chunkLID) \
+ DO_TO_FIELD (4, UInt32, recordID) \
+
+
+// ========================================
+// ===== ROMDBResourceHeader1Type =====
+// ========================================
+
+#define FOR_ROMDBResourceHeader1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMDBResourceHeader1Type, 10, FOR_ROMDBResourceHeader1Type_FIELDS)
+
+#define FOR_ROMDBResourceHeader1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, type) \
+ DO_TO_FIELD (4, UInt16, id) \
+ DO_TO_FIELD (6, UInt32, chunkLID) \
+
+
+// ========================================
+// ===== ROMDBHeader1Type =====
+// ========================================
+
+#define FOR_ROMDBHeader1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMDBHeader1Type, 78, FOR_ROMDBHeader1Type_FIELDS)
+
+#define FOR_ROMDBHeader1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, char, name) \
+ DO_TO_FIELD (32, UInt16, flags) \
+ DO_TO_FIELD (34, UInt16, version) \
+ DO_TO_FIELD (36, UInt32, creationTime) \
+ DO_TO_FIELD (40, UInt32, modificationTime) \
+ DO_TO_FIELD (44, UInt32, backupTime) \
+ DO_TO_FIELD (48, UInt32, modificationNumber) \
+ DO_TO_FIELD (52, UInt32, appinfoLID) \
+ DO_TO_FIELD (56, UInt32, sortinfoLID) \
+ DO_TO_FIELD (60, UInt32, type) \
+ DO_TO_FIELD (64, UInt32, creator) \
+ DO_TO_FIELD (68, UInt32, uniqueIDSeed) \
+ DO_TO_FIELD (72, UInt32, extensionHeader) \
+ DO_TO_FIELD (76, UInt16, recordCount) \
+ DO_TO_FIELD (78, ROMDBRecordHeader1Type, records) \
+ DO_TO_FIELD (78, ROMDBResourceHeader1Type, resources) \
+
+
+// ========================================
+// ===== ROMHeapChunkHdr2Type =====
+// ========================================
+
+#define FOR_ROMHeapChunkHdr2Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMHeapChunkHdr2Type, 8, FOR_ROMHeapChunkHdr2Type_FIELDS)
+
+#define FOR_ROMHeapChunkHdr2Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, long1) \
+ DO_TO_FIELD (4, UInt32, long2) \
+
+
+// ========================================
+// ===== ROMHeapChunkHdr1Type =====
+// ========================================
+
+#define FOR_ROMHeapChunkHdr1Type_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (ROMHeapChunkHdr1Type, 6, FOR_ROMHeapChunkHdr1Type_FIELDS)
+
+#define FOR_ROMHeapChunkHdr1Type_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, size) \
+ DO_TO_FIELD (2, UInt8, lockOwner) \
+ DO_TO_FIELD (3, UInt8, flags) \
+ DO_TO_FIELD (4, UInt16, hOffset) \
+
+
+// ========================================
+// ===== ROMFtrFeatureType =====
+// ========================================
+
+#define FOR_ROMFtrFeatureType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(ROMFtrFeatureType, 6, FOR_ROMFtrFeatureType_FIELDS)
+
+#define FOR_ROMFtrFeatureType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, num) \
+ DO_TO_FIELD (2, UInt32, value) \
+
+
+// ========================================
+// ===== ROMFtrCreatorType =====
+// ========================================
+
+#define FOR_ROMFtrCreatorType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(ROMFtrCreatorType, 6, FOR_ROMFtrCreatorType_FIELDS)
+
+#define FOR_ROMFtrCreatorType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, creator) \
+ DO_TO_FIELD (4, UInt16, numEntries) \
+ DO_TO_FIELD (6, ROMFtrFeatureType, feature) \
+
+
+// ========================================
+// ===== ROMFtrTableType =====
+// ========================================
+
+#define FOR_ROMFtrTableType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(ROMFtrTableType, 2, FOR_ROMFtrTableType_FIELDS)
+
+#define FOR_ROMFtrTableType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, numEntries) \
+ DO_TO_FIELD (2, ROMFtrCreatorType, creator) \
+
+
+// ========================================
+// ===== TableAttrType =====
+// ========================================
+
+#define FOR_TableAttrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(TableAttrType, 2, FOR_TableAttrType_FIELDS)
+
+#define FOR_TableAttrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, flags) \
+
+
+// ========================================
+// ===== TableType =====
+// ========================================
+
+#define FOR_TableType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(TableType, 74, FOR_TableType_FIELDS)
+
+#define FOR_TableType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, id) \
+ DO_TO_FIELD (2, RectangleType, bounds) \
+ DO_TO_FIELD (10, TableAttrType, attr) \
+ DO_TO_FIELD (12, Int16, numColumns) \
+ DO_TO_FIELD (14, Int16, numRows) \
+ DO_TO_FIELD (16, Int16, currentRow) \
+ DO_TO_FIELD (18, Int16, currentColumn) \
+ DO_TO_FIELD (20, Int16, topRow) \
+ DO_TO_FIELD (22, emuptr, columnAttrs) \
+ DO_TO_FIELD (26, emuptr, rowAttrs) \
+ DO_TO_FIELD (30, emuptr, items) \
+ DO_TO_FIELD (34, FieldType, currentField) \
+
+
+// ========================================
+// ===== TimGlobalsType =====
+// ========================================
+
+#define FOR_TimGlobalsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT(TimGlobalsType, 24, FOR_TimGlobalsType_FIELDS)
+
+#define FOR_TimGlobalsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt32, rtcHours) \
+ DO_TO_FIELD (4, UInt32, alarmSeconds) \
+ DO_TO_FIELD (8, Boolean, rtcBugWorkaround) \
+ DO_TO_FIELD (9, Boolean, rtcBugAsleep) \
+ DO_TO_FIELD (10, UInt32, rtcBugAlarm) \
+ DO_TO_FIELD (14, UInt32, rtcBugSeconds) \
+ DO_TO_FIELD (18, UInt32, rtcBugLastSeconds) \
+ DO_TO_FIELD (22, Boolean, rtcBugFastMinuteCalc) \
+ DO_TO_FIELD (23, UInt8, reserved) \
+
+
+// ========================================
+// ===== UIColorStateType =====
+// ========================================
+
+#define FOR_UIColorStateType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIColorStateType, 12, FOR_UIColorStateType_FIELDS)
+
+#define FOR_UIColorStateType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, colorTableP) \
+ DO_TO_FIELD (4, emuptr, colorTableStackP) \
+ DO_TO_FIELD (8, Int16, colorTableStackIndex) \
+ DO_TO_FIELD (10, Boolean, tablesDirty) \
+ DO_TO_FIELD (11, UInt8, reserved) \
+
+
+// ========================================
+// ===== UIGlobalsType =====
+// ========================================
+// Universal type; contains only parts up to where
+// different versions diverge.
+
+#define FOR_UIGlobalsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsType, 56, FOR_UIGlobalsType_FIELDS)
+
+#define FOR_UIGlobalsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV1, gStateV1) \
+ DO_TO_FIELD (28, GraphicStateTypeV2, gStateV2) \
+ DO_TO_FIELD (28, GraphicStateTypeV3, gStateV3) \
+
+
+// ========================================
+// ===== UIGlobalsTypeCommon =====
+// ========================================
+// Mostly Universal type. Can be used on anything except 1.0. Skips over
+// a gap if shifting fields between the gState and uiCurrentFontID fields,
+// does include uiCurrentMenuRscID and uiDecimalSeparator, but doesn't
+// include allFormsClosing, uiOptions and menuCmdBarCurrent fields.
+
+#define FOR_UIGlobalsTypeCommon_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeCommon, 163, FOR_UIGlobalsTypeCommon_FIELDS)
+
+#define FOR_UIGlobalsTypeCommon_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV1, gStateV1) \
+ DO_TO_FIELD (28, GraphicStateTypeV2, gStateV2) \
+ DO_TO_FIELD (28, GraphicStateTypeV3, gStateV3) \
+ /* Gap of shifting fields */ \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV1 =====
+// ========================================
+// Used in Palm OS 1.0.
+
+#define FOR_UIGlobalsTypeV1_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV1, 160, FOR_UIGlobalsTypeV1_FIELDS)
+
+#define FOR_UIGlobalsTypeV1_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV1, gState) \
+ DO_TO_FIELD (48, emuptr, eventQ) \
+ DO_TO_FIELD (52, UInt16, eventQIndex) \
+ DO_TO_FIELD (54, UInt16, eventQLength) \
+ DO_TO_FIELD (56, Int16, lastScreenX) \
+ DO_TO_FIELD (58, Int16, lastScreenY) \
+ DO_TO_FIELD (60, Boolean, lastPenDown) \
+ DO_TO_FIELD (61, UInt8, _unused1) \
+ DO_TO_FIELD (62, Int32, needNullTickCount) \
+ DO_TO_FIELD (66, emuptr, uiCurrentFontPtr) \
+ /* array of 7 emuptrs */ \
+ DO_TO_FIELD (70, emuptr, uiFontTable) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (154, UInt8, gsiState) \
+ DO_TO_FIELD (155, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (156, PointType, gsiLocation) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV2 =====
+// ========================================
+// Used in Palm OS 2.0.
+// Inserts uiCurrentMenuRscID and adds uiDecimalSeparator.
+
+#define FOR_UIGlobalsTypeV2_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV2, 163, FOR_UIGlobalsTypeV2_FIELDS)
+
+#define FOR_UIGlobalsTypeV2_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV1, gState) \
+ DO_TO_FIELD (48, emuptr, eventQ) \
+ DO_TO_FIELD (52, UInt16, eventQIndex) \
+ DO_TO_FIELD (54, UInt16, eventQLength) \
+ DO_TO_FIELD (56, Int16, lastScreenX) \
+ DO_TO_FIELD (58, Int16, lastScreenY) \
+ DO_TO_FIELD (60, Boolean, lastPenDown) \
+ DO_TO_FIELD (61, UInt8, _unused1) \
+ DO_TO_FIELD (62, Int32, needNullTickCount) \
+ DO_TO_FIELD (66, emuptr, uiCurrentFontPtr) \
+ /* array of 7 emuptrs */ \
+ DO_TO_FIELD (70, emuptr, uiFontTable) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV3 =====
+// ========================================
+// Used in Palm OS 3.0.
+// Uses V2 GraphicStateType, replaces uiFontTable with uiSysFontTablePtr...uiUnused2.
+
+#define FOR_UIGlobalsTypeV3_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV3, 163, FOR_UIGlobalsTypeV3_FIELDS)
+
+#define FOR_UIGlobalsTypeV3_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV2, gState) \
+ DO_TO_FIELD (56, emuptr, eventQ) \
+ DO_TO_FIELD (60, UInt16, eventQIndex) \
+ DO_TO_FIELD (62, UInt16, eventQLength) \
+ DO_TO_FIELD (64, Int16, lastScreenX) \
+ DO_TO_FIELD (66, Int16, lastScreenY) \
+ DO_TO_FIELD (68, Boolean, lastPenDown) \
+ DO_TO_FIELD (69, UInt8, _unused1) \
+ DO_TO_FIELD (70, Int32, needNullTickCount) \
+ DO_TO_FIELD (74, emuptr, uiCurrentFontPtr) \
+ DO_TO_FIELD (78, emuptr, uiSysFontTablePtr) \
+ DO_TO_FIELD (82, emuptr, uiAppFontTablePtr) \
+ DO_TO_FIELD (86, UInt16, uiNumSysFonts) \
+ DO_TO_FIELD (88, UInt16, uiNumAppFonts) \
+ DO_TO_FIELD (90, UInt32, uiUnused1) \
+ DO_TO_FIELD (94, UInt32, uiUnused2) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV31 =====
+// ========================================
+// Used in Palm OS 3.1.
+// Replaces uiUnused1 with uiFontListPtr.
+
+#define FOR_UIGlobalsTypeV31_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV31, 163, FOR_UIGlobalsTypeV31_FIELDS)
+
+#define FOR_UIGlobalsTypeV31_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV2, gState) \
+ DO_TO_FIELD (56, emuptr, eventQ) \
+ DO_TO_FIELD (60, UInt16, eventQIndex) \
+ DO_TO_FIELD (62, UInt16, eventQLength) \
+ DO_TO_FIELD (64, Int16, lastScreenX) \
+ DO_TO_FIELD (66, Int16, lastScreenY) \
+ DO_TO_FIELD (68, Boolean, lastPenDown) \
+ DO_TO_FIELD (69, UInt8, _unused1) \
+ DO_TO_FIELD (70, Int32, needNullTickCount) \
+ DO_TO_FIELD (74, emuptr, uiCurrentFontPtr) \
+ DO_TO_FIELD (78, emuptr, uiSysFontTablePtr) \
+ DO_TO_FIELD (82, emuptr, uiAppFontTablePtr) \
+ DO_TO_FIELD (86, UInt16, uiNumSysFonts) \
+ DO_TO_FIELD (88, UInt16, uiNumAppFonts) \
+ DO_TO_FIELD (90, UInt32, uiFontListPtr) \
+ DO_TO_FIELD (94, UInt32, uiUnused2) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV32 =====
+// ========================================
+// Used in Palm OS 3.2.
+// Replaces uiUnused2 with rootWindow.
+
+#define FOR_UIGlobalsTypeV32_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV32, 163, FOR_UIGlobalsTypeV32_FIELDS)
+
+#define FOR_UIGlobalsTypeV32_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV2, gState) \
+ DO_TO_FIELD (56, emuptr, eventQ) \
+ DO_TO_FIELD (60, UInt16, eventQIndex) \
+ DO_TO_FIELD (62, UInt16, eventQLength) \
+ DO_TO_FIELD (64, Int16, lastScreenX) \
+ DO_TO_FIELD (66, Int16, lastScreenY) \
+ DO_TO_FIELD (68, Boolean, lastPenDown) \
+ DO_TO_FIELD (69, UInt8, _unused1) \
+ DO_TO_FIELD (70, Int32, needNullTickCount) \
+ DO_TO_FIELD (74, emuptr, uiCurrentFontPtr) \
+ DO_TO_FIELD (78, emuptr, uiSysFontTablePtr) \
+ DO_TO_FIELD (82, emuptr, uiAppFontTablePtr) \
+ DO_TO_FIELD (86, UInt16, uiNumSysFonts) \
+ DO_TO_FIELD (88, UInt16, uiNumAppFonts) \
+ DO_TO_FIELD (90, UInt32, uiFontListPtr) \
+ DO_TO_FIELD (94, UInt32, rootWindow) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, _unused2) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+
+
+// ========================================
+// ===== UIGlobalsTypeV35 =====
+// ========================================
+// Used in Palm OS 3.5.
+// Replaces GraphicStateTypeV2 with GraphicStateTypeV3, uicState, and
+// lastTapTime, replaces _unused1 with tapCount, replaces _unused2 with
+// allFormsClosing, added uiOptions and menuCmdBarCurrent.
+
+#define FOR_UIGlobalsTypeV35_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UIGlobalsTypeV35, 168, FOR_UIGlobalsTypeV35_FIELDS)
+
+#define FOR_UIGlobalsTypeV35_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, activeWindow) \
+ DO_TO_FIELD (4, emuptr, displayWindow) \
+ DO_TO_FIELD (8, emuptr, drawWindow) \
+ DO_TO_FIELD (12, emuptr, firstWindow) \
+ DO_TO_FIELD (16, emuptr, exitWindowID) \
+ DO_TO_FIELD (20, emuptr, enterWindowID) \
+ DO_TO_FIELD (24, emuptr, exitedWindowID) \
+ DO_TO_FIELD (28, GraphicStateTypeV3, gState) \
+ DO_TO_FIELD (40, UIColorStateType, uicState) \
+ DO_TO_FIELD (52, UInt32, lastTapTime) \
+ DO_TO_FIELD (56, emuptr, eventQ) \
+ DO_TO_FIELD (60, UInt16, eventQIndex) \
+ DO_TO_FIELD (62, UInt16, eventQLength) \
+ DO_TO_FIELD (64, Int16, lastScreenX) \
+ DO_TO_FIELD (66, Int16, lastScreenY) \
+ DO_TO_FIELD (68, Boolean, lastPenDown) \
+ DO_TO_FIELD (69, UInt8, tapCount) \
+ DO_TO_FIELD (70, Int32, needNullTickCount) \
+ DO_TO_FIELD (74, emuptr, uiCurrentFontPtr) \
+ DO_TO_FIELD (78, emuptr, uiSysFontTablePtr) \
+ DO_TO_FIELD (82, emuptr, uiAppFontTablePtr) \
+ DO_TO_FIELD (86, UInt16, uiNumSysFonts) \
+ DO_TO_FIELD (88, UInt16, uiNumAppFonts) \
+ DO_TO_FIELD (90, UInt32, uiFontListPtr) \
+ DO_TO_FIELD (94, UInt32, rootWindow) \
+ DO_TO_FIELD (98, UInt8, uiCurrentFontID) \
+ DO_TO_FIELD (99, Int16, allFormsClosing) \
+ DO_TO_FIELD (100, emuptr, currentForm) \
+ DO_TO_FIELD (104, Boolean, insPtIsEnabled) \
+ DO_TO_FIELD (105, Boolean, insPtOn) \
+ DO_TO_FIELD (106, PointType, insPtLoc) \
+ DO_TO_FIELD (110, Int16, insPtHeight) \
+ DO_TO_FIELD (112, Int32, insPtLastTick) \
+ DO_TO_FIELD (116, emuptr, insPtBitsBehind) \
+ /* array of 3 ClipboardItems */ \
+ DO_TO_FIELD (120, ClipboardItem, clipboard) \
+ DO_TO_FIELD (138, emuptr, uiCurrentMenu) \
+ DO_TO_FIELD (142, UInt16, uiCurrentMenuRscID) \
+ DO_TO_FIELD (144, FieldUndoType, undoGlobals) \
+ DO_TO_FIELD (156, UInt8, gsiState) \
+ DO_TO_FIELD (157, Boolean, gsiIsEnabled) \
+ DO_TO_FIELD (158, PointType, gsiLocation) \
+ DO_TO_FIELD (162, Char, uiDecimalSeparator) \
+ DO_TO_FIELD (163, UInt8, uiOptions) \
+ DO_TO_FIELD (164, emuptr, menuCmdBarCurrent) \
+
+
+// ========================================
+// ===== UsbHwrType =====
+// ========================================
+
+#define FOR_UsbHwrType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (UsbHwrType, 4, FOR_UsbHwrType_FIELDS)
+
+#define FOR_UsbHwrType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt8, data) \
+ DO_TO_FIELD (1, UInt8, ___filler0) \
+ DO_TO_FIELD (2, UInt8, command) \
+ DO_TO_FIELD (3, UInt8, ___filler1) \
+
+
+
+// ========================================
+// ===== WindowFlagsType =====
+// ========================================
+
+#define FOR_WindowFlagsType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (WindowFlagsType, 2, FOR_WindowFlagsType_FIELDS)
+
+#define FOR_WindowFlagsType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, UInt16, flags) \
+
+
+// ========================================
+// ===== WindowType =====
+// ========================================
+
+#define FOR_WindowType_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (WindowType, 40, FOR_WindowType_FIELDS)
+
+#define FOR_WindowType_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, Coord, displayWidthV20) \
+ DO_TO_FIELD (2, Coord, displayHeightV20) \
+ DO_TO_FIELD (4, emuptr, displayAddrV20) \
+ DO_TO_FIELD (8, WindowFlagsType, windowFlags) \
+ DO_TO_FIELD (10, RectangleType, windowBounds) \
+ DO_TO_FIELD (18, AbsRectType, clippingBounds) \
+ DO_TO_FIELD (26, emuptr, bitmapP) \
+ DO_TO_FIELD (30, FrameBitsType, frameType) \
+ DO_TO_FIELD (32, emuptr, drawStateP) \
+ DO_TO_FIELD (36, emuptr, nextWindow) \
+
+
+// ========================================
+// ===== cjxln =====
+// ========================================
+
+#define FOR_cjxln_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (cjxln, 8, FOR_cjxln_FIELDS)
+
+#define FOR_cjxln_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, emuptr, xlnnext) \
+ DO_TO_FIELD (4, emuptr, xlnprev) \
+
+
+// ========================================
+// ===== cj_xgbh =====
+// ========================================
+
+#define FOR_cj_xgbh_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (cj_xgbh, 28, FOR_cj_xgbh_FIELDS)
+
+#define FOR_cj_xgbh_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, cjxln, xgbhln) \
+ DO_TO_FIELD (8, cjxln, xgbhwait) \
+ DO_TO_FIELD (16, Int16, xgbhpry) \
+ DO_TO_FIELD (18, UInt8, xgbhmod) \
+ DO_TO_FIELD (19, Int8, xgbhidkey) \
+ DO_TO_FIELD (20, UInt32, xgbhtag) \
+ DO_TO_FIELD (24, UInt32, xgbhdjp) \
+
+
+// ========================================
+// ===== cj_xsmb =====
+// ========================================
+
+#define FOR_cj_xsmb_STRUCT(DO_TO_STRUCT) \
+ DO_TO_STRUCT (cj_xsmb, 48, FOR_cj_xsmb_FIELDS)
+
+#define FOR_cj_xsmb_FIELDS(DO_TO_FIELD) \
+ DO_TO_FIELD (0, cj_xgbh, xsmh) \
+ DO_TO_FIELD (28, emuptr, xsmowner) \
+ DO_TO_FIELD (32, Int32, xsmival) \
+ DO_TO_FIELD (36, Int32, xsmval) \
+ DO_TO_FIELD (40, Int32, xsmuse) \
+ DO_TO_FIELD (44, Int32, xsmrsv) \
+
diff --git a/SrcShared/EmPixMap.cpp b/SrcShared/EmPixMap.cpp
new file mode 100644
index 0000000..5b73c9f
--- /dev/null
+++ b/SrcShared/EmPixMap.cpp
@@ -0,0 +1,2500 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPixMap.h"
+
+#include "Platform.h" // Platform::AllocateMemory
+
+/*
+ EmPixMap is a simple class for managing pixmaps (multi-bpp bitmap)
+ in a cross-platform fashion.
+
+ Poser makes use of pixmaps in the following ways:
+
+ - Converting the LCD frame buffer to something that can be
+ displayed by the host.
+ - Converting the JPEG skin images to something that can be
+ displayed by the host.
+ - Executing the "Save Screen..." command.
+
+ As such, EmPixMap does not try to be everything to everybody. In
+ particular, it does not support all possible bitdepths and pixel
+ formats. In general, it supports 1-, 8-, 24-, and 32-bit buffers,
+ where the 32-bit buffer is always in ARGB format. While there are
+ routines that manage the conversion of 1-, 2-, and 4-bpp buffers into
+ one of the above formats, these are in place solely for converting
+ the LCD framebuffer into one of the standard EmPixMap formats.
+
+ EmPixMap also has some utility routines that are useful for carrying
+ some of Poser's facilities. It can flip all of the scanlines in order
+ to help interoperate with Windows BMPs; it can create an outline region
+ that can be used to create a host window's border; etc.
+*/
+
+
+static uint32* gConvert1To8; // Used to convert a 4-bit nybble consisting of 4 1-bit pixels
+ // to a 32-bit value containing 4 8-bit pixels.
+
+static uint32* gConvert2To8; // Used to convert an 8-bit byte consisting of 4 2-bit pixels
+ // to a 32-bit value containing 4 8-bit pixels.
+
+static uint16* gConvert4To8; // Used to convert an 8-bit byte consisting of 2 4-bit pixels
+ // to a 16-bit value containing 4 8-bit pixels.
+
+struct ScanlineParms
+{
+ uint8* fDestScanline;
+ const uint8* fSrcScanline;
+ const RGBList* fDestColors;
+ const RGBList* fSrcColors;
+ EmCoord fLeft;
+ EmCoord fRight;
+};
+
+
+// We have scanline converters that can go from bitdepth M to bitdepth N.
+// The appropriate converter is chosen and stored in a variable of the
+// following type.
+
+typedef void (*ScanlineConverter) (const ScanlineParms&);
+
+
+static void PrvMakeMask (void* dstPtr, void* srcPtr, long rowBytes, long width, long height);
+static void PrvAddToRegion (EmRegion& region, int top, int left, int right);
+static EmPixMapDepth PrvGetDepth (EmPixMapFormat);
+
+#define DECLARE_CONVERTER(src_format, dest_format) \
+ static void PrvConvert##src_format##To##dest_format (const ScanlineParms&);
+
+
+// Define FOR_EACH_FORMAT, a macro which iterates over all of
+// pixmap formats we support.
+//
+// !!! Science project...how can I use this macro to iterate
+// over *pairs* of formats in a generic way? That is, I want
+// be able to say something like:
+//
+// #define FOR_EACH_FORMAT_PAIR(DO_TO_PAIR) ...
+//
+// #define DECLARE_CONVERTER(format1, format2) ...
+//
+// FOR_EACH_FORMAT_PAIR(DECLARE_CONVERTER)
+//
+// One restriction of this exercise is that I don't want to
+// define another macro that explicitly lists the formats.
+// That should be limited to FOR_EACH_FORMAT.
+
+#define FOR_EACH_FORMAT(DO_TO_FORMAT) \
+ DO_TO_FORMAT (1) \
+ DO_TO_FORMAT (2) \
+ DO_TO_FORMAT (4) \
+ DO_TO_FORMAT (8) \
+ DO_TO_FORMAT (24RGB) \
+ DO_TO_FORMAT (24BGR) \
+ DO_TO_FORMAT (32ARGB) \
+ DO_TO_FORMAT (32ABGR) \
+ DO_TO_FORMAT (32RGBA) \
+ DO_TO_FORMAT (32BGRA)
+
+
+
+// Define FOR_EACH_FORMAT_PAIR, which iterates over all of the src/dest
+// format pairings. We do this with a helper macro (FOR_EACH_FORMAT_PAIR_0)
+// that allows us to multiply all the pairings together.
+
+#define FOR_EACH_FORMAT_PAIR_0(DO_TO_PAIR, fmt) \
+ DO_TO_PAIR (fmt, 1) \
+ DO_TO_PAIR (fmt, 2) \
+ DO_TO_PAIR (fmt, 4) \
+ DO_TO_PAIR (fmt, 8) \
+ DO_TO_PAIR (fmt, 24RGB) \
+ DO_TO_PAIR (fmt, 24BGR) \
+ DO_TO_PAIR (fmt, 32ARGB) \
+ DO_TO_PAIR (fmt, 32ABGR) \
+ DO_TO_PAIR (fmt, 32RGBA) \
+ DO_TO_PAIR (fmt, 32BGRA)
+
+
+#define FOR_EACH_FORMAT_PAIR(DO_TO_PAIR) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 1) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 2) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 4) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 8) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 24RGB) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 24BGR) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 32ARGB) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 32ABGR) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 32RGBA) \
+ FOR_EACH_FORMAT_PAIR_0 (DO_TO_PAIR, 32BGRA)
+
+
+FOR_EACH_FORMAT_PAIR (DECLARE_CONVERTER)
+
+
+// Macros used for accessing and converting/copying pixels.
+
+#define GET_24RGB(srcPtr, r, g, b, a) \
+ r = *srcPtr++; \
+ g = *srcPtr++; \
+ b = *srcPtr++; \
+ a = 0;
+
+
+#define GET_24BGR(srcPtr, r, g, b, a) \
+ b = *srcPtr++; \
+ g = *srcPtr++; \
+ r = *srcPtr++; \
+ a = 0;
+
+
+#define GET_32ARGB(srcPtr, r, g, b, a) \
+ a = *srcPtr++; \
+ r = *srcPtr++; \
+ g = *srcPtr++; \
+ b = *srcPtr++;
+
+
+#define GET_32ABGR(srcPtr, r, g, b, a) \
+ a = *srcPtr++; \
+ b = *srcPtr++; \
+ g = *srcPtr++; \
+ r = *srcPtr++;
+
+
+#define GET_32RGBA(srcPtr, r, g, b, a) \
+ r = *srcPtr++; \
+ g = *srcPtr++; \
+ b = *srcPtr++; \
+ a = *srcPtr++;
+
+
+#define GET_32BGRA(srcPtr, r, g, b, a) \
+ b = *srcPtr++; \
+ g = *srcPtr++; \
+ r = *srcPtr++; \
+ a = *srcPtr++;
+
+
+#define PUT_24RGB(destPtr, r, g, b, a) \
+ *destPtr++ = r; \
+ *destPtr++ = g; \
+ *destPtr++ = b;
+
+
+#define PUT_24BGR(destPtr, r, g, b, a) \
+ *destPtr++ = b; \
+ *destPtr++ = g; \
+ *destPtr++ = r;
+
+
+#define PUT_32ARGB(destPtr, r, g, b, a) \
+ *destPtr++ = a; \
+ *destPtr++ = r; \
+ *destPtr++ = g; \
+ *destPtr++ = b;
+
+
+#define PUT_32ABGR(destPtr, r, g, b, a) \
+ *destPtr++ = a; \
+ *destPtr++ = b; \
+ *destPtr++ = g; \
+ *destPtr++ = r;
+
+
+#define PUT_32RGBA(destPtr, r, g, b, a) \
+ *destPtr++ = r; \
+ *destPtr++ = g; \
+ *destPtr++ = b; \
+ *destPtr++ = a;
+
+
+#define PUT_32BGRA(destPtr, r, g, b, a) \
+ *destPtr++ = b; \
+ *destPtr++ = g; \
+ *destPtr++ = r; \
+ *destPtr++ = a;
+
+
+#define CONVERT_PACKED_PIXEL(shift, mask, dest_format) \
+ if (xx++ >= right) \
+ break; \
+ { \
+ const RGBType& rgb = (*srcColors)[(bits >> (shift)) & (mask)]; \
+ PUT_##dest_format(destPtr, rgb.fRed, rgb.fGreen, rgb.fBlue, 0) \
+ }
+
+
+#define CONVERT_PACKED_BYTE_1(dest_format) \
+ CONVERT_PACKED_PIXEL(7, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(6, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(5, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(4, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(3, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(2, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(1, 0x01, dest_format) \
+ CONVERT_PACKED_PIXEL(0, 0x01, dest_format)
+
+
+#define CONVERT_PACKED_BYTE_2(dest_format) \
+ CONVERT_PACKED_PIXEL(6, 0x03, dest_format) \
+ CONVERT_PACKED_PIXEL(4, 0x03, dest_format) \
+ CONVERT_PACKED_PIXEL(2, 0x03, dest_format) \
+ CONVERT_PACKED_PIXEL(0, 0x03, dest_format)
+
+
+#define CONVERT_PACKED_BYTE_4(dest_format) \
+ CONVERT_PACKED_PIXEL(4, 0x0F, dest_format) \
+ CONVERT_PACKED_PIXEL(0, 0x0F, dest_format)
+
+
+#define CONVERT_PACKED_BYTE_8(dest_format) \
+ if (xx++ >= right) \
+ break; \
+ \
+ const RGBType& rgb = (*srcColors)[bits]; \
+ PUT_##dest_format(destPtr, rgb.fRed, rgb.fGreen, rgb.fBlue, 0)
+
+
+#define STD_NO_CONVERT(BPP) \
+ long numBytes = ((parms.fRight * BPP) + 7) / 8; \
+ memcpy (parms.fDestScanline, parms.fSrcScanline, numBytes);
+
+
+#define STD_DIRECT_CONVERT(src_format, dest_format) \
+ EmCoord right = parms.fRight; \
+ uint8* destPtr = parms.fDestScanline; \
+ const uint8* srcPtr = parms.fSrcScanline; \
+ \
+ for (EmCoord xx = 0; xx < right; ++xx) \
+ { \
+ uint8 r, g, b, a; \
+ GET_##src_format(srcPtr, r, g, b, a) \
+ PUT_##dest_format(destPtr, r, g, b, a) \
+ }
+
+
+#define STD_INDEX_TO_DIRECT_CONVERT(src_format, dest_format) \
+ EmCoord right = parms.fRight; \
+ uint8* destPtr = parms.fDestScanline; \
+ const uint8* srcPtr = parms.fSrcScanline; \
+ const RGBList* srcColors = parms.fSrcColors; \
+ \
+ EmAssert (srcColors); \
+ \
+ EmCoord xx = 0; \
+ while (1) \
+ { \
+ uint8 bits = *srcPtr++; \
+ CONVERT_PACKED_BYTE_##src_format(dest_format) \
+ }
+
+
+#define STD_DIRECT_TO_1_CONVERT(src_format) \
+ EmCoord right = parms.fRight; \
+ uint8* destPtr = parms.fDestScanline; \
+ const uint8* srcPtr = parms.fSrcScanline; \
+ \
+ uint8 bitMask = 0x80; \
+ uint8 aByte = 0; \
+ \
+ for (EmCoord xx = 0; xx < right; ++xx) \
+ { \
+ uint8 r, g, b, a; \
+ GET_##src_format(srcPtr, r, g, b, a) \
+ \
+ Bool isDark1 = r < 0xC0; \
+ Bool isDark2 = g < 0xC0; \
+ Bool isDark3 = b < 0xC0; \
+ \
+ if (isDark1 || isDark2 || isDark3) \
+ { \
+ /* Assumes white/black color table! */ \
+ aByte |= bitMask; \
+ } \
+ \
+ bitMask >>= 1; \
+ if (bitMask == 0) \
+ { \
+ *destPtr++ = aByte; \
+ bitMask = 0x80; \
+ aByte = 0; \
+ } \
+ } \
+ \
+ /* Write out any partially filled out byte. */ \
+ \
+ if (bitMask != 0) \
+ { \
+ *destPtr++ = aByte; \
+ }
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap constructor
+ *
+ * DESCRIPTION: Intialize data members.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmPixMap::EmPixMap (void) :
+ fSize (0, 0),
+ fFormat (kPixMapFormat1),
+ fRowBytes (0),
+ fColors (),
+ fPixels (NULL),
+ fPixelsOwned (true)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap copy constructor
+ *
+ * DESCRIPTION: Create a new EmPixMap that is a clone of "other".
+ *
+ * PARAMETERS: other - pixmap to make a copy of.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmPixMap::EmPixMap (const EmPixMap& other) :
+ fSize (other.fSize),
+ fFormat (other.fFormat),
+ fRowBytes (other.fRowBytes),
+ fColors (other.fColors),
+ fPixels (NULL),
+ fPixelsOwned (true)
+{
+ this->CopyPixelBuffer (other);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap destructor
+ *
+ * DESCRIPTION: Reclaim resources.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmPixMap::~EmPixMap (void)
+{
+ if (fPixelsOwned)
+ {
+ Platform::DisposeMemory (fPixels);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap assignment operator
+ *
+ * DESCRIPTION: Make "*this" look like "other".
+ *
+ * PARAMETERS: other - source pixmap.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmPixMap&
+EmPixMap::operator= (const EmPixMap& other)
+{
+ if (&other != this)
+ {
+ fSize = other.fSize;
+ fFormat = other.fFormat;
+ fRowBytes = other.fRowBytes;
+ fColors = other.fColors;
+
+ this->CopyPixelBuffer (other);
+ }
+
+ return *this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetSize
+ *
+ * DESCRIPTION: Return the size of the image.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: EmPoint containing the image size.
+ *
+ ***********************************************************************/
+
+EmPoint
+EmPixMap::GetSize (void) const
+{
+ return fSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::SetSize
+ *
+ * DESCRIPTION: Set the size of the image. Any old image is discarded
+ * and a new buffer is allocated.
+ *
+ * PARAMETERS: p - new image size.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::SetSize (const EmPoint& p)
+{
+ if (fSize != p)
+ {
+ fSize = p;
+ fRowBytes = this->DetermineRowBytes ();
+ this->InvalidateBuffer ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetDepth
+ *
+ * DESCRIPTION: Return the image depth (bits per pixel).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The image depth.
+ *
+ ***********************************************************************/
+
+EmPixMapDepth
+EmPixMap::GetDepth (void) const
+{
+ return ::PrvGetDepth (fFormat);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetFormat
+ *
+ * DESCRIPTION: Return the format of the pixels.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The pixel format.
+ *
+ ***********************************************************************/
+
+EmPixMapFormat
+EmPixMap::GetFormat (void) const
+{
+ return fFormat;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::SetFormat
+ *
+ * DESCRIPTION: Set the bitdepth of the image. Any old image is
+ * discarded and a new buffer is allocated.
+ *
+ * PARAMETERS: d - new bith depth.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::SetFormat (EmPixMapFormat f)
+{
+ EmPixMapDepth oldDepth = this->GetDepth ();
+
+ fFormat = f;
+
+ if (oldDepth != this->GetDepth ())
+ {
+ fRowBytes = this->DetermineRowBytes ();
+ this->InvalidateBuffer ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetRowBytes
+ *
+ * DESCRIPTION: Return the number of bytes in a scanline.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The number of bytes in a scanline.
+ *
+ ***********************************************************************/
+
+EmPixMapRowBytes
+EmPixMap::GetRowBytes (void) const
+{
+ return fRowBytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::SetRowBytes
+ *
+ * DESCRIPTION: Set the number of bytes in a scanline. Any old image is
+ * discarded and a new buffer is allocated. In general,
+ * you should not have to call this function; a rowbytes
+ * value is determined based on the width and depth of the
+ * image. You should call SetRowBytes only under
+ * exceptional circumstances to override the default.
+ *
+ * PARAMETERS: b - new rowbytes value.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::SetRowBytes (EmPixMapRowBytes b)
+{
+ if (fRowBytes != b)
+ {
+ fRowBytes = b;
+ this->InvalidateBuffer ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetColorTable
+ *
+ * DESCRIPTION: Return a *CONST REFERENCE* to the color table used by
+ * the image. The color table will be empty for direct
+ * pixmaps (where the depth is > 8). In general, the
+ * number of entries in the table will be (1 << depth),
+ * but nothing in EmPixMap itself relies on this.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Reference to the color table.
+ *
+ ***********************************************************************/
+
+const RGBList&
+EmPixMap::GetColorTable (void) const
+{
+ return fColors;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::SetColorTable
+ *
+ * DESCRIPTION: Set the color table to be used for indexed pixmaps
+ * (where the depth is <= 8). It is up to the caller to
+ * make sure enough entries are supplied; EmPixMap assumes
+ * that there are. Also, no color mapping is performed
+ * (that is, no effort is made to change the pixels in the
+ * buffer such that they end up pointing to the same or
+ * similar RGB values).
+ *
+ * PARAMETERS: c - the new color table.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::SetColorTable (const RGBList& c)
+{
+ fColors = c;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::GetBits
+ *
+ * DESCRIPTION: Return a pointer to the pixel buffer.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Pointer to the pixel buffer.
+ *
+ ***********************************************************************/
+
+const void*
+EmPixMap::GetBits (void) const
+{
+ this->UpdateBuffer ();
+ return &fPixels[0];
+}
+
+void*
+EmPixMap::GetBits (void)
+{
+ this->UpdateBuffer ();
+ return &fPixels[0];
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::SetBits
+ *
+ * DESCRIPTION: Set the pixels to be used by the pixmap. Note that the
+ * pixels are NOT OWNED, nor are they copied! This
+ * function is used to wrap up EXISTING pixels from some
+ * other source (such as a host pixmap).
+ *
+ * PARAMETERS: bits - bits to adopt.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::SetBits (void* bits)
+{
+ this->InvalidateBuffer ();
+ fPixels = (uint8*) bits;
+ fPixelsOwned = false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::CreateMask
+ *
+ * DESCRIPTION: Change dest to be a 1-bpp pixmap containing a mask for
+ * the "this" pixmap. The mask will contain black pixels
+ * for the parts inside the mask, and white pixels for the
+ * parts outside the mask. The mask created is similar to
+ * that used by the Macintosh Finder to define the boundary
+ * of an icon.
+ *
+ * PARAMETERS: dest - pixmap that will receive the mask. The caller
+ * does not need to prepare this pixmap in any way; it
+ * gets completely reinitialized by this function.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmPixMap::CreateMask (EmPixMap& dest) const
+{
+ // Create a simple black & white color table.
+
+ RGBList colors;
+ colors.push_back (RGBType (255, 255, 255)); // 0 = white
+ colors.push_back (RGBType (0, 0, 0)); // 1 = black
+
+ // Convert (*this) into a 1-bpp bitmap, putting the result in src.
+
+ EmPixMap src;
+ src.SetSize (this->GetSize ());
+ src.SetFormat (kPixMapFormat1);
+ src.SetColorTable (colors);
+
+ EmRect rect (EmPoint (0, 0), this->GetSize());
+
+ EmPixMap::CopyRect (src, *this, rect, rect);
+
+ // Initialize the destination bitmap.
+
+ dest.SetSize (this->GetSize ());
+ dest.SetFormat (kPixMapFormat1);
+ dest.SetColorTable (colors);
+
+ // Call low-level routine to create the mask.
+
+ ::PrvMakeMask (dest.GetBits (), src.GetBits (), src.GetRowBytes (),
+ src.GetSize().fX, src.GetSize().fY);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::CreateRegion
+ *
+ * DESCRIPTION: Scan-convert a 1-bpp bitmap into a region. Zero bits
+ * are outside the region and one bits are inside it.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The bitmap converted into a region.
+ *
+ ***********************************************************************/
+
+EmRegion
+EmPixMap::CreateRegion (void) const
+{
+ EmRegion region;
+
+ uint8* bits = (uint8*) this->GetBits ();
+ EmCoord width = this->GetSize().fX;
+ EmCoord height = this->GetSize().fY;
+ EmPixMapRowBytes rowBytes = this->GetRowBytes ();
+
+ for (EmCoord yy = 0; yy < height; ++yy)
+ {
+ Bool wasInRegion = false;
+ long xStart = 0;
+ long xEnd = 0;
+
+ uint8* cBits = bits + yy * rowBytes;
+
+ uint8 aByte = 0;
+ uint8 bitMask = 0;
+
+ for (long xx = 0; xx < width; ++xx, bitMask >>= 1)
+ {
+ if (bitMask == 0)
+ {
+ bitMask = 0x80;
+ aByte = *cBits++;
+ }
+
+ Bool nowInRegion = (aByte & bitMask) != 0;
+
+ // Entering a region?
+
+ if (nowInRegion && !wasInRegion)
+ {
+ // Start new "in region" scan
+
+ xStart = xx;
+ }
+
+ // Exiting a region?
+
+ else if (!nowInRegion && wasInRegion)
+ {
+ // Close off "in region" scan.
+
+ xEnd = xx;
+ ::PrvAddToRegion (region, yy, xStart, xEnd);
+ }
+
+ wasInRegion = nowInRegion;
+ }
+
+ // End of scan line. Check to see if the region scan is still
+ // open. If so, close it.
+
+ if (wasInRegion)
+ {
+ xEnd = width;
+ ::PrvAddToRegion (region, yy, xStart, xEnd);
+ }
+ }
+
+ return region;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::ChangeTone
+ *
+ * DESCRIPTION: Adjust the pixmap in the given line range by the given
+ * percentage.
+ *
+ * PARAMETERS: amount - amount by which the image should be adjusted.
+ * 100 = White
+ * 1...99 = Lighten
+ * 0 = No change
+ * -1...-99 = Darken
+ * -100 = Black
+ *
+ * firstLine - first scanline in the image to alter.
+ *
+ * lastLine - last scanline in the image to alter plus 1.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+inline void PrvAdjustPixel_ChangeTone (uint8& r, uint8& g, uint8& b, int32 amount)
+{
+ if (amount >= 0)
+ {
+ // Lighten the value.
+ //
+ // If amount == 0, rhs == 0, leaving value unchanged.
+ //
+ // If amount == 255, rhs == 255 - (value * 255 / 255),
+ // == 255 - value, leaving value at 255.
+
+ r += (amount - (r * amount / 255));
+ g += (amount - (g * amount / 255));
+ b += (amount - (b * amount / 255));
+ }
+ else
+ {
+ // Darken the value.
+ //
+ // If amount == 0, rhs == 0, leaving value unchanged.
+ //
+ // If amount == -255, rhs == value * -255 / 255 == -value, leaving value at zero.
+
+ r += (r * amount / 255);
+ g += (g * amount / 255);
+ b += (b * amount / 255);
+ }
+}
+
+
+void
+EmPixMap::ChangeTone (int32 percent, EmCoord firstLine, EmCoord lastLine)
+{
+ EmAssert (percent >= -100);
+ EmAssert (percent <= 100);
+
+ EmPixMapDepth depth = this->GetDepth ();
+ EmPixMapFormat format = this->GetFormat ();
+ int32 amount = (percent * 255) / 100;
+
+ if (firstLine == -1)
+ firstLine = 0;
+
+ if (lastLine == -1)
+ lastLine = this->GetSize ().fY;
+
+ // If the image has a color table, alter that.
+
+ if (depth <= 8)
+ {
+ RGBList::iterator iter = fColors.begin ();
+ while (iter != fColors.end ())
+ {
+ // Munge the RGB values directly. You might be tempted to
+ // convert the RGB values to HSV values, alter the V
+ // parameter, and then convert back. However, that gives
+ // pretty much the same results.
+
+ RGBType& rgb = *iter;
+
+ ::PrvAdjustPixel_ChangeTone (rgb.fRed, rgb.fGreen, rgb.fBlue, amount);
+
+ ++iter;
+ }
+ }
+
+ // If the image is direct, alter that.
+
+ else
+ {
+ uint8* image = (uint8*) this->GetBits ();
+ EmPixMapRowBytes rowBytes = this->GetRowBytes ();
+ EmCoord width = this->GetSize ().fX;
+
+ for (int yy = firstLine; yy < lastLine; ++yy)
+ {
+ uint8* scanline = image + rowBytes * yy;
+ uint8* pixPtr = scanline;
+
+ for (int xx = 0; xx < width; ++xx)
+ {
+ uint8 r, g, b, a;
+
+ switch (format)
+ {
+ case kPixMapFormat24RGB: GET_24RGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat24BGR: GET_24BGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ARGB: GET_32ARGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ABGR: GET_32ABGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32RGBA: GET_32RGBA (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32BGRA: GET_32BGRA (pixPtr, r, g, b, a); break;
+ default: EmAssert (false); r = g = b = a = 0;
+ }
+
+ // Munge the RGB values directly. You might be tempted to
+ // convert the RGB values to HSV values, alter the V
+ // parameter, and then convert back. However, that gives
+ // pretty much the same results.
+
+ ::PrvAdjustPixel_ChangeTone (r, g, b, amount);
+
+ switch (format)
+ {
+ case kPixMapFormat24RGB: pixPtr -= 3; PUT_24RGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat24BGR: pixPtr -= 3; PUT_24BGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ARGB: pixPtr -= 4; PUT_32ARGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ABGR: pixPtr -= 4; PUT_32ABGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32RGBA: pixPtr -= 4; PUT_32RGBA (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32BGRA: pixPtr -= 4; PUT_32BGRA (pixPtr, r, g, b, a); break;
+ default: EmAssert (false);
+ }
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::ConvertToColor
+ *
+ * DESCRIPTION: Adjust the pixmap in the given line range by the given
+ * percentage.
+ *
+ * PARAMETERS: type - color to which the pixmap should be converted.
+ * 100 = White
+ * 1...99 = Lighten
+ * 0 = No change
+ * -1...-99 = Darken
+ * -100 = Black
+ *
+ * firstLine - first scanline in the image to alter.
+ *
+ * lastLine - last scanline in the image to alter plus 1.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+inline void PrvAdjustPixel_ConvertToColor (uint8& r, uint8& g, uint8& b, int type)
+{
+ // First convert to grayscale.
+
+ uint8 gray = (uint8) ((r * 0.2990) + (g * 0.5870) + (b * 0.1140));
+
+ // The assign the 8-bit grayscale value accordingly.
+
+ switch (type)
+ {
+ case 0:
+ r = gray;
+ g = gray;
+ b = gray;
+ break;
+
+ case 1:
+ r = gray;
+ g = 0;
+ b = 0;
+ break;
+
+ case 2:
+ r = 0;
+ g = gray;
+ b = 0;
+ break;
+
+ case 3:
+ r = 0;
+ g = 0;
+ b = gray;
+ break;
+ }
+}
+
+
+void
+EmPixMap::ConvertToColor (int type, EmCoord firstLine, EmCoord lastLine)
+{
+ EmAssert (type >= 0);
+ EmAssert (type <= 3);
+
+ EmPixMapDepth depth = this->GetDepth ();
+ EmPixMapFormat format = this->GetFormat ();
+
+ if (firstLine == -1)
+ firstLine = 0;
+
+ if (lastLine == -1)
+ lastLine = this->GetSize ().fY;
+
+ // If the image has a color table, alter that.
+
+ if (depth <= 8)
+ {
+ RGBList::iterator iter = fColors.begin ();
+ while (iter != fColors.end ())
+ {
+ // Munge the RGB values directly.
+
+ RGBType& rgb = *iter;
+
+ ::PrvAdjustPixel_ConvertToColor (rgb.fRed, rgb.fGreen, rgb.fBlue, type);
+
+ ++iter;
+ }
+ }
+
+ // If the image is direct, alter that.
+
+ else
+ {
+ uint8* image = (uint8*) this->GetBits ();
+ EmPixMapRowBytes rowBytes = this->GetRowBytes ();
+ EmCoord width = this->GetSize ().fX;
+
+ for (int yy = firstLine; yy < lastLine; ++yy)
+ {
+ uint8* scanline = image + rowBytes * yy;
+ uint8* pixPtr = scanline;
+
+ for (int xx = 0; xx < width; ++xx)
+ {
+ uint8 r, g, b, a;
+
+ switch (format)
+ {
+ case kPixMapFormat24RGB: GET_24RGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat24BGR: GET_24BGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ARGB: GET_32ARGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ABGR: GET_32ABGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32RGBA: GET_32RGBA (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32BGRA: GET_32BGRA (pixPtr, r, g, b, a); break;
+ default: EmAssert (false); r = g = b = a = 0;
+ }
+
+ // Munge the RGB values directly.
+
+ ::PrvAdjustPixel_ConvertToColor (r, g, b, type);
+
+ switch (format)
+ {
+ case kPixMapFormat24RGB: pixPtr -= 3; PUT_24RGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat24BGR: pixPtr -= 3; PUT_24BGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ARGB: pixPtr -= 4; PUT_32ARGB (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32ABGR: pixPtr -= 4; PUT_32ABGR (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32RGBA: pixPtr -= 4; PUT_32RGBA (pixPtr, r, g, b, a); break;
+ case kPixMapFormat32BGRA: pixPtr -= 4; PUT_32BGRA (pixPtr, r, g, b, a); break;
+ default: EmAssert (false);
+ }
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::FlipScanlines
+ *
+ * DESCRIPTION: Invert the image in the pixel buffer, swapping all the
+ * pixels around the x-axis horizontally bisecting the image.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::FlipScanlines (void)
+{
+ long height = fSize.fY;
+ long rowBytes = fRowBytes;
+ uint8* topLine = (uint8*) this->GetBits ();
+ uint8* bottomLine = topLine + (height - 1) * rowBytes;
+
+ void* tempBuffer = Platform::AllocateMemory (rowBytes);
+
+ while (bottomLine > topLine)
+ {
+ memcpy (tempBuffer, topLine, rowBytes);
+ memcpy (topLine, bottomLine, rowBytes);
+ memcpy (bottomLine, tempBuffer, rowBytes);
+
+ topLine += rowBytes;
+ bottomLine -= rowBytes;
+ }
+
+ Platform::DisposeMemory (tempBuffer);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::ConvertToFormat
+ *
+ * DESCRIPTION: Convert "*this" to be a pixmap of the given depth,
+ * preserving the pixels in the current buffer.
+ *
+ * PARAMETERS: destDepth - the new depth of the pixmap.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::ConvertToFormat (EmPixMapFormat destFormat)
+{
+ // Copy our pixels to a new pixmap, converting along the way.
+
+ EmPixMap dest;
+ dest.SetSize (this->GetSize ());
+ dest.SetFormat (destFormat);
+ dest.SetColorTable (this->GetColorTable ());
+
+ EmRect rect (EmPoint (0, 0), this->GetSize());
+
+ EmPixMap::CopyRect (dest, *this, rect, rect);
+
+ // Now copy those newly-converted pixels back to us.
+
+ this->SetFormat (destFormat);
+ this->CopyPixelBuffer (dest);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CopyRect
+ *
+ * DESCRIPTION: Copy pixels from src pixmap to dest pixmap, copying
+ * from srcRect to destRect, converting and scaling along
+ * the way.
+ *
+ * RESTRICTIONS: Currently, no translation of pixels can
+ * occur. Additionally, the only scaling allowed
+ * is scaling up by a factor of two. Finally, no
+ * depth conversions will take place if the process
+ * requires an inverse table lookup.
+ *
+ * PARAMETERS: dest - pixmap to receive the pixels.
+ *
+ * src - pixmap to provide the pixels.
+ *
+ * destRect - area within dest to where the pixels will be
+ * copied.
+ *
+ * srcRect - area within src fro where the pixels will be
+ * copied.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::CopyRect (EmPixMap& dest, const EmPixMap& src,
+ const EmRect& destRect, const EmRect& srcRect)
+{
+ // Validate the parameters; we don't support everything just yet.
+
+ EmAssert (destRect.fLeft == 0);
+ EmAssert (srcRect.fLeft == 0);
+
+ EmAssert (destRect.fRight == dest.GetSize().fX);
+ EmAssert (srcRect.fRight == src.GetSize().fX);
+
+ EmAssert (srcRect.fRight == destRect.fRight || srcRect.fRight * 2 == destRect.fRight);
+ EmAssert (srcRect.fTop == destRect.fTop || srcRect.fTop * 2 == destRect.fTop);
+ EmAssert (srcRect.fBottom == destRect.fBottom || srcRect.fBottom * 2 == destRect.fBottom);
+
+ // Gather data common to all conversions.
+
+ EmPixMapRowBytes destRowBytes = dest.GetRowBytes ();
+ EmPixMapRowBytes srcRowBytes = src.GetRowBytes ();
+
+ EmCoord top = srcRect.fTop;
+ EmCoord bottom = srcRect.fBottom;
+
+ ScanlineParms parms;
+
+ parms.fDestScanline = ((uint8*) dest.GetBits ()) + top * destRowBytes;
+ parms.fSrcScanline = ((uint8*) src.GetBits ()) + top * srcRowBytes;
+
+ parms.fDestColors = dest.GetDepth () <= 8 ? &dest.GetColorTable () : NULL;
+ parms.fSrcColors = src.GetDepth () <= 8 ? &src.GetColorTable () : NULL;
+
+ parms.fLeft = srcRect.fLeft;
+ parms.fRight = srcRect.fRight;
+
+
+ // Determine what scanline converter to use.
+
+ ScanlineConverter conv = NULL;
+ long srcDestFormat = (((uint32) src.GetFormat ()) << 16) | (uint32) dest.GetFormat ();
+
+ switch (srcDestFormat)
+ {
+
+#define CONVERTER_CASE(src_format, dest_format) \
+ case (((uint32) kPixMapFormat##src_format) << 16) | (uint32) kPixMapFormat##dest_format: \
+ conv = &::PrvConvert##src_format##To##dest_format; \
+ break;
+
+ FOR_EACH_FORMAT_PAIR (CONVERTER_CASE)
+ }
+
+ EmAssert (conv);
+
+ // Create any tables we (might) need.
+
+ ::Get1To8Table ();
+ ::Get2To8Table ();
+ ::Get4To8Table ();
+
+ // Do the conversion.
+
+ for (EmCoord yy = top; yy < bottom; ++yy)
+ {
+ conv (parms);
+
+ parms.fDestScanline += destRowBytes;
+ parms.fSrcScanline += srcRowBytes;
+ }
+
+ if (destRect != srcRect)
+ {
+ // Now scale up. The pixels have been copied in 8-, 24- or
+ // 32-bit format to the upper-left of the dest pixmap. Expand
+ // that guy both horizontally and vertically. In order to not
+ // smash the pixels already there (we're converting the dest
+ // pixmap "in place"), scale from bottom to top and right to left.
+
+ EmPixMapDepth destDepth = dest.GetDepth ();
+ uint8* destBasePtr = (uint8*) dest.GetBits ();
+ long halfDestRowBytes = destRowBytes / 2;
+ uint8* srcLinePtr = destBasePtr + bottom * destRowBytes + halfDestRowBytes;
+ uint8* destLinePtr = destBasePtr + bottom * destRowBytes * 2 + destRowBytes;
+
+ for (EmCoord yy = top; yy < bottom; ++yy)
+ {
+ srcLinePtr -= destRowBytes;
+ destLinePtr -= destRowBytes + destRowBytes;
+
+ uint8* srcPtr = srcLinePtr;
+ uint8* destPtr1 = destLinePtr;
+ uint8* destPtr2 = destPtr1 + destRowBytes;
+ int xx = halfDestRowBytes;
+
+ if (destDepth == 8)
+ {
+ while ((xx -= 1) >= 0)
+ {
+ uint8 c1 = *--srcPtr;
+
+ *--destPtr1 = *--destPtr2 = c1;
+ *--destPtr1 = *--destPtr2 = c1;
+ }
+ }
+ else if (destDepth == 24)
+ {
+ while ((xx -= 3) >= 0)
+ {
+ uint8 c1 = *--srcPtr;
+ uint8 c2 = *--srcPtr;
+ uint8 c3 = *--srcPtr;
+
+ *--destPtr1 = *--destPtr2 = c1;
+ *--destPtr1 = *--destPtr2 = c2;
+ *--destPtr1 = *--destPtr2 = c3;
+
+ *--destPtr1 = *--destPtr2 = c1;
+ *--destPtr1 = *--destPtr2 = c2;
+ *--destPtr1 = *--destPtr2 = c3;
+ }
+ }
+ else if (destDepth == 32)
+ {
+ while ((xx -= 4) >= 0)
+ {
+ uint8 c1 = *--srcPtr;
+ uint8 c2 = *--srcPtr;
+ uint8 c3 = *--srcPtr;
+ uint8 c4 = *--srcPtr;
+
+ *--destPtr1 = *--destPtr2 = c1;
+ *--destPtr1 = *--destPtr2 = c2;
+ *--destPtr1 = *--destPtr2 = c3;
+ *--destPtr1 = *--destPtr2 = c4;
+
+ *--destPtr1 = *--destPtr2 = c1;
+ *--destPtr1 = *--destPtr2 = c2;
+ *--destPtr1 = *--destPtr2 = c3;
+ *--destPtr1 = *--destPtr2 = c4;
+ }
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::DetermineRowBytes
+ *
+ * DESCRIPTION: Determine a rowbytes value appropriate for the current
+ * pixel depth and image width. Currently, the value
+ * returned is the minimum number of bytes required,
+ * rounded up to a multiple of four.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Suggested row bytes value.
+ *
+ ***********************************************************************/
+
+EmPixMapRowBytes
+EmPixMap::DetermineRowBytes (void) const
+{
+ // RowBytes rounded up to 32-bit boundaries.
+
+ long width = fSize.fX;
+ EmPixMapDepth depth = this->GetDepth ();
+
+ return ((width * depth + 31) & ~31) / 8;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::InvalidateBuffer
+ *
+ * DESCRIPTION: Mark the current pixel buffer as invalid. The next time
+ * the buffer is accessed, it will be regenerated. This
+ * function is used after SetBounds, SetDepth, or SetRowBytes
+ * is called.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::InvalidateBuffer (void)
+{
+ if (fPixelsOwned)
+ {
+ Platform::DisposeMemory (fPixels);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::UpdateBuffer
+ *
+ * DESCRIPTION: Allocate a new image buffer if the old one has been
+ * marked invalid by InvalidateBuffer. Called by GetBits
+ * before returning the address of the buffer.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::UpdateBuffer (void) const
+{
+ if (!fPixels)
+ {
+ long neededSize = fSize.fY * fRowBytes;
+ const_cast <EmPixMap*> (this)->fPixels =
+ (uint8*) Platform::AllocateMemory (neededSize);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPixMap::CopyPixelBuffer
+ *
+ * DESCRIPTION: Utility function to copy the pixels of one pixmap to
+ * another. Used as a helper function in the copy
+ * constructor and assignment operator.
+ *
+ * PARAMETERS: other - source pixmap.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmPixMap::CopyPixelBuffer (const EmPixMap& other)
+{
+ this->InvalidateBuffer ();
+
+ memcpy (this->GetBits (), other.GetBits (), fSize.fY * fRowBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Get1To8Table
+ *
+ * DESCRIPTION: Return a table that can be used to convert 1-bpp pixels
+ * into 8-bpp pixels. The table is 16 entries long, and
+ * so is indexed with a full nybble. The result is a
+ * 32-bit value, where each of the 4 1-bpp pixels have been
+ * converted to 4 8-bpp pixels.
+ *
+ * Nybbles of the form 0b0000wxyz are converted to:
+ *
+ * 0b0000000w0000000x0000000y0000000z
+ *
+ * Note that the 32-bit value returned is already
+ * byteswapped so that it appears correctly in memory when
+ * stored on Little-Endian architectures.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Pointer to the table.
+ *
+ ***********************************************************************/
+
+uint32* Get1To8Table (void)
+{
+ if (!gConvert1To8)
+ {
+ const int kTableSize = 16;
+ gConvert1To8 = (uint32*) Platform::AllocateMemory (sizeof (*gConvert1To8) * kTableSize);
+
+ for (int ii = 0; ii < kTableSize; ++ii)
+ {
+ uint32 pixels = ((ii & 0x08) << (24 - 3)) |
+ ((ii & 0x04) << (16 - 2)) |
+ ((ii & 0x02) << (8 - 1)) |
+ ((ii & 0x01) << (0 - 0));
+
+ gConvert1To8[ii] = pixels;
+ }
+ }
+
+ return gConvert1To8;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Get2To8Table
+ *
+ * DESCRIPTION: Return a table that can be used to convert 1-bpp pixels
+ * into 8-bpp pixels. The table is 256 entries long, and
+ * so is indexed with a full byte. The result is a
+ * 32-bit value, where each of the 4 2-bpp pixels have been
+ * converted to 4 8-bpp pixels.
+ *
+ * Bytes of the form 0bwwxxyyzz are converted to:
+ *
+ * 0b000000ww000000xx000000yy000000zz
+ *
+ * Note that the 32-bit value returned is already
+ * byteswapped so that it appears correctly in memory when
+ * stored on Little-Endian architectures.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Pointer to the table.
+ *
+ ***********************************************************************/
+
+uint32* Get2To8Table (void)
+{
+ if (!gConvert2To8)
+ {
+ const int kTableSize = 256;
+ gConvert2To8 = (uint32*) Platform::AllocateMemory (sizeof (*gConvert2To8) * kTableSize);
+
+ for (int ii = 0; ii < kTableSize; ++ii)
+ {
+ uint32 pixels = ((ii & 0xC0) << (24 - 6)) |
+ ((ii & 0x30) << (16 - 4)) |
+ ((ii & 0x0C) << (8 - 2)) |
+ ((ii & 0x03) << (0 - 0));
+
+ gConvert2To8[ii] = pixels;
+ }
+ }
+
+ return gConvert2To8;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Get4To8Table
+ *
+ * DESCRIPTION: Return a table that can be used to convert 4-bpp pixels
+ * into 8-bpp pixels. The table is 256 entries long, and
+ * so is indexed with a full byte. The result is a
+ * 16-bit value, where each of the 2 4-bpp pixels have been
+ * converted to 2 8-bpp pixels.
+ *
+ * Bytes of the form 0bxxxxyyyy are converted to:
+ *
+ * 0b000xxxx0000yyyy
+ *
+ * Note that the 16-bit value returned is already
+ * byteswapped so that it appears correctly in memory when
+ * stored on Little-Endian architectures.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Pointer to the table.
+ *
+ ***********************************************************************/
+
+uint16* Get4To8Table (void)
+{
+ if (!gConvert4To8)
+ {
+ const int kTableSize = 256;
+ gConvert4To8 = (uint16*) Platform::AllocateMemory (sizeof (*gConvert4To8) * kTableSize);
+
+ for (int ii = 0; ii < kTableSize; ++ii)
+ {
+ uint16 pixels = ((ii & 0xF0) << (8 - 4)) |
+ ((ii & 0x0F) << (0 - 0));
+
+ gConvert4To8[ii] = pixels;
+ }
+ }
+
+ return gConvert4To8;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvMakeMask
+ *
+ * DESCRIPTION: Calculate a mask for the given 1-bpp image. The mask
+ * contains 1's inside the image, and 0's outside the
+ * image (where the image is defined as the closed outer
+ * boundary of 1 pixels in the source). Thus:
+ *
+ * src dest
+ * ........... ...........
+ * .....*..... .....*.....
+ * ....*.*.... ....***....
+ * ...*...*... => ...*****...
+ * ....*.*.... ....***....
+ * .....*..... .....*.....
+ * ........... ...........
+ *
+ * ...where .'s are 0's, and *'s are 1's.
+ *
+ * The algorithm is interesting. It starts by initializing
+ * the dest bitmap to all black. It then creates white
+ * sentinel pixels all around the src bitmap. These
+ * sentinels are not actually inserted into the bitmap,
+ * but are logically and effectively there. The sentinels
+ * are then used to start a process of "smearing", where
+ * white pixels are smeared left, right, up, and down
+ * until they reach black pixels in the src. This process
+ * continues until no changes are made in the destination.
+ *
+ * I can't find any reference to this algorithm on the
+ * net. This implementation is based on an algorithm
+ * described to me by Jerry(?) Harris while I was at
+ * Taligent.
+ *
+ * PARAMETERS: dstPtr - buffer to hold the generated mask. Caller is
+ * responsible for making the buffer is large enough.
+ *
+ * srcPtr - pointer to the input 1-bpp image.
+ *
+ * rowBytes - number of bytes in a row (scanline).
+ *
+ * width - width of the source image, in pixels.
+ *
+ * height - height of the source image, in pixels.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+static void PrvMakeMask (void* dstPtr, void* srcPtr, long rowBytes,
+ long /*width*/, long height)
+{
+ uint8* src = (uint8*) srcPtr;
+ uint8* dest = (uint8*) dstPtr;
+ uint8* prev;
+ uint8* prev0;
+ uint8 srcVal, destVal, prevDestVal, newDestVal;
+ long absRowBytes = rowBytes;
+ long xx, yy;
+ long valChanged, anyChange;
+ long pass = 0;
+ uint8 edge = 0; // Sentry for the left and right edges.
+
+ // Set the destination bitmap to black (1's)
+
+ memset (dest, ~0, rowBytes * height);
+
+ // Allocate a scanline buffer on the stack. This scanline
+ // acts as a sentry at the top and bottom of the dest buffer.
+
+ prev0 = (uint8*) Platform::AllocateMemory (rowBytes);
+ memset (prev0, edge, rowBytes);
+
+ do { // Loop while we're still effectively smearing.
+ ++pass;
+ prev = prev0;
+ anyChange = false;
+ yy = height;
+
+ do { // Loop through all the scanlines.
+
+ // Smear down and to the right.
+
+ prevDestVal = edge;
+ xx = absRowBytes;
+
+ do { // Loop through all the bytes in this line.
+ destVal = *dest;
+
+ if (destVal != 0) // If it's not already all-white, let's see if we can mess with it.
+ {
+ srcVal = *src;
+
+ // The following code effectively pushes down any 0's from
+ // the previous line, then adds any 1's from the source.
+
+ destVal = (destVal & *prev) | srcVal;
+
+ do {
+ // Shift destVal to the right. The upper bit of the
+ // new value gets filled in with the lower bit of the
+ // previous destVal.
+
+ newDestVal = (destVal >> 1) | (prevDestVal << 7);
+
+ // AND the shifted destVal with the pre-shifted destVal.
+ // This has the effect of smearing any 0's to the right.
+
+ newDestVal &= destVal;
+
+ // OR in the corresponding byte from the source. This
+ // has the effect of stopping the smear when it hits a 1.
+
+ newDestVal |= srcVal;
+
+ // See if the destVal we're working on has changed. If
+ // so, keep smearing to the right.
+
+ valChanged = (newDestVal != destVal);
+ if (valChanged)
+ {
+ destVal = newDestVal;
+ }
+ } while (valChanged);
+
+ // If this destVal has changed, record the fact and write
+ // out the new value.
+
+ if (*dest != destVal)
+ {
+ anyChange = true;
+ *dest = destVal;
+ }
+ }
+
+ // Move to the next bytes in this line.
+
+ ++src;
+ ++prev;
+ ++dest;
+ prevDestVal = destVal;
+ } while (--xx != 0);
+
+ // Smear down and to the left. Same logic as before.
+
+ prevDestVal = edge;
+ xx = absRowBytes;
+ do {
+ --src;
+ --prev;
+ --dest;
+ destVal = *dest;
+
+ if (destVal != 0)
+ {
+ srcVal = *src;
+ destVal = (destVal & *prev) | srcVal;
+
+ do {
+ newDestVal = (destVal << 1) | (prevDestVal >> 7);
+ newDestVal &= destVal;
+ newDestVal |= srcVal;
+ valChanged = (newDestVal != destVal);
+ if (valChanged)
+ destVal = newDestVal;
+ } while (valChanged);
+
+ if (*dest != destVal)
+ {
+ anyChange = true;
+ *dest = destVal;
+ }
+ }
+
+ prevDestVal = destVal;
+ } while (--xx != 0);
+
+ // Move to the next scanlines. Our movement is either
+ // up or down, depending on whether rowBytes is negative
+ // or not.
+
+ src += rowBytes;
+ prev = dest;
+ dest += rowBytes;
+ } while (--yy != 0);
+
+ // Switch direction, adjust ptrs, and loop until no change.
+ // Make sure we do at least one up and one down pass, though.
+
+ rowBytes = -rowBytes;
+ src += rowBytes;
+ dest += rowBytes;
+ } while (anyChange || (pass < 2));
+
+ Platform::DisposeMemory (prev0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvAddToRegion
+ *
+ * DESCRIPTION: Utility function that adds a rectangle with the given
+ * bounds to the given region. If the given region is
+ * empty, the region is *set* to the rectangle.
+ *
+ * PARAMETERS: region - region to update (or initialize).
+ *
+ * top, left, right - coordinates of the rectangle (where
+ * the bottom is top + 1).
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void PrvAddToRegion (EmRegion& region, int top, int left, int right)
+{
+ if (region.IsEmpty ())
+ {
+ region = EmRegion (EmRect (left, top, right, top + 1));
+ }
+ else
+ {
+ EmRegion tempRegion (EmRect (left, top, right, top + 1));
+ region.UnionWith (tempRegion);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetDepth
+ *
+ * DESCRIPTION: Return the depth implied by the given format
+ *
+ * PARAMETERS: f - format determining the depth.
+ *
+ * RETURNED: The depth implied by the format.
+ *
+ ***********************************************************************/
+
+EmPixMapDepth PrvGetDepth (EmPixMapFormat f)
+{
+ static const uint8 kDepthArray[] =
+ { 1, 2, 4, 8, 16, 16, 16, 16, 24, 24, 32, 32, 32, 32 };
+
+ EmAssert (f >= 0 && f < kPixMapFormatLast);
+ COMPILE_TIME_ASSERT (countof (kDepthArray) == kPixMapFormatLast);
+
+ return kDepthArray [f];
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvConvertMToN
+ *
+ * DESCRIPTION: Scanline converters.
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+#pragma mark -
+
+void PrvConvert1To1 (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(1)
+}
+
+void PrvConvert1To2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert1To4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert1To8 (const ScanlineParms& parms)
+{
+ // Note, this conversion assumes that the first two entries of
+ // the destination color table contains the same colors as the
+ // first two entries in the source color table.
+
+ EmCoord right = parms.fRight;
+ uint8* destPtr = parms.fDestScanline;
+ const uint8* srcPtr = parms.fSrcScanline;
+
+ for (EmCoord xx = 0; xx < right; )
+ {
+ // Get 8 pixels.
+
+ uint8 bits = *srcPtr++;
+
+ // Convert each nybble (which contains four 1-bit pixels) to
+ // a 32-bit value containing four 8-bit pixels.
+
+ uint32 p1 = gConvert1To8[(bits >> 4) & 0x0F];
+ uint32 p2 = gConvert1To8[(bits >> 0) & 0x0F];
+
+ if (xx++ < right)
+ *destPtr++ = p1 >> 24;
+ if (xx++ < right)
+ *destPtr++ = p1 >> 16;
+ if (xx++ < right)
+ *destPtr++ = p1 >> 8;
+ if (xx++ < right)
+ *destPtr++ = p1 >> 0;
+
+ if (xx++ < right)
+ *destPtr++ = p2 >> 24;
+ if (xx++ < right)
+ *destPtr++ = p2 >> 16;
+ if (xx++ < right)
+ *destPtr++ = p2 >> 8;
+ if (xx++ < right)
+ *destPtr++ = p2 >> 0;
+ }
+}
+
+void PrvConvert1To24RGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 24RGB)
+}
+
+void PrvConvert1To24BGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 24BGR)
+}
+
+void PrvConvert1To32ARGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 32ARGB)
+}
+
+void PrvConvert1To32ABGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 32ABGR)
+}
+
+void PrvConvert1To32RGBA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 32RGBA)
+}
+
+void PrvConvert1To32BGRA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(1, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert2To1 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert2To2 (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(2)
+}
+
+void PrvConvert2To4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert2To8 (const ScanlineParms& parms)
+{
+ // Note, this conversion assumes that the first four entries of
+ // the destination color table contains the same colors as the
+ // first four entries in the source color table.
+
+ EmCoord right = parms.fRight;
+ uint8* destPtr = parms.fDestScanline;
+ const uint8* srcPtr = parms.fSrcScanline;
+
+ for (EmCoord xx = 0; xx < right; )
+ {
+ // Get 4 pixels.
+
+ uint8 bits = *srcPtr++;
+
+ // Convert the byte (which contains four 2-bit pixels) to
+ // a 32-bit value containing four 8-bit pixels.
+
+ uint32 p = gConvert2To8[bits];
+
+ if (xx++ < right)
+ *destPtr++ = p >> 24;
+ if (xx++ < right)
+ *destPtr++ = p >> 16;
+ if (xx++ < right)
+ *destPtr++ = p >> 8;
+ if (xx++ < right)
+ *destPtr++ = p >> 0;
+ }
+}
+
+void PrvConvert2To24RGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 24RGB)
+}
+
+void PrvConvert2To24BGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 24BGR)
+}
+
+void PrvConvert2To32ARGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 32ARGB)
+}
+
+void PrvConvert2To32ABGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 32ABGR)
+}
+
+void PrvConvert2To32RGBA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 32RGBA)
+}
+
+void PrvConvert2To32BGRA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(2, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert4To1 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert4To2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert4To4 (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(4)
+}
+
+void PrvConvert4To8 (const ScanlineParms& parms)
+{
+ // Note, this conversion assumes that the first 16 entries of
+ // the destination color table contains the same colors as the
+ // first 16 entries in the source color table.
+
+ EmCoord right = parms.fRight;
+ uint8* destPtr = parms.fDestScanline;
+ const uint8* srcPtr = parms.fSrcScanline;
+
+ for (EmCoord xx = 0; xx < right; )
+ {
+ // Get 2 pixels.
+
+ uint8 bits = *srcPtr++;
+
+ // Convert the byte (which contains two 4-bit pixels) to
+ // a 16-bit value containing two 8-bit pixels.
+
+ uint16 p = gConvert4To8[bits];
+
+ if (xx++ < right)
+ *destPtr++ = p >> 8;
+ if (xx++ < right)
+ *destPtr++ = p >> 0;
+ }
+}
+
+void PrvConvert4To24RGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 24RGB)
+}
+
+void PrvConvert4To24BGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 24BGR)
+}
+
+void PrvConvert4To32ARGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 32ARGB)
+}
+
+void PrvConvert4To32ABGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 32ABGR)
+}
+
+void PrvConvert4To32RGBA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 32RGBA)
+}
+
+void PrvConvert4To32BGRA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(4, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert8To1 (const ScanlineParms& parms)
+{
+ EmCoord right = parms.fRight;
+ uint8* destPtr = parms.fDestScanline;
+ const uint8* srcPtr = parms.fSrcScanline;
+ const RGBList* srcColors = parms.fSrcColors;
+
+ EmAssert (srcColors);
+
+ uint8 bitMask = 0x80;
+ uint8 aByte = 0;
+
+ for (EmCoord xx = 0; xx < right; ++xx)
+ {
+ // Get the RGB value.
+
+ uint8 pixel = *srcPtr++;
+ const RGBType& rgb = (*srcColors)[pixel];
+
+ // See if the current pixel is dark.
+
+ Bool isDark1 = rgb.fRed < 0xC0;
+ Bool isDark2 = rgb.fGreen < 0xC0;
+ Bool isDark3 = rgb.fBlue < 0xC0;
+
+ if (isDark1 || isDark2 || isDark3)
+ {
+ aByte |= bitMask; // !!! Assumes white/black color table
+ }
+
+ bitMask >>= 1;
+ if (bitMask == 0)
+ {
+ *destPtr++ = aByte;
+ bitMask = 0x80;
+ aByte = 0;
+ }
+ }
+
+ // Write out any partially filled out byte.
+
+ if (bitMask != 0)
+ {
+ *destPtr++ = aByte;
+ }
+}
+
+void PrvConvert8To2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert8To4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert8To8 (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(8)
+}
+
+void PrvConvert8To24RGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 24RGB)
+}
+
+void PrvConvert8To24BGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 24BGR)
+}
+
+void PrvConvert8To32ARGB (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 32ARGB)
+}
+
+void PrvConvert8To32ABGR (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 32ABGR)
+}
+
+void PrvConvert8To32RGBA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 32RGBA)
+}
+
+void PrvConvert8To32BGRA (const ScanlineParms& parms)
+{
+ STD_INDEX_TO_DIRECT_CONVERT(8, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert24RGBTo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(24RGB)
+}
+
+void PrvConvert24RGBTo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24RGBTo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24RGBTo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24RGBTo24RGB (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(24)
+}
+
+void PrvConvert24RGBTo24BGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24RGB, 24BGR)
+}
+
+void PrvConvert24RGBTo32ARGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24RGB, 32ARGB)
+}
+
+void PrvConvert24RGBTo32ABGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24RGB, 32ABGR )
+}
+
+void PrvConvert24RGBTo32RGBA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24RGB, 32RGBA)
+}
+
+void PrvConvert24RGBTo32BGRA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24RGB, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert24BGRTo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(24BGR)
+}
+
+void PrvConvert24BGRTo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24BGRTo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24BGRTo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert24BGRTo24RGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24BGR, 24RGB)
+}
+
+void PrvConvert24BGRTo24BGR (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(24)
+}
+
+void PrvConvert24BGRTo32ARGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24BGR, 32ARGB)
+}
+
+void PrvConvert24BGRTo32ABGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24BGR, 32ABGR)
+}
+
+void PrvConvert24BGRTo32RGBA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24BGR, 32RGBA )
+}
+
+void PrvConvert24BGRTo32BGRA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(24BGR, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert32ARGBTo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(32ARGB)
+}
+
+void PrvConvert32ARGBTo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ARGBTo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ARGBTo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ARGBTo24RGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ARGB, 24RGB)
+}
+
+void PrvConvert32ARGBTo24BGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ARGB, 24BGR)
+}
+
+void PrvConvert32ARGBTo32ARGB (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(32)
+}
+
+void PrvConvert32ARGBTo32ABGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ARGB, 32ABGR)
+}
+
+void PrvConvert32ARGBTo32RGBA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ARGB, 32RGBA)
+}
+
+void PrvConvert32ARGBTo32BGRA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ARGB, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert32ABGRTo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(32ABGR)
+}
+
+void PrvConvert32ABGRTo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ABGRTo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ABGRTo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32ABGRTo24RGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ABGR, 24RGB )
+}
+
+void PrvConvert32ABGRTo24BGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ABGR, 24BGR)
+}
+
+void PrvConvert32ABGRTo32ARGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ABGR, 32ARGB)
+}
+
+void PrvConvert32ABGRTo32ABGR (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(32)
+}
+
+void PrvConvert32ABGRTo32RGBA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ABGR, 32RGBA)
+}
+
+void PrvConvert32ABGRTo32BGRA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32ABGR, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert32RGBATo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(32RGBA)
+}
+
+void PrvConvert32RGBATo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32RGBATo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32RGBATo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32RGBATo24RGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32RGBA, 24RGB)
+}
+
+void PrvConvert32RGBATo24BGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32RGBA, 24BGR)
+}
+
+void PrvConvert32RGBATo32ARGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32RGBA, 32ARGB)
+}
+
+void PrvConvert32RGBATo32ABGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32RGBA, 32ABGR)
+}
+
+void PrvConvert32RGBATo32RGBA (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(32)
+}
+
+void PrvConvert32RGBATo32BGRA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32RGBA, 32BGRA)
+}
+
+#pragma mark -
+
+void PrvConvert32BGRATo1 (const ScanlineParms& parms)
+{
+ STD_DIRECT_TO_1_CONVERT(32BGRA)
+}
+
+void PrvConvert32BGRATo2 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32BGRATo4 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32BGRATo8 (const ScanlineParms& /*parms*/)
+{
+ EmAssert (false);
+}
+
+void PrvConvert32BGRATo24RGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32BGRA, 24RGB)
+}
+
+void PrvConvert32BGRATo24BGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32BGRA, 24BGR)
+}
+
+void PrvConvert32BGRATo32ARGB (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32BGRA, 32ARGB)
+}
+
+void PrvConvert32BGRATo32ABGR (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32BGRA, 32ABGR)
+}
+
+void PrvConvert32BGRATo32RGBA (const ScanlineParms& parms)
+{
+ STD_DIRECT_CONVERT(32BGRA, 32RGBA)
+}
+
+void PrvConvert32BGRATo32BGRA (const ScanlineParms& parms)
+{
+ STD_NO_CONVERT(32)
+}
diff --git a/SrcShared/EmPixMap.h b/SrcShared/EmPixMap.h
new file mode 100644
index 0000000..8517062
--- /dev/null
+++ b/SrcShared/EmPixMap.h
@@ -0,0 +1,104 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPixMap_h
+#define EmPixMap_h
+
+#include "EmStructs.h" // RGBList
+#include "EmRegion.h" // EmRegion
+
+#include <vector>
+
+typedef int EmPixMapDepth;
+typedef int EmPixMapRowBytes;
+
+enum EmPixMapFormat
+{
+ // If you change these values, be sure to update PrvGetDepth.
+
+ kPixMapFormat1,
+ kPixMapFormat2,
+ kPixMapFormat4,
+ kPixMapFormat8,
+ kPixMapFormat16RGB555,
+ kPixMapFormat16BGR555,
+ kPixMapFormat16RGB565,
+ kPixMapFormat16BGR565,
+ kPixMapFormat24RGB,
+ kPixMapFormat24BGR,
+ kPixMapFormat32ARGB,
+ kPixMapFormat32ABGR,
+ kPixMapFormat32RGBA,
+ kPixMapFormat32BGRA,
+
+ kPixMapFormatLast
+};
+
+
+class EmPixMap
+{
+ public:
+ EmPixMap (void);
+ EmPixMap (const EmPixMap&);
+ ~EmPixMap (void);
+
+ EmPixMap& operator= (const EmPixMap&);
+
+ EmPoint GetSize (void) const;
+ void SetSize (const EmPoint&);
+
+ EmPixMapDepth GetDepth (void) const;
+ EmPixMapFormat GetFormat (void) const;
+ void SetFormat (EmPixMapFormat);
+
+ EmPixMapRowBytes GetRowBytes (void) const;
+ void SetRowBytes (EmPixMapRowBytes);
+
+ const RGBList& GetColorTable (void) const;
+ void SetColorTable (const RGBList&);
+
+ const void* GetBits (void) const;
+ void* GetBits (void);
+ void SetBits (void*);
+
+ void CreateMask (EmPixMap& dest) const;
+ EmRegion CreateRegion (void) const;
+
+ void ChangeTone (int32 percent, EmCoord firstLine = -1, EmCoord lastLine = -1);
+ void ConvertToColor (int type, EmCoord firstLine = -1, EmCoord lastLine = -1);
+ void FlipScanlines (void);
+ void ConvertToFormat (EmPixMapFormat);
+
+ static void CopyRect (EmPixMap& dest, const EmPixMap& src,
+ const EmRect& destRect, const EmRect& srcRect);
+
+ private:
+ EmPixMapRowBytes DetermineRowBytes (void) const;
+ void InvalidateBuffer (void);
+ void UpdateBuffer (void) const;
+ void CopyPixelBuffer (const EmPixMap& other);
+
+ private:
+ EmPoint fSize;
+ EmPixMapFormat fFormat;
+ EmPixMapRowBytes fRowBytes;
+ RGBList fColors;
+ uint8* fPixels;
+ Bool fPixelsOwned;
+};
+
+uint32* Get1To8Table (void);
+uint32* Get2To8Table (void);
+uint16* Get4To8Table (void);
+
+#endif // EmPixMap_h
diff --git a/SrcShared/EmPoint.cpp b/SrcShared/EmPoint.cpp
new file mode 100644
index 0000000..a8a2f6b
--- /dev/null
+++ b/SrcShared/EmPoint.cpp
@@ -0,0 +1,316 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPoint.h"
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmPointTempl<coord>::Offset (coord x, coord y)
+{
+ fX += x;
+ fY += y;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmPointTempl<coord>::operator+ (const EmPointTempl<coord>& pt) const
+{
+ EmPointTempl<coord> result;
+
+ result.fX = this->fX + pt.fX;
+ result.fY = this->fY + pt.fY;
+
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmPointTempl<coord>::operator- (const EmPointTempl<coord>& pt) const
+{
+ EmPointTempl<coord> result;
+
+ result.fX = this->fX - pt.fX;
+ result.fY = this->fY - pt.fY;
+
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmPointTempl<coord>::operator- (void) const
+{
+ EmPointTempl<coord> result;
+
+ result.fX = -this->fX;
+ result.fY = -this->fY;
+
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>&
+EmPointTempl<coord>::operator+= (const EmPointTempl<coord>& pt)
+{
+ fX += pt.fX;
+ fY += pt.fY;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>&
+EmPointTempl<coord>::operator-= (const EmPointTempl<coord>& pt)
+{
+ fX -= pt.fX;
+ fY -= pt.fY;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmPointTempl<coord>::operator* (const EmPointTempl<coord>& pt) const
+{
+ EmPointTempl<coord> result;
+
+ result.fX = this->fX * pt.fX;
+ result.fY = this->fY * pt.fY;
+
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmPointTempl<coord>::operator/ (const EmPointTempl<coord>& pt) const
+{
+ EmPointTempl<coord> result;
+
+ EmAssert (pt.fX != 0);
+ EmAssert (pt.fY != 0);
+
+ result.fX = this->fX / pt.fX;
+ result.fY = this->fY / pt.fY;
+
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>&
+EmPointTempl<coord>::operator*= (const EmPointTempl<coord>& pt)
+{
+ fX *= pt.fX;
+ fY *= pt.fY;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>&
+EmPointTempl<coord>::operator/= (const EmPointTempl<coord>& pt)
+{
+ EmAssert (pt.fX != 0);
+ EmAssert (pt.fY != 0);
+
+ fX /= pt.fX;
+ fY /= pt.fY;
+
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Boolean
+EmPointTempl<coord>::operator!= (const EmPointTempl<coord>& pt) const
+{
+ return
+ (fX != pt.fX) ||
+ (fY != pt.fY);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Boolean
+EmPointTempl<coord>::operator== (const EmPointTempl<coord>& pt) const
+{
+ return
+ (fX == pt.fX) &&
+ (fY == pt.fY);
+}
+
+
+// ----------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4660) // template-class specialization is already instatiated
+#endif
+
+template class EmPointTempl<EmCoord>;
+
+
+// ----------------------------------------------------------------------
+// Psuedo-type definitions to aid in the conversion process without
+// actually having to #include the requisite headers.
+// ----------------------------------------------------------------------
+
+#ifndef _WINDEF_
+struct tagSIZE { char _[8]; };
+struct tagPOINT { char _[8]; };
+#endif
+
+#ifndef __AFXWIN_H__
+class CSize { char _[8]; };
+class CPoint { char _[8]; };
+#endif
+
+#ifndef __MACTYPES__
+struct Point { char _[4]; };
+#endif
+
+#ifndef _H_LPane
+struct SDimension16 { char _[4]; };
+struct SDimension32 { char _[8]; };
+struct SPoint32 { char _[8]; };
+#endif
+struct VPoint { char _[8]; };
+
+
+// ----------------------------------------------------------------------
+// * EmPoint
+// ----------------------------------------------------------------------
+
+//
+// Construct from another kind of point
+// Assigned from another kind of point
+//
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ EmPoint::EmPoint(const cls& pt) : \
+ EmPointTempl<EmCoord>(((size*)&pt)[x], ((size*)&pt)[y]) {} \
+ const EmPoint& EmPoint::operator=(const cls& pt) \
+ { fX = ((size*)&pt)[x]; fY = ((size*)&pt)[y]; return *this; }
+
+ POINT_LIST_XY_SHORT
+ POINT_LIST_XY_LONG
+ POINT_LIST_YX_SHORT
+ POINT_LIST_YX_LONG
+
+//
+// Return another kind of point
+//
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ EmPoint::operator cls() const \
+ { size pt[2]; pt[x] = fX; pt[y] = fY; return *(cls*) pt; }
+
+ POINT_LIST_XY_LONG
+ POINT_LIST_YX_LONG
+ POINT_LIST_XY_SHORT
+ POINT_LIST_YX_SHORT
+
+//
+// Return a [const] (* | &) to another kind of point
+//
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ EmPoint::operator const cls*() const \
+ { return (const cls*) this; } \
+ EmPoint::operator cls*() \
+ { return (cls*) this; } \
+ EmPoint::operator const cls&() const \
+ { return *(const cls*) this; } \
+ EmPoint::operator cls&() \
+ { return *(cls*) this; }
+
+ POINT_LIST_LONG
+
+//#define TESTING
+#ifdef TESTING
+// ----------------------------------------------------------------------
+#include "stdio.h"
+void TestPoint();
+void TestPoint()
+{
+ printf("Testing EmPointTempl class...\n");
+
+ {
+ EmPoint pt1(1, 2);
+ EmAssert(pt1.fX == 1);
+ EmAssert(pt1.fY == 2);
+
+ EmPoint pt2(5, 6);
+ EmPoint pt3;
+ pt3 = pt2;
+ EmAssert(pt3.fX == 5);
+ EmAssert(pt3.fY == 6);
+
+ EmPoint pt4(pt2);
+ EmAssert(pt4.fX == 5);
+ EmAssert(pt4.fY == 6);
+
+ pt4.Offset(-5, -50);
+ EmAssert(pt4.fX == 5 - 5);
+ EmAssert(pt4.fY == 6 - 50);
+
+ EmPoint pt5 = pt1 + pt2;
+ EmAssert(pt5.fX == 1 + 5);
+ EmAssert(pt5.fY == 2 + 6);
+
+ EmPoint pt6 = pt1 - pt2;
+ EmAssert(pt6.fX == 1 - 5);
+ EmAssert(pt6.fY == 2 - 6);
+
+ EmPoint pt7 = -pt2;
+ EmAssert(pt7.fX == -5);
+ EmAssert(pt7.fY == -6);
+
+ EmPoint pt8(10, 11);
+ pt8 += pt2;
+ EmAssert(pt8.fX == 10 + 5);
+ EmAssert(pt8.fY == 11 + 6);
+
+ EmPoint pt9(10, 11);
+ pt9 -= pt2;
+ EmAssert(pt9.fX == 10 - 5);
+ EmAssert(pt9.fY == 11 - 6);
+
+ EmAssert(pt9 != pt7);
+ EmAssert(pt2 == pt2);
+ EmAssert(pt3 == pt2);
+
+ // !!! Need to test all the constructors and conversion operators
+ }
+}
+#endif
diff --git a/SrcShared/EmPoint.h b/SrcShared/EmPoint.h
new file mode 100644
index 0000000..c9b0842
--- /dev/null
+++ b/SrcShared/EmPoint.h
@@ -0,0 +1,262 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPoint_h
+#define EmPoint_h
+
+/*
+ Contains classes for working with points:
+
+ EmPointTempl<coord>: Generic template class. The type of point
+ coordinate is provided by the client.
+
+ EmPoint: Specific specialization of EmPointTempl for EmCoord.
+
+ For flexibility, the x/y ordering of coordinates within the object
+ is controlled by the XYPoint pre-processor symbol. Choosing a
+ particular order enables certain conversion operations; choosing the
+ other order enables other conversion operations. For instance, when
+ using long coordinates and XY ordering, we can produce a POINT*
+ (Win32 point), but not a VPoint* (MacApp point).
+
+ EmPoint offers no new operations. What it does offer is constructors
+ for creation from a platform-specific point (like Point, POINT, CPoint,
+ VPoint, etc.) or for producing some variant of a platform-specific
+ point. The different kinds of points that EmPoint attempts to convert
+ to/from are:
+
+ SIZE SDimension16 Point
+ CSize SDimension32 VPoint
+
+ POINT SPoint16
+ CPoint SPoint32
+
+ Where possible, EmPoint produces pointers, const pointers, references,
+ and const references to the above types.
+
+ Note that there are no virtual functions. These point classes are
+ not intended to be used polymorphically.
+*/
+
+#if PLATFORM_WINDOWS
+ #define XYPoint 1
+#else
+ #define XYPoint 0
+#endif
+
+template <class coord>
+class EmPointTempl
+{
+ public:
+ EmPointTempl (void)
+ {}
+ EmPointTempl (coord x, coord y) :
+#if XYPoint
+ fX (x),
+ fY (y)
+#else
+ fY (y),
+ fX (x)
+#endif
+ {}
+ EmPointTempl (const EmPointTempl<coord>& pt) :
+#if XYPoint
+ fX (pt.fX),
+ fY (pt.fY)
+#else
+ fY (pt.fY),
+ fX (pt.fX)
+#endif
+ {}
+// ~EmPointTempl (void) {};
+ // Constructors/Destructor. The default constructor doesn't do anything,
+ // including setting its members to zero. There is no destructor to cut
+ // down on the amount of code generated for this lightweight class.
+
+ void Offset (coord x, coord y);
+ // Add x and y to the point's coordinates. Same as operator+=()
+ // except that you specify coordinates, not another point.
+
+ EmPointTempl<coord> operator+ (const EmPointTempl<coord>& pt) const;
+ EmPointTempl<coord> operator- (const EmPointTempl<coord>& pt) const;
+ // Add or subtract the two points with each other, producing a
+ // new EmPointTempl<coord>.
+
+ EmPointTempl<coord> operator- (void) const;
+ // Unary minus. Negate our coordinates.
+
+ EmPointTempl<coord>& operator+= (const EmPointTempl<coord>& pt);
+ EmPointTempl<coord>& operator-= (const EmPointTempl<coord>& pt);
+ // Add or subtract the coordinates of the given point from
+ // ourselves.
+
+ EmPointTempl<coord> operator* (const EmPointTempl<coord>& pt) const;
+ EmPointTempl<coord> operator/ (const EmPointTempl<coord>& pt) const;
+ EmPointTempl<coord>& operator*= (const EmPointTempl<coord>& pt);
+ EmPointTempl<coord>& operator/= (const EmPointTempl<coord>& pt);
+ // Scale up or down the controlled point by the given point.
+
+ Boolean operator!= (const EmPointTempl<coord>& pt) const;
+ Boolean operator== (const EmPointTempl<coord>& pt) const;
+ // (In)equality operators. Returns whether or not the coordinates
+ // of the two points are equal to each other.
+
+ // Directly accessible data members.
+#if XYPoint
+ coord fX;
+ coord fY;
+#else
+ coord fY;
+ coord fX;
+#endif
+};
+
+
+// ----------------------------------------------------------------------
+// Types we interoperate with
+// ----------------------------------------------------------------------
+
+struct tagSIZE;
+typedef struct tagSIZE SIZE;
+class CSize;
+
+struct tagPOINT;
+typedef struct tagPOINT POINT;
+class CPoint;
+
+struct SDimension16;
+struct SDimension32;
+
+struct Point;
+typedef Point SPoint16;
+
+struct SPoint32;
+struct VPoint;
+
+
+/* ----------------------------------------------------------------------
+ Macros to help with creating the massive number of constructors and
+ conversion operators we support:
+
+ POINT_LIST_XY_SHORT: List of point-types using x/y coordinate
+ ordering and short coordinates.
+
+ POINT_LIST_XY_LONG: List of point-types using x/y coordinate
+ ordering and long coordinates.
+
+ POINT_LIST_YX_SHORT: List of point-types using y/x coordinate
+ ordering and short coordinates.
+
+ POINT_LIST_YX_LONG: List of point-types using y/x coordinate
+ ordering and long coordinates.
+
+ POINT_LIST_SHORT: List of point-types using short coordinates.
+ Only point-types using the same x/y ordering
+ as indicated by XYPoint are included.
+
+ POINT_LIST_LONG: List of point-types using long coordinates.
+ Only point-types using the same x/y ordering
+ as indicated by XYPoint are included.
+
+ Each of the above lists includes a reference to a point-type using a
+ FOR_POINT macro. The FOR_POINT macro takes as parameters the
+ point-type, the size of coordinates, and offsets to each coordinate.
+ This information is all that's needed for constructing all of
+ constructors and convertion operators, both declarations and
+ implementations. To perform the actual construction, FOR_POINT is
+ defined to expand to the appropriate code for a single constructor
+ or conversion, and then the appropriate POINT_LIST macro from above
+ is "invoked" to expand the list as needed.
+ ---------------------------------------------------------------------- */
+
+#define POINT_LIST_XY_SHORT \
+ FOR_POINT(SDimension16, short, 0, 1)\
+ FOR_POINT(PointType, short, 0, 1)
+
+#define POINT_LIST_XY_LONG \
+ FOR_POINT(SIZE, long, 0, 1) \
+ FOR_POINT(CSize, long, 0, 1) \
+ FOR_POINT(SDimension32, long, 0, 1) \
+ FOR_POINT(POINT, long, 0, 1) \
+ FOR_POINT(CPoint, long, 0, 1) \
+ FOR_POINT(SPoint32, long, 0, 1)
+
+#define POINT_LIST_YX_SHORT \
+ FOR_POINT(Point, short, 1, 0)
+
+#define POINT_LIST_YX_LONG \
+ FOR_POINT(VPoint, long, 1, 0)
+
+#if XYPoint
+ #define POINT_LIST_LONG POINT_LIST_XY_LONG
+ #define POINT_LIST_SHORT POINT_LIST_XY_SHORT
+#else
+ #define POINT_LIST_LONG POINT_LIST_YX_LONG
+ #define POINT_LIST_SHORT POINT_LIST_YX_SHORT
+#endif
+
+// ----------------------------------------------------------------------
+// * EmPoint
+// ----------------------------------------------------------------------
+
+class EmPoint : public EmPointTempl<EmCoord>
+{
+ public:
+ EmPoint() {};
+ EmPoint(EmCoord x, EmCoord y) : EmPointTempl<EmCoord>(x, y) {};
+ EmPoint(const EmPointTempl<EmCoord>& pt) : EmPointTempl<EmCoord>(pt) {};
+// ~EmPoint() {};
+
+ //
+ // Construct from another kind of point
+ // Assigned from another kind of point
+ // !!! Move functionality inline?
+ //
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ EmPoint(const cls&); \
+ const EmPoint& operator=(const cls&);
+
+ POINT_LIST_XY_SHORT
+ POINT_LIST_XY_LONG
+ POINT_LIST_YX_SHORT
+ POINT_LIST_YX_LONG
+
+ //
+ // Return another kind of point
+ // !!! Move functionality inline?
+ //
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ operator cls() const;
+
+ POINT_LIST_XY_LONG
+ POINT_LIST_YX_LONG
+ POINT_LIST_XY_SHORT
+ POINT_LIST_YX_SHORT
+
+ //
+ // Return a [const] (* | &) to another kind of point
+ // !!! Move functionality inline?
+ //
+ #undef FOR_POINT
+ #define FOR_POINT(cls, size, x, y) \
+ operator const cls*() const; \
+ operator cls*(); \
+ operator const cls&() const; \
+ operator cls&();
+
+ POINT_LIST_LONG
+};
+
+#endif // EmPoint_h
diff --git a/SrcShared/EmQuantizer.cpp b/SrcShared/EmQuantizer.cpp
new file mode 100644
index 0000000..ce64d4c
--- /dev/null
+++ b/SrcShared/EmQuantizer.cpp
@@ -0,0 +1,328 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmQuantizer.h"
+
+#include "EmPixMap.h"
+#include "Platform.h" // Platform::AllocateMemory
+
+
+struct NODE
+{
+ Bool bIsLeaf; // true if node has no children
+ uint32 nPixelCount; // Number of pixels represented by this leaf
+ uint32 nRedSum; // Sum of red components
+ uint32 nGreenSum; // Sum of green components
+ uint32 nBlueSum; // Sum of blue components
+ NODE* pChild[8]; // Pointers to child nodes
+ NODE* pNext; // Pointer to next reducible node
+};
+
+EmQuantizer::EmQuantizer (uint32 nMaxColors, uint32 nColorBits)
+{
+ EmAssert (nColorBits <= 8);
+
+ m_pTree = NULL;
+ m_nLeafCount = 0;
+
+ for (int ii = 0; ii <= (int) nColorBits; ++ii)
+ {
+ m_pReducibleNodes[ii] = NULL;
+ }
+
+ m_nMaxColors = nMaxColors;
+ m_nColorBits = nColorBits;
+}
+
+EmQuantizer::~EmQuantizer ()
+{
+ if (m_pTree != NULL)
+ this->DeleteTree (&m_pTree);
+}
+
+Bool EmQuantizer::ProcessImage (const EmPixMap& pixMap)
+{
+ uint8* pbBits;
+ uint8 r, g, b;
+ int i, j;
+
+ EmPoint size = pixMap.GetSize ();
+ EmPixMapFormat bitFormat = pixMap.GetFormat ();
+ int bitCount = pixMap.GetDepth ();
+ int nPad = pixMap.GetRowBytes () - (((size.fX * bitCount) + 7) / 8);
+
+ switch (bitFormat)
+ {
+ case kPixMapFormat8:
+ {
+ const RGBList& colors = pixMap.GetColorTable ();
+ pbBits = (uint8*) pixMap.GetBits ();
+
+ for (i = 0; i < size.fY; ++i)
+ {
+ for (j = 0; j < size.fX; ++j)
+ {
+ uint8 pixel = *pbBits++;
+ const RGBType& color = colors[pixel];
+
+ b = color.fBlue;
+ g = color.fGreen;
+ r = color.fRed;
+
+ this->AddColor (&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
+ m_pReducibleNodes);
+
+ while (m_nLeafCount > m_nMaxColors)
+ {
+ this->ReduceTree (m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
+ }
+ }
+
+ pbBits += nPad;
+ }
+ break;
+ }
+
+ case kPixMapFormat24RGB:
+ {
+ pbBits = (uint8*) pixMap.GetBits ();
+ for (i = 0; i < size.fY; ++i)
+ {
+ for (j = 0; j < size.fX; ++j)
+ {
+ r = *pbBits++;
+ g = *pbBits++;
+ b = *pbBits++;
+
+ this->AddColor (&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
+ m_pReducibleNodes);
+
+ while (m_nLeafCount > m_nMaxColors)
+ {
+ this->ReduceTree (m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
+ }
+ }
+
+ pbBits += nPad;
+ }
+ break;
+ }
+
+ case kPixMapFormat32ARGB:
+ {
+ pbBits = (uint8*) pixMap.GetBits ();
+ for (i = 0; i < size.fY; ++i)
+ {
+ for (j = 0; j < size.fX; ++j)
+ {
+ pbBits++; // Skip the alpha channel
+ r = *pbBits++;
+ g = *pbBits++;
+ b = *pbBits++;
+
+ this->AddColor (&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
+ m_pReducibleNodes);
+
+ while (m_nLeafCount > m_nMaxColors)
+ {
+ this->ReduceTree (m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
+ }
+ }
+
+ pbBits += nPad;
+ }
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ return false;
+ }
+
+ return true;
+}
+
+Bool EmQuantizer::ProcessColorTable (const RGBList& colors)
+{
+ uint8 r, g, b;
+
+ for (size_t ii = 0; ii < colors.size (); ++ii)
+ {
+ const RGBType& color = colors[ii];
+
+ b = color.fBlue;
+ g = color.fGreen;
+ r = color.fRed;
+
+ this->AddColor (&m_pTree, r, g, b, m_nColorBits, 0, &m_nLeafCount,
+ m_pReducibleNodes);
+
+ while (m_nLeafCount > m_nMaxColors)
+ {
+ this->ReduceTree (m_nColorBits, &m_nLeafCount, m_pReducibleNodes);
+ }
+ }
+
+ return true;
+}
+
+void EmQuantizer::AddColor (NODE** ppNode, uint8 r, uint8 g, uint8 b,
+ uint32 nColorBits, uint32 nLevel, uint32* pLeafCount, NODE** pReducibleNodes)
+{
+ //
+ // If the node doesn't exist, create it.
+ //
+ if (*ppNode == NULL)
+ {
+ *ppNode = this->CreateNode (nLevel, nColorBits, pLeafCount, pReducibleNodes);
+ }
+
+ //
+ // Update color information if it's a leaf node.
+ //
+ if ((*ppNode)->bIsLeaf)
+ {
+ (*ppNode)->nPixelCount++;
+ (*ppNode)->nRedSum += r;
+ (*ppNode)->nGreenSum += g;
+ (*ppNode)->nBlueSum += b;
+ }
+
+ //
+ // Recurse a level deeper if the node is not a leaf.
+ //
+ else
+ {
+ int shift = 7 - nLevel;
+ int nIndex =
+ (((r >> shift) & 1) << 2) |
+ (((g >> shift) & 1) << 1) |
+ (((b >> shift) & 1) << 0);
+
+ this->AddColor (&((*ppNode)->pChild[nIndex]), r, g, b, nColorBits,
+ nLevel + 1, pLeafCount, pReducibleNodes);
+ }
+}
+
+NODE* EmQuantizer::CreateNode (uint32 nLevel, uint32 nColorBits, uint32* pLeafCount,
+ NODE** pReducibleNodes)
+{
+ NODE* pNode;
+
+ pNode = (NODE*) Platform::AllocateMemory (sizeof (NODE));
+ if (pNode == NULL)
+ return NULL;
+
+ memset (pNode, 0, sizeof (NODE));
+
+ pNode->bIsLeaf = (nLevel == nColorBits) ? true : false;
+ if (pNode->bIsLeaf)
+ {
+ (*pLeafCount)++;
+ }
+ else
+ {
+ pNode->pNext = pReducibleNodes[nLevel];
+ pReducibleNodes[nLevel] = pNode;
+ }
+
+ return pNode;
+}
+
+void EmQuantizer::ReduceTree (uint32 nColorBits, uint32* pLeafCount,
+ NODE** pReducibleNodes)
+{
+ int ii;
+
+ //
+ // Find the deepest level containing at least one reducible node.
+ //
+ for (ii = nColorBits - 1; (ii > 0) && (pReducibleNodes[ii] == NULL); --ii)
+ ;
+
+ //
+ // Reduce the node most recently added to the list at level i.
+ //
+ NODE* pNode = pReducibleNodes[ii];
+ pReducibleNodes[ii] = pNode->pNext;
+
+ uint32 nRedSum = 0;
+ uint32 nGreenSum = 0;
+ uint32 nBlueSum = 0;
+ uint32 nChildren = 0;
+
+ for (ii = 0; ii < 8; ++ii)
+ {
+ if (pNode->pChild[ii] != NULL)
+ {
+ nRedSum += pNode->pChild[ii]->nRedSum;
+ nGreenSum += pNode->pChild[ii]->nGreenSum;
+ nBlueSum += pNode->pChild[ii]->nBlueSum;
+ pNode->nPixelCount += pNode->pChild[ii]->nPixelCount;
+
+ Platform::DisposeMemory (pNode->pChild[ii]);
+ nChildren++;
+ }
+ }
+
+ pNode->bIsLeaf = true;
+ pNode->nRedSum = nRedSum;
+ pNode->nGreenSum = nGreenSum;
+ pNode->nBlueSum = nBlueSum;
+ *pLeafCount -= (nChildren - 1);
+}
+
+void EmQuantizer::DeleteTree (NODE** ppNode)
+{
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ if ((*ppNode)->pChild[ii] != NULL)
+ {
+ this->DeleteTree (&((*ppNode)->pChild[ii]));
+ }
+ }
+
+ Platform::DisposeMemory (*ppNode);
+}
+
+void EmQuantizer::GetPaletteColors (NODE* pTree, RGBType* prgb, uint32* pIndex)
+{
+ if (pTree->bIsLeaf)
+ {
+ prgb[*pIndex].fRed = (uint8) ((pTree->nRedSum) / (pTree->nPixelCount));
+ prgb[*pIndex].fGreen = (uint8) ((pTree->nGreenSum) / (pTree->nPixelCount));
+ prgb[*pIndex].fBlue = (uint8) ((pTree->nBlueSum) / (pTree->nPixelCount));
+
+ (*pIndex)++;
+ }
+ else
+ {
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ if (pTree->pChild[ii] != NULL)
+ {
+ this->GetPaletteColors (pTree->pChild[ii], prgb, pIndex);
+ }
+ }
+ }
+}
+
+void EmQuantizer::GetColorTable (RGBList& colors)
+{
+ colors.clear ();
+ colors.resize (m_nLeafCount);
+
+ uint32 nIndex = 0;
+ this->GetPaletteColors (m_pTree, &colors[0], &nIndex);
+}
diff --git a/SrcShared/EmQuantizer.h b/SrcShared/EmQuantizer.h
new file mode 100644
index 0000000..f6a8f60
--- /dev/null
+++ b/SrcShared/EmQuantizer.h
@@ -0,0 +1,52 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmQuantizer_h
+#define EmQuantizer_h
+
+#include "EmStructs.h" // RGBList
+
+class EmPixMap;
+
+struct NODE;
+
+class EmQuantizer
+{
+ public:
+ EmQuantizer (uint32 nMaxColors, uint32 nColorBits);
+ virtual ~EmQuantizer (void);
+
+ Bool ProcessImage (const EmPixMap&);
+ Bool ProcessColorTable (const RGBList&);
+ void GetColorTable (RGBList&);
+
+ protected:
+ void AddColor (NODE** ppNode, uint8 r, uint8 g, uint8 b,
+ uint32 nColorBits, uint32 nLevel,
+ uint32* pLeafCount, NODE** pReducibleNodes);
+ NODE* CreateNode (uint32 nLevel, uint32 nColorBits,
+ uint32* pLeafCount, NODE** pReducibleNodes);
+ void ReduceTree (uint32 nColorBits,
+ uint32* pLeafCount, NODE** pReducibleNodes);
+ void DeleteTree (NODE** ppNode);
+ void GetPaletteColors (NODE* pTree, RGBType* prgb, uint32* pIndex);
+
+ protected:
+ NODE* m_pTree;
+ uint32 m_nLeafCount;
+ NODE* m_pReducibleNodes[9];
+ uint32 m_nMaxColors;
+ uint32 m_nColorBits;
+};
+
+#endif // EmQuantizer_h
diff --git a/SrcShared/EmROMReader.cpp b/SrcShared/EmROMReader.cpp
new file mode 100644
index 0000000..4627fca
--- /dev/null
+++ b/SrcShared/EmROMReader.cpp
@@ -0,0 +1,868 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include <EmCommon.h>
+#include <EmROMReader.h>
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(void)
+{
+ fSize = 0;
+ fSizeAdj = 0;
+ fFree = false;
+ fAddress = 0;
+ fOwner = 0;
+ fHOffset = 0;
+ fLockCount = 0;
+ fHdrSize = 0;
+
+ recordNumber = 0;
+ type = typeOther;
+ dbNumber = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(const EmAliasROMHeapChunkHdr2Type<A>& chunk, UInt32 addr)
+{
+ fPtr = chunk.GetPtr();
+ fSize = (chunk.long1 >> 0) & 0x00FFFFFFU;
+
+ if (fSize == 0)
+ {
+ fFree = 0;
+ fSizeAdj = 0;
+ fLockCount = 0;
+ fOwner = 0;
+ fHdrSize = 0;
+ fAddress = 0;
+ }
+ else
+ {
+ fFree = (chunk.long1 >> 31) & 0x0001;
+ fSizeAdj = (chunk.long1 >> 24) & 0x000F;
+ fLockCount = (chunk.long2 >> 28) & 0x000F;
+ fHOffset = (chunk.long2 >> 0) & 0x00FFFFFFU;
+ fOwner = (chunk.long2 >> 24) & 0x000F;
+ fHdrSize = chunk.GetSize();
+ fAddress = addr + fHdrSize;
+ }
+
+ recordNumber = 0;
+ dbNumber = 0;
+ type = fFree ? typeFree : typeOther;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ChunkType::ChunkType
+// ---------------------------------------------------------------------------
+
+EmROMReader::ChunkType::ChunkType(const EmAliasROMHeapChunkHdr1Type<A>& chunk, UInt32 addr)
+{
+ fPtr = chunk.GetPtr();
+ fSize = chunk.size;
+
+ if (fSize == 0)
+ {
+ fFree = 0;
+ fSizeAdj = 0;
+ fLockCount = 0;
+ fOwner = 0;
+ fHdrSize = 0;
+ fAddress = 0;
+ }
+ else
+ {
+ fFree = !!(chunk.flags & 0x80);
+ fSizeAdj = chunk.flags & 0x0F;
+ fLockCount = chunk.lockOwner >> 4;
+ fHOffset = chunk.hOffset;
+ fOwner = chunk.lockOwner & 0x0F;
+ fHdrSize = chunk.GetSize();
+ fAddress = addr + fHdrSize;
+ }
+
+ recordNumber = 0;
+ dbNumber = 0;
+ type = fFree ? typeFree : typeOther;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(void)
+{
+ fDeleted = fDirty = fBusy = fSecret = false;
+ fCategory = fType = fID = fChunkLID = 0;
+
+ fChunk = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(const EmAliasROMDBRecordHeader1Type<A> record, EmROMReader* rom)
+{
+ UInt32 bits = record.recordID;
+
+ fRecord = true;
+
+ fDeleted = !!((bits >> 31) & 1);
+ fDirty = !!((bits >> 30) & 1);
+ fBusy = !!((bits >> 29) & 1);
+ fSecret = !!((bits >> 28) & 1);
+ fCategory = (bits >> 24) & 0xF;
+ fID = bits & 0x00FFFFFFU;
+
+ fType = 0;
+
+ fChunkLID = record.chunkLID;
+
+ ChunkList::iterator block = rom->Chunks().find(fChunkLID);
+ if (block != rom->Chunks().end())
+ fChunk = &block->second;
+ else
+ fChunk = NULL;
+
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseItemType::DatabaseItemType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseItemType::DatabaseItemType(const EmAliasROMDBResourceHeader1Type<A> resource, EmROMReader* rom)
+{
+ fRecord = false;
+
+ fType = resource.type;
+ fID = resource.id;
+
+ fDeleted = fDirty = fBusy = fSecret = false;
+ fCategory = 0;
+
+ fChunkLID = resource.chunkLID;
+
+ ChunkList::iterator block = rom->Chunks().find(fChunkLID);
+ if (block != rom->Chunks().end())
+ fChunk = &block->second;
+ else
+ fChunk = NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseType::DatabaseType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseType::DatabaseType(void)
+{
+ fAppInfoChunk = fSortInfoChunk = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ DatabaseType::DatabaseType
+// ---------------------------------------------------------------------------
+
+EmROMReader::DatabaseType::DatabaseType(ChunkType* hdr, EmROMReader* rom)
+{
+ int i;
+
+ if (hdr->Size() < EmAliasROMDBHeader1Type<A>::GetSize())
+ return;
+
+ EmAliasROMDBHeader1Type<A> db(hdr->GetPtr());
+
+ char name[dmDBNameLength];
+ A::BlockCopy(name, db.name.GetPtr(), dmDBNameLength);
+ name[dmDBNameLength-1] = '\0';
+ fName = name;
+
+ fCreationTime = db.creationTime;
+ fModificationTime = db.modificationTime;
+ fBackupTime = db.backupTime;
+ fType = db.type;
+ fCreator = db.creator;
+ fVersion = db.version;
+ fUniqueIDSeed = db.uniqueIDSeed;
+ fFlags = db.flags;
+ fVersion = db.version;
+
+ fAppInfoChunk = 0;
+ if (db.appinfoLID != 0)
+ {
+ ChunkList::iterator ai = rom->Chunks().find(db.appinfoLID);
+ if (ai != rom->Chunks().end())
+ fAppInfoChunk = &ai->second;
+ }
+
+ fSortInfoChunk = 0;
+ if (db.sortinfoLID != 0)
+ {
+ ChunkList::iterator si = rom->Chunks().find(db.sortinfoLID);
+ if (si != rom->Chunks().end())
+ fSortInfoChunk = &si->second;
+ }
+
+ for (i=0; i<db.recordCount; i++)
+ {
+ if (db.flags & 1)
+ fItems.push_back(DatabaseItemType(db.resources[i], rom));
+ else
+ fItems.push_back(DatabaseItemType(db.records[i], rom));
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::EmROMReader
+// ---------------------------------------------------------------------------
+
+EmROMReader::EmROMReader(ptr_type arenaPtr, size_t arenaSize) :
+ fPtr(arenaPtr),
+ fSize(arenaSize),
+ fEndPtr(A::add(arenaPtr, arenaSize)),
+ fCardAddress(0),
+ fChunks (),
+ fDatabases (),
+ fFeatures (),
+ fFlag328 (false),
+ fFlagEZ (false),
+ fFlagVZ (false),
+ fFlagSZ (false),
+ fCardVersion(0),
+ fCardName (),
+ fCardManuf (),
+ fStoreVersion(0),
+ fCompanyID(0),
+ fHalID(0),
+ fRomVersion(0),
+ fRomVersionString(),
+ fSplashChunk(0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::~EmROMReader
+// ---------------------------------------------------------------------------
+
+EmROMReader::~EmROMReader(void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireCardHeader
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireCardHeader(void)
+{
+ // Make sure the buffer is big enough for a card header
+
+ if (fSize < EmAliasROMCardHeader5Type<A>::GetSize())
+ return false;
+
+ EmAliasROMCardHeader5Type<A> cardHdr(fPtr);
+
+ // Make sure the stack size isn't something ludicrous.
+
+ if ((cardHdr.initStack == 0) ||
+ (cardHdr.initStack > 0x000FFFFFL)) // 1 Meg
+ return false;
+
+ if (cardHdr.signature != sysCardSignature)
+ return false;
+
+ // Make sure the header version isn't ludicrous.
+
+ if ((cardHdr.hdrVersion == 0) ||
+ (cardHdr.hdrVersion > 255)) // arbitrary val
+ return false;
+
+ // Make sure this isn't a "RAM only" card.
+
+ if (cardHdr.flags & memCardHeaderFlagRAMOnly)
+ return false;
+
+ char buffer[memMaxNameLen + 1];
+
+ fFlag328 = (cardHdr.flags & 0x0010) != 0;
+ fFlagEZ = (cardHdr.flags & 0x0020) != 0;
+ fFlagVZ = (cardHdr.flags & 0x0040) != 0;
+ fFlagSZ = (cardHdr.flags & 0x0080) != 0;
+ fCardVersion = cardHdr.hdrVersion;
+
+ buffer[memMaxNameLen] = '\0';
+
+ A::BlockCopy(buffer, cardHdr.cardName.GetPtr(), memMaxNameLen - 1);
+ fCardName = buffer;
+
+ A::BlockCopy(buffer, cardHdr.cardManuf.GetPtr(), memMaxNameLen - 1);
+ fCardManuf = buffer;
+
+ fCompanyID = cardHdr.companyID;
+ fHalID = cardHdr.halID;
+ fRomVersion = cardHdr.romVersionNumber;
+
+ A::BlockCopy(buffer, cardHdr.romVersionString.GetPtr(), memMaxNameLen - 1);
+ fRomVersionString = buffer;
+
+ SetCardAddress(GuessCardAddress());
+
+ unsigned long bigROM = (fCardVersion < 2) ? 0x3000 : cardHdr.bigrom;
+
+ if ((fCardAddress & 0x0FFFFF) != (bigROM & 0x0FFFFF))
+ {
+ /* Whoops, we probably just read a Small ROM. Skip to the
+ probable Big ROM, and continue from there. */
+
+ fPtr = A::add(fPtr, bigROM & 0x0FFFFF);
+ fSize -= (bigROM & 0x0FFFFF);
+
+ return AcquireCardHeader();
+ }
+
+ return true; // Card header verified properly
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::GuessCardAddress
+// ---------------------------------------------------------------------------
+
+UInt32 EmROMReader::GuessCardAddress(void)
+{
+ EmAliasROMCardHeader5Type<A> cardHdr(fPtr);
+
+ return (unsigned long)cardHdr.ramlist - 0x200;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::SetCardAddress
+// ---------------------------------------------------------------------------
+
+void EmROMReader::SetCardAddress(UInt32 address)
+{
+ fCardAddress = address;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireROMHeap
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireROMHeap(void)
+{
+ // Local IDs cannot be understood without card address
+
+ if (!fCardAddress)
+ return false;
+
+ EmAliasROMStoreHeader4Type<A> storeHdr(GetCardStorePtr());
+
+ if (storeHdr[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for store header?
+
+ if (storeHdr.signature != sysStoreSignature)
+ return false;
+
+ fStoreVersion = storeHdr.version;
+
+ ptr_type romHeapListPtr = A::add(fPtr, (UInt32)storeHdr.heapAddr-fCardAddress);
+
+ EmAliasUInt16<A> romHeapCount(romHeapListPtr);
+
+ if (romHeapListPtr < fPtr)
+ return false; // Heap list within buffer?
+
+ if (romHeapCount[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap list?
+
+ EmAliasUInt32<A> romHeapList(romHeapCount[1].GetPtr());
+
+ fChunks.clear();
+
+ fDatabases.clear();
+
+ fFeatures.clear();
+
+ /* Heap arrangements past version 1 will only have
+ a single heap. */
+
+ for (int heap=0; heap<romHeapCount; heap++)
+ {
+ if (romHeapList[heap+1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap list?
+
+ ptr_type romHeapPtr = A::add(fPtr, (UInt32)romHeapList[heap]-fCardAddress);
+ unsigned long checkSize;
+
+ if (romHeapPtr < fPtr)
+ return false; // Heap within buffer?
+
+ EmAliasROMHeapHeader1Type<A> heapHdr1(romHeapPtr);
+
+ if (heapHdr1.flags & 0x2000) // Version 4 heap
+ {
+ EmAliasROMHeapHeader3Type<A> heapHdr3(romHeapPtr);
+
+ checkSize = heapHdr3[1].GetSize();
+
+ if (heapHdr3[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr3[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr3.size)
+ goto fail; // Double-check of heap size failed
+
+ // If a free chunk is listed, perform verification
+
+ if ((UInt32)heapHdr3.freeChunk)
+ {
+ UInt32 freeLID = (UInt32)romHeapList + ((UInt32)heapHdr3.freeChunk * 2) + 8;
+
+ if (fChunks.find(freeLID) == fChunks.end())
+ goto fail; // Unable to find "free" chunk
+
+ if (!fChunks[freeLID].Free())
+ goto fail; // Supposedly free chunk isn't
+ }
+ }
+ else if (heapHdr1.flags & 0x4000) // Version 3 heap
+ {
+ EmAliasROMHeapHeader3Type<A> heapHdr3(romHeapPtr);
+
+ checkSize = heapHdr3[1].GetSize();
+
+ if (heapHdr3[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr3[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr3.size)
+ goto fail; // Double-check of heap size failed
+
+ // If a free chunk is listed, perform verification
+
+ if ((UInt32)heapHdr3.freeChunk)
+ {
+ UInt32 freeLID = (UInt32)romHeapList + ((UInt32)heapHdr3.freeChunk * 2) + 8;
+
+ if (fChunks.find(freeLID) == fChunks.end())
+ goto fail; // Unable to find "free" chunk
+
+ if (!fChunks[freeLID].Free())
+ goto fail; // Supposedly free chunk isn't
+ }
+ }
+ else if (heapHdr1.flags & 0x8000) // Version 2 heap
+ {
+ EmAliasROMHeapHeader2Type<A> heapHdr2(romHeapPtr);
+
+ checkSize = heapHdr2[1].GetSize();
+
+ if (heapHdr2[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr2[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr2Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 4; /* zero-length tail "chunk" */
+
+ if (checkSize != heapHdr2.size)
+ goto fail; // Double-check of heap size failed
+ }
+ else // Version 1 heap
+ {
+ EmAliasROMHeapHeader1Type<A> heapHdr1(romHeapPtr);
+
+ checkSize = heapHdr1[1].GetSize();
+
+ if (heapHdr1[1].GetPtr() >= fEndPtr)
+ return false; // Buffer big enough for heap header?
+
+ ptr_type chunkPtr = heapHdr1[1].GetPtr();
+ unsigned long addr = A::diff(chunkPtr, fPtr) + fCardAddress;
+
+ for (;;)
+ {
+ if (chunkPtr >= fEndPtr)
+ goto fail;
+
+ EmAliasROMHeapChunkHdr1Type<A> chunkHdr(chunkPtr);
+ ChunkType ct(chunkHdr, addr);
+
+ if (ct.TotalSize() == 0)
+ break;
+
+ /* store a ChunkType record mapped
+ by the "local ID" of each chunk */
+
+ fChunks[ct.LocalID()] = ct;
+
+ chunkPtr = A::add(chunkPtr, ct.TotalSize());
+ addr += ct.TotalSize();
+ checkSize += ct.TotalSize();
+ }
+
+ checkSize += 2; /* zero-length tail "chunk" */
+
+ if ((UInt16)(checkSize & 0xFFFF) != (UInt16)heapHdr1.size)
+ goto fail; // Double-check of heap size failed
+ }
+ } // next heap
+
+ return true; // Sucessfull acquisition
+
+fail:
+ fChunks.clear();
+ return false; // Failure
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireDatabases
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireDatabases(void)
+{
+ if (fChunks.size() == 0)
+ return false; // Must get chunks first
+
+ EmAliasROMStoreHeader4Type<A> storeHdr(GetCardStorePtr());
+
+ ChunkList::iterator dbHdrChunk = fChunks.find(storeHdr.dbLID);
+ if (dbHdrChunk == fChunks.end())
+ return false; // Could not find database directory chunk
+
+ dbHdrChunk->second.type = ChunkType::typeDBTable;
+
+ fDatabases.clear();
+
+ fFeatures.clear();
+
+ ptr_type dbHdrPtr = dbHdrChunk->second.GetPtr();
+
+#if LOG_DATABASES_HACK
+ LogAppendMsg ("-----");
+#endif
+ for (;;)
+ {
+ EmAliasROMDBDir1Type<A> dbHdr(dbHdrPtr);
+
+ for (int i=0; i<dbHdr.count; i++)
+ {
+ ChunkList::iterator dbChunk = fChunks.find(dbHdr.dbLID[i]);
+ if (dbChunk == fChunks.end())
+ continue; // Could not find database directory chunk
+
+ dbChunk->second.type = ChunkType::typeDBHeader;
+
+#if LOG_DATABASES_HACK
+ DatabaseType dbInfo(&dbChunk->second, this);
+
+ LogAppendMsg ("%s", dbInfo.Name ().c_str ());
+#endif
+
+ fDatabases.push_back(DatabaseType(&dbChunk->second, this));
+
+ for (unsigned int j=0; j<fDatabases[i].Items().size(); j++)
+ {
+ ChunkType* chunk = fDatabases[i].Items()[j].Chunk();
+ if (chunk)
+ {
+ chunk->type = ChunkType::typeRecord;
+ chunk->dbNumber = i;
+ chunk->recordNumber = j;
+ }
+ }
+ }
+
+ if (dbHdr.nextTable == 0)
+ break;
+ else
+ {
+ dbHdrChunk = fChunks.find(dbHdr.nextTable);
+ if (dbHdrChunk == fChunks.end())
+ break; // Could not find database directory chunk
+ dbHdrPtr = dbHdrChunk->second.GetPtr();
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireFeatures
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireFeatures(void)
+{
+ /* Nothing to see here... */
+ if (fDatabases.size() == 0)
+ return false; // Must get databases first
+
+ fFeatures.clear();
+
+ DatabaseList::iterator dbiter = fDatabases.begin();
+ for (; dbiter != fDatabases.end(); dbiter++)
+ {
+ if (dbiter->Creator() == 'psys')
+ {
+ for (DatabaseItemList::iterator iter = dbiter->Items().begin();
+ iter != dbiter->Items().end();
+ iter++)
+ {
+ if (iter->Type() == 'feat')
+ {
+ EmAliasROMFtrTableType<A> table(iter->Chunk()->GetPtr());
+
+ ptr_type pos = table.creator.GetPtr();
+
+ for (int i=0; i<table.numEntries; i++)
+ {
+ EmAliasROMFtrCreatorType<A> creator(pos);
+
+ int j;
+ for (j=0; j<creator.numEntries; j++)
+ {
+ fFeatures[creator.creator][creator.feature[j].num]
+ = creator.feature[j].value;
+ }
+
+ pos = creator.feature[j].GetPtr();
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::AcquireSplashDB
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::AcquireSplashDB(void)
+{
+ fSplashChunk = 0;
+
+ for (DatabaseList::iterator iter = fDatabases.begin();
+ iter != fDatabases.end();
+ iter++)
+ {
+ if (iter->Creator() == 'psys')
+ {
+ for (EmROMReader::DatabaseItemList::iterator jter = iter->Items().begin();
+ jter != iter->Items().end();
+ jter++)
+ {
+ if ((jter->Type() == 'Tbsb') &&
+ (jter->ID() == 19001))
+ {
+ fSplashChunk = jter->Chunk();
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::ContainsDB
+// ---------------------------------------------------------------------------
+
+bool EmROMReader::ContainsDB(string dbName) const
+{
+ for ( EmROMReader::DatabaseList::const_iterator i = fDatabases.begin();
+ i != fDatabases.end();
+ i++)
+ {
+ if (i->Name() == dbName)
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::Version
+// ---------------------------------------------------------------------------
+
+void EmROMReader::Version( int& major,
+ int& minor,
+ int& fix,
+ int& stage,
+ int& build) const
+{
+ major = minor = fix = stage = build = 0;
+
+ FeatureList::const_iterator psys = fFeatures.find('psys');
+ if (psys == fFeatures.end())
+ return;
+
+ map<int, int>::const_iterator psys_1 = psys->second.find(1);
+ if (psys_1 == psys->second.end())
+ return;
+
+ unsigned long ver = psys_1->second;
+ major = (ver >> 24) & 0x00FF;
+ minor = (ver >> 20) & 0x000F;
+ fix = (ver >> 16) & 0x000F;
+ stage = (ver >> 12) & 0x000F;
+ build = (ver >> 0) & 0x0FFF;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::Version
+// ---------------------------------------------------------------------------
+
+unsigned long EmROMReader::Version(void) const
+{
+ int major, minor, fix, state, build;
+ Version(major, minor, fix, state, build);
+
+ return (major << 16) | (minor << 8) | fix;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmROMReader::IsBitmapColor
+// ---------------------------------------------------------------------------
+
+int EmROMReader::IsBitmapColor (ChunkType& chunk, bool bootScreen)
+{
+ ptr_type pos = chunk.GetPtr();
+
+ if (bootScreen)
+ pos = A::add(pos, 6);
+
+ for (;;)
+ {
+ if (!chunk.Contains(pos, EmAliasBitmapTypeV2<A>::GetSize()))
+ return -1;
+
+ EmAliasBitmapTypeV2<A> bitmap(pos);
+
+ if (bitmap.pixelSize >= 8)
+ return 1;
+
+ if (!bitmap.nextDepthOffset)
+ break;
+
+ unsigned long offset = bitmap.nextDepthOffset;
+
+ pos = A::add(pos, offset * 4);
+ }
+
+ return 0;
+}
diff --git a/SrcShared/EmROMReader.h b/SrcShared/EmROMReader.h
new file mode 100644
index 0000000..902f64a
--- /dev/null
+++ b/SrcShared/EmROMReader.h
@@ -0,0 +1,260 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmROMReader_h
+#define EmROMReader_h
+
+/*
+ This file defines EmROMReader, a class used to parse up raw ROM
+ images and return information about them, such as the version number
+ in the version resource, card header information, and whether or not
+ the splash screen is in color. This information is used when trying
+ to determine on what device or devices the ROM can run.
+
+ NOTE: this class used to be a template class, parameterized on LAS
+ and PAS in EmPalmStructs.h. The intent was that it could be used to
+ access a raw ROM image from disk (using LAS) or the ROM image as
+ utilized in the emulated address space (using PAS). However, VC++
+ had problems trying to compile the nested classes in the EmROMReader
+ class template, so that feature was sacrificed.
+*/
+
+#include "EmPalmStructs.h"
+
+// Define this to 1 if you want to dump a list of databases
+// to the log file as the ROM is being enumerated. This is
+// handy when trying to find something in the ROM that differentiates
+// it from other ROMs.
+
+#define LOG_DATABASES_HACK 0
+
+#if LOG_DATABASES_HACK
+#include "Logging.h" // LogAppendMsg
+#endif
+
+#include <vector>
+#include <map>
+#include <string>
+
+typedef LAS A;
+
+class EmROMReader
+{
+ public:
+ typedef A::ptr_type ptr_type;
+
+ class ChunkType
+ {
+ public:
+
+ ChunkType(void);
+ ChunkType(const EmAliasROMHeapChunkHdr2Type<A>& chunk, UInt32 addr);
+ ChunkType(const EmAliasROMHeapChunkHdr1Type<A>& chunk, UInt32 addr);
+
+ public:
+
+ bool Free(void) { return fFree; }
+ int Owner(void) { return fOwner; }
+ unsigned long TotalSize(void) { return fSize; }
+ size_t Size(void) { return fSize - fHdrSize - fSizeAdj; }
+ ptr_type GetHdrPtr(void) { return fPtr; }
+ ptr_type GetPtr(void) { return A::add(fPtr, (int)(fHdrSize)); }
+ UInt32 LocalID(void) { return fAddress; }
+
+ bool Contains(ptr_type pos, size_t len=1)
+ { return (A::diff(pos, fPtr) >= 0) &&
+ ((A::diff(pos, fPtr) + len) <= fSize); }
+
+ private:
+
+ friend class EmROMReader;
+
+ unsigned long fSize;
+ bool fFree;
+ unsigned long fSizeAdj;
+ int fLockCount;
+ int fHOffset;
+ int fOwner;
+ ptr_type fPtr;
+ unsigned long fAddress;
+ int fHdrSize;
+
+ unsigned long recordNumber;
+ unsigned long dbNumber;
+
+ enum
+ {
+ typeOther,
+ typeRecord,
+ typeDBHeader,
+ typeDBTable,
+ typeFree
+ } type;
+ };
+
+ typedef map<unsigned long, ChunkType> ChunkList;
+
+ class DatabaseItemType
+ {
+ public:
+
+ DatabaseItemType(void);
+ DatabaseItemType(const EmAliasROMDBRecordHeader1Type<A> record, EmROMReader* rom);
+ DatabaseItemType(const EmAliasROMDBResourceHeader1Type<A> resource, EmROMReader* rom);
+
+ public:
+
+ bool Deleted(void) { return fDeleted; }
+ bool Dirty(void) { return fDirty; }
+ bool Busy(void) { return fBusy; }
+ bool Secret(void) { return fSecret; }
+ int Category(void) { return fCategory; }
+ unsigned long ID(void) { return fID; }
+ unsigned long Type(void) { return fType; }
+ bool Record(void) { return fRecord; }
+ ChunkType* Chunk(void) { return fChunk; }
+
+ private:
+
+ friend class EmROMReader;
+
+ bool fRecord;
+ unsigned long fID;
+ unsigned long fType;
+ int fCategory;
+ bool fDeleted;
+ bool fDirty;
+ bool fBusy;
+ bool fSecret;
+ UInt32 fChunkLID;
+
+ ChunkType* fChunk;
+ };
+
+ typedef vector<DatabaseItemType> DatabaseItemList;
+
+ class DatabaseType
+ {
+ public:
+
+ DatabaseType(void);
+ DatabaseType(ChunkType* hdr, EmROMReader* rom);
+
+ public:
+
+ string& Name(void) { return fName; }
+ const string& Name(void) const { return fName; }
+ DatabaseItemList& Items(void) { return fItems; }
+
+ unsigned long CreationTime(void) { return fCreationTime; }
+ unsigned long ModificationTime(void) { return fModificationTime; }
+ unsigned long BackupTime(void) { return fBackupTime; }
+ unsigned int Flags(void) { return fFlags; }
+ unsigned int Version(void) { return fVersion; }
+ unsigned long UniqueIDSeed(void) { return fUniqueIDSeed; }
+
+ unsigned long Creator(void) { return fCreator; }
+ unsigned long Type(void) { return fType; }
+
+ private:
+
+ friend class EmROMReader;
+
+ DatabaseItemList fItems;
+ string fName;
+ unsigned long fCreator, fType;
+ unsigned long fCreationTime, fModificationTime, fBackupTime;
+ unsigned int fFlags, fVersion;
+ unsigned long fUniqueIDSeed;
+ ChunkType* fAppInfoChunk;
+ ChunkType* fSortInfoChunk;
+ };
+
+ typedef vector<DatabaseType> DatabaseList;
+ typedef map<unsigned long, map<int, int> > FeatureList;
+
+ public:
+
+ EmROMReader(ptr_type arenaPtr, size_t arenaSize);
+ ~EmROMReader(void);
+
+ bool AcquireCardHeader(void);
+ UInt32 GuessCardAddress(void);
+ void SetCardAddress(UInt32 address);
+ bool AcquireROMHeap(void);
+ bool AcquireDatabases(void);
+ bool AcquireFeatures(void);
+ bool AcquireSplashDB(void);
+
+ bool ContainsDB(string dbName) const;
+
+ void Version(int& major,
+ int& minor,
+ int& fix,
+ int& stage,
+ int& build) const;
+ unsigned long Version(void) const;
+
+ static int IsBitmapColor (ChunkType& chunk, bool bootScreen);
+
+ public:
+
+ ChunkList& Chunks(void) { return fChunks; }
+ DatabaseList& Databases(void) { return fDatabases; }
+ FeatureList& Features(void) { return fFeatures; }
+ ChunkType* GetSplashChunk(void) const { return fSplashChunk; }
+ ptr_type GetCardHeaderPtr(void) const { return fPtr; }
+ ptr_type GetCardStorePtr(void) const { return A::add(fPtr, EmAliasROMCardHeader5Type<A>::GetSize()); }
+ bool GetFlag328(void) const { return fFlag328; }
+ bool GetFlagEZ(void) const { return fFlagEZ; }
+ bool GetFlagVZ(void) const { return fFlagVZ; }
+ bool GetFlagSZ(void) const { return fFlagSZ; }
+ UInt16 GetCardVersion(void) const { return fCardVersion; }
+ string GetCardName(void) const { return fCardName; }
+ string GetCardManufacturer(void) const { return fCardManuf; }
+ UInt16 GetStoreVersion(void) const { return fStoreVersion; }
+ UInt32 GetCompanyID(void) const { return fCompanyID; }
+ UInt32 GetHalID(void) const { return fHalID; }
+ UInt32 GetRomVersion(void) const { return fRomVersion; }
+ string GetRomVersionString(void) const { return fRomVersionString; }
+
+ private:
+
+ ptr_type fPtr;
+ size_t fSize;
+ ptr_type fEndPtr;
+
+ UInt32 fCardAddress;
+
+ ChunkList fChunks;
+ DatabaseList fDatabases;
+ FeatureList fFeatures;
+
+ bool fFlag328;
+ bool fFlagEZ;
+ bool fFlagVZ;
+ bool fFlagSZ;
+
+ UInt16 fCardVersion;
+ string fCardName, fCardManuf;
+
+ UInt16 fStoreVersion;
+
+ UInt32 fCompanyID, fHalID;
+ UInt32 fRomVersion;
+ string fRomVersionString;
+
+ ChunkType* fSplashChunk;
+};
+
+#endif // EmROMReader_h
diff --git a/SrcShared/EmROMTransfer.cpp b/SrcShared/EmROMTransfer.cpp
new file mode 100644
index 0000000..feb0c5a
--- /dev/null
+++ b/SrcShared/EmROMTransfer.cpp
@@ -0,0 +1,770 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmROMTransfer.h"
+
+#include "EmDlg.h" // DoTransferROM
+#include "EmStreamFile.h" // EmStreamFile
+#include "EmTransport.h" // EmTransport
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "ErrorHandling.h" // Errors::ThrowIfError
+#include "Platform.h" // Platform::GetMilliseconds
+#include "Strings.r.h" // kStr_Waiting
+
+
+/*
+ Notes on the XModem/YModem implementation used in this file:
+
+ Basic XModem is dead simple:
+
+ 1. Sender waits for NAK from receiver.
+ 2. Sender sends SOH, block#, complement of block#
+ 3. Sender sends 128 bytes of data.
+ 3. Sender sends one-byte sum of those 128 bytes as checksum.
+ 4. Receiver sends ACK or NAK.
+ 5. If NAK, go back to step 2.
+ 6. If ACK, increment block# and go back to step 2.
+ 7. At end of file, sender sends EOT.
+ 8. Receiver acknowledges EOT with ACK.
+
+ There is an XModem variant called Ymodem that sends an additional block at
+ the start of the protocol - this block contains the file name and size,
+ among other things.
+*/
+
+
+const int kXModemBlockSize = 1024; // 1k-XModem variant
+const int kXModemBufferSize = 1029; // 1k-XModem variant
+const char kXModemSoh = 1; // start of block header
+const char kXModemEof = 4; // end of file signal
+const char kXModemAck = 6; // acknowledge
+const char kXModemNak = 21; // negative acknowledge (resend packet)
+const char kXModemCan = 24; // cancel
+const char kXModemNakCrc = 'C'; // used instead of NAK for initial block
+
+
+enum
+{
+ kWaitingForTransport, // Waiting for transprt to come online
+ kOpen // Transport ready, first NakCrc sent
+};
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::ROMTransfer
+ *
+ * DESCRIPTION: Handle the entire process of downloading a ROM, from
+ * asking them for port/baud, to showing the progress
+ * dialog, to downloading the ROM, to saving it, and to
+ * handling the Cancel button.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmROMTransfer::ROMTransfer (void)
+{
+ // Run the dialog that sets up the download process.
+
+ EmTransport::Config* cfg;
+ if (EmDlg::DoROMTransferQuery (cfg) == kDlgItemCancel)
+ return;
+
+ EmAssert (cfg != NULL);
+
+ EmTransport* oldTransport = NULL;
+ EmTransport* transport = NULL;
+
+ try
+ {
+ // Close whatever might be on the selected port already.
+
+ oldTransport = cfg->GetTransport ();
+ if (oldTransport)
+ Errors::ThrowIfError (oldTransport->Close ());
+
+ // Open the port we want to use for downloading the ROM.
+
+ transport = cfg->NewTransport ();
+ Errors::ThrowIfError (transport->Open());
+
+ // Create the ROM transfer object with this transport.
+
+ EmROMTransfer transferer (transport);
+
+ // Run the progress window.
+
+ EmDlgItemID result = EmDlg::DoROMTransferProgress (transferer);
+
+ if (result != kDlgItemCancel && transferer.HaveEntireROM ())
+ {
+ // Ask what name to save the ROM image to.
+
+ EmFileRef ref;
+ EmFileTypeList typeList (1, kFileTypeROM);
+ if (EmDlg::DoPutFile (ref, "", "", typeList, "") == kDlgItemOK)
+ {
+ // Save the ROM image.
+
+ EmStreamFile stream (ref, kCreateOrEraseForUpdate,
+ kFileCreatorEmulator, kFileTypeROM);
+
+ stream.PutBytes (transferer.Data (), transferer.Size ());
+ }
+ }
+
+ ResetSerialPort (oldTransport, transport);
+ }
+ catch (ErrCode errCode)
+ {
+ ResetSerialPort (oldTransport, transport);
+ Errors::ReportIfError (kStr_CmdTransferROM, errCode, 0, false);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer c'tor
+ *
+ * DESCRIPTION: Create the object. Initialize all data members.
+ *
+ * PARAMETERS: transport - transport object for low-level communications.
+ * We do not own it; the client deletes it.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmROMTransfer::EmROMTransfer (EmTransport* transport) :
+ fState (kWaitingForTransport),
+ fTransport (transport),
+ fROMSize (0),
+ fROMRead (0),
+ fROMBuffer (),
+ fHaveFirstBlock (false),
+ fHaveLastBlock (false),
+ fLastValidBlock ((uint8) -1),
+ fProgressCaption (-1),
+ fProgressValue (-1),
+ fProgressMax (-1),
+ fProgressLastUpdate (0),
+// fTempBuffer (),
+ fTempBufferOffset (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer d'tor
+ *
+ * DESCRIPTION: Destroy the object. Delete all data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmROMTransfer::~EmROMTransfer (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::Continue
+ *
+ * DESCRIPTION: Continually called to incrementally download a ROM.
+ *
+ * PARAMETERS: dlg - reference to the progress dialog
+ *
+ * RETURNED: True to continue downloading, false if done.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::Continue (EmDlgRef dlg)
+{
+ switch (fState)
+ {
+ case kWaitingForTransport:
+ return this->WaitForTransport (dlg);
+
+ case kOpen:
+ return this->ReadSomeData (dlg);
+ }
+
+ return false; // Don't continue
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::Abort
+ *
+ * DESCRIPTION: Abort the download. Called when the user clicks on
+ * the Cancel button.
+ *
+ * PARAMETERS: dlg - reference to the progress dialog
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmROMTransfer::Abort (EmDlgRef)
+{
+ // Nothing to do. All memory is reclaimed in the destructor, and
+ // the transport is closed and called by EmROMTransfer::ROMTransfer.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::Size
+ *
+ * DESCRIPTION: Return the size of the ROM. Valid only if the ROM has
+ * been successfully downloaded (that is, Continue had
+ * been called until it finally returned false).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Size of the ROM in bytes.
+ *
+ ***********************************************************************/
+
+long EmROMTransfer::Size (void)
+{
+ return fROMSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::Data
+ *
+ * DESCRIPTION: Return a pointer to the ROM. Valid only if the ROM has
+ * been successfully downloaded (that is, Continue had
+ * been called until it finally returned false).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Pointer to the ROM image.
+ *
+ ***********************************************************************/
+
+void* EmROMTransfer::Data (void)
+{
+ return fROMBuffer.Get();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::WaitForTransport
+ *
+ * DESCRIPTION: Called while waiting for the transport object to
+ * indicate that the transport is ready for sending
+ * data. Until it is, we idle the progress indicator.
+ * When the transport is ready, prepare our state
+ * variables for downloading the ROM.
+ *
+ * PARAMETERS: dlg - reference to the progress dialog
+ *
+ * RETURNED: True to indicate that the Continue function should
+ * still be called.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::WaitForTransport (EmDlgRef dlg)
+{
+ // Update the progress indicator.
+
+ this->UpdateProgress (dlg, kStr_Waiting, 0, 0);
+
+ if (fTransport->CanRead ())
+ {
+ // Start the transfer by sending kXModemNakCrc.
+
+ this->SendByte (kXModemNakCrc);
+
+ // Initialize our download state
+
+ fROMSize = 0;
+ fROMRead = 0;
+ fHaveFirstBlock = false;
+ fHaveLastBlock = false;
+ fLastValidBlock = (uint8) -1;
+ fTimeoutBase = Platform::GetMilliseconds ();
+ fTempBufferOffset = 0;
+
+ // Switch over to the engine state
+
+ fState = kOpen;
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::ReadSomeData
+ *
+ * DESCRIPTION: Called to incrementally download a ROM. Reads data
+ * until we have enough for an XModem packet. Examines
+ * the packet. If valid, adds it to our full ROM image and
+ * acks the packet. If invalid, requests a resend.
+ *
+ * PARAMETERS: dlg - reference to the progress dialog
+ *
+ * RETURNED: True to indicate that the Continue function should
+ * still be called. False if the entire ROM has now
+ * been downloaded.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::ReadSomeData (EmDlgRef dlg)
+{
+ this->BufferPendingData ();
+
+ uint8 ackChar;
+
+ // If we have an entire new valid block by now, process it.
+
+ if (this->HaveValidBlock ())
+ {
+ ackChar = this->HandleNewBlock ();
+ }
+
+ // EOF signal.
+
+ else if (fTempBufferOffset > 0 && fTempBuffer[0] == kXModemEof)
+ {
+ ackChar = kXModemAck;
+ fHaveLastBlock = true;
+ }
+
+ // Check for timeouts.
+
+ else
+ {
+ // Returns:
+ //
+ // kXModemNak If timeout in middle of transfer
+ // kXModemNakCrc If timeout and haven't started transfer, yet
+ // 0 If no timeout
+
+ ackChar = this->CheckForTimeouts ();
+ }
+
+ // Send the ack char and reset our timeout counter.
+
+ if (ackChar)
+ {
+ this->SendByte (ackChar);
+ }
+
+ // Update the progress indicator.
+
+ if (fHaveFirstBlock)
+ {
+ this->UpdateProgress (dlg, kStr_Transferring, fROMRead, fROMSize);
+ }
+
+ return !this->HaveEntireROM ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::HandleNewBlock
+ *
+ * DESCRIPTION: A new ROM block has been downloaded and verified as
+ * valid. Add it to our incrementally built ROM image
+ * and prepare for the next block.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The character with which to acknowledge the packet.
+ *
+ ***********************************************************************/
+
+uint8 EmROMTransfer::HandleNewBlock (void)
+{
+ // If this is the first block, skip past the "file name" and
+ // get the file (ROM) size. Allocate a buffer to hold the image.
+
+ uint8 receivedBlock = fTempBuffer[1];
+
+ EmAssert (
+ !fHaveFirstBlock ||
+ fLastValidBlock == receivedBlock ||
+ fLastValidBlock == (uint8) (receivedBlock - 1));
+
+ if (!fHaveFirstBlock)
+ {
+ char* p = (char*) &fTempBuffer[3];
+ p += strlen (p) + 1;
+ fROMSize = atoi (p);
+ fROMBuffer.Adopt ((char*) Platform::AllocateMemory (fROMSize));
+
+ fHaveFirstBlock = true;
+ }
+
+ // Got a good block of data. Copy it into the ROM image.
+
+ else if (fLastValidBlock != receivedBlock)
+ {
+ memcpy (fROMBuffer.Get () + fROMRead, &fTempBuffer[3], kXModemBlockSize);
+ fROMRead += kXModemBlockSize;
+
+#ifndef NDEBUG
+ int blocksRead = fROMRead / kXModemBlockSize;
+ EmAssert ((blocksRead % 256) == receivedBlock);
+ EmAssert (fROMRead <= fROMSize);
+#endif
+ }
+
+ fLastValidBlock = receivedBlock;
+
+ // Prepare the read buffer for the next block of data.
+
+ fTempBufferOffset = 0;
+
+ // Acknowledge this packet as good.
+
+ return kXModemAck;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::CheckForTimeouts
+ *
+ * DESCRIPTION: Check to see if a certain amount of time has elapsed
+ * since we received a valid packet. If it has, indicate
+ * that the sender resend the previous packet.
+ *
+ * PARAMETERS: ackChar - the current ackChar the caller is considering
+ * sending back to the client.
+ *
+ * RETURNED: The ackChar to *really* send back to the client. If
+ * the timeout hasn't occurred, just send back what the
+ * caller sent us. If it has timed out, return an ackChar
+ * based on whether we're in the middle of a download or
+ * just starting up.
+ *
+ ***********************************************************************/
+
+uint8 EmROMTransfer::CheckForTimeouts (void)
+{
+ if (Platform::GetMilliseconds () - fTimeoutBase > kTimeout)
+ {
+ // We haven't received a good packet in some time. Probably a dropped
+ // character, or we're just starting the protocol. If just starting, nak
+ // with kXModemNakCrc 'C', else just use regular nak '\025'.
+
+ fTempBufferOffset = 0;
+ return fROMRead > 0 ? kXModemNak : kXModemNakCrc;
+ }
+
+ return 0; // No timeout
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::BufferPendingData
+ *
+ * DESCRIPTION: Transfer any data in the transport's buffer into our
+ * own private little buffer used to hold a single packet.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmROMTransfer::BufferPendingData (void)
+{
+ // Get some data. Read as much as we can, but don't overflow
+ // our local buffer.
+
+ long bytesInPort = fTransport->BytesInBuffer (kXModemBufferSize);
+
+ if (bytesInPort > 0)
+ {
+ long bytesToRead = min (bytesInPort, kBufferSize - fTempBufferOffset);
+ ErrCode err = fTransport->Read (bytesToRead, &fTempBuffer[fTempBufferOffset]);
+ Errors::ThrowIfError (err);
+ fTempBufferOffset += bytesToRead;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::HaveValidBlock
+ *
+ * DESCRIPTION: Check to see if our little packet buffer now contains
+ * a full and valid packet
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::HaveValidBlock (void)
+{
+ // Check to see whether we have enough data for a full block, and
+ // that the block is valid, and it's the block number we're expecting
+
+ Bool haveEnoughData = fTempBufferOffset >= kXModemBufferSize;
+ Bool checksumValid = haveEnoughData && this->ValidXModemBlock (fTempBuffer);
+
+ return haveEnoughData && checksumValid;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::HaveEntireROM
+ *
+ * DESCRIPTION: Return whether or now we have downloaded the entire ROM.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::HaveEntireROM (void)
+{
+ return fHaveLastBlock;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::ValidXModemBlock
+ *
+ * DESCRIPTION: Validate a packet by doing a checksum and comparing it
+ * to the checksum that came with the packet.
+ *
+ * PARAMETERS: block - the packet to checksum
+ *
+ * RETURNED: True if valid.
+ *
+ ***********************************************************************/
+
+Bool EmROMTransfer::ValidXModemBlock (const uint8* block)
+{
+ /*
+ * XModem-1k block layout is as follows:
+ *
+ * +--------------+
+ * | SOH = '\002' |
+ * +--------------+
+ * | Block number |
+ * +--------------+
+ * | Block compl. | Complement of block number
+ * +--------------+
+ * | 1024 bytes |
+ * | of data |
+ * . . .
+ * . . .
+ * +--------------+
+ * | CRC hi byte | CRC-16 of preceding 1024 bytes of data,
+ * +--------------+ plus two zero bytes
+ * | CRC lo byte |
+ * +--------------+
+ */
+
+ if (block[0] != kXModemSoh)
+ {
+ return false;
+ }
+
+ if ((block[1] ^ block[2]) != 0xFF)
+ {
+ return false;
+ }
+
+ uint16 calculatedCRC = Crc16CalcBlock ((void*) &block[3], kXModemBlockSize, 0);
+
+ uint8 zeros[2] = {0, 0};
+ calculatedCRC = Crc16CalcBlock (zeros, 2, calculatedCRC);
+
+ uint16 xmittedCRC = (((uint16) (block[3 + kXModemBlockSize])) << 8) |
+ block[3 + kXModemBlockSize + 1];
+
+ return xmittedCRC == calculatedCRC;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::SendByte
+ *
+ * DESCRIPTION: Send a single byte to the client.
+ *
+ * PARAMETERS: byte - the byte to send.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+#define CORRUPT_SENDS 0
+
+#if CORRUPT_SENDS
+static UInt32 PrvRange (UInt32 maxValue)
+{
+ static int initialized;
+ if (!initialized)
+ {
+ initialized = true;
+ srand (1);
+ }
+
+ return (rand () * maxValue) / (1UL + RAND_MAX);
+}
+#endif
+
+
+void EmROMTransfer::SendByte (uint8 byte)
+{
+#if CORRUPT_SENDS
+ // Drop a character.
+ if (::PrvRange (100) < 5)
+ {
+ LogAppendMsg ("CORRUPTOR: dropping a character");
+ fTimeoutBase = Platform::GetMilliseconds ();
+ return;
+ }
+
+ // Corrupt a character.
+ if (::PrvRange (100) < 5)
+ {
+ LogAppendMsg ("CORRUPTOR: changing a character");
+ byte++;
+ }
+#endif
+
+ long len = 1;
+ /*ErrCode err =*/ fTransport->Write (len, &byte);
+
+ // Any errors will just cause the retry/timeout mechanisms to kick in.
+// Errors::ThrowIfError (err);
+
+ fTimeoutBase = Platform::GetMilliseconds ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::UpdateProgress
+ *
+ * DESCRIPTION: Update the progress bar according to whether or not we
+ * have started the download process and, if so, how far
+ * along we are. The progress information is updated only
+ * incrementally and only when it's been changed.
+ *
+ * PARAMETERS: dlg - reference to progress dialog.
+ * caption - StrID of string for caption.
+ * value - number indicating how much of the ROM has been
+ * downloaded.
+ * max - number indicating how large the ROM image is.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmROMTransfer::UpdateProgress (EmDlgRef dlg, long caption, long value, long maxValue)
+{
+ if (fProgressCaption != caption)
+ {
+ fProgressCaption = caption;
+ EmDlg::SetItemText (dlg, kDlgItemDlpMessage, caption);
+ }
+
+ uint32 now = Platform::GetMilliseconds ();
+ uint32 delta = now - fProgressLastUpdate;
+ bool timeout = delta > kProgressTimeout;
+
+ if (timeout)
+ {
+ // Divide values by 1024, since the Windows control deals only
+ // with 16-bit values. (This is fixed in later versions of
+ // the progress control, but those aren't shipped with stock
+ // Windows installations, yet.)
+
+ if (fProgressMax != maxValue)
+ {
+ fProgressMax = maxValue;
+ EmDlg::SetItemMax (dlg, kDlgItemDlpProgress, max (1L, maxValue / 1024));
+ }
+
+ if (fProgressValue != value)
+ {
+ fProgressValue = value;
+ EmDlg::SetItemValue (dlg, kDlgItemDlpProgress, value / 1024);
+ }
+
+ fProgressLastUpdate = now;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmROMTransfer::ResetSerialPort
+ *
+ * DESCRIPTION: We're done downloading the ROM (either successfully, or
+ * after an error or after the user Cancels). Close up
+ * the transport object we were using and, if needed,
+ * restore the old transport object.
+ *
+ * PARAMETERS: oldTransport - the transport object that was using the
+ * connection medium before we came along and usurped
+ * it. Usually a serial port.
+ *
+ * curTransport - the transport object used to download
+ * the ROM and that now needs to be closed.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmROMTransfer::ResetSerialPort (EmTransport* oldTransport, EmTransport* curTransport)
+{
+ // Close our stream.
+
+ if (curTransport)
+ {
+ curTransport->Close ();
+ delete curTransport;
+ }
+
+ // Reopen the stream used before we got in the way.
+
+ if (oldTransport)
+ {
+ oldTransport->Open ();
+ }
+}
diff --git a/SrcShared/EmROMTransfer.h b/SrcShared/EmROMTransfer.h
new file mode 100644
index 0000000..29362fe
--- /dev/null
+++ b/SrcShared/EmROMTransfer.h
@@ -0,0 +1,79 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmROMTransfer_h
+#define EmROMTransfer_h
+
+class EmTransport;
+
+#include "EmDlg.h" // EmDlgRef
+#include "EmTypes.h" // ErrCode
+#include "Miscellaneous.h" // StMemory
+
+class EmROMTransfer
+{
+ public:
+ EmROMTransfer (EmTransport*);
+ ~EmROMTransfer (void);
+
+ static void ROMTransfer (void);
+
+ Bool Continue (EmDlgRef);
+ void Abort (EmDlgRef);
+
+ long Size (void);
+ void* Data (void);
+
+ private:
+ Bool WaitForTransport (EmDlgRef);
+ Bool ReadSomeData (EmDlgRef);
+ uint8 HandleNewBlock (void);
+ uint8 CheckForTimeouts (void);
+ void BufferPendingData (void);
+ Bool HaveValidBlock (void);
+ Bool HaveEntireROM (void);
+ Bool ValidXModemBlock (const uint8* block);
+ void SendByte (uint8 byte);
+ void UpdateProgress (EmDlgRef, long, long, long);
+ static void ResetSerialPort (EmTransport* oldPort,
+ EmTransport* serPort);
+
+ private:
+ int fState;
+ EmTransport* fTransport;
+
+ long fROMSize;
+ long fROMRead;
+ StMemory fROMBuffer;
+
+ Bool fHaveFirstBlock;
+ Bool fHaveLastBlock;
+ uint8 fLastValidBlock;
+
+ long fProgressCaption;
+ long fProgressValue;
+ long fProgressMax;
+ uint32 fProgressLastUpdate;
+ enum { kProgressTimeout = 300 }; // Milliseconds
+
+ enum { kTimeout = 1 * 1000 }; // Milliseconds
+ uint32 fTimeoutBase;
+
+ enum { kXModemBlockSize = 1024L };
+ enum { kBufferSize = 2 * kXModemBlockSize };
+ uint8 fTempBuffer[kBufferSize];
+ long fTempBufferOffset;
+};
+
+
+#endif /* EmROMTransfer_h */
diff --git a/SrcShared/EmRPC.cpp b/SrcShared/EmRPC.cpp
new file mode 100644
index 0000000..3fb1b6e
--- /dev/null
+++ b/SrcShared/EmRPC.cpp
@@ -0,0 +1,451 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRPC.h"
+
+#include "EmPalmStructs.h" // SysPktRPCParamType, SysPktRPCType, SysPktRPC2Type
+#include "EmSession.h" // SuspendByExternal
+#include "HostControl.h" // hostErrTimeout
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // CountBits
+#include "Platform.h" // Platform::GetMilliseconds
+#include "PreferenceMgr.h" // Preference
+#include "EmMemory.h" // CEnableFullAccess
+#include "SLP.h" // SLP::EventCallback
+#include "SocketMessaging.h" // CTCPSocket
+#include "SystemPacket.h" // SystemPacket::
+
+
+struct SLPTimeout
+{
+ // Default constructor for the creation of STL collections.
+ // CodeWarrior needed this; VC++ didn't.
+ SLPTimeout () :
+ fSLP (),
+ fStart (0),
+ fTimeout (0)
+ {
+ }
+
+ SLPTimeout (SLP& slp, long timeout) :
+ fSLP (slp),
+ fStart (Platform::GetMilliseconds ()),
+ fTimeout (timeout)
+ {
+ }
+
+ SLP fSLP;
+ uint32 fStart;
+ uint32 fTimeout;
+};
+
+typedef vector<SLPTimeout> SLPTimeoutList;
+
+static SLPTimeoutList gSLPTimeouts;
+static SLP* gCurrentPacket;
+static omni_mutex gMutex;
+
+#define PRINTF if (true) ; else LogAppendMsg
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::Startup
+ *
+ * DESCRIPTION: Create all the sockets we'll need for the application
+ * and start them listening for clients. Call this once
+ * at application startup.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void RPC::Startup (void)
+{
+ RPC::CreateNewListener ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::Shutdown
+ *
+ * DESCRIPTION: Call this once at application shutdown.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void RPC::Shutdown (void)
+{
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::Idle
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void RPC::Idle (void)
+{
+ omni_mutex_lock lock (gMutex);
+
+ uint32 now = Platform::GetMilliseconds ();
+
+ SLPTimeoutList::iterator iter = gSLPTimeouts.begin ();
+
+ while (iter != gSLPTimeouts.end ())
+ {
+ SLP& slp = iter->fSLP;
+ uint32 start = iter->fStart;
+ uint32 timeout = iter->fTimeout;
+
+ if (now - start > timeout)
+ {
+ PRINTF ("RPC::Idle: Timing out.");
+
+ EmAssert (slp.HavePacket ());
+
+ slp.DeferReply (false);
+
+ EmProxySysPktBodyType& response = slp.Body ();
+ if (response.command == sysPktRPCCmd)
+ {
+ EmAliasSysPktRPCType<LAS> response (slp.Body().GetPtr());
+
+ response.command = sysPktRPCRsp;
+ response._filler = 0;
+
+ response.resultD0 = (UInt32) hostErrTimeout;
+ response.resultA0 = 0;
+ }
+ else
+ {
+ EmAliasSysPktRPC2Type<LAS> response (slp.Body().GetPtr());
+
+ response.command = sysPktRPC2Rsp;
+ response._filler = 0;
+
+ response.resultD0 = (UInt32) hostErrTimeout;
+ response.resultA0 = 0;
+ response.resultException = 0;
+ }
+
+ long bodySize = slp.GetPacketSize () - (slp.Header().GetSize() + slp.Footer().GetSize());
+
+ slp.SendPacket (response.GetPtr (), bodySize);
+
+ iter = gSLPTimeouts.erase (iter);
+ continue;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::SignalWaiters
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void RPC::SignalWaiters (HostSignalType signal)
+{
+ omni_mutex_lock lock (gMutex);
+
+ PRINTF ("RPC::SignalWaiters: Entering");
+
+ Bool signalledOne = false;
+ SLPTimeoutList::iterator iter = gSLPTimeouts.begin ();
+
+ while (iter != gSLPTimeouts.end ())
+ {
+ PRINTF ("RPC::SignalWaiters: Signaling");
+
+ SLP& slp = iter->fSLP;
+
+ EmAssert (slp.HavePacket ());
+
+ slp.DeferReply (false);
+
+ EmProxySysPktBodyType& response = slp.Body ();
+ if (response.command == sysPktRPCCmd)
+ {
+ EmAliasSysPktRPCType<LAS> response (slp.Body().GetPtr());
+
+ response.command = sysPktRPCRsp;
+ response._filler = 0;
+
+ response.resultD0 = errNone;
+ response.resultA0 = 0;
+
+ EmAliasSysPktRPCParamType<LAS> param (response.param.GetPtr ());
+
+ param.asLong = signal;
+ }
+ else
+ {
+ EmAliasSysPktRPC2Type<LAS> response (slp.Body().GetPtr());
+
+ response.command = sysPktRPC2Rsp;
+ response._filler = 0;
+
+ response.resultD0 = errNone;
+ response.resultA0 = 0;
+ response.resultException = 0;
+
+ int numRegs = ::CountBits(response.DRegMask) +
+ ::CountBits(response.ARegMask);
+ UInt16* numParams = ((UInt16*) response.Regs.GetPtr ()) + numRegs;
+ EmAliasSysPktRPCParamType<LAS> param (numParams + 1);
+
+ param.asLong = signal;
+ }
+
+ long bodySize = slp.GetPacketSize () - (slp.Header().GetSize() + slp.Footer().GetSize());
+
+ ErrCode result = slp.SendPacket (response.GetPtr (), bodySize);
+
+ if (result == errNone)
+ {
+ signalledOne = true;
+ }
+
+ ++iter;
+ }
+
+ gSLPTimeouts.clear ();
+
+ // gSession may be NULL if we're signally a hostSignalQuit.
+
+ if (signalledOne && gSession)
+ {
+ gSession->ScheduleSuspendExternal ();
+ }
+
+ PRINTF ("RPC::SignalWaiters: Exiting");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::HandleNewPacket
+ *
+ * DESCRIPTION: Completely handle a packet sent from an external
+ * client, setting any state and sending a reply if
+ * necessary.
+ *
+ * PARAMETERS: slp - a reference to a SerialLink Protocol object that
+ * contains the packet information and the horse...uh,
+ * socket it rode in on.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode RPC::HandleNewPacket (SLP& slp)
+{
+ ErrCode result = errNone;
+
+ EmAssert (slp.Header ().dest == slkSocketRPC);
+
+ gCurrentPacket = &slp;
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ try
+ {
+ switch (slp.Body ().command)
+ {
+ case sysPktReadMemCmd:
+ result = SystemPacket::ReadMem (slp);
+ break;
+
+ case sysPktWriteMemCmd:
+ result = SystemPacket::WriteMem (slp);
+ break;
+
+ case sysPktRPCCmd:
+ result = SystemPacket::RPC (slp);
+ break;
+
+ case sysPktRPC2Cmd:
+ result = SystemPacket::RPC2 (slp);
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (...)
+ {
+ gCurrentPacket = NULL;
+ throw;
+ }
+
+ gCurrentPacket = NULL;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::HandlingPacket
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool RPC::HandlingPacket (void)
+{
+ return gCurrentPacket != NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::DeferCurrentPacket
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void RPC::DeferCurrentPacket (long timeout)
+{
+ omni_mutex_lock lock (gMutex);
+
+ PRINTF ("RPC::DeferCurrentPacket: Entering");
+
+ EmAssert (gCurrentPacket);
+
+ gCurrentPacket->DeferReply (true);
+ gSLPTimeouts.push_back (SLPTimeout (*gCurrentPacket, timeout));
+
+ PRINTF ("RPC::DeferCurrentPacket: Exiting");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::EventCallback
+ *
+ * DESCRIPTION: Callback function for RPC-related sockets. When an RPC
+ * socket connects, we instantly create a new listener.
+ * When an RPC socket disconnects, we delete it.
+ *
+ * PARAMETERS: s - the socket that connected, disconnected, or received
+ * some data.
+ *
+ * event - a code indicating what happened.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void RPC::EventCallback (CSocket* s, int event)
+{
+ switch (event)
+ {
+ case CSocket::kConnected:
+ {
+ RPC::CreateNewListener ();
+ break;
+ }
+
+ case CSocket::kDataReceived:
+ {
+ break;
+ }
+
+ case CSocket::kDisconnected:
+ {
+ // A socket just disconnected. If we had anything on that
+ // socket waiting for us to signal it, forget about it.
+
+ SLPTimeoutList::iterator iter = gSLPTimeouts.begin ();
+
+ while (iter != gSLPTimeouts.end ())
+ {
+ if (iter->fSLP.HasSocket (s))
+ {
+ gSLPTimeouts.erase (iter);
+ iter = gSLPTimeouts.begin ();
+ continue;
+ }
+
+ ++iter;
+ }
+
+ s->Delete ();
+ }
+ }
+
+ SLP::EventCallback (s, event);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RPC::CreateNewListener
+ *
+ * DESCRIPTION: Create a new socket for listening for RPC clients.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void RPC::CreateNewListener (void)
+{
+ Preference<long> portPref (kPrefKeyRPCSocketPort);
+
+ if (*portPref != 0)
+ {
+ CSocket* rpcSocket = new CTCPSocket (&RPC::EventCallback, *portPref);
+ ErrCode err = rpcSocket->Open ();
+ if (err != errNone)
+ {
+ rpcSocket->Delete ();
+ rpcSocket = NULL;
+ }
+ }
+}
+
+
diff --git a/SrcShared/EmRPC.h b/SrcShared/EmRPC.h
new file mode 100644
index 0000000..ea6f769
--- /dev/null
+++ b/SrcShared/EmRPC.h
@@ -0,0 +1,47 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRPC_h
+#define EmRPC_h
+
+#include "EmTypes.h" // ErrCode
+#include "HostControl.h" // HostSignal
+
+class SLP;
+class CSocket;
+
+#define slkSocketRPC (slkSocketFirstDynamic + 10)
+#define sysPktRPC2Cmd 0x70
+#define sysPktRPC2Rsp 0xF0
+
+class RPC
+{
+ public:
+ static void Startup (void);
+ static void Shutdown (void);
+
+ static void Idle (void);
+ static void SignalWaiters (HostSignalType);
+
+ static ErrCode HandleNewPacket (SLP&);
+
+ static Bool HandlingPacket (void);
+ static void DeferCurrentPacket (long timeout);
+
+ private:
+ static void EventCallback (CSocket* s, int event);
+ static void CreateNewListener (void);
+};
+
+#endif /* EmRPC_h */
+
diff --git a/SrcShared/EmRect.cpp b/SrcShared/EmRect.cpp
new file mode 100644
index 0000000..1734a8f
--- /dev/null
+++ b/SrcShared/EmRect.cpp
@@ -0,0 +1,1047 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRect.h"
+
+// ----------------------------------------------------------------------
+// * Helper functions
+// ----------------------------------------------------------------------
+
+template <class coord>
+inline
+coord Min (coord a, coord b) { return a < b ? a : b; }
+
+template <class coord>
+inline
+coord Max (coord a, coord b) { return a > b ? a : b; }
+
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+coord
+EmRectTempl<coord>::Width (void) const
+{
+ return fRight - fLeft;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+coord
+EmRectTempl<coord>::Height (void) const
+{
+ return fBottom - fTop;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::Size (void) const
+{
+ return EmPointTempl<coord> (Width (), Height ());
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::TopLeft (void) const
+{
+ return EmPointTempl<coord> (fLeft, fTop);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::TopRight (void) const
+{
+ return EmPointTempl<coord> (fRight, fTop);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::BottomLeft (void) const
+{
+ return EmPointTempl<coord> (fLeft, fBottom);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::BottomRight (void) const
+{
+ return EmPointTempl<coord> (fRight, fBottom);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::North (void) const
+{
+ return EmPointTempl<coord> ((fLeft + fRight) / 2, fTop);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::South (void) const
+{
+ return EmPointTempl<coord> ((fLeft + fRight) / 2, fBottom);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::East (void) const
+{
+ return EmPointTempl<coord> (fRight, (fTop + fBottom) / 2);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::West (void) const
+{
+ return EmPointTempl<coord> (fLeft, (fTop + fBottom) / 2);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmPointTempl<coord>
+EmRectTempl<coord>::Center (void) const
+{
+ return EmPointTempl<coord> ((fLeft + fRight) / 2, (fTop + fBottom) / 2);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::IsEmpty (void) const
+{
+ return fRight <= fLeft || fBottom <= fTop;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::IsNull (void) const
+{
+ return fTop == 0 && fLeft == 0 && fBottom == 0 && fRight == 0;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::IsEqual (const EmRectTempl<coord>& other) const
+{
+ return
+ fTop == other.fTop &&
+ fLeft == other.fLeft &&
+ fBottom == other.fBottom &&
+ fRight == other.fRight;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::Contains(const EmPointTempl<coord>& pt) const
+{
+ return
+ pt.fY >= fTop &&
+ pt.fY < fBottom &&
+ pt.fX >= fLeft &&
+ pt.fX < fRight;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::Contains (const EmRectTempl<coord>& rt) const
+{
+ return rt.fTop >= fTop &&
+ rt.fTop <= fBottom &&
+ rt.fLeft >= fLeft &&
+ rt.fLeft <= fRight &&
+ rt.fBottom >= fTop &&
+ rt.fBottom <= fBottom &&
+ rt.fRight >= fLeft &&
+ rt.fRight <= fRight;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::Intersects (const EmRectTempl<coord>& rt) const
+{
+#if 0
+ //
+ // Different semantics we might want to consider.
+ //
+ if (IsEmpty() || rt.IsEmpty())
+ return false;
+#endif
+
+ return
+ (rt.fTop < this->fBottom && rt.fBottom > this->fTop) &&
+ (rt.fLeft < this->fRight && rt.fRight > this->fLeft);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::Set (coord left, coord top, coord right, coord bottom)
+{
+ fLeft = left;
+ fTop = top;
+ fRight = right;
+ fBottom = bottom;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::Set (const EmPointTempl<coord>& topLeft, const EmPointTempl<coord>& bottomRight)
+{
+ fLeft = topLeft.fX;
+ fTop = topLeft.fY;
+ fRight = bottomRight.fX;
+ fBottom = bottomRight.fY;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::BeEmpty (void)
+{
+ fTop = fLeft = fBottom = fRight = 0;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::Inset (coord x, coord y)
+{
+ fTop += y;
+ fLeft += x;
+ fBottom -= y;
+ fRight -= x;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::Offset (coord x, coord y)
+{
+ fTop += y;
+ fLeft += x;
+ fBottom += y;
+ fRight += x;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::ScaleUp (coord x, coord y)
+{
+ fTop *= y;
+ fLeft *= x;
+ fBottom *= y;
+ fRight *= x;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::ScaleDown (coord x, coord y)
+{
+ EmAssert (x != 0);
+ EmAssert (y != 0);
+
+ fTop /= y;
+ fLeft /= x;
+ fBottom /= y;
+ fRight /= x;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::IntersectWith (const EmRectTempl<coord>& other)
+{
+ if (this->IsEmpty ())
+ {
+ }
+ else if (other.IsEmpty ())
+ {
+ this->BeEmpty ();
+ }
+ else
+ {
+ if (other.fLeft > fLeft)
+ fLeft = other.fLeft;
+
+ if (other.fTop > fTop)
+ fTop = other.fTop;
+
+ if (other.fRight < fRight)
+ fRight = other.fRight;
+
+ if (other.fBottom < fBottom)
+ fBottom = other.fBottom;
+ }
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::UnionWith (const EmRectTempl<coord>& other)
+{
+ if (this->IsEmpty ())
+ {
+ *this = other;
+ }
+ else if (other.IsEmpty ())
+ {
+ }
+ else
+ {
+ this->ExtendTo (other);
+ }
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::ExtendTo (const EmPointTempl<coord>& pt)
+{
+ if (pt.fX < fLeft)
+ fLeft = pt.fX;
+
+ if (pt.fY < fTop)
+ fTop = pt.fY;
+
+ if (pt.fX > fRight)
+ fRight = pt.fX;
+
+ if (pt.fY > fBottom)
+ fBottom = pt.fY;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::ExtendTo (const EmRectTempl<coord>& other)
+{
+ if (other.fLeft < fLeft)
+ fLeft = other.fLeft;
+
+ if (other.fTop < fTop)
+ fTop = other.fTop;
+
+ if (other.fRight > fRight)
+ fRight = other.fRight;
+
+ if (other.fBottom > fBottom)
+ fBottom = other.fBottom;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+void
+EmRectTempl<coord>::Normalize (void)
+{
+ coord temp;
+
+ if (fBottom < fTop)
+ {
+ temp = fBottom;
+ fBottom = fTop;
+ fTop = temp;
+ }
+
+ if (fRight < fLeft)
+ {
+ temp = fRight;
+ fRight = fLeft;
+ fLeft = temp;
+ }
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator+ (const EmPointTempl<coord>& pt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.Offset (pt.fX, pt.fY);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator- (const EmPointTempl<coord>& pt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.Offset (-pt.fX, -pt.fY);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator+= (const EmPointTempl<coord>& pt)
+{
+ this->Offset (pt.fX, pt.fY);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator-= (const EmPointTempl<coord>& pt)
+{
+ this->Offset (-pt.fX, -pt.fY);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator* (const EmPointTempl<coord>& pt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.ScaleUp (pt.fX, pt.fY);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator/ (const EmPointTempl<coord>& pt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.ScaleDown (pt.fX, pt.fY);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator*= (const EmPointTempl<coord>& pt)
+{
+ this->ScaleUp (pt.fX, pt.fY);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator/= (const EmPointTempl<coord>& pt)
+{
+ this->ScaleDown (pt.fX, pt.fY);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::operator== (const EmRectTempl<coord>& rt) const
+{
+ return this->IsEqual (rt);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+Bool
+EmRectTempl<coord>::operator!= (const EmRectTempl<coord>& rt) const
+{
+ return !this->IsEqual (rt);
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator& (const EmRectTempl<coord>& rt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.IntersectWith (rt);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>
+EmRectTempl<coord>::operator| (const EmRectTempl<coord>& rt) const
+{
+ EmRectTempl<coord> result (*this);
+ result.UnionWith (rt);
+ return result;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator&= (const EmRectTempl<coord>& rt)
+{
+ this->IntersectWith (rt);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+template <class coord>
+EmRectTempl<coord>&
+EmRectTempl<coord>::operator|= (const EmRectTempl<coord>& rt)
+{
+ this->UnionWith (rt);
+ return *this;
+}
+
+// ----------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4660) // template-class specialization is already instatiated
+#endif
+
+template class EmRectTempl<EmCoord>;
+
+
+// ----------------------------------------------------------------------
+// Psuedo-type definitions to aid in the conversion process without
+// actually having to #include the requisite headers.
+// ----------------------------------------------------------------------
+
+#ifndef _WINDEF_
+struct tagRECT { char _[16]; };
+#endif
+
+#ifndef __AFXWIN_H__
+class CRect { char _[16]; };
+#endif
+
+#ifndef __MACTYPES__
+struct Rect { char _[ 8]; };
+#endif
+
+struct VRect { char _[16]; };
+
+// ----------------------------------------------------------------------
+// * EmRect
+// ----------------------------------------------------------------------
+
+//
+// Construct from another kind of rectangle
+// Assigned from another kind of rectangle
+//
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, r, b) \
+ EmRect::EmRect(const cls& rt) : \
+ EmRectTempl<EmCoord>(((size*)&rt)[l], ((size*)&rt)[t], ((size*)&rt)[r], ((size*)&rt)[b]) {} \
+ const EmRect& EmRect::operator= (const cls& rt) \
+ { fLeft = ((size*)&rt)[l]; fTop = ((size*)&rt)[t]; fRight = ((size*)&rt)[r]; fBottom = ((size*)&rt)[b]; return *this; }
+
+ RECT_LIST_XY_SHORT
+ RECT_LIST_XY_LONG
+ RECT_LIST_YX_SHORT
+ RECT_LIST_YX_LONG
+
+//
+// Return another kind of rectangle
+//
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, r, b) \
+ EmRect::operator cls () const \
+ { size pt[4]; pt[l] = fLeft; pt[t] = fTop; pt[r] = fRight; pt[b] = fBottom; return *(cls*) pt; }
+
+ RECT_LIST_XY_LONG
+ RECT_LIST_YX_LONG
+ RECT_LIST_XY_SHORT
+ RECT_LIST_YX_SHORT
+
+//
+// Return a [const] (* | &) to another kind of rectangle
+//
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, r, b) \
+ EmRect::operator const cls*() const \
+ { return (const cls*) this; } \
+ EmRect::operator cls*() \
+ { return (cls*) this; } \
+ EmRect::operator const cls&() const \
+ { return *(const cls*) this; } \
+ EmRect::operator cls&() \
+ { return *(cls*) this; }
+
+ RECT_LIST_LONG
+
+//#define TESTING
+#ifdef TESTING
+// ----------------------------------------------------------------------
+#include "stdio.h"
+void TestRect();
+void TestRect()
+{
+ printf("Testing EmRectTempl class...\n");
+
+ {
+ //
+ // Constructor (coords)
+ //
+ EmRect rect1(1, 2, 3, 4);
+ EmAssert(rect1.fLeft == 1);
+ EmAssert(rect1.fTop == 2);
+ EmAssert(rect1.fRight == 3);
+ EmAssert(rect1.fBottom == 4);
+
+ //
+ // Constructor (points)
+ //
+ EmRect rect2(EmPoint(2, 4), EmPoint(6, 8));
+ EmAssert(rect2.fLeft == 2);
+ EmAssert(rect2.fTop == 4);
+ EmAssert(rect2.fRight == 6);
+ EmAssert(rect2.fBottom == 8);
+
+ //
+ // Constructor (copy)
+ //
+ EmRect rect3(rect2);
+ EmAssert(rect3.fLeft == 2);
+ EmAssert(rect3.fTop == 4);
+ EmAssert(rect3.fRight == 6);
+ EmAssert(rect3.fBottom == 8);
+
+ //
+ // Assignment
+ //
+ EmRect rect4;
+ rect4 = rect2;
+ EmAssert(rect4.fLeft == 2);
+ EmAssert(rect4.fTop == 4);
+ EmAssert(rect4.fRight == 6);
+ EmAssert(rect4.fBottom == 8);
+
+ //
+ // Equality
+ //
+ EmAssert(rect1 == rect1);
+ EmAssert(!(rect1 != rect1));
+ EmAssert(rect1 != rect2);
+ EmAssert(!(rect1 == rect2));
+ EmAssert(rect2 == rect3);
+ EmAssert(!(rect2 != rect3));
+
+ EmAssert(rect1.IsEqual(rect1));
+ EmAssert(!rect1.IsEqual(rect2));
+ EmAssert(rect2.IsEqual(rect3));
+
+ //
+ // Width / height
+ //
+ EmAssert(rect1.Width() == 3 - 1);
+ EmAssert(rect2.Width() == 6 - 2);
+ EmAssert(rect1.Height() == 4 - 2);
+ EmAssert(rect2.Height() == 8 - 4);
+
+ //
+ // Size
+ //
+#ifndef forWin32
+ EmAssert(rect1.Size() == EmPoint(3 - 1, 4 - 2));
+ EmAssert(rect2.Size() == EmPoint(6 - 2, 8 - 4));
+#endif
+
+ //
+ // Top / left / bottom / right
+ //
+ EmAssert(rect1.TopLeft() == EmPoint(1, 2));
+ EmAssert(rect2.TopLeft() == EmPoint(2, 4));
+ EmAssert(rect1.TopRight() == EmPoint(3, 2));
+ EmAssert(rect2.TopRight() == EmPoint(6, 4));
+ EmAssert(rect1.BottomLeft() == EmPoint(1, 4));
+ EmAssert(rect2.BottomLeft() == EmPoint(2, 8));
+ EmAssert(rect1.BottomRight() == EmPoint(3, 4));
+ EmAssert(rect2.BottomRight() == EmPoint(6, 8));
+
+ //
+ // N / S / E / W / Center
+ //
+ EmAssert(rect1.North() == EmPoint(2, 2));
+ EmAssert(rect2.North() == EmPoint(4, 4));
+ EmAssert(rect1.South() == EmPoint(2, 4));
+ EmAssert(rect2.South() == EmPoint(4, 8));
+ EmAssert(rect1.West() == EmPoint(1, 3));
+ EmAssert(rect2.West() == EmPoint(2, 6));
+ EmAssert(rect1.East() == EmPoint(3, 3));
+ EmAssert(rect2.East() == EmPoint(6, 6));
+ EmAssert(rect1.Center() == EmPoint(2, 3));
+ EmAssert(rect2.Center() == EmPoint(4, 6));
+
+ //
+ // Empty / Null
+ //
+ EmRect rect5(5, 5, 5, 5);
+ EmRect rect6(0, 0, 0, 0);
+
+ EmAssert(rect5.IsEmpty());
+ EmAssert(!rect5.IsNull());
+ EmAssert(rect6.IsEmpty());
+ EmAssert(rect6.IsNull());
+ EmAssert(!rect2.IsEmpty());
+ EmAssert(!rect2.IsNull());
+
+ {
+ //
+ // Contains (point)
+ //
+ EmPoint pt1(0, 0);
+ EmPoint pt2(3, 0);
+ EmPoint pt3(6, 0);
+ EmPoint pt4(0, 6);
+ EmPoint pt5(3, 6);
+ EmPoint pt6(6, 6);
+ EmPoint pt7(0, 12);
+ EmPoint pt8(3, 12);
+ EmPoint pt9(6, 12);
+
+ EmAssert(!rect2.Contains(pt1));
+ EmAssert(!rect2.Contains(pt2));
+ EmAssert(!rect2.Contains(pt3));
+
+ EmAssert(!rect2.Contains(pt4));
+ EmAssert(rect2.Contains(pt5));
+ EmAssert(!rect2.Contains(pt6));
+
+ EmAssert(!rect2.Contains(pt7));
+ EmAssert(!rect2.Contains(pt8));
+ EmAssert(!rect2.Contains(pt9));
+
+ EmAssert(rect2.Contains(rect2.TopLeft()));
+ EmAssert(rect2.Contains(rect2.North()));
+ EmAssert(!rect2.Contains(rect2.TopRight()));
+
+ EmAssert(rect2.Contains(rect2.West()));
+ EmAssert(rect2.Contains(rect2.Center()));
+ EmAssert(!rect2.Contains(rect2.East()));
+
+ EmAssert(!rect2.Contains(rect2.BottomLeft()));
+ EmAssert(!rect2.Contains(rect2.South()));
+ EmAssert(!rect2.Contains(rect2.BottomRight()));
+ }
+
+ {
+ //
+ // Contains (rect)
+ //
+ rect4 = rect2;
+ EmAssert( rect2.Contains(rect4));
+ EmAssert( rect4.Contains(rect2));
+
+ rect4.fTop--;
+ EmAssert(!rect2.Contains(rect4));
+ EmAssert( rect4.Contains(rect2));
+
+ rect4.fTop += 2;
+ EmAssert( rect2.Contains(rect4));
+ EmAssert(!rect4.Contains(rect2));
+
+ rect4 = rect2;
+ rect4.fLeft--;
+ EmAssert(!rect2.Contains(rect4));
+ EmAssert( rect4.Contains(rect2));
+
+ rect4.fLeft += 2;
+ EmAssert( rect2.Contains(rect4));
+ EmAssert(!rect4.Contains(rect2));
+
+ rect4 = rect2;
+ rect4.fBottom++;
+ EmAssert(!rect2.Contains(rect4));
+ EmAssert( rect4.Contains(rect2));
+
+ rect4.fBottom -= 2;
+ EmAssert( rect2.Contains(rect4));
+ EmAssert(!rect4.Contains(rect2));
+
+ rect4 = rect2;
+ rect4.fRight++;
+ EmAssert(!rect2.Contains(rect4));
+ EmAssert( rect4.Contains(rect2));
+
+ rect4.fRight -= 2;
+ EmAssert( rect2.Contains(rect4));
+ EmAssert(!rect4.Contains(rect2));
+ }
+
+ {
+ //
+ // Intersects
+ //
+ EmRect rect(100, 200, 300, 400);
+
+ /*
+ 0 50 100 200 300 350 400
+ 0 +-------------------+--------------------+--------------------+
+ | | | |
+ | | | |
+ | | | |
+ 100 | 0 * 1 * 2 |
+ | | | |
+ | | | |
+ | | | |
+ 200 +---------*---------*----------*---------*----------*---------+
+ | | | |
+ | | | |
+ | | | |
+ 300 | 3 * 4 * 5 |
+ | | | |
+ | | | |
+ | | | |
+ 400 +---------*---------*----------*---------*----------*---------+
+ | | | |
+ | | | |
+ | | | |
+ 500 | 6 * 7 * 8 |
+ | | | |
+ | | | |
+ | | | |
+ 600 +-------------------+--------------------+--------------------+
+
+ */
+
+ EmCoord xCoords[] = {
+ 0, 50, 100, 101, 200, 300, 301, 350, 400
+ };
+
+ EmCoord yCoords[] = {
+ 0,
+ 100,
+ 200,
+
+ 201,
+ 300,
+ 400,
+
+ 401,
+ 500,
+ 600
+ };
+
+ #define neither -1
+
+ char results[9][9] = {
+ false, false, false,
+ false, true, true,
+ false, true, true,
+
+ neither, false, false,
+ neither, true, true,
+ neither, true, true,
+
+ neither, neither, false,
+ neither, neither, false,
+ neither, neither, false,
+
+ neither, neither, neither,
+ false, true, true,
+ false, true, true,
+
+ neither, neither, neither,
+ neither, true, true,
+ neither, true, true,
+
+ neither, neither, neither,
+ neither, neither, false,
+ neither, neither, false,
+
+ neither, neither, neither,
+ neither, neither, neither,
+ false, false, false,
+
+ neither, neither, neither,
+ neither, neither, neither,
+ neither, false, false,
+
+ neither, neither, neither,
+ neither, neither, neither,
+ neither, neither, false,
+
+ };
+
+ for (int y1 = 0; y1 < 9; y1++)
+ {
+ for (int x1 = 0; x1 < 9; x1++)
+ {
+ for (int y2 = 0; y2 < 9; y2++)
+ {
+ for (int x2 = 0; x2 < 9; x2++)
+ {
+ int qx1 = xCoords[x1] >= 300 ? 2 : xCoords[x1] >= 100 ? 1 : 0;
+ int qy1 = yCoords[y1] >= 400 ? 2 : yCoords[y1] >= 200 ? 1 : 0;
+
+ int qx2 = xCoords[x2] <= 100 ? 0 : xCoords[x2] <= 300 ? 1 : 2;
+ int qy2 = yCoords[y2] <= 200 ? 0 : yCoords[y2] <= 400 ? 1 : 2;
+
+ int q1 = qy1 * 3 + qx1;
+ int q2 = qy2 * 3 + qx2;
+
+ if (results[q1][q2] != neither)
+ {
+ EmRect testRect(xCoords[x1], yCoords[y1], xCoords[x2], yCoords[y2]);
+ testRect.Normalize();
+
+ if (rect.Intersects(testRect) != results[q1][q2])
+ {
+ printf("rect (%d, %d, %d, %d) %s rect (%d, %d, %d, %d)\n",
+ rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+ rect.Intersects(testRect) ? "intersects" : "does not intersect",
+ testRect.fLeft, testRect.fTop, testRect.fRight, testRect.fBottom);
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ {
+ //
+ // Set(coords) / Set(point) / BeEmpty
+ //
+ EmRect rect;
+
+ rect.Set(1, 2, 3, 4);
+ EmAssert(rect.fLeft == 1);
+ EmAssert(rect.fTop == 2);
+ EmAssert(rect.fRight == 3);
+ EmAssert(rect.fBottom == 4);
+
+ rect.Set(EmPoint(2, 4), EmPoint(6, 8));
+ EmAssert(rect.fLeft == 2);
+ EmAssert(rect.fTop == 4);
+ EmAssert(rect.fRight == 6);
+ EmAssert(rect.fBottom == 8);
+
+ rect.BeEmpty();
+ EmAssert(rect.IsEmpty());
+
+ rect.Set(10, 20, 30, 40);
+ rect.Inset(6, 12);
+ EmAssert(rect.fLeft == 10 + 6);
+ EmAssert(rect.fTop == 20 + 12);
+ EmAssert(rect.fRight == 30 - 6);
+ EmAssert(rect.fBottom == 40 - 12);
+
+ rect.Set(10, 20, 30, 40);
+ rect.Offset(6, 12);
+ EmAssert(rect.fLeft == 10 + 6);
+ EmAssert(rect.fTop == 20 + 12);
+ EmAssert(rect.fRight == 30 + 6);
+ EmAssert(rect.fBottom == 40 + 12);
+ }
+
+ {
+ // Intersect
+
+ EmRect rect(100, 200, 300, 400);
+
+ EmRect rect1(0, 0, 0, 0);
+ rect1.IntersectWith(rect);
+ EmAssert(rect1.IsEmpty());
+
+ EmRect rect2(0, 0, 100, 200);
+ rect2.IntersectWith(rect);
+ EmAssert(rect2.IsEmpty());
+
+ EmRect rect3(0, 0, 200, 300);
+ rect3.IntersectWith(rect);
+ EmAssert(rect3 == EmRect(100, 200, 200, 300));
+ }
+
+ {
+ // !!! Union
+ }
+
+ {
+ //
+ // Normalize
+ //
+
+ EmRect rect(0, 1, 2, 3);
+
+ EmRect rect1(0, 1, 2, 3);
+ rect1.Normalize();
+ EmAssert(rect1 == rect);
+
+ EmRect rect2(2, 1, 0, 3);
+ rect2.Normalize();
+ EmAssert(rect2 == rect);
+
+ EmRect rect3(0, 3, 2, 1);
+ rect3.Normalize();
+ EmAssert(rect3 == rect);
+
+ EmRect rect4(2, 3, 0, 1);
+ rect4.Normalize();
+ EmAssert(rect4 == rect);
+ }
+
+ // !!! Need to test all the constructors and conversion operators
+ }
+}
+#endif
diff --git a/SrcShared/EmRect.h b/SrcShared/EmRect.h
new file mode 100644
index 0000000..efffda8
--- /dev/null
+++ b/SrcShared/EmRect.h
@@ -0,0 +1,389 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRect_h
+#define EmRect_h
+
+/*
+ Contains classes for working with rectangles:
+
+ EmRectTempl<coord>: Generic template class. The type of rectangle
+ coordinate is provided by the client.
+
+ EmRect: Specific specialization of EmRectTempl for EmCoord.
+
+ For flexibility, the x/y ordering of coordinates within the object
+ is controlled by the XYRect pre-processor symbol. Choosing a
+ particular order enables certain conversion operations; choosing the
+ other order enables other conversion operations. For instance, when
+ using long coordinates and XY ordering, we can produce a RECT*
+ (Win32 rect), but not a VRect* (MacApp rect).
+
+ EmRect offers no new operations. What it does offer is constructors
+ for creation from a platform-specific rectangle (like Rect, RECT, CRect,
+ or VRect) or for producing some variant of a platform-specific
+ rectangle. The different kinds of rects that EmRect attempts to convert
+ to/from are:
+
+ RECT Rect
+ CRect VRect
+
+ Where possible, EmRect produces pointers, const pointers, references,
+ and const references to the above types.
+
+ Note that there are no virtual functions. These rect classes are
+ not intended to be used polymorphically.
+*/
+
+#include "EmPoint.h" // EmPoint
+
+#if PLATFORM_WINDOWS
+ #define XYRect 1
+#else
+ #define XYRect 0
+#endif
+
+#undef topLeft
+
+template <class coord>
+class EmRectTempl
+{
+ public:
+ EmRectTempl ()
+ {}
+ EmRectTempl (coord left, coord top, coord right, coord bottom) :
+#if XYRect
+ fLeft (left),
+ fTop (top),
+ fRight (right),
+ fBottom (bottom)
+#else
+ fTop (top),
+ fLeft (left),
+ fBottom (bottom),
+ fRight (right)
+#endif
+ {}
+ EmRectTempl (const EmPointTempl<coord>& topLeft, const EmPointTempl<coord>& bottomRight) :
+#if XYRect
+ fLeft (topLeft.fX),
+ fTop (topLeft.fY),
+ fRight (bottomRight.fX),
+ fBottom (bottomRight.fY)
+#else
+ fTop (topLeft.fY),
+ fLeft (topLeft.fX),
+ fBottom (bottomRight.fY),
+ fRight (bottomRight.fX)
+#endif
+ {}
+ EmRectTempl (const EmRectTempl<coord>& other) :
+#if XYRect
+ fLeft (other.fLeft),
+ fTop (other.fTop),
+ fRight (other.fRight),
+ fBottom (other.fBottom)
+#else
+ fTop (other.fTop),
+ fLeft (other.fLeft),
+ fBottom (other.fBottom),
+ fRight (other.fRight)
+#endif
+ {}
+
+// ~EmRectTempl() {};
+ // Constructors/Destructor. The default constructor doesn't do anything,
+ // including setting its members to zero. There is no destructor to cut
+ // down on the amount of code generated for this lightweight class.
+
+ coord Width (void) const;
+ coord Height (void) const;
+ // Return the width and height of the rectangle. The return type
+ // is the same as the coordinate type.
+
+ EmPointTempl<coord> Size (void) const;
+ // Return the size of the rectangle. The return type is an
+ // EmPointTempl<coord> with the same type as the coordinate type.
+
+ EmPointTempl<coord> TopLeft (void) const;
+ EmPointTempl<coord> TopRight (void) const;
+ EmPointTempl<coord> BottomLeft (void) const;
+ EmPointTempl<coord> BottomRight (void) const;
+ EmPointTempl<coord> North (void) const;
+ EmPointTempl<coord> South (void) const;
+ EmPointTempl<coord> East (void) const;
+ EmPointTempl<coord> West (void) const;
+ EmPointTempl<coord> Center (void) const;
+ // Return the following marked points of a rectangle. The return
+ // type is an EmPointTempl<coord> with the same type as the coordinate
+ // type.
+ // North
+ // TopLeft X-----X-----X TopRight
+ // | |
+ // | |
+ // West X X X East
+ // | Ctr |
+ // | |
+ // BottomLeft X-----X-----X BottomRight
+ // South
+
+ Bool IsEmpty (void) const;
+ // Returns whether or not the rectangle contains positive area. The
+ // coordinates do not necessarily have to be zero.
+
+ Bool IsNull (void) const;
+ // Returns whether or not all four coordinates are zero.
+
+ Bool IsEqual (const EmRectTempl<coord>& other) const;
+ // Returns whether or not two rectangles have the same coordinates.
+ // Same as operator==().
+
+ Bool Contains (const EmPointTempl<coord>&) const;
+ Bool Contains (const EmRectTempl<coord>&) const;
+ // Returns whether or not the given point or rectangle is contained
+ // by the rectangle. Comparisons are made on a half-open interval.
+
+ Bool Intersects (const EmRectTempl<coord>&) const;
+ // Returns whether or not the two rectangles intersect each other.
+
+ void Set (coord left, coord top, coord right, coord bottom);
+ void Set (const EmPointTempl<coord>& topLeft, const EmPointTempl<coord>& bottomRight);
+ // Set the coordinates of an already created rectangle. Performs
+ // essentially the same operation as the constructors.
+
+ void BeEmpty (void);
+ // Set all four coordinates to zero. Technically, I supposed this
+ // is a "SetNull" operation, but a future implementation could
+ // conceivably just set fRight to fLeft.
+
+ void Inset (coord x, coord y);
+ // Inset the four coordinates by the given amounts.
+
+ void Offset (coord x, coord y);
+ // Add x and y to the rects's coordinates. Same as operator+=()
+ // except that you specify coordinates, not another point.
+
+ void ScaleUp (coord x, coord y);
+ // Multiply the rects's coordinates by x and y. Same as operator*=()
+ // except that you specify coordinates, not another point.
+
+ void ScaleDown (coord x, coord y);
+ // Divide the rects's coordinates by x and y. Same as operator/=()
+ // except that you specify coordinates, not another point.
+
+ void IntersectWith(const EmRectTempl<coord>& other);
+ // Intersect *this with other, storing the result in *this.
+ // If other is an empty rectangle, *this will end up being an
+ // empty rectangle, but no other guarantee is made about its
+ // coordinates.
+
+ void UnionWith (const EmRectTempl<coord>& other);
+ // Union *this with other, storing the result in *this.
+ // Empty rectangles are ignored (i.e., if *this is an empty
+ // rectangle, other is copied into *this. If other is an empty
+ // rectangle, *this is unchanged).
+
+ void ExtendTo (const EmPointTempl<coord>& pt);
+ void ExtendTo (const EmRectTempl<coord>& other);
+ // Extend *this to contain the points expressed by the given
+ // point or rectangle. The version taking a rectangle is similar
+ // to UnionWith, the difference being that empty rectangles are
+ // not ignored.
+
+ void Normalize (void);
+ // Order the coordinates such that fLeft <= fRight and fTop
+ // <= fBottom.
+
+ EmRectTempl<coord> operator+ (const EmPointTempl<coord>& pt) const;
+ EmRectTempl<coord> operator- (const EmPointTempl<coord>& pt) const;
+ EmRectTempl<coord>& operator+= (const EmPointTempl<coord>& pt);
+ EmRectTempl<coord>& operator-= (const EmPointTempl<coord>& pt);
+ // Offset the rectangle by the amounts indicated by the EmPointTempl
+ // parameter. The first two methods return a new EmRectTempl, leaving
+ // the original untouched. The second two alter the original
+ // rectangle in-place.
+
+ EmRectTempl<coord> operator* (const EmPointTempl<coord>& pt) const;
+ EmRectTempl<coord> operator/ (const EmPointTempl<coord>& pt) const;
+ EmRectTempl<coord>& operator*= (const EmPointTempl<coord>& pt);
+ EmRectTempl<coord>& operator/= (const EmPointTempl<coord>& pt);
+ // Scale the rectangle by the amounts indicated by the EmPointTempl
+ // parameter. The first two methods return a new EmRectTempl, leaving
+ // the original untouched. The second two alter the original
+ // rectangle in-place.
+
+ Bool operator== (const EmRectTempl<coord>& rt) const;
+ Bool operator!= (const EmRectTempl<coord>& rt) const;
+ // (In)equality operators. Returns whether or not the coordinates
+ // of the two rectangles are equal to each other.
+
+ EmRectTempl<coord> operator& (const EmRectTempl<coord>& rt) const; // Intersection
+ EmRectTempl<coord> operator| (const EmRectTempl<coord>& rt) const; // Union
+ EmRectTempl<coord>& operator&= (const EmRectTempl<coord>& rt);
+ EmRectTempl<coord>& operator|= (const EmRectTempl<coord>& rt);
+ // Synonyms for Intersect and Union, respectively. The first
+ // two operators return the result in a new EmRectTempl. The second
+ // pair of operators alter the target rectangle in-place.
+
+ // Directly accessible data members.
+#if XYRect
+ coord fLeft;
+ coord fTop;
+ coord fRight;
+ coord fBottom;
+#else
+ coord fTop;
+ coord fLeft;
+ coord fBottom;
+ coord fRight;
+#endif
+};
+
+
+// ----------------------------------------------------------------------
+// Types we interoperate with
+// ----------------------------------------------------------------------
+
+struct tagRECT;
+typedef struct tagRECT RECT;
+class CRect;
+
+struct Rect;
+struct VRect;
+
+
+/* ----------------------------------------------------------------------
+ Macros to help with creating the massive number of constructors and
+ conversion operators we support:
+
+ RECT_LIST_XY_SHORT: List of rect-types using x/y coordinate
+ ordering and short coordinates.
+
+ RECT_LIST_XY_LONG: List of rect-types using x/y coordinate
+ ordering and long coordinates.
+
+ RECT_LIST_YX_SHORT: List of rect-types using y/x coordinate
+ ordering and short coordinates.
+
+ RECT_LIST_YX_LONG: List of rect-types using y/x coordinate
+ ordering and long coordinates.
+
+ RECT_LIST_SHORT: List of rect-types using short coordinates.
+ Only rect-types using the same x/y ordering
+ as indicated by XYRect are included.
+
+ RECT_LIST_LONG: List of rect-types using long coordinates.
+ Only point-types using the same x/y ordering
+ as indicated by XYRect are included.
+
+ Each of the above lists includes a reference to a rect-type using a
+ FOR_RECT macro. The FOR_RECT macro takes as parameters the
+ rect-type, the size of coordinates, and offsets to each coordinate.
+ This information is all that's needed for constructing all of
+ constructors and convertion operators, both declarations and
+ implementations. To perform the actual construction, FOR_RECT is
+ defined to expand to the appropriate code for a single constructor
+ or conversion, and then the appropriate RECT_LIST macro from above
+ is "invoked" to expand the list as needed.
+ ---------------------------------------------------------------------- */
+
+#define RECT_LIST_XY_SHORT \
+ FOR_RECT(AbsRectType, short, 0, 1, 2, 3)
+
+#define RECT_LIST_XY_LONG \
+ FOR_RECT(RECT, long, 0, 1, 2, 3) \
+ FOR_RECT(CRect, long, 0, 1, 2, 3)
+
+#define RECT_LIST_YX_SHORT \
+ FOR_RECT(Rect, short, 1, 0, 3, 2)
+
+#define RECT_LIST_YX_LONG \
+ FOR_RECT(VRect, long, 1, 0, 3, 2)
+
+#if XYRect
+ #define RECT_LIST_LONG RECT_LIST_XY_LONG
+ #define RECT_LIST_SHORT RECT_LIST_XY_SHORT
+#else
+ #define RECT_LIST_LONG RECT_LIST_YX_LONG
+ #define RECT_LIST_SHORT RECT_LIST_YX_SHORT
+#endif
+
+// ----------------------------------------------------------------------
+// * EmRect
+// ----------------------------------------------------------------------
+
+class EmRect : public EmRectTempl<EmCoord>
+{
+ public:
+ EmRect ()
+ {}
+ EmRect (EmCoord left, EmCoord top, EmCoord right, EmCoord bottom) :
+ EmRectTempl<EmCoord> (left, top, right, bottom)
+ {}
+ EmRect (const RectangleType& r) :
+ EmRectTempl<EmCoord> ( r.topLeft.x, r.topLeft.y,
+ r.topLeft.x + r.extent.x,
+ r.topLeft.y + r.extent.y)
+ {}
+ EmRect (const EmPointTempl<EmCoord>& topLeft, const EmPointTempl<EmCoord>& bottomRight) :
+ EmRectTempl<EmCoord>(topLeft, bottomRight)
+ {}
+ EmRect (const EmRectTempl<EmCoord>& r) :
+ EmRectTempl<EmCoord>(r)
+ {}
+
+// ~EmRect() {};
+
+ //
+ // Construct from another kind of rectangle
+ // Assigned from another kind of rectangle
+ // !!! Move functionality inline?
+ //
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, b, r) \
+ EmRect (const cls&); \
+ const EmRect& operator= (const cls&);
+
+ RECT_LIST_XY_SHORT
+ RECT_LIST_XY_LONG
+ RECT_LIST_YX_SHORT
+ RECT_LIST_YX_LONG
+
+ //
+ // Return another kind of rectangle
+ // !!! Move functionality inline?
+ //
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, b, r) \
+ operator cls () const;
+
+ RECT_LIST_XY_LONG
+ RECT_LIST_YX_LONG
+ RECT_LIST_XY_SHORT
+ RECT_LIST_YX_SHORT
+
+ //
+ // Return a [const] (* | &) to another kind of rectangle
+ // !!! Move functionality inline?
+ //
+ #undef FOR_RECT
+ #define FOR_RECT(cls, size, l, t, b, r) \
+ operator const cls* () const; \
+ operator cls* (); \
+ operator const cls& () const; \
+ operator cls& ();
+
+ RECT_LIST_LONG
+};
+
+#endif // EmRect_h
diff --git a/SrcShared/EmRefCounted.cpp b/SrcShared/EmRefCounted.cpp
new file mode 100644
index 0000000..ec917a1
--- /dev/null
+++ b/SrcShared/EmRefCounted.cpp
@@ -0,0 +1,15 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRefCounted.h"
diff --git a/SrcShared/EmRefCounted.h b/SrcShared/EmRefCounted.h
new file mode 100644
index 0000000..3282fe0
--- /dev/null
+++ b/SrcShared/EmRefCounted.h
@@ -0,0 +1,278 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRefCounted_h
+#define EmRefCounted_h
+
+/*
+ EmRefCounted is a base class for any other class that you wish to be
+ reference counted. Simply descend from this guy; you don't have to
+ override any members.
+
+ EmRefCounter is a class for managing RefCounted objects. It takes care
+ of the tedious details of adding and removing refcounts, cloning the
+ object if necessary (if the object is marked unshareable).
+
+ See EmRegion's implementation for an example of this class's use. In
+ general, it's pretty simple:
+
+ {
+ EmRefCounter owner1(CreateRefCountedObject()); // One owner
+ EmRefCounter owner2 = owner1; // Two owners
+ {
+ EmRefCounter owner3 = owner1; // Three owners
+ }
+ // Back down to two owners here
+ }
+ // No more owners, the internal object is destroyed.
+
+ This class is based on the discussion by Scott Meyers in one of his
+ "More Effective C++" books.
+*/
+
+class EmRefCounted
+{
+ public:
+ EmRefCounted (void);
+ EmRefCounted (const EmRefCounted& copy);
+ virtual ~EmRefCounted (void);
+
+ EmRefCounted& operator= (const EmRefCounted& other);
+ // Override of the assignment operator to prevent the refcount
+ // from being transferred from the rhs object.
+
+ void addReference (void);
+ void removeReference (void);
+ // Add or remove a reference to the object. Attempting to
+ // add a reference to an unshareable object is an error; an
+ // assertion will be thrown. Removing the last reference to
+ // an object will cause that object to delete itself.
+
+ void markUnshareable (void);
+ Bool isShareable (void) const;
+ Bool isShared (void) const;
+ // Marking an object unshareable is a signal to the client/owner
+ // of the RefCounted class that this object should not have
+ // addReference() called on it. Instead, the object should be
+ // cloned (EmRefCounter respects this convention). Call isShareable
+ // to see if the object can be shared. Call IsShared to see if
+ // more than one client is pointing to this object.
+
+ private:
+ long fRefCount;
+};
+
+template <class T>
+class EmRefCounter
+{
+ public:
+ EmRefCounter (T* p);
+ EmRefCounter (const EmRefCounter& other);
+ ~EmRefCounter (void);
+
+ EmRefCounter<T>& operator= (const EmRefCounter& other);
+ EmRefCounter<T>& operator= (T* p);
+ // Methods for assuming (shared) ownership of a refcounted
+ // object. If the object does not descend from EmRefCounted,
+ // you'll get a compiler error.
+
+ int operator== (const EmRefCounter& other) const;
+ // See if the internal objects are equal to each other.
+
+ T* operator-> (void) const;
+ T& operator* (void) const;
+ T* get (void) const;
+ // Ways of getting to the internal object.
+
+ private:
+ EmRefCounter (void);
+ void Init (void);
+ void Replace (T*);
+
+ T* fObject;
+};
+
+// ----------------------------------------------------------------------
+
+inline
+EmRefCounted::EmRefCounted (void) :
+ fRefCount (0)
+{
+}
+
+inline
+EmRefCounted::EmRefCounted (const EmRefCounted&) :
+ fRefCount (0)
+{
+}
+
+inline
+EmRefCounted::~EmRefCounted (void)
+{
+}
+
+inline
+EmRefCounted&
+EmRefCounted::operator= (const EmRefCounted&)
+{
+ return *this;
+}
+
+inline
+void
+EmRefCounted::addReference (void)
+{
+ EmAssert(fRefCount >= 0); // Can't add a reference to an unshareable item
+
+ fRefCount++;
+}
+
+inline
+void
+EmRefCounted::removeReference (void)
+{
+ if (--fRefCount <= 0)
+ delete this;
+}
+
+inline
+void
+EmRefCounted::markUnshareable (void)
+{
+ fRefCount = -1;
+}
+
+inline
+Bool
+EmRefCounted::isShareable (void) const
+{
+ return fRefCount >= 0;
+}
+
+inline
+Bool
+EmRefCounted::isShared (void) const
+{
+ return fRefCount > 0;
+}
+
+// ----------------------------------------------------------------------
+
+template <class T>
+EmRefCounter<T>::EmRefCounter (void) :
+ fObject (NULL)
+{
+ this->Init ();
+}
+
+template <class T>
+EmRefCounter<T>::EmRefCounter (T* p) :
+ fObject (p)
+{
+ this->Init ();
+}
+
+template <class T>
+EmRefCounter<T>::EmRefCounter (const EmRefCounter& other) :
+ fObject (other.fObject)
+{
+ this->Init ();
+}
+
+template <class T>
+EmRefCounter<T>::~EmRefCounter ()
+{
+ if (fObject)
+ fObject->removeReference ();
+}
+
+template <class T>
+EmRefCounter<T>&
+EmRefCounter<T>::operator= (const EmRefCounter& other)
+{
+ this->Replace (other.fObject);
+ return *this;
+}
+
+template <class T>
+EmRefCounter<T>&
+EmRefCounter<T>::operator= (T* p)
+{
+ this->Replace (p);
+ return *this;
+}
+
+template <class T>
+int
+EmRefCounter<T>::operator== (const EmRefCounter& other) const
+{
+ if (this == &other)
+ return true;
+
+ if (this->fObject == other.fObject)
+ return true;
+
+ return *(this->fObject) == *(other.fObject);
+}
+
+template <class T>
+T*
+EmRefCounter<T>::operator-> (void) const
+{
+ return fObject;
+}
+
+template <class T>
+T&
+EmRefCounter<T>::operator* (void) const
+{
+ return *fObject;
+}
+
+template <class T>
+T*
+EmRefCounter<T>::get (void) const
+{
+ return fObject;
+}
+
+template <class T>
+void
+EmRefCounter<T>::Init ()
+{
+ if (fObject)
+ {
+ if (!fObject->isShareable ())
+ {
+ fObject = new T (*fObject);
+ }
+
+ fObject->addReference ();
+ }
+}
+
+template <class T>
+void
+EmRefCounter<T>::Replace (T* p)
+{
+ if (fObject != p)
+ {
+ if (fObject)
+ fObject->removeReference ();
+
+ fObject = p;
+ Init ();
+ }
+}
+
+#endif // EmRefCounted_h
diff --git a/SrcShared/EmRegion.cpp b/SrcShared/EmRegion.cpp
new file mode 100644
index 0000000..d811ef2
--- /dev/null
+++ b/SrcShared/EmRegion.cpp
@@ -0,0 +1,1500 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegion.h"
+
+/*
+ See .h file for usage.
+
+ EmRegion relies on an internal helper class, EmRegionImpl. EmRegionImpl
+ is a ref-counted implementation class. It can be shared among multiple
+ ARegions for efficient copying. If one region is altered, it creates
+ a new EmRegionImpl to contain the results, dropping the reference to
+ the previous EmRegionImpl (possibly causing it to be deleted).
+
+ EmRegionImpl provides basic operations on regions. It stores region
+ data in a buffer of ACoords in the following format:
+
+ <number of transition points in this scanline>
+ <y coordinate of scanline>
+ <x coordinate of "enter region" event>
+ <x coordinate of "exit region" event>
+ ...
+ <number of transition points in this scanline>
+ <y coordinate of scanline>
+ <x coordinate of "enter region" event>
+ <x coordinate of "exit region" event>
+ ...
+ ...
+ <number of points in this scanline>
+ <y coordinate of scanline>
+ <End of region marker>
+
+ For example, take the following region:
+
+
+ | 5 10 15 20 25 30
+ ----+-----|-----|-----|-----|-----|-----|-----
+ |
+ |
+ 5 - +-----+ +-----+
+ | |.....| |.....|
+ | |.....| |.....|
+ 10 - |.....+-----------+.....|
+ | |.......................|
+ | |.......................|
+ 15 - +-----------------------+
+ |
+
+ This region would be represented with the following data:
+
+ 5 // Number of coordinates in this line
+ 5 // y coordinate
+ 5 // entering x coordinate
+ 10 // exiting x coordinate
+ 20 // entering x coordinate
+ 25 // exiting x coordinate
+ 3 // Number of coordinates on this line
+ 10 // y coordinate
+ 5 // entering x coordinate
+ 25 // exiting x coordinate
+ 1 // Number of coordinates in this line
+ 15 // y coordinate
+ 0 // End of region marker
+
+ Thus, the buffer would look as follows:
+
+ 5 5 5 10 20 25 3 10 5 25 1 15 0
+*/
+
+#include "EmCommon.h"
+#include "EmRegion.h"
+
+#include "string.h" // memcpy
+
+// ---------------------------------------------------------------------------
+// * EmRegionImpl
+// ---------------------------------------------------------------------------
+// Constructor for an empty region.
+
+EmRegion::EmRegionImpl::EmRegionImpl (void) :
+ fBounds (0, 0, 0, 0),
+ fCapacity (0),
+ fBuf (NULL)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// * EmRegionImpl
+// ---------------------------------------------------------------------------
+// Constructor for a rectangular region. Uses a built-in array instead of
+// getting memory from the heap. The array ends up looking as follows:
+//
+// 3, top, left, right, 1, bottom ,0
+
+EmRegion::EmRegionImpl::EmRegionImpl (const EmRect& r) :
+ fBounds (r),
+ fCapacity (7),
+ fBuf (fRectBuf)
+{
+ EmCoord* s = fBuf;
+
+ *s++ = 3;
+ *s++ = r.fTop;
+ *s++ = r.fLeft;
+ *s++ = r.fRight;
+
+ *s++ = 1;
+ *s++ = r.fBottom;
+
+ *s = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// * EmRegionImpl
+// ---------------------------------------------------------------------------
+// Constructor for a general region. Works from a buffer created by
+// RegionOp, so it's not likely that clients will be calling this constructor.
+
+EmRegion::EmRegionImpl::EmRegionImpl (const EmCoord* s, long len) :
+ fCapacity (0),
+ fBuf (NULL)
+{
+ if (s && len > 0)
+ {
+ fCapacity = len;
+
+ if (len <= 7)
+ fBuf = fRectBuf;
+ else
+ fBuf = new EmCoord[len];
+
+ memcpy (fBuf, s, len * sizeof (EmCoord));
+
+ CalcBounds ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// * ~EmRegionImpl
+// ---------------------------------------------------------------------------
+// Destructor
+
+EmRegion::EmRegionImpl::~EmRegionImpl (void)
+{
+ if (fRectBuf != fBuf)
+ delete [] fBuf;
+}
+
+
+// ---------------------------------------------------------------------------
+// * Equality
+// ---------------------------------------------------------------------------
+
+Bool
+EmRegion::EmRegionImpl::operator== (const EmRegionImpl& other) const
+{
+ return this->IsEqual (other);
+}
+
+
+// ---------------------------------------------------------------------------
+// * GetRects
+// ---------------------------------------------------------------------------
+// Returns the number of rects this region decomposes to. If a buffer is
+// provided, return the rects themselves, too. This method assumes the
+// buffer is already large enough, so you might want to call it with NULL
+// first to get a rect count. Or, better yet, use EmRegionRectIterator to
+// get the rectangles one-by-one.
+
+long
+EmRegion::EmRegionImpl::GetRects (EmRect* rp) const
+{
+ EmCoord* s = fBuf;
+ long ii = 0;
+
+ if (s)
+ {
+ EmCoord next;
+ EmRect r;
+
+ while ((next = *s++) != 0)
+ {
+ r.fTop = *s++;
+ r.fBottom = s[next];
+
+ while (next > 1)
+ {
+ r.fLeft = *s++;
+ r.fRight = *s++;
+ next -= 2;
+
+ if (!r.IsEmpty ())
+ {
+ if (rp)
+ rp[ii] = r;
+
+ ++ii;
+ }
+ }
+ }
+
+ EmAssert (s <= fBuf + fCapacity);
+ }
+
+ return ii;
+}
+
+
+// ---------------------------------------------------------------------------
+// * CalcBounds
+// ---------------------------------------------------------------------------
+// Scan the buffer data and determine the region's extent. This is done by
+// essentially decomposing the region into a series of rectangles and then
+// unioning those rectangles together.
+
+void
+EmRegion::EmRegionImpl::CalcBounds (void)
+{
+ EmCoord* s = fBuf;
+
+ fBounds.BeEmpty ();
+
+ if (s)
+ {
+ EmCoord next;
+ EmRect r;
+
+ while ((next = *s++) != 0)
+ {
+ r.fTop = *s++;
+ r.fBottom = s[next];
+
+ while (next > 1)
+ {
+ r.fLeft = *s++;
+ r.fRight = *s++;
+ next -= 2;
+ fBounds.UnionWith (r);
+ }
+ }
+
+ EmAssert (s <= fBuf + fCapacity);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// * Contains
+// ---------------------------------------------------------------------------
+// Scan the buffer data and determine if the given point falls within
+// the region. For each scanline, see if the y-coordinate of the point
+// falls between it and the next scanline. If so, scan all the x-coordinate
+// pairs for the scanline to see if the x-coordinate of the point falls
+// between any of them.
+
+Bool
+EmRegion::EmRegionImpl::Contains (const EmPoint& p) const
+{
+ EmCoord* bp = fBuf;
+ EmCoord s, e, next;
+
+ if (fBounds.Contains (p))
+ {
+ while ((next = *bp++) != 0) // while we haven't hit the end...
+ {
+ s = *bp++;
+ if (p.fY >= s && p.fY < bp[next]) // if between right scanlines...
+ {
+ while (next > 1) // while we have more x-pairs...
+ {
+ s = *bp++; // entering region x-coord
+ e = *bp++; // exiting region x-coord
+ if (p.fX >= s && p.fX < e)
+ return true; // *** We're in! Return TRUE. ***
+
+ next -= 2; // move to next pair
+ }
+ }
+ else
+ {
+ bp += next - 1; // move to next scanline
+ }
+ }
+
+ EmAssert (bp <= fBuf + fCapacity);
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// * Offset
+// ---------------------------------------------------------------------------
+// Scan the buffer data, adding dy to each y-event, and dx to each pair of
+// x-events. Also update the region bounds.
+
+void
+EmRegion::EmRegionImpl::Offset (EmCoord dx, EmCoord dy)
+{
+ EmCoord* s = fBuf;
+
+ if (s && (dx || dy))
+ {
+ EmCoord next;
+
+ while ((next = *s++) != 0)
+ {
+ *s++ += dy;
+ while (next > 1)
+ {
+ *s++ += dx;
+ *s++ += dx;
+ next -= 2;
+ }
+ }
+
+ fBounds.Offset (dx, dy); // !!! Do this outside "if (s)..."?
+
+ EmAssert (s <= fBuf + fCapacity);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// * IsEqual
+// ---------------------------------------------------------------------------
+// Determine if two regions encompass the same area. First do some
+// quick-tests:
+//
+// - See if the buffer lengths are equal. If not, regions are not equal.
+//
+// - See if the buffers are both NULL. If so, they're both empty regions
+// and are considered equal.
+//
+// - See if just one buffer is NULL. If so, it's empty and the other is
+// not, so they are not equal.
+//
+// Finally, compare the two buffers. Since the data in the buffer is well-
+// ordered, we can do a direct memory compare to see if they are equal.
+
+Bool
+EmRegion::EmRegionImpl::IsEqual (const EmRegionImpl& r2) const
+{
+ if (fCapacity != r2.fCapacity)
+ return false;
+
+ if (fBuf == NULL && r2.fBuf == NULL)
+ return true;
+
+ if (fBuf == NULL || r2.fBuf == NULL)
+ return false;
+
+ return memcmp (fBuf, r2.fBuf, fCapacity * sizeof (EmCoord)) == 0;
+}
+
+
+
+
+// ---------------------------------------------------------------------------
+// * EmRegion
+// ---------------------------------------------------------------------------
+// You want constructors, we got constructors...
+
+EmRegion::EmRegion (void) :
+ fImpl (new EmRegionImpl)
+{
+ EmAssert (fImpl.get ());
+}
+
+EmRegion::EmRegion (const EmCoord* s, long len) :
+ fImpl (new EmRegionImpl (s, len))
+{
+ EmAssert (fImpl.get ());
+}
+
+EmRegion::EmRegion (const EmRect& r) :
+ fImpl (new EmRegionImpl (r))
+{
+ EmAssert(fImpl.get ());
+}
+
+EmRegion::EmRegion (const EmRegion& r) :
+ fImpl (r.fImpl)
+{
+ EmAssert (fImpl.get ());
+}
+
+
+// ---------------------------------------------------------------------------
+// * ~EmRegion
+// ---------------------------------------------------------------------------
+// Destructor. Merely unreference our implementation object. If we're the
+// last/only region referencing it, it will delete itself.
+
+EmRegion::~EmRegion (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// * Assignment operator
+// ---------------------------------------------------------------------------
+// If one region is being assigned to another, drop the reference to the
+// old implementation object and alias the new implementation object.
+//
+// If a rectangle is being assigned to a region (a common operation), see
+// if the region already holds rectangular information and if we are the
+// exclusive owners of that information. If so, do a quick rect-copy. If
+// not, create a new implementation object to hold the rect.
+
+EmRegion&
+EmRegion::operator= (const EmRegion& r)
+{
+ if (this != &r)
+ {
+ fImpl = r.fImpl;
+ }
+
+ return *this;
+}
+
+
+EmRegion&
+EmRegion::operator= (const EmRect& r)
+{
+ EmAssert (fImpl.get ());
+
+ if (!fImpl->isShared () && fImpl->fCapacity <= 7)
+ {
+// *fImpl = EmRegionImpl(r); // !!! Do it this way?
+
+ if (fImpl->fBuf == NULL)
+ fImpl->fBuf = fImpl->fRectBuf;
+
+ fImpl->fCapacity = 7;
+
+ EmCoord* s = fImpl->fBuf;
+
+ *s++ = 3;
+ *s++ = r.fTop;
+ *s++ = r.fLeft;
+ *s++ = r.fRight;
+
+ *s++ = 1;
+ *s++ = r.fBottom;
+
+ *s = 0;
+
+ fImpl->fBounds = r;
+ }
+ else
+ {
+ fImpl = EmRefCounter<EmRegionImpl> (new EmRegionImpl (r));
+ }
+
+ return *this;
+}
+
+
+// ---------------------------------------------------------------------------
+// * BeEmpty
+// ---------------------------------------------------------------------------
+// If we are not already empty and if we are the exclusive owner of our
+// implementation object, quickly set the implementation to an empty rect.
+// Otherwise, create a new empty implementation object.
+
+void
+EmRegion::BeEmpty (void)
+{
+ EmAssert (fImpl.get ());
+
+ if (fImpl->fBuf) // If not already empty
+ {
+ if (!fImpl->isShared () && fImpl->fBuf == fImpl->fRectBuf)
+ {
+ fImpl->fBuf = NULL;
+ fImpl->fCapacity = 0;
+ fImpl->fBounds.BeEmpty ();
+ }
+ else
+ {
+ fImpl = new EmRegionImpl;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// * Bounds
+// ---------------------------------------------------------------------------
+
+const EmRect&
+EmRegion::Bounds (void) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->fBounds;
+}
+
+
+// ---------------------------------------------------------------------------
+// * GetRects
+// ---------------------------------------------------------------------------
+
+long
+EmRegion::GetRects (EmRect* rp) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->GetRects (rp);
+}
+
+
+// ---------------------------------------------------------------------------
+// * IsEmpty
+// ---------------------------------------------------------------------------
+
+Bool
+EmRegion::IsEmpty (void) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->fBounds.IsEmpty ();
+}
+
+
+// ---------------------------------------------------------------------------
+// * IsEqual
+// ---------------------------------------------------------------------------
+
+Bool
+EmRegion::IsEqual (const EmRegion& other) const
+{
+ EmAssert (fImpl.get ());
+
+ if (fImpl == other.fImpl)
+ return true;
+
+ return fImpl->IsEqual (*other.fImpl);
+}
+
+
+// ---------------------------------------------------------------------------
+// * Contains
+// ---------------------------------------------------------------------------
+
+Bool
+EmRegion::Contains (const EmPoint& p) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->Contains (p);
+}
+
+
+// ---------------------------------------------------------------------------
+// * Equality/inequality
+// ---------------------------------------------------------------------------
+
+Bool operator== (const EmRegion& r1, const EmRegion& r2)
+{
+ return r1.IsEqual (r2);
+}
+
+Bool operator!= (const EmRegion& r1, const EmRegion& r2)
+{
+ return !r1.IsEqual (r2);
+}
+
+
+// ---------------------------------------------------------------------------
+// * Offset
+// ---------------------------------------------------------------------------
+
+void
+EmRegion::Offset (const EmPoint& pt)
+{
+ EmAssert (fImpl.get ());
+
+ fImpl->Offset (pt.fX, pt.fY);
+}
+
+void
+EmRegion::Offset (EmCoord dx, EmCoord dy)
+{
+ EmAssert (fImpl.get ());
+
+ fImpl->Offset (dx, dy);
+}
+
+
+// ---------------------------------------------------------------------------
+// * Inset
+// ---------------------------------------------------------------------------
+// Doing a horizontal inset is easy: Just take each x-event pair and move
+// the first one to the right and the second one to the left.
+//
+// But wait, is it really so easy? What happens if the two x values cross
+// over each other? Then the pair must be discarded. Or what if the inset
+// operation is passed negative values and the x range now overlaps an
+// adjacent x range?
+//
+// The easiest thing to do is convert the region into a series of rectangles,
+// perform the inset/outset on the left and right coordinates of the
+// rectangles, and then union the whole shebang back together, letting
+// the RegionOp function sort out overlaps and empty rectangles.
+//
+// Once that's done, we have to figure out how to perform the vertical
+// inset operation. The easiest way is to turn the region 90 degrees and
+// perform another horizontal inset. To do the rotation, the region
+// is turned into rectangles, the rectangles are flipped around the X==Y
+// axis, and a new region is built up. That new region is inset, and
+// the resulting region is again flipped, giving us our final answer.
+
+void
+EmRegion::Inset (const EmPoint& pt)
+{
+ this->Inset (pt.fX, pt.fY);
+}
+
+void
+EmRegion::Inset (EmCoord dx, EmCoord dy)
+{
+ EmRegion newRgn, rectRgn;
+ EmRect r, r2;
+
+ for (int ii = 0; ii < 2; ii++)
+ {
+ EmRegionRectIterator iter1(*this);
+ newRgn.BeEmpty();
+
+ while (iter1.Next (r))
+ {
+ r.fLeft += dx;
+ r.fRight -= dx;
+
+ if (!r.IsEmpty ())
+ {
+ // !!! I can probably flip the rectangles here,
+ // and forego doing it as a seperate loop below.
+ rectRgn = r;
+ newRgn.UnionWith (rectRgn);
+ }
+ }
+
+ *this = newRgn;
+
+ EmRegionRectIterator iter2(*this);
+ newRgn.BeEmpty();
+
+ while (iter2.Next (r))
+ {
+ r2.fTop = r.fLeft;
+ r2.fLeft = r.fTop;
+ r2.fBottom = r.fRight;
+ r2.fRight = r.fBottom;
+
+ rectRgn = r2;
+ newRgn.UnionWith (rectRgn);
+ }
+
+ *this = newRgn;
+
+ dx = dy;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// * Operations
+// ---------------------------------------------------------------------------
+
+EmRegion&
+EmRegion::UnionWith (const EmRegion& other)
+{
+ return *this = RegionOp (EmRegion::eUnion, *this, other);
+}
+
+EmRegion&
+EmRegion::IntersectWith (const EmRegion& other)
+{
+ return *this = RegionOp (EmRegion::eIntersection, *this, other);
+}
+
+EmRegion&
+EmRegion::Subtract (const EmRegion& other)
+{
+ return *this = RegionOp (EmRegion::eDifference, *this, other);
+}
+
+EmRegion&
+EmRegion::XorWith (const EmRegion& other)
+{
+ return *this = Xor (*this, other);
+}
+
+EmRegion Union (const EmRegion& r1, const EmRegion& r2)
+{
+ return EmRegion::RegionOp (EmRegion::eUnion, r1, r2);
+}
+
+EmRegion Intersection (const EmRegion& r1, const EmRegion& r2)
+{
+ return EmRegion::RegionOp (EmRegion::eIntersection, r1, r2);
+}
+
+EmRegion Difference (const EmRegion& r1, const EmRegion& r2)
+{
+ return EmRegion::RegionOp (EmRegion::eDifference, r1, r2);
+}
+
+EmRegion Xor (const EmRegion& r1, const EmRegion& r2)
+{
+ return Difference (Union (r1, r2), Intersection (r1, r2));
+}
+
+
+// ---------------------------------------------------------------------------
+// * GetBuf
+// ---------------------------------------------------------------------------
+
+EmCoord*
+EmRegion::GetBuf (void) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->fBuf;
+}
+
+
+// ---------------------------------------------------------------------------
+// * Length
+// ---------------------------------------------------------------------------
+
+long
+EmRegion::Length (void) const
+{
+ EmAssert (fImpl.get ());
+
+ return fImpl->fCapacity;
+}
+
+
+// ---------------------------------------------------------------------------
+// * RegionOp
+// ---------------------------------------------------------------------------
+// Scan over two regions, building a third region from them. As we scan
+// over the two regions, keep track of our state. We keep track of whether
+// or not we are in each of the regions. At each point where we transition
+// in or out of particular region, we optionally record an x event depending
+// on the operation.
+
+EmRegion
+EmRegion::RegionOp (EOpcode code, const EmRegion& r1, const EmRegion& r2)
+{
+ //
+ // Do the easy cases first
+ //
+ switch (code)
+ {
+ case EmRegion::eUnion:
+ if (r1.IsEmpty () && r2.IsEmpty ())
+ return EmRegion();
+
+ if (r1.IsEmpty ())
+ return r2;
+
+ if (r2.IsEmpty ())
+ return r1;
+
+ break;
+
+ case EmRegion::eDifference:
+ if (r1.IsEmpty ())
+ return EmRegion ();
+
+ if (r2.IsEmpty ())
+ return r1;
+
+ break;
+
+ case EmRegion::eRevDifference:
+ if (r2.IsEmpty ())
+ return EmRegion ();
+
+ if (r1.IsEmpty ())
+ return r2;
+
+ break;
+
+ case EmRegion::eIntersection:
+ if (r1.IsEmpty () || r2.IsEmpty ())
+ return EmRegion ();
+
+ break;
+ }
+
+ //
+ // Get working pointers to our two input buffers.
+ // "shape1" and "shape2" point to the beginnings
+ // of the next scanlines to process.
+ //
+ EmCoord* shape1 = r1.GetBuf ();
+ EmCoord* shape2 = r2.GetBuf ();
+
+ //
+ // Get a pointer to our destination buffer.
+ // Use a buffer on the stack for speed if possible.
+ //
+ long buflen = (r1.Length () * r2.Length ());
+ EmAssert (buflen > 0);
+
+ EmCoord* buf;
+ EmCoord stackBuf[100]; // !!! Bigger? Smaller?
+ if (buflen > (long) countof (stackBuf))
+ buf = new EmCoord[buflen];
+ else
+ buf = stackBuf;
+
+ EmAssert(buf);
+
+ EmCoord* ss = buf;
+ EmCoord* oldss = NULL;
+
+ EmCoord* x1 = 0;
+ EmCoord* x2 = 0;
+ EmCoord* fixup;
+ EmCoord y, l1 = 0, l2 = 0, tl1, tl2;
+ long len, oldlen = -1;
+ int test;
+
+ for (;;)
+ {
+ //
+ // Get the lengths of the next scanlines to work with.
+ //
+ tl1 = *shape1;
+ tl2 = *shape2;
+
+ //
+ // If they are both zero, we are at the ends of both regions,
+ // and can quit.
+ //
+ if (tl1 == 0 && tl2 == 0)
+ break;
+
+ //
+ // Set "test" based on which scanline is above the other.
+ // If scanline1 is above scanline2, set "test" to negative.
+ // If scanline1 is below scanline2, set "test" to positive.
+ // If both scanlines are on the same line, set "test" to zero.
+ // If the length of the scanline is zero, we are at the end
+ // of the region, and so are conceptually at the bottom of
+ // the coordinate space.
+ //
+ if (tl1 == 0)
+ test = 1;
+ else if (tl2 == 0)
+ test = -1;
+ else
+ test = shape1[1] - shape2[1];
+
+ //
+ // Start processing the scanlines. Remember some information
+ // on each one before merging them together.
+ //
+ if (test <= 0)
+ {
+ y = shape1[1]; // Remember y coordinate
+ x1 = &shape1[2]; // Point to start of x-pairs
+ shape1 += tl1 + 1; // Bump to next scanline in this region
+ l1 = tl1 - 1; // Remember number of x-coordinates
+ }
+
+ if (test >= 0)
+ {
+ y = shape2[1]; // Remember y coordinate
+ x2 = &shape2[2]; // Point to start of x-pairs
+ shape2 += tl2 + 1; // Bump to next scanline in this region
+ l2 = tl2 - 1; // Remember number of x-coordinates
+ }
+
+ //
+ // Start outputting a new scanline. First, remember where it
+ // starts so we can write the final length later. Next, write
+ // an initial length of 1. Follow it with the y-coordinate of
+ // the new scanline.
+ //
+ fixup = ss;
+ *ss++ = 1;
+ *ss++ = y;
+
+ EmAssert(ss - buf < buflen);
+
+ if (l1 == 0 && l2 == 0)
+ {
+ //
+ // If there are no x events in either scanline, there's nothing
+ // to merge together, so there's nothing to output.
+ //
+ }
+ else if (l1 == 0)
+ {
+ //
+ // The first region is depleted or we haven't reached its
+ // first scanline yet, so work solely with the second
+ // region. If we're doing a union or reverse difference
+ // operation (where region A is subtracted from region B),
+ // copy region B's data.
+ //
+ if (code == EmRegion::eUnion || code == EmRegion::eRevDifference)
+ {
+ memcpy (ss, x2, l2 * sizeof (EmCoord));
+ ss += l2;
+ EmAssert (ss - buf < buflen);
+ }
+ }
+ else if (l2 == 0)
+ {
+ //
+ // The second region is depleted or we haven't reached its
+ // first scanline yet, so work solely with the first
+ // region. If we're doing a union or difference
+ // operation (where region B is subtracted from region A),
+ // copy region A's data.
+ //
+ if (code == EmRegion::eUnion || code == EmRegion::eDifference)
+ {
+ memcpy (ss, x1, l1 * sizeof (EmCoord));
+ ss += l1;
+ EmAssert (ss - buf < buflen);
+ }
+ }
+ else
+ {
+ //
+ // Start merging two scanlines together. While there
+ // are still x-pairs left to examine:
+ //
+ // -- Compare an x-value from region A against an
+ // x-value from region B.
+ //
+ // -- If Region A's is less than Region B's, bump
+ // to the next x-value in Region A and invert
+ // a state bit indicating whether or not we are
+ // "in" region A.
+ //
+ // -- If Region B's is less than Region A's, bump
+ // to the next x-value in Region B and invert
+ // a state bit indicating whether or not we are
+ // "in" region B.
+ //
+ // -- If both x-values are the same, bump to the next
+ // x-values in both regions, and invert the state
+ // bits for both regions.
+ //
+ // -- Examine the state bits. They tell us when we are
+ // leaving one state and entering another. If we
+ // are entering a desired state (for instance, we
+ // are doing an intersection operation and both
+ // state bits are now on), emit an x-event in the
+ // destination region. Similarly, if we were just
+ // in a desired state and are now leaving it, again
+ // emit an x-event to close off the previous x-event.
+ //
+ // Note that our operation codes are cleverly chosen to
+ // correspond to our state value. If we are doing an
+ // intersection operation, for example, we are interested
+ // in pixels that are in both Region A and Region B. Thus
+ // we are interested in ranges where both state bits are
+ // on. When both state bits are on, the state value is "3",
+ // which also happens to be the value of eIntersection.
+ //
+ // As another example, consider the "difference" operation,
+ // where Region B is subtracted from Region A. In that case,
+ // we are interested in the pixels that are in Region A but
+ // not in Region B. In other words, we are interested in
+ // ranges where Region A's state bit (bit 0) is set and
+ // Region B's state bit (bit 1) is clear. At that time, the
+ // state value is "1", which also happens to be the value
+ // of eDifference.
+ //
+ // The process of the eRevDifference operation is analogous.
+ //
+ // The process of the eUnion operation is a little
+ // tricky. The value of eUnion is zero, which means that we
+ // are interested in ranges that belong to _neither_ of the
+ // two regions. That means that our resulting region logically
+ // describes the pixels _outside_ the union of the two source
+ // regions. However, it's all a matter of definition. Ultimately,
+ // what we have is an outline. Whether we choose to be interested
+ // in the bits "inside" the outline or "outside" the outline is
+ // up to us. In other words, if the union of two regions happens
+ // to result in a square, our algorithm will think its generating
+ // the following region:
+ //
+ // . . . . . . . . . . . . . . .
+ // . . . . . . . . . . . . . . .
+ // . . . . . . . . . . . . . . .
+ // . . . . +--------+. . . . . .
+ // . . . . .| | . . . . .
+ // . . . . | |. . . . . .
+ // . . . . .| | . . . . .
+ // . . . . | |. . . . . .
+ // . . . . .+--------+ . . . . .
+ // . . . . . . . . . . . . . . .
+ // . . . . . . . . . . . . . . .
+ // . . . . . . . . . . . . . . .
+ //
+ // But we are perfectly free to think of it as:
+ //
+ // +--------+
+ // |. . . . |
+ // | . . . .|
+ // |. . . . |
+ // | . . . .|
+ // +--------+
+ //
+ EmCoord* p1 = x1;
+ EmCoord* p2 = x2;
+ EmCoord xl1 = l1, xl2 = l2;
+ EmCoord x, xold = 0;
+ int xflag = 0;
+
+ while (xl1 > 0 && xl2 > 0)
+ {
+ test = *p1 - *p2;
+
+ if (test <= 0)
+ {
+ x = *p1++;
+ xflag ^= 1;
+ xl1--;
+ }
+
+ if (test >= 0)
+ {
+ x = *p2++;
+ xflag ^= 2;
+ xl2--;
+ }
+
+ if (xflag == code || xold == code)
+ {
+ *ss++ = x;
+ EmAssert (ss - buf < buflen);
+ }
+
+ xold = xflag;
+ }
+
+ //
+ // One of the scanlines has been exhausted. Determine what
+ // to do with the remaining one based on the operation we're
+ // performing. If we're doing a union or difference operation
+ // and there's still data left in Region A's scanline, copy
+ // that data to the destination. If we're doing a union or
+ // reverse difference operation and there's still data in
+ // Region B's scanline, copy that data to the destination.
+ //
+ if (code == EmRegion::eUnion || code == EmRegion::eDifference)
+ {
+ while (xl1-- > 0)
+ {
+ *ss++ = *p1++;
+ EmAssert (ss - buf < buflen);
+ }
+ }
+
+ if (code == EmRegion::eUnion || code == EmRegion::eRevDifference)
+ {
+ while (xl2-- > 0)
+ {
+ *ss++ = *p2++;
+ EmAssert (ss - buf < buflen);
+ }
+ }
+ }
+
+ //
+ // We've just merged two scanlines. First, determine the new
+ // scanline's length and write it out to the fixup location.
+ //
+ len = ss - fixup - 2;
+ *fixup = len + 1;
+
+ //
+ // Next, if the new scanline happens to be identical to the
+ // previous scanline, don't bother recording it (reset our
+ // "ss" pointer so that a subsequent scanline will overwrite
+ // the one we're getting rid of).
+ //
+ if (len > 0 &&
+ len == oldlen &&
+ memcmp (&oldss[2], &fixup[2], len * sizeof (EmCoord)) == 0)
+ {
+ ss = fixup;
+ }
+ else
+ {
+ oldss = fixup;
+ oldlen = len;
+ }
+ }
+
+ //
+ // Done with all the scanlines. Write out our terminator.
+ //
+ *ss++ = 0;
+
+ EmAssert (ss - buf < buflen);
+
+ //
+ // Create our new region from the raw buffer.
+ //
+ EmRegion result (buf, ss - buf);
+
+ //
+ // Delete our raw buffer if necessary.
+ //
+ if (buf != stackBuf)
+ delete [] buf;
+
+ return result;
+}
+
+
+
+
+// ---------------------------------------------------------------------------
+// * EmRegionRectIterator
+// ---------------------------------------------------------------------------
+// Constructor. Note that "fRegion" is an EmRegion, _not_ a reference to an
+// EmRegion. This means that any changes to the source region will not affect
+// the iterator, as the iterator effectively makes a copy of the region
+// at construction time.
+
+EmRegionRectIterator::EmRegionRectIterator (const EmRegion& r) :
+ fRegion (r)
+{
+ this->Reset ();
+}
+
+
+// ---------------------------------------------------------------------------
+// * Reset
+// ---------------------------------------------------------------------------
+
+void
+EmRegionRectIterator::Reset (void)
+{
+ fBufPtr = fRegion.GetBuf ();
+ fNext = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// * Next
+// ---------------------------------------------------------------------------
+// Return the next rectangle composing the region.
+//
+// Iteration works as follows. The first time we're called, we notice the
+// fact and fetch information on the next scanline. That information
+// includes the scanline's y-coordinate and an offset to the next scanline.
+// The y-coordinate of the current scanline is our rectangle's top value,
+// while the y-coordinate of the next scanline is our rectangles bottom
+// value. Next, we start processing the rest of the scanline, which
+// contains x-coordinate pairs. Each pair makes up the left and right
+// values of the rectangle. Rectangles are formed until we reach the
+// end of the scanline, at which time we move to the next scanline. If
+// we run out of scanlines, we're done iterating.
+
+Bool
+EmRegionRectIterator::Next (EmRect& r)
+{
+ while (fBufPtr)
+ {
+ if (fNext > 1)
+ {
+ r.fLeft = *fBufPtr++;
+ r.fRight = *fBufPtr++;
+ fNext -= 2;
+
+ EmAssert (fBufPtr <= fRegion.GetBuf () + fRegion.Length ());
+ return true;
+ }
+
+ fNext = *fBufPtr++;
+ if (fNext == 0)
+ {
+ EmAssert (fBufPtr <= fRegion.GetBuf () + fRegion.Length ());
+ return false;
+ }
+
+ r.fTop = *fBufPtr++;
+ r.fBottom = fBufPtr[fNext];
+ }
+
+ EmAssert (fBufPtr <= fRegion.GetBuf () + fRegion.Length ());
+
+ return false;
+}
+
+#if 0
+// ---------------------------------------------------------------------------
+// * Testing code
+// ---------------------------------------------------------------------------
+#include "stdio.h"
+
+void TestRegion();
+void PrintRegion(const EmRegion& r);
+Bool VerifyRegion(const char*, const EmRegion& r, EmRect rects[], int numRects);
+
+void PrintRegion(const EmRegion& r)
+{
+ int ii = 0;
+ EmRect testRect;
+ EmRegionRectIterator iter(r);
+ while (iter.Next(testRect))
+ {
+ ii++;
+ printf("rect #%d: l = %ld, t = %ld, r = %ld, b = %ld\n", ii,
+ testRect.fLeft, testRect.fTop, testRect.fRight, testRect.fBottom);
+ }
+
+ printf("\n");
+}
+
+Bool VerifyRegion(const char* testName, const EmRegion& r, EmRect rects[], int numRects)
+{
+ Bool success = true;
+
+ printf("Region test: %s\n", testName);
+
+ int ii = 0;
+ EmRect testRect;
+ EmRegionRectIterator iter(r);
+ while (iter.Next(testRect))
+ {
+ if (ii < numRects)
+ {
+ if (testRect != rects[ii])
+ {
+ printf("expected rect #%d: l = %ld, t = %ld, r = %ld, b = %ld\n", ii,
+ rects[ii].fLeft, rects[ii].fTop, rects[ii].fRight, rects[ii].fBottom);
+ printf("returned rect #%d: l = %ld, t = %ld, r = %ld, b = %ld\n", ii,
+ testRect.fLeft, testRect.fTop, testRect.fRight, testRect.fBottom);
+
+ success = false;
+ }
+ }
+ else
+ {
+ printf("Iterator returned extra rectangle:\n");
+ printf("returned rect #%d: l = %ld, t = %ld, r = %ld, b = %ld\n", ii,
+ testRect.fLeft, testRect.fTop, testRect.fRight, testRect.fBottom);
+
+ success = false;
+ }
+ ii++;
+ }
+
+ if (ii != numRects)
+ {
+ printf("Iterator returned %d rects, expected %d\n", ii, numRects);
+
+ success = false;
+ }
+
+ printf("\n");
+
+ return success;
+}
+
+void TestRegion()
+{
+ printf("Testing EmRegion class...\n");
+
+ Bool success = true;
+
+ EmRegion testRegion1;
+ EmRegion testRegion2;
+
+ testRegion1 = EmRegion(EmRect(0, 0, 0, 0));
+ EmRect resultRects1[] =
+ {
+ EmRect( 0, 0, 0, 0 )
+ };
+ success &= VerifyRegion("Set to empty rect", testRegion1, resultRects1, countof(resultRects1));
+
+ testRegion2 = EmRegion(EmRect(1, 2, 3, 4));
+ EmRect resultRects2[] =
+ {
+ EmRect( 1, 2, 3, 4 )
+ };
+ success &= VerifyRegion("Set to non-empty rect", testRegion2, resultRects2, countof(resultRects2));
+
+ testRegion2 = EmRegion(EmRect(5, 6, 7, 8));
+ EmRect resultRects3[] =
+ {
+ EmRect( 5, 6, 7, 8 )
+ };
+ success &= VerifyRegion("Reassign to non-empty rect", testRegion2, resultRects3, countof(resultRects3));
+
+ EmRegion testRegion(EmRect(0, 0, 10, 10));
+ EmRegion containedRegion(EmRect(3, 3, 7, 7));
+ EmRegion containingRegion(EmRect(-5, -5, 15, 15));
+ EmRegion disjointRegion(EmRect(15, 15, 25, 25));
+ EmRegion overlappingRegion(EmRect(5, 5, 15, 15));
+ EmRegion result;
+
+ {
+ //
+ // Test Subtract
+ //
+
+ result = Difference(testRegion, containedRegion);
+ EmRect resultRects1[] =
+ {
+ EmRect( 0, 0, 10, 3 ),
+ EmRect( 0, 3, 3, 7 ),
+ EmRect( 7, 3, 10, 7 ),
+ EmRect( 0, 7, 10, 10 )
+ };
+ success &= VerifyRegion("Difference/contained", result, resultRects1, countof(resultRects1));
+
+ result = Difference(testRegion, containingRegion);
+ success &= VerifyRegion("Difference/containing", result, NULL, 0);
+
+ result = Difference(testRegion, disjointRegion);
+ EmRect resultRects3[] =
+ {
+ EmRect( 0, 0, 10, 10 )
+ };
+ success &= VerifyRegion("Difference/disjoint", result, resultRects3, countof(resultRects3));
+
+ result = Difference(testRegion, overlappingRegion);
+ EmRect resultRects4[] =
+ {
+ EmRect( 0, 0, 10, 5 ),
+ EmRect( 0, 5, 5, 10 )
+ };
+ success &= VerifyRegion("Difference/overlapping", result, resultRects4, countof(resultRects4));
+ }
+
+ {
+ //
+ // Test Intersection
+ //
+
+ result = Intersection(testRegion, containedRegion);
+ EmRect resultRects1[] =
+ {
+ EmRect( 3, 3, 7, 7 )
+ };
+ success &= VerifyRegion("Intersection/contained", result, resultRects1, countof(resultRects1));
+
+ result = Intersection(testRegion, containingRegion);
+ EmRect resultRects2[] =
+ {
+ EmRect( 0, 0, 10, 10 )
+ };
+ success &= VerifyRegion("Intersection/containing", result, resultRects2, countof(resultRects2));
+
+ result = Intersection(testRegion, disjointRegion);
+ success &= VerifyRegion("Intersection/disjoint", result, NULL, 0);
+
+ result = Intersection(testRegion, overlappingRegion);
+ EmRect resultRects4[] =
+ {
+ EmRect( 5, 5, 10, 10 )
+ };
+ success &= VerifyRegion("Intersection/overlapping", result, resultRects4, countof(resultRects4));
+ }
+
+ {
+ //
+ // Test Union
+ //
+
+ result = Union(testRegion, containedRegion);
+ EmRect resultRects1[] =
+ {
+ EmRect( 0, 0, 10, 10 )
+ };
+ success &= VerifyRegion("Union/contained", result, resultRects1, countof(resultRects1));
+
+ result = Union(testRegion, containingRegion);
+ EmRect resultRects2[] =
+ {
+ EmRect( -5, -5, 15, 15 )
+ };
+ success &= VerifyRegion("Union/containing", result, resultRects2, countof(resultRects2));
+
+ result = Union(testRegion, disjointRegion);
+ EmRect resultRects3[] =
+ {
+ EmRect( 0, 0, 10, 10 ),
+ EmRect( 15, 15, 25, 25 )
+ };
+ success &= VerifyRegion("Union/disjoint", result, resultRects3, countof(resultRects3));
+
+ result = Union(testRegion, overlappingRegion);
+ EmRect resultRects4[] =
+ {
+ EmRect( 0, 0, 10, 5 ),
+ EmRect( 0, 5, 15, 10 ),
+ EmRect( 5, 10, 15, 15 )
+ };
+ success &= VerifyRegion("Union/overlapping", result, resultRects4, countof(resultRects4));
+ }
+
+ {
+ //
+ // Test offset
+ //
+
+ EmRegion rgn1(EmRect(10, 0, 40, 10));
+ EmRegion rgn2(EmRect(20, 0, 30, 5));
+
+ result = Difference(rgn1, rgn2);
+ result.Offset(1, 1);
+
+ EmRect resultRects1[] =
+ {
+ EmRect( 11, 1, 21, 6 ),
+ EmRect( 31, 1, 41, 6 ),
+ EmRect( 11, 6, 41, 11 )
+ };
+ success &= VerifyRegion("Offset", result, resultRects1, countof(resultRects1));
+
+ // Test with different x and y values to make
+ // sure I haven't swapped them.
+ result = Difference(rgn1, rgn2);
+ result.Offset(1, 2);
+
+ EmRect resultRects2[] =
+ {
+ EmRect( 11, 2, 21, 7 ),
+ EmRect( 31, 2, 41, 7 ),
+ EmRect( 11, 7, 41, 12 )
+ };
+ success &= VerifyRegion("Offset", result, resultRects2, countof(resultRects2));
+
+ // Test with one of them zero to make sure I
+ // don't improperly optimize.
+ result = Difference(rgn1, rgn2);
+ result.Offset(0, 2);
+
+ EmRect resultRects3[] =
+ {
+ EmRect( 10, 2, 20, 7 ),
+ EmRect( 30, 2, 40, 7 ),
+ EmRect( 10, 7, 40, 12 )
+ };
+ success &= VerifyRegion("Offset", result, resultRects3, countof(resultRects3));
+ }
+
+ {
+ //
+ // Test inset
+ //
+
+ EmRegion rgn1(EmRect(10, 0, 40, 10));
+ EmRegion rgn2(EmRect(20, 0, 30, 5));
+
+ result = Difference(rgn1, rgn2);
+ result.Inset(1, 1);
+
+ EmRect resultRects[] =
+ {
+ EmRect( 11, 1, 19, 6 ),
+ EmRect( 31, 1, 39, 6 ),
+ EmRect( 11, 6, 39, 9 )
+ };
+ success &= VerifyRegion("Inset", result, resultRects, countof(resultRects));
+ }
+
+ if (success)
+ printf("TestRegion() succeeded.\n");
+ else
+ printf("TestRegion() failed!\n");
+}
+
+#endif // if 0
diff --git a/SrcShared/EmRegion.h b/SrcShared/EmRegion.h
new file mode 100644
index 0000000..da73139
--- /dev/null
+++ b/SrcShared/EmRegion.h
@@ -0,0 +1,216 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegion_h
+#define EmRegion_h
+
+/*
+ EmRegion is a cross-platform region class. It provides for the following needs:
+
+ - A common API that can be used on both Mac and Windows
+
+ - An internal 32-bit representation so that regions can be calculated
+ in a 32-bit coordinate plane.
+
+ - Automatic management of heap structures so that you don't have to
+ remember to call DisposeRgn or DeleteObject.
+
+ Use regions as you would something like EmRect. Create them on the stack,
+ declare them as data members, pass them by reference, etc. For instance,
+ ScriptViewCore uses regions as follows to determine the highlight area:
+
+ {
+ EmRegion scratch;
+ EmRect aRect;
+
+ // The selection's bounding rectangle
+ aRect = ...; // Calculate full bounds
+ highlight = aRect;
+
+ // ... minus beginning of the first line
+ aRect = ...; // Calculate leading area to subtract
+ scratch = aRect;
+ highlight.Subtract(scratch);
+
+ // ... and the end of the last line
+ aRect = ...; // Calculate trailing area to subtract
+ scratch = aRect;
+ highlight.Subtract(scratch);
+ }
+
+ If you need to decompose the region into a series of rectangles, you can use
+ the EmRegionRectIterator class for this. It can be used as follows:
+
+ EmRegionRectIterator iter(*this);
+ EmRect r;
+ while (iter.Next(r))
+ {
+ // ...do something with the rect...
+ }
+
+ This region class is based on the region class from ET++ 3.2.2, used by
+ permission from AndrŽ Weinand:
+
+ Regions: yes sure, just use the code and send me the bugs!
+
+ --andre
+ P.S.: my official life-long mail address is weinand@acm.org
+*/
+
+#include "EmPoint.h" // EmPoint
+#include "EmRect.h" // EmRect
+#include "EmRefCounted.h"
+
+
+class EmRegion
+{
+ public:
+ EmRegion (void);
+ // Creates a region spanning {0, 0, 0, 0}.
+
+ EmRegion (const EmRect& r);
+ // Creates a region spanning the given rectangle.
+
+ EmRegion (const EmRegion& r);
+ // Copy constructor. The internal data is copied via an internal
+ // reference counted object, so cloning regions is quick.
+
+ ~EmRegion (void);
+
+ EmRegion& operator= (const EmRegion& r);
+ EmRegion& operator= (const EmRect& r);
+ // Assignment operator. Similar to copy constructor. There is also
+ // a version that takes an EmRect as an r-value.
+
+ void BeEmpty (void);
+ // Quickly empty out a region so that you don't have to do anything
+ // goofy like assigning a NULL rectangle to it.
+
+ const EmRect& Bounds (void) const;
+ // Returns an EmRect containing the bounds of the region.
+
+ long GetRects (EmRect* r) const;
+ // Decompose the region into a set of rectangles, returning the
+ // number of rectangles. You pass in a pointer to a buffer that
+ // will receive the rectangles. If you pass in NULL, no rectangles
+ // will be returned, but you'll still get the rectangle count.
+ // You should probably use a region iterator instead of this method
+ // if you want to mess with the rectangles.
+
+ Bool IsEmpty (void) const;
+ // Returns whether or not the region encompases any area.
+
+ Bool IsEqual (const EmRegion& r2) const;
+ // Compares two regions, returning whether or not they encompass
+ // the same area (set of pixels).
+
+ Bool Contains (const EmPoint& p) const;
+ // Returns whether or not the given point is in the interior of
+ // the area described by the region. Testing is performed on the
+ // normal half-open interval.
+
+ friend inline Bool operator== (const EmRegion& r1, const EmRegion& r2);
+ friend inline Bool operator!= (const EmRegion& r1, const EmRegion& r2);
+ // Shortcuts for the IsEqual method
+
+ void Offset (const EmPoint&);
+ void Offset (EmCoord dx, EmCoord dy);
+ // Offset the region by the given deltas. Positive deltas move
+ // the region down and to the right.
+
+ void Inset (const EmPoint&);
+ void Inset (EmCoord dx, EmCoord dy);
+ // Inset the region by the given deltas. Positive deltas move
+ // the region inward.
+
+ EmRegion& UnionWith (const EmRegion&);
+ EmRegion& IntersectWith(const EmRegion&);
+ EmRegion& Subtract (const EmRegion&);
+ EmRegion& XorWith (const EmRegion&);
+ // Modify the region in place. Note that XorWith is synthesized from
+ // the other operations, so it's not quite as effiecient as it
+ // could be.
+
+ friend inline EmRegion Union (const EmRegion& r1, const EmRegion& r2);
+ friend inline EmRegion Intersection(const EmRegion& r1, const EmRegion& r2);
+ friend inline EmRegion Difference (const EmRegion& r1, const EmRegion& r2);
+ friend inline EmRegion Xor (const EmRegion& r1, const EmRegion& r2);
+ // Versions of the previous four operations, with the difference
+ // being that neither of the given regions are modified. Instead,
+ // a new region containing the result is returned.
+
+ private:
+ enum EOpcode
+ {
+ eUnion = 0,
+ eDifference = 1,
+ eRevDifference = 2,
+ eIntersection = 3
+ };
+
+ EmRegion (const EmCoord* s, long len);
+ EmCoord* GetBuf (void) const;
+ long Length (void) const;
+
+ static EmRegion RegionOp (EOpcode code, const EmRegion& r1, const EmRegion& r2);
+
+ friend class EmRegionRectIterator;
+
+ class EmRegionImpl : public EmRefCounted
+ {
+ public:
+ EmRegionImpl (void);
+ EmRegionImpl (const EmCoord* s, long len);
+ EmRegionImpl (const EmRect& r);
+ EmRegionImpl (const EmRegion& r);
+ ~EmRegionImpl (void);
+
+ Bool operator== (const EmRegionImpl& other) const;
+
+ long GetRects (EmRect* r) const;
+ Bool IsEqual (const EmRegionImpl&) const;
+ Bool Contains (const EmPoint& p) const;
+
+ void Offset (EmCoord dx, EmCoord dy);
+
+ protected:
+ void CalcBounds (void);
+
+ protected:
+ friend class EmRegion;
+
+ EmRect fBounds;
+ long fCapacity;
+ EmCoord* fBuf;
+ EmCoord fRectBuf[7];
+ };
+
+ EmRefCounter<EmRegionImpl> fImpl;
+};
+
+class EmRegionRectIterator
+{
+ public:
+ EmRegionRectIterator (const EmRegion& r);
+
+ void Reset (void);
+ Bool Next (EmRect& r);
+
+ private:
+ EmRegion fRegion;
+ EmCoord* fBufPtr;
+ long fNext;
+};
+
+
+#endif // EmRegion_h
diff --git a/SrcShared/EmScreen.cpp b/SrcShared/EmScreen.cpp
new file mode 100644
index 0000000..1808f3b
--- /dev/null
+++ b/SrcShared/EmScreen.cpp
@@ -0,0 +1,281 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmScreen.h"
+
+#include "EmHAL.h" // EmHAL:: GetLCDBeginEnd
+#include "EmMemory.h" // CEnableFullAccess
+#include "MetaMemory.h" // MetaMemory::MarkScreen
+
+
+static emuptr gScreenDirtyLow;
+static emuptr gScreenDirtyHigh;
+
+static emuptr gScreenBegin;
+static emuptr gScreenEnd;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Initialize (void)
+{
+ gScreenDirtyLow = EmMemEOM;
+ gScreenDirtyHigh = EmMemNULL;
+
+ gScreenBegin = EmMemNULL;
+ gScreenEnd = EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Reset (void)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ gScreenBegin = EmMemNULL;
+ gScreenEnd = EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Load (SessionFile&)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ EmHAL::GetLCDBeginEnd (gScreenBegin, gScreenEnd);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::MarkDirty
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::MarkDirty (emuptr address, uint32 size)
+{
+ /*
+ SUBTLE BUG NOTE: Both of these tests need to be performed.
+ Originally, I had this as an if (...) ... else if (...) ... After
+ all, how could a given address be above the high- water mark if it
+ was below the low-water mark? "Obviously", it couldn't, so I didn't
+ see the need to test against the high-water mark if we were below
+ the low-water mark.
+
+ Well, duh, that assumption was false. After the LCD buffer is
+ copied to the screen, we set the low-water mark to the end of the
+ buffer and the high-water mark to the beginning of the buffer. If
+ the screen is modified in such a way that each pixel affected
+ appears lower in memory than any previous pixel (as happens when we
+ scroll a document down), then we always entered the low-water mark
+ of the code below; we never entered the high-water mark of the code.
+ Thus, the high-water mark stayed set to the beginning of the
+ buffer, giving us a NULL update range.
+ */
+
+ if (address < gScreenDirtyLow)
+ {
+ gScreenDirtyLow = address;
+ }
+
+ if (address + size > gScreenDirtyHigh)
+ {
+ gScreenDirtyHigh = address + size;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::InvalidateAll
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::InvalidateAll (void)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ emuptr newScreenBegin;
+ emuptr newScreenEnd;
+ EmHAL::GetLCDBeginEnd (newScreenBegin, newScreenEnd);
+
+ if (newScreenBegin != gScreenBegin || newScreenEnd != gScreenEnd)
+ {
+ MetaMemory::UnmarkScreen (gScreenBegin, gScreenEnd);
+
+ gScreenBegin = newScreenBegin;
+ gScreenEnd = newScreenEnd;
+
+ MetaMemory::MarkScreen (gScreenBegin, gScreenEnd);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::GetBits
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmScreen::GetBits (EmScreenUpdateInfo& info)
+{
+ // Always return whether or not the LCD is on.
+
+ info.fLCDOn = EmHAL::GetLCDScreenOn ();
+
+ // Get the first and last scanlines to update. This is a *big* win
+ // when running Gremlins. Without this check, a typical test ran
+ // 240 seconds. With the check, the test ran 170 seconds.
+
+ // Get the screen begin and end. We'll be clipping against this
+ // range (just in case screenLow and/or screenHigh got out of whack,
+ // which might happen in a multi-threaded system and we aren't using
+ // synchronization objects).
+
+ emuptr screenBegin;
+ emuptr screenEnd;
+ EmHAL::GetLCDBeginEnd (screenBegin, screenEnd);
+
+ // Get the range of bytes affected, clipping to the range of the
+ // screen. From this information, we can determine the first and
+ // last affected scanlines.
+
+ info.fScreenLow = max (gScreenDirtyLow, screenBegin);
+ info.fScreenHigh = min (gScreenDirtyHigh, screenEnd);
+
+ // Reset gScreenDirtyLow/High with sentinel values so that they can
+ // be munged again by EmScreen::MarkDirty.
+
+ gScreenDirtyLow = EmMemEOM;
+ gScreenDirtyHigh = EmMemNULL;
+
+ // If no lines need to be updated, we can return now.
+
+ if (info.fScreenLow >= info.fScreenHigh)
+ {
+ return false;
+ }
+
+ // Get the current state of things. Do this only if the LCD is on.
+ // If the LCD is off, we may not be able to get the contents of its
+ // frame buffer (the bus to the buffer may be disabled).
+
+ if (info.fLCDOn)
+ {
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ EmHAL::GetLCDScanlines (info);
+ }
+
+ return true;
+}
diff --git a/SrcShared/EmScreen.h b/SrcShared/EmScreen.h
new file mode 100644
index 0000000..453d5e0
--- /dev/null
+++ b/SrcShared/EmScreen.h
@@ -0,0 +1,58 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmScreen_h
+#define EmScreen_h
+
+#include "EmPixMap.h" // EmPixMap
+
+class SessionFile;
+
+class EmScreenUpdateInfo
+{
+ public:
+ // Output parameters. Passed back to caller of
+ // Screen::GetBits. fLCDOn is always valid. The
+ // other fields are valid only if Screen::GetBits
+ // returns true.
+
+ EmPixMap fImage; // LCD image
+ long fFirstLine; // First changed scanline
+ long fLastLine; // Last changed scanline + 1
+ long fLeftMargin; // If LCD is scrlled by some sub-byte amount,
+ // this contains that amount.
+ Bool fLCDOn; // True if LCD is on at all
+
+ // Input parameters. Set by Screen::GetBits and
+ // passed to EmHAL::GetLCDScanlines.
+
+ emuptr fScreenLow; // First dirty byte
+ emuptr fScreenHigh; // Last dirty byte
+};
+
+class EmScreen
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void MarkDirty (emuptr address, uint32 size);
+ static void InvalidateAll (void);
+
+ static Bool GetBits (EmScreenUpdateInfo&);
+};
+
+#endif // EmScreen_h
diff --git a/SrcShared/EmSession.cpp b/SrcShared/EmSession.cpp
new file mode 100644
index 0000000..135b4c5
--- /dev/null
+++ b/SrcShared/EmSession.cpp
@@ -0,0 +1,2443 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmSession.h"
+
+#include "ChunkFile.h" // ChunkFile
+#include "EmApplication.h" // gApplication, GetBoundDevice, etc.
+#include "EmCPU.h" // EmCPU::Execute
+#include "EmDocument.h" // gDocument
+#include "EmErrCodes.h" // kError_InvalidSessionFile
+#include "EmEventPlayback.h" // EmEventPlayback::ReplayingEvents
+#include "EmException.h" // EmExceptionTopLevelAction
+#include "EmHAL.h" // EmHAL::ButtonEvent
+#include "EmMemory.h" // Memory::ResetBankHandlers
+#include "EmMinimize.h" // EmMinimize::RealLoadInitialState
+#include "EmStreamFile.h" // EmStreamFile
+#include "ErrorHandling.h" // Errors::Throw
+#include "Hordes.h" // Hordes::AutoSaveState, etc.
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // EmValueChanger
+#include "PreferenceMgr.h" // Preference
+#include "ROMStubs.h" // EvtWakeup
+#include "SessionFile.h" // SessionFile
+#include "Strings.r.h" // kStr_EnterPen
+
+#include "EmMemory.h" // Memory::Initialize ();
+#include "Platform.h" // Platform::Initialize ();
+#include "DebugMgr.h" // Debug::Initialize ();
+#include "HostControlPrv.h" // Host::Initialize ();
+#include "EmScreen.h" // EmScreen::Initialize ();
+#include "ErrorHandling.h" // Errors::Initialize ();
+#include "EmPalmOS.h" // EmPalmOS::Initialize
+
+EmSession* gSession;
+
+static uint32 gLastButtonEvent;
+const uint32 kButtonEventThreshold = 100;
+
+#ifndef NDEBUG
+Bool gIterating = false;
+#endif
+
+Bool PrvCanBotherCPU (void);
+void PrvWakeUpCPU (long strID);
+
+
+/*
+ Sub-system methods:
+
+ Startup:
+ Called just once when Poser is started.
+
+ Initialize:
+ Called just once when a session is created. Will be followed
+ by one or more Reset or Load calls.
+
+ Reset:
+ Called any time the Reset menu item is selected or the SysReset
+ function is called.
+
+ Save:
+ Called to save the state to a file. May be called when the user
+ selects the Save menu item, when the user closes the session,
+ or as part of a Gremlin Horde auto-saving sequence.
+
+ Load:
+ Called to restore the saved state from a file. Can assume that
+ Initialize has been called first.
+
+ Dispose:
+ Called just once when a session is closed. May be called on a
+ partially constructed session, so Dispose methods should be
+ prepared to handle NULL pointers, etc.
+
+ Shutdown:
+ Called just once when Poser quits.
+*/
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::EmSession
+// ---------------------------------------------------------------------------
+// EmSession constructor. Initialize data members and point the global
+// "current EmSession" pointer to us. This method does not explicitly
+// throw any exceptions, and really shouldn't fail unless we've exhausted
+// the free store.
+
+EmSession::EmSession (void) :
+ fConfiguration (),
+ fFile (),
+ fCPU (NULL),
+#if HAS_OMNI_THREAD
+ fThread (NULL),
+ fSharedLock (),
+ fSharedCondition (&fSharedLock),
+ fSleepLock (),
+ fSleepCondition (&fSleepLock),
+ fStop (false),
+#endif
+ fSuspendState (),
+ fState (kStopped),
+ fBreakOnSysCall (false),
+ fNestLevel (0),
+ fReset (false),
+ fResetBanks (false),
+ fHordeAutoSaveState (false),
+ fHordeSaveRootState (false),
+ fHordeSaveSuspendState (false),
+ fHordeLoadRootState (false),
+ fHordeNextGremlinFromRootState (false),
+ fHordeNextGremlinFromSuspendState (false),
+ fMinimizeLoadState (false),
+ fDeferredErrs (),
+ fResetType (kResetSys),
+ fButtonQueue (),
+ fKeyQueue (),
+ fPenQueue (),
+ fLastPenEvent (EmPoint (-1, -1), false),
+ fBootKeys (0)
+{
+ fSuspendState.fAllCounters = 0;
+
+ EmAssert (gSession == NULL);
+ gSession = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::~EmSession
+// ---------------------------------------------------------------------------
+// EmSession destructor. Stop the CPU thread and release all resources.
+// Clear the global "current EmSession" pointer. This method really shouldn't
+// throw any exceptions or in any other way fail.
+
+EmSession::~EmSession (void)
+{
+ this->DestroyThread ();
+ this->Dispose ();
+
+ // Delete the CPU object here instead of in Dispose. When reloading a
+ // saved state as part of a Gremlin Horde procedure, EmSession::Load
+ // is called. That method calls Dispose, Initialize, and then the
+ // various Load methods of all the subsystems. This process is
+ // performed while the current session and cpu objects are active (that
+ // is, functions belonging to them are on the stack). Since Dispose is
+ // called, it would be unwise for Dispose to delete the active cpu object.
+
+ delete fCPU;
+ fCPU = NULL;
+
+ EmAssert (gSession == this);
+ gSession = NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CreateNew
+// ---------------------------------------------------------------------------
+// Create a new session based on the given configuration. This method can
+// throw an exception if the creation attemp fails (for instance, the
+// configuration is invalid, or if the free store is exhausted).
+
+void EmSession::CreateNew (const Configuration& cfg)
+{
+ EmAssert (!gApplication->IsBound ());
+
+ this->Initialize (cfg);
+ this->Reset (kResetSoft);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CreateOld
+// ---------------------------------------------------------------------------
+// Create a new session based on information stored in the given disk file.
+// If possible, the entire previously-saved state is restored. However, if
+// any critical information is missing from the file, the emulated state may
+// be reset so that it can be used (as if the user had used a pin to reset
+// an actual device). If the file is corrupted or missing even the basic
+// saved-state information, and exception is thrown.
+
+void EmSession::CreateOld (const EmFileRef& ref)
+{
+ EmAssert (!gApplication->IsBound ());
+
+ EmStreamFile stream (ref, kOpenExistingForRead);
+ ChunkFile chunkFile (stream);
+ SessionFile sessionFile (chunkFile);
+
+ // Load enough information so that we can initialize the system.
+
+ Configuration cfg;
+ if (!sessionFile.ReadConfiguration (cfg))
+ {
+ Errors::Throw (kError_InvalidSessionFile);
+ }
+
+ this->Initialize (cfg);
+
+ // Now load the saved state.
+
+ this->Load (sessionFile);
+
+ // Remember who we are.
+
+ fFile = ref;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CreateBound
+// ---------------------------------------------------------------------------
+// Create a new session based on information stored in resources or other data
+// attached to the emulator executable.
+
+void EmSession::CreateBound (void)
+{
+ EmAssert (gApplication->IsBound ());
+ EmAssert (gApplication);
+
+ Configuration cfg;
+
+ cfg.fDevice = gApplication->GetBoundDevice ();
+ cfg.fRAMSize = gApplication->GetBoundRAMSize ();
+// cfg.fROMFile ignored in Initialize (gets the ROM from the resource)
+
+ // Initialize the system.
+
+ this->Initialize (cfg);
+
+ // If there is session data, read that in and continue initializing
+ // (like in CreateOld).
+
+ if (gApplication->IsBoundFully ())
+ {
+ Chunk psf;
+ gApplication->GetPSFResource (psf);
+
+ EmStreamBlock stream (psf.GetPointer (), psf.GetLength ());
+ ChunkFile chunkFile (stream);
+ SessionFile sessionFile (chunkFile);
+
+ // Now load the saved state.
+
+ this->Load (sessionFile);
+ }
+
+ // Otherwise, reset the session (like in CreateNew).
+
+ else
+ {
+ this->Reset (kResetSoft);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Initialize
+// ---------------------------------------------------------------------------
+// Called by the various CreateFoo methods to initialize our state according
+// to the given configuration.
+
+void EmSession::Initialize (const Configuration& cfg)
+{
+ // Set the hardware device here. We need to have it set up now
+ // for things like EmBankSRAM::Initialize and Memory::Initialize,
+ // which need to know what mode they're in.
+
+ fConfiguration = cfg;
+
+ // Ideally, we can initialize sub-systems in any order.
+
+ EmAssert (!fCPU);
+ fCPU = this->GetDevice ().CreateCPU (this);
+
+ // If ROM is an embedded resouce, use it.
+
+ if (gApplication->IsBound ())
+ {
+ Chunk rom;
+
+#ifndef NDEBUG
+ Bool resourceLoaded = gApplication->GetROMResource (rom);
+ EmAssert (resourceLoaded);
+#else
+ gApplication->GetROMResource (rom);
+#endif
+
+ EmStreamChunk stream (rom);
+ Memory::Initialize (stream, cfg.fRAMSize);
+ }
+
+ // If ROM is not embedded, use the filespec.
+
+ else
+ {
+ EmStreamFile stream (cfg.fROMFile, kOpenExistingForRead);
+ Memory::Initialize (stream, cfg.fRAMSize);
+ }
+
+ Platform::Initialize ();
+ Debug::Initialize ();
+ Host::Initialize ();
+ EmScreen::Initialize ();
+ Errors::Initialize ();
+
+ EmPalmOS::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Dispose
+// ---------------------------------------------------------------------------
+
+void EmSession::Dispose (void)
+{
+ // Ideally, we can dispose sub-systems in any order. However,
+ // it's probably a good idea to dispose them in the reverse
+ // order in which they were initialized.
+ //
+ // Note also that this is called from the destructor, which could
+ // be called on an object that was not completely initialized.
+ // Therefore, each Dispose method should be prepared to handle
+ // NULL pointers, etc.
+
+ EmPalmOS::Dispose ();
+
+ Errors::Dispose ();
+ EmScreen::Dispose ();
+ Host::Dispose ();
+ Debug::Dispose ();
+ Platform::Dispose ();
+
+ Memory::Dispose ();
+
+ fInstructionBreakFuncs.clear ();
+ fDataBreakFuncs.clear ();
+
+ this->ClearDeferredErrors ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Reset
+// ---------------------------------------------------------------------------
+
+void EmSession::Reset (EmResetType resetType)
+{
+ /*
+ React to the various ways to reset as follows:
+
+ kResetSys
+ Not much to do here. We reset our internal state, but don't
+ reset any hardware registers.
+
+ kResetSoft
+ Same as above, but we also reset the hardware registers.
+
+ kResetHard
+ Same as above, but we also force the wiping out of the storage
+ heap by simulating the Power key down.
+
+ kResetDebug
+ Same as kResetSoft, but we also force the entering of the
+ Debugger by simulating the Page Down key down.
+
+
+ NOTES ON VARIOUS RESET SEQUENCES:
+ ---------------------------------
+ The ROM has three entry points for resetting: SoftReset, HardReset,
+ and DebugReset. From the ROM's comments:
+
+ // These two entry points are the soft and hard reset entry points
+ // The soft reset is called when the processor comes out of reset or
+ // when the SysReset call is executed.
+ // The hard reset is called when the SysColdBoot call is executed.
+
+ I can't find that DebugReset is called.
+
+ SoftReset sets D0 to 0 and branches to Reset. HardReset sets D0 to
+ -1 and branches to Reset. DebugReset sets D0 to 1 and falls through
+ to Reset. When Reset calls InitStage1, this value is passed as the
+ hardResetOrDebug parameter.
+
+ InitStage1 checks to see if hardResetOrDebug is 1. If so, it sets
+ it to zero, sets enterDebugger to true, and sets sysResetFlagGoingToDebugger
+ in GSysResetFlags.
+
+ Later in InitStage1, the Power key is checked (by calling KeyBootKeys)
+ and hardResetOrDebug is set to true (that is, 1) if it's down. Also,
+ the Page Down key is checked and enterDebugger is set to true if it's
+ down. (As an aside, the Page Up key is checked and the sysResetFlagNoExtensions
+ bit of GSysResetFlags is set if it's down.) After all this, if enterDebugger
+ is true, DbgBreak is called. Finally, InitStage2 is called with hardResetOrDebug
+ as the parameter.
+
+ InitStage2 merely calls SysLaunch with the value of the parameter
+ passed to it. At this point, the parameter is merely a Boolean
+ called "hardReset".
+
+ SysLaunch checks the state of the storage heap. If the heap looks bad,
+ then hardReset is forced to true. Next, if hardReset is true because
+ of the Power key, the user is asked if they want to erase the device's
+ contents (they are NOT asked this if the heap looks bad). Depending
+ on their choice (by pressing the Page Up key or not), hardReset is set
+ to true or false.
+
+ Finally if hardReset is true, MemCardFormat is called.
+ */
+
+ EmAssert (fNestLevel == 0);
+
+ // !!! Need to re-establish any pressed buttons.
+
+ // Perform any last minute cleanup.
+
+ // If we're resetting while running a Gremlin, save the events.
+
+ if (Hordes::IsOn ())
+ {
+ Hordes::SaveEvents ();
+ }
+
+ // Ideally, we can reset sub-systems in any order. However,
+ // it's probably a good idea to reset them in the same order
+ // in which they were initialized.
+
+ // Reset Memory *before* CPU, as the CPU looks at memory location
+ // zero to find it's reset address. Memory can't be accessed until
+ // the first call to Memory::ResetBankHandlers, which occurs at the
+ // end of Memory::Reset.
+
+ Memory::Reset ((resetType & kResetTypeMask) != kResetSys);
+
+ EmAssert (fCPU);
+ fCPU->Reset ((resetType & kResetTypeMask) != kResetSys);
+
+ Platform::Reset ();
+ Debug::Reset ();
+ Host::Reset ();
+ EmScreen::Reset ();
+ Errors::Reset ();
+
+ EmPalmOS::Reset ();
+
+
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ // Now reset self.
+
+// fSuspendState.fCounters.fSuspendByUIThread = 0;
+ fSuspendState.fCounters.fSuspendByDebugger = 0;
+ fSuspendState.fCounters.fSuspendByExternal = 0;
+// fSuspendState.fCounters.fSuspendByTimeout = 0;
+ fSuspendState.fCounters.fSuspendBySysCall = 0;
+ fSuspendState.fCounters.fSuspendBySubroutineReturn = 0;
+
+ fBreakOnSysCall = false;
+ fNestLevel = 0;
+
+ fReset = false;
+ fResetBanks = false;
+ fHordeAutoSaveState = false;
+ fHordeSaveRootState = false;
+ fHordeSaveSuspendState = false;
+ fHordeLoadRootState = false;
+ fHordeNextGremlinFromRootState = false;
+ fHordeNextGremlinFromSuspendState = false;
+ fMinimizeLoadState = false;
+
+ this->ClearDeferredErrors ();
+
+ fResetType = kResetSys;
+
+ // Don't clear these out on a SysReset call. kResetSys
+ // is also issued when transitioning between the small and
+ // big ROMs. In that case, we don't want to clear out the
+ // button queues in case we have a pending button up event
+ // to complete a button down event used for triggering a
+ // Hard, Debug, or No Extensions reset.
+
+ if ((resetType & kResetTypeMask) != kResetSys)
+ {
+ fButtonQueue.Clear ();
+ fKeyQueue.Clear ();
+ fPenQueue.Clear ();
+ }
+
+ fLastPenEvent = EmPenEvent (EmPoint (-1, -1), false);
+
+ // All of meta-memory gets wiped out on reset; re-establish these.
+
+ this->InstallInstructionBreaks ();
+ this->InstallDataBreaks ();
+
+ // Deal with the emulation of the pressing of the keys that
+ // modify the Reset sequence. We set the hardware bits here.
+ // After it looks like the key state has been read, the hardware
+ // emulation routines call EmSession::ReleaseBootKeys, where we
+ // reverse the bit setting.
+
+ fBootKeys = 0;
+
+ if ((resetType & kResetTypeMask) == kResetHard)
+ {
+ EmHAL::ButtonEvent (kElement_PowerButton, true);
+ fBootKeys |= 1L << kElement_PowerButton;
+ }
+ else if ((resetType & kResetTypeMask) == kResetDebug)
+ {
+ EmHAL::ButtonEvent (kElement_DownButton, true);
+ fBootKeys |= 1L << kElement_DownButton;
+ }
+
+ if ((resetType & kResetExtMask) == kResetNoExt)
+ {
+ EmHAL::ButtonEvent (kElement_UpButton, true);
+ fBootKeys |= 1L << kElement_UpButton;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Save
+// ---------------------------------------------------------------------------
+
+void EmSession::Save (SessionFile& f)
+{
+ // Write out the device type.
+
+ EmAssert (fConfiguration.fDevice.Supported ());
+ f.WriteDevice (fConfiguration.fDevice);
+
+ // Ideally, we can save sub-systems in any order. However,
+ // it's probably a good idea to save them in the same order
+ // in which they were initialized.
+
+ EmAssert (fCPU);
+ fCPU->Save (f);
+ Memory::Save (f);
+
+ Platform::Save (f);
+ Debug::Save (f);
+ Host::Save (f);
+ EmScreen::Save (f);
+ Errors::Save (f);
+
+ EmPalmOS::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Load
+// ---------------------------------------------------------------------------
+
+void EmSession::Load (SessionFile& f)
+{
+ // Load the saved state from the session file. First, set the flag
+ // that says whether or not we can successfully restart from the
+ // information in this file. As parts are loaded, the various
+ // sub-systems will have a chance to veto this optimistic assumption.
+
+ f.SetCanReload (true);
+
+ // Ideally, we can load sub-systems in any order. However,
+ // it's probably a good idea to load them in the same order
+ // in which they were initialized.
+
+ // Load Memory before EmCPU. That way, the memory system will be
+ // initialized when we restore the CPU registers (which will include
+ // a sanity check of the PC).
+
+ Memory::Load (f);
+
+ EmAssert (fCPU);
+ fCPU->Load (f);
+
+ Platform::Load (f);
+ Debug::Load (f);
+ Host::Load (f);
+ EmScreen::Load (f);
+ Errors::Load (f);
+
+ EmPalmOS::Load (f);
+
+ // If we weren't able to get all the pieces from the file we needed,
+ // force a reset.
+
+ if (!f.GetCanReload ())
+ {
+ this->Reset (kResetSoft);
+ fNeedPostLoad = false;
+ }
+
+ // Otherwise, set a flag saying that "post load" activities need to
+ // take place. These activities normally take place while the device
+ // is first booted up. However, any side-effect of those activities
+ // may no longer be valid (for instance, we may need to install or
+ // remove a 'gdbS' Feature).
+ //
+ // We set a flag to schedule these activities rather than performing
+ // them now, as the emulated state may not be in any shape to respond
+ // to them. For instance, the OS may not be able to handle a call to
+ // FtrSet at the moment. Therefore, we check for this flag at the next
+ // convenient moment and take action at that time.
+
+ else
+ {
+ fNeedPostLoad = true;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Save
+// ---------------------------------------------------------------------------
+
+void EmSession::Save (const EmFileRef& ref, Bool updateFileRef)
+{
+ EmStreamFile stream (ref, kCreateOrEraseForUpdate,
+ kFileCreatorEmulator, kFileTypeSession);
+ ChunkFile chunkFile (stream);
+ SessionFile sessionFile (chunkFile);
+
+ this->Save (sessionFile);
+
+ if (updateFileRef)
+ {
+ fFile = ref;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Load
+// ---------------------------------------------------------------------------
+
+void EmSession::Load (const EmFileRef& ref)
+{
+ EmStreamFile stream (ref, kOpenExistingForRead);
+ ChunkFile chunkFile (stream);
+ SessionFile sessionFile (chunkFile);
+
+ this->Load (sessionFile);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CreateThread
+// ---------------------------------------------------------------------------
+
+void EmSession::CreateThread (Bool suspended)
+{
+#if HAS_OMNI_THREAD
+ if (fThread)
+ return;
+
+ // Initialize some variables that control the thread state.
+
+ fStop = false;
+
+ fSuspendState.fAllCounters = 0;
+ fSuspendState.fCounters.fSuspendByUIThread = suspended ? 1 : 0;
+ fState = suspended ? kSuspended : kRunning;
+
+ // Create the thread and start it running.
+
+ fThread = new omni_thread (&EmSession::RunStatic, this);
+ fThread->start ();
+#else
+
+ // Initialize some variables that control the thread state.
+
+ fSuspendState.fAllCounters = 0;
+ fSuspendState.fCounters.fSuspendByUIThread = suspended ? 1 : 0;
+ fState = kSuspended;
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::DestroyThread
+// ---------------------------------------------------------------------------
+
+void EmSession::DestroyThread (void)
+{
+#if HAS_OMNI_THREAD
+ if (!fThread)
+ return;
+
+ omni_mutex_lock lock (fSharedLock);
+
+ fStop = true;
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ fSharedCondition.broadcast ();
+
+ while (fState != kStopped)
+ fSharedCondition.wait ();
+
+ // fThread thread will quit and destroy itself.
+
+ fThread = NULL;
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::SuspendThread
+// ---------------------------------------------------------------------------
+// Suspend the thread in the requested fashion. Returns true if the attempt
+// succeeded and the thread needs to be resumed with a call to ResumeThread.
+// Returns false if the thread could not or was not suspended, and
+// ResumeThread should not be called.
+
+Bool EmSession::SuspendThread (EmStopMethod how)
+{
+ if (how == kStopNone)
+ return false;
+
+#if HAS_OMNI_THREAD
+
+ EmAssert (fThread);
+
+ omni_mutex_lock lock (fSharedLock);
+
+ // Set a flag for the CPU thread to find, telling it how to stop.
+ //
+ // !!! What to do when fSuspendByUIThread, fSuspendByDebugger or
+ // fSuspendByExternal are set, especially if how == kStopOnSysCall?
+
+ Bool desiredBreakOnSysCall = false;
+
+// LogAppendMsg ("EmSession::SuspendThread (enter): fState = %ld", (long) fState);
+
+ switch (how)
+ {
+ case kStopNone:
+ EmAssert (false);
+ break;
+
+ case kStopNow:
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ break;
+
+ case kStopOnCycle:
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ break;
+
+ case kStopOnSysCall:
+ desiredBreakOnSysCall = true;
+ break;
+ }
+
+ // Get it to a suspended or blocked state, if not there already.
+ // Run the CPU loop until we are suspended or blocked on the UI.
+ //
+ // Note: if we're doing a kStopOnSysCall and the
+ // the thread's already been suspended by, say, kStopNow, then
+ // we might want to start the thread up again if it's OK.
+
+ if (fState == kRunning)
+ {
+ // Wake up the thread if it's sleeping.
+
+ fSleepLock.lock ();
+ fSleepCondition.broadcast ();
+ fSleepLock.unlock ();
+
+ // Wait for it to stop.
+ // !!! Do a timed wait in case we never reach the desired stop point?
+
+ while (fState == kRunning)
+ {
+ // Establish these inside the while loop. It's possible for them
+ // to get cleared in Reset, and we don't want that.
+ //
+ // More specifically, we're trying to prevent a condition that can
+ // occur when ending a CodeWarrior debug session. After clicking
+ // on the X button in CodeWarrior, we get an RPC packet for
+ // SysReset. In handling that packet, Poser merely sets the
+ // PC to the SysReset function address. When the CPU is
+ // restarted, it starts executing that code. When SysReset
+ // gets to the ultimate JSR to the reset vector, Poser notices
+ // that and call gSession->Reset(false). EmSession::Reset
+ // clears the fBreakOnSysCall flag.
+ //
+ // In the meantime, CodeWarrior has broken the socket connection
+ // to us. Poser responds to that by trying to unregister the
+ // 'gdbS' feature. In order to do that, it must halt the CPU
+ // on a system call. On my PC, the disconnect and call to
+ // FtrUnregister can happen *before* we get to this code here.
+ //
+ // So, here is the UI thread, waiting for a system call to
+ // occur. Before that can happen, the Reset code executes,
+ // clearing the fBreakOnSysCall flag! Thus, the UI thread keeps
+ // waiting for a system call to occur, while the CPU thread no
+ // longer thinks it needs to halt on that condition.
+
+ fBreakOnSysCall = desiredBreakOnSysCall;
+ fSharedCondition.broadcast ();
+
+ fSharedCondition.wait ();
+// LogAppendMsg ("EmSession::SuspendThread (waking): fState = %ld", (long) fState);
+
+#ifndef NDEBUG
+ if (!this->IsNested ())
+ {
+ if (how == kStopNow)
+ {
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread != 0 ||
+ this->fState == kBlockedOnUI);
+ }
+ else if (how == kStopOnCycle)
+ {
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread != 0);
+ }
+ }
+#endif
+ }
+ }
+
+#else
+
+ // Set a flag for the CPU thread to find, telling it how to stop.
+ //
+ // !!! What to do when fSuspendByUIThread, fSuspendByDebugger or
+ // fSuspendByExternal are set, especially if how == kStopOnSysCall?
+
+ switch (how)
+ {
+ case kStopNone:
+ EmAssert (false);
+ break;
+
+ case kStopNow:
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ break;
+
+ case kStopOnCycle:
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ break;
+
+ case kStopOnSysCall:
+ fBreakOnSysCall = true;
+ break;
+ }
+
+ // Run the CPU loop until we break at the right point.
+
+ fSuspendState.fCounters.fSuspendByTimeout = 0;
+
+ while (fState == kSuspended && fSuspendState.fAllCounters == 0)
+ {
+ this->ExecuteIncremental ();
+
+ // Ignore this suspend condition.
+
+ fSuspendState.fCounters.fSuspendByTimeout = 0;
+ }
+
+#endif
+
+ // Resulting state should be kSuspended or kBlockedOnUI. It should never
+ // be kStopped, because we didn't set the fStop flag.
+
+ EmAssert (fState == kSuspended || fState == kBlockedOnUI);
+
+
+ // Make sure we stopped the way we wanted to.
+ //
+ // If appropriate, clear the flag that got us here and say that the UI
+ // thread stopped us. If any other flags remain set, the client needs
+ // to deal with that.
+
+ Bool result = true; // assume we stopped OK
+
+ switch (how)
+ {
+ case kStopNone:
+ EmAssert (false);
+ break;
+
+ case kStopNow:
+ // Stopped on either "suspended" or "blocked" is OK.
+ result = true;
+ break;
+
+ case kStopOnCycle:
+ // Only "stopped on suspended" is OK
+ result = (fState == kSuspended);
+ break;
+
+ case kStopOnSysCall:
+ // Must be "stopped on suspended" and on a system call.
+ result = (fState == kSuspended) && fSuspendState.fCounters.fSuspendBySysCall;
+ if (result)
+ {
+ fSuspendState.fCounters.fSuspendByUIThread++;
+ }
+ break;
+ }
+
+ fBreakOnSysCall = false;
+
+ if (result)
+ {
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread > 0);
+ EmAssert (fSuspendState.fCounters.fSuspendBySubroutineReturn == 0);
+ EmAssert (fNestLevel == 0 || fState == kBlockedOnUI); // (If blocked on UI, fNestLevel may be > 0).
+ }
+
+// LogAppendMsg ("EmSession::SuspendThread (exit): fState = %ld", (long) fState);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ResumeThread
+// ---------------------------------------------------------------------------
+
+void EmSession::ResumeThread (void)
+{
+#if HAS_OMNI_THREAD
+ EmAssert (fThread);
+
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+// LogAppendMsg ("EmSession::ResumeThread (enter): fState = %ld", (long) fState);
+
+ if (fSuspendState.fCounters.fSuspendByUIThread > 0)
+ {
+ --fSuspendState.fCounters.fSuspendByUIThread;
+
+ if (fSuspendState.fCounters.fSuspendByUIThread == 0 &&
+ fSuspendState.fCounters.fSuspendByExternal == 0)
+ {
+ fSuspendState.fCounters.fSuspendBySysCall = 0;
+ }
+
+#if HAS_OMNI_THREAD
+ if (fSuspendState.fAllCounters == 0)
+ {
+ // Don't change the state if it's kBlockedOnUI.
+ if (fState == kSuspended)
+ {
+ fState = kRunning;
+ }
+ }
+
+ fSharedCondition.broadcast ();
+#endif
+ }
+
+// LogAppendMsg ("EmSession::ResumeThread (exit): fState = %ld", (long) fState);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Sleep
+// ---------------------------------------------------------------------------
+
+#if HAS_OMNI_THREAD
+void EmSession::Sleep (unsigned long msecs)
+{
+ const unsigned long kMillisecondsPerSecond = 1000;
+ const unsigned long kNanosecondsPerMillisecond = 1000000;
+
+ unsigned long secs = msecs / kMillisecondsPerSecond;
+ unsigned long nsecs = (msecs % kMillisecondsPerSecond) * kNanosecondsPerMillisecond;
+
+ fThread->get_time (&secs, &nsecs, secs, nsecs);
+
+ fSleepLock.lock ();
+ fSleepCondition.timedwait (secs, nsecs);
+ fSleepLock.unlock ();
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::InCPUThread
+// ---------------------------------------------------------------------------
+
+#if HAS_OMNI_THREAD
+Bool EmSession::InCPUThread (void) const
+{
+ return (omni_thread::self () == fThread);
+}
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetSessionState
+// ---------------------------------------------------------------------------
+
+EmSessionState EmSession::GetSessionState (void) const
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ return fState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetSuspendState
+// ---------------------------------------------------------------------------
+
+EmSuspendState EmSession::GetSuspendState (void) const
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+
+ if (this->InCPUThread ())
+ EmAssert (fState == kRunning);
+ else
+ EmAssert ((fNestLevel == 0 && fState != kRunning) || (fNestLevel > 0 && fState == kRunning));
+#endif
+
+ return fSuspendState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::SetSuspendState
+// ---------------------------------------------------------------------------
+
+void EmSession::SetSuspendState (const EmSuspendState& s)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+
+ if (this->InCPUThread ())
+ EmAssert (fState == kRunning);
+ else
+ EmAssert ((fNestLevel == 0 && fState != kRunning) || (fNestLevel > 0 && fState == kRunning));
+#endif
+
+ fSuspendState = s;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ExecuteIncremental
+// ---------------------------------------------------------------------------
+
+void EmSession::ExecuteIncremental (void)
+{
+// LogAppendMsg ("EmSession::ExecuteIncremental (enter): fState = %ld", (long) fState);
+
+ fSuspendState.fCounters.fSuspendByTimeout = 0;
+
+ EmAssert (fState == kSuspended || fState == kBlockedOnUI);
+ EmAssert (fSuspendState.fCounters.fSuspendByTimeout == 0);
+ EmAssert (fNestLevel == 0);
+
+ // Enter the CPU loop only if it's not suspended. The thread could
+ // be suspended if fSuspendByUIThread, fSuspendByDebugger or
+ // fSuspendByExternal are true.
+
+ if (fState == kBlockedOnUI)
+ return;
+
+ if (fSuspendState.fAllCounters == 0)
+ {
+ try
+ {
+ this->CallCPU ();
+ }
+ catch (EmExceptionReset& e)
+ {
+ e.Display ();
+ e.DoAction ();
+ }
+ catch (EmExceptionTopLevelAction& e)
+ {
+ e.DoAction ();
+ }
+ catch (...)
+ {
+ EmAssert (false);
+ }
+
+ /*
+ Check the reason for EmCPU::Execute returning:
+
+ fSuspendByUIThread
+ Should not happen. That flag is set if the UI thread asks
+ the CPU thread to suspend. ExecuteIncremental is called
+ on the Mac with no multiple threads.
+
+ fSuspendByDebugger
+ Could happen. Let it make this function exit. The debugger
+ should already have been notified.
+
+ fSuspendByExternal
+ Could happen. Let it make this function exit.
+
+ fSuspendByTimeout
+ Could happen. Let it make this function exit.
+
+ fSuspendBySysCall
+ Could happen. Let it make this function exit.
+
+ fSuspendBySubroutineReturn
+ Should not happen. Should occur only on calls to
+ ExecuteSubroutine.
+ */
+
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread == 0);
+ }
+
+ EmAssert (fState == kSuspended);
+ EmAssert (fSuspendState.fCounters.fSuspendBySubroutineReturn == 0);
+ EmAssert (fNestLevel == 0);
+
+// LogAppendMsg ("EmSession::ExecuteIncremental (exit): fState = %ld", (long) fState);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ExecuteSubroutine
+// ---------------------------------------------------------------------------
+
+void EmSession::ExecuteSubroutine (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ EmAssert (fNestLevel >= 0);
+
+// LogAppendMsg ("EmSession::ExecuteSubroutine (enter): fState = %ld", (long) fState);
+
+#if HAS_OMNI_THREAD
+ if (this->InCPUThread ())
+ EmAssert (fState == kRunning);
+ else
+ EmAssert ((fNestLevel == 0 && fState != kRunning) || (fNestLevel > 0 && fState == kRunning));
+#endif
+
+#ifndef NDEBUG
+ EmSuspendCounters origState = fSuspendState.fCounters;
+ Bool uiFlagChanged = false;
+#endif
+
+ EmSuspendCounters oldState = fSuspendState.fCounters;
+ fSuspendState.fAllCounters = 0;
+
+ while (fSuspendState.fAllCounters == 0)
+ {
+ // Enter new scope so that the omni_mutex_unlock will re-lock
+ // the mutex before we look at fSuspendState, etc.
+ {
+ EmValueChanger<int> oldNestLevel (fNestLevel, fNestLevel + 1);
+
+#if HAS_OMNI_THREAD
+ fSharedCondition.broadcast ();
+
+ omni_mutex_unlock unlock (fSharedLock);
+#endif
+
+ this->CallCPU ();
+ }
+
+ /*
+ Check the reason for EmCPU::Execute returning:
+
+ fSuspendByUIThread
+ fSuspendByExternal
+ fSuspendByTimeout
+ fSuspendBySysCall
+ Could happen. Remember that it occurred, clear it, and
+ re-enter the CPU loop. On the way out of this function
+ re-establish the request.
+
+ fSuspendByDebugger
+ Could happen. Let it make this function exit.
+
+ fSuspendBySubroutineReturn
+ Could happen. Let it make this function exit.
+ */
+
+#ifndef NDEBUG
+ if (fSuspendState.fCounters.fSuspendByUIThread)
+ {
+ uiFlagChanged = true;
+ }
+#endif
+
+ oldState.fSuspendByUIThread += fSuspendState.fCounters.fSuspendByUIThread;
+ fSuspendState.fCounters.fSuspendByUIThread = 0;
+
+ oldState.fSuspendByDebugger += fSuspendState.fCounters.fSuspendByDebugger;
+
+ oldState.fSuspendByExternal += fSuspendState.fCounters.fSuspendByExternal;
+ fSuspendState.fCounters.fSuspendByExternal = 0;
+
+ fSuspendState.fCounters.fSuspendBySysCall = 0;
+
+ oldState.fSuspendByTimeout |= fSuspendState.fCounters.fSuspendByTimeout;
+ fSuspendState.fCounters.fSuspendByTimeout = 0;
+ }
+
+ fSuspendState.fCounters = oldState;
+
+#ifndef NDEBUG
+ if (uiFlagChanged)
+ {
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread != origState.fSuspendByUIThread);
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread > 0);
+ }
+#endif
+
+ // This could have gone negative..._HostSignalWait will decrement the
+ // counter as a courtesy.
+
+ if (fSuspendState.fCounters.fSuspendByExternal < 0)
+ {
+ fSuspendState.fCounters.fSuspendByExternal = 0;
+ }
+
+ EmAssert (fNestLevel >= 0);
+
+#if HAS_OMNI_THREAD
+ if (this->InCPUThread ())
+ EmAssert (fState == kRunning);
+ else
+ EmAssert ((fNestLevel == 0 && fState != kRunning) || (fNestLevel > 0 && fState == kRunning));
+
+ fSharedCondition.broadcast ();
+#endif
+
+#ifndef NDEBUG
+ if (uiFlagChanged)
+ {
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread != origState.fSuspendByUIThread);
+ EmAssert (fSuspendState.fCounters.fSuspendByUIThread > 0);
+ }
+#endif
+
+// LogAppendMsg ("EmSession::ExecuteSubroutine (exit): fState = %ld", (long) fState);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ExecuteSpecial
+// ---------------------------------------------------------------------------
+
+Bool EmSession::ExecuteSpecial (Bool checkForResetOnly)
+{
+ if (fReset)
+ {
+ fReset = false;
+ fResetBanks = false;
+
+ this->Reset (fResetType);
+ }
+
+ if (fResetBanks)
+ {
+ fResetBanks = false;
+
+ Memory::ResetBankHandlers ();
+ }
+
+ if (!fDeferredErrs.empty ())
+ {
+#ifndef NDEBUG
+ gIterating = true;
+#endif
+
+ EmDeferredErrList::iterator iter = fDeferredErrs.begin ();
+
+ while (iter != fDeferredErrs.end ())
+ {
+ EmAssert (iter >= fDeferredErrs.begin ());
+ EmAssert (iter < fDeferredErrs.end ());
+
+ try
+ {
+ (*iter)->Do ();
+ }
+ catch (...)
+ {
+ // Clicking on Reset or Debug will throw an
+ // exception; we need to clean up from that.
+
+#ifndef NDEBUG
+ gIterating = false;
+#endif
+
+ this->ClearDeferredErrors ();
+
+ throw;
+ }
+
+ ++iter;
+ }
+
+#ifndef NDEBUG
+ gIterating = false;
+#endif
+
+ this->ClearDeferredErrors ();
+ }
+
+ if (checkForResetOnly)
+ return false;
+
+ if (fHordeAutoSaveState)
+ {
+ fHordeAutoSaveState = false;
+
+ Hordes::AutoSaveState ();
+ }
+
+ if (fHordeSaveRootState)
+ {
+ EmAssert (!fHordeSaveSuspendState);
+
+ EmAssert (!fHordeLoadRootState);
+ EmAssert (!fHordeNextGremlinFromRootState);
+ EmAssert (!fHordeNextGremlinFromSuspendState);
+
+ fHordeSaveRootState = false;
+
+ Hordes::SaveRootState ();
+ }
+
+ if (fHordeSaveSuspendState)
+ {
+ EmAssert (!fHordeSaveRootState);
+
+ EmAssert (!fHordeLoadRootState);
+ EmAssert (!fHordeNextGremlinFromRootState);
+ EmAssert (!fHordeNextGremlinFromSuspendState);
+
+ fHordeSaveSuspendState = false;
+
+ Hordes::SaveSuspendedState ();
+ }
+
+ if (fHordeLoadRootState)
+ {
+ EmAssert (!fHordeSaveSuspendState);
+ EmAssert (!fHordeSaveRootState);
+
+ EmAssert (!fHordeNextGremlinFromRootState);
+ EmAssert (!fHordeNextGremlinFromSuspendState);
+
+ fHordeLoadRootState = false;
+
+ Hordes::LoadRootState ();
+ }
+
+ if (fHordeNextGremlinFromRootState)
+ {
+ EmAssert (!fHordeSaveSuspendState);
+ EmAssert (!fHordeSaveRootState);
+
+ EmAssert (!fHordeLoadRootState);
+ EmAssert (!fHordeNextGremlinFromSuspendState);
+
+ fHordeNextGremlinFromRootState = false;
+
+ if (Hordes::LoadRootState () == errNone)
+ {
+ Hordes::StartGremlinFromLoadedRootState ();
+ }
+ else
+ {
+ Hordes::TurnOn (false);
+ }
+ }
+
+ if (fHordeNextGremlinFromSuspendState)
+ {
+ EmAssert (!fHordeSaveSuspendState);
+ EmAssert (!fHordeSaveRootState);
+
+ EmAssert (!fHordeLoadRootState);
+ EmAssert (!fHordeNextGremlinFromRootState);
+
+ fHordeNextGremlinFromSuspendState = false;
+
+ if (Hordes::LoadSuspendedState () == errNone)
+ {
+ Hordes::StartGremlinFromLoadedSuspendedState ();
+ }
+ else
+ {
+ Hordes::TurnOn (false);
+ }
+ }
+
+ if (fMinimizeLoadState)
+ {
+ fMinimizeLoadState = false;
+ EmMinimize::RealLoadInitialState ();
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CheckForBreak
+// ---------------------------------------------------------------------------
+// Check to see if the conditions tell us to break from the CPU Execute loop.
+
+Bool EmSession::CheckForBreak (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ if (fSuspendState.fAllCounters == 0)
+ return false;
+
+ // If nested, ignore fSuspendByExternal. If we're nested and it's
+ // non-zero, then that's because someone just made a HostControl call to
+ // change it. We need to let that call finish. Because we're in a
+ // nested call, fSuspendByExternal starts out at zero. Therefore, a
+ // call to suspend the CPU thread will increment it to 1, and a call to
+ // resume the thread will decrement it to -1. We need to preserve those
+ // values so that they can be integrated into the the state that was
+ // saved in EmSession::ExecuteSubroutine.
+
+ if (this->IsNested ())
+ {
+ int old = fSuspendState.fCounters.fSuspendByExternal;
+ fSuspendState.fCounters.fSuspendByExternal = 0;
+
+ Bool result = fSuspendState.fAllCounters != 0;
+
+ fSuspendState.fCounters.fSuspendByExternal = old;
+
+ return result;
+ }
+
+ return fSuspendState.fAllCounters != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::CallCPU
+// ---------------------------------------------------------------------------
+// Wrapper for EmCPU::Execute. Called by EmSession::ExecuteIncremental,
+// EmSession::ExecuteSubroutine, and EmSession::Run. This wrapper ensures
+// that the state is set to "running", calls EmCPU::Execute, and restores the
+// state to what it was before this function was called when it exits.
+
+void EmSession::CallCPU (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ EmValueChanger<EmSessionState> oldState (fState, kRunning);
+
+#if HAS_OMNI_THREAD
+ omni_mutex_unlock unlock (fSharedLock);
+#endif
+
+ EmAssert (fCPU);
+ fCPU->Execute ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::BlockOnDialog
+// ---------------------------------------------------------------------------
+// Schedule an error dialog to be displayed. If running on a multi-threaded
+// implementation, save the parameters and signal the UI thread to use them
+// to display a dialog box. Otherwise, if we are not on a multi-threaded
+// system, indicate that the session is suspended and safely call back into
+// EmDlg::RunDialog.
+//
+// The result of this function is the button used to dismiss the dialog. If
+// the UI thread is more interested in aborting the CPU thread instead of
+// displaying a dialog box, it will cause this function to return -1.
+
+EmDlgItemID EmSession::BlockOnDialog (EmDlgThreadFn fn, const void* parameters)
+{
+#if HAS_OMNI_THREAD
+ EmAssert (this->InCPUThread ());
+ EmAssert (gDocument);
+
+ omni_mutex_lock lock (fSharedLock);
+
+ EmDlgItemID result = kDlgItemNone;
+
+ gDocument->ScheduleDialog (fn, parameters, result);
+
+// LogAppendMsg ("EmSession::RunDialog (enter): fState = %ld", (long) fState);
+
+ {
+ EmValueChanger<EmSessionState> oldState (fState, kBlockedOnUI);
+
+ // Broadcast the change in fState.
+
+ fSharedCondition.broadcast ();
+
+ while (result == kDlgItemNone && !fStop)
+ {
+// LogAppendMsg ("EmSession::RunDialog (middle): fState = %ld", (long) fState);
+ EmAssert (fState == kBlockedOnUI);
+ fSharedCondition.wait ();
+ }
+ }
+
+ // Broadcast the change in fState.
+
+ fSharedCondition.broadcast ();
+
+// LogAppendMsg ("EmSession::RunDialog (exit): fState = %ld", (long) fState);
+
+ // !!! Throw an exception if fDialogResult == -1.
+
+ return result;
+
+#else
+
+// LogAppendMsg ("EmSession::RunDialog (enter): fState = %ld", (long) fState);
+
+ // Change the state so that (a) calling EmDlg::RunDialog will call
+ // EmDlg::HostRunDialog instead of calling back into here, and (b)
+ // so that EmSessionStopper's call to EmSession::SuspendThread
+ // doesn't complain when the state is kRunning.
+
+ EmValueChanger<EmSessionState> oldState (fState, kBlockedOnUI);
+
+ // Don't let the CPU loop run at idle.
+
+ EmSessionStopper stopper (this, kStopNow);
+
+ // Call back in to RunDialog now that the state has changed to
+ // indicate that the session is suspended in some way.
+
+ EmDlgItemID result = fn (parameters);
+
+// LogAppendMsg ("EmSession::RunDialog (exit): fState = %ld", (long) fState);
+
+ return result;
+
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::UnblockDialog
+// ---------------------------------------------------------------------------
+// Called by the UI thread after displaying a CPU thread-requested dialog,
+// reporting the button the user used to dismiss the dialog.
+
+#if HAS_OMNI_THREAD
+void EmSession::UnblockDialog (void)
+{
+ omni_mutex_lock lock (fSharedLock);
+ fSharedCondition.broadcast ();
+}
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::PostButtonEvent
+// ¥ EmSession::HasButtonEvent
+// ¥ EmSession::PeekButtonEvent
+// ¥ EmSession::GetButtonEvent
+// ---------------------------------------------------------------------------
+
+void EmSession::PostButtonEvent (const EmButtonEvent& event, Bool postNow)
+{
+ if (!::PrvCanBotherCPU())
+ return;
+
+ fButtonQueue.Put (event);
+
+ if (postNow)
+ {
+ gLastButtonEvent = Platform::GetMilliseconds () - kButtonEventThreshold;
+ }
+}
+
+
+Bool EmSession::HasButtonEvent (void)
+{
+ // Don't feed hardware events out too quickly. Otherwise, the OS
+ // may not have time to react to the register changes.
+
+ uint32 now = Platform::GetMilliseconds ();
+
+ if (now - gLastButtonEvent < kButtonEventThreshold)
+ {
+ return false;
+ }
+
+ return fButtonQueue.GetUsed () > 0;
+}
+
+
+EmButtonEvent EmSession::PeekButtonEvent (void)
+{
+ return fButtonQueue.Peek ();
+}
+
+
+EmButtonEvent EmSession::GetButtonEvent (void)
+{
+ // Don't feed hardware events out too quickly. Otherwise, the OS
+ // may not have time to react to the register changes.
+
+ gLastButtonEvent = Platform::GetMilliseconds ();
+
+ return fButtonQueue.Get ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::PostKeyEvent
+// ¥ EmSession::HasKeyEvent
+// ¥ EmSession::PeekKeyEvent
+// ¥ EmSession::GetKeyEvent
+// ---------------------------------------------------------------------------
+
+void EmSession::PostKeyEvent (const EmKeyEvent& event)
+{
+ if (!::PrvCanBotherCPU())
+ return;
+
+ fKeyQueue.Put (event);
+
+ // Wake up the CPU in case it's sleeping so that it can
+ // quickly handle the event.
+
+ ::PrvWakeUpCPU (kStr_EnterPen);
+}
+
+
+Bool EmSession::HasKeyEvent (void)
+{
+ return fKeyQueue.GetUsed () > 0;
+}
+
+
+EmKeyEvent EmSession::PeekKeyEvent (void)
+{
+ return fKeyQueue.Peek ();
+}
+
+
+EmKeyEvent EmSession::GetKeyEvent (void)
+{
+ return fKeyQueue.Get ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::PostPenEvent
+// ¥ EmSession::HasPenEvent
+// ¥ EmSession::PeekPenEvent
+// ¥ EmSession::GetPenEvent
+// ---------------------------------------------------------------------------
+
+void EmSession::PostPenEvent (const EmPenEvent& event)
+{
+ if (!::PrvCanBotherCPU())
+ return;
+
+ // If this pen-down event is the same as the last pen-down
+ // event, do nothing.
+
+ if (event.fPenIsDown && event == fLastPenEvent)
+ {
+ return;
+ }
+
+ // Add the event to our queue.
+
+ fPenQueue.Put (event);
+
+ // Remember this event for the next time.
+
+ fLastPenEvent = event;
+
+ // Wake up the CPU in case it's sleeping so that it can
+ // quickly handle the event.
+
+ ::PrvWakeUpCPU (kStr_EnterPen);
+}
+
+
+Bool EmSession::HasPenEvent (void)
+{
+ return fPenQueue.GetUsed () > 0;
+}
+
+
+EmPenEvent EmSession::PeekPenEvent (void)
+{
+ return fPenQueue.Peek ();
+}
+
+
+EmPenEvent EmSession::GetPenEvent (void)
+{
+ return fPenQueue.Get ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ReleaseBootKeys
+// ---------------------------------------------------------------------------
+
+void EmSession::ReleaseBootKeys (void)
+{
+ if (fBootKeys & (1L << kElement_PowerButton))
+ EmHAL::ButtonEvent (kElement_PowerButton, false);
+
+ if (fBootKeys & (1L << kElement_DownButton))
+ EmHAL::ButtonEvent (kElement_DownButton, false);
+
+ if (fBootKeys & (1L << kElement_UpButton))
+ EmHAL::ButtonEvent (kElement_UpButton, false);
+
+ fBootKeys = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCanBotherCPU
+// ---------------------------------------------------------------------------
+
+Bool PrvCanBotherCPU (void)
+{
+ if (Hordes::IsOn ())
+ return false;
+
+ if (EmEventPlayback::ReplayingEvents ())
+ return false;
+
+ if (EmMinimize::IsOn ())
+ return false;
+
+// if (!Patches::UIInitialized ())
+// return false;
+
+ // !!! Need a check for if the device is sleeping.
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvWakeUpCPU
+// ---------------------------------------------------------------------------
+
+void PrvWakeUpCPU (long strID)
+{
+ // Make sure the app's awake. Normally, we post events on a patch to
+ // SysEvGroupWait. However, if the Palm device is already waiting,
+ // then that trap will never get called. By calling EvtWakeup now,
+ // we'll wake up the Palm device from its nap.
+
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+
+ if (stopper.Stopped ())
+ {
+ Errors::ReportIfPalmError (strID, ::EvtWakeup ());
+ }
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetConfiguration
+// ---------------------------------------------------------------------------
+
+Configuration EmSession::GetConfiguration (void)
+{
+ return fConfiguration;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetFile
+// ---------------------------------------------------------------------------
+
+EmFileRef EmSession::GetFile (void)
+{
+ return fFile;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetDevice
+// ---------------------------------------------------------------------------
+
+EmDevice EmSession::GetDevice (void)
+{
+ return fConfiguration.fDevice;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetBreakOnSysCall
+// ---------------------------------------------------------------------------
+
+Bool EmSession::GetBreakOnSysCall (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ return fBreakOnSysCall;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::IsNested
+// ---------------------------------------------------------------------------
+
+#if 0 // Inlined
+Bool EmSession::IsNested (void)
+{
+ return fNestLevel > 0;
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::GetNeedPostLoad
+// ---------------------------------------------------------------------------
+
+Bool EmSession::GetNeedPostLoad (void)
+{
+ return fNeedPostLoad;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::SetNeedPostLoad
+// ---------------------------------------------------------------------------
+
+void EmSession::SetNeedPostLoad (Bool newValue)
+{
+ fNeedPostLoad = newValue;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ScheduleSuspendException
+// ¥ EmSession::ScheduleSuspendError
+// ¥ EmSession::ScheduleSuspendExternal
+// ¥ EmSession::ScheduleSuspendTimeout
+// ¥ EmSession::ScheduleSuspendSysCall
+// ¥ EmSession::ScheduleSuspendSubroutineReturn
+// ---------------------------------------------------------------------------
+
+void EmSession::ScheduleSuspendException (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendByDebugger++;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSuspendError (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendByDebugger++;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSuspendExternal (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendByExternal++;
+ fSuspendState.fCounters.fSuspendBySysCall = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSuspendTimeout (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendByTimeout = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSuspendSysCall (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendBySysCall = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSuspendSubroutineReturn (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ fSuspendState.fCounters.fSuspendBySubroutineReturn = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleResumeExternal (void)
+{
+#if HAS_OMNI_THREAD
+ omni_mutex_lock lock (fSharedLock);
+#endif
+
+ // Let it go negative. It needs to do this if we're resuming.
+ // See comments in EmCPU68K::CheckForBreak.
+
+// if (fSuspendState.fCounters.fSuspendByExternal)
+ {
+ fSuspendState.fCounters.fSuspendByExternal--;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::ScheduleReset
+// ¥ EmSession::ScheduleResetBanks
+// ¥ EmSession::ScheduleAutoSaveState
+// ¥ EmSession::ScheduleSaveRootState
+// ¥ EmSession::ScheduleSaveSuspendedState
+// ¥ EmSession::ScheduleLoadRootState
+// ¥ EmSession::ScheduleNextGremlinFromRootState
+// ¥ EmSession::ScheduleNextGremlinFromSuspendedState
+// ---------------------------------------------------------------------------
+
+void EmSession::ScheduleReset (EmResetType resetType)
+{
+ fReset = 1;
+ fResetType = resetType;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleResetBanks (void)
+{
+ fResetBanks = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleAutoSaveState (void)
+{
+ fHordeAutoSaveState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSaveRootState (void)
+{
+ fHordeSaveRootState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleSaveSuspendedState (void)
+{
+ fHordeSaveSuspendState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleLoadRootState (void)
+{
+ fHordeLoadRootState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleNextGremlinFromRootState (void)
+{
+ fHordeNextGremlinFromRootState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleNextGremlinFromSuspendedState (void)
+{
+ fHordeNextGremlinFromSuspendState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleMinimizeLoadState (void)
+{
+ fMinimizeLoadState = 1;
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ScheduleDeferredError (EmDeferredErr* err)
+{
+ EmAssert (gIterating == false);
+
+ fDeferredErrs.push_back (err);
+
+ EmAssert (fCPU);
+ fCPU->CheckAfterCycle ();
+}
+
+
+void EmSession::ClearDeferredErrors (void)
+{
+ EmAssert (gIterating == false);
+
+ EmDeferredErrList::iterator iter = fDeferredErrs.begin ();
+ while (iter != fDeferredErrs.end ())
+ {
+ delete *iter;
+ ++iter;
+ }
+
+ fDeferredErrs.clear ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::AddInstructionBreakHandlers
+// ---------------------------------------------------------------------------
+
+void EmSession::AddInstructionBreakHandlers ( InstructionBreakInstaller f1,
+ InstructionBreakRemover f2,
+ InstructionBreakReacher f3)
+{
+ InstructionBreakFuncs funcs;
+
+ funcs.fInstaller = f1;
+ funcs.fRemover = f2;
+ funcs.fReacher = f3;
+
+ fInstructionBreakFuncs.push_back (funcs);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::AddDataBreakHandlers
+// ---------------------------------------------------------------------------
+
+void EmSession::AddDataBreakHandlers ( DataBreakInstaller f1,
+ DataBreakRemover f2,
+ DataBreakReacher f3)
+{
+ DataBreakFuncs funcs;
+
+ funcs.fInstaller = f1;
+ funcs.fRemover = f2;
+ funcs.fReacher = f3;
+
+ fDataBreakFuncs.push_back (funcs);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::InstallInstructionBreaks
+// ---------------------------------------------------------------------------
+
+void EmSession::InstallInstructionBreaks (void)
+{
+ InstructionBreakFuncList::iterator iter = fInstructionBreakFuncs.begin ();
+
+ while (iter != fInstructionBreakFuncs.end ())
+ {
+ iter->fInstaller ();
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::RemoveInstructionBreaks
+// ---------------------------------------------------------------------------
+
+void EmSession::RemoveInstructionBreaks (void)
+{
+ InstructionBreakFuncList::iterator iter = fInstructionBreakFuncs.begin ();
+
+ while (iter != fInstructionBreakFuncs.end ())
+ {
+ iter->fRemover ();
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::HandleInstructionBreak
+// ---------------------------------------------------------------------------
+
+void EmSession::HandleInstructionBreak (void)
+{
+ InstructionBreakFuncList::iterator iter = fInstructionBreakFuncs.begin ();
+
+ while (iter != fInstructionBreakFuncs.end ())
+ {
+ iter->fReacher ();
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::InstallDataBreaks
+// ---------------------------------------------------------------------------
+
+void EmSession::InstallDataBreaks (void)
+{
+ DataBreakFuncList::iterator iter = fDataBreakFuncs.begin ();
+
+ while (iter != fDataBreakFuncs.end ())
+ {
+ iter->fInstaller ();
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::RemoveDataBreaks
+// ---------------------------------------------------------------------------
+
+void EmSession::RemoveDataBreaks (void)
+{
+ DataBreakFuncList::iterator iter = fDataBreakFuncs.begin ();
+
+ while (iter != fDataBreakFuncs.end ())
+ {
+ iter->fRemover ();
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::HandleDataBreak
+// ---------------------------------------------------------------------------
+
+void EmSession::HandleDataBreak (emuptr address, int size, Bool forRead)
+{
+ DataBreakFuncList::iterator iter = fDataBreakFuncs.begin ();
+
+ while (iter != fDataBreakFuncs.end ())
+ {
+ iter->fReacher (address, size, forRead);
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::RunStatic
+// ---------------------------------------------------------------------------
+
+#if HAS_OMNI_THREAD
+
+void EmSession::RunStatic (void* arg)
+{
+ EmAssert (arg);
+ ((EmSession*) arg)->Run ();
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSession::Run
+// ---------------------------------------------------------------------------
+
+#if HAS_OMNI_THREAD
+
+void EmSession::Run ()
+{
+ EmAssert (fCPU);
+
+ // Acquire the lock to the shared variables so that we can check fState.
+
+ omni_mutex_lock lock (fSharedLock);
+
+ // Loop until we're asked to stop.
+
+// LogAppendMsg ("EmSession::Run (enter): fState = %ld", (long) fState);
+
+ try
+ {
+ while (!fStop)
+ {
+// LogAppendMsg ("EmSession::Run (top outer loop): fState = %ld", (long) fState);
+
+ // Block while we're suspended. We set fState to kSuspended so
+ // that clients know our state, and unlock fSharedLock so that
+ // fSuspendState or fStop can be changed externally.
+ //
+ // While looping in our "blocked" loop, check to see if we're
+ // nested or not. If the CPU thread has been suspended, the UI
+ // thread may be making calls into EmSession methods. These
+ // methods could signal fSharedCondition as a matter of changing
+ // the session's state. While the UI thread is calling into the
+ // session, the session is considered to be "nested". We shouldn't
+ // resume from a suspended state until we are no longer nested.
+ // Otherwise, we could wake up before the UI thread is done with
+ // us. Why doesn't fSuspendState.fAllCounters prevent us from
+ // resuming? Because those flags are zeroed out when the UI thread
+ // calls into the session. Otherwise, the session wouldn't run
+ // in it's nested state.
+
+ if (fSuspendState.fAllCounters)
+ {
+ while (this->IsNested () || (fSuspendState.fAllCounters && !fStop))
+ {
+// LogAppendMsg ("EmSession::Run (top inner loop): fState = %ld", (long) fState);
+
+ // If we were asked to start, our state will have been set to kRunning.
+ // If we were asked to stop before we could actually start running,
+ // we need to set it to kSuspended again.
+
+ if (!this->IsNested ())
+ {
+ fState = kSuspended;
+ }
+
+ fSharedCondition.broadcast ();
+
+ fSharedCondition.wait ();
+ }
+
+// LogAppendMsg ("EmSession::Run (after inner loop): fState = %ld", (long) fState);
+
+ if (fStop)
+ {
+ continue;
+ }
+ }
+
+// LogAppendMsg ("EmSession::Run (after if): fState = %ld", (long) fState);
+
+ EmAssert (fSuspendState.fAllCounters == 0);
+ EmAssert (fNestLevel == 0);
+ EmAssert (fState == kRunning);
+
+ // We're no longer suspended. Release our shared globals.
+
+ fSharedLock.unlock ();
+
+ // Execute the "fetch an opcode and emulate it" loop. This
+ // function returns only if requested or an error occurs.
+
+ try
+ {
+ this->CallCPU ();
+ }
+ catch (EmExceptionReset& e)
+ {
+ e.Display ();
+ e.DoAction ();
+ }
+ catch (EmExceptionTopLevelAction& e)
+ {
+ e.DoAction ();
+ }
+ catch (...)
+ {
+ EmAssert (false);
+ }
+
+ fSharedLock.lock ();
+
+// LogAppendMsg ("EmSession::Run (after CallCPU): fState = %ld", (long) fState);
+
+ EmAssert (fState == kRunning);
+ EmAssert (fNestLevel == 0);
+ }
+ }
+ catch (...)
+ {
+ // We don't actually know if fSharedLock is acquired or
+ // not on this exception. Hopefully, its being unlocked
+ // if it's already unlocked is OK.
+ }
+
+ // fStop is set to true
+ // fSharedLock is locked
+
+ fState = kStopped;
+ fSharedCondition.broadcast ();
+}
+
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSessionStopper::EmSessionStopper
+// ---------------------------------------------------------------------------
+
+EmSessionStopper::EmSessionStopper (EmSession* cpu, EmStopMethod how) :
+ fSession (cpu),
+ fHow (how),
+ fStopped (false)
+{
+ if (fSession)
+ {
+ fStopped = fSession->SuspendThread (how);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSessionStopper::~EmSessionStopper
+// ---------------------------------------------------------------------------
+
+EmSessionStopper::~EmSessionStopper (void)
+{
+ if (fSession && fStopped)
+ {
+ fSession->ResumeThread ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSessionStopper::Stopped
+// ---------------------------------------------------------------------------
+
+Bool EmSessionStopper::Stopped (void)
+{
+ return fStopped;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSessionStopper::CanCall
+// ---------------------------------------------------------------------------
+
+Bool EmSessionStopper::CanCall (void)
+{
+ return (fSession != NULL) &&
+ (fHow == kStopOnSysCall) &&
+ (fStopped /*== true*/);
+}
diff --git a/SrcShared/EmSession.h b/SrcShared/EmSession.h
new file mode 100644
index 0000000..a514ad6
--- /dev/null
+++ b/SrcShared/EmSession.h
@@ -0,0 +1,728 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmSession_h
+#define EmSession_h
+
+#include "EmDevice.h" // EmDevice
+#include "EmDlg.h" // EmDlgItemID, EmCommonDialogFlags
+#include "EmThreadSafeQueue.h" // EmThreadSafeQueue
+#include "Skins.h" // SkinElementType
+
+#if HAS_OMNI_THREAD
+#include "omnithread.h" // omni_thread, omni_mutex, omni_condition
+#endif
+
+/*
+** EmSession is the class used to manage an emulation session. Its
+** responsibilities are:
+**
+** * Create new session
+** * Save session to disk
+** * Load old session from disk or resources
+** * Manage the "CPU loop"
+** * Synchronize with running session
+** * Destroy session
+**
+** That's the main abstraction. However, as you can tell from the
+** interface, a number of other duties have crept in, including:
+**
+** * UI interaction
+** * Gremlins coordination
+** * Instruction and data breakpoints
+*/
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmSuspendCounters
+// ---------------------------------------------------------------------------
+
+/*
+** The CPU loop can be suspended for any number of reasons by any number of
+** sources. EmSuspendCounters records which clients have requested that
+** the CPU loop be suspended and for what reason. To support nesting, it
+** keeps track of those statistics as counters instead of booleans. If
+** it's OK by any client for the CPU loop to run, its counter is zero.
+** Otherwise, it gets incremented to non-zero. When the CPU loop checks to
+** see if it's OK to run, it looks at all of these counters en masse via
+** the union nature of EmSuspendState.
+*/
+
+struct EmSuspendCounters
+{
+ // Incremented by calls to EmSession::SuspendThread. Decremented on
+ // calls to EmSession::ResumeThread. For executing commands, getting
+ // LCD data, etc.
+
+ int fSuspendByUIThread : 4;
+
+ // Incremented when an exception or error occurs. Decremented (or
+ // cleared) when the debugger sends a Continue packet.
+
+ int fSuspendByDebugger : 4;
+
+ // Incremented on calls to HostSessionSuspend, or an implicit
+ // scripting suspend occurred. Decremented on HostSessionResume.
+
+ int fSuspendByExternal : 4;
+
+ // Set when it's time for the CPU thread to exit after running for a
+ // little while. Used on the Mac, and on other systems when calling
+ // a Palm OS function that needs to occasionally return control (as
+ // when installing a file with the Exchange Manager).
+
+ int fSuspendByTimeout : 1;
+
+ // Set when we're leaving because we called Execute in order to spin
+ // the state up to a system call, and that state is reached.
+
+ int fSuspendBySysCall : 1;
+
+ // Set when we're leaving because we called Execute in order to call
+ // a subroutine, and that subroutine returned.
+
+ int fSuspendBySubroutineReturn : 1;
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmSuspendState
+// ---------------------------------------------------------------------------
+
+/*
+** EmSuspendState is a union of EmSuspendCounters and a 32-bit integer. Its
+** purpose is to allow the testing of *all* the suspend flags at once. If
+** any flag is set, then emulation is suspended.
+*/
+
+union EmSuspendState
+{
+ EmSuspendCounters fCounters;
+ uint32 fAllCounters;
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmSessionState
+// ---------------------------------------------------------------------------
+
+/*
+** The current state of the "CPU loop". If the stateis kSuspended, the
+** reason for that suspension can usually be found in EmSuspendState.
+*/
+
+enum EmSessionState
+{
+ kRunning, // The CPU thread is running.
+ kStopped, // The CPU thread is not started or has finished.
+ kSuspended, // The CPU thread is suspended at the end of a cycle.
+ kBlockedOnUI // The CPU thread is waiting for a dialog to be handled.
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmStopMethod
+// ---------------------------------------------------------------------------
+
+/*
+** An enumerated value passed to EmSessionStopper (or SuspendThread if it's
+** called directly) describing the way in which the thread should be
+** suspended.
+*/
+
+enum EmStopMethod
+{
+ kStopNone, // Don't stop the CPU.
+
+ kStopNow, // Suspend now, no matter what.
+
+ kStopOnCycle, // Suspend at the end of a cycle. This request may
+ // fail if the CPU thread is blocked on the UI.
+
+ kStopOnSysCall // Suspend on the next call to a system function. This
+ // request may fail if the CPU thread is block on the
+ // UI. The request may *hang* if the CPU thread is in
+ // a state such that it never reaches a system call.
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmButtonEvent
+// ---------------------------------------------------------------------------
+
+/*
+** Struct containing all data for a button event (that is, when the user
+** clicks the mouse on a hard button, or presses an FKEY bound to one of
+** the hard buttons).
+*/
+
+struct EmButtonEvent
+{
+ EmButtonEvent (SkinElementType button, Bool isDown) :
+ fButton (button),
+ fButtonIsDown (isDown)
+ {
+ }
+
+ SkinElementType fButton;
+ Bool fButtonIsDown;
+};
+
+typedef EmThreadSafeQueue<EmButtonEvent> EmButtonQueue;
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmKeyEvent
+// ---------------------------------------------------------------------------
+
+/*
+** Struct containing all data for a key event.
+*/
+
+struct EmKeyEvent
+{
+ EmKeyEvent (uint16 ch) :
+ fKey (ch),
+ fShiftDown (0),
+ fCapsLockDown (0),
+ fNumLockDown (0),
+ fCommandDown (0),
+ fOptionDown (0),
+ fControlDown (0),
+ fAltDown (0),
+ fWindowsDown (0)
+ {}
+
+ uint16 fKey;
+ Bool fShiftDown;
+ Bool fCapsLockDown;
+ Bool fNumLockDown;
+ Bool fCommandDown;
+ Bool fOptionDown;
+ Bool fControlDown;
+ Bool fAltDown;
+ Bool fWindowsDown;
+};
+
+typedef EmThreadSafeQueue<EmKeyEvent> EmKeyQueue;
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmPenEvent
+// ---------------------------------------------------------------------------
+
+/*
+** Struct containing all data for a pen event (that is, when the user clicks
+** the mouse in the touchscreen area).
+*/
+
+struct EmPenEvent
+{
+ EmPenEvent (const EmPoint& point, Bool isDown) :
+ fPenPoint (point),
+ fPenIsDown (isDown)
+ {
+ }
+
+ EmPoint fPenPoint;
+ Bool fPenIsDown;
+
+ bool operator==(const EmPenEvent& other) const
+ {
+ return fPenPoint == other.fPenPoint &&
+ fPenIsDown == other.fPenIsDown;
+ }
+};
+
+typedef EmThreadSafeQueue<EmPenEvent> EmPenQueue;
+
+
+// ---------------------------------------------------------------------------
+#pragma mark Instruction/DataBreak
+// ---------------------------------------------------------------------------
+
+/*
+** Data types and collections for managing functions that install, remove,
+** and respond to instruction and data breaks.
+**
+** Instruction breaks occur when the PC reaches an indicated memory location.
+** Data breaks occur when an indicated memory location is accessed (either
+** read or write). An instruction or instruction data fetch does not trigger
+** a data break. (!!! Actually, I think the latter does...should it?)
+*/
+
+typedef void (*InstructionBreakInstaller) (void);
+typedef void (*InstructionBreakRemover) (void);
+typedef void (*InstructionBreakReacher) (void);
+
+struct InstructionBreakFuncs
+{
+ InstructionBreakInstaller fInstaller;
+ InstructionBreakRemover fRemover;
+ InstructionBreakReacher fReacher;
+};
+
+typedef vector<InstructionBreakFuncs> InstructionBreakFuncList;
+
+
+typedef void (*DataBreakInstaller) (void);
+typedef void (*DataBreakRemover) (void);
+typedef void (*DataBreakReacher) (emuptr, int size, Bool forRead);
+
+struct DataBreakFuncs
+{
+ DataBreakInstaller fInstaller;
+ DataBreakRemover fRemover;
+ DataBreakReacher fReacher;
+};
+
+typedef vector<DataBreakFuncs> DataBreakFuncList;
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmSession
+// ---------------------------------------------------------------------------
+
+class EmCPU;
+class EmDeferredErr;
+class SessionFile;
+struct Configuration;
+
+typedef vector<EmDeferredErr*> EmDeferredErrList;
+
+class EmSession;
+extern EmSession* gSession;
+
+class EmSession
+{
+ public:
+ // -----------------------------------------------------------------------------
+ // constructor / destructor
+ // -----------------------------------------------------------------------------
+
+ EmSession (void);
+ ~EmSession (void);
+
+ // -----------------------------------------------------------------------------
+ // public methods
+ // -----------------------------------------------------------------------------
+
+ // Methods to create a new session. One of these methods must be called after
+ // creation the EmSession object. CreateNew creates a new session based on
+ // the data in Configuration. CreateOld reads a previously saved session from
+ // the given file. CreateBound reads a previously saved session from resources
+ // bound to the file.
+ //
+ // After a session has been created, the client needs to call CreateThread.
+ // If "true" is passed to CreateThread, the client also needs to call
+ // ResumeThread. (On the Mac, it only makes sense to pass "false".)
+
+ void CreateNew (const Configuration&);
+ void CreateOld (const EmFileRef&);
+ void CreateBound (void);
+
+ // Standard sub-system methods:
+ // Reset: Resets the state. Called on hardware resets or on
+ // calls to SysReset. Also called from constructor.
+ // Save: Saves the state to the given file.
+ // Load: Loads the state from the given file. Can assume that
+ // Reset has been called first.
+
+ void Reset (EmResetType);
+ void Save (SessionFile&);
+ void Load (SessionFile&);
+
+ // Utility methods that create a SessionFile for the given file, and then
+ // call the above Save and Load methods. If updateFileRef is true, then
+ // the EmFileRef is remembered as part of the session's "identity".
+
+ void Save (const EmFileRef&,
+ Bool updateFileRef);
+ void Load (const EmFileRef&);
+
+ // Called by external thread to create and destroy the thread. CreateThread
+ // is called after the EmSession is created. If "suspended" is true, the
+ // client should also call ResumeThread. If "suspended" is false, the
+ // thread will start running immediately. DestroyThread can be called
+ // manually, but will also be called in the destructor (getting called
+ // more than once is OK).
+
+ void CreateThread (Bool suspended);
+ void DestroyThread (void);
+
+ // Called by external thread to suspend and resume the CPU thread. Not
+ // normally called directly by clients. Instead, clients should use
+ // a stack-based EmSessionStopper object.
+
+ Bool SuspendThread (EmStopMethod how);
+ void ResumeThread (void);
+
+#if HAS_OMNI_THREAD
+ // Pause the thread by the given number of milliseconds.
+
+ void Sleep (unsigned long msecs);
+
+ // Return whether or not the calling function is executing in the context of
+ // the CPU thread or not. If not, it's most likely executing in the UI
+ // thread -- much of Poser assumes this is the case.
+ //
+ // It's not clear if this function should return true or false on single-
+ // threaded systems, so it's not available to those.
+
+ Bool InCPUThread (void) const;
+#endif
+
+ // GetSessionState returns the state of the CPU thread, as described in the
+ // definition of the EmSessionState type. If the thread is suspended, you
+ // can call GetSuspendState to find out why. After a thread has been
+ // suspended, you might need to clear the reason for it being suspended
+ // by calling SetSuspendState before calling ResumeThread.
+ //
+ // These methods are protected by their own mutex, and can be called
+ // by any thread.
+
+ EmSessionState GetSessionState (void) const;
+ EmSuspendState GetSuspendState (void) const;
+ void SetSuspendState (const EmSuspendState&);
+
+ // Called on the Mac at idle time to execute a little bit then leave.
+ // Also called by SuspendThread when the CPU state needs to be halted
+ // on a system call or when the Palm OS is idle.
+ //
+ // Clients should check the suspend state in order to make sure that
+ // ExecuteIncremental exitted for the right reason. If the reason was
+ // fSuspendByTimeout, this flag will automatically be cleared before
+ // the function returns. If the reason was fSuspendByDebugger, then
+ // the debugger will have already been contacted.
+ //
+ // If the suspend state is non-zero when this function is called, the
+ // function merely exits immediately.
+
+ void ExecuteIncremental (void);
+
+ // Called by mechanisms that allow the calling of Palm OS system functions
+ // as if they were Poser subroutines.
+ //
+ // Clients should check the suspend state in order to make sure that
+ // ExecuteSubroutine exitted for the right reason.
+ //
+ // If the suspend state is non-zero when this function is called, the
+ // function saves that state, clears the suspend flags, and then enters
+ // the CPU loop. The previous suspend state flags are restored on
+ // exit. If any benign suspend flags were set while executing the
+ // Palm OS subroutine (for instance, fSuspendByTimeout), those flags
+ // are applied to the previously-saved flags before they are restored.
+
+ void ExecuteSubroutine (void);
+
+ // Called by the CPU thread if any processor-independent "end of cycle"
+ // processing needs to be carried out (for instance, Gremlins needs to
+ // save a snapshot or needs to switch to a previously saved state).
+ //
+ // This method is also responsible for resetting the emulation state
+ // (either in response to a hardware reset or a call to SysReset).
+ // "checkForResetOnly" is true if *only* this responsibility should
+ // be carried out and any other duties should be skipped. If it's
+ // false, then all end-of-cycle duties should be carried out.
+
+ Bool ExecuteSpecial (Bool checkForResetOnly);
+
+ Bool CheckForBreak (void);
+
+ // Called by the CPU thread when it needs to display an error message.
+ // Do NOT call this from any other thread.
+
+ EmDlgItemID BlockOnDialog (EmDlgThreadFn fn,
+ const void* parameters);
+
+#if HAS_OMNI_THREAD
+ // Called by the UI thread when the dialog has been dismissed, or
+ // if a thread blocked on the UI needs to be stopped. In the
+ // former case, dialogResult should be set to the button that
+ // dismissed the dialog. In the latter case, dialogResult should
+ // be set to -1.
+
+ void UnblockDialog (void);
+#endif
+
+ // Methods for interacting with the UI:
+ //
+ // PostFooEvent:
+ // Called by the UI thread to post UI events. Clients need not
+ // synchronize with the CPU thread first. These methods will do
+ // whatever is needed.
+ //
+ // HasFooEvent:
+ // Returns true if there's an event posted to the queue.
+ //
+ // PeekFooEvent:
+ // Returns the top event on the queue, but doesn't remove it
+ // from the queue.
+ //
+ // GetFooEvent:
+ // Returns the top event from the queue and removes it from
+ // the queue.
+ //
+ // These methods are protected by their own mutex, and can be called
+ // by any thread.
+
+ void PostButtonEvent (const EmButtonEvent&, Bool postNow = false);
+ Bool HasButtonEvent (void);
+ EmButtonEvent PeekButtonEvent (void);
+ EmButtonEvent GetButtonEvent (void);
+
+ void PostKeyEvent (const EmKeyEvent&);
+ Bool HasKeyEvent (void);
+ EmKeyEvent PeekKeyEvent (void);
+ EmKeyEvent GetKeyEvent (void);
+
+ void PostPenEvent (const EmPenEvent&);
+ Bool HasPenEvent (void);
+ EmPenEvent PeekPenEvent (void);
+ EmPenEvent GetPenEvent (void);
+
+ void ReleaseBootKeys (void);
+
+ // Method for getting information on the device we're emulating.
+ // Callable at any time from any thread.
+
+ Configuration GetConfiguration (void);
+ EmFileRef GetFile (void);
+ EmDevice GetDevice (void);
+
+ // Methods for determining if emulation should halt at certain
+ // points. Called inside the CPU thread.
+
+ Bool GetBreakOnSysCall (void);
+
+ // Called by the CPU thread to determine if emulation code is being
+ // executed as part of normal emulation, or as part of a subroutine
+ // call into the Palm OS. Certain features may be enable or disabled
+ // as a result of this check (for instance, breakpoints are generally
+ // disabled when Poser is making a Palm OS subroutine call).
+
+ Bool IsNested (void);
+
+ // Methods for determining if post-load operations need to take
+ // place. Called inside the CPU thread.
+
+ Bool GetNeedPostLoad (void);
+ void SetNeedPostLoad (Bool);
+
+ // Schedule for the CPU thread to suspend. Called inside the CPU thread.
+
+ void ScheduleSuspendException (void);
+ void ScheduleSuspendError (void);
+ void ScheduleSuspendExternal (void);
+ void ScheduleSuspendTimeout (void);
+ void ScheduleSuspendSysCall (void);
+ void ScheduleSuspendSubroutineReturn (void);
+
+ void ScheduleResumeExternal (void);
+
+ // Schedule for stuff to happen at the end of the current instruction
+ // cycle. Called inside the CPU thread.
+
+ void ScheduleReset (EmResetType);
+ void ScheduleResetBanks (void);
+ void ScheduleAutoSaveState (void);
+ void ScheduleSaveRootState (void);
+ void ScheduleSaveSuspendedState (void);
+ void ScheduleLoadRootState (void);
+ void ScheduleNextGremlinFromRootState (void);
+ void ScheduleNextGremlinFromSuspendedState (void);
+ void ScheduleMinimizeLoadState (void);
+ void ScheduleDeferredError (EmDeferredErr*);
+
+ void ClearDeferredErrors (void);
+
+ // Provide routines that get called when it's appropriate to install an
+ // instruction break, when it's appropriate to remove an instruction break,
+ // or when an instruction break has been reached. Called by various
+ // sub-systems in their Initialize methods.
+
+ void AddInstructionBreakHandlers (InstructionBreakInstaller,
+ InstructionBreakRemover,
+ InstructionBreakReacher);
+
+ // Provide routines that get called when it's appropriate to install a
+ // data break, when it's appropriate to remove a data break, or when a
+ // data break has been reached. Called by various sub-systems in their
+ // Initialize methods.
+
+ void AddDataBreakHandlers (DataBreakInstaller,
+ DataBreakRemover,
+ DataBreakReacher);
+
+ // Call the installed routines to install/remove the breakpoints.
+
+ void InstallInstructionBreaks (void);
+ void RemoveInstructionBreaks (void);
+ void HandleInstructionBreak (void);
+
+ void InstallDataBreaks (void);
+ void RemoveDataBreaks (void);
+ void HandleDataBreak (emuptr, int size, Bool forRead);
+
+ private:
+ // Initialize the state of the session and all of it's sub-systems based
+ // on the given configuration. The configuration is also saved and can
+ // later be queried if needed.
+
+ void Initialize (const Configuration&);
+
+ // Dispose of all of our resources, as well as all of our sub-systems'.
+ // Called from the destructor (after first stopping the CPU thread).
+
+ void Dispose (void);
+
+#if HAS_OMNI_THREAD
+ // -----------------------------------------------------------------------------
+ // omni_thread overrides
+ // -----------------------------------------------------------------------------
+
+ static void RunStatic (void* arg);
+ void Run (void);
+#endif
+
+ void CallCPU (void);
+
+ private:
+ friend class EmCPU;
+ friend class EmCPU68K; // Accesses fSuspendState and fStop directly.
+
+ private:
+ Configuration fConfiguration;
+ EmFileRef fFile;
+
+ EmCPU* fCPU;
+
+#if HAS_OMNI_THREAD
+ // Accessed from external thread only.
+
+ omni_thread* fThread;
+
+ // Accessed from any thread.
+
+ mutable omni_mutex fSharedLock;
+ mutable omni_condition fSharedCondition;
+
+ omni_mutex fSleepLock;
+ omni_condition fSleepCondition;
+#endif
+
+ // ----------------------------------------------------------------------
+ // The variables in this section are protected by the mutex, and should
+ // not be accessed without first acquiring it.
+ // ----------------------------------------------------------------------
+
+#if HAS_OMNI_THREAD
+ // Set to true if the thread should quit. If set by an external
+ // thread, the CPU thread will notice the request, but not immediately.
+ // If set internally, the CPU thread should also set SPCFLAG_EXIT of
+ // regs.spcflags in order for it to get noticed.
+
+ Bool fStop;
+#endif
+
+ // Set to non-zero if the thread should pause. If set by an external
+ // thread, the CPU thread will notice the request, but not immediately.
+ // If set internally, the CPU thread should also set SPCFLAG_SUSPEND of
+ // regs.spcflags in order for it to get noticed.
+
+ EmSuspendState fSuspendState;
+
+ // Set to kStopped when the thread is about to quit.
+ //
+ // Set to kSuspended when the thread is about to suspend.
+ //
+ // Set to kBlockedOnUI when thread is waiting for UI thread
+ // to display a dialog. UI thread should set this
+ // to false after the dialog is displayed and dismissed.
+ //
+ // Otherwise, set to kRunning.
+
+ EmSessionState fState;
+
+ // These values are read in any thread at any time, but should only
+ // be changed after stopping the CPU thread. They're set up by the
+ // ExecuteUntilFoo methods.
+
+ Bool fBreakOnSysCall;
+ int fNestLevel;
+
+ Bool fNeedPostLoad;
+
+ // These values indicate that certain end-of-cycle actions
+ // should take place.
+
+ Bool fReset;
+ Bool fResetBanks;
+ Bool fHordeAutoSaveState;
+ Bool fHordeSaveRootState;
+ Bool fHordeSaveSuspendState;
+ Bool fHordeLoadRootState;
+ Bool fHordeNextGremlinFromRootState;
+ Bool fHordeNextGremlinFromSuspendState;
+ Bool fMinimizeLoadState;
+
+ EmDeferredErrList fDeferredErrs;
+
+ EmResetType fResetType;
+
+ private:
+ EmButtonQueue fButtonQueue;
+ EmKeyQueue fKeyQueue;
+ EmPenQueue fPenQueue;
+
+ EmPenEvent fLastPenEvent;
+ uint32 fBootKeys;
+
+ private:
+ InstructionBreakFuncList fInstructionBreakFuncs;
+ DataBreakFuncList fDataBreakFuncs;
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark EmSessionStopper
+// ---------------------------------------------------------------------------
+
+/*
+** Stack object used to briefly stop the emulator.
+*/
+
+class EmSessionStopper
+{
+ public:
+ EmSessionStopper (EmSession*, EmStopMethod how);
+ ~EmSessionStopper (void);
+
+ Bool Stopped (void);
+ Bool CanCall (void);
+
+ private:
+ EmSession* fSession;
+ int fHow;
+ Bool fStopped;
+};
+
+
+// Inlined because it's called from EmCPU68K::Execute on every opcode.
+
+inline Bool EmSession::IsNested (void)
+{
+ return fNestLevel > 0;
+}
+
+#endif /* EmSession_h */
diff --git a/SrcShared/EmStream.cpp b/SrcShared/EmStream.cpp
new file mode 100644
index 0000000..d513de0
--- /dev/null
+++ b/SrcShared/EmStream.cpp
@@ -0,0 +1,591 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+// ===========================================================================
+// EmStream.cpp ©1993-1998 Metrowerks Inc. All rights reserved.
+// ===========================================================================
+//
+// Abstract class for reading/writing an ordered sequence of bytes
+
+#include "EmCommon.h"
+#include "EmStream.h"
+
+#include "Byteswapping.h" // Canonical
+
+
+#pragma mark --- Construction & Destruction ---
+
+// ---------------------------------------------------------------------------
+// ¥ EmStream
+// ---------------------------------------------------------------------------
+// Default Constructor
+
+EmStream::EmStream (void) :
+ mMarker (0),
+ mLength (0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ~EmStream
+// ---------------------------------------------------------------------------
+// Destructor
+
+EmStream::~EmStream (void)
+{
+}
+
+
+#pragma mark --- Accessors ---
+
+// ---------------------------------------------------------------------------
+// ¥ SetMarker
+// ---------------------------------------------------------------------------
+// Place the Read/Write Marker at an offset from a specified position
+//
+// inFromWhere can be streamFrom_Start, streamFrom_End, or streamFrom_Marker
+
+void
+EmStream::SetMarker (
+ int32 inOffset,
+ StreamFromType inFromWhere)
+{
+ int32 newMarker = mMarker;
+
+ switch (inFromWhere)
+ {
+ case kStreamFromStart:
+ newMarker = inOffset;
+ break;
+
+ case kStreamFromEnd:
+ newMarker = this->GetLength () - inOffset;
+ break;
+
+ case kStreamFromMarker:
+ newMarker += inOffset;
+ break;
+ }
+
+ if (newMarker < 0) // marker must be between 0 and Length, inclusive
+ {
+ newMarker = 0;
+ }
+ else if (newMarker > GetLength ())
+ {
+ newMarker = this->GetLength ();
+ }
+
+ mMarker = newMarker;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetMarker
+// ---------------------------------------------------------------------------
+// Return the Read/Write Marker position
+//
+// Position is a byte offset from the start of the Stream
+
+int32
+EmStream::GetMarker (void) const
+{
+ return mMarker;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SetLength
+// ---------------------------------------------------------------------------
+// Set the length, in bytes, of the Stream
+
+void
+EmStream::SetLength(
+ int32 inLength)
+{
+ int32 oldLength = this->GetLength ();
+ mLength = inLength;
+ // If making Stream shorter, call
+ // SetMarker to make sure that
+ if (oldLength > inLength) // marker is not past the end
+ {
+ this->SetMarker (this->GetMarker (), kStreamFromStart);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetLength
+// ---------------------------------------------------------------------------
+// Return the length, in bytes, of the Stream
+
+int32
+EmStream::GetLength (void) const
+{
+ return mLength;
+}
+
+#pragma mark --- Low-Level I/O ---
+
+// ---------------------------------------------------------------------------
+// ¥ PutBytes
+// ---------------------------------------------------------------------------
+// Write bytes from a buffer to a Stream
+//
+// Returns an error code and passes back the number of bytes actually
+// written, which may be less than the number requested if an error occurred.
+//
+// Subclasses must override this function to support writing.
+//
+// NOTE: You should not throw an Exception out of this function.
+
+ErrCode
+EmStream::PutBytes (
+ const void* inBuffer,
+ int32 ioByteCount)
+{
+ UNUSED_PARAM(inBuffer)
+ UNUSED_PARAM(ioByteCount)
+
+ return 1;
+}
+
+
+EmStream&
+EmStream::operator << (const char* inString)
+{
+ WriteCString (inString);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (const string& inString)
+{
+ WriteString (inString);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (int8 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (uint8 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (char inChar)
+{
+ Canonical (inChar);
+ PutBytes (&inChar, sizeof (inChar));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (int16 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (uint16 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (int32 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (uint32 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (int64 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (uint64 inNum)
+{
+ Canonical (inNum);
+ PutBytes (&inNum, sizeof (inNum));
+ return (*this);
+}
+
+EmStream&
+EmStream::operator << (bool inBool)
+{
+ Canonical (inBool);
+ PutBytes (&inBool, sizeof (inBool));
+ return (*this);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetBytes
+// ---------------------------------------------------------------------------
+// Read bytes from a Stream to a buffer
+//
+// Returns an error code and passes back the number of bytes actually
+// read, which may be less than the number requested if an error occurred.
+//
+// Subclasses must override this function to support reading.
+//
+// NOTE: You should not throw an Exception out of this function.
+
+ErrCode
+EmStream::GetBytes (
+ void* outBuffer,
+ int32 ioByteCount)
+{
+ UNUSED_PARAM(outBuffer)
+ UNUSED_PARAM(ioByteCount)
+
+ return 1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PeekData
+// ---------------------------------------------------------------------------
+// Read data from a Stream to a buffer, without moving the Marker
+//
+// Return the number of bytes actually read, which may be less than the
+// number requested if an error occurred
+
+int32
+EmStream::PeekData (
+ void* outBuffer,
+ int32 inByteCount)
+{
+ int32 currentMarker = this->GetMarker ();
+
+ int32 bytesToPeek = inByteCount;
+ this->GetBytes (outBuffer, bytesToPeek);
+
+ this->SetMarker (currentMarker, kStreamFromStart);
+
+ return bytesToPeek;
+}
+
+EmStream&
+EmStream::operator >> (char* outString)
+{
+ ReadCString (outString);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (string& outString)
+{
+ ReadString (outString);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (int8 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (uint8 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (char &outChar)
+{
+ GetBytes (&outChar, sizeof (outChar));
+ Canonical (outChar);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (int16 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (uint16 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (int32 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (uint32 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (int64 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (uint64 &outNum)
+{
+ GetBytes (&outNum, sizeof (outNum));
+ Canonical (outNum);
+ return (*this);
+}
+
+EmStream&
+EmStream::operator >> (bool &outBool)
+{
+ GetBytes (&outBool, sizeof (outBool));
+ Canonical (outBool);
+ return (*this);
+}
+
+
+#pragma mark --- High-Level I/O ---
+
+// ---------------------------------------------------------------------------
+// ¥ WriteCString
+// ---------------------------------------------------------------------------
+// Write a C string to a Stream
+//
+// Returns the number of bytes written.
+
+int32
+EmStream::WriteCString (
+ const char* inString)
+{
+ EmAssert (inString);
+
+ int32 strLen = strlen (inString);
+
+ // Write C string as a 4-byte count followed by the characters.
+ // Do not write the null terminator.
+
+ *this << strLen;
+ this->PutBytes (inString, strLen);
+
+ return (strLen + (int32) sizeof (strLen));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ReadCString
+// ---------------------------------------------------------------------------
+// Read a C string from a Stream
+//
+// Returns the number of bytes read
+
+int32
+EmStream::ReadCString (
+ char* outString)
+{
+ EmAssert (outString);
+
+ // C string is stored as a 4-byte count followed by the
+ // characters. The null terminator is not stored and must
+ // be added afterwards.
+
+ int32 strLen;
+ *this >> strLen;
+
+ this->GetBytes (outString, strLen);
+ outString[strLen] = '\0'; // Null terminator
+
+ return (strLen + (int32) sizeof (int32));
+}
+
+// ---------------------------------------------------------------------------
+// ¥ WriteString
+// ---------------------------------------------------------------------------
+// Write a C string to a Stream
+//
+// Returns the number of bytes written.
+
+int32
+EmStream::WriteString (
+ const string& inString)
+{
+ return this->WriteCString (inString.c_str ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ReadString
+// ---------------------------------------------------------------------------
+// Read a C string from a Stream
+//
+// Returns the number of bytes read
+
+int32
+EmStream::ReadString(
+ string& outString)
+{
+ // C string is stored as a 4-byte count followed by the
+ // characters. The null terminator is not stored and must
+ // be added afterwards.
+
+ int32 strLen;
+ *this >> strLen;
+
+ outString.resize (strLen);
+ if (strLen > 0)
+ {
+ GetBytes(&outString[0], strLen);
+ }
+
+ return (strLen + (int32) sizeof (int32));
+}
+
+
+// ===========================================================================
+// EmStreamBlock.cpp ©1993-1998 Metrowerks Inc. All rights reserved.
+// ===========================================================================
+//
+// A Stream whose bytes are in a Chunk
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmStreamBlock(Handle) Parameterized Constructor [public]
+// ---------------------------------------------------------------------------
+// Construct from an existing Chunk
+
+EmStreamBlock::EmStreamBlock(void* data, int32 length) :
+ EmStream (),
+ fData (data)
+{
+ EmStream::SetLength (length);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ~EmStreamBlock Destructor [public]
+// ---------------------------------------------------------------------------
+
+EmStreamBlock::~EmStreamBlock()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SetLength [public]
+// ---------------------------------------------------------------------------
+// Set the length, in bytes, of the EmStreamBlock
+
+void
+EmStreamBlock::SetLength(
+ int32 /*inLength*/)
+{
+ // Do nothing...can't change the length.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PutBytes
+// ---------------------------------------------------------------------------
+// Write bytes from a buffer to a EmStreamBlock
+//
+// Returns an error code and passes back the number of bytes actually
+// written, which may be less than the number requested if an error occurred.
+//
+// Grows data Chunk if necessary.
+
+ErrCode
+EmStreamBlock::PutBytes(
+ const void* inBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ int32 endOfWrite = this->GetMarker () + ioByteCount;
+
+ if (endOfWrite > this->GetLength ()) // Need to grow Chunk
+ {
+ this->SetLength (endOfWrite);
+ }
+ // Copy bytes into Chunk
+ if (ioByteCount > 0)
+ {
+ memmove ((char*) fData + this->GetMarker (), inBuffer, ioByteCount);
+ this->SetMarker (ioByteCount, kStreamFromMarker);
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetBytes
+// ---------------------------------------------------------------------------
+// Read bytes from a EmStreamBlock to a buffer
+//
+// Returns an error code and passes back the number of bytes actually
+// read, which may be less than the number requested if an error occurred.
+//
+// Errors:
+// readErr Attempt to read past the end of the EmStreamBlock
+
+ErrCode
+EmStreamBlock::GetBytes(
+ void* outBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ // Upper bound is number of bytes from
+ // marker to end
+ if ((this->GetMarker () + ioByteCount) > this->GetLength ())
+ {
+ ioByteCount = this->GetLength () - this->GetMarker ();
+ err = 1;
+ }
+ // Copy bytes from Handle into buffer
+
+ memmove (outBuffer, (char*) fData + this->GetMarker (), ioByteCount);
+ this->SetMarker (ioByteCount, kStreamFromMarker);
+
+ return err;
+}
diff --git a/SrcShared/EmStream.h b/SrcShared/EmStream.h
new file mode 100644
index 0000000..47c25de
--- /dev/null
+++ b/SrcShared/EmStream.h
@@ -0,0 +1,387 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+// ===========================================================================
+// EmStream.h ©1993-1998 Metrowerks Inc. All rights reserved.
+// ===========================================================================
+//
+// Abstract class for reading/writing an ordered sequence of bytes
+
+#ifndef EmStream_h
+#define EmStream_h
+
+#include "EmTypes.h" // ErrCode
+
+#include <deque>
+#include <list>
+#include <string>
+#include <vector>
+
+// ---------------------------------------------------------------------------
+
+enum StreamFromType
+{
+ kStreamFromStart = 1,
+ kStreamFromEnd,
+ kStreamFromMarker
+};
+
+// ---------------------------------------------------------------------------
+
+class EmStream
+{
+ public:
+ EmStream (void);
+ virtual ~EmStream (void);
+
+ virtual void SetMarker (int32 inOffset,
+ StreamFromType inFromWhere);
+ virtual int32 GetMarker (void) const;
+
+ virtual void SetLength (int32 inLength);
+ virtual int32 GetLength (void) const;
+
+ Bool AtEnd (void) const
+ {
+ return GetMarker () >= GetLength ();
+ }
+
+ // Write Operations
+
+ virtual ErrCode PutBytes (const void* inBuffer,
+ int32 ioByteCount);
+
+ EmStream& operator << (const char* inString);
+ EmStream& operator << (const string& inString);
+ EmStream& operator << (int8 inNum);
+ EmStream& operator << (uint8 inNum);
+ EmStream& operator << (char inChar);
+ EmStream& operator << (int16 inNum);
+ EmStream& operator << (uint16 inNum);
+ EmStream& operator << (int32 inNum);
+ EmStream& operator << (uint32 inNum);
+ EmStream& operator << (int64 inNum);
+ EmStream& operator << (uint64 inNum);
+ EmStream& operator << (bool inBool);
+
+ // Read Operations
+
+ virtual ErrCode GetBytes (void* outBuffer,
+ int32 ioByteCount);
+ int32 PeekData (void* outButter,
+ int32 inByteCount);
+
+ EmStream& operator >> (char* outString);
+ EmStream& operator >> (string& outString);
+ EmStream& operator >> (int8 &outNum);
+ EmStream& operator >> (uint8 &outNum);
+ EmStream& operator >> (char &outChar);
+ EmStream& operator >> (int16 &outNum);
+ EmStream& operator >> (uint16 &outNum);
+ EmStream& operator >> (int32 &outNum);
+ EmStream& operator >> (uint32 &outNum);
+ EmStream& operator >> (int64 &outNum);
+ EmStream& operator >> (uint64 &outNum);
+ EmStream& operator >> (bool &outBool);
+
+ template <class T>
+ EmStream& operator >> (deque<T>& container)
+ {
+ Int32 numElements;
+ *this >> numElements;
+
+ container.resize (numElements);
+
+ deque<T>::iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this >> *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ EmStream& operator >> (list<T>& container)
+ {
+ Int32 numElements;
+ *this >> numElements;
+
+ container.resize (numElements);
+
+ list<T>::iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this >> *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ EmStream& operator >> (vector<T>& container)
+ {
+ Int32 numElements;
+ *this >> numElements;
+
+ container.resize (numElements);
+
+ vector<T>::iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this >> *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ EmStream& operator << (const deque<T>& container)
+ {
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ deque<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ EmStream& operator << (const list<T>& container)
+ {
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ list<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+ template <class T>
+ EmStream& operator << (const vector<T>& container)
+ {
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ vector<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ ++iter;
+ }
+
+ return *this;
+ }
+
+
+ // Data-specific read/write functions
+ // There is an equivalent Shift operator for each one
+ // except WritePtr/ReadPtr (since Ptr is really a char*,
+ // which is the same as a C string).
+
+ int32 WriteCString (const char* inString);
+ int32 ReadCString (char* outString);
+
+ int32 WriteString (const string& inString);
+ int32 ReadString (string& outString);
+
+ int PrintF (const char* fmt, ...);
+ int ScanF (const char* fmt, ...);
+
+ int PutC (int);
+ int GetC (void);
+
+ int PutS (const char*);
+ char* GetS (char*, int n);
+
+ protected:
+ int32 mMarker;
+ int32 mLength;
+};
+
+
+
+
+inline EmStream& operator << (EmStream& s, const MemPtr& p)
+{
+ s << (emuptr) p;
+
+ return s;
+}
+
+inline EmStream& operator >> (EmStream& s, MemPtr& p)
+{
+ emuptr t;
+ s >> t;
+
+ p = (MemPtr) t;
+
+ return s;
+}
+
+inline EmStream& operator << (EmStream& s, const MemHandle& h)
+{
+ s << (emuptr) h;
+
+ return s;
+}
+
+inline EmStream& operator >> (EmStream& s, MemHandle& h)
+{
+ emuptr t;
+ s >> t;
+
+ h = (MemHandle) t;
+
+ return s;
+}
+
+
+#if 0
+ // Although the MSL headers indicate that it can support member template
+ // functions (see _MSL_MUST_INLINE_MEMBER_TEMPLATE in mslconfig), the
+ // following out-of-line definitions result in a compilation error. So,
+ // for now, the definitions are in-line.
+
+template <class T>
+EmStream& EmStream::operator>> (deque<T>& container)
+{
+ Int32 numElements;
+ *this >> numElements;
+
+ container.clear ();
+
+ for (Int32 ii = 0; ii < numElements; ++ii)
+ {
+ T object;
+ *this >> object;
+ container.push_back (object);
+ }
+
+ return *this;
+}
+
+
+template <class T>
+EmStream& EmStream::operator<T> >> (list<T>& container)
+{
+ Int32 numElements;
+ *this >> numElements;
+
+ container.clear ();
+
+ for (Int32 ii = 0; ii < numElements; ++ii)
+ {
+ T object;
+ *this >> object;
+ container.push_back (object);
+ }
+
+ return *this;
+}
+
+
+template <class T>
+EmStream& EmStream::operator<T> >> (vector<T>& container)
+{
+ Int32 numElements;
+ *this >> numElements;
+
+ container.clear ();
+
+ for (Int32 ii = 0; ii < numElements; ++ii)
+ {
+ T object;
+ *this >> object;
+ container.push_back (object);
+ }
+
+ return *this;
+}
+
+
+template <class T>
+EmStream& EmStream::operator<T> << (const deque<T>& container)
+{
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ const deque<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ }
+
+ return *this;
+}
+
+
+template <class T>
+EmStream& EmStream::operator<T> << (const list<T>& container)
+{
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ const list<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ }
+
+ return *this;
+}
+
+
+template <class T>
+EmStream& EmStream::operator<T> << (const vector<T>& container)
+{
+ Int32 numElements = container.size ();
+
+ *this << numElements;
+
+ const vector<T>::const_iterator iter = container.begin ();
+ while (iter != container.end ())
+ {
+ *this << *iter;
+ }
+
+ return *this;
+}
+#endif /* if 0 */
+
+class EmStreamBlock : public EmStream
+{
+ public:
+ EmStreamBlock (void*, int32);
+ virtual ~EmStreamBlock (void);
+
+ virtual void SetLength (int32 inLength);
+
+ virtual ErrCode PutBytes (const void* inBuffer,
+ int32 ioByteCount);
+ virtual ErrCode GetBytes (void* outBuffer,
+ int32 ioByteCount);
+
+ private:
+ void* fData;
+};
+
+
+
+#endif /* EmStream_h */
diff --git a/SrcShared/EmStreamFile.cpp b/SrcShared/EmStreamFile.cpp
new file mode 100644
index 0000000..380750c
--- /dev/null
+++ b/SrcShared/EmStreamFile.cpp
@@ -0,0 +1,595 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmStreamFile.h"
+
+#include "EmErrCodes.h" // ConvertFromStdCError
+#include "ErrorHandling.h" // Errors::ThrowIfStdCError
+
+#include <errno.h> // EBADF, errno
+
+
+// ===========================================================================
+// ¥ EmStreamFile
+//
+// A EmStreamFile is a lightweight reference to an open file. The class's
+// constructor attempts to open (or create) the file based on the input
+// parameters. The class's destructor closes the file.
+//
+// Once a file is open, member functions can be used to operate on the
+// file (read from it, write to it, etc.).
+//
+// FileHandles can be copied, but no reference counting is performed.
+// Thus, after the first EmStreamFile is deleted, copies of it will
+// contain invalid file references.
+//
+// ===========================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::EmStreamFile
+ *
+ * DESCRIPTION: EmStreamFile constructor. Opens and/or creates the
+ * file according to the input parameters.
+ *
+ * PARAMETERS: ref - reference to the file to create/open.
+ *
+ * openMode - flags describing how to open/create the file
+ *
+ * creator - creator value to assign to the file if it's
+ * created (only used on Mac).
+ *
+ * fileType - file type value to assign to the file if it's
+ * created (only used on the Mac).
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+EmStreamFile::EmStreamFile (const EmFileRef& ref,
+ long openMode,
+ EmFileCreator creator,
+ EmFileType fileType) :
+ EmStream (),
+ fFileRef (ref),
+#if USE_MAC_CALLS
+ fRefNum (0)
+#else
+ fStream (NULL)
+#endif
+{
+ this->Open (ref, openMode, creator, fileType);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::~EmStreamFile
+ *
+ * DESCRIPTION: EmStreamFile destructor. Closes the file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+EmStreamFile::~EmStreamFile (void)
+{
+ this->Close ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetMarker
+ *
+ * DESCRIPTION: Set the read/write position within the file.
+ *
+ * PARAMETERS: inOffset - stdio-style offset value.
+ *
+ * inFromWhere - stdio-style mode value.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetMarker (int32 inOffset,
+ StreamFromType inFromWhere)
+{
+ EmStream::SetMarker (inOffset, inFromWhere);
+
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ int whence;
+
+ if (inFromWhere == kStreamFromStart)
+ {
+ whence = fsFromStart;
+ }
+ else if (inFromWhere == kStreamFromEnd)
+ {
+ whence = fsFromLEOF;
+ }
+ else
+ {
+ EmAssert (inFromWhere == kStreamFromMarker);
+ whence = fsFromMark;
+ }
+
+ OSErr err = ::SetFPos (fRefNum, whence, inOffset);
+ if (err)
+ {
+ Need to deal with this being a Mac error, not a Std C error.
+ this->Throw (err);
+ }
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ int whence;
+
+ if (inFromWhere == kStreamFromStart)
+ {
+ whence = SEEK_SET;
+ }
+ else if (inFromWhere == kStreamFromEnd)
+ {
+ whence = SEEK_END;
+ }
+ else
+ {
+ EmAssert (inFromWhere == kStreamFromMarker);
+ whence = SEEK_CUR;
+ }
+
+ int err = fseek (fStream, inOffset, whence);
+ if (err)
+ {
+ this->Throw (errno);
+ }
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetMarker
+ *
+ * DESCRIPTION: Set the read/write position within the file.
+ *
+ * PARAMETERS: inOffset - stdio-style offset value.
+ *
+ * inFromWhere - stdio-style mode value.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+int32
+EmStreamFile::GetMarker (void) const
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ long pos;
+ OSErr err = ::GetFPos (fRefNum, &pos);
+ return pos;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ return ftell (fStream);
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetLength
+ *
+ * DESCRIPTION: Set the length of the file.
+ *
+ * PARAMETERS: inLength - the desired file length.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetLength (int32 inLength)
+{
+ EmStream::SetLength (inLength);
+
+ // !!! Use BOOL SetEndOfFile (fHandle);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetLength
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The length of the stream (file) in bytes.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+int32
+EmStreamFile::GetLength (void) const
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ long eof;
+ OSErr err = ::GetEOF (fRefNum, &eof);
+ return eof;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ long cur = ftell (fStream);
+ fseek (fStream, 0, SEEK_END);
+
+ long length = ftell (fStream);
+ fseek (fStream, cur, SEEK_SET);
+
+ return length;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::PutBytes
+ *
+ * DESCRIPTION: Write data to the file.
+ *
+ * PARAMETERS: length - amount of data to write.
+ *
+ * buffer - buffer from which data is retrieved
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+ErrCode
+EmStreamFile::PutBytes (const void* inBuffer,
+ int32 inByteCount)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ return EBADF;
+ }
+
+ if (!inBuffer)
+ {
+ return EINVAL;
+ }
+
+ long count = inByteCount;
+ OSErr err = ::FSWrite (fRefNum, &count, inBuffer);
+
+ return err;
+#else
+ if (fStream == NULL)
+ {
+ return EBADF;
+ }
+
+ if (!inBuffer)
+ {
+ return EINVAL;
+ }
+
+ fwrite (inBuffer, 1, inByteCount, fStream);
+ if (ferror (fStream))
+ {
+ return ::ConvertFromStdCError (errno);
+ }
+
+ return 0;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetBytes
+ *
+ * DESCRIPTION: Read data from the file.
+ *
+ * PARAMETERS: length - amount of data to read.
+ *
+ * buffer - buffer into which the data is place.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+ErrCode
+EmStreamFile::GetBytes (void* outBuffer,
+ int32 inByteCount)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ return EBADF;
+ }
+
+ if (!outBuffer)
+ {
+ return EINVAL;
+ }
+
+ long count = inByteCount;
+ OSErr err = ::FSRead (fRefNum, &count, outBuffer);
+
+ if (!err && fTextMode)
+ {
+ char* buffer = (char*) outBuffer;
+ while (inByteCount--)
+ {
+ if (*buffer == '/n')
+ *buffer = '/r';
+ else if (*buffer == '/r')
+ *buffer = '/n';
+
+ ++buffer;
+ }
+ }
+
+ return err;
+#else
+ if (fStream == NULL)
+ {
+ return EBADF;
+ }
+
+ if (!outBuffer)
+ {
+ return EINVAL;
+ }
+
+ if (fread (outBuffer, 1, inByteCount, fStream) == 0)
+ {
+ return 1; // !!! need better error code
+ }
+
+ if (ferror (fStream))
+ {
+ return ::ConvertFromStdCError (errno);
+ }
+
+ return 0;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Open [protected]
+ *
+ * DESCRIPTION: Opens and/or creates the given file based on the given
+ * parameters. This function is called from the ctor in
+ * order to do all the work.
+ *
+ * PARAMETERS: ref - reference to the file to create/open.
+ *
+ * openMode - flags describing how to open/create the file
+ *
+ * creator - creator value to assign to the file if it's
+ * created (only used on Mac).
+ *
+ * fileType - file type value to assign to the file if it's
+ * created (only used on the Mac).
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Open (const EmFileRef& ref, long openMode,
+ EmFileCreator creator, EmFileType fileType)
+{
+#if USE_MAC_CALLS
+
+ // Open/create the file.
+
+ string cName = ref.GetFullPath ();
+ LStr255 name (cName.c_str ());
+ OSErr err;
+
+ if ((openMode & kOpenTypeMask) == kCreateOrEraseForUpdate)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ if (err == fnfErr)
+ {
+ err = ::Create (name, 0, creator, fileType);
+
+ if (!err)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ }
+
+ if (!err)
+ {
+ err = ::SetEOF (fRefNum, 0);
+ }
+ }
+ }
+ else if ((openMode & kOpenTypeMask) == kOpenExistingForRead)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ }
+
+ // Check for errors.
+
+ if (err)
+ {
+ fRefNum = 0;
+ this->Throw (err);
+ }
+
+ fTextMode = (openMode & kOpenText) != 0;
+#else
+ char* kModes[] = { "r", "w", "a", "r+", "w+", "a+" };
+ string mode (kModes[openMode & kOpenTypeMask]);
+
+ if ((openMode & kOpenText) != 0)
+ mode += 't';
+ else
+ mode += 'b';
+
+ // Open/create the file.
+
+ fStream = fopen (ref.GetFullPath ().c_str (), mode.c_str ());
+
+ // Check for errors.
+
+ if (fStream == NULL)
+ {
+ this->Throw (errno);
+ }
+#endif
+
+ if (creator && fileType)
+ {
+ ref.SetCreatorAndType (creator, fileType);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Close [protected]
+ *
+ * DESCRIPTION: Closes the file. Called from the dtor to do all the
+ * work.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Close (void)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EINVAL);
+ }
+
+ ::FSClose (fRefNum);
+ fRefNum = 0;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EINVAL);
+ }
+
+ if (fclose (fStream))
+ {
+ fStream = NULL;
+ this->Throw (errno);
+ }
+
+ fStream = NULL;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Throw [protected]
+ *
+ * DESCRIPTION: Bottleneck function for throwing an exception. Makes
+ * sure that the file's name is installed as an error
+ * message parameter and then throws the exception.
+ *
+ * PARAMETERS: err - Std C error code to throw.
+ *
+ * RETURNED: never.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Throw (int err) const
+{
+ this->SetFileNameParameter ();
+
+ Errors::ThrowIfStdCError (err);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetFileNameParameter [protected]
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetFileNameParameter (void) const
+{
+ string name = fFileRef.GetName ();
+ Errors::SetParameter ("%filename", name);
+}
diff --git a/SrcShared/EmStreamFile.h b/SrcShared/EmStreamFile.h
new file mode 100644
index 0000000..310509f
--- /dev/null
+++ b/SrcShared/EmStreamFile.h
@@ -0,0 +1,98 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmStreamFile_h
+#define EmStreamFile_h
+
+#include "EmStream.h" // EmStream
+
+#include "EmFileRef.h" // EmFileRef
+#include "EmTypes.h" // ErrCode
+
+#include "stdio.h" // FILE
+
+enum
+{
+ kOpenExistingForRead, // "r" Open an existing file for input.
+ kCreateOrEraseForWrite, // "w" Create a new file, or truncate an
+ // existing one, for output.
+ kCreateOrOpenForWrite, // "a" Create a new file, or append to an
+ // existing one, for output.
+
+ kOpenExistingForUpdate, // "r+" Open an existing file for update,
+ // starting at the beginning of the file.
+ kCreateOrEraseForUpdate, // "w+" Create a new file, or truncate an
+ // existing one, for update.
+ kCreateOrOpenForUpdate, // "a+" Create a new file, or append to an
+ // existing one, for update.
+
+ kOpenTypeMask = 63,
+ kOpenText = 64
+};
+
+
+class EmStreamFile : public EmStream
+{
+ public:
+ EmStreamFile (const EmFileRef&,
+ long openMode,
+ EmFileCreator creator = kFileCreatorNone,
+ EmFileType fileType = kFileTypeNone);
+ virtual ~EmStreamFile (void);
+
+ virtual void SetMarker (int32 inOffset,
+ StreamFromType inFromWhere);
+ virtual int32 GetMarker (void) const;
+
+ virtual void SetLength (int32 inLength);
+ virtual int32 GetLength (void) const;
+
+ virtual ErrCode PutBytes (const void* inBuffer,
+ int32 inByteCount);
+ virtual ErrCode GetBytes (void* outBuffer,
+ int32 inByteCount);
+
+ EmFileRef GetFileRef (void) const
+ {
+ return fFileRef;
+ }
+
+ protected:
+ void Open (const EmFileRef&,
+ long openMode,
+ EmFileCreator creator,
+ EmFileType fileType);
+
+ void Close (void);
+
+ void Throw (int) const;
+ void SetFileNameParameter (void) const;
+
+ private:
+ // Protect the copy constructor so that we don't
+ // accidentally make copies (what does it mean to
+ // copy a reference to an open file?).
+
+ EmStreamFile (const EmStreamFile&);
+
+ EmFileRef fFileRef;
+
+#if USE_MAC_CALLS
+ short fRefNum;
+ Bool fTextMode;
+#else
+ FILE* fStream;
+#endif
+};
+
+#endif /* EmStreamFile_h */
diff --git a/SrcShared/EmStructs.h b/SrcShared/EmStructs.h
new file mode 100644
index 0000000..140a452
--- /dev/null
+++ b/SrcShared/EmStructs.h
@@ -0,0 +1,315 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmStructs_h
+#define EmStructs_h
+
+#include "EmFileRef.h" // EmFileRef
+#include "EmDevice.h" // EmDevice
+#include "EmTypes.h" // GremlinEventType, EventIDType
+
+#include <deque>
+#include <map>
+#include <string>
+#include <vector>
+
+// ---------- Collections ----------
+
+typedef vector<ScaleType> ScaleList;
+typedef vector<RAMSizeType> RAMSizeList;
+
+typedef vector<uint8> ByteList;
+typedef vector<string> StringList;
+
+typedef map<string, string> StringStringMap;
+typedef vector<CloseActionType> CloseActionList;
+typedef vector<LoggingType> LoggingList;
+
+
+// ---------- RGBType ----------
+
+struct RGBType
+{
+ RGBType (void) {}
+ RGBType (uint8 red, uint8 green, uint8 blue) :
+ fRed (red),
+ fGreen (green),
+ fBlue (blue)
+ {}
+
+ bool operator== (const RGBType& rhs) const
+ {
+ return fRed == rhs.fRed && fGreen == rhs.fGreen && fBlue == rhs.fBlue;
+ }
+
+ bool operator!= (const RGBType& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ uint8 fRed;
+ uint8 fGreen;
+ uint8 fBlue;
+ uint8 fFiller; // Pad this out to 4 bytes to make array lookups more efficient.
+};
+typedef vector<RGBType> RGBList;
+
+
+// ---------- SystemCallContext ----------
+
+struct SystemCallContext
+{
+ emuptr fPC; // PC at which the system call was made.
+ emuptr fNextPC; // PC of instruction after system call.
+ emuptr fDestPC1; // Address of system function (in the trap table).
+ emuptr fDestPC2; // Address of system function (if subdispatching is involved).
+ uint16 fTrapWord; // Trapword, even for SYSTRAP_FAST calls.
+ uint16 fTrapIndex; // Trapword with the high 4 bits removed.
+ emuptr fExtra; // RefNum for library calls, D2 for "dispatch" calls.
+ Bool fViaTrap; // True if called via TRAP $F.
+ Bool fViaJsrA1; // True if called via SYSTRAP_FASTER.
+
+ long fError; // If an error occurred getting the context, error is here
+ long fLibIndex; // Resource base number for function name
+ long fMaxRefNum; // If the refNum was too big, this is the max value it could be.
+};
+typedef vector<SystemCallContext> SystemCallContextList;
+
+
+// ---------- DatabaseInfo ----------
+
+struct DatabaseInfo
+{
+ UInt32 creator;
+ UInt32 type;
+ UInt16 version;
+ LocalID dbID;
+ UInt16 cardNo;
+ UInt32 modDate;
+ UInt16 dbAttrs;
+
+ char name[dmDBNameLength];
+ char dbName[dmDBNameLength];
+
+ Bool operator < (const DatabaseInfo& other) const
+ { if (creator < other.creator) return true;
+ if (creator > other.creator) return false;
+ if (type < other.type) return true;
+ return false; }
+
+ Bool operator == (const DatabaseInfo& other) const
+ { return (creator == other.creator) &&
+ (type == other.type); }
+};
+typedef vector<DatabaseInfo> DatabaseInfoList;
+
+
+// ---------- SlotInfoType ----------
+
+struct SlotInfoType
+{
+ long fSlotNumber;
+ Bool fSlotOccupied;
+ EmDirRef fSlotRoot;
+};
+typedef vector<SlotInfoType> SlotInfoList;
+
+
+// ---------- Configuration ----------
+
+struct Configuration
+{
+ Configuration () :
+ fDevice (),
+ fRAMSize (1024),
+ fROMFile ()
+ {
+ }
+
+ Configuration (const Configuration& cfg) :
+ fDevice (cfg.fDevice),
+ fRAMSize (cfg.fRAMSize),
+ fROMFile (cfg.fROMFile)
+ {
+ }
+
+ Configuration (const EmDevice& dt, long size, const EmFileRef& rom) :
+ fDevice (dt),
+ fRAMSize (size),
+ fROMFile (rom)
+ {
+ }
+
+ Bool IsValid (void) const
+ {
+ // Return whether or not the configuration looks
+ // valid.
+
+ if (!fDevice.Supported ())
+ return false;
+
+ if (fRAMSize <= 0)
+ return false;
+
+ if (!fROMFile.IsSpecified ())
+ return false;
+
+ if (!fROMFile.Exists ())
+ return false;
+
+ if (!fDevice.SupportsROM (fROMFile))
+ return false;
+
+ return true;
+ }
+
+ EmDevice fDevice;
+ RAMSizeType fRAMSize;
+ EmFileRef fROMFile;
+};
+typedef vector<Configuration> ConfigurationList;
+
+
+// ---------- GremlinInfo ----------
+
+struct GremlinInfo
+{
+ GremlinInfo () :
+ fNumber (0),
+ fSteps (-1),
+ fFinal (-1),
+ fSaveFrequency (10000),
+ fAppList ()
+ {
+ }
+
+ long fNumber;
+ long fSteps;
+ long fFinal;
+ long fSaveFrequency;
+ DatabaseInfoList fAppList;
+};
+typedef vector<GremlinInfo> GremlinInfoList;
+
+
+// ---------- HordeInfo ----------
+
+struct HordeInfo
+{
+ HordeInfo () :
+ fStartNumber (0),
+ fStopNumber (0),
+ fDepthSwitch (30000),
+ fDepthSave (10000),
+ fDepthStop (1000000),
+ fCanSwitch (false),
+ fCanSave (false),
+ fCanStop (false),
+ fAppList (),
+ fSaveFrequency (0), // Rewritten in c'tor
+ fSwitchDepth (0), // Rewritten in c'tor
+ fMaxDepth (0), // Rewritten in c'tor
+ fFirstLaunchedAppName ("")
+ {
+ NewToOld ();
+ }
+
+ long fStartNumber;
+ long fStopNumber;
+
+ long fDepthSwitch;
+ long fDepthSave;
+ long fDepthStop;
+
+ Bool fCanSwitch;
+ Bool fCanSave;
+ Bool fCanStop;
+
+ DatabaseInfoList fAppList;
+
+ // Old fields that I want to get rid of, but
+ // I need to update Gremlins and Hordes first.
+
+ long fSaveFrequency;
+ long fSwitchDepth;
+ long fMaxDepth;
+
+ // New field added so that the first application
+ // to be launched can be specified
+
+ string fFirstLaunchedAppName;
+
+ void NewToOld (void)
+ {
+ fSwitchDepth = fCanSwitch ? fDepthSwitch : -1;
+ fSaveFrequency = fCanSave ? fDepthSave : 0;
+ fMaxDepth = fCanStop ? fDepthStop : -1;
+ }
+
+ void OldToNew (void)
+ {
+ fCanSwitch = fSwitchDepth > 0;
+ fDepthSwitch = fCanSwitch ? fSwitchDepth : 30000;
+
+ fCanSave = fSaveFrequency > 0;
+ fDepthSave = fCanSave ? fSaveFrequency : 10000;
+
+ fCanStop = fMaxDepth > 0;
+ fDepthStop = fCanStop ? fMaxDepth : 1000000;
+ }
+};
+typedef vector<HordeInfo> HordeInfoList;
+
+
+// ---------- EmGremlinThreadInfo ----------
+
+struct EmGremlinThreadInfo
+{
+ Bool fHalted;
+ Int32 fErrorEvent;
+ StrCode fMessageID;
+};
+
+
+// ---------- EmGremlinErrorFrequencyInfo ----------
+
+struct EmGremlinErrorFrequencyInfo
+{
+ Int32 fCount;
+ Int32 fErrorFrequency;
+ Int32 fFirstErrantGremlinIndex;
+};
+
+
+// ---------- SysLibTblEntryTypeV10 ----------
+
+typedef struct SysLibTblEntryTypeV10 {
+ MemPtr* dispatchTblP; // pointer to library dispatch table
+ void* globalsP; // Library globals
+ } SysLibTblEntryTypeV10;
+typedef SysLibTblEntryTypeV10* SysLibTblEntryV10Ptr;
+
+
+// ---------- EmStackFrame ----------
+
+struct EmStackFrame
+{
+ emuptr fAddressInFunction;
+ emuptr fA6;
+};
+
+typedef vector<EmStackFrame> EmStackFrameList;
+
+
+
+#endif // EmStructs_h
diff --git a/SrcShared/EmSubroutine.cpp b/SrcShared/EmSubroutine.cpp
new file mode 100644
index 0000000..e378403
--- /dev/null
+++ b/SrcShared/EmSubroutine.cpp
@@ -0,0 +1,3113 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmSubroutine.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmMemory.h" // EmMemPut8, etc.
+#include "EmPalmStructs.h" // EmAlias
+#include "EmStructs.h" // StringList
+#include "Miscellaneous.h" // SeparateList
+#include "Platform.h" // Platform::AllocateMemory
+
+#include <ctype.h> // isspace
+
+
+static EmParamInfo kEmParamInfo [] =
+{
+ // These are the base integral types.
+
+ { "Int8", kEm_SI1, false },
+ { "Int16", kEm_SI2, false },
+ { "Int32", kEm_SI4, false },
+// { "Int64", kEm_SI8, false },
+
+ { "UInt8", kEm_UI1, false },
+ { "UInt16", kEm_UI2, false },
+ { "UInt32", kEm_UI4, false },
+// { "UInt64", kEm_UI8, false },
+
+// { "Float", kEm_FP4, false },
+// { "Double", kEm_FP8, false },
+// { "LongDouble", kEm_FP16, false },
+
+ // These types are synonyms for the simple integral values.
+
+ { "char", kEm_SI1, false },
+ { "short", kEm_SI2, false },
+ { "long", kEm_SI4, false },
+
+ { "Char", kEm_UI1, false },
+ { "WChar", kEm_UI2, false },
+
+ { "Boolean", kEm_UI1, false },
+ { "ClipboardFormatType", kEm_UI1, false },
+ { "DlkSyncStateType", kEm_UI1, false },
+ { "FormObjectKind", kEm_UI1, false },
+ { "LocalIDKind", kEm_UI1, false },
+ { "NetSocketAddrEnum", kEm_UI1, false },
+ { "NetSocketTypeEnum", kEm_UI1, false },
+ { "SystemPreferencesChoice",kEm_UI1, false },
+
+ { "DmResID", kEm_UI2, false },
+ { "Err", kEm_UI2, false },
+ { "HostControlSelectorType",kEm_UI2, false },
+
+ { "Coord", kEm_SI2, false },
+ { "NetSocketRef", kEm_SI2, false },
+
+ { "DmResType", kEm_UI4, false },
+ { "LocalID", kEm_UI4, false },
+ { "NetFDSetType", kEm_UI4, false },
+ { "NetIPAddr", kEm_UI4, false },
+
+ { "HostBoolType", kEm_SI4, false },
+ { "HostClockType", kEm_SI4, false },
+ { "HostErrType", kEm_SI4, false },
+ { "HostIDType", kEm_SI4, false },
+ { "HostPlatformType", kEm_SI4, false },
+ { "HostSignalType", kEm_SI4, false },
+ { "HostSizeType", kEm_SI4, false },
+ { "HostTimeType", kEm_SI4, false },
+
+ // These types are pointer types, but are mostly treated as integral values.
+ // They get pushed onto the stack as a 4-byte value, but the stuff they
+ // point to is not affected or adjusted in any way. Also, when used as a
+ // return type on the 68K, they are treated as pointers, not integers.
+
+ { "DmOpenRef", kEm_Void, true },
+ { "HostFILEType", kEm_Void, true },
+
+ // The void type can be used as a return type ("void foo (int);"), or as an
+ // empty parameter list ("int foo (void);"). It can also be used as a
+ // generic pointer type ("void foo (void*);").
+
+ { "void", kEm_Void, false }
+
+};
+
+
+class EmSubroutineCPU
+{
+ public:
+ EmSubroutineCPU (void);
+ virtual ~EmSubroutineCPU (void);
+
+ virtual long FormatStack (EmParamList&) = 0;
+ virtual Err PrepareStack (Bool forCalling, Bool forStdArg, long stackSize) = 0;
+ virtual Err PrepareStack (emuptr) = 0;
+
+ virtual Err Call (uint16) = 0;
+ virtual Err CallSelector (uint16, uint16) = 0;
+
+ virtual void GetParamVal (EmParam&, int8&);
+ virtual void GetParamVal (EmParam&, int16&);
+ virtual void GetParamVal (EmParam&, int32&);
+ virtual void GetParamVal (EmParam&, int64&);
+ virtual void GetParamVal (EmParam&, uint8&);
+ virtual void GetParamVal (EmParam&, uint16&);
+ virtual void GetParamVal (EmParam&, uint32&);
+ virtual void GetParamVal (EmParam&, uint64&);
+ virtual void GetParamVal (EmParam&, float&);
+ virtual void GetParamVal (EmParam&, double&);
+ virtual void GetParamVal (EmParam&, long double&);
+
+ virtual void SetParamVal (EmParam&, int8);
+ virtual void SetParamVal (EmParam&, int16);
+ virtual void SetParamVal (EmParam&, int32);
+ virtual void SetParamVal (EmParam&, int64);
+ virtual void SetParamVal (EmParam&, uint8);
+ virtual void SetParamVal (EmParam&, uint16);
+ virtual void SetParamVal (EmParam&, uint32);
+ virtual void SetParamVal (EmParam&, uint64);
+ virtual void SetParamVal (EmParam&, float);
+ virtual void SetParamVal (EmParam&, double);
+ virtual void SetParamVal (EmParam&, long double);
+
+ virtual uint32 GetReturnRegInteger (void) = 0;
+ virtual emuptr GetReturnRegPointer (void) = 0;
+
+ virtual void SetReturnRegInteger (uint32) = 0;
+ virtual void SetReturnRegPointer (void*) = 0;
+
+ protected:
+ emuptr fStackPtr;
+};
+
+
+class EmSubroutineCPU68K : public EmSubroutineCPU
+{
+ public:
+ EmSubroutineCPU68K (void);
+ virtual ~EmSubroutineCPU68K (void);
+
+ virtual long FormatStack (EmParamList&);
+ virtual Err PrepareStack (Bool forCalling, Bool forStdArg, long stackSize);
+ virtual Err PrepareStack (emuptr) ;
+
+ virtual Err Call (uint16);
+ virtual Err CallSelector (uint16, uint16);
+
+ virtual uint32 GetReturnRegInteger (void);
+ virtual emuptr GetReturnRegPointer (void);
+
+ virtual void SetReturnRegInteger (uint32);
+ virtual void SetReturnRegPointer (void*);
+
+ private:
+ Err DoCall (uint16 trapWord);
+ char* GetStackBase (void);
+
+ static Bool HandleTrap12 (void);
+
+ enum { kStackSize = 4096 };
+ char fStack[kStackSize + 3];
+
+ uint32 fReturnedA0;
+ uint32 fReturnedD0;
+};
+
+
+class EmSubroutineCPUARM : public EmSubroutineCPU
+{
+ public:
+ EmSubroutineCPUARM (void);
+ virtual ~EmSubroutineCPUARM (void);
+
+ virtual long FormatStack (EmParamList&);
+ virtual Err PrepareStack (Bool forCalling, Bool forStdArg, long stackSize);
+ virtual Err PrepareStack (emuptr) ;
+
+ virtual Err Call (uint16);
+ virtual Err CallSelector (uint16, uint16);
+
+ virtual void GetParamVal (EmParam&, int8&);
+ virtual void GetParamVal (EmParam&, int16&);
+ virtual void GetParamVal (EmParam&, int32&);
+ virtual void GetParamVal (EmParam&, int64&);
+ virtual void GetParamVal (EmParam&, uint8&);
+ virtual void GetParamVal (EmParam&, uint16&);
+ virtual void GetParamVal (EmParam&, uint32&);
+ virtual void GetParamVal (EmParam&, uint64&);
+ virtual void GetParamVal (EmParam&, float&);
+ virtual void GetParamVal (EmParam&, double&);
+ virtual void GetParamVal (EmParam&, long double&);
+
+ virtual void SetParamVal (EmParam&, int8);
+ virtual void SetParamVal (EmParam&, int16);
+ virtual void SetParamVal (EmParam&, int32);
+ virtual void SetParamVal (EmParam&, int64);
+ virtual void SetParamVal (EmParam&, uint8);
+ virtual void SetParamVal (EmParam&, uint16);
+ virtual void SetParamVal (EmParam&, uint32);
+ virtual void SetParamVal (EmParam&, uint64);
+ virtual void SetParamVal (EmParam&, float);
+ virtual void SetParamVal (EmParam&, double);
+ virtual void SetParamVal (EmParam&, long double);
+
+ virtual uint32 GetReturnRegInteger (void);
+ virtual emuptr GetReturnRegPointer (void);
+
+ virtual void SetReturnRegInteger (uint32);
+ virtual void SetReturnRegPointer (void*);
+};
+
+
+#if NDEBUG
+ #define ERROR_CHECKING 0
+#else
+ #define ERROR_CHECKING 1
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine constructor
+// ---------------------------------------------------------------------------
+
+EmSubroutine::EmSubroutine (void) :
+ fCPU (NULL),
+ fParams (),
+ fReturnType (),
+ fStackSize (-1)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine destructor
+// ---------------------------------------------------------------------------
+
+EmSubroutine::~EmSubroutine (void)
+{
+ delete fCPU;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::DescribeDecl
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::DescribeDecl (EmParamDecl returnType, EmParamListDecl decl)
+{
+ // Determine the return type.
+
+ Err err = this->ParseParamDecl (returnType, fReturnType);
+#if ERROR_CHECKING
+ if (err)
+ {
+ this->Reset ();
+ return err;
+ }
+#endif
+
+ // Determine the parameter types. Start by breaking up the parameter
+ // list at the commas.
+
+ StringList paramDecls;
+ ::SeparateList (paramDecls, decl, ',');
+
+ // Iterate over all the stuff we found between the commas.
+
+ StringList::iterator iter = paramDecls.begin ();
+ while (iter != paramDecls.end ())
+ {
+ // For each intra-comma chunk, parse it up and determine the
+ // type and name information it specifies.
+
+ err = this->AddParam (iter->c_str ());
+#if ERROR_CHECKING
+ if (err)
+ {
+ this->Reset ();
+ return err;
+ }
+#endif
+
+ ++iter;
+ }
+
+ // After all the parameters have been parsed up, determine where they
+ // should appear on the stack (specified as offsets from the stack
+ // pointer).
+
+ fStackSize = this->GetCPU ()->FormatStack (fParams);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::AddParam
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::AddParam (EmParamDecl decl)
+{
+ EmParam param;
+
+#if ERROR_CHECKING
+ Err err = this->ParseParamDecl (decl, param);
+ if (err)
+ {
+ this->Reset ();
+ return err;
+ }
+#else
+ this->ParseParamDecl (decl, param);
+#endif
+
+ // If it's not just a bare "(void)", push it onto our collection
+ // of parsed parameter information.
+
+ if (param.fByRef || param.fType != kEm_Void)
+ {
+ fParams.push_back (param);
+ }
+
+ // After all the parameters have been parsed up, determine where they
+ // should appear on the stack (specified as offsets from the stack
+ // pointer).
+
+ fStackSize = this->GetCPU ()->FormatStack (fParams);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::PrepareStack (Bool forCalling, Bool forStdArg)
+{
+ return this->GetCPU ()->PrepareStack (forCalling, forStdArg, fStackSize);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::PrepareStack (emuptr stackAddr)
+{
+ return this->GetCPU ()->PrepareStack (stackAddr);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::Reset
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::Reset (void)
+{
+ fParams.clear ();
+ fReturnType = EmParam ();
+
+ delete fCPU;
+ fCPU = NULL;
+
+ fStackSize = -1;
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, int8& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, int16& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, int32& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, int64& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, uint8& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, uint16& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, uint32& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (!iter->fByRef && iter->fType != kEm_UI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+// if (iter->fByRef)
+// {
+// EmAssert (false);
+// return kEmErrTypeMismatch;
+// }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, uint64& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, float& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, double& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetParamVal (EmParamNameArg name, long double& result)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP16)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->GetParamVal (*iter, result);
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (int8& result)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ uint32 reg = this->GetReturnRegInteger ();
+ result = (int8) reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (int16& result)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ uint32 reg = this->GetReturnRegInteger ();
+ result = (int16) reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (int32& result)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ uint32 reg = this->GetReturnRegInteger ();
+ result = (int32) reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (int64& /*result*/)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (uint8& result)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ uint32 reg = this->GetReturnRegInteger ();
+ result = (uint8) reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (uint16& result)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ uint32 reg = this->GetReturnRegInteger ();
+ result = (uint16) reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (uint32& result)
+{
+#if ERROR_CHECKING
+ if (!fReturnType.fByRef && fReturnType.fType != kEm_UI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+// if (fReturnType.fByRef)
+// {
+// EmAssert (false);
+// return kEmErrTypeMismatch;
+// }
+#endif
+
+ uint32 reg;
+
+ if (fReturnType.fByRef)
+ reg = this->GetReturnRegPointer ();
+ else
+ reg = this->GetReturnRegInteger ();
+
+ result = reg;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (uint64& /*result*/)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (float& /*result*/)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (double& /*result*/)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::GetReturnVal (long double&)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP16)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, int8 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, int16 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, int32 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, int64 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_SI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, uint8 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, uint16 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, uint32 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (!iter->fByRef && iter->fType != kEm_UI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+// if (iter->fByRef)
+// {
+// EmAssert (false);
+// return kEmErrTypeMismatch;
+// }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, uint64 val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_UI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, float val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, double val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetParamVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetParamVal (EmParamNameArg name, long double val)
+{
+ EmParamList::iterator iter = this->FindParam (name);
+
+#if ERROR_CHECKING
+ if (iter == fParams.end ())
+ {
+ EmAssert (false);
+ return kEmErrUnknownParameter;
+ }
+
+ if (iter->fType != kEm_FP16)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (iter->fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ fCPU->SetParamVal (*iter, val);
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (int8 val)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ this->SetReturnRegInteger ((uint32)(uint8) val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (int16 val)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ this->SetReturnRegInteger ((uint32)(uint16) val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (int32 val)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ this->SetReturnRegInteger ((uint32) val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (int64)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_SI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+// this->SetReturnRegInteger ((uint32) val);
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (uint8 val)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI1)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ this->SetReturnRegInteger (val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (uint16 val)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI2)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+ this->SetReturnRegInteger (val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (uint32 val)
+{
+#if ERROR_CHECKING
+ if (!fReturnType.fByRef && fReturnType.fType != kEm_UI4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+// if (fReturnType.fByRef)
+// {
+// EmAssert (false);
+// return kEmErrTypeMismatch;
+// }
+#endif
+
+ if (fReturnType.fByRef)
+ this->SetReturnRegPointer ((void*) val);
+ else
+ this->SetReturnRegInteger (val);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (uint64)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_UI8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+// this->SetReturnRegInteger (val);
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (float)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP4)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+// this->SetReturnRegInteger (val);
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (double)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP8)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+// this->SetReturnRegInteger (val);
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnVal
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::SetReturnVal (long double)
+{
+#if ERROR_CHECKING
+ if (fReturnType.fType != kEm_FP16)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+
+ if (fReturnType.fByRef)
+ {
+ EmAssert (false);
+ return kEmErrTypeMismatch;
+ }
+#endif
+
+// this->SetReturnRegInteger (val);
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::Call
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::Call (uint16 trapWord)
+{
+ return this->GetCPU ()->Call (trapWord);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::CallSelector
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::CallSelector (uint16 trapWord, uint16 selector)
+{
+ return this->GetCPU ()->CallSelector (trapWord, selector);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+uint32 EmSubroutine::GetReturnRegInteger (void)
+{
+ return this->GetCPU ()->GetReturnRegInteger ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+emuptr EmSubroutine::GetReturnRegPointer (void)
+{
+ return this->GetCPU ()->GetReturnRegPointer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+void EmSubroutine::SetReturnRegInteger (uint32 val)
+{
+ this->GetCPU ()->SetReturnRegInteger (val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::SetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+void EmSubroutine::SetReturnRegPointer (void* val)
+{
+ this->GetCPU ()->SetReturnRegPointer (val);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetCPU
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPU* EmSubroutine::GetCPU (void)
+{
+ if (fCPU == NULL)
+ {
+ if (this->Is68K ())
+ fCPU = new EmSubroutineCPU68K;
+ else if (this->IsARM ())
+ fCPU = new EmSubroutineCPUARM;
+ else
+ EmAssert (false);
+ }
+
+ return fCPU;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::Is68K
+// ---------------------------------------------------------------------------
+
+Bool EmSubroutine::Is68K (void)
+{
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::IsARM
+// ---------------------------------------------------------------------------
+
+Bool EmSubroutine::IsARM (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::ParseParamDecl
+// ---------------------------------------------------------------------------
+
+Err EmSubroutine::ParseParamDecl (EmParamDecl decl, EmParam& result)
+{
+ string token;
+ string::size_type offset = 0;
+
+ // Get the type.
+
+ token = this->GetToken (decl, offset);
+
+ // See if we recognize it.
+
+ size_t ii;
+ for (ii = 0; ii < countof (kEmParamInfo); ++ii)
+ {
+ if (token == kEmParamInfo[ii].fTypeName)
+ {
+ result.fType = kEmParamInfo[ii].fType;
+ result.fByRef = kEmParamInfo[ii].fByRef;
+ break;
+ }
+ }
+
+ // If not, try some default processing.
+
+ if (ii >= countof (kEmParamInfo))
+ {
+ // Set it up as an unknown type. Hopefully, it will be
+ // followed by a "*", so that we can treat it as a pointer type.
+
+ result.fType = kEm_Unknown;
+ result.fByRef = false;
+
+ // Check the name to see if it ends in "Ptr" or "Handle. If so,
+ // treat it as a pointer type.
+
+ if (::EndsWith (token.c_str (), "Ptr") ||
+ ::EndsWith (token.c_str (), "Handle"))
+ {
+ result.fByRef = true;
+ }
+ }
+
+ // Get what follows the type. This is either the parameter name,
+ // or a "*" to indicate a reference parameter.
+
+ token = this->GetToken (decl, offset);
+
+ if (token == "*")
+ {
+ result.fByRef = true;
+
+ // OK, *now* get the parameter name.
+
+ token = this->GetToken (decl, offset);
+
+ // Whoops...it's another "*". So make the param a ptr to a ptr.
+
+ while (token == "*")
+ {
+ result.fType = kEm_Void;
+
+ // OK, *now* get the parameter name.
+
+ token = this->GetToken (decl, offset);
+ }
+ }
+
+ result.fName = token;
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::GetToken
+// ---------------------------------------------------------------------------
+
+string EmSubroutine::GetToken (EmParamDecl decl, string::size_type& offset)
+{
+ string result;
+
+ // Get a C++ string so that we can use the STL routines.
+
+ string str (decl);
+
+ do
+ {
+ // Skip whitespace.
+
+ while (isspace (str[offset]))
+ ++offset;
+
+ // Nothing but whitespace. This could happen if the
+ // declaration has a type but no name.
+
+ if (offset >= str.size ())
+ {
+ result.erase ();
+ }
+
+ // If this is a "*", return it.
+
+ else if (str[offset] == '*')
+ {
+ ++offset;
+ result = "*";
+ }
+
+ // Otherwise, scoop of the identifer
+
+ else
+ {
+ string::size_type begin = offset;
+
+ while (isalnum (str[offset]) || str[offset] == '_')
+ ++offset;
+
+ result = str.substr (begin, offset - begin);
+ }
+
+ // If it's "const", "signed" or "unsigned", filter it out.
+ }
+ while (result == "const" || result == "signed" || result == "unsigned");
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutine::FindParam
+// ---------------------------------------------------------------------------
+
+EmParamList::iterator EmSubroutine::FindParam (EmParamNameArg name)
+{
+ EmParamList::iterator iter = fParams.begin ();
+
+ while (iter != fParams.end ())
+ {
+ if (iter->fName == name)
+ {
+ break;
+ }
+
+ ++iter;
+ }
+
+ return iter;
+}
+
+
+#pragma mark ------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::EmSubroutineCPU
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPU::EmSubroutineCPU (void) :
+ fStackPtr (EmMemNULL)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::~EmSubroutineCPU
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPU::~EmSubroutineCPU (void)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, int8& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet8 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, int16& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet16 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, int32& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet32 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, int64& /*result*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, uint8& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet8 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, uint16& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet16 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, uint32& result)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ result = EmMemGet32 (fStackPtr + param.fStackOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, uint64& /*result*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, float& /*result*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, double& /*result*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::GetParamVal (EmParam& param, long double& /*result*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, int8 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut8 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, int16 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut16 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, int32 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut32 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, int64 /*val*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, uint8 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut8 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, uint16 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut16 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, uint32 val)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmMemPut32 (fStackPtr + param.fStackOffset, val);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, uint64 /*val*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, float /*val*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, double /*val*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU::SetParamVal (EmParam& param, long double /*val*/)
+{
+#if ERROR_CHECKING
+ EmAssert (fStackPtr);
+ EmAssert (param.fStackOffset >= 0);
+#endif
+
+ EmAssert (false);
+}
+
+
+#pragma mark ------------------------------
+
+#include "EmCPU68K.h" // GetRegisters
+#include "EmException.h" // EmExceptionReset
+#include "EmPalmOS.h" // StackRange, RememberStackRange, ForgetStack
+#include "EmSession.h" // gSession
+#include "Profiling.h" // StDisableAllProfiling
+#include "UAE.h" // m68k_dreg, etc.
+
+const uint16 kOpcode_ROMCall = m68kTrapInstr + sysDispatchTrapNum;
+const uint16 kOpcode_ATrapReturn = m68kTrapInstr + kATrapReturnTrapNum;
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::EmSubroutineCPU68K
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPU68K::EmSubroutineCPU68K (void) :
+ fReturnedA0 (0),
+ fReturnedD0 (0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::~EmSubroutineCPU68K
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPU68K::~EmSubroutineCPU68K (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::FormatStack
+// ---------------------------------------------------------------------------
+
+long EmSubroutineCPU68K::FormatStack (EmParamList& params)
+{
+ long offset = 0;
+
+ EmParamList::iterator iter = params.begin ();
+ while (iter != params.end ())
+ {
+ iter->fStackOffset = offset;
+
+ if (iter->fByRef)
+ {
+ offset += 4;
+ }
+ else
+ {
+ switch (iter->fType)
+ {
+ case kEm_SI1:
+ case kEm_SI2:
+ case kEm_UI1:
+ case kEm_UI2:
+ offset += 2;
+ break;
+
+ case kEm_SI4:
+ case kEm_UI4:
+ offset += 4;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+ }
+
+ ++iter;
+ }
+
+ return offset;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPU68K::PrepareStack (Bool forCalling, Bool /*forStdArg*/, long stackSize)
+{
+ if (forCalling)
+ {
+ // Give ourselves our own private stack. We'll want this in case
+ // we're in the debugger and the stack pointer is hosed.
+
+ EmBankMapped::MapPhysicalMemory (this->GetStackBase (), kStackSize);
+
+ char* stackBase = this->GetStackBase ();
+ char* stackTop = &stackBase[kStackSize - 4];
+ emuptr eStackTop = EmBankMapped::GetEmulatedAddress (stackTop);
+
+ fStackPtr = eStackTop - stackSize;
+ }
+ else
+ {
+ fStackPtr = m68k_areg (regs, 7);
+
+ // Get these values, in case the EmSubroutine object is used
+ // when tailpatching a function and we need to examine the
+ // value being returned by the original version.
+
+ fReturnedA0 = m68k_areg (regs, 0);
+ fReturnedD0 = m68k_dreg (regs, 0);
+ }
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPU68K::PrepareStack (emuptr stackAddr)
+{
+ fStackPtr = stackAddr;
+
+ // Get these values, in case the EmSubroutine object is used
+ // when tailpatching a function and we need to examine the
+ // value being returned by the original version.
+
+ fReturnedA0 = m68k_areg (regs, 0);
+ fReturnedD0 = m68k_dreg (regs, 0);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::Call
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPU68K::Call (uint16 trapWord)
+{
+ Err err = errNone;
+
+ // Save the current state.
+
+ regstruct oldRegs;
+ gCPU68K->GetRegisters (oldRegs);
+
+ // Make sure the CPU is not stopped. I suppose that we could force the CPU
+ // to no longer be stopped, but I'd rather that the Palm OS itself woke up
+ // first before we try making calls into it. Therefore, anything making
+ // an out-of-the-blue Palm OS call via this class (that is, a call outside
+ // of the context of a Palm OS function head- or tailpatch) should first
+ // bring the CPU to a halt by calling EmSession::SuspendThread (kStopOnSysCall)
+ // first (usually by using EmSessionStopper (kStopOnSysCall)).
+
+ EmAssert (oldRegs.stopped == 0);
+
+ // Remember this as a stack so that our stack sniffer won't complain.
+ // Do this *before* changing the stack pointer, or else CheckSP won't
+ // be able to determine the stack we've switched into.
+
+ char* stackBase = this->GetStackBase ();
+ StackRange range ( EmBankMapped::GetEmulatedAddress (&stackBase[0]),
+ EmBankMapped::GetEmulatedAddress (&stackBase[kStackSize - 4]));
+ EmPalmOS::RememberStackRange (range);
+
+ // Point us to the business end of our private stack.
+ //
+ // Make sure we do this using SetRegisters (instead of just slamming
+ // regs[SP]) so that we can record the switch to the new stack (for
+ // our stack access monitoring code).
+
+ regstruct newRegs = oldRegs;
+
+ m68k_areg (newRegs, 7) = fStackPtr;
+ gCPU68K->SetRegisters (newRegs);
+
+ // Call the Palm OS function.
+
+ err = this->DoCall (trapWord);
+
+ // Save the result.
+
+ fReturnedA0 = m68k_areg (regs, 0);
+ fReturnedD0 = m68k_dreg (regs, 0);
+
+ // Restore the original state.
+
+ EmPalmOS::ForgetStack (EmBankMapped::GetEmulatedAddress (this->GetStackBase ()));
+
+ EmAssert (gCPU68K);
+ gCPU68K->SetRegisters (oldRegs);
+
+ // Unmap the stack that got mapped in PrepareStack.
+
+ EmBankMapped::UnmapPhysicalMemory (this->GetStackBase ());
+
+ // Check to see if anything interesting was registered while we
+ // were making the Palm OS subroutine call. The "check after end
+ // of cycle" bit may have gotten cleared when restoring the old
+ // registers, so set it on the off chance that it was. Doing this
+ // is harmless if there really aren't any scheduled tasks.
+
+ EmAssert (gSession);
+ gCPU68K->CheckAfterCycle ();
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::CallSelector
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPU68K::CallSelector (uint16 trapWord, uint16 selector)
+{
+ Err err = errNone;
+
+ // Save the current state.
+
+ regstruct oldRegs;
+ gCPU68K->GetRegisters (oldRegs);
+
+ // Set up the selector.
+
+ regstruct newRegs = oldRegs;
+
+ m68k_dreg (newRegs, 2) = selector;
+ gCPU68K->SetRegisters (newRegs);
+
+ // Call the function.
+
+ err = this->Call (trapWord);
+
+ // Restore the original state.
+
+ EmAssert (gCPU68K);
+ gCPU68K->SetRegisters (oldRegs);
+
+ return err;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::GetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+uint32 EmSubroutineCPU68K::GetReturnRegInteger (void)
+{
+ return fReturnedD0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::GetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+emuptr EmSubroutineCPU68K::GetReturnRegPointer (void)
+{
+ return fReturnedA0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::SetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU68K::SetReturnRegInteger (uint32 val)
+{
+ fReturnedD0 = val;
+ m68k_dreg (regs, 0) = val;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::SetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPU68K::SetReturnRegPointer (void* val)
+{
+ fReturnedA0 = (uae_u32) val;
+ m68k_areg (regs, 0) = (uae_u32) val;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::DoCall
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPU68K::DoCall (uint16 trapWord)
+{
+ Err err = errNone;
+
+ // Stop all profiling activities. Stop cycle counting and stop the
+ // recording of function entries and exits. We want our calls to
+ // ROM functions to be as transparent as possible.
+
+ StDisableAllProfiling stopper;
+
+
+ // Assert that the function we're trying to call is implemented.
+ //
+ // Oops...bad test...this doesn't work when we're calling a library.
+ // Instead, since we now invoke ROM functions by creating a TRAP $F
+ // sequence, we'll let our TRAP $F handler deal with validating the
+ // function call (it does that anyway).
+
+// EmAssert (LowMem::GetTrapAddress (trapWord));
+
+ // We call the ROM function by dummying up a sequence of 68xxx instructions
+ // for it. The sequence of instructions is:
+ //
+ // TRAP $F
+ // DC.W <dispatch number>
+ // TRAP $C
+ //
+ // The first two words invoke the function (calling any head- or tailpatches
+ // along the way). The third word allows the emulator to regain control
+ // after the function has returned.
+ //
+ // Note: this gets a little ugly on little-endian machines. The following
+ // instructions are stored on the emulator's stack. This memory is mapped
+ // into the emulated address space in such a fashion that no byteswapping of
+ // word or long values occurs. Thus, we have to put the data into Big Endian
+ // format when putting it into the array.
+ //
+ // However, opcodes are a special case. They are optimized in the emulator
+ // for fast access. Opcodes are *always* fetched a word at a time in host-
+ // endian order. Thus, the opcodes below have to be stored in host-endian
+ // order. That's why there's no call to Canonical to put them into Big
+ // Endian order.
+
+ uint16 code[] = { kOpcode_ROMCall, trapWord, kOpcode_ATrapReturn };
+
+ // Oh, OK, we do have to byteswap the trapWord. Opcodes are fetched with
+ // EmMemDoGet16, which always gets the value in host byte order. The
+ // trapWord is fetched with EmMemGet16, which gets values according to the
+ // rules of the memory bank. For the dummy bank, the defined byte order
+ // is Big Endian.
+
+ Canonical (code[1]);
+
+ // Map in the code stub so that the emulation code can access it.
+
+ StMemoryMapper mapper (code, sizeof (code));
+
+ // Prepare to handle the TRAP 12 exception.
+
+ EmAssert (gCPU68K);
+ gCPU68K->InstallHookException (kException_ATrapReturn,
+ (Hook68KException) HandleTrap12);
+
+ // Point the PC to our code.
+
+ emuptr newPC = EmBankMapped::GetEmulatedAddress (code);
+ m68k_setpc (newPC);
+
+ // Execute until the next break.
+
+ try
+ {
+ EmAssert (gSession);
+ gSession->ExecuteSubroutine ();
+ }
+ catch (EmExceptionReset& e)
+ {
+ e.SetTrapWord (trapWord);
+
+ // Remove the TRAP 12 exception handler.
+
+ EmAssert (gCPU68K);
+ gCPU68K->RemoveHookException (kException_ATrapReturn,
+ (Hook68KException) HandleTrap12);
+
+ throw;
+ }
+
+ // Remove the TRAP 12 exception handler.
+
+ EmAssert (gCPU68K);
+ gCPU68K->RemoveHookException (kException_ATrapReturn,
+ (Hook68KException) HandleTrap12);
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::HandleTrap12
+// ---------------------------------------------------------------------------
+// This function really takes an ExceptionNumber as a parameter. However,
+// we don't use/need it, and omitting it helps our forward declarations.
+
+Bool EmSubroutineCPU68K::HandleTrap12 (void)
+{
+ EmAssert (gSession);
+ gSession->ScheduleSuspendSubroutineReturn ();
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::GetStackBase
+// ---------------------------------------------------------------------------
+
+char* EmSubroutineCPU68K::GetStackBase ()
+{
+ // Ensure that the stack is aligned to a longword address.
+
+ uint32 stackBase = (uint32) fStack;
+
+ stackBase += 3;
+ stackBase &= ~3;
+
+ return (char*) stackBase;
+}
+
+
+#pragma mark ------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::EmSubroutineCPUARM
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPUARM::EmSubroutineCPUARM (void)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::~EmSubroutineCPUARM
+// ---------------------------------------------------------------------------
+
+EmSubroutineCPUARM::~EmSubroutineCPUARM (void)
+{
+ EmAssert (false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::FormatStack
+// ---------------------------------------------------------------------------
+
+long EmSubroutineCPUARM::FormatStack (EmParamList& /*params*/)
+{
+ EmAssert (false);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPUARM::PrepareStack (Bool /*forCalling*/, Bool /*forStdArg*/, long /*stackSize*/)
+{
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::PrepareStack
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPUARM::PrepareStack (emuptr /*stackAddr*/)
+{
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::Call
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPUARM::Call (uint16 /*trapWord*/)
+{
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPU68K::CallSelector
+// ---------------------------------------------------------------------------
+
+Err EmSubroutineCPUARM::CallSelector (uint16 /*trapWord*/, uint16 /*selector*/)
+{
+ EmAssert (false);
+
+ return errNone;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, int8& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, int16& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, int32& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, int64& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, uint8& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, uint16& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, uint32& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, uint64& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, float& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, double& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::GetParamVal (EmParam& /*param*/, long double& /*result*/)
+{
+ EmAssert (false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, int8 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, int16 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, int32 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, int64 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, uint8 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, uint16 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, uint32 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, uint64 /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, float /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, double /*val*/)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetParamVal
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetParamVal (EmParam& /*param*/, long double /*val*/)
+{
+ EmAssert (false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+uint32 EmSubroutineCPUARM::GetReturnRegInteger (void)
+{
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::GetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+emuptr EmSubroutineCPUARM::GetReturnRegPointer (void)
+{
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetReturnRegInteger
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetReturnRegInteger (uint32)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSubroutineCPUARM::SetReturnRegPointer
+// ---------------------------------------------------------------------------
+
+void EmSubroutineCPUARM::SetReturnRegPointer (void*)
+{
+}
diff --git a/SrcShared/EmSubroutine.h b/SrcShared/EmSubroutine.h
new file mode 100644
index 0000000..d9c8236
--- /dev/null
+++ b/SrcShared/EmSubroutine.h
@@ -0,0 +1,377 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmSubroutine_h
+#define EmSubroutine_h
+
+#include <string>
+#include <vector>
+
+/*
+ Overview:
+ ---------
+
+ From time to time, Poser needs to interfere with emulated code
+ as it calls from one subroutine to another. In some cases, Poser
+ needs to intercept the call on entry or exit and perform some
+ actions. On rarer occasions, Poser needs to completely replace
+ the called subroutine, prohibiting from executing entirely. And
+ on other occasions, Poser needs to be able to call a subroutine
+ in the emulated environment.
+
+ The EmSubroutine class helps in these activities. For the cases
+ where it is patching a called subroutine (possibly replacing it
+ entirely), Poser needs to read the parameters passed to the subroutine,
+ and possibly even provide a function result. For the cases where
+ is calling an emulated subroutine, Poser needs to push parameters
+ onto the emulated stack, and then read back any function result
+ when the subroutine returns.
+
+ Both of these activities (calling an emulated function, and being
+ called from an emulated function) require that Poser know the
+ format of the stack (that is, the number, order, and type of the
+ parameters pushed or to be pushed onto the stack).
+
+ The EmSubroutine class has methods used to define the stack format.
+ When defining the stack format, the EmSubroutine class needs to
+ provide one to three pieces of information for each parameter:
+
+ * The parameter type.
+ * An optional parameter name.
+ * An optional parameter value.
+
+
+ Calling an emulated function:
+ -----------------------------
+
+ When Poser needs to call an emulated function, it takes the following
+ steps:
+
+ * Creates an EmSubroutine object.
+
+ * Specifies the types and values of the parameters with a
+ specification string passed to the object's constructor.
+
+ * Sets the values of the parameters with multiple calls
+ to SetParamVal.
+
+ * Calls the function by calling Call.
+
+ * Reads any return value by calling GetReturnVal.
+
+ For example:
+
+ Err DmCreateDatabase (UInt16 cardNo, const Char * const nameP,
+ UInt32 creator, UInt32 type, Boolean resDB)
+ {
+ // Create subroutine object.
+
+ EmSubroutine sub ( "Err",
+ "UInt16 cardNo,"
+ "const Char * const nameP,"
+ "UInt32 creator,"
+ "UInt32 type,"
+ "Boolean resDB",
+ true);
+
+ // Set parameter values.
+
+ sub.SetParamVal ("cardNo", cardNo);
+ sub.SetParamVal ("nameP", nameP);
+ sub.SetParamVal ("creator", creator);
+ sub.SetParamVal ("type", type);
+ sub.SetParamVal ("resDB", resDB);
+
+ // Call the subroutine.
+
+ sub.Call (sysTrapDmCreateDatabase);
+
+ // Get and return subroutine result.
+
+ Err result;
+ sub.GetReturnVal (result);
+ return result;
+ }
+
+
+ Being called by an emulated function:
+ -------------------------------------
+
+ When Poser needs to respond to an emulated function making a
+ subroutine call, it takes the following steps:
+
+ * Creates an EmSubroutine object.
+
+ * Specifies the types and values of the parameters with a
+ specification string passed to the object's constructor.
+
+ * Retrieves the values on the stack with multple calls
+ to GetParamVal.
+
+ * Optionally specifies a function return value by calling
+ SetReturnVal.
+
+ For example:
+
+ CallROMType SysHeadpatch::ExgDoDialog (void)
+ {
+ // Boolean ExgDoDialog (ExgSocketPtr socketP,
+ // ExgDialogInfoType* infoP,
+ // Err* errP)
+
+ // If this patch is not supposed to do anything special
+ // right now, just return, saying that the ROM version
+ // should be executed as normal.
+
+ if (!gAutoAcceptBeamDialogs)
+ return kExecuteROM;
+
+ // Create subroutine object.
+
+ EmSubroutine sub ( "Boolean",
+ "ExgSocketPtr socketP,"
+ "ExgDialogInfoType* infoP,"
+ "Err* errP",
+ false);
+
+ // Read the parameter values.
+
+ void* socketP;
+ void* infoP;
+ void* errP;
+
+ sub.GetParamVal ("socketP", socketP);
+ sub.GetParamVal ("infoP", infoP);
+ sub.GetParamVal ("errP", errP);
+
+ // If no socket, just return, saying that the ROM version
+ // should be executed as normal.
+
+ if (!socketP)
+ return kExecuteROM;
+
+ // Set the "errP" parameter to zero.
+
+ sub.SetParamRef ("errP", (Err) errNone);
+
+ // Set the function result to "true".
+
+ sub.SetReturnVal ((Bool) true);
+
+ // Return, saying that we completely implemented the
+ // function and that the ROM version should not be
+ // executed at all.
+
+ return kSkipROM;
+ }
+*/
+
+
+typedef string EmParamName;
+typedef const char* EmParamNameArg;
+typedef const char* EmParamDecl;
+typedef const char* EmParamListDecl;
+
+
+enum EmParamType
+{
+ kEm_Unknown, // Unknown type.
+ kEm_Void, // Return type, and generic pointer type
+
+ kEm_SI1, // 1-byte signed integer
+ kEm_SI2, // 2-byte signed integer
+ kEm_SI4, // 4-byte signed integer
+ kEm_SI8, // 8-byte signed integer
+
+ kEm_UI1, // 1-byte unsigned integer
+ kEm_UI2, // 2-byte unsigned integer
+ kEm_UI4, // 4-byte unsigned integer
+ kEm_UI8, // 8-byte unsigned integer
+
+ kEm_FP4, // 4-byte floating point
+ kEm_FP8, // 8-byte floating point
+ kEm_FP16 // 16-byte floating point
+};
+
+
+struct EmParamInfo
+{
+ const char* fTypeName;
+
+ // If the parameter is passed by value, this holds the type of
+ // the value. If the parameter is pass by reference, this holds
+ // the type pointed to.
+
+ EmParamType fType;
+
+ // If this is false, the parameter is passed by value, and pushed
+ // directly onto the stack. If this is true, the parameter is
+ // passed by reference, and a pointer to the value is pushed onto
+ // the stack.
+ //
+ // If the EmParamInfo is used to record information about a function's
+ // return value, fByRef can indicate where the return value is stored.
+ // On 68K platforms, pointers are stored in A0, while directly scalar
+ // values are stored in D0.
+
+ Bool fByRef;
+};
+
+struct EmParam
+{
+ EmParam (void) :
+ fName (),
+ fType (kEm_Void),
+ fStackOffset (0),
+ fByRef (false)
+ {
+ }
+
+ EmParamName fName;
+
+ EmParamType fType;
+ long fStackOffset;
+ Bool fByRef;
+};
+
+typedef vector<EmParam> EmParamList;
+
+class EmSubroutineCPU;
+
+#define kForCalling true
+#define kForBeingCalled false
+
+enum
+{
+ kEmErrUnsupportedType = 1,
+ kEmErrUnknownParameter,
+ kEmErrTypeMismatch
+};
+
+
+
+#define VIRTUAL
+
+class EmSubroutine
+{
+ public:
+ EmSubroutine (void);
+ VIRTUAL ~EmSubroutine (void);
+
+ VIRTUAL Err DescribeDecl (EmParamDecl, EmParamListDecl);
+ VIRTUAL Err AddParam (EmParamDecl);
+ VIRTUAL Err PrepareStack (Bool forCalling, Bool forStdArgs);
+ VIRTUAL Err PrepareStack (emuptr);
+ VIRTUAL Err Reset (void);
+
+ // Read the parameter indicated by the given parameter name
+ // and return it as the given type.
+ //
+ // !!! What to do if the given parameter type is not the same
+ // as the return parameter type?
+
+ VIRTUAL Err GetParamVal (EmParamNameArg, int8&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, int16&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, int32&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, int64&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, uint8&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, uint16&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, uint32&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, uint64&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, float&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, double&);
+ VIRTUAL Err GetParamVal (EmParamNameArg, long double&);
+
+ // Get the value returned by the function.
+
+ VIRTUAL Err GetReturnVal (int8&);
+ VIRTUAL Err GetReturnVal (int16&);
+ VIRTUAL Err GetReturnVal (int32&);
+ VIRTUAL Err GetReturnVal (int64&);
+ VIRTUAL Err GetReturnVal (uint8&);
+ VIRTUAL Err GetReturnVal (uint16&);
+ VIRTUAL Err GetReturnVal (uint32&);
+ VIRTUAL Err GetReturnVal (uint64&);
+ VIRTUAL Err GetReturnVal (float&);
+ VIRTUAL Err GetReturnVal (double&);
+ VIRTUAL Err GetReturnVal (long double&);
+
+ // Store the given value into the memory pointed to by the
+ // pointer parameter indicated by the given parameter name.
+ // These functions are useful for returning results in "pass
+ // by reference" parameters.
+ //
+ // !!! What to do if the specified parameter is not a pointer
+ // type. Of less concern, what if it is not the right type?
+
+ VIRTUAL Err SetParamVal (EmParamNameArg, int8);
+ VIRTUAL Err SetParamVal (EmParamNameArg, int16);
+ VIRTUAL Err SetParamVal (EmParamNameArg, int32);
+ VIRTUAL Err SetParamVal (EmParamNameArg, int64);
+ VIRTUAL Err SetParamVal (EmParamNameArg, uint8);
+ VIRTUAL Err SetParamVal (EmParamNameArg, uint16);
+ VIRTUAL Err SetParamVal (EmParamNameArg, uint32);
+ VIRTUAL Err SetParamVal (EmParamNameArg, uint64);
+ VIRTUAL Err SetParamVal (EmParamNameArg, float);
+ VIRTUAL Err SetParamVal (EmParamNameArg, double);
+ VIRTUAL Err SetParamVal (EmParamNameArg, long double);
+
+ // Set the value to be returned by the function.
+
+ VIRTUAL Err SetReturnVal (int8);
+ VIRTUAL Err SetReturnVal (int16);
+ VIRTUAL Err SetReturnVal (int32);
+ VIRTUAL Err SetReturnVal (int64);
+ VIRTUAL Err SetReturnVal (uint8);
+ VIRTUAL Err SetReturnVal (uint16);
+ VIRTUAL Err SetReturnVal (uint32);
+ VIRTUAL Err SetReturnVal (uint64);
+ VIRTUAL Err SetReturnVal (float);
+ VIRTUAL Err SetReturnVal (double);
+ VIRTUAL Err SetReturnVal (long double);
+
+ // Call the given system function. The first form merely
+ // calls the indicated function. The second stores the
+ // selector in D2 and then calls the function.
+ //
+ // !!! Needs to be extended for calling library functions,
+ // calling HostControl functions (which take the selector
+ // on the stack), and may need to be adjusted according to
+ // however ARM functions will be specified.
+
+ VIRTUAL Err Call (uint16 trapWord);
+ VIRTUAL Err CallSelector (uint16 trapWord, uint16 selector);
+
+ private:
+ uint32 GetReturnRegInteger (void);
+ emuptr GetReturnRegPointer (void);
+
+ void SetReturnRegInteger (uint32);
+ void SetReturnRegPointer (void*);
+
+ EmSubroutineCPU* GetCPU (void);
+ Bool Is68K (void);
+ Bool IsARM (void);
+
+ Err ParseParamDecl (EmParamDecl, EmParam&);
+ string GetToken (EmParamDecl, string::size_type& offset);
+ EmParamList::iterator FindParam (EmParamNameArg);
+
+ private:
+ EmSubroutineCPU* fCPU;
+ EmParamList fParams;
+ EmParam fReturnType;
+ long fStackSize;
+};
+
+#endif // EmSubroutine_h
diff --git a/SrcShared/EmThreadSafeQueue.cpp b/SrcShared/EmThreadSafeQueue.cpp
new file mode 100644
index 0000000..9e1a905
--- /dev/null
+++ b/SrcShared/EmThreadSafeQueue.cpp
@@ -0,0 +1,186 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmThreadSafeQueue.h"
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue
+// ---------------------------------------------------------------------------
+
+template <class T>
+EmThreadSafeQueue<T>::EmThreadSafeQueue (int maxSize) :
+ fMutex (),
+#if HAS_OMNI_THREAD
+ fAvailable (&fMutex),
+#endif
+ fContainer (),
+ fMaxSize (maxSize)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue
+// ---------------------------------------------------------------------------
+
+template <class T>
+EmThreadSafeQueue<T>::~EmThreadSafeQueue (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::Put
+// ---------------------------------------------------------------------------
+
+template <class T>
+void EmThreadSafeQueue<T>::Put (const T& value)
+{
+ omni_mutex_lock lock (fMutex);
+
+ EmAssert (fMaxSize == 0 || (long) fContainer.size () < fMaxSize);
+
+ fContainer.push_back (value);
+
+#if HAS_OMNI_THREAD
+ // Tell clients that there may be new data in the buffer.
+ fAvailable.signal ();
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::Get
+// ---------------------------------------------------------------------------
+
+template <class T>
+T EmThreadSafeQueue<T>::Get (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ // Make sure there's something in the queue (this shouldn't happen,
+ // because the caller should always call GetUsed before Get).
+
+ EmAssert (fContainer.size () > 0);
+
+ T result = fContainer[0];
+ fContainer.pop_front ();
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::Peek
+// ---------------------------------------------------------------------------
+
+template <class T>
+T EmThreadSafeQueue<T>::Peek (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ // Make sure there's something in the queue (this shouldn't happen,
+ // because the caller should always call GetUsed before Get).
+
+ EmAssert (fContainer.size () > 0);
+
+ T result = fContainer[0];
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::GetFree
+// ---------------------------------------------------------------------------
+
+template <class T>
+int EmThreadSafeQueue<T>::GetFree (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ return fMaxSize - fContainer.size ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::GetUsed
+// ---------------------------------------------------------------------------
+
+template <class T>
+int EmThreadSafeQueue<T>::GetUsed (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ return fContainer.size ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::WaitForDataAvailable
+// ---------------------------------------------------------------------------
+
+template <class T>
+Bool EmThreadSafeQueue<T>::WaitForDataAvailable (long timeoutms)
+{
+#if HAS_OMNI_THREAD
+
+ // calc absolute time to wait until:
+ unsigned long sec;
+ unsigned long nanosec;
+ omni_thread::get_time (&sec, &nanosec, 0, timeoutms * 1000);
+
+ return fAvailable.timedwait (sec, nanosec) == 1;
+
+#else
+
+ UNUSED_PARAM (timeoutms)
+ return fContainer.size () > 0;
+
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::Clear
+// ---------------------------------------------------------------------------
+
+template <class T>
+void EmThreadSafeQueue<T>::Clear (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fContainer.clear ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmThreadSafeQueue::GetMaxSize
+// ---------------------------------------------------------------------------
+
+template <class T>
+int EmThreadSafeQueue<T>::GetMaxSize (void)
+{
+ return fMaxSize;
+}
+
+// Instantiate the ones we want.
+
+#include "EmSession.h" // uint8 (Byte), EmButtonEvent, EmKeyEvent, EmPenEvent
+
+template class EmThreadSafeQueue<uint8>;
+template class EmThreadSafeQueue<EmButtonEvent>;
+template class EmThreadSafeQueue<EmKeyEvent>;
+template class EmThreadSafeQueue<EmPenEvent>;
diff --git a/SrcShared/EmThreadSafeQueue.h b/SrcShared/EmThreadSafeQueue.h
new file mode 100644
index 0000000..817a93a
--- /dev/null
+++ b/SrcShared/EmThreadSafeQueue.h
@@ -0,0 +1,49 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmThreadSafeQueue_h
+#define EmThreadSafeQueue_h
+
+#include "omnithread.h"
+
+#include <deque>
+
+template <class T>
+class EmThreadSafeQueue
+{
+ public:
+ EmThreadSafeQueue (int maxSize = 0);
+ ~EmThreadSafeQueue (void);
+
+ void Put (const T&);
+ T Get (void);
+ T Peek (void);
+ int GetUsed (void);
+ int GetFree (void);
+ Bool WaitForDataAvailable (long timeoutms);
+
+ void Clear (void);
+ int GetMaxSize (void);
+
+ private:
+ omni_mutex fMutex;
+#if HAS_OMNI_THREAD
+ omni_condition fAvailable;
+#endif
+ deque<T> fContainer;
+ int fMaxSize;
+};
+
+typedef EmThreadSafeQueue<uint8> EmByteQueue;
+
+#endif // EmThreadSafeQueue_h
diff --git a/SrcShared/EmTransport.cpp b/SrcShared/EmTransport.cpp
new file mode 100644
index 0000000..89f1f92
--- /dev/null
+++ b/SrcShared/EmTransport.cpp
@@ -0,0 +1,669 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransport.h"
+
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "EmTransportSocket.h" // EmTransportSocket
+#include "EmTransportUSB.h" // EmTransportUSB
+
+#include <vector> // vector
+#include <algorithm> // find()
+
+
+typedef vector<EmTransport*> EmTransportList;
+EmTransportList gTransports;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransport::EmTransport (void)
+{
+ gTransports.push_back (this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransport::~EmTransport (void)
+{
+ EmTransportList::iterator iter = find (gTransports.begin (),
+ gTransports.end (),
+ this);
+
+ if (iter != gTransports.end ())
+ {
+ gTransports.erase (iter);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::Open
+ *
+ * DESCRIPTION: Open the transport using the information provided
+ * either in the constructor or with SetConfig.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransport::Open (void)
+{
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::Close
+ *
+ * DESCRIPTION: Close the transport.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransport::Close (void)
+{
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::Read
+ *
+ * DESCRIPTION: Read up to the given number of bytes, storing them in
+ * the given buffer.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransport::Read (long&, void*)
+{
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::Write
+ *
+ * DESCRIPTION: Write up the the given number of bytes, using the data
+ * in the given buffer.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransport::Write (long&, const void*)
+{
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::CanRead
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a read operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there are
+ * actually any bytes available to be read.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransport::CanRead (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::CanWrite
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a write operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there is
+ * actually any room in the transport's internal buffer
+ * for the data being written.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransport::CanWrite (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::BytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: minBytes - try to buffer at least this many bytes.
+ * Return when we have this many bytes buffered, or
+ * until some small timeout has occurred.
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransport::BytesInBuffer (long /*minBytes*/)
+{
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransport::CloseAllTransports
+ *
+ * DESCRIPTION: Shutdown routine. Close all existing transports.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransport::CloseAllTransports (void)
+{
+ EmTransportList::iterator iter = gTransports.begin ();
+ while (iter != gTransports.end ())
+ {
+ EmTransport* transport = *iter;
+ transport->Close ();
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportNull::EmTransportNull
+// ---------------------------------------------------------------------------
+
+EmTransportNull::EmTransportNull (void)
+{
+}
+
+
+EmTransportNull::EmTransportNull (const EmTransportDescriptor&)
+{
+}
+
+
+EmTransportNull::EmTransportNull (const ConfigNull&)
+{
+}
+
+
+EmTransportNull::~EmTransportNull (void)
+{
+ this->Close ();
+}
+
+
+ErrCode EmTransportNull::Open (void)
+{
+ return errNone;
+}
+
+
+ErrCode EmTransportNull::Close (void)
+{
+ return errNone;
+}
+
+
+ErrCode EmTransportNull::Read (long& size, void*)
+{
+ size = 0;
+ return errNone;
+}
+
+
+ErrCode EmTransportNull::Write (long&, const void*)
+{
+ return errNone;
+}
+
+
+Bool EmTransportNull::CanRead (void)
+{
+ return true;
+}
+
+
+Bool EmTransportNull::CanWrite (void)
+{
+ return true;
+}
+
+
+long EmTransportNull::BytesInBuffer (long /*minBytes*/)
+{
+ return 0;
+}
+
+
+string EmTransportNull::GetSpecificName (void)
+{
+ return "Bit Bucket";
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportNull:: GetDescriptorList
+ *
+ * DESCRIPTION: Return the list of TCP ports on this computer. Used
+ * to prepare a menu of TCP port choices.
+ *
+ * PARAMETERS: nameList - port names are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportNull::GetDescriptorList (EmTransportDescriptorList& descList)
+{
+ descList.clear ();
+
+ descList.push_back (EmTransportDescriptor (kTransportNull));
+}
+
+
+#pragma mark -
+
+// EmTransportDescriptor
+//
+// This is a simple class that manages the creation of an EmTransport.
+// It can be initialized with information describing what kind of transport
+// to create (Serial, Socket, USB, etc.) and the parameters used to create
+// it (serial configuration, IP address, etc.). Once that information has
+// be established, calling CreateTransport will create the appropriate
+// transport object.
+//
+// EmTransportDescriptor is also called upon to provide UI information
+// appropriate for display in dialogs (in menus or edit text items).
+//
+// Internally, this information is stored as a string. The string is
+// divided into two parts: a "scheme", and scheme-specific data. These
+// two parts are divided by a colon. The scheme identifies what kind of
+// transport is to be created, and any option scheme-specific data
+// describes the creation parameters.
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::EmTransportDescriptor (void) :
+ fDescriptor ("unknown")
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::EmTransportDescriptor (EmTransportType type) :
+ fDescriptor (GetSchemePrefix (type) + ":")
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::EmTransportDescriptor (EmTransportType type, const string& s) :
+ fDescriptor (GetSchemePrefix (type) + ":" + s)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::EmTransportDescriptor (const string& s) :
+ fDescriptor (s)
+{
+#if PLATFORM_UNIX
+ if (this->GetType () == kTransportUnknown)
+ {
+ // On Unix, we'll be handed something that looks either like a device
+ // or an IP address. Try to guess which and set up the scheme type
+ // based on what we decide.
+
+ if (s.size () == 0)
+ {
+ // Empty string -- turn into a NULL descriptor.
+
+ fDescriptor = this->GetSchemePrefix (kTransportNull) + ":";
+ }
+ else if (s[0] == '/')
+ {
+ // It looks like a device name -- turn into a Serial descriptor.
+
+ fDescriptor = this->GetSchemePrefix (kTransportSerial) + ":" + fDescriptor;
+ }
+ else
+ {
+ // Assume IP address. I'm not sure if there's a good way to
+ // ensure this. What's a good heuristic check?
+
+ fDescriptor = this->GetSchemePrefix (kTransportSocket) + ":" + fDescriptor;
+ }
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::EmTransportDescriptor (const EmTransportDescriptor& other) :
+ fDescriptor (other.fDescriptor)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::~EmTransportDescriptor
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor::~EmTransportDescriptor (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::operator=
+// ---------------------------------------------------------------------------
+
+EmTransportDescriptor& EmTransportDescriptor::operator= (const EmTransportDescriptor& other)
+{
+ fDescriptor = other.fDescriptor;
+
+ return *this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::operator==
+// ---------------------------------------------------------------------------
+
+bool EmTransportDescriptor::operator== (const EmTransportDescriptor& other) const
+{
+ return fDescriptor == other.fDescriptor;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::CreateTransport
+// ---------------------------------------------------------------------------
+
+EmTransport* EmTransportDescriptor::CreateTransport (void) const
+{
+ EmTransport* result;
+ EmTransportType type = this->GetType ();
+
+ switch (type)
+ {
+ case kTransportNull:
+ result = new EmTransportNull (*this);
+ break;
+
+ case kTransportSerial:
+ result = new EmTransportSerial (*this);
+ break;
+
+ case kTransportSocket:
+ result = new EmTransportSocket (*this);
+ break;
+
+ case kTransportUSB:
+ result = new EmTransportUSB (*this);
+ break;
+
+ default:
+ EmAssert (false);
+ result = new EmTransportNull (*this);
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetMenuName
+// ---------------------------------------------------------------------------
+
+string EmTransportDescriptor::GetMenuName (void) const
+{
+ string result;
+ EmTransportType type = this->GetType ();
+
+ switch (type)
+ {
+#if !PLATFORM_UNIX
+ case kTransportNull:
+ result = "No Port";
+ break;
+
+ case kTransportSerial:
+ result = this->GetSchemeSpecific ();
+ break;
+
+ case kTransportSocket:
+ result = "TCP/IP";
+ break;
+
+ case kTransportUSB:
+ result = "USB";
+ break;
+
+ default:
+ EmAssert (false);
+ result = "No Port";
+ break;
+#else
+ case kTransportNull:
+ case kTransportSerial:
+ case kTransportSocket:
+ case kTransportUSB:
+ result = this->GetSchemeSpecific ();
+ break;
+
+ default:
+ EmAssert (false);
+ result = "";
+ break;
+#endif
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetDescriptor
+// ---------------------------------------------------------------------------
+
+string EmTransportDescriptor::GetDescriptor (void) const
+{
+ EmAssert (this->GetType () != kTransportUnknown);
+
+ return this->fDescriptor;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetScheme
+// ---------------------------------------------------------------------------
+
+string EmTransportDescriptor::GetScheme (void) const
+{
+ string::size_type pos = this->fDescriptor.find (':');
+ EmAssert (pos != string::npos);
+ return this->fDescriptor.substr (0, pos);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetSchemeSpecific
+// ---------------------------------------------------------------------------
+
+string EmTransportDescriptor::GetSchemeSpecific (void) const
+{
+ string::size_type pos = this->fDescriptor.find (':');
+ EmAssert (pos != string::npos);
+ return this->fDescriptor.substr (pos + 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetType
+// ---------------------------------------------------------------------------
+
+EmTransportType EmTransportDescriptor::GetType (void) const
+{
+ if (this->PrvTestType (kTransportNull))
+ return kTransportNull;
+
+ if (this->PrvTestType (kTransportSerial))
+ return kTransportSerial;
+
+ if (this->PrvTestType (kTransportSocket))
+ return kTransportSocket;
+
+ if (this->PrvTestType (kTransportUSB))
+ return kTransportUSB;
+
+ return kTransportUnknown;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::GetSchemePrefix
+// ---------------------------------------------------------------------------
+// Return the descriptor prefix for the given scheme. The separating ":" is
+// NOT included.
+
+string EmTransportDescriptor::GetSchemePrefix (EmTransportType type)
+{
+ string result;
+
+ switch (type)
+ {
+ case kTransportNull:
+ result = "null";
+ break;
+
+ case kTransportSerial:
+ result = "serial";
+ break;
+
+ case kTransportSocket:
+ result = "socket";
+ break;
+
+ case kTransportUSB:
+ result = "usb";
+ break;
+
+ default:
+ EmAssert (false);
+ result = "null";
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTransportDescriptor::PrvTestType
+// ---------------------------------------------------------------------------
+// Return whether or not the controlled descriptor is part of the given scheme.
+
+Bool EmTransportDescriptor::PrvTestType (EmTransportType type) const
+{
+ string scheme = this->GetSchemePrefix (type) + ":";
+
+ if (this->fDescriptor.size () < scheme.size ())
+ return false;
+
+ string prefix = this->fDescriptor.substr (0, scheme.size ());
+
+ return prefix == scheme;
+}
diff --git a/SrcShared/EmTransport.h b/SrcShared/EmTransport.h
new file mode 100644
index 0000000..376d236
--- /dev/null
+++ b/SrcShared/EmTransport.h
@@ -0,0 +1,143 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransport_h
+#define EmTransport_h
+
+#include "EmTypes.h" // ErrCode
+
+#include <string> // string
+#include <vector> // vector
+
+
+enum EmTransportType
+{
+ kTransportNull, // "null:"
+ kTransportSerial, // "serial:"
+ kTransportSocket, // "tcp:"
+ kTransportUSB, // "usb:"
+
+ kTransportUnknown
+};
+
+class EmTransport;
+
+
+// Wraps up a "transport descriptor", something that identifies
+// a tranport that a user can point to and use in the UI.
+
+class EmTransportDescriptor
+{
+ public:
+ EmTransportDescriptor (void);
+ EmTransportDescriptor (EmTransportType);
+ EmTransportDescriptor (EmTransportType, const string&);
+ EmTransportDescriptor (const string&);
+ EmTransportDescriptor (const EmTransportDescriptor&);
+ ~EmTransportDescriptor (void);
+ EmTransportDescriptor& operator= (const EmTransportDescriptor&);
+
+ EmTransport* CreateTransport (void) const;
+
+ string GetMenuName (void) const; // For menus (e.g., "COM1", "TCP/IP")
+ string GetDescriptor (void) const; // Full text (e.g., "serial:COM1")
+ string GetScheme (void) const; // First part of text (e.g., "serial", "socket")
+ string GetSchemeSpecific (void) const; // Second part of text (e.g., "127.0.0.1:5001")
+ EmTransportType GetType (void) const; // Scheme in numeric form
+
+ static string GetSchemePrefix (EmTransportType); // Convert numeric format to scheme prefix
+
+ bool operator== (const EmTransportDescriptor&) const;
+
+ private:
+ Bool PrvTestType (EmTransportType type) const;
+
+ private:
+ string fDescriptor;
+};
+
+typedef vector<EmTransportDescriptor> EmTransportDescriptorList;
+
+
+class EmTransport
+{
+ public:
+ struct Config
+ {
+ Config (void) {};
+ virtual ~Config (void) {};
+
+ virtual EmTransport* NewTransport (void) = 0;
+ virtual EmTransport* GetTransport (void) = 0;
+ };
+
+ public:
+ EmTransport (void);
+ virtual ~EmTransport (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+
+ virtual ErrCode Read (long&, void*);
+ virtual ErrCode Write (long&, const void*);
+
+ virtual Bool CanRead (void);
+ virtual Bool CanWrite (void);
+
+ virtual long BytesInBuffer (long minBytes);
+
+ virtual string GetSpecificName (void) = 0;
+
+ static void CloseAllTransports (void);
+};
+
+
+class EmTransportNull : public EmTransport
+{
+ public:
+
+ // Note: this used to be named "Config", but that runs
+ // afoul of a bug in VC++ (see KB Q143082).
+ struct ConfigNull : public EmTransport::Config
+ {
+ ConfigNull (void) {};
+ virtual ~ConfigNull (void) {};
+
+ virtual EmTransport* NewTransport (void) { return new EmTransportNull; };
+ virtual EmTransport* GetTransport (void);
+ };
+
+ public:
+ EmTransportNull (void);
+ EmTransportNull (const EmTransportDescriptor&);
+ EmTransportNull (const ConfigNull&);
+ virtual ~EmTransportNull (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+
+ virtual ErrCode Read (long&, void*);
+ virtual ErrCode Write (long&, const void*);
+
+ virtual Bool CanRead (void);
+ virtual Bool CanWrite (void);
+
+ virtual long BytesInBuffer (long minBytes);
+
+ virtual string GetSpecificName (void);
+
+ static void GetDescriptorList (EmTransportDescriptorList&);
+};
+
+
+#endif /* EmTransport_h */
diff --git a/SrcShared/EmTransportSerial.cpp b/SrcShared/EmTransportSerial.cpp
new file mode 100644
index 0000000..190ca69
--- /dev/null
+++ b/SrcShared/EmTransportSerial.cpp
@@ -0,0 +1,696 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransportSerial.h"
+
+#include "EmErrCodes.h" // kError_CommOpen
+#include "Logging.h" // LogSerial
+
+
+EmTransportSerial::OpenPortList EmTransportSerial::fgOpenPorts;
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::EmTransportSerial (void) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ this->HostConstruct ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: desc - descriptor information used when opening
+ * the serial port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::EmTransportSerial (const EmTransportDescriptor& desc) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ ConfigSerial config;
+
+ config.fPort = desc.GetSchemeSpecific ();
+
+ this->HostConstruct ();
+ this->SetConfig (config);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: config - configuration information used when opening
+ * the serial port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::EmTransportSerial (const ConfigSerial& config) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ this->HostConstruct ();
+ this->SetConfig (config);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::~EmTransportSerial (void)
+{
+ this->Close ();
+
+ this->HostDestruct ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::Open
+ *
+ * DESCRIPTION: Open the transport using the information provided
+ * either in the constructor or with SetConfig.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::Open (void)
+{
+ PRINTF ("EmTransportSerial::Open...");
+
+ // Exit if communications have already been established.
+
+ if (fCommEstablished)
+ {
+ PRINTF ("EmTransportSerial::Open: Serial port already open...leaving...");
+ return kError_CommOpen;
+ }
+
+ EmAssert (fgOpenPorts.find (fConfig.fPort) == fgOpenPorts.end ());
+
+ ErrCode err = this->HostOpen ();
+
+ if (!err)
+ err = this->HostSetConfig (fConfig);
+
+ if (err)
+ {
+ this->HostClose ();
+ }
+ else
+ {
+ fCommEstablished = true;
+ fgOpenPorts[fConfig.fPort] = this;
+ }
+
+ if (err)
+ PRINTF ("EmTransportSerial::Open: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::Close
+ *
+ * DESCRIPTION: Close the transport.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::Close (void)
+{
+ PRINTF ("EmTransportSerial::Close...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSerial::Close: Serial port not open...leaving...");
+ return kError_CommNotOpen;
+ }
+
+ fCommEstablished = false;
+ fgOpenPorts.erase (fConfig.fPort);
+
+ ErrCode err = this->HostClose ();
+
+ if (err)
+ PRINTF ("EmTransportSerial::Close: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::Read
+ *
+ * DESCRIPTION: Read up to the given number of bytes, storing them in
+ * the given buffer.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::Read (long& len, void* data)
+{
+ PRINTF ("EmTransportSerial::Read...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSerial::Read: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostRead (len, data);
+
+ if (err)
+ PRINTF ("EmTransportSerial::Read: err = %ld", err);
+ else
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportSerial::Read: reading %ld bytes.", len);
+ else
+ PRINTF ("EmTransportSerial::Read: reading %ld bytes", len);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::Write
+ *
+ * DESCRIPTION: Write up the the given number of bytes, using the data
+ * in the given buffer.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::Write (long& len, const void* data)
+{
+ PRINTF ("EmTransportSerial::Write...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSerial::Write: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostWrite (len, data);
+
+ if (err)
+ PRINTF ("EmTransportSerial::Write: err = %ld", err);
+ else
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportSerial::Write: writing %ld bytes.", len);
+ else
+ PRINTF ("EmTransportSerial::Write: writing %ld bytes", len);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::CanRead
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a read operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there are
+ * actually any bytes available to be read.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::CanRead (void)
+{
+ return fCommEstablished;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::CanWrite
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a write operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there is
+ * actually any room in the transport's internal buffer
+ * for the data being written.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::CanWrite (void)
+{
+ return fCommEstablished;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::BytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: minBytes - try to buffer at least this many bytes.
+ * Return when we have this many bytes buffered, or
+ * until some small timeout has occurred.
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransportSerial::BytesInBuffer (long minBytes)
+{
+ if (!fCommEstablished)
+ return 0;
+
+ return this->HostBytesInBuffer (minBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetSpecificName
+ *
+ * DESCRIPTION: Returns the port name, or host address, depending on the
+ * transport in question.
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: string, appropriate to the transport in question.
+ *
+ ***********************************************************************/
+
+ string EmTransportSerial::GetSpecificName (void)
+ {
+ return fConfig.fPort;
+ }
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::SetConfig
+ *
+ * DESCRIPTION: Set the configuration to be used when opening the port,
+ * or to reconfigure a currently open port.
+ *
+ * PARAMETERS: config - the configuration to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::SetConfig (const ConfigSerial& config)
+{
+ PRINTF ("EmTransportSerial::SetConfig...");
+
+ if (config == fConfig)
+ {
+ PRINTF ("EmTransportSerial::SetConfig: Config unchanged, so not setting settings...");
+ return errNone;
+ }
+
+ fConfig = config;
+
+ // Exit if communications have not been established.
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSerial::SetConfig: Serial port closed, so not setting settings...");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostSetConfig (fConfig);
+
+ if (err)
+ PRINTF ("EmTransportSerial::SetConfig: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetConfig
+ *
+ * DESCRIPTION: Return the configuration specified in the constructor
+ * or in the last call to SetConfig.
+ *
+ * PARAMETERS: config - config object to receive the settings.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::GetConfig (ConfigSerial& config)
+{
+ config = fConfig;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::SetRTS
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::SetRTS (RTSControl state)
+{
+ this->HostSetRTS (state);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::SetDTR
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::SetDTR (Bool state)
+{
+ this->HostSetDTR (state);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::SetBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::SetBreak (Bool state)
+{
+ this->HostSetBreak (state);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetCTS
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::GetCTS (void)
+{
+ return this->HostGetCTS ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetDSR
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::GetDSR (void)
+{
+ return this->HostGetDSR ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: config - The configuration object containing information
+ * on a port in which we're interested. All or some
+ * of the information in this object is used when
+ * searching for a transport object already utilizing
+ * the port.
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransportSerial* EmTransportSerial::GetTransport (const ConfigSerial& config)
+{
+ OpenPortList::iterator iter = fgOpenPorts.find (config.fPort);
+
+ if (iter == fgOpenPorts.end ())
+ return NULL;
+
+ return iter->second;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetDescriptorList
+ *
+ * DESCRIPTION: Return the list of serial ports on this computer. Used
+ * to prepare a menu of serial port choices.
+ *
+ * PARAMETERS: nameList - port names are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::GetDescriptorList (EmTransportDescriptorList& descList)
+{
+ PortNameList portList;
+ HostGetPortNameList (portList);
+
+ descList.clear ();
+
+ PortNameList::iterator iter = portList.begin ();
+ while (iter != portList.end ())
+ {
+ descList.push_back (EmTransportDescriptor (kTransportSerial, *iter));
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::GetSerialBaudList
+ *
+ * DESCRIPTION: Return the list of baud rates support by this computer.
+ * Used to prepare a menu of baud rate choices.
+ *
+ * PARAMETERS: baudList - baud rates are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::GetSerialBaudList (BaudList& baudList)
+{
+ HostGetSerialBaudList (baudList);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::ConfigSerial c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::ConfigSerial::ConfigSerial (void) :
+ fPort (),
+ fBaud (57600),
+ fParity (kNoParity),
+ fStopBits (1),
+ fDataBits (8),
+ fHwrHandshake (true)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::ConfigSerial d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSerial::ConfigSerial::~ConfigSerial (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::ConfigSerial::NewTransport
+ *
+ * DESCRIPTION: Create a new transport object based on the configuration
+ * information in this object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The new transport object.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportSerial::ConfigSerial::NewTransport (void)
+{
+ return new EmTransportSerial (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::ConfigSerial::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportSerial::ConfigSerial::GetTransport (void)
+{
+ return EmTransportSerial::GetTransport (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::ConfigSerial::operator==
+ *
+ * DESCRIPTION: Compare two Config objects to each other
+ *
+ * PARAMETERS: other - the object to compare "this" to.
+ *
+ * RETURNED: True if the objects are equivalent.
+ *
+ ***********************************************************************/
+
+bool EmTransportSerial::ConfigSerial::operator==(const ConfigSerial& other) const
+{
+ return
+ fPort == other.fPort &&
+ fBaud == other.fBaud &&
+ fParity == other.fParity &&
+ fStopBits == other.fStopBits &&
+ fDataBits == other.fDataBits &&
+ fHwrHandshake == other.fHwrHandshake;
+}
diff --git a/SrcShared/EmTransportSerial.h b/SrcShared/EmTransportSerial.h
new file mode 100644
index 0000000..d74d2ba
--- /dev/null
+++ b/SrcShared/EmTransportSerial.h
@@ -0,0 +1,134 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransportSerial_h
+#define EmTransportSerial_h
+
+#include "EmTransport.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+class EmHostTransportSerial;
+
+class EmTransportSerial : public EmTransport
+{
+ public:
+ typedef string PortName;
+ typedef long Baud;
+ typedef long StopBits;
+ typedef long DataBits;
+ typedef long HwrHandshake;
+
+ typedef vector<PortName> PortNameList;
+ typedef vector<Baud> BaudList;
+
+ enum Parity
+ {
+ kNoParity,
+ kOddParity,
+ kEvenParity
+ };
+
+ enum RTSControl
+ {
+ kRTSOff,
+ kRTSOn,
+ kRTSAuto
+ };
+
+ // Note: this used to be named "Config", but that runs
+ // afoul of a bug in VC++ (see KB Q143082).
+ struct ConfigSerial : public EmTransport::Config
+ {
+ ConfigSerial (void);
+ virtual ~ConfigSerial (void);
+
+ virtual EmTransport* NewTransport (void);
+ virtual EmTransport* GetTransport (void);
+
+ bool operator==(const ConfigSerial& other) const;
+
+ PortName fPort;
+ Baud fBaud;
+ Parity fParity;
+ StopBits fStopBits;
+ DataBits fDataBits;
+ HwrHandshake fHwrHandshake;
+ };
+
+ typedef map<PortName, EmTransportSerial*> OpenPortList;
+
+ public:
+ EmTransportSerial (void);
+ EmTransportSerial (const EmTransportDescriptor&);
+ EmTransportSerial (const ConfigSerial&);
+ virtual ~EmTransportSerial (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+
+ virtual ErrCode Read (long&, void*);
+ virtual ErrCode Write (long&, const void*);
+
+ virtual Bool CanRead (void);
+ virtual Bool CanWrite (void);
+ virtual long BytesInBuffer (long minBytes);
+ virtual string GetSpecificName (void);
+
+ ErrCode SetConfig (const ConfigSerial&);
+ void GetConfig (ConfigSerial&);
+
+ void SetRTS (RTSControl state);
+ void SetDTR (Bool state);
+ void SetBreak (Bool state);
+
+ Bool GetCTS (void);
+ Bool GetDSR (void);
+
+ static EmTransportSerial* GetTransport (const ConfigSerial&);
+ static void GetDescriptorList (EmTransportDescriptorList&);
+ static void GetSerialBaudList (BaudList&);
+
+ private:
+ void HostConstruct (void);
+ void HostDestruct (void);
+
+ ErrCode HostOpen (void);
+ ErrCode HostClose (void);
+
+ ErrCode HostRead (long&, void*);
+ ErrCode HostWrite (long&, const void*);
+ long HostBytesInBuffer (long minBytes);
+
+ ErrCode HostSetConfig (const ConfigSerial&);
+
+ void HostSetRTS (RTSControl state);
+ void HostSetDTR (Bool state);
+ void HostSetBreak (Bool state);
+
+ Bool HostGetCTS (void);
+ Bool HostGetDSR (void);
+
+ static void HostGetPortNameList (PortNameList&);
+ static void HostGetSerialBaudList (BaudList&);
+
+ EmHostTransportSerial* fHost;
+ ConfigSerial fConfig;
+ Bool fCommEstablished;
+
+ static OpenPortList fgOpenPorts;
+};
+
+#endif /* EmTransportSerial_h */
diff --git a/SrcShared/EmTransportSocket.cpp b/SrcShared/EmTransportSocket.cpp
new file mode 100644
index 0000000..8121cec
--- /dev/null
+++ b/SrcShared/EmTransportSocket.cpp
@@ -0,0 +1,1220 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransportSocket.h"
+
+#include "EmErrCodes.h" // kError_CommOpen, kError_CommNotOpen, kError_NoError
+#include "Logging.h" // LogSerial
+#include "Platform.h" // Platform::AllocateMemory
+
+#if PLATFORM_MAC
+#include <GUSIPOSIX.h> // inet_addr
+#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_addr
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+EmTransportSocket::OpenPortList EmTransportSocket::fgOpenPorts;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ * NOTES: We used to only have a fDataSocket. Now, to allow for
+ * a listening socket to be opened before a connection is
+ * attempted, we need two sockets. Note that EmTransport
+ * Socket does not get its hands dirty with actual sockets.
+ * Thus, fDataListenSocket is not a socket in the traditional
+ * sense, and may be connected or not.
+ *
+ ***********************************************************************/
+
+EmTransportSocket::EmTransportSocket (void) :
+ fReadMutex (),
+ fReadBuffer (),
+ fDataConnectSocket (NULL),
+ fDataListenSocket (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: desc - descriptor information used when opening
+ * the TCP port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSocket::EmTransportSocket (const EmTransportDescriptor& desc) :
+ fReadMutex (),
+ fReadBuffer (),
+ fDataConnectSocket (NULL),
+ fDataListenSocket (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ ConfigSocket config;
+
+ string addr = desc.GetSchemeSpecific ();
+ string::size_type colonPos = addr.find (':');
+ string::size_type nonNumPos = addr.find_first_not_of ("0123456789");
+
+ // If there's a colon, assume a fully-specified address.
+
+ if (colonPos != string::npos)
+ {
+ config.fTargetHost = addr.substr (0, colonPos);
+ config.fTargetPort = addr.substr (colonPos + 1);
+ }
+
+ // If there's no colon, look for numbers. If the entire
+ // address is made up of numbers, assume it's a port number.
+
+ else if (nonNumPos == string::npos)
+ {
+ config.fTargetPort = addr;
+ }
+
+ // Otherwise, assume it's a host address with no port.
+
+ else
+ {
+ config.fTargetHost = addr;
+ }
+
+ fConfig = config;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: config - configuration information used when opening
+ * the TCP port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSocket::EmTransportSocket (const ConfigSocket& config) :
+ fReadMutex (),
+ fReadBuffer (),
+ fDataConnectSocket (NULL),
+ fDataListenSocket (NULL),
+ fConfig (config),
+ fCommEstablished (false)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSocket::~EmTransportSocket (void)
+{
+ this->Close ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::Open
+ *
+ * DESCRIPTION: Open the transport using the information provided
+ * either in the constructor or with SetConfig.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ * NOTES: Implements the new method of opening a listening socket,
+ * then opening a connection socket. This avoids the problem
+ * where both machines might try to connect, fail, and then
+ * each fall back to listening. However, this approach does
+ * not work in localhost mode, for obvious (upon reflection)
+ * reasons: if you start listening, then shout, you are
+ * going to hear yourself (or in this case, you're going to
+ * drop your listening socket once your connecting socket
+ * tells you that it has connected, not knowing that you have
+ * connected to yourself).
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::Open (void)
+{
+ PRINTF ("EmTransportSocket::Open...");
+
+ // Exit if communications have already been established.
+
+ if (fCommEstablished)
+ {
+ PRINTF ("EmTransportSocket::Open: TCP port already open...leaving...");
+ return kError_CommOpen;
+ }
+
+ string registrationKey = "TCP:" + fConfig.fTargetHost + ":" + fConfig.fTargetPort;
+ EmAssert (fgOpenPorts.find (registrationKey) == fgOpenPorts.end ());
+
+ ErrCode err;
+
+ if (fConfig.fTargetHost != "localhost")
+ {
+ err= OpenCommPortListen (fConfig);
+
+ if (err)
+ {
+ PRINTF ("EmTransportSocket::Open: comm port closed due to error %ld on listening attempt", err);
+ PRINTF ("EmTransportSocket::Open: closing listening socket");
+
+ err = CloseCommPortListen ();
+ fCommEstablished = false;
+
+ if (err)
+ PRINTF ("EmTransportSocket::Open: err = %ld when closing listen socket", err);
+ }
+ else if (fDataListenSocket->ConnectPending ())
+ {
+ PRINTF ("EmTransportSocket::Open: not attempting to connect due to a pending connection");
+ }
+ else
+ {
+ PRINTF ("EmTransportSocket::Open: listening socket opened properly");
+
+ // set to true here because we are listening properly; not affected by whether this
+ // next connect call fails
+ fCommEstablished = true;
+
+ err = OpenCommPortConnect (fConfig);
+ }
+
+ if (err == 0)
+ {
+ fCommEstablished = true;
+ fgOpenPorts[registrationKey] = this;
+
+ PRINTF ("EmTransportSocket::Open: successful connection, so closing listening socket");
+
+ err = CloseCommPortListen ();
+ }
+ else
+ {
+ PRINTF ("EmTransportSocket::Open: err = %ld on connect attempt", err);
+ PRINTF ("EmTransportSocket::Open: closing connect socket");
+
+ err = CloseCommPortConnect ();
+ }
+ }
+ else
+ {
+ PRINTF ("EmTransportSocket::Open: opening in localhost mode (old style)");
+
+ err = OpenCommPortConnect (fConfig);
+
+ if (err)
+ {
+ PRINTF ("EmTransportSocket::Open: err %ld in connect attempt", err);
+
+ err = CloseCommPortConnect ();
+
+ if (err)
+ PRINTF ("EmTransportSocket::Open: err %ld in connect socket close", err);
+
+ PRINTF ("EmTransportSocket::Open: falling back to listening");
+
+ err = OpenCommPortListen (fConfig);
+
+ PRINTF ("EmTransportSocket::Open: listening socket opened properly");
+ }
+
+ if (err == 0)
+ {
+ fCommEstablished = true;
+ fgOpenPorts [registrationKey] = this;
+ }
+ else
+ {
+ PRINTF ("EmTransportSocket::Open: error %ld on listening attempt, closing listen socket", err);
+
+ err = CloseCommPortListen ();
+ }
+ }
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::Close
+ *
+ * DESCRIPTION: Close the transport.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::Close (void)
+{
+ PRINTF ("EmTransportSocket::Close...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSocket::Close: TCP port not open...leaving...");
+ return kError_CommNotOpen;
+ }
+
+ fCommEstablished = false;
+
+ string registrationKey = "TCP:" + fConfig.fTargetHost + ":" + fConfig.fTargetPort;
+
+ fgOpenPorts.erase (registrationKey);
+
+ ErrCode err = CloseCommPort ();
+
+ if (err)
+ PRINTF ("EmTransportSocket::Close: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::Read
+ *
+ * DESCRIPTION: Read up to the given number of bytes, storing them in
+ * the given buffer.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::Read (long& len, void* data)
+{
+ PRINTF ("EmTransportSocket::Read...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportSocket::Read: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ GetIncomingData (data, len);
+
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportSocket::Read: reading %ld bytes.", len);
+ else
+ PRINTF ("EmTransportSocket::Read: reading %ld bytes", len);
+
+ return kError_NoError;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::Write
+ *
+ * DESCRIPTION: Write up the the given number of bytes, using the data
+ * in the given buffer.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::Write (long& len, const void* data)
+{
+ PRINTF ("EmTransportSocket::Write...");
+
+ ErrCode err;
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("...EmTransportSocket::Write: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ // Tracking errors here so that we can close the connection if some
+ // mechanism farther down the food chain (in CTCPSocket) finds out
+ // that the connection was dropped. This wasn't checked before, as
+ // errors were ignored in PutOutgoingData, explaining the many
+ // writes of 0 bytes (indicating a dropped connection) in log files.
+
+ err = PutOutgoingData (data, len);
+
+ if (err)
+ {
+ PRINTF ("...EmTransportSocket::Write: PutOutgoingData returned err %ld, closing connection", err);
+
+ this->Close ();
+
+ return kError_CommNotOpen;
+ }
+
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportSocket::Write: writing %ld bytes.", len);
+ else
+ PRINTF ("EmTransportSocket::Write: writing %ld bytes", len);
+
+ return kError_NoError;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::CanRead
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a read operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there are
+ * actually any bytes available to be read.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportSocket::CanRead (void)
+{
+ return fCommEstablished;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::CanWrite
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a write operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there is
+ * actually any room in the transport's internal buffer
+ * for the data being written.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportSocket::CanWrite (void)
+{
+ return fCommEstablished;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::BytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: minBytes - try to buffer at least this many bytes.
+ * Return when we have this many bytes buffered, or
+ * until some small timeout has occurred.
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransportSocket::BytesInBuffer (long /*minBytes*/)
+{
+ if (!fCommEstablished)
+ return 0;
+
+ return this->IncomingDataSize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::GetSpecificName
+ *
+ * DESCRIPTION: Returns the port name, or host address, depending on the
+ * transport in question.
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: string, appropriate to the transport in question.
+ *
+ ***********************************************************************/
+
+ string EmTransportSocket::GetSpecificName (void)
+ {
+ string returnString = fConfig.fTargetHost + ":" + fConfig.fTargetPort;
+ return returnString;
+ }
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: config - The configuration object containing information
+ * on a port in which we're interested. All or some
+ * of the information in this object is used when
+ * searching for a transport object already utilizing
+ * the port.
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransportSocket* EmTransportSocket::GetTransport (const ConfigSocket& config)
+{
+ string registrationKey = "TCP:" + config.fTargetHost + ":" + config.fTargetPort;
+ OpenPortList::iterator iter = fgOpenPorts.find (registrationKey);
+
+ if (iter == fgOpenPorts.end ())
+ return NULL;
+
+ return iter->second;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::GetDescriptorList
+ *
+ * DESCRIPTION: Return the list of TCP ports on this computer. Used
+ * to prepare a menu of TCP port choices.
+ *
+ * PARAMETERS: nameList - port names are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSocket::GetDescriptorList (EmTransportDescriptorList& descList)
+{
+ descList.clear ();
+
+ descList.push_back (EmTransportDescriptor (kTransportSocket));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::OpenCommPortConnect
+ *
+ * DESCRIPTION: Open the TCP port.
+ *
+ * PARAMETERS: config - data block describing which port to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ * NOTES: Implements a subset of OpenCommPort's functionality.
+ * In particular, it tries to connect, then returns.
+ * OpenCommPortListen implements the listening behavior.
+ * This change was made so that control over the behavior
+ * (whether connect first or listen first) could be
+ * in Open.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::OpenCommPortConnect (const EmTransportSocket::ConfigSocket& config)
+{
+ ErrCode err;
+
+ if (fDataConnectSocket)
+ return errNone;
+
+ fDataConnectSocket = new CTCPClientSocket (EmTransportSocket::EventCallBack,
+ config.fTargetHost, atoi (config.fTargetPort.c_str ()), this);
+
+ // Try establishing a connection to some peer already waiting on the
+ // target host, on the target port
+
+ err = fDataConnectSocket->Open ();
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::OpenCommPortListen
+ *
+ * DESCRIPTION: Open the TCP port.
+ *
+ * PARAMETERS: config - data block describing which port to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::OpenCommPortListen (const EmTransportSocket::ConfigSocket& config)
+{
+ ErrCode err;
+
+ if (fDataListenSocket)
+ return errNone;
+
+ fDataListenSocket = new CTCPClientSocket (EmTransportSocket::EventCallBack,
+ config.fTargetHost, atoi (config.fTargetPort.c_str ()), this);
+
+ // Fall into server mode and start waiting
+
+ err = fDataListenSocket->OpenInServerMode ();
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::EventCallBack
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+void EmTransportSocket::EventCallBack (CSocket* s, int event)
+{
+ switch (event)
+ {
+ case CSocket::kConnected:
+ break;
+
+ case CSocket::kDataReceived:
+ while (s->HasUnreadData(1))
+ {
+ long len = 1;
+ char buf;
+
+ s->Read(&buf, len, &len);
+
+ if (len > 0)
+ {
+ // Log the data.
+ if (LogSerialData ())
+ LogAppendData (&buf, len, "EmTransportSocket::CommRead: Received data:");
+ else
+ PRINTF ("EmTransportSocket::CommRead: Received %ld TCP bytes.", len);
+
+ // Add the data to the EmTransportSocket object's buffer.
+ ((CTCPClientSocket*)s)->GetOwner()->PutIncomingData (&buf, len);
+ }
+ }
+ break;
+
+ case CSocket::kDisconnected:
+ break;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::CloseCommPort
+ *
+ * DESCRIPTION: Close the comm port.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::CloseCommPort (void)
+{
+ // Must close each socket separately.
+
+ if (fDataListenSocket)
+ {
+ fDataListenSocket->Close ();
+ fDataListenSocket->Delete ();
+ fDataListenSocket = NULL;
+ }
+
+ if (fDataConnectSocket)
+ {
+ fDataConnectSocket->Close ();
+ fDataConnectSocket->Delete ();
+ fDataConnectSocket = NULL;
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::CloseCommPortConnect
+ *
+ * DESCRIPTION: Close the comm port.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::CloseCommPortConnect (void)
+{
+ if (fDataConnectSocket)
+ {
+ fDataConnectSocket->Close ();
+ fDataConnectSocket->Delete ();
+ fDataConnectSocket = NULL;
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::CloseCommPortListen
+ *
+ * DESCRIPTION: Close the comm port.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::CloseCommPortListen (void)
+{
+ if (fDataListenSocket)
+ {
+ fDataListenSocket->Close ();
+ fDataListenSocket->Delete ();
+ fDataListenSocket = NULL;
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::PutIncomingData
+ *
+ * DESCRIPTION: Thread-safe method for adding data to the queue that
+ * holds data read from the TCP port.
+ *
+ * PARAMETERS: data - pointer to the read data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSocket::PutIncomingData (const void* data, long& len)
+{
+ if (len == 0)
+ return;
+
+ omni_mutex_lock lock (fReadMutex);
+
+ char* begin = (char*) data;
+ char* end = begin + len;
+ while (begin < end)
+ fReadBuffer.push_back (*begin++);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::GetIncomingData
+ *
+ * DESCRIPTION: Thread-safe method for getting data from the queue
+ * holding data read from the TCP port.
+ *
+ * PARAMETERS: data - pointer to buffer to receive data.
+ * len - on input, number of bytes available in "data".
+ * On exit, number of bytes written to "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSocket::GetIncomingData (void* data, long& len)
+{
+ omni_mutex_lock lock (fReadMutex);
+
+ if (len > (long) fReadBuffer.size ())
+ len = (long) fReadBuffer.size ();
+
+ char* p = (char*) data;
+ deque<char>::iterator begin = fReadBuffer.begin ();
+ deque<char>::iterator end = begin + len;
+
+ copy (begin, end, p);
+ fReadBuffer.erase (begin, end);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::IncomingDataSize
+ *
+ * DESCRIPTION: Thread-safe method returning the number of bytes in the
+ * read queue.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Number of bytes in the read queue.
+ *
+ ***********************************************************************/
+
+
+long EmTransportSocket::IncomingDataSize (void)
+{
+ omni_mutex_lock lock (fReadMutex);
+
+ return fReadBuffer.size ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::PutOutgoingData
+ *
+ * DESCRIPTION: Thread-safe method for adding data to the queue that
+ * holds data to be written to the TCP port.
+ *
+ * PARAMETERS: data - pointer to the read data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ * NOTES: See the caveat in the constructor's comments about treating
+ * these "sockets" as real sockets. The actual control over
+ * sockets is down a level in CTCPSocket; thus, the listening
+ * socket at this level is, logically, where data should be
+ * written to. The connect socket is tried first, as the
+ * listening socket is closed on a successful connection.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSocket::PutOutgoingData (const void* data, long& len)
+{
+ ErrCode err = kError_CommNotOpen;
+
+ if (fDataListenSocket)
+ err = fDataListenSocket->Write (data, len, &len);
+ if (fDataConnectSocket)
+ err = fDataConnectSocket->Write (data, len, &len);
+
+ return err;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::ConfigSocket c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSocket::ConfigSocket::ConfigSocket (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::ConfigSocket d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportSocket::ConfigSocket::~ConfigSocket (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::ConfigSocket::NewTransport
+ *
+ * DESCRIPTION: Create a new transport object based on the configuration
+ * information in this object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The new transport object.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportSocket::ConfigSocket::NewTransport (void)
+{
+ return new EmTransportSocket (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::ConfigSocket::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportSocket::ConfigSocket::GetTransport (void)
+{
+ return EmTransportSocket::GetTransport (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSocket::ConfigSocket::operator==
+ *
+ * DESCRIPTION: Compare two Config objects to each other
+ *
+ * PARAMETERS: other - the object to compare "this" to.
+ *
+ * RETURNED: True if the objects are equivalent.
+ *
+ ***********************************************************************/
+
+bool EmTransportSocket::ConfigSocket::operator==(const ConfigSocket& other) const
+{
+ return
+ fTargetHost == other.fTargetHost &&
+ fTargetPort == other.fTargetPort;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::CTCPClientSocket
+ *
+ * DESCRIPTION:CTPClientSocket c'tor
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+enum { kSocketState_Unconnected, kSocketState_Listening, kSocketState_Connected };
+
+CTCPClientSocket::CTCPClientSocket (EventCallback fn, string targetHost, int targetPort, EmTransportSocket* transport) :
+ CTCPSocket (fn, targetPort)
+{
+ fTargetHost = targetHost;
+ fTransport = transport;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::~CTCPClientSocket
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+CTCPClientSocket::~CTCPClientSocket ()
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::Open
+ *
+ * DESCRIPTION: Open a socket and try to establish a connection to a
+ * TCP target.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: errNone if a connection has been established, or a
+ * nonzero error code otherwise
+ *
+ ***********************************************************************/
+
+ErrCode CTCPClientSocket::Open (void)
+{
+ PRINTF ("CTCPClientSocket(0x%08X)::Open...", this);
+
+ EmAssert (fSocketState == kSocketState_Unconnected);
+ EmAssert (fConnectedSocket == INVALID_SOCKET);
+
+ sockaddr addr;
+ int result;
+
+ fConnectedSocket = this->NewSocket ();
+ if (fConnectedSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...NewSocket failed for connecting socket; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ // Attempt to connect to that address (in case anyone is listening).
+ result = connect (fConnectedSocket, this->FillAddress (&addr), sizeof(addr));
+ if (result == 0)
+ {
+ PRINTF ("...connected!");
+
+ fSocketState = kSocketState_Connected;
+ return errNone;
+ }
+ // if the connection was unsuccessful, this should be logged as well
+ else
+ {
+ PRINTF ("...unable to connect: %d", result);
+ }
+
+ closesocket (fConnectedSocket);
+ fConnectedSocket = INVALID_SOCKET;
+
+ return this->ErrorOccurred ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::OpenInServerMode
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: errNone if a connection has been established, or a
+ * nonzero error code otherwise
+ *
+ ***********************************************************************/
+
+ErrCode CTCPClientSocket::OpenInServerMode (void)
+{
+ int result;
+ sockaddr addr;
+
+ fListeningSocket = this->NewSocket ();
+ if (fListeningSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...NewSocket failed for listening socket; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ result = bind (fListeningSocket, this->FillLocalAddress (&addr), sizeof(addr));
+ if (result != 0)
+ {
+ PRINTF ("...bind failed; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ // Start listening for a connection.
+
+ result = listen (fListeningSocket, 1);
+ if (result != 0)
+ {
+ PRINTF ("...listen failed; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ PRINTF ("...listening for connection");
+
+ fSocketState = kSocketState_Listening;
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::FillLocalAddress
+ *
+ * DESCRIPTION: Fill in a sockaddr data structure with values
+ * appropriate for connecting from the outside. This is an
+ * Internet address on the local machine.
+ *
+ * PARAMETERS: addr - the sockaddr to fill in.
+ *
+ * RETURNED: The same sockaddr passed in.
+ *
+ ***********************************************************************/
+
+sockaddr* CTCPClientSocket::FillLocalAddress (sockaddr* addr)
+{
+ sockaddr_in* addr_in = (sockaddr_in*) addr;
+
+#ifdef HAVE_SIN_LEN
+ addr_in->sin_len = sizeof (*addr_in);
+#endif
+ addr_in->sin_family = AF_INET;
+ addr_in->sin_port = htons (fPort);
+ addr_in->sin_addr.s_addr = htonl (INADDR_ANY);
+
+ return addr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::GetOwner
+ *
+ * DESCRIPTION:This creates a link between a CTCPClientSocket object and
+ * a EmTransportSocket object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Associated transport object, as passed to c'tor
+ *
+ ***********************************************************************/
+
+EmTransportSocket* CTCPClientSocket::GetOwner (void)
+{
+ return fTransport;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPClientSocket::FillAddress
+ *
+ * DESCRIPTION: Fill in a sockaddr data structure with values
+ * appropriate for connecting from the outside. This is an
+ * Internet address on the local machine.
+ *
+ * PARAMETERS: addr - the sockaddr to fill in.
+ *
+ * RETURNED: The same sockaddr passed in.
+ *
+ ***********************************************************************/
+
+sockaddr* CTCPClientSocket::FillAddress (sockaddr* addr)
+{
+ PRINTF ("CTCPSocket(0x%08X)::FillAddress...", this);
+
+ sockaddr_in* addr_in = (sockaddr_in*) addr;
+ const char* name = fTargetHost.c_str ();
+ unsigned long ip;
+
+ // Check for common "localhost" case in order to avoid a name lookup on the Mac
+
+ if (!_stricmp(name,"localhost"))
+ {
+ ip = htonl(INADDR_LOOPBACK);
+ }
+ else
+ {
+ // Try decoding a dotted ip address string
+ ip = inet_addr(name);
+
+ if (ip == INADDR_NONE)
+ {
+ hostent* entry;
+
+ // Perform a DNS lookup
+ entry = gethostbyname(name);
+
+ if (entry)
+ {
+ ip = *(unsigned long*) entry->h_addr;
+ }
+ }
+ }
+
+#ifdef HAVE_SIN_LEN
+ addr_in->sin_len = sizeof (*addr_in);
+#endif
+ addr_in->sin_family = AF_INET;
+ addr_in->sin_port = htons (fPort);
+ addr_in->sin_addr.s_addr = ip;
+
+ return addr;
+}
diff --git a/SrcShared/EmTransportSocket.h b/SrcShared/EmTransportSocket.h
new file mode 100644
index 0000000..10f0ed3
--- /dev/null
+++ b/SrcShared/EmTransportSocket.h
@@ -0,0 +1,125 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransportSocket_h
+#define EmTransportSocket_h
+
+#include "EmTransport.h"
+#include "SocketMessaging.h"
+
+#include <deque>
+#include <map>
+#include <vector>
+#include <string>
+
+#include "omnithread.h" // omni_mutex
+
+
+
+class EmTransportSocket;
+
+class CTCPClientSocket : public CTCPSocket
+{
+ public:
+ CTCPClientSocket (EventCallback fn, string targetHost, int targetPort, EmTransportSocket* transport);
+ virtual ~CTCPClientSocket (void);
+
+ sockaddr* FillAddress (sockaddr* addr);
+ virtual ErrCode Open (void);
+ ErrCode OpenInServerMode (void);
+ EmTransportSocket* GetOwner (void);
+ sockaddr* FillLocalAddress (sockaddr* addr);
+
+ private:
+ string fTargetHost;
+ EmTransportSocket* fTransport; // Owner
+};
+
+class EmTransportSocket : public EmTransport
+{
+ public:
+ typedef string PortName;
+ typedef vector<PortName> PortNameList;
+
+ struct ConfigSocket : public EmTransport::Config
+ {
+ ConfigSocket (void);
+ virtual ~ConfigSocket (void);
+
+ virtual EmTransport* NewTransport (void);
+ virtual EmTransport* GetTransport (void);
+
+ bool operator==(const ConfigSocket& other) const;
+
+ string fTargetHost;
+ string fTargetPort;
+ };
+
+ typedef map<PortName, EmTransportSocket*> OpenPortList;
+
+ public:
+ EmTransportSocket (void);
+ EmTransportSocket (const EmTransportDescriptor&);
+ EmTransportSocket (const ConfigSocket&);
+ virtual ~EmTransportSocket (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+
+ virtual ErrCode Read (long&, void*);
+ virtual ErrCode Write (long&, const void*);
+
+ virtual Bool CanRead (void);
+ virtual Bool CanWrite (void);
+ virtual long BytesInBuffer (long minBytes);
+ virtual string GetSpecificName (void);
+
+ static EmTransportSocket* GetTransport (const ConfigSocket&);
+ static void GetDescriptorList (EmTransportDescriptorList&);
+
+ // ErrCode OpenCommPort (const EmTransportSocket::ConfigSocket&);
+ ErrCode OpenCommPortListen (const EmTransportSocket::ConfigSocket&);
+ ErrCode OpenCommPortConnect (const EmTransportSocket::ConfigSocket&);
+ ErrCode CloseCommPort (void);
+ ErrCode CloseCommPortConnect (void);
+ ErrCode CloseCommPortListen (void);
+
+ // Manage data coming in the host socket.
+ void PutIncomingData (const void*, long&);
+ void GetIncomingData (void*, long&);
+ long IncomingDataSize (void);
+
+ // Manage data going out the host socket.
+ ErrCode PutOutgoingData (const void*, long&);
+ long OutgoingDataSize (void);
+
+ static void EventCallBack (CSocket* s, int event);
+
+ public:
+
+ omni_mutex fReadMutex;
+ deque<char> fReadBuffer;
+
+ // CTCPClientSocket* fDataSocket;
+ CTCPClientSocket* fDataConnectSocket;
+ CTCPClientSocket* fDataListenSocket;
+
+ private:
+
+ ConfigSocket fConfig;
+ Bool fCommEstablished;
+
+ static OpenPortList fgOpenPorts;
+};
+
+#endif /* EmTransportSocket_h */
diff --git a/SrcShared/EmTransportUSB.cpp b/SrcShared/EmTransportUSB.cpp
new file mode 100644
index 0000000..04e04e6
--- /dev/null
+++ b/SrcShared/EmTransportUSB.cpp
@@ -0,0 +1,571 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransportUSB.h"
+
+#include "EmErrCodes.h" // kError_CommOpen
+#include "Logging.h" // LogSerial
+
+
+//EmTransportUSB::OpenPortList EmTransportUSB::fgOpenPorts;
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::EmTransportUSB (void) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ this->HostConstruct ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: desc - descriptor information used when opening
+ * the USB port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::EmTransportUSB (const EmTransportDescriptor& /* desc */) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ ConfigUSB config;
+
+ this->HostConstruct ();
+ this->SetConfig (config);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: config - configuration information used when opening
+ * the USB port.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::EmTransportUSB (const ConfigUSB& config) :
+ fHost (NULL),
+ fConfig (),
+ fCommEstablished (false)
+{
+ this->HostConstruct ();
+ this->SetConfig (config);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::~EmTransportUSB (void)
+{
+ this->Close ();
+ this->HostDestruct ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::Open
+ *
+ * DESCRIPTION: Open the transport using the information provided
+ * either in the constructor or with SetConfig.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::Open (void)
+{
+ PRINTF ("EmTransportUSB::Open...");
+
+ // Exit if communications have already been established.
+
+ if (fCommEstablished)
+ {
+ PRINTF ("EmTransportUSB::Open: USB port already open...leaving...");
+ return kError_CommOpen;
+ }
+
+// EmAssert (fgOpenPorts.find (fConfig.fPort) == fgOpenPorts.end ());
+
+ ErrCode err = this->HostOpen ();
+
+ if (!err)
+ err = this->HostSetConfig (fConfig);
+
+ if (err)
+ {
+ this->HostClose ();
+ }
+ else
+ {
+ fCommEstablished = true;
+// fgOpenPorts[fConfig.fPort] = this;
+ }
+
+ if (err)
+ PRINTF ("EmTransportUSB::Open: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::Close
+ *
+ * DESCRIPTION: Close the transport.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::Close (void)
+{
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportUSB::Close: USB port not open...leaving...");
+ return kError_CommNotOpen;
+ }
+
+ fCommEstablished = false;
+// fgOpenPorts.erase (fConfig.fPort);
+
+ ErrCode err = this->HostClose ();
+
+ if (err)
+ PRINTF ("EmTransportUSB::Close: err = %ld", err);
+
+ PRINTF ("EmTransportUSB::Close: now closed...");
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::Read
+ *
+ * DESCRIPTION: Read up to the given number of bytes, storing them in
+ * the given buffer.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::Read (long& len, void* data)
+{
+ PRINTF ("EmTransportUSB::Read...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportUSB::Read: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostRead (len, data);
+
+ if (err)
+ PRINTF ("EmTransportUSB::Read: err = %ld", err);
+ else
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportUSB::Read: reading %ld bytes.", len);
+ else
+ PRINTF ("EmTransportUSB::Read: reading %ld bytes", len);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::Write
+ *
+ * DESCRIPTION: Write up the the given number of bytes, using the data
+ * in the given buffer.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::Write (long& len, const void* data)
+{
+ PRINTF ("EmTransportUSB::Write...");
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportUSB::Write: port not open, leaving");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostWrite (len, data);
+
+ if (err)
+ PRINTF ("EmTransportUSB::Write: err = %ld", err);
+ else
+ if (LogSerialData ())
+ LogAppendData (data, len, "EmTransportUSB::Write: writing %ld bytes.", len);
+ else
+ PRINTF ("EmTransportUSB::Write: writing %ld bytes", len);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::CanRead
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a read operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there are
+ * actually any bytes available to be read.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportUSB::CanRead (void)
+{
+ return this->HostCanRead ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::CanWrite
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a write operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there is
+ * actually any room in the transport's internal buffer
+ * for the data being written.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportUSB::CanWrite (void)
+{
+ return this->HostCanRead ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::BytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: minBytes - try to buffer at least this many bytes.
+ * Return when we have this many bytes buffered, or
+ * until some small timeout has occurred.
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransportUSB::BytesInBuffer (long minBytes)
+{
+ if (!fCommEstablished)
+ return 0;
+
+ return this->HostBytesInBuffer (minBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::GetSpecificName
+ *
+ * DESCRIPTION: Returns the port name, or host address, depending on the
+ * transport in question.
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: string, appropriate to the transport in question.
+ *
+ ***********************************************************************/
+
+ string EmTransportUSB::GetSpecificName (void)
+ {
+ return "USB";
+ }
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::SetConfig
+ *
+ * DESCRIPTION: Set the configuration to be used when opening the port,
+ * or to reconfigure a currently open port.
+ *
+ * PARAMETERS: config - the configuration to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::SetConfig (const ConfigUSB& config)
+{
+ PRINTF ("EmTransportUSB::SetConfig...");
+
+ if (config == fConfig)
+ {
+ PRINTF ("EmTransportUSB::SetConfig: Config unchanged, so not setting settings...");
+ return errNone;
+ }
+
+ fConfig = config;
+
+ // Exit if communications have not been established.
+
+ if (!fCommEstablished)
+ {
+ PRINTF ("EmTransportUSB::SetConfig: USB port closed, so not setting settings...");
+ return kError_CommNotOpen;
+ }
+
+ ErrCode err = this->HostSetConfig (fConfig);
+
+ if (err)
+ PRINTF ("EmTransportUSB::SetConfig: err = %ld", err);
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::GetConfig
+ *
+ * DESCRIPTION: Return the configuration specified in the constructor
+ * or in the last call to SetConfig.
+ *
+ * PARAMETERS: config - config object to receive the settings.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportUSB::GetConfig (ConfigUSB& config)
+{
+ config = fConfig;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: config - The configuration object containing information
+ * on a port in which we're interested. All or some
+ * of the information in this object is used when
+ * searching for a transport object already utilizing
+ * the port.
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransportUSB* EmTransportUSB::GetTransport (const ConfigUSB& /*config*/)
+{
+#if 0
+ OpenPortList::iterator iter = fgOpenPorts.find (config.fPort);
+
+ if (iter == fgOpenPorts.end ())
+ return NULL;
+
+ return iter->second;
+#endif
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::GetDescriptorList
+ *
+ * DESCRIPTION: Return the list of USB ports on this computer. Used
+ * to prepare a menu of USB port choices.
+ *
+ * PARAMETERS: nameList - port names are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportUSB::GetDescriptorList (EmTransportDescriptorList& descList)
+{
+ descList.clear ();
+
+ if (EmTransportUSB::HostHasUSB ())
+ {
+ descList.push_back (EmTransportDescriptor (kTransportUSB));
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::ConfigUSB c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::ConfigUSB::ConfigUSB ()
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::ConfigUSB d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmTransportUSB::ConfigUSB::~ConfigUSB (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::ConfigUSB::NewTransport
+ *
+ * DESCRIPTION: Create a new transport object based on the configuration
+ * information in this object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The new transport object.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportUSB::ConfigUSB::NewTransport (void)
+{
+ return new EmTransportUSB (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::ConfigUSB::GetTransport
+ *
+ * DESCRIPTION: Return any transport object currently using the port
+ * specified in the given configuration.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Any found transport object. May be NULL.
+ *
+ ***********************************************************************/
+
+EmTransport* EmTransportUSB::ConfigUSB::GetTransport (void)
+{
+ return EmTransportUSB::GetTransport (*this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::ConfigUSB::operator==
+ *
+ * DESCRIPTION: Compare two Config objects to each other
+ *
+ * PARAMETERS: other - the object to compare "this" to.
+ *
+ * RETURNED: True if the objects are equivalent.
+ *
+ ***********************************************************************/
+
+bool EmTransportUSB::ConfigUSB::operator==(const ConfigUSB& /*other*/) const
+{
+ return true;
+}
diff --git a/SrcShared/EmTransportUSB.h b/SrcShared/EmTransportUSB.h
new file mode 100644
index 0000000..925d46a
--- /dev/null
+++ b/SrcShared/EmTransportUSB.h
@@ -0,0 +1,95 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransportUSB_h
+#define EmTransportUSB_h
+
+#include "EmTransport.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+class EmHostTransportUSB;
+
+class EmTransportUSB : public EmTransport
+{
+ public:
+ typedef string PortName;
+ typedef vector<PortName> PortNameList;
+
+ // Note: this used to be named "Config", but that runs
+ // afoul of a bug in VC++ (see KB Q143082).
+ struct ConfigUSB : public EmTransport::Config
+ {
+ ConfigUSB ();
+ virtual ~ConfigUSB (void);
+
+ virtual EmTransport* NewTransport (void);
+ virtual EmTransport* GetTransport (void);
+
+ bool operator==(const ConfigUSB& other) const;
+ };
+
+// typedef map<PortName, EmTransportUSB*> OpenPortList;
+
+ public:
+ EmTransportUSB (void);
+ EmTransportUSB (const EmTransportDescriptor&);
+ EmTransportUSB (const ConfigUSB&);
+ virtual ~EmTransportUSB (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+
+ virtual ErrCode Read (long&, void*);
+ virtual ErrCode Write (long&, const void*);
+
+ virtual Bool CanRead (void);
+ virtual Bool CanWrite (void);
+ virtual long BytesInBuffer (long minBytes);
+ virtual string GetSpecificName (void);
+
+ ErrCode SetConfig (const ConfigUSB&);
+ void GetConfig (ConfigUSB&);
+
+ static EmTransportUSB* GetTransport (const ConfigUSB&);
+
+ static void GetDescriptorList (EmTransportDescriptorList&);
+
+ private:
+ static Bool HostHasUSB (void);
+
+ void HostConstruct (void);
+ void HostDestruct (void);
+
+ ErrCode HostOpen (void);
+ ErrCode HostClose (void);
+
+ ErrCode HostRead (long&, void*);
+ ErrCode HostWrite (long&, const void*);
+
+ Bool HostCanRead (void);
+ Bool HostCanWrite (void);
+ long HostBytesInBuffer (long minBytes);
+
+ ErrCode HostSetConfig (const ConfigUSB&);
+
+ EmHostTransportUSB* fHost;
+ ConfigUSB fConfig;
+ Bool fCommEstablished;
+
+// static OpenPortList fgOpenPorts;
+};
+
+#endif /* EmTransportUSB_h */
diff --git a/SrcShared/EmTypes.h b/SrcShared/EmTypes.h
new file mode 100644
index 0000000..3cb177c
--- /dev/null
+++ b/SrcShared/EmTypes.h
@@ -0,0 +1,100 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTypes_h
+#define EmTypes_h
+
+// =====================================
+// ========== SIMPLE TYPEDEFS ==========
+// =====================================
+
+// Standard integral types
+
+ typedef signed char int8;
+ typedef unsigned char uint8;
+
+ typedef signed short int16;
+ typedef unsigned short uint16;
+
+ typedef signed long int32;
+ typedef unsigned long uint32;
+
+#ifdef _MSC_VER
+ typedef signed __int64 int64;
+ typedef unsigned __int64 uint64;
+#else
+ typedef signed long long int64;
+ typedef unsigned long long uint64;
+#endif
+
+typedef uint32 emuptr;
+
+typedef int Bool;
+
+typedef int32 ErrCode;
+typedef int32 StrCode;
+
+typedef uint8 ScaleType;
+typedef int32 RAMSizeType;
+typedef int32 EmCoord;
+
+#define EmMemNULL ((emuptr) 0)
+#define EmMemEOM ((emuptr) 0xFFFFFFFF)
+
+
+// Enumerated types
+
+enum CloseActionType
+{
+ kSaveAlways,
+ kSaveAsk,
+ kSaveNever
+};
+
+
+enum LoggingType
+{
+ kNormalLogging = 0x01,
+ kGremlinLogging = 0x02,
+ kAllLogging = kNormalLogging | kGremlinLogging
+};
+
+
+enum EmResetType
+{
+ kResetSys, // Triggered by calling SysReset
+ kResetSoft, // Same as sticking pin in Reset hole
+ kResetHard, // Same as Soft Reset with Power key down
+ kResetDebug, // Same as Soft Reset with Page Down key down
+
+ kResetTypeMask = 0x07,
+ kResetExtMask = 0x08,
+ kResetNoExt = 0x08,
+
+ kResetSysNoExt = kResetNoExt | kResetSys, // Same as kResetSys with Page Up key down.
+ kResetSoftNoExt = kResetNoExt | kResetSoft, // Same as kResetSoft with Page Up key down.
+ kResetHardNoExt = kResetNoExt | kResetHard, // Same as kResetHard with Page Up key down.
+ kResetDebugNoExt = kResetNoExt | kResetDebug // Same as kResetDebug with Page Up key down.
+};
+
+
+enum EmErrorHandlingOption
+{
+ kShow,
+ kContinue,
+ kQuit,
+ kSwitch
+};
+
+
+#endif // EmTypes_h
diff --git a/SrcShared/EmWindow.cpp b/SrcShared/EmWindow.cpp
new file mode 100644
index 0000000..7ab366e
--- /dev/null
+++ b/SrcShared/EmWindow.cpp
@@ -0,0 +1,1388 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmWindow.h"
+
+#include "EmHAL.h" // EmHAL::GetVibrateOn
+#include "EmJPEG.h" // JPEGToPixMap
+#include "EmPixMap.h" // EmPixMap
+#include "EmQuantizer.h" // EmQuantizer
+#include "EmRegion.h" // EmRegion
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmSession.h" // PostPenEvent, PostButtonEvent, etc.
+#include "EmStream.h" // delete imageStream
+#include "Platform.h" // Platform::PinToScreen
+
+EmWindow* gWindow;
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::EmWindow
+// ---------------------------------------------------------------------------
+// Constructor. Perform simple data member initialization. The heavy stuff
+// occurs in WindowCreate.
+
+EmWindow::EmWindow (void) :
+ fSkinBase (),
+ fSkinCurrent (),
+ fSkinColors (),
+ fSkinRegion (),
+ fPrevLCDColors (),
+ fCurrentButton (kElement_None),
+ fNeedWindowReset (false),
+ fNeedWindowInvalidate (false),
+ fOldLCDOn (false),
+ fOldBacklightOn (false),
+ fOldLEDState (0),
+ fWiggled (false),
+ fActive (true),
+ fDebugMode (false),
+ fGremlinMode (false)
+{
+ EmAssert (gWindow == NULL);
+ gWindow = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::~EmWindow
+// ---------------------------------------------------------------------------
+// Dispose of the window and all its data. Unregister for notification, save
+// the window location, and destroy the host window object.
+
+EmWindow::~EmWindow (void)
+{
+ EmAssert (gWindow == this);
+ gWindow = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PreDestroy
+// ---------------------------------------------------------------------------
+// Carry out actions to be performed just before the window is closed. These
+// actions would normally be performed in EmWindow's destructor, except that
+// the host window is already deleted by then. Therefore, each sub-class of
+// EmWindow needs to call this in *its* destructor before destroying the host
+// window.
+
+void EmWindow::PreDestroy (void)
+{
+ gPrefs->RemoveNotification (EmWindow::PrefsChangedCB);
+
+ // Save the window location.
+
+ EmRect rect (this->HostWindowBoundsGet ());
+
+ if (!rect.IsEmpty ())
+ {
+ Preference <EmPoint> pref (kPrefKeyWindowLocation);
+ pref = rect.TopLeft ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::WindowInit
+// ---------------------------------------------------------------------------
+// Create the LCD window, along with any host data and host window objects.
+// Set the window's skin, register for any notification regarding the window's
+// appearance, reposition the window to where it should live, ensure that
+// the window is still on the screen, and then finally make the window
+// visible.
+//
+// This function should be called immediately after the EmWindow object is
+// created.
+
+void EmWindow::WindowInit (void)
+{
+ // Establish the window's skin.
+
+ this->WindowReset ();
+
+ // Install notification callbacks for when the skin changes.
+
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeySkins, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyScale, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyDimWhenInactive, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyShowDebugMode, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyShowGremlinMode, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyBackgroundColor, this);
+ gPrefs->AddNotification (&EmWindow::PrefsChangedCB, kPrefKeyStayOnTop, this);
+
+ // Restore the window location.
+
+ Preference<EmPoint> pref (kPrefKeyWindowLocation);
+
+ if (pref.Loaded ())
+ {
+ this->HostWindowMoveTo (*pref);
+ }
+
+ // No previously saved position, so center it.
+
+ else
+ {
+ this->HostWindowCenter ();
+ }
+
+ // Ensure the window is on the screen.
+
+ EmRect rect (this->HostWindowBoundsGet ());
+
+ if (Platform::PinToScreen (rect))
+ {
+ this->HostWindowMoveTo (rect.TopLeft ());
+ }
+
+ // Show the window.
+
+ this->HostWindowShow ();
+
+ // Make the window stay on top if it is set as such.
+
+ this->HostWindowStayOnTop ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::WindowReset
+// ---------------------------------------------------------------------------
+
+void EmWindow::WindowReset (void)
+{
+ // Can only set the skin if we have a session running, so that we can
+ // query it for its configuration.
+
+ if (!gSession)
+ return;
+
+ // Configure our Skin engine.
+
+ ::SkinSetSkin ();
+
+ // Get the specified skin, or the default skin if the specified
+ // one cannot be found.
+
+ if (!this->GetSkin (fSkinBase))
+ {
+ this->GetDefaultSkin (fSkinBase);
+ }
+
+ // Create a one-bpp mask of the skin.
+
+ EmPixMap mask;
+ fSkinBase.CreateMask (mask);
+
+ // Convert it to a region.
+
+ fSkinRegion = mask.CreateRegion ();
+
+ // Clear our color caches. They'll get filled again on demand.
+
+ for (int ii = 0; ii < (long) countof (fSkinColors); ++ii)
+ {
+ fSkinColors[ii].clear ();
+ }
+
+ // Clear the image of the skin, altered for its mode. This image
+ // will get regenerated on demand.
+
+ fSkinCurrent = EmPixMap ();
+
+ // Clear out the previously saved LCD colors. This will force the
+ // any host palettes to be regenerated, because they'll think the
+ // Palm OS LCD palette has changed.
+
+ fPrevLCDColors.clear ();
+
+ // Now convert this all to platform-specific data structures.
+ // This will also resize the window.
+
+ this->HostWindowReset ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandlePenEvent
+// ---------------------------------------------------------------------------
+
+void EmWindow::HandlePenEvent (const EmPoint& where, Bool down)
+{
+ // Find out what part of the case we clicked on.
+
+ SkinElementType what;
+
+ // If the mouse button is down and we aren't currently tracking
+ // anything, then find out what the user clicked on.
+
+ if (down && (fCurrentButton == kElement_None))
+ {
+ what = ::SkinTestPoint (where);
+
+ if ((what != kElement_Frame) && (what != kElement_None))
+ {
+ this->HostMouseCapture ();
+ }
+ }
+
+ // If the pen is up, or if we were already in the progress of tracking
+ // something, then stick with it.
+
+ else
+ {
+ what = fCurrentButton;
+ }
+
+ // If we clicked in the touchscreen area (which includes the LCD area
+ // and the silkscreen area), start the mechanism for tracking the mouse.
+
+ if (what == kElement_Touchscreen)
+ {
+ EmPoint whereLCD = ::SkinWindowToTouchscreen (where);
+ EmPenEvent event (whereLCD, down);
+
+ EmAssert (gSession);
+ gSession->PostPenEvent (event);
+ }
+
+ // If we clicked in the frame, start dragging the window.
+
+ else if (what == kElement_Frame)
+ {
+ if (down)
+ {
+ this->HostWindowDrag ();
+
+ // We normally record the mouse button going up in
+ // EventMouseUp. However, that method is not called
+ // after ClickInDrag, so say the mouse button is up here.
+
+ down = false;
+ }
+ }
+
+ // Otherwise, if we clicked on a button, start tracking it.
+
+ else if (what != kElement_None)
+ {
+ EmButtonEvent event (what, down);
+
+ EmAssert (gSession);
+ gSession->PostButtonEvent (event);
+ }
+
+ // Set or clear what we're tracking.
+
+ if (down)
+ fCurrentButton = what;
+ else
+ fCurrentButton = kElement_None;
+
+ if (fCurrentButton == kElement_None)
+ {
+ this->HostMouseRelease ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleUpdate
+// ---------------------------------------------------------------------------
+// Called to handle update events.
+
+void EmWindow::HandleUpdate (void)
+{
+ this->HostUpdateBegin ();
+
+ this->PaintScreen (true, true);
+
+ this->HostUpdateEnd ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandlePalette
+// ---------------------------------------------------------------------------
+// Called when we need to tell the OS what our preferred palette is. Usually
+// called when window orders change.
+
+void EmWindow::HandlePalette (void)
+{
+ this->HostPalette ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleDisplayChange
+// ---------------------------------------------------------------------------
+// Called when the display depth changes.
+
+void EmWindow::HandleDisplayChange (void)
+{
+ this->HostDisplayChange ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleActivate
+// ---------------------------------------------------------------------------
+// Called when the display depth changes.
+
+void EmWindow::HandleActivate (Bool active)
+{
+ if (fActive != active)
+ {
+ fActive = active;
+ this->HostWindowReset ();
+
+ fSkinCurrent = EmPixMap ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleDebugMode
+// ---------------------------------------------------------------------------
+// Called when the display depth changes.
+
+void EmWindow::HandleDebugMode (Bool debugMode)
+{
+ if (fDebugMode != debugMode)
+ {
+ fDebugMode = debugMode;
+ this->HostWindowReset ();
+
+ fSkinCurrent = EmPixMap ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleGremlinMode
+// ---------------------------------------------------------------------------
+// Called when the display depth changes.
+
+void EmWindow::HandleGremlinMode (Bool gremlinMode)
+{
+ if (fGremlinMode != gremlinMode)
+ {
+ fGremlinMode = gremlinMode;
+ this->HostWindowReset ();
+
+ fSkinCurrent = EmPixMap ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HandleIdle
+// ---------------------------------------------------------------------------
+// Called several times a second to perform idle time events such as
+// refreshing the LCD area and vibrating the window.
+
+void EmWindow::HandleIdle (void)
+{
+ // Get the current mouse position.
+
+ EmPoint where = this->HostGetCurrentMouse ();
+
+ // Track the pen if it's down.
+
+ if (fCurrentButton == kElement_Touchscreen)
+ {
+ this->HandlePenEvent (where, true);
+ }
+
+ // Refresh the LCD area.
+
+ this->HostDrawingBegin ();
+
+ if (fNeedWindowReset)
+ {
+ this->WindowReset ();
+ }
+ else if (fNeedWindowInvalidate)
+ {
+ this->PaintScreen (false, true);
+ }
+ else
+ {
+ this->PaintScreen (false, false);
+ }
+
+ fNeedWindowReset = false;
+ fNeedWindowInvalidate = false;
+
+ this->HostDrawingEnd ();
+
+
+ // Do the Wiggle Walk.
+
+ {
+ const int kWiggleOffset = 2;
+
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ if (stopper.Stopped ())
+ {
+ if (EmHAL::GetVibrateOn ())
+ {
+ if (!fWiggled)
+ {
+ fWiggled = true;
+ this->HostWindowMoveBy (EmPoint (kWiggleOffset, 0));
+ }
+ else
+ {
+ fWiggled = false;
+ this->HostWindowMoveBy (EmPoint (-kWiggleOffset, 0));
+ }
+ }
+
+ // If the vibrator just went off, then put the window
+ // back to where it was.
+
+ else if (fWiggled)
+ {
+ fWiggled = false;
+ this->HostWindowMoveBy (EmPoint (-kWiggleOffset, 0));
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetLCDContents
+// ---------------------------------------------------------------------------
+// Return the full contents of the LCD area. Used for screenshots.
+
+void EmWindow::GetLCDContents (EmScreenUpdateInfo& info)
+{
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ if (stopper.Stopped ())
+ {
+ EmScreen::InvalidateAll ();
+ EmScreen::GetBits (info);
+ EmScreen::InvalidateAll ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintScreen
+// ---------------------------------------------------------------------------
+// Paint the entire window. Could be called in response to an update event
+// or as part of our regular idle time handling.
+
+void EmWindow::PaintScreen (Bool drawCase, Bool wholeLCD)
+{
+ EmScreenUpdateInfo info;
+ Bool bufferDirty;
+ Bool drawFrame = false;
+ Bool drawLED = false;
+ Bool drawLCD = false;
+ Bool lcdOn;
+ Bool backlightOn;
+ uint16 ledState;
+
+ {
+ // Pause the CPU so that we can get the current hardware state.
+
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ if (!stopper.Stopped ())
+ return;
+
+ // Determine if we have to force the redrawing of the background.
+ // We have to do that if the LCD or LEDs have turned off.
+
+ lcdOn = EmHAL::GetLCDScreenOn ();
+ backlightOn = EmHAL::GetLCDBacklightOn ();
+ ledState = EmHAL::GetLEDState ();
+
+ if (!lcdOn && fOldLCDOn)
+ {
+ drawCase = true;
+ }
+
+ if (!ledState && fOldLEDState)
+ {
+ drawCase = true;
+ }
+
+ // Determine if we have to draw the LCD or LED. We'd have to do that
+ // if their state has changed or if we had to draw the background.
+
+ if (drawCase || (lcdOn != fOldLCDOn) || (backlightOn != fOldBacklightOn))
+ {
+ drawLCD = lcdOn;
+ }
+
+ if (drawCase || (lcdOn != fOldLCDOn))
+ {
+ drawFrame = lcdOn && EmHAL::GetLCDHasFrame ();
+ }
+
+ if (drawCase || (ledState != fOldLEDState))
+ {
+ drawLED = ledState != 0;
+ }
+
+ fOldLCDOn = lcdOn;
+ fOldBacklightOn = backlightOn;
+ fOldLEDState = ledState;
+
+ // If we're going to be drawing the whole LCD, then invalidate
+ // the entire screen.
+
+ if (wholeLCD || drawLCD)
+ {
+ EmScreen::InvalidateAll ();
+ }
+
+ // Get the current LCD state.
+
+ bufferDirty = EmScreen::GetBits (info);
+
+ // If the buffer was dirty, that's another reason to draw the LCD.
+
+ if (bufferDirty)
+ {
+ drawLCD = lcdOn;
+ }
+
+ // If there is no width or height to the buffer, then that's a
+ // great reason to NOT draw the LCD.
+
+ EmPoint size = info.fImage.GetSize ();
+ if (size.fX == 0 || size.fY == 0)
+ {
+ drawLCD = false;
+ }
+ }
+
+ // Set up the graphics palette.
+
+ Bool drawAnything = drawCase || drawFrame || drawLED || drawLCD;
+
+ if (drawAnything)
+ {
+ this->HostPaletteSet (info);
+ }
+
+
+ // Draw the case.
+
+ if (drawCase)
+ {
+ this->PaintCase (info);
+ }
+
+ // Draw any LCD frame.
+
+ if (drawFrame)
+ {
+ this->PaintLCDFrame (info);
+ }
+
+ // Draw any LEDs.
+
+ if (drawLED)
+ {
+ this->PaintLED (ledState);
+ }
+
+ // Draw the LCD area.
+
+ if (drawLCD)
+ {
+ this->PaintLCD (info);
+ }
+
+#if 0
+ // Draw frames around the buttons. This is handy when determining their
+ // locations initially.
+
+ if (drawCase)
+ {
+ this->PaintButtonFrames ();
+ }
+#endif
+
+ // Restore the palette that was changed in HostSetPalette.
+
+ if (drawAnything)
+ {
+ this->HostPaletteRestore ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintCase
+// ---------------------------------------------------------------------------
+// Draw the skin.
+
+void EmWindow::PaintCase (const EmScreenUpdateInfo& info)
+{
+ this->HostPaintCase (info);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintLCDFrame
+// ---------------------------------------------------------------------------
+// Draw any frame around the LCD area required in order to faithfully
+// emulate the appearance of the real LCD.
+
+void EmWindow::PaintLCDFrame (const EmScreenUpdateInfo&)
+{
+ RGBType backlightColor (0xff, 0xff, 0xff);
+ EmRect lcdRect (this->GetLCDBounds ());
+ EmPoint penSize (2, 2);
+
+ penSize = ::SkinScaleUp (penSize);
+
+ lcdRect.Inset (-penSize.fX, -penSize.fY);
+
+ this->HostRectFrame (lcdRect, penSize, backlightColor);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintLCD
+// ---------------------------------------------------------------------------
+// Draw the LCD portion of the window.
+
+void EmWindow::PaintLCD (const EmScreenUpdateInfo& info)
+{
+ // Get the bounds of the LCD area.
+
+ EmRect lcdRect = this->GetLCDBounds ();
+
+ // Limit the vertical range to the lines that have changed.
+
+ EmRect destRect = ::SkinScaleDown (lcdRect);
+
+ destRect.fBottom = destRect.fTop + info.fLastLine;
+ destRect.fTop = destRect.fTop + info.fFirstLine;
+
+ destRect = ::SkinScaleUp (destRect);
+
+ // Get the bounds of the area we'll be blitting from.
+
+ EmRect srcRect (destRect);
+ srcRect -= lcdRect.TopLeft ();
+
+ // Determine if the image needs to be scaled.
+
+ EmPoint before (1, 1);
+ EmPoint after = ::SkinScaleUp (before);
+
+ // Setup is done. Let the host-specific routines handle the rest.
+
+ this->HostPaintLCD (info, srcRect, destRect, before.fX != after.fX);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintLED
+// ---------------------------------------------------------------------------
+
+void EmWindow::PaintLED (uint16 ledState)
+{
+ // Get the color for the LED.
+
+ RGBType ledColor;
+
+ if ((ledState & (kLEDRed | kLEDGreen)) == (kLEDRed | kLEDGreen))
+ {
+ ledColor = RGBType (255, 128, 0); // Orange
+ }
+ else if ((ledState & kLEDRed) == kLEDRed)
+ {
+ ledColor = RGBType (255, 0, 0); // Red
+ }
+ else /* green */
+ {
+ ledColor = RGBType (0, 255, 0); // Green
+ }
+
+ EmRect bounds (this->GetLEDBounds ());
+
+ this->HostOvalPaint (bounds, ledColor);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PaintButtonFrames
+// ---------------------------------------------------------------------------
+// Draw frames around the buttons. This is handy when determining their
+// locations initially.
+
+void EmWindow::PaintButtonFrames (void)
+{
+ EmPoint penSize (1, 1);
+ RGBType color (0, 0, 0);
+
+ int index = 0;
+ SkinElementType type;
+ EmRect bounds;
+
+ while (::SkinGetElementInfo (index, type, bounds))
+ {
+ this->HostRectFrame (bounds, penSize, color);
+
+ ++index;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PrefsChangedCB
+// ---------------------------------------------------------------------------
+// Respond to a preference change. This version of the function retrieves
+// the EmWindow object pointer and calls a non-static member function of the
+// object.
+
+void EmWindow::PrefsChangedCB (PrefKeyType key, void* data)
+{
+ EmAssert (data);
+
+ EmWindow* lcd = static_cast<EmWindow*>(data);
+ lcd->PrefsChanged (key);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PrefsChanged
+// ---------------------------------------------------------------------------
+// Respond to a preference change. If the sking or display size has changed,
+// we need to rebuild our skin image. If the background color preference
+// has changed, then just flag that the LCD area needs to be redrawn.
+
+void EmWindow::PrefsChanged (PrefKeyType key)
+{
+ if (::PrefKeysEqual (key, kPrefKeyScale) ||
+ ::PrefKeysEqual (key, kPrefKeySkins) ||
+ ::PrefKeysEqual (key, kPrefKeyShowDebugMode) ||
+ ::PrefKeysEqual (key, kPrefKeyShowGremlinMode) ||
+ ::PrefKeysEqual (key, kPrefKeyBackgroundColor))
+ {
+ fNeedWindowReset = true;
+ }
+ else if (::PrefKeysEqual (key, kPrefKeyBackgroundColor))
+ {
+ fNeedWindowInvalidate = true;
+ }
+ else if (::PrefKeysEqual (key, kPrefKeyStayOnTop))
+ {
+ this->HostWindowStayOnTop ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetLCDBounds
+// ---------------------------------------------------------------------------
+// Get the bounds for the LCD.
+
+EmRect EmWindow::GetLCDBounds (void)
+{
+ int ii = 0;
+ SkinElementType type = kElement_None;
+ EmRect bounds (10, 10, 170, 170);
+
+ while (::SkinGetElementInfo (ii, type, bounds))
+ {
+ if (type == kElement_LCD)
+ {
+ break;
+ }
+
+ ++ii;
+ }
+
+ return bounds;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetLEDBounds
+// ---------------------------------------------------------------------------
+// Get the bounds for the LED. Put it in the power button.
+
+EmRect EmWindow::GetLEDBounds (void)
+{
+ int ii = 0;
+ SkinElementType type = kElement_None;
+ Bool found = false;
+ EmRect bounds (10, 10, 20, 20);
+
+ while (::SkinGetElementInfo (ii++, type, bounds))
+ {
+ if (type == kElement_LED)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ ii = 0;
+ while (::SkinGetElementInfo (ii++, type, bounds))
+ {
+ if (type == kElement_PowerButton)
+ {
+ // Create a square centered in the power button.
+
+ if (bounds.Width () > bounds.Height ())
+ {
+ bounds.fLeft = bounds.fLeft + (bounds.Width () - bounds.Height ()) / 2;
+ bounds.fRight = bounds.fLeft + bounds.Height ();
+ }
+ else
+ {
+ bounds.fTop = bounds.fTop + (bounds.Height () - bounds.Width ()) / 2;
+ bounds.fBottom = bounds.fTop + bounds.Width ();
+ }
+
+ // Inset it a little -- looks better this way.
+
+ bounds.Inset (2, 2);
+
+ break;
+ }
+ }
+ }
+
+ return bounds;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetSkin
+// ---------------------------------------------------------------------------
+// Get the currently selected skin as a PixMap.
+
+Bool EmWindow::GetSkin (EmPixMap& pixMap)
+{
+ EmStream* imageStream = ::SkinGetSkinStream ();
+
+ if (!imageStream)
+ return false;
+
+ // Turn the JPEG image into BMP format.
+
+ ::JPEGToPixMap (*imageStream, pixMap);
+
+ // Free up the resource info.
+
+ delete imageStream;
+ imageStream = NULL;
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetDefaultSkin
+// ---------------------------------------------------------------------------
+// Get the default, built-in skin as a PixMap.
+
+void EmWindow::GetDefaultSkin (EmPixMap& pixMap)
+{
+ Preference<ScaleType> scalePref (kPrefKeyScale);
+
+ EmAssert ((*scalePref == 1) || (*scalePref == 2));
+
+ this->HostGetDefaultSkin (pixMap, *scalePref);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::PrevLCDColorsChanged
+// ---------------------------------------------------------------------------
+
+Bool EmWindow::PrevLCDColorsChanged (const RGBList& newLCDColors)
+{
+ // If the incoming image does not have a color table, then it's a
+ // direct-pixel image. It can have any set of colors in it, so
+ // we'll have to create an 8-bit palette for it no matter what.
+ //
+ // If the incoming image's color table has a different size than
+ // the previously saved color table, then we'll need to regenerate
+ // our cached palette.
+
+ if (newLCDColors.size () == 0 ||
+ newLCDColors.size () != fPrevLCDColors.size ())
+ {
+ return true;
+ }
+
+ // The incoming color table size is the same as the previously saved
+ // color table size, and neither of them are zero. Check the contents
+ // of the two tables to see if they've changed.
+
+ for (size_t ii = 0; ii < newLCDColors.size (); ++ii)
+ {
+ if (newLCDColors[ii] != fPrevLCDColors[ii])
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::SaveLCDColors
+// ---------------------------------------------------------------------------
+
+void EmWindow::SaveLCDColors (const RGBList& newLCDColors)
+{
+ fPrevLCDColors = newLCDColors;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetSystemColors
+// ---------------------------------------------------------------------------
+
+void EmWindow::GetSystemColors (const EmScreenUpdateInfo& info, RGBList& colors)
+{
+ // If this is a 1, 2, or 4 bit LCD, then we can use the whole
+ // palette from it along with our beefy skin color table.
+
+ if (info.fImage.GetDepth () <= 4)
+ {
+ colors = info.fImage.GetColorTable ();
+ colors.insert (colors.end (),
+ this->GetCurrentSkinColors (false).begin (),
+ this->GetCurrentSkinColors (false).end ());
+ }
+
+ // If this is an 8-bit image, then we have an interesting problem. We
+ // want to generate a palette that we can cache until the Palm OS
+ // palette changes. The palette we generate shouldn't be based on the
+ // current image, as that can change and use different colors without
+ // the Palm OS palette changing. So if we were to take that route,
+ // the palette we generated would be based on the handful of colors on
+ // the screen and not what's in the palette. It would be nice to use
+ // the Palm OS palette itself, but there are 256 colors in there, and
+ // we need to cut that down a little so that we can share time with
+ // the skin. Therefore, we run the Palm OS palette itself through the
+ // color quantizer itself to generate a nice subset of the palette.
+ // Since we have to merge 84 or so colors together, and since all
+ // colors in the Palm OS palette are weighted evenly, we don't want
+ // those 84 merged colors to appear at one end of the spectrum or the
+ // other. Therefore, we'll randomize the Palm OS palette before
+ // offering its colors to the quantizer.
+
+ else if (info.fImage.GetDepth () == 8)
+ {
+ srand (1); // Randomize it consistantly... :-)
+
+ colors = info.fImage.GetColorTable ();
+
+ for (size_t ii = 0; ii < colors.size (); ++ii)
+ {
+ size_t jj = rand () % colors.size ();
+
+ swap (colors[ii], colors[jj]);
+ }
+
+ EmQuantizer q (172, 6);
+ q.ProcessColorTable (colors);
+ q.GetColorTable (colors);
+
+ colors.insert (colors.end (),
+ this->GetCurrentSkinColors (true).begin (),
+ this->GetCurrentSkinColors (true).end ());
+ }
+
+ // Otherwise, if this is a 16 or 24 bit LCD, then we have to
+ // get the best 172 colors and combine that with our 64-entry
+ // skin color table.
+
+ else
+ {
+ EmQuantizer q (172, 6);
+ q.ProcessImage (info.fImage);
+ q.GetColorTable (colors);
+
+ colors.insert (colors.end (),
+ this->GetCurrentSkinColors (true).begin (),
+ this->GetCurrentSkinColors (true).end ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::QuantizeSkinColors
+// ---------------------------------------------------------------------------
+
+void EmWindow::QuantizeSkinColors (const EmPixMap& skin, RGBList& colors, Bool polite)
+{
+ if (polite)
+ {
+ EmQuantizer q (64, 6); // Leaves 256 - 64 - 20 = 172 for LCD
+ q.ProcessImage (skin);
+ q.GetColorTable (colors);
+ }
+ else
+ {
+ EmQuantizer q (220, 6); // Leaves 256 - 220 - 20 = 16 for LCD
+ q.ProcessImage (skin);
+ q.GetColorTable (colors);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetCurrentSkin
+// ---------------------------------------------------------------------------
+
+const EmPixMap& EmWindow::GetCurrentSkin (void)
+{
+ if (fSkinCurrent.GetSize () == EmPoint (0, 0))
+ {
+ fSkinCurrent = fSkinBase;
+
+ Preference<bool> prefDimWhenInactive (kPrefKeyDimWhenInactive);
+ Preference<bool> prefShowDebugMode (kPrefKeyShowDebugMode);
+ Preference<bool> prefShowGremlinMode (kPrefKeyShowGremlinMode);
+
+ if (!fActive && *prefDimWhenInactive)
+ fSkinCurrent.ChangeTone (40);
+
+ if (fDebugMode && *prefShowDebugMode)
+ fSkinCurrent.ConvertToColor (1);
+
+ else if (fGremlinMode && *prefShowGremlinMode)
+ fSkinCurrent.ConvertToColor (2);
+ }
+
+ return fSkinCurrent;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetCurrentSkinColors
+// ---------------------------------------------------------------------------
+
+const RGBList& EmWindow::GetCurrentSkinColors (Bool polite)
+{
+ int index = 0;
+
+ if (fDebugMode)
+ index |= 0x0001;
+
+ else if (fGremlinMode)
+ index |= 0x0002;
+
+ if (fActive)
+ index |= 0x0004;
+
+ if (polite)
+ index |= 0x0008;
+
+ RGBList& result = fSkinColors[index];
+
+ if (result.empty ())
+ {
+ const EmPixMap& skin = this->GetCurrentSkin ();
+
+ this->QuantizeSkinColors (skin, result, polite);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::GetCurrentSkinRegion
+// ---------------------------------------------------------------------------
+
+const EmRegion& EmWindow::GetCurrentSkinRegion (void)
+{
+ return fSkinRegion;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowReset
+// ---------------------------------------------------------------------------
+// Update the window's appearance due to a skin change.
+
+void EmWindow::HostWindowReset (void)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostMouseCapture
+// ---------------------------------------------------------------------------
+// Capture the mouse so that all mouse events get sent to this window.
+
+void EmWindow::HostMouseCapture (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostMouseRelease
+// ---------------------------------------------------------------------------
+// Release the mouse so that mouse events get sent to the window the
+// cursor is over.
+
+void EmWindow::HostMouseRelease (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostUpdateBegin
+// ---------------------------------------------------------------------------
+// Prepare the host window object for updating.
+
+void EmWindow::HostUpdateBegin (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostUpdateEnd
+// ---------------------------------------------------------------------------
+// Finalize the host window object after it's been updated.
+
+void EmWindow::HostUpdateEnd (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostDrawingBegin
+// ---------------------------------------------------------------------------
+// Prepare the host window object for drawing outside of an update event.
+
+void EmWindow::HostDrawingBegin (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostDrawingEnd
+// ---------------------------------------------------------------------------
+// Finalize the host window object after drawing outside of an update event.
+
+void EmWindow::HostDrawingEnd (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostPaletteSet
+// ---------------------------------------------------------------------------
+// Establish the palette to be used for drawing.
+
+void EmWindow::HostPaletteSet (const EmScreenUpdateInfo&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostPaletteRestore
+// ---------------------------------------------------------------------------
+// Clean up after HostPaletteSet.
+
+void EmWindow::HostPaletteRestore (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowMoveBy
+// ---------------------------------------------------------------------------
+// Move the host window object by the given offset.
+
+void EmWindow::HostWindowMoveBy (const EmPoint&)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowMoveTo
+// ---------------------------------------------------------------------------
+// Move the host window object to the given location.
+
+void EmWindow::HostWindowMoveTo (const EmPoint&)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowBoundsGet
+// ---------------------------------------------------------------------------
+// Get the global bounds of the host window object.
+
+EmRect EmWindow::HostWindowBoundsGet (void)
+{
+ EmAssert (false);
+ return EmRect (0, 0, 0, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowCenter
+// ---------------------------------------------------------------------------
+// Center the window to the main display.
+
+void EmWindow::HostWindowCenter (void)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowShow
+// ---------------------------------------------------------------------------
+// Make the host window object visible.
+
+void EmWindow::HostWindowShow (void)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowStayOnTop
+// ---------------------------------------------------------------------------
+// Make the host window stay on top.
+
+void EmWindow::HostWindowStayOnTop (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostWindowDrag
+// ---------------------------------------------------------------------------
+// The user has clicked in a region of the host window object that causes
+// the window to be dragged. Drag the window around.
+
+void EmWindow::HostWindowDrag (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostRectFrame
+// ---------------------------------------------------------------------------
+// Draw a rectangle frame with the given width in the given color.
+
+void EmWindow::HostRectFrame (const EmRect&, const EmPoint&, const RGBType&)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostOvalPaint
+// ---------------------------------------------------------------------------
+// Fill an oval with the given color.
+
+void EmWindow::HostOvalPaint (const EmRect&, const RGBType&)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostPaintCase
+// ---------------------------------------------------------------------------
+// Draw the skin.
+
+void EmWindow::HostPaintCase (const EmScreenUpdateInfo&)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostPaintLCD
+// ---------------------------------------------------------------------------
+// Draw the LCD area.
+
+void EmWindow::HostPaintLCD (const EmScreenUpdateInfo&, const EmRect&,
+ const EmRect&, Bool)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostPalette
+// ---------------------------------------------------------------------------
+// Tell the system about the palette we want to use. Called when Windows
+// is updating its system palette.
+
+void EmWindow::HostPalette (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostDisplayChange
+// ---------------------------------------------------------------------------
+// Respond to the display's bit depth changing. All we do here is flush our
+// caches of the skin information. It will get regenerated when it's needed.
+
+void EmWindow::HostDisplayChange (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostGetDefaultSkin
+// ---------------------------------------------------------------------------
+// Get the default (built-in) skin image.
+
+void EmWindow::HostGetDefaultSkin (EmPixMap&, int)
+{
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::HostGetCurrentMouse
+// ---------------------------------------------------------------------------
+// Get the current mouse location.
+
+EmPoint EmWindow::HostGetCurrentMouse (void)
+{
+ EmAssert (false);
+ return EmPoint (0, 0);
+}
diff --git a/SrcShared/EmWindow.h b/SrcShared/EmWindow.h
new file mode 100644
index 0000000..087efde
--- /dev/null
+++ b/SrcShared/EmWindow.h
@@ -0,0 +1,177 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmWindow_h
+#define EmWindow_h
+
+#include "EmPixMap.h" // EmPixMap
+#include "EmRegion.h" // EmRegion
+#include "EmStructs.h" // RGBList
+#include "PreferenceMgr.h" // PrefKeyType
+
+/*
+ EmWindow is the cross-platform object representing the window that
+ displays the emulation. It is not the actual thing that appears on
+ the monitor as a window, but merely deals with cross-platform
+ aspects of handling it, such as updating its contents, changing
+ skins, etc.
+
+ EmWindow handles all the cross-platform issues. It can deal with
+ the upper-level parts of updating the LCD area, wiggling the window
+ if the vibrator is going, changing skins, etc.
+
+ EmWindow manages most of the platform-specific aspects by defining
+ HostFoo methods, which are then defined differently on each
+ platform. These HostFoo methods are implemented in
+ EmWindow<Host>.cpp.
+
+ EmWindow<Host> is also defined in EmWindow<Host>.cpp, and holds any
+ platform-specific data (such as the HWND on Windows, etc.). It
+ declares and implements any support functions needed on that
+ particular platform, but which can't be declared in EmWindow because
+ either not all platforms need those functions, or they involve
+ platform-specific types.
+
+ One creates a window by calling "window = new EmWindow<Host>;"
+ followed by "window->WindowInit();". Cross-platform code can then
+ call high-level functions in EmWindow such as HandleUpdate and
+ HandlePen. Platform-specific code can perform platform-specific
+ operations. When it's time to close the window, call
+ "window->WindowDispose();" followed by "delete window;"
+*/
+
+class EmPoint;
+class EmScreenUpdateInfo;
+
+class EmWindow
+{
+ public:
+ EmWindow (void);
+ virtual ~EmWindow (void);
+
+ static EmWindow* NewWindow (void);
+
+ void WindowInit (void);
+ void WindowReset (void);
+
+ void HandlePenEvent (const EmPoint&, Bool down);
+ void HandleUpdate (void);
+ void HandlePalette (void);
+ void HandleDisplayChange (void);
+ void HandleActivate (Bool active);
+ virtual void HandleIdle (void);
+
+ void HandleDebugMode (Bool debugMode);
+ void HandleGremlinMode (Bool gremlinMode);
+
+ void GetLCDContents (EmScreenUpdateInfo& info);
+
+ private:
+ void PaintScreen (Bool drawCase, Bool always);
+ void PaintCase (const EmScreenUpdateInfo& info);
+ void PaintLCDFrame (const EmScreenUpdateInfo& info);
+ void PaintLCD (const EmScreenUpdateInfo& info);
+ void PaintLED (uint16 ledState);
+ void PaintButtonFrames (void);
+
+ static void PrefsChangedCB (PrefKeyType key, void* data);
+ void PrefsChanged (PrefKeyType key);
+
+ EmRect GetLCDBounds (void);
+ EmRect GetLEDBounds (void);
+
+ Bool GetSkin (EmPixMap&);
+ void GetDefaultSkin (EmPixMap&);
+
+ protected:
+ void PreDestroy (void);
+ Bool PrevLCDColorsChanged(const RGBList& newLCDColors);
+ void SaveLCDColors (const RGBList& newLCDColors);
+ void GetSystemColors (const EmScreenUpdateInfo&,
+ RGBList&);
+ void QuantizeSkinColors (const EmPixMap& skin,
+ RGBList& colors,
+ Bool polite);
+
+ const EmPixMap& GetCurrentSkin (void);
+ const RGBList& GetCurrentSkinColors(Bool polite);
+ const EmRegion& GetCurrentSkinRegion(void);
+
+ private:
+ virtual void HostWindowReset (void) = 0;
+
+ virtual void HostMouseCapture (void);
+ virtual void HostMouseRelease (void);
+
+ virtual void HostUpdateBegin (void);
+ virtual void HostUpdateEnd (void);
+
+ virtual void HostDrawingBegin (void);
+ virtual void HostDrawingEnd (void);
+
+ virtual void HostPaletteSet (const EmScreenUpdateInfo&);
+ virtual void HostPaletteRestore (void);
+
+ virtual void HostWindowMoveBy (const EmPoint&) = 0;
+ virtual void HostWindowMoveTo (const EmPoint&) = 0;
+ virtual EmRect HostWindowBoundsGet (void) = 0;
+ virtual void HostWindowCenter (void) = 0;
+ virtual void HostWindowShow (void) = 0;
+ virtual void HostWindowDrag (void);
+ virtual void HostWindowStayOnTop (void);
+
+ virtual void HostRectFrame (const EmRect&, const EmPoint&, const RGBType&) = 0;
+ virtual void HostOvalPaint (const EmRect&, const RGBType&) = 0;
+
+ virtual void HostPaintCase (const EmScreenUpdateInfo&) = 0;
+ virtual void HostPaintLCD (const EmScreenUpdateInfo& info,
+ const EmRect& srcRect,
+ const EmRect& destRect,
+ Bool scaled) = 0;
+
+ virtual void HostPalette (void);
+ virtual void HostDisplayChange (void);
+
+ virtual void HostGetDefaultSkin (EmPixMap&, int scale) = 0;
+ virtual EmPoint HostGetCurrentMouse (void) = 0;
+
+ private:
+ static EmWindow* fgWindow;
+
+ EmPixMap fSkinBase;
+ EmPixMap fSkinCurrent;
+
+ RGBList fSkinColors[16];
+
+ EmRegion fSkinRegion;
+
+ RGBList fPrevLCDColors;
+
+ SkinElementType fCurrentButton;
+
+ Bool fNeedWindowReset;
+ Bool fNeedWindowInvalidate;
+
+ Bool fOldLCDOn;
+ Bool fOldBacklightOn;
+ uint16 fOldLEDState;
+
+ Bool fWiggled;
+ Bool fActive;
+ Bool fDebugMode;
+ Bool fGremlinMode;
+};
+
+extern EmWindow* gWindow;
+
+#endif // EmWindow_h
diff --git a/SrcShared/ErrorHandling.cpp b/SrcShared/ErrorHandling.cpp
new file mode 100644
index 0000000..fcb7c39
--- /dev/null
+++ b/SrcShared/ErrorHandling.cpp
@@ -0,0 +1,3388 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "ErrorHandling.h"
+
+#include "DebugMgr.h" // Debug::EnterDebugger
+#include "EmApplication.h" // ScheduleQuit
+#include "EmBankDRAM.h" // EmBankDRAM::ValidAddress
+#include "EmBankSRAM.h" // EmBankSRAM::ValidAddress
+#include "EmCPU.h" // gCPU
+#include "EmCPU68K.h" // gCPU68K, kException_SoftBreak
+#include "EmDlg.h" // kDebugReset, kErrorAlert, kContinueDebugReset, kCautionAlert
+#include "EmErrCodes.h" // kError_OutOfMemory, ConvertFromStdCError
+#include "EmEventOutput.h" // ErrorOccurred
+#include "EmEventPlayback.h" // RecordErrorEvent
+#include "EmException.h" // EmExceptionEnterDebugger
+#include "EmMinimize.h" // EmMinimize::IsOn, NextMinimizer
+#include "EmPalmFunction.h" // gLibErrorBase
+#include "EmPalmOS.h" // GenerateStackCrawl
+#include "EmPalmStructs.h" // EmAliasWindowType
+#include "EmPatchState.h" // EmPatchState::GetCurrentAppInfo
+#include "EmSession.h" // gSession
+#include "Hordes.h" // Hordes::IsOn, RecordErrorStats
+#include "Logging.h" // LogWrite, ReportFoo functions
+#include "MetaMemory.h" // MetaMemory
+#include "Miscellaneous.h" // LaunchCmdToString, SystemCallContext, ReplaceString
+#include "Platform.h" // GetString, CommonDialog
+#include "PreferenceMgr.h" // Preference
+#include "Strings.r.h" // kStr_ values
+
+
+// ===========================================================================
+// ¥ Errors
+// ===========================================================================
+
+#define FIELDS(type, name, fns) \
+ { \
+ 0, \
+ EmAlias##type<PAS>::offsetof_##name (), \
+ #name, \
+ fns, \
+ NULL \
+ }
+
+#define SUB_FIELDS(type, name, sub_table) \
+ { \
+ 1, \
+ EmAlias##type<PAS>::offsetof_##name (), \
+ #name, \
+ NULL, \
+ sub_table \
+ }
+
+#define END_OF_FIELDS {2, 0, NULL, NULL, NULL }
+
+
+struct EmFieldLookup
+{
+ int fType; // 0 == FIELDS, 1 == SUB_FIELDS
+ size_t fOffset; // Offset of the field
+ const char* fFieldName; // Name of the field
+
+ // Used for FIELDS.
+ const char* fFunction; // Name(s) of accessor function(s)
+
+ // Used for SUB_FIELDS.
+ const EmFieldLookup* fNextTable; // pointer to sub-struct table
+};
+
+
+/*
+ BitmapType
+ Int16 width;
+ Int16 height;
+ UInt16 rowBytes;
+ BitmapFlagsType flags;
+ UInt8 pixelSize; // bits/pixel
+ UInt8 version; // version of bitmap. This is vers 2
+ UInt16 nextDepthOffset; // # of DWords to next BitmapType
+ // from beginnning of this one
+ UInt8 transparentIndex; // v2 only, if flags.hasTransparency is true,
+ // index number of transparent color
+ UInt8 compressionType; // v2 only, if flags.compressed is true, this is
+ // the type, see BitmapCompressionType
+
+ UInt16 reserved; // for future use, must be zero!
+
+ // [colorTableType] pixels | pixels*
+ // If hasColorTable != 0, we have:
+ // ColorTableType followed by pixels.
+ // If hasColorTable == 0:
+ // this is the start of the pixels
+ // if indirect != 0 bits are stored indirectly.
+ // the address of bits is stored here
+ // In some cases the ColorTableType will
+ // have 0 entries and be 2 bytes long.
+*/
+
+static const EmFieldLookup kBitmapTypeV2Table[] =
+{
+ FIELDS(BitmapTypeV2, width, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV2, height, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV2, rowBytes, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV2, flags, NULL),
+ FIELDS(BitmapTypeV2, pixelSize, "BmpGetBitDepth"),
+ FIELDS(BitmapTypeV2, version, NULL),
+ FIELDS(BitmapTypeV2, nextDepthOffset, "BmpGetNextBitmap"),
+ FIELDS(BitmapTypeV2, transparentIndex, NULL),
+ FIELDS(BitmapTypeV2, compressionType, NULL),
+ FIELDS(BitmapTypeV2, reserved, NULL),
+ END_OF_FIELDS
+};
+
+
+static const EmFieldLookup kBitmapTypeV3Table[] =
+{
+ FIELDS(BitmapTypeV3, width, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV3, height, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV3, rowBytes, "BmpGetDimensions"),
+ FIELDS(BitmapTypeV3, flags, NULL),
+ FIELDS(BitmapTypeV3, pixelSize, "BmpGetBitDepth"),
+ FIELDS(BitmapTypeV3, version, NULL),
+ FIELDS(BitmapTypeV3, size, NULL),
+ FIELDS(BitmapTypeV3, pixelFormat, NULL),
+ FIELDS(BitmapTypeV3, unused, NULL),
+ FIELDS(BitmapTypeV3, compressionType, NULL),
+ FIELDS(BitmapTypeV3, density, NULL),
+ FIELDS(BitmapTypeV3, transparentValue, NULL),
+ FIELDS(BitmapTypeV3, nextDepthOffset, "BmpGetNextBitmap"),
+ END_OF_FIELDS
+};
+
+
+/*
+ WindowType
+ Coord displayWidthV20; // WinGetDisplayExtent
+ Coord displayHeightV20; // WinGetDisplayExtent
+ void * displayAddrV20; // BmpGetBits (aka BltGetBitsAddr) [3.5]
+ WindowFlagsType windowFlags;
+ format //
+ offscreen //
+ modal // WinModal
+ focusable //
+ enabled // WinEnableWindow, WinDisableWindow
+ visible //
+ dialog //
+ freeBitmap //
+ RectangleType windowBounds; // WinGetWindowFrameRect, WinGetFramesRectangle, WinSetBounds
+ AbsRectType clippingBounds; // WinSetClip, WinResetClip
+ BitmapPtr bitmapP; // WinGetBitmap [3.5]
+ FrameBitsType frameType; //
+ DrawStateType * drawStateP; // WinSetForeColor, WinSetBackColor, WinSetTextColor, WinSetForeColorRGB, WinSetBackColorRGB, WinSetTextColorRGB, WinGetPattern, WinSetPattern, WinGetPatternType, WinSetPatternType, WinSetDrawMode, WinSetUnderlineMode
+ struct WindowType * nextWindow; //
+*/
+
+static const EmFieldLookup kWindowTypeTable[] =
+{
+ FIELDS(WindowType, displayWidthV20, "WinGetDisplayExtent"),
+ FIELDS(WindowType, displayHeightV20, "WinGetDisplayExtent"),
+ FIELDS(WindowType, displayAddrV20, "BmpGetBits"),
+ FIELDS(WindowType, windowFlags, "WinModal, WinEnableWindow, WinDisableWindow"),
+ FIELDS(WindowType, windowBounds, "WinGetWindowFrameRect, WinGetFramesRectangle, WinSetBounds"),
+ FIELDS(WindowType, clippingBounds, "WinSetClip, WinResetClip"),
+ FIELDS(WindowType, bitmapP, "WinGetBitmap"),
+ FIELDS(WindowType, frameType, NULL),
+ FIELDS(WindowType, drawStateP, "WinSetForeColor, WinSetBackColor, WinSetTextColor, WinSetForeColorRGB, WinSetBackColorRGB, WinSetTextColorRGB, WinGetPattern, WinSetPattern, WinGetPatternType, WinSetPatternType, WinSetDrawMode, WinSetUnderlineMode"),
+ FIELDS(WindowType, nextWindow, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormType
+ WindowType window;
+ UInt16 formId;
+ FormAttrType attr;
+ usable :1; // Set if part of ui
+ enabled :1; // Set if interactable (not grayed out)
+ visible :1; // Set if drawn, used internally
+ dirty :1; // Set if dialog has been modified
+ saveBehind :1; // Set if bits behind form are save when form ids drawn
+ graffitiShift :1; // Set if graffiti shift indicator is supported
+ globalsAvailable:1; // Set by Palm OS if globals are available for the
+ // form event handler
+ doingDialog :1; // FrmDoDialog is using for nested event loop
+ exitDialog :1; // tells FrmDoDialog to bail out and stop using this form
+ reserved :7; // pad to 16
+ reserved2; // FormAttrType now explicitly 32-bits wide.
+ WinHandle bitsBehindForm;
+ FormEventHandlerType* handler;
+ UInt16 focus;
+ UInt16 defaultButton;
+ UInt16 helpRscId;
+ UInt16 menuRscId;
+ UInt16 numObjects;
+ FormObjListType* objects;
+*/
+
+static const EmFieldLookup kFormTypeTable[] =
+{
+ SUB_FIELDS(FormType, window, kWindowTypeTable),
+ FIELDS(FormType, formId, NULL),
+ FIELDS(FormType, attr, NULL),
+ FIELDS(FormType, bitsBehindForm, NULL),
+ FIELDS(FormType, handler, NULL),
+ FIELDS(FormType, focus, NULL),
+ FIELDS(FormType, defaultButton, NULL),
+ FIELDS(FormType, helpRscId, NULL),
+ FIELDS(FormType, menuRscId, NULL),
+ FIELDS(FormType, numObjects, NULL),
+ FIELDS(FormType, objects, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormObjListType
+ FormObjectKind objectType;
+ UInt8 reserved;
+ FormObjectType object;
+*/
+
+static const EmFieldLookup kFormObjListTypeTable[] =
+{
+ FIELDS(FormObjListType, objectType, NULL),
+ FIELDS(FormObjListType, reserved, NULL),
+ FIELDS(FormObjListType, object, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FieldType
+ UInt16 id;
+ RectangleType rect;
+ FieldAttrType attr;
+ Char* text; // pointer to the start of text string
+ MemHandle textHandle; // block the contains the text string
+ LineInfoPtr lines;
+ UInt16 textLen;
+ UInt16 textBlockSize;
+ UInt16 maxChars;
+ UInt16 selFirstPos;
+ UInt16 selLastPos;
+ UInt16 insPtXPos;
+ UInt16 insPtYPos;
+ FontID fontID;
+ UInt8 maxVisibleLines;
+*/
+
+static const EmFieldLookup kFieldTypeTable[] =
+{
+ FIELDS(FieldType, id, NULL),
+ FIELDS(FieldType, rect, NULL),
+ FIELDS(FieldType, attr, NULL),
+ FIELDS(FieldType, text, NULL),
+ FIELDS(FieldType, textHandle, NULL),
+ FIELDS(FieldType, lines, NULL),
+ FIELDS(FieldType, textLen, NULL),
+ FIELDS(FieldType, textBlockSize, NULL),
+ FIELDS(FieldType, maxChars, NULL),
+ FIELDS(FieldType, selFirstPos, NULL),
+ FIELDS(FieldType, selLastPos, NULL),
+ FIELDS(FieldType, insPtXPos, NULL),
+ FIELDS(FieldType, insPtYPos, NULL),
+ FIELDS(FieldType, fontID, NULL),
+ FIELDS(FieldType, maxVisibleLines, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ ControlType
+ UInt16 id;
+ RectangleType bounds;
+ Char* text;
+ ControlAttrType attr;
+ ControlStyleType style;
+ FontID font;
+ UInt8 group;
+ UInt8 reserved;
+*/
+
+static const EmFieldLookup kControlTypeTable[] =
+{
+ FIELDS(ControlType, id, NULL),
+ FIELDS(ControlType, bounds, NULL),
+ FIELDS(ControlType, text, NULL),
+ FIELDS(ControlType, attr, NULL),
+ FIELDS(ControlType, style, NULL),
+ FIELDS(ControlType, font, NULL),
+ FIELDS(ControlType, group, NULL),
+ FIELDS(ControlType, reserved, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ GraphicControlType
+ UInt16 id;
+ RectangleType bounds;
+ DmResID bitmapID; // overlays text in ControlType
+ DmResID selectedBitmapID; // overlays text in ControlType
+ ControlAttrType attr;
+ ControlStyleType style;
+ FontID unused;
+ UInt8 group;
+ UInt8 reserved;
+*/
+
+static const EmFieldLookup kGraphicControlTypeTable[] =
+{
+ FIELDS(GraphicControlType, id, NULL),
+ FIELDS(GraphicControlType, bounds, NULL),
+ FIELDS(GraphicControlType, bitmapID, NULL),
+ FIELDS(GraphicControlType, selectedBitmapID, NULL),
+ FIELDS(GraphicControlType, attr, NULL),
+ FIELDS(GraphicControlType, style, NULL),
+ FIELDS(GraphicControlType, unused, NULL),
+ FIELDS(GraphicControlType, group, NULL),
+ FIELDS(GraphicControlType, reserved, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ SliderControlType
+ UInt16 id;
+ RectangleType bounds;
+ DmResID thumbID; // overlays text in ControlType
+ DmResID backgroundID; // overlays text in ControlType
+ ControlAttrType attr; // graphical *is* set
+ ControlStyleType style; // must be sliderCtl or repeatingSliderCtl
+ UInt8 reserved;
+ Int16 minValue;
+ Int16 maxValue;
+ Int16 pageSize;
+ Int16 value;
+ MemPtr activeSliderP;
+*/
+
+static const EmFieldLookup kSliderControlTypeTable[] =
+{
+ FIELDS(SliderControlType, id, NULL),
+ FIELDS(SliderControlType, bounds, NULL),
+ FIELDS(SliderControlType, thumbID, NULL),
+ FIELDS(SliderControlType, backgroundID, NULL),
+ FIELDS(SliderControlType, attr, NULL),
+ FIELDS(SliderControlType, style, NULL),
+ FIELDS(SliderControlType, reserved, NULL),
+ FIELDS(SliderControlType, minValue, NULL),
+ FIELDS(SliderControlType, maxValue, NULL),
+ FIELDS(SliderControlType, pageSize, NULL),
+ FIELDS(SliderControlType, value, NULL),
+ FIELDS(SliderControlType, activeSliderP, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ ListType
+ UInt16 id;
+ RectangleType bounds;
+ ListAttrType attr;
+ Char** itemsText;
+ Int16 numItems; // number of choices in the list
+ Int16 currentItem; // currently display choice
+ Int16 topItem; // top item visible when poped up
+ FontID font; // font used to draw list
+ UInt8 reserved;
+ WinHandle popupWin; // used only by popup lists
+ ListDrawDataFuncPtr drawItemsCallback; // 0 indicates no function
+*/
+
+static const EmFieldLookup kListTypeTable[] =
+{
+ FIELDS(ListType, id, NULL),
+ FIELDS(ListType, bounds, NULL),
+ FIELDS(ListType, attr, NULL),
+ FIELDS(ListType, itemsText, NULL),
+ FIELDS(ListType, numItems, NULL),
+ FIELDS(ListType, currentItem, NULL),
+ FIELDS(ListType, topItem, NULL),
+ FIELDS(ListType, font, NULL),
+ FIELDS(ListType, reserved, NULL),
+ FIELDS(ListType, popupWin, NULL),
+ FIELDS(ListType, drawItemsCallback, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ TableType
+ UInt16 id;
+ RectangleType bounds;
+ TableAttrType attr;
+ Int16 numColumns;
+ Int16 numRows;
+ Int16 currentRow;
+ Int16 currentColumn;
+ Int16 topRow;
+ TableColumnAttrType* columnAttrs;
+ TableRowAttrType* rowAttrs;
+ TableItemPtr items;
+ FieldType currentField;
+*/
+
+static const EmFieldLookup kTableTypeTable[] =
+{
+ FIELDS(TableType, id, NULL),
+ FIELDS(TableType, bounds, NULL),
+ FIELDS(TableType, attr, NULL),
+ FIELDS(TableType, numColumns, NULL),
+ FIELDS(TableType, numRows, NULL),
+ FIELDS(TableType, currentRow, NULL),
+ FIELDS(TableType, currentColumn, NULL),
+ FIELDS(TableType, topRow, NULL),
+ FIELDS(TableType, columnAttrs, NULL),
+ FIELDS(TableType, rowAttrs, NULL),
+ FIELDS(TableType, items, NULL),
+ SUB_FIELDS(TableType, currentField, kFieldTypeTable),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormBitmapType
+ FormObjAttrType attr;
+ PointType pos;
+ UInt16 rscID;
+*/
+
+static const EmFieldLookup kFormBitmapTypeTable[] =
+{
+ FIELDS(FormBitmapType, attr, NULL),
+ FIELDS(FormBitmapType, pos, NULL),
+ FIELDS(FormBitmapType, rscID, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormLineType
+ FormObjAttrType attr;
+ PointType point1;
+ PointType point2;
+*/
+
+static const EmFieldLookup kFormLineTypeTable[] =
+{
+ FIELDS(FormLineType, attr, NULL),
+ FIELDS(FormLineType, point1, NULL),
+ FIELDS(FormLineType, point2, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormFrameType
+ UInt16 id;
+ FormObjAttrType attr;
+ RectangleType rect;
+ UInt16 frameType;
+*/
+
+static const EmFieldLookup kFormFrameTypeTable[] =
+{
+ FIELDS(FormFrameType, id, NULL),
+ FIELDS(FormFrameType, attr, NULL),
+ FIELDS(FormFrameType, rect, NULL),
+ FIELDS(FormFrameType, frameType, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormRectangleType
+ FormObjAttrType attr;
+ RectangleType rect;
+*/
+
+static const EmFieldLookup kFormRectangleTypeTable[] =
+{
+ FIELDS(FormRectangleType, attr, NULL),
+ FIELDS(FormRectangleType, rect, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormLabelType
+ UInt16 id;
+ PointType pos;
+ FormObjAttrType attr;
+ FontID fontID;
+ UInt8 reserved;
+ Char* text;
+*/
+
+static const EmFieldLookup kFormLabelTypeTable[] =
+{
+ FIELDS(FormLabelType, id, NULL),
+ FIELDS(FormLabelType, pos, NULL),
+ FIELDS(FormLabelType, attr, NULL),
+ FIELDS(FormLabelType, fontID, NULL),
+ FIELDS(FormLabelType, reserved, NULL),
+ FIELDS(FormLabelType, text, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormTitleType
+ RectangleType rect;
+ Char * text;
+*/
+
+static const EmFieldLookup kFormTitleTypeTable[] =
+{
+ FIELDS(FormTitleType, rect, NULL),
+ FIELDS(FormTitleType, text, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormPopupType
+ UInt16 controlID;
+ UInt16 listID;
+*/
+
+static const EmFieldLookup kFormPopupTypeTable[] =
+{
+ FIELDS(FormPopupType, controlID, NULL),
+ FIELDS(FormPopupType, listID, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FrmGraffitiStateType
+ PointType pos;
+*/
+
+static const EmFieldLookup kFrmGraffitiStateTypeTable[] =
+{
+ FIELDS(FrmGraffitiStateType, pos, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ FormGadgetType
+ UInt16 id;
+ FormGadgetAttrType attr;
+ RectangleType rect;
+ const void* data;
+ FormGadgetHandlerType* handler;
+*/
+
+static const EmFieldLookup kFormGadgetTypeTable[] =
+{
+ FIELDS(FormGadgetType, id, NULL),
+ FIELDS(FormGadgetType, attr, NULL),
+ FIELDS(FormGadgetType, rect, NULL),
+ FIELDS(FormGadgetType, data, NULL),
+ FIELDS(FormGadgetType, handler, NULL),
+ END_OF_FIELDS
+};
+
+
+/*
+ ScrollBarType
+ RectangleType bounds;
+ UInt16 id;
+ ScrollBarAttrType attr;
+ Int16 value;
+ Int16 minValue;
+ Int16 maxValue;
+ Int16 pageSize;
+ Int16 penPosInCar;
+ Int16 savePos;
+*/
+
+static const EmFieldLookup kScrollBarTypeTable[] =
+{
+ FIELDS(ScrollBarType, bounds, NULL),
+ FIELDS(ScrollBarType, id, NULL),
+ FIELDS(ScrollBarType, attr, NULL),
+ FIELDS(ScrollBarType, value, NULL),
+ FIELDS(ScrollBarType, minValue, NULL),
+ FIELDS(ScrollBarType, maxValue, NULL),
+ FIELDS(ScrollBarType, pageSize, NULL),
+ FIELDS(ScrollBarType, penPosInCar, NULL),
+ FIELDS(ScrollBarType, savePos, NULL),
+ END_OF_FIELDS
+};
+
+
+void PrvLookupField (const EmFieldLookup* table, size_t offset,
+ const char*& fieldName, const char*& function);
+string PrvGetProscribedReason (const SystemCallContext& context);
+
+
+static ParamList gUserParameters;
+
+
+// This table should match up with gPalmOSLibraries in EmPalmFunction.cpp.
+static const long gResourceBases [] =
+{
+ kStr_INetLibTrapBase,
+ kStr_IrLibTrapBase, // Also includes Exchange Lib
+ kStr_SecLibTrapBase,
+ kStr_WebLibTrapBase,
+// kStr_serIrCommLibTrapBase, // ???SerIrCommLib.h doesn't declare the functions as SYSTRAPs!
+ kStr_SerLibTrapBase,
+ kStr_SerLibTrapBase,
+ kStr_NetLibTrapBase,
+ kStr_HTALLibTrapBase,
+ kStr_RailLibTrapBase,
+ kStr_NPILibTrapBase,
+ kStr_SerLibTrapBase,
+ kStr_SerLibTrapBase,
+ kStr_HTALLibTrapBase
+};
+
+
+#pragma mark -
+
+#define kFatal 1
+#define kEnterDebuggerFirst 2
+
+static EmCommonDialogFlags PrvButtonFlags (int flags)
+{
+ return (flags & kFatal)
+ ? kDlgFlags_continue_DEBUG_Reset
+ : kDlgFlags_Continue_DEBUG_Reset;
+}
+
+static Bool PrvEnterDebuggerFirst (int flags)
+{
+ return (flags & kEnterDebuggerFirst) ? true : false;
+}
+
+static string PrvAsHex4 (uint16 value)
+{
+ char buffer[20];
+ sprintf (buffer, "0x%04lX", (uint32) value);
+ return string (buffer);
+}
+
+static string PrvAsHex8 (uint32 value)
+{
+ char buffer[20];
+ sprintf (buffer, "0x%08lX", value);
+ return string (buffer);
+}
+
+static string PrvAsDecimal (int32 value)
+{
+ char buffer[20];
+ sprintf (buffer, "%ld", value);
+ return string (buffer);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Initialize
+// ---------------------------------------------------------------------------
+
+void Errors::Initialize (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Reset
+// ---------------------------------------------------------------------------
+
+void Errors::Reset (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Save
+// ---------------------------------------------------------------------------
+
+void Errors::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Load
+// ---------------------------------------------------------------------------
+
+void Errors::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Dispose
+// ---------------------------------------------------------------------------
+
+void Errors::Dispose (void)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportIfError
+// ---------------------------------------------------------------------------
+// Checks for the indicated error condition. If there is an error, it
+// displays a "Could not foo because bar." message in a dialog with an OK
+// button. If an optional recovery string is provided, the message is
+// "Could no foo because bar. Do this." message. If "throwAfter" is true,
+// Errors::Scram is called after the dialog is dismissed.
+//
+// "operation" and "recovery" are "kStr_Foo" values.
+// "error" is Mac or Windows error number, or a kError_Foo value.
+
+void Errors::ReportIfError (StrCode operation, ErrCode error, StrCode recovery, Bool throwAfter)
+{
+ if (error)
+ {
+ Errors::SetStandardParameters ();
+
+ if (Errors::SetErrorParameters (operation, error, recovery))
+ {
+ Errors::DoDialog (kStr_OpErrorRecover, kDlgFlags_OK);
+ }
+ else
+ {
+ Errors::DoDialog (kStr_OpError, kDlgFlags_OK);
+ }
+
+ if (throwAfter)
+ {
+ Errors::Scram ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportIfPalmError
+// ---------------------------------------------------------------------------
+// Checks for the indicated error condition. If there is an error, it
+// displays a "Could not foo because bar." message in a dialog with an OK
+// button. If an optional recovery string is provided, the message is
+// "Could no foo because bar. Do this." message. If "throwAfter" is true,
+// Errors::Scram is called after the dialog is dismissed.
+//
+// "operation" and "recovery" are "kStr_Foo" values.
+// "err" is a Palm OS error number.
+
+void Errors::ReportIfPalmError (StrCode operation, Err err, StrCode recovery, Bool throwAfter)
+{
+ if (err)
+ {
+ Errors::ReportIfError (operation, ::ConvertFromPalmError (err), recovery, throwAfter);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportIfNULL
+// ---------------------------------------------------------------------------
+// Checks for the indicated error condition. If there is an error, it
+// displays a "Could not foo because bar." message in a dialog with an OK
+// button. If an optional recovery string is provided, the message is
+// "Could no foo because bar. Do this." message. If "throwAfter" is true,
+// Errors::Scram is called after the dialog is dismissed.
+//
+// "operation" and "recovery" are "kStr_Foo" values.
+// "p" is a pointer to be tested.
+
+void Errors::ReportIfNULL (StrCode operation, void* p, StrCode recovery, Bool throwAfter)
+{
+ if (p == NULL)
+ {
+ Errors::ReportIfError (operation, kError_OutOfMemory, recovery, throwAfter);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrBusError
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrBusError (emuptr address, long size, Bool forRead)
+{
+ if (EmBankSRAM::ValidAddress (address, size))
+ {
+ Errors::ReportErrStorageHeap (address, size, forRead);
+ }
+
+ else if (address >= 0x80000000 && address < 0x80000000 + EmAliasWindowType<PAS>::GetSize ())
+ {
+ Errors::ReportErrNoDrawWindow (address, size, forRead);
+ }
+
+ else if (Errors::LooksLikeA5Access (address, size, forRead))
+ {
+ Errors::ReportErrNoGlobals (address, size, forRead);
+ }
+
+ else
+ {
+ Errors::ReportErrAccessCommon (
+ kStr_ErrBusError,
+ kException_BusErr,
+ kFatal,
+ address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrAddressError
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrAddressError (emuptr address, long size, Bool forRead)
+{
+ Errors::ReportErrAccessCommon (
+ kStr_ErrAddressError,
+ kException_AddressErr,
+ kFatal,
+ address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrIllegalInstruction
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrIllegalInstruction (uint16 opcode)
+{
+ Errors::ReportErrOpcodeCommon (
+ kStr_ErrIllegalInstruction,
+ kException_IllegalInstr,
+ kFatal,
+ opcode);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrDivideByZero
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrDivideByZero (void)
+{
+ Errors::ReportErrCommon (kStr_ErrDivideByZero, kException_DivideByZero, kFatal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrCHKInstruction
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrCHKInstruction (void)
+{
+ Errors::ReportErrCommon (kStr_ErrCHKInstruction, kException_Chk, kFatal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrTRAPVInstruction
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrTRAPVInstruction (void)
+{
+ Errors::ReportErrCommon (kStr_ErrTRAPVInstruction, kException_Trap, kFatal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrPrivilegeViolation
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrPrivilegeViolation (uint16 opcode)
+{
+ Errors::ReportErrOpcodeCommon (
+ kStr_ErrPrivilegeViolation,
+ kException_Privilege,
+ kFatal,
+ opcode);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrTrace
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrTrace (void)
+{
+ Errors::ReportErrCommon (kStr_ErrTrace, kException_Trace, kFatal | kEnterDebuggerFirst);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrATrap
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrATrap (uint16 opcode)
+{
+ if (opcode == 0xA9EB || opcode == 0xA9EC || opcode == 0xA9EE)
+ {
+ Errors::ReportErrSANE ();
+ }
+
+ else
+ {
+ Errors::ReportErrOpcodeCommon (kStr_ErrATrap, kException_ATrap, kFatal, opcode);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrFTrap
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrFTrap (uint16 opcode)
+{
+ Errors::ReportErrOpcodeCommon (kStr_ErrFTrap, kException_FTrap, kFatal, opcode);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrTRAPx
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrTRAPx (int trapNum)
+{
+ if (trapNum == 0)
+ {
+ Errors::ReportErrTRAP0 ();
+ }
+
+ else if (trapNum == 8)
+ {
+ Errors::ReportErrTRAP8 ();
+ }
+
+ else
+ {
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %num message variable.
+
+ Errors::SetParameter ("%num", trapNum);
+
+ // Show the dialog.
+
+ Errors::HandleDialog (
+ kStr_ErrTRAPx,
+ (ExceptionNumber) (kException_Trap0 + trapNum),
+ kDlgFlags_continue_DEBUG_Reset, false);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrStorageHeap
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrStorageHeap (emuptr address, long size, Bool forRead)
+{
+ Errors::ReportErrAccessCommon (
+ kStr_ErrStorageHeap,
+ kException_BusErr,
+ kFatal,
+ address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrNoDrawWindow
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrNoDrawWindow (emuptr address, long size, Bool forRead)
+{
+ Errors::ReportErrAccessCommon (
+ kStr_ErrNoDrawWindow,
+ kException_BusErr,
+ kFatal,
+ address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrNoGlobals
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrNoGlobals (emuptr address, long size, Bool forRead)
+{
+ // Set the %launch_code message variable.
+
+ EmuAppInfo appInfo = EmPatchState::GetCurrentAppInfo ();
+ const char* launchStr = ::LaunchCmdToString (appInfo.fCmd);
+
+ Errors::SetParameter ("%launch_code", launchStr);
+
+ Errors::ReportErrAccessCommon (
+ kStr_ErrNoGlobals,
+ kException_BusErr,
+ kFatal,
+ address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrSANE
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrSANE (void)
+{
+ Errors::ReportErrCommon (kStr_ErrSANE, kException_ATrap, kFatal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrTRAP0
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrTRAP0 (void)
+{
+ Errors::ReportErrCommon (kStr_ErrTRAP0, kException_Trap0, kFatal | kEnterDebuggerFirst);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrTRAP8
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrTRAP8 (void)
+{
+ Errors::ReportErrCommon (kStr_ErrTRAP8, kException_Trap8, kEnterDebuggerFirst);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrStackOverflow
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrStackOverflow (void)
+{
+ Errors::ReportErrStackCommon (kStr_ErrStackOverflow, kException_SoftBreak, kFatal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrUnimplementedTrap
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrUnimplementedTrap (const SystemCallContext& context)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %trap_num message variable.
+
+ string asString (::PrvAsHex4 (context.fTrapWord));
+ Errors::SetParameter ("%trap_num", asString.c_str ());
+
+ // Get the trap name. Look it up in our string resources first.
+
+ uint32 errorBase = ::IsSystemTrap (context.fTrapWord)
+ ? kStr_SysTrapBase
+ : gResourceBases[context.fLibIndex];
+
+ string trapName (Platform::GetString (errorBase + context.fTrapIndex));
+
+ // If we couldn't find it, say that it's an unknown trap.
+
+ if (trapName[0] == '<') // Start of "<Missing string...>"
+ {
+ trapName = Platform::GetString (kStr_UnknownTrapNumber);
+ }
+
+ // Set the %trap_name message variable.
+
+ Errors::SetParameter ("%trap_name", trapName);
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrUnimplementedTrap, kException_SoftBreak, kDlgFlags_continue_DEBUG_Reset, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrInvalidRefNum
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrInvalidRefNum (const SystemCallContext& context)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %ref_num message variable.
+
+ Errors::SetParameter ("%ref_num", context.fExtra);
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrInvalidRefNum, kException_SoftBreak, kDlgFlags_continue_DEBUG_Reset, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrCorruptedHeap
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrCorruptedHeap (ErrCode corruptionType, emuptr chunkHdr)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %mem message variable.
+
+ string asString (::PrvAsHex8 (chunkHdr));
+ Errors::SetParameter ("%mem", asString.c_str ());
+
+ // Get the string that describes the type of corruption.
+
+ int strID = 0;
+
+ switch (corruptionType)
+ {
+ case kError_CorruptedHeap_ChunkNotInHeap:
+ strID = kStr_ChunkNotInHeap;
+ break;
+
+ case kError_CorruptedHeap_ChunkTooLarge:
+ strID = kStr_ChunkTooLarge;
+ break;
+
+ case kError_CorruptedHeap_InvalidFlags:
+ strID = kStr_InvalidFlags;
+ break;
+
+ case kError_CorruptedHeap_HOffsetNotInMPT:
+ strID = kStr_HOffsetNotInMPT;
+ break;
+
+ case kError_CorruptedHeap_HOffsetNotBackPointing:
+ strID = kStr_HOffsetNotBackPointing;
+ break;
+
+ case kError_CorruptedHeap_InvalidLockCount:
+ strID = kStr_InvalidLockCount;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ // Set the %corruption_type message variable.
+
+ Errors::SetParameter ("%corruption_type", Platform::GetString (strID));
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrCorruptedHeap, kException_SoftBreak, kDlgFlags_continue_debug_RESET, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrInvalidPC
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrInvalidPC (emuptr address, int reason)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %mem message variable.
+
+ string asString (::PrvAsHex8 (address));
+ Errors::SetParameter ("%mem", asString.c_str ());
+
+ // Get the string describing why the address is invalid.
+
+ int strID = 0;
+
+ switch (reason)
+ {
+ case kUnmappedAddress:
+ strID = kStr_UnmappedAddress;
+ break;
+
+ case kNotInCodeSegment:
+ strID = kStr_NotInCodeSegment;
+ break;
+
+ case kOddAddress:
+ strID = kStr_OddAddress;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ // Set the %reason message variable.
+
+ Errors::SetParameter ("%reason", Platform::GetString (strID));
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrInvalidPC1, kException_SoftBreak, kDlgFlags_continue_DEBUG_Reset, false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrLowMemory
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrLowMemory (emuptr address, long size, Bool forRead)
+{
+ if (::ReportLowMemoryAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrLowMemory, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrSystemGlobals
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrSystemGlobals (emuptr address, long size, Bool forRead)
+{
+ if (::ReportSystemGlobalAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrSystemGlobals, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrScreen
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrScreen (emuptr address, long size, Bool forRead)
+{
+ if (::ReportScreenAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrScreen, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrHardwareRegisters
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrHardwareRegisters (emuptr address, long size, Bool forRead)
+{
+ if (::ReportHardwareRegisterAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrHardwareRegisters, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrROM
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrROM (emuptr address, long size, Bool forRead)
+{
+ if (::ReportROMAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrROM, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrMemMgrStructures
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrMemMgrStructures (emuptr address, long size, Bool forRead)
+{
+ if (::ReportMemMgrDataAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrMemMgrStructures, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrMemMgrLeaks
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrMemMgrLeaks (int leaks)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %num_leaks message variable.
+
+ Errors::SetParameter ("%num_leaks", leaks);
+
+ // Show the dialog.
+
+ StrCode templateStrCode = leaks == 1 ? kStr_ErrMemoryLeak : kStr_ErrMemoryLeaks;
+ Errors::HandleDialog (templateStrCode, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrMemMgrSemaphore
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrMemMgrSemaphore (void)
+{
+ if (::ReportMemMgrSemaphore ())
+ {
+ Errors::ReportErrCommon (kStr_ErrMemMgrSemaphore, kException_SoftBreak, 0);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrFreeChunk
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrFreeChunk (emuptr address, long size, Bool forRead)
+{
+ if (::ReportFreeChunkAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrFreeChunk, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrUnlockedChunk
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrUnlockedChunk (emuptr address, long size, Bool forRead)
+{
+ if (::ReportUnlockedChunkAccess ())
+ {
+ Errors::ReportErrAccessCommon (kStr_ErrUnlockedChunk, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrLowStack
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrLowStack (emuptr stackLow,
+ emuptr stackPointer,
+ emuptr stackHigh,
+ emuptr address,
+ long size,
+ Bool forRead)
+
+{
+ if (::ReportLowStackAccess ())
+ {
+ // Set the %stack_low message variable.
+
+ string asString1 (::PrvAsHex8 (stackLow));
+ Errors::SetParameter ("%stack_low", asString1.c_str ());
+
+ // Set the %stack_pointer message variable.
+
+ string asString2 (::PrvAsHex8 (stackPointer));
+ Errors::SetParameter ("%stack_pointer", asString2.c_str ());
+
+ // Set the %stack_high message variable.
+
+ string asString3 (::PrvAsHex8 (stackHigh));
+ Errors::SetParameter ("%stack_high", asString3.c_str ());
+
+ Errors::ReportErrAccessCommon (kStr_ErrLowStack, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrStackFull
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrStackFull (void)
+{
+ if (::ReportStackAlmostOverflow ())
+ {
+ Errors::ReportErrStackCommon (kStr_ErrStackFull, kException_SoftBreak, 0);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrSizelessObject
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrSizelessObject (uint16 id, const EmRect& r)
+{
+ if (::ReportSizelessObject ())
+ {
+ Errors::ReportErrObjectCommon (kStr_ErrSizelessObject, kException_SoftBreak, 0, id, r);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrOffscreenObject
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrOffscreenObject (uint16 id, const EmRect& r)
+{
+ if (::ReportOffscreenObject ())
+ {
+ Errors::ReportErrObjectCommon (kStr_ErrOffscreenObject, kException_SoftBreak, 0, id, r);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrFormAccess
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrFormAccess (emuptr formAddress, emuptr address, long size, Bool forRead)
+{
+ if (::ReportUIMgrDataAccess ())
+ {
+ // Set the %form message variable.
+
+ string asString (::PrvAsHex8 (formAddress));
+ Errors::SetParameter ("%form", asString.c_str ());
+
+ // Set the %field and %function variables.
+
+ EmAssert (address >= formAddress);
+
+ size_t offset = address - formAddress;
+ const char* fieldName = NULL;
+ const char* function = NULL;
+
+
+ if (offset < EmAliasFormType<PAS>::GetSize ())
+ {
+ // Set the %field message variable.
+
+ ::PrvLookupField (kFormTypeTable, offset, fieldName, function);
+
+ Errors::SetParameter ("%field", fieldName);
+
+ Errors::ReportErrAccessCommon (kStr_ErrFormAccess, kException_BusErr, 0, address, size, forRead);
+ }
+ else
+ {
+ CEnableFullAccess munge;
+
+ EmAliasFormType<PAS> form (formAddress);
+
+ emuptr firstObject = form.objects;
+#ifndef NDEBUG
+ uint16 numObjects = form.numObjects;
+ emuptr lastObject = firstObject + numObjects * EmAliasFormObjListType<PAS>::GetSize ();
+#endif
+
+ EmAssert (address >= firstObject && address < lastObject);
+
+ size_t listOffset = address - firstObject;
+ size_t index = listOffset / EmAliasFormObjListType<PAS>::GetSize ();
+ size_t fieldOffset = listOffset % EmAliasFormObjListType<PAS>::GetSize ();
+
+ // Set the %field message variable.
+
+ ::PrvLookupField (kFormObjListTypeTable, fieldOffset, fieldName, function);
+
+ Errors::SetParameter ("%field", fieldName);
+
+ // Set the %index message variable.
+
+ string asString (::PrvAsDecimal (index));
+ Errors::SetParameter ("%index", asString.c_str ());
+
+ Errors::ReportErrAccessCommon (kStr_ErrFormObjectListAccess, kException_BusErr, 0, address, size, forRead);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrFormObjectAccess
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrFormObjectAccess (emuptr objectAddress, emuptr formAddress, emuptr address, long size, Bool forRead)
+{
+ if (::ReportUIMgrDataAccess ())
+ {
+ CEnableFullAccess munge;
+
+ EmAliasFormObjListType<PAS> object (objectAddress);
+ FormObjectKind kind = object.objectType;
+ emuptr addr = object.object;
+
+ string typeString ("unknown");
+ const EmFieldLookup* table = NULL;
+
+ switch (kind)
+ {
+ case frmFieldObj: typeString = "frmFieldObj"; table = kFieldTypeTable; break;
+ case frmControlObj: typeString = "frmControlObj"; table = kControlTypeTable; break;
+ case frmListObj: typeString = "frmListObj"; table = kListTypeTable; break;
+ case frmTableObj: typeString = "frmTableObj"; table = kTableTypeTable; break;
+ case frmBitmapObj: typeString = "frmBitmapObj"; table = kFormBitmapTypeTable; break;
+ case frmLineObj: typeString = "frmLineObj"; table = kFormLineTypeTable; break;
+ case frmFrameObj: typeString = "frmFrameObj"; table = kFormFrameTypeTable; break;
+ case frmRectangleObj: typeString = "frmRectangleObj"; table = kFormRectangleTypeTable; break;
+ case frmLabelObj: typeString = "frmLabelObj"; table = kFormLabelTypeTable; break;
+ case frmTitleObj: typeString = "frmTitleObj"; table = kFormTitleTypeTable; break;
+ case frmPopupObj: typeString = "frmPopupObj"; table = kFormPopupTypeTable; break;
+ case frmGraffitiStateObj: typeString = "frmGraffitiStateObj"; table = kFrmGraffitiStateTypeTable; break;
+ case frmGadgetObj: typeString = "frmGadgetObj"; table = kFormGadgetTypeTable; break;
+ case frmScrollBarObj: typeString = "frmScrollBarObj"; table = kScrollBarTypeTable; break;
+ }
+
+ // Set the %object message variable.
+
+ string asString1 (::PrvAsHex8 (addr));
+ Errors::SetParameter ("%object", asString1.c_str ());
+
+ // Set the %field message variable.
+
+ EmAssert (address >= addr);
+
+ size_t offset = address - addr;
+ const char* fieldName = NULL;
+ const char* function = NULL;
+
+ ::PrvLookupField (table, offset, fieldName, function);
+
+ Errors::SetParameter ("%field", fieldName);
+
+ // Set the %type message variable.
+
+ Errors::SetParameter ("%type", typeString.c_str ());
+
+ // Set the %form message variable.
+
+ string asString2 (::PrvAsHex8 (formAddress));
+ Errors::SetParameter ("%form", asString2.c_str ());
+
+ Errors::ReportErrAccessCommon (kStr_ErrFormObjectAccess, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrWindowAccess
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrWindowAccess (emuptr windowAddress, emuptr address, long size, Bool forRead)
+{
+ if (::ReportUIMgrDataAccess ())
+ {
+ // Set the %window message variable.
+
+ string asString (::PrvAsHex8 (windowAddress));
+ Errors::SetParameter ("%window", asString.c_str ());
+
+ // Set the %field and %function variables.
+
+ EmAssert (address >= windowAddress);
+
+ size_t offset = address - windowAddress;
+ const char* fieldName = NULL;
+ const char* function = NULL;
+
+ ::PrvLookupField (kWindowTypeTable, offset, fieldName, function);
+
+ Errors::SetParameter ("%field", fieldName);
+
+ Errors::ReportErrAccessCommon (kStr_ErrWindowAccess, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrBitmapAccess
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrBitmapAccess (emuptr bitmapAddress, emuptr address, long size, Bool forRead)
+{
+ if (::ReportUIMgrDataAccess ())
+ {
+ // Set the %window message variable.
+
+ string asString (::PrvAsHex8 (bitmapAddress));
+ Errors::SetParameter ("%bitmap", asString.c_str ());
+
+ // Set the %field and %function variables.
+
+ EmAssert (address >= bitmapAddress);
+
+ size_t offset = address - bitmapAddress;
+ const char* fieldName = NULL;
+ const char* function = NULL;
+
+ ::PrvLookupField (kBitmapTypeV2Table, offset, fieldName, function);
+
+ Errors::SetParameter ("%field", fieldName);
+
+ Errors::ReportErrAccessCommon (kStr_ErrBitmapAccess, kException_BusErr, 0, address, size, forRead);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrProscribedFunction
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrProscribedFunction (const SystemCallContext& context)
+{
+ if (::ReportProscribedFunction ())
+ {
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %function_name message variable.
+
+ string asString (::GetTrapName (context, true));
+ Errors::SetParameter ("%function_name", asString.c_str ());
+
+ // Set the %reason message variable.
+
+ string asString2 (::PrvGetProscribedReason (context));
+ Errors::SetParameter ("%reason", asString2.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrProscribedFunction, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrStepSpy
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrStepSpy (emuptr writeAddress,
+ int writeBytes,
+ emuptr ssAddress,
+ uint32 ssValue,
+ uint32 newValue)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %op message variable.
+
+ string operation (Platform::GetString (kStr_WroteTo));
+ Errors::SetParameter ("%op", operation);
+
+ // Set the %mem message variable.
+
+ string asString1 (::PrvAsHex8 (writeAddress));
+ Errors::SetParameter ("%mem", asString1.c_str ());
+
+ // Set the %write_bytes message variable.
+
+ string asString2 (::PrvAsDecimal (writeBytes));
+ Errors::SetParameter ("%write_bytes", asString2.c_str ());
+
+ // Set the %ss_address message variable.
+
+ string asString3 (::PrvAsHex8 (ssAddress));
+ Errors::SetParameter ("%ss_address", asString3.c_str ());
+
+ // Set the %old_value message variable.
+
+ string asString4 (::PrvAsHex8 (ssValue));
+ Errors::SetParameter ("%old_value", asString4.c_str ());
+
+ // Set the %new_value message variable.
+
+ string asString5 (::PrvAsHex8 (newValue));
+ Errors::SetParameter ("%new_value", asString5.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrStepSpy, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrWatchpoint
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrWatchpoint (emuptr writeAddress,
+ int writeBytes,
+ emuptr watchAddress,
+ uint32 watchBytes)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %op message variable.
+
+ string operation (Platform::GetString (kStr_WroteTo));
+ Errors::SetParameter ("%op", operation);
+
+ // Set the %mem message variable.
+
+ string asString1 (::PrvAsHex8 (writeAddress));
+ Errors::SetParameter ("%mem", asString1.c_str ());
+
+ // Set the %write_bytes message variable.
+
+ string asString2 (::PrvAsDecimal (writeBytes));
+ Errors::SetParameter ("%write_bytes", asString2.c_str ());
+
+ // Set the %watch_start message variable.
+
+ string asString3 (::PrvAsHex8 (watchAddress));
+ Errors::SetParameter ("%watch_start", asString3.c_str ());
+
+ // Set the %watch_end message variable.
+
+ string asString4 (::PrvAsHex8 (watchAddress + watchBytes));
+ Errors::SetParameter ("%watch_end", asString4.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrWatchpoint, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors:ReportErrSysFatalAlert
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrSysFatalAlert (const char* appMsg)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %message message variable.
+
+ Errors::SetParameter ("%message", appMsg);
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrSysFatalAlert, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors:ReportErrDbgMessage
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrDbgMessage (const char* appMsg)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %message message variable.
+
+ Errors::SetParameter ("%message", appMsg);
+
+ // Show the dialog.
+
+ Errors::HandleDialog (kStr_ErrDbgMessage, kException_SoftBreak,
+ kDlgFlags_Continue_DEBUG_Reset, false);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrAccessCommon
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrAccessCommon (StrCode strIndex, ExceptionNumber excNum, int flags,
+ emuptr address, long size, Bool forRead)
+{
+ UNUSED_PARAM(size);
+
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %op message variable.
+
+ string operation (Platform::GetString (forRead ? kStr_ReadFrom : kStr_WroteTo));
+ Errors::SetParameter ("%op", operation);
+
+ // Set the %mem message variable.
+
+ string asString (::PrvAsHex8 (address));
+ Errors::SetParameter ("%mem", asString.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (strIndex, excNum,
+ ::PrvButtonFlags (flags),
+ ::PrvEnterDebuggerFirst (flags));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrObjectCommon
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrObjectCommon (StrCode strIndex, ExceptionNumber excNum, int flags,
+ uint16 id, const EmRect& r)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %obj_id message variable.
+
+ {
+ string asString (::PrvAsDecimal (id));
+ Errors::SetParameter ("%obj_id", asString.c_str ());
+ }
+
+ // Set the %left, %top, %right, and %bottom message variables.
+
+ {
+ string asString (::PrvAsDecimal (r.fLeft));
+ Errors::SetParameter ("%left", asString.c_str ());
+ }
+
+ {
+ string asString (::PrvAsDecimal (r.fTop));
+ Errors::SetParameter ("%top", asString.c_str ());
+ }
+
+ {
+ string asString (::PrvAsDecimal (r.fRight));
+ Errors::SetParameter ("%right", asString.c_str ());
+ }
+
+ {
+ string asString (::PrvAsDecimal (r.fBottom));
+ Errors::SetParameter ("%bottom", asString.c_str ());
+ }
+
+ // Show the dialog.
+
+ Errors::HandleDialog (strIndex, excNum,
+ ::PrvButtonFlags (flags),
+ ::PrvEnterDebuggerFirst (flags));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrOpcodeCommon
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrOpcodeCommon (StrCode strIndex, ExceptionNumber excNum, int flags, uint16 opcode)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Set the %ins message variable.
+
+ string asString (::PrvAsHex4 (opcode));
+ Errors::SetParameter ("%ins", asString.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (strIndex, excNum,
+ ::PrvButtonFlags (flags),
+ ::PrvEnterDebuggerFirst (flags));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrStackCommon
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrStackCommon (StrCode strIndex, ExceptionNumber excNum, int flags)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Generate the stack crawl information.
+
+ emuptr oldStackLow = gCPU->GetSP ();
+ EmStackFrameList stackCrawl;
+ EmPalmOS::GenerateStackCrawl (stackCrawl);
+
+ string stackCrawlString;
+
+ stackCrawlString = ::StackCrawlString (stackCrawl, 200, true, oldStackLow);
+
+ // Set the %sc message variable.
+
+ Errors::SetParameter ("%sc", stackCrawlString.c_str ());
+
+ // Show the dialog.
+
+ Errors::HandleDialog (strIndex, excNum,
+ ::PrvButtonFlags (flags),
+ ::PrvEnterDebuggerFirst (flags));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReportErrCommon
+// ---------------------------------------------------------------------------
+
+void Errors::ReportErrCommon (StrCode strIndex, ExceptionNumber excNum, int flags)
+{
+ // Set the %app message variable.
+
+ Errors::SetStandardParameters ();
+
+ // Show the dialog.
+
+ Errors::HandleDialog (strIndex, excNum,
+ ::PrvButtonFlags (flags),
+ ::PrvEnterDebuggerFirst (flags));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors:ReportErrCommPort
+// ---------------------------------------------------------------------------
+
+EmDlgItemID Errors::ReportErrCommPort (string errString)
+{
+ Errors::SetParameter ("%transport", errString);
+ string commString = Errors::ReplaceParameters (kStr_CommPortError);
+
+ EmDlgItemID button = Errors::DoDialog (commString.c_str (),
+ kDlgFlags_OK, -1);
+
+ return button;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors:ReportErrSockets
+// ---------------------------------------------------------------------------
+
+EmDlgItemID Errors::ReportErrSockets (string errString)
+{
+ Errors::SetParameter ("%transport", errString);
+ string socketsString = Errors::ReplaceParameters (kStr_SocketsError);
+
+ EmDlgItemID button = Errors::DoDialog (socketsString.c_str (),
+ kDlgFlags_OK, -1);
+
+ return button;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::SetParameter
+// ---------------------------------------------------------------------------
+// Add a user-supplied substitution rule. Parameters are deleted after they
+// are used (by making a call to ReportMessage), so they need to be
+// re-established after every call to that function.
+
+void Errors::SetParameter (const string& key, const string& value)
+{
+ ClearParameter (key);
+ gUserParameters.push_back (key);
+ gUserParameters.push_back (value);
+}
+
+void Errors::SetParameter (const string& key, const char* value)
+{
+ SetParameter (key, string (value));
+}
+
+void Errors::SetParameter (const string& key, const unsigned char* value)
+{
+ SetParameter (key, string ((char*) &value[1], value[0]));
+}
+
+void Errors::SetParameter (const string& key, long value)
+{
+ char buffer[20];
+ sprintf (buffer, "%ld", value);
+
+ SetParameter (key, string (buffer));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ClearParameter
+// ---------------------------------------------------------------------------
+// Remove a user-supplied substitution rule.
+
+void Errors::ClearParameter (const string& key)
+{
+ long index = (long) gUserParameters.size () - 2;
+
+ while (index >= 0)
+ {
+ if (gUserParameters[index] == key)
+ {
+ gUserParameters.erase (gUserParameters.begin () + index,
+ gUserParameters.begin () + index + 2);
+ break;
+ }
+
+ index -= 2;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ClearAllParameters
+// ---------------------------------------------------------------------------
+// Remove a user-supplied substitution rule.
+
+void Errors::ClearAllParameters (void)
+{
+ gUserParameters.clear ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::SetErrorParameters
+// ---------------------------------------------------------------------------
+
+Bool Errors::SetErrorParameters (StrCode operation, ErrCode error, StrCode recovery)
+{
+ // Add %operation, %reason, and %recovery entries to our parameter
+ // list in such a way that they appear at the start of the list
+ // in that order. That way, if any of the replacement strings
+ // contain parameters to be replaced, they can be replaced by
+ // user-defined values.
+
+ string s;
+
+ // Add the error number as a possible substitution value.
+
+ ErrCode errCode = error;
+ if (::IsPalmError (errCode))
+ {
+ errCode = ::ConvertToPalmError (errCode);
+
+ // For Palm OS errors, try coming up with a description of the error.
+
+ s = Platform::GetString (kStr_PalmOSErrorBase + errCode);
+
+ if (s[0] == '<')
+ {
+ s = Platform::GetString (kStr_UnknownErrorCode);
+ }
+
+ Errors::SetParameter ("%error_desc", s);
+ }
+
+ char errCodeString[20];
+ sprintf (errCodeString, "0x%04X", (int) errCode);
+ Errors::SetParameter ("%error", errCodeString);
+
+ // If the caller didn't provide a recovery string ID, let's try to get
+ // appropriate for this error code.
+
+ if (recovery == 0)
+ {
+ recovery = Errors::GetIDForRecovery (error);
+ }
+
+ // If we (now) have a recovery string ID, use it to get the string
+ // and add it to our parameter list.
+
+ if (recovery)
+ {
+ s = Platform::GetString (recovery);
+ gUserParameters.insert (gUserParameters.begin (), s);
+ gUserParameters.insert (gUserParameters.begin (), "%recovery");
+ }
+
+ // Get a string for the error code provided. If we don't have a canned
+ // string, create a generic string that includes the error number.
+
+ StrCode errID = Errors::GetIDForError (error);
+ s = Platform::GetString (errID);
+ gUserParameters.insert (gUserParameters.begin (), s);
+ gUserParameters.insert (gUserParameters.begin (), "%reason");
+
+ // Finally, add the operation string to the parameter list.
+
+ s = Platform::GetString (operation);
+ gUserParameters.insert (gUserParameters.begin (), s);
+ gUserParameters.insert (gUserParameters.begin (), "%operation");
+
+ return recovery != 0; // Return whether or not there's a recovery string in
+ // the parameter list. The caller will want to know
+ // this so that it can provide the right template for it.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::SetStandardParameters
+// ---------------------------------------------------------------------------
+// Set the following three parameters for text substitution:
+//
+// %Application = current application name, or "The current application"
+// %application = current application name, or "the current application"
+// %version = current application version, or "(unknown version)"
+
+void Errors::SetStandardParameters (void)
+{
+ string appNameUC;
+ string appNameLC;
+ string version;
+
+ Errors::GetAppName (appNameUC, appNameLC);
+ Errors::GetAppVersion (version);
+
+ Errors::SetParameter ("%App", appNameUC + " (" + version + ")");
+ Errors::SetParameter ("%app", appNameLC + " (" + version + ")");
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::HandleDialog
+// ---------------------------------------------------------------------------
+// Display the dialog, handling button selections in a standard fashion:
+//
+// Continue:
+// Exit this function. The caller will then be able to
+// continue without further incident.
+//
+// Debug:
+// Attempt to enter the debugger. If the attempt fails,
+// show the dialog again.
+//
+// Reset:
+// Throw an exception that causes a reset at the top of
+// the CPU loop.
+//
+// Next Gremlin:
+// Throw an exception that causes the next gremlin
+// to be loaded at the top of the CPU loop.
+
+void Errors::HandleDialog (StrCode messageID,
+ ExceptionNumber excNum,
+ EmCommonDialogFlags flags,
+ Bool enterDebuggerFirst)
+{
+ // Expand the template here so that we can get the string in its final
+ // form. If we were to let Errors::DoDialog do the expansion, it would
+ // form the string locally to itself, discarding the template parameters
+ // in the process. If we then need to loop because we were unable to
+ // enter the debugger, Errors::DoDialog would not be able to reform
+ // the message because the template parameters are now gone. So form
+ // the message here and hold onto it.
+
+ string msgTemplate (Platform::GetString (messageID));
+ string msg (Errors::ReplaceParameters (msgTemplate, gUserParameters));
+
+ // If this error occurred while nested (that is, while Poser itself
+ // is calling into the ROM as a subroutine), then we can't really
+ // recover from that. At the very least, we don't need to bother
+ // users with messages about our own mistakes. So simply say
+ // that an internal error occurred and that we're now about to reset.
+
+ if (gSession && gSession->IsNested ())
+ {
+ EmExceptionReset e (kResetSoft);
+ e.SetMessage (msg.c_str ());
+ throw e;
+ }
+
+ // Insert a note into the event stream that an error occurred.
+
+ EmEventPlayback::RecordErrorEvent ();
+
+ // If we reach this point, and minimization is taking place, then the
+ // error was generated on purpose. Instead of warning the user, silently
+ // switch to the next minimizer.
+
+ if (EmMinimize::IsOn ())
+ {
+ if (LogGremlins ())
+ {
+ LogAppendMsg ("Calling EmMinimize::ErrorOccurred after encountering an error");
+ }
+
+ EmEventOutput::ErrorOccurred (msg);
+ EmMinimize::ErrorOccurred ();
+
+ return;
+ }
+
+ EmDlgItemID button;
+
+ do
+ {
+ if (enterDebuggerFirst)
+ {
+ button = kDlgItemDebug;
+ enterDebuggerFirst = false;
+ }
+ else
+ {
+ button = Errors::DoDialog (msg.c_str (), flags, messageID);
+
+ // If we show a dialog, then the user has already been told
+ // what's gone wrong. They don't need CodeWarrior to tell
+ // them again. Besides, CodeWarrior often puts up dialogs
+ // with "missing" characters in them. To inhibit CodeWarrior
+ // from showing a dialog, we can change the exception to
+ // a TRAP 0 exception.
+
+ excNum = kException_SoftBreak;
+ }
+
+ if (button == kDlgItemDebug)
+ {
+ // If the user clicked on Debug, simulate a breakpoint in order to
+ // get us into the debugger.
+
+ if (Debug::EnterDebugger (excNum, NULL) == errNone)
+ {
+ EmExceptionEnterDebugger e;
+ throw e;
+ }
+ }
+
+ else if (button == kDlgItemReset)
+ {
+ // Find out what kind of reset.
+
+ EmResetType type;
+ if (EmDlg::DoReset (type) == kDlgItemOK)
+ {
+ EmExceptionReset e (type);
+ throw e;
+ }
+ }
+
+ else if (button == kDlgItemNextGremlin)
+ {
+ EmExceptionNextGremlin e;
+ throw e;
+ }
+ } while (button != kDlgItemContinue);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::DoDialog
+// ---------------------------------------------------------------------------
+// Displays a dialog box with the given message and according to
+// the given flags. Returns which button was clicked.
+
+EmDlgItemID Errors::DoDialog (StrCode messageID, EmCommonDialogFlags flags)
+{
+ string msg (Platform::GetString (messageID));
+ return Errors::DoDialog (msg.c_str (), flags, messageID);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::DoDialog
+// ---------------------------------------------------------------------------
+// Displays a dialog box with the given message and according to
+// the given flags. Returns which button was clicked.
+
+EmDlgItemID Errors::DoDialog (const char* msg, EmCommonDialogFlags flags, StrCode messageID)
+{
+ string msgStr (msg);
+ msgStr = Errors::ReplaceParameters (msgStr, gUserParameters);
+
+ // If this error occurred while nested (that is, while Poser itself
+ // is calling into the ROM as a subroutine), then we can't really
+ // recover from that. At the very least, we don't need to bother
+ // users with messages about our own mistakes. So simply say
+ // that an internal error occurred and that we're now about to reset.
+
+ if (gSession && gSession->IsNested ())
+ {
+ EmExceptionReset e (kResetSoft);
+ e.SetMessage (msgStr.c_str ());
+ throw e;
+ }
+
+ // See if this is a fatal or non-fatal message (also called "error"
+ // or "warning"). The message is non-fatal if the first button
+ // is a visible, enabled Continue button.
+
+ uint8 button0 = GET_BUTTON (0, flags);
+ Bool isFatal = !((button0 & kButtonMask) == kDlgItemContinue &&
+ (button0 & (kButtonVisible | kButtonEnabled)) == (kButtonVisible | kButtonEnabled));
+
+ // Notify Hordes of the error so that it can keep stats.
+
+ Hordes::RecordErrorStats (messageID);
+
+ // Set flags governing Poser's return value.
+
+ if (isFatal)
+ gErrorHappened = true;
+ else
+ gWarningHappened = true;
+
+ // If we are logging this kind of message, then we can further check
+ // to see what kind of other actions to carry out. Otherwise, we
+ // display the error message.
+
+ if (gEmuPrefs->LogMessage (isFatal))
+ {
+ // Log the error message.
+
+ const char* typeStr = isFatal ? "ERROR" : "WARNING";
+
+ LogAppendMsg ("=== %s: ********************************************************************************", typeStr);
+ LogAppendMsg ("=== %s: %s", typeStr, msgStr.c_str ());
+ LogAppendMsg ("=== %s: ********************************************************************************", typeStr);
+
+ LogDump ();
+
+ // Determine what else we should do: quit the emulator,
+ // continue on as if the user had pressed the Continue
+ // button, switch to the next Gremlin in a Horde, or
+ // display the message in a dialog.
+
+ if (gEmuPrefs->ShouldQuit (isFatal))
+ {
+ EmAssert (gApplication);
+ gApplication->ScheduleQuit ();
+
+ if (Hordes::IsOn ())
+ {
+ return kDlgItemNextGremlin;
+ }
+
+ return kDlgItemContinue;
+ }
+ else if (gEmuPrefs->ShouldContinue (isFatal))
+ {
+ return kDlgItemContinue;
+ }
+ else if (gEmuPrefs->ShouldNextGremlin (isFatal))
+ {
+ return kDlgItemNextGremlin;
+ }
+
+ // ...else, drop through to show the dialog
+ }
+
+ // If we got here, it's either because logging is off for this
+ // type of message (in which case, force the user to see the
+ // message, or else they'd completely miss it), or their error
+ // handling option said to show it in a dialog.
+
+ return EmDlg::DoCommonDialog (msgStr, flags);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReplaceParameters
+// ---------------------------------------------------------------------------
+// Take a string template (that is, a string containing text interspersed
+// with "parameters" (of the form "%parameterName") that need to be
+// replaced) and replace the parameters with their final values.
+
+string Errors::ReplaceParameters (StrCode templateID)
+{
+ return Errors::ReplaceParameters (templateID, gUserParameters);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReplaceParameters
+// ---------------------------------------------------------------------------
+// Take a string template (that is, a string containing text interspersed
+// with "parameters" (of the form "%parameterName") that need to be
+// replaced) and replace the parameters with their final values.
+
+string Errors::ReplaceParameters (StrCode templateID, ParamList& params)
+{
+ string templ = Platform::GetString (templateID);
+ return Errors::ReplaceParameters (templ, params);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ReplaceParameters
+// ---------------------------------------------------------------------------
+// Take a string template (that is, a string containing text interspersed
+// with "parameters" (of the form "%parameterName") that need to be
+// replaced) and replace the parameters with their final values.
+//
+// Parameters are replaced one at a time, according to their position in
+// the ParamList. The first parameter is first fully replaced in the
+// string template, in such a manner than recursion does not occur (that
+// is, if a parameter value itself include a parameter with the same
+// name, that embedded parameter is not also replaced).
+//
+// The next parameter is then pulled off of ParamList and treated the
+// same way. This time, any new parameters introduced during the previous
+// substitution pass can be replaced.
+//
+// This approach allows for sequences like the following:
+//
+// string template "Could not %operation because %reason."
+//
+// parameter list: "%operation" "save the file Ò%extraÓ"
+// "%reason" "the disk is full"
+// "%extra" "FooBlitzky"
+//
+// result: "Could not save the file ÒFooBlitzky" because the disk is full."
+//
+// If the "%extra" in "save the file Ò%extraÓ" had been "%operation", it
+// would have stayed that way and never been replaced (unless "%operation"
+// appeared in the parameter list again).
+
+string Errors::ReplaceParameters (const string& templ, ParamList& params)
+{
+ string result (templ);
+
+ ParamList::iterator paramIter;
+
+ for (paramIter = params.begin (); paramIter != params.end (); )
+ {
+ string key = *paramIter++;
+ string value = *paramIter++;
+
+ result = ::ReplaceString (result, key, value);
+ }
+
+ Errors::ClearAllParameters ();
+
+ return result;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Throw
+// ---------------------------------------------------------------------------
+
+#ifndef Throw_
+#define Throw_(x) throw x
+#endif
+
+void Errors::Throw (ErrCode error)
+{
+ Throw_ (error);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ThrowIfError
+// ---------------------------------------------------------------------------
+
+void Errors::ThrowIfError (ErrCode error)
+{
+ if (error)
+ {
+ Errors::Throw (error);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ThrowIfPalmError
+// ---------------------------------------------------------------------------
+
+void Errors::ThrowIfPalmError (Err error)
+{
+ if (error)
+ {
+ Errors::Throw (::ConvertFromPalmError (error));
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ThrowIfStdCError
+// ---------------------------------------------------------------------------
+
+void Errors::ThrowIfStdCError (int error)
+{
+ if (error)
+ {
+ Errors::Throw (::ConvertFromStdCError (error));
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::ThrowIfNULL
+// ---------------------------------------------------------------------------
+
+void Errors::ThrowIfNULL (void* p)
+{
+ if (!p)
+ {
+ Errors::Throw (kError_OutOfMemory);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::Scram
+// ---------------------------------------------------------------------------
+
+void Errors::Scram (void)
+{
+ Errors::Throw (kError_NoError);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::GetIDForError
+// ---------------------------------------------------------------------------
+
+int Errors::GetIDForError (ErrCode error)
+{
+ if (::IsPalmError (error))
+ {
+ Err err = ::ConvertToPalmError (error);
+ switch (err)
+ {
+ case dmErrDatabaseOpen: return kStr_DmErrDatabaseOpen;
+ case memErrNotEnoughSpace: return kStr_MemErrNotEnoughSpace;
+ default: return kStr_GenericPalmError;
+ }
+ }
+ else if (::IsStdCError (error))
+ {
+ int status = ::ConvertToPalmError (error);
+ switch (status)
+ {
+#if defined (ENOENT)
+ case ENOENT: return kStr_FileNotFound;
+#endif
+
+#if defined (ENOMEM)
+ case ENOMEM: return kStr_MemFull;
+#endif
+
+#if defined (EACCES)
+ case EACCES: return kStr_FileLocked;
+#endif
+
+#if defined (ECANCELED)
+ case ECANCELED: return kStr_UserCancel;
+#endif
+
+#if defined (EEXIST)
+ case EEXIST: return kStr_DuplicateFileName;
+#endif
+
+#if defined (ENFILE)
+ case ENFILE: return kStr_TooManyFilesOpen;
+#endif
+
+#if defined (EMFILE)
+ case EMFILE: return kStr_TooManyFilesOpen;
+#endif
+
+#if defined (ENOSPC)
+ case ENOSPC: return kStr_DiskFull;
+#endif
+
+#if defined (EROFS)
+ case EROFS: return kStr_DiskWriteProtected;
+#endif
+ default: return kStr_GenericError;
+ }
+ }
+ else if (::IsEmuError (error))
+ {
+ switch (error)
+ {
+ case kError_OutOfMemory: return kStr_MemFull;
+
+ case kError_BadROM: return kStr_BadROM;
+ case kError_WrongROMForType: return kStr_WrongROMForType;
+ case kError_UnsupportedROM: return kStr_UnsupportedROM;
+ case kError_InvalidDevice: return kStr_InvalidDevice;
+ case kError_InvalidSessionFile: return kStr_InvalidSession;
+ case kError_InvalidConfiguration: return kStr_InvalidConfiguration;
+
+ case kError_CantDownloadROM_BadBaudRate: return kStr_GenericError;
+ case kError_CantDownloadROM_SerialPortBusy: return kStr_GenericError;
+ case kError_CantDownloadROM_Generic: return kStr_GenericError;
+
+ case kError_OnlySameType: return kStr_OnlySameType;
+ case kError_OnlyOnePSF: return kStr_OnlyOnePSF;
+ case kError_OnlyOneROM: return kStr_OnlyOneROM;
+ case kError_UnknownType: return kStr_UnknownType;
+
+ case kError_BadDB_NameNotNULLTerminated: return kStr_NameNotNULLTerminated;
+ case kError_BadDB_NameNotPrintable: return kStr_NameNotPrintable;
+ case kError_BadDB_FileTooSmall: return kStr_FileTooSmall;
+ case kError_BadDB_nextRecordListIDNonZero: return kStr_nextRecordListIDNonZero;
+ case kError_BadDB_ResourceTooSmall: return kStr_ResourceTooSmall;
+ case kError_BadDB_RecordTooSmall: return kStr_RecordTooSmall;
+ case kError_BadDB_ResourceOutOfRange: return kStr_ResourceOutOfRange;
+ case kError_BadDB_RecordOutOfRange: return kStr_RecordOutOfRange;
+ case kError_BadDB_OverlappingResource: return kStr_OverlappingResource;
+ case kError_BadDB_OverlappingRecord: return kStr_OverlappingRecord;
+ case kError_BadDB_ResourceMemError: return kStr_ResourceMemError;
+ case kError_BadDB_RecordMemError: return kStr_RecordMemError;
+ case kError_BadDB_AppInfoMemError: return kStr_AppInfoMemError;
+ case kError_BadDB_DuplicateResource: return kStr_DuplicateResource;
+
+ default: return kStr_GenericError;
+ }
+ }
+
+ return Platform::GetIDForError (error);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::GetIDForRecovery
+// ---------------------------------------------------------------------------
+
+int Errors::GetIDForRecovery (ErrCode error)
+{
+ if (::IsPalmError (error))
+ {
+ switch (::ConvertToPalmError (error))
+ {
+ default:
+ return 0;
+ }
+ }
+ else if (::IsEmuError (error))
+ {
+ switch (error)
+ {
+ default:
+ return 0;
+ }
+ }
+
+ return Platform::GetIDForRecovery (error);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::GetAppName
+// ---------------------------------------------------------------------------
+// Get the current application's name. If the name is not known, return
+// "Unknown application" and "unknown application".
+
+void Errors::GetAppName (string& appNameUC, string& appNameLC)
+{
+ EmuAppInfo appInfo = EmPatchState::GetCurrentAppInfo ();
+
+ if (strlen (appInfo.fName) > 0)
+ {
+ appNameUC = appInfo.fName;
+ appNameLC = appInfo.fName;
+ }
+ else
+ {
+ appNameUC = Platform::GetString (kStr_CurrentAppUC);
+ appNameLC = Platform::GetString (kStr_CurrentAppLC);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::GetAppVersion
+// ---------------------------------------------------------------------------
+// Get the current application's version. If the version cannot be
+// determined, return "(unknown version)".
+
+void Errors::GetAppVersion (string& appVersion)
+{
+ EmuAppInfo appInfo = EmPatchState::GetCurrentAppInfo ();
+
+ if (strlen (appInfo.fVersion) > 0)
+ {
+ appVersion = appInfo.fVersion;
+ }
+ else
+ {
+ appVersion = Platform::GetString (kStr_UnknownVersion);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::LooksLikeA5Access
+// ---------------------------------------------------------------------------
+
+Bool Errors::LooksLikeA5Access (emuptr address, long size, Bool forRead)
+{
+ UNUSED_PARAM (forRead);
+
+ // The OS sets the high bit of the A5 register when calling PilotMain
+ // with a launch code that doesn't allow global variable access.
+
+ emuptr A5 = gCPU68K->GetRegister (e68KRegID_A5);
+
+ if ((address & 0x80000000) == 0 || (A5 & 0x80000000) == 0)
+ return false;
+
+ emuptr strippedAddress = address & 0x7FFFFFFF;
+ emuptr strippedA5 = A5 & 0x7FFFFFFF;
+
+ // See if the stripped test address and the real A5 both reside in
+ // the dynamic heap.
+
+ if (!EmBankDRAM::ValidAddress (strippedA5, 1) ||
+ !EmBankDRAM::ValidAddress (strippedAddress, size))
+ return false;
+
+ // Now see if they both point into the same heap.
+
+ const EmPalmHeap* heap1 = EmPalmHeap::GetHeapByPtr (strippedA5);
+ const EmPalmHeap* heap2 = EmPalmHeap::GetHeapByPtr (strippedAddress);
+
+ if ((heap1 == NULL) || (heap2 == NULL) || (heap1 != heap2))
+ return false;
+
+ // Now see if they both point into the same chunk.
+
+ const EmPalmChunk* chunk1 = heap1->GetChunkBodyContaining (strippedA5);
+ const EmPalmChunk* chunk2 = heap1->GetChunkBodyContaining (strippedAddress);
+
+ if ((chunk1 == NULL) || (chunk2 == NULL) || (chunk1 != chunk2))
+ return false;
+
+ // All tests pass, so report that it looks like an attempt
+ // to utilize A5 in a verbotten situation.
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvLookupField
+// ---------------------------------------------------------------------------
+
+void PrvLookupField (const EmFieldLookup* table, size_t offset,
+ const char*& fieldName, const char*& function)
+{
+ if (!table || table->fType == 2)
+ return;
+
+ fieldName = NULL;
+ function = NULL;
+
+ // Find the end of the table;
+
+ const EmFieldLookup* p = table;
+ while (p->fType != 2)
+ ++p;
+
+ // Now walk the table backwards, looking for the first (that is, last)
+ // entry with an offset greater than or equal to the one we're looking for.
+
+ while (--p >= table)
+ {
+ if (offset >= p->fOffset)
+ {
+ if (p->fType == 1)
+ {
+ const EmFieldLookup* newTable = p->fNextTable;
+ size_t newOffset = offset - p->fOffset;
+
+ ::PrvLookupField (newTable, newOffset, fieldName, function);
+
+ if (fieldName)
+ {
+ return;
+ }
+ }
+
+ fieldName = p->fFieldName;
+ function = p->fFunction;
+
+ return;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetProscribedReason
+// ---------------------------------------------------------------------------
+
+string PrvGetProscribedReason (const SystemCallContext& context)
+{
+ string result;
+ int reason = ::GetProscribedReason (context);
+
+ switch (reason)
+ {
+ case kProscribedDocumentedSystemUseOnly:
+ case kProscribedUndocumentedSystemUseOnly:
+ case kProscribedKernelUseOnly:
+ case kProscribedGhost:
+ case kProscribedSystemUseOnlyAnyway:
+ case kProscribedRare:
+ result = Platform::GetString (kStr_SystemUseOnly);
+ break;
+
+ case kProscribedObsolete:
+ result = Platform::GetString (kStr_Obsolete);
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ return result;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErr
+// ---------------------------------------------------------------------------
+
+EmDeferredErr::EmDeferredErr (void)
+{
+}
+
+EmDeferredErr::~EmDeferredErr (void)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrAccessCommon
+// ---------------------------------------------------------------------------
+
+EmDeferredErrAccessCommon::EmDeferredErrAccessCommon (emuptr address, long size, Bool forRead) :
+ EmDeferredErr (),
+ fAddress (address),
+ fSize (size),
+ fForRead (forRead)
+{
+}
+
+EmDeferredErrAccessCommon::~EmDeferredErrAccessCommon (void)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrLowMemory
+// ---------------------------------------------------------------------------
+
+EmDeferredErrLowMemory::EmDeferredErrLowMemory (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrLowMemory::~EmDeferredErrLowMemory (void)
+{
+}
+
+void EmDeferredErrLowMemory::Do (void)
+{
+ Errors::ReportErrLowMemory (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrSystemGlobals
+// ---------------------------------------------------------------------------
+
+EmDeferredErrSystemGlobals::EmDeferredErrSystemGlobals (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrSystemGlobals::~EmDeferredErrSystemGlobals (void)
+{
+}
+
+void EmDeferredErrSystemGlobals::Do (void)
+{
+ Errors::ReportErrSystemGlobals (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrScreen
+// ---------------------------------------------------------------------------
+
+EmDeferredErrScreen::EmDeferredErrScreen (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrScreen::~EmDeferredErrScreen (void)
+{
+}
+
+void EmDeferredErrScreen::Do (void)
+{
+ Errors::ReportErrScreen (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrHardwareRegisters
+// ---------------------------------------------------------------------------
+
+EmDeferredErrHardwareRegisters::EmDeferredErrHardwareRegisters (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrHardwareRegisters::~EmDeferredErrHardwareRegisters (void)
+{
+}
+
+void EmDeferredErrHardwareRegisters::Do (void)
+{
+ Errors::ReportErrHardwareRegisters (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrROM
+// ---------------------------------------------------------------------------
+
+EmDeferredErrROM::EmDeferredErrROM (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrROM::~EmDeferredErrROM (void)
+{
+}
+
+void EmDeferredErrROM::Do (void)
+{
+ Errors::ReportErrROM (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrMemMgrStructures
+// ---------------------------------------------------------------------------
+
+EmDeferredErrMemMgrStructures::EmDeferredErrMemMgrStructures (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrMemMgrStructures::~EmDeferredErrMemMgrStructures (void)
+{
+}
+
+void EmDeferredErrMemMgrStructures::Do (void)
+{
+ Errors::ReportErrMemMgrStructures (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrMemMgrSemaphore
+// ---------------------------------------------------------------------------
+
+EmDeferredErrMemMgrSemaphore::EmDeferredErrMemMgrSemaphore (void) :
+ EmDeferredErr ()
+{
+}
+
+EmDeferredErrMemMgrSemaphore::~EmDeferredErrMemMgrSemaphore (void)
+{
+}
+
+void EmDeferredErrMemMgrSemaphore::Do (void)
+{
+ Errors::ReportErrMemMgrSemaphore ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrFreeChunk
+// ---------------------------------------------------------------------------
+
+EmDeferredErrFreeChunk::EmDeferredErrFreeChunk (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrFreeChunk::~EmDeferredErrFreeChunk (void)
+{
+}
+
+void EmDeferredErrFreeChunk::Do (void)
+{
+ Errors::ReportErrFreeChunk (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrUnlockedChunk
+// ---------------------------------------------------------------------------
+
+EmDeferredErrUnlockedChunk::EmDeferredErrUnlockedChunk (emuptr address, long size, Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead)
+{
+}
+
+EmDeferredErrUnlockedChunk::~EmDeferredErrUnlockedChunk (void)
+{
+}
+
+void EmDeferredErrUnlockedChunk::Do (void)
+{
+ Errors::ReportErrUnlockedChunk (fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrLowStack
+// ---------------------------------------------------------------------------
+
+EmDeferredErrLowStack::EmDeferredErrLowStack (emuptr stackLow,
+ emuptr stackPointer,
+ emuptr stackHigh,
+ emuptr address,
+ long size,
+ Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead),
+ fStackLow (stackLow),
+ fStackPointer (stackPointer),
+ fStackHigh (stackHigh)
+{
+}
+
+EmDeferredErrLowStack::~EmDeferredErrLowStack (void)
+{
+}
+
+void EmDeferredErrLowStack::Do (void)
+{
+ Errors::ReportErrLowStack (fStackLow, fStackPointer, fStackHigh,
+ fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrStackFull
+// ---------------------------------------------------------------------------
+
+EmDeferredErrStackFull::EmDeferredErrStackFull (void) :
+ EmDeferredErr ()
+{
+}
+
+EmDeferredErrStackFull::~EmDeferredErrStackFull (void)
+{
+}
+
+void EmDeferredErrStackFull::Do (void)
+{
+ Errors::ReportErrStackFull ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrObjectCommon
+// ---------------------------------------------------------------------------
+
+EmDeferredErrObjectCommon::EmDeferredErrObjectCommon (uint16 id, const EmRect& rect) :
+ EmDeferredErr (),
+ fID (id),
+ fRect (rect)
+{
+}
+
+EmDeferredErrObjectCommon::~EmDeferredErrObjectCommon (void)
+{
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrSizelessObject
+// ---------------------------------------------------------------------------
+
+EmDeferredErrSizelessObject::EmDeferredErrSizelessObject (uint16 id, const EmRect& rect) :
+ EmDeferredErrObjectCommon (id, rect)
+{
+}
+
+EmDeferredErrSizelessObject::~EmDeferredErrSizelessObject (void)
+{
+}
+
+void EmDeferredErrSizelessObject::Do (void)
+{
+ Errors::ReportErrSizelessObject (fID, fRect);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrOffscreenObject
+// ---------------------------------------------------------------------------
+
+EmDeferredErrOffscreenObject::EmDeferredErrOffscreenObject (uint16 id, const EmRect& rect) :
+ EmDeferredErrObjectCommon (id, rect)
+{
+}
+
+EmDeferredErrOffscreenObject::~EmDeferredErrOffscreenObject (void)
+{
+}
+
+void EmDeferredErrOffscreenObject::Do (void)
+{
+ Errors::ReportErrOffscreenObject (fID, fRect);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrFormAccess
+// ---------------------------------------------------------------------------
+
+EmDeferredErrFormAccess::EmDeferredErrFormAccess (emuptr formAddress,
+ emuptr address,
+ long size,
+ Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead),
+ fFormAddress (formAddress)
+{
+}
+
+EmDeferredErrFormAccess::~EmDeferredErrFormAccess (void)
+{
+}
+
+void EmDeferredErrFormAccess::Do (void)
+{
+ Errors::ReportErrFormAccess (fFormAddress, fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrFormObjectAccess
+// ---------------------------------------------------------------------------
+
+EmDeferredErrFormObjectAccess::EmDeferredErrFormObjectAccess (emuptr objectAddress,
+ emuptr formAddress,
+ emuptr address,
+ long size,
+ Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead),
+ fObjectAddress (objectAddress),
+ fFormAddress (formAddress)
+{
+}
+
+EmDeferredErrFormObjectAccess::~EmDeferredErrFormObjectAccess (void)
+{
+}
+
+void EmDeferredErrFormObjectAccess::Do (void)
+{
+ Errors::ReportErrFormObjectAccess (fObjectAddress, fFormAddress, fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrWindowAccess
+// ---------------------------------------------------------------------------
+
+EmDeferredErrWindowAccess::EmDeferredErrWindowAccess (emuptr windowAddress,
+ emuptr address,
+ long size,
+ Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead),
+ fWindowAddress (windowAddress)
+{
+}
+
+EmDeferredErrWindowAccess::~EmDeferredErrWindowAccess (void)
+{
+}
+
+void EmDeferredErrWindowAccess::Do (void)
+{
+ Errors::ReportErrWindowAccess (fWindowAddress, fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrBitmapAccess
+// ---------------------------------------------------------------------------
+
+EmDeferredErrBitmapAccess::EmDeferredErrBitmapAccess (emuptr bitmapAddress,
+ emuptr address,
+ long size,
+ Bool forRead) :
+ EmDeferredErrAccessCommon (address, size, forRead),
+ fBitmapAddress (bitmapAddress)
+{
+}
+
+EmDeferredErrBitmapAccess::~EmDeferredErrBitmapAccess (void)
+{
+}
+
+void EmDeferredErrBitmapAccess::Do (void)
+{
+ Errors::ReportErrBitmapAccess (fBitmapAddress, fAddress, fSize, fForRead);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrProscribedFunction
+// ---------------------------------------------------------------------------
+
+EmDeferredErrProscribedFunction::EmDeferredErrProscribedFunction (const SystemCallContext& context) :
+ EmDeferredErr (),
+ fContext (context)
+{
+}
+
+EmDeferredErrProscribedFunction::~EmDeferredErrProscribedFunction (void)
+{
+}
+
+void EmDeferredErrProscribedFunction::Do (void)
+{
+ Errors::ReportErrProscribedFunction (fContext);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrStepSpy
+// ---------------------------------------------------------------------------
+
+EmDeferredErrStepSpy::EmDeferredErrStepSpy (emuptr writeAddress,
+ int writeBytes,
+ emuptr ssAddress,
+ uint32 ssValue,
+ uint32 newValue) :
+ EmDeferredErr (),
+ fWriteAddress (writeAddress),
+ fWriteBytes (writeBytes),
+ fSSAddress (ssAddress),
+ fSSValue (ssValue),
+ fNewValue (newValue)
+{
+}
+
+EmDeferredErrStepSpy::~EmDeferredErrStepSpy (void)
+{
+}
+
+void EmDeferredErrStepSpy::Do (void)
+{
+ Errors::ReportErrStepSpy (fWriteAddress, fWriteBytes, fSSAddress, fSSValue, fNewValue);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDeferredErrWatchpoint
+// ---------------------------------------------------------------------------
+
+EmDeferredErrWatchpoint::EmDeferredErrWatchpoint (emuptr writeAddress,
+ int writeBytes,
+ emuptr watchAddress,
+ uint32 watchBytes) :
+ EmDeferredErr (),
+ fWriteAddress (writeAddress),
+ fWriteBytes (writeBytes),
+ fWatchAddress (watchAddress),
+ fWatchBytes (watchBytes)
+{
+}
+
+EmDeferredErrWatchpoint::~EmDeferredErrWatchpoint (void)
+{
+}
+
+void EmDeferredErrWatchpoint::Do (void)
+{
+ Errors::ReportErrWatchpoint (fWriteAddress, fWriteBytes, fWatchAddress, fWatchBytes);
+}
diff --git a/SrcShared/ErrorHandling.h b/SrcShared/ErrorHandling.h
new file mode 100644
index 0000000..3b35695
--- /dev/null
+++ b/SrcShared/ErrorHandling.h
@@ -0,0 +1,515 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _ERRORHANDLING_H_
+#define _ERRORHANDLING_H_
+
+#include <vector>
+#include <string>
+
+#include "EmCPU68K.h" // ExceptionNumber
+#include "EmDlg.h" // EmCommonDialogFlags
+#include "EmRect.h" // ExceptionNumber
+
+
+class SessionFile;
+struct SystemCallContext;
+
+
+// ParamList contains a sequence of key/value pairs. The even-numbered
+// strings are the keys, and the odd-numbered strings are the values.
+// The key/value pairs are used in string template substitution. When
+// substitution needs to take place, the keys and values are pulled
+// out of the list one pair at a time. The template string is then
+// traversed, with each key being replaced by its value.
+//
+// Keys are typically of the form "%text" (with the "%" showing up in
+// both the key text and the string template text), but could actually
+// be in any form that is unique by convention.
+//
+// To create a parameter list, do something like the following:
+//
+// ParamList paramList;
+// paramList.push_back (string ("%foo"));
+// paramList.push_back (string ("bar"));
+// ... repeat as necessary ...
+
+typedef vector<string> ParamList;
+
+
+// Values passed to ReportInvalidPC.
+
+enum
+{
+ kUnmappedAddress,
+ kNotInCodeSegment,
+ kOddAddress
+};
+
+class Errors
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+
+ // These three functions check for the indicated error condition. If
+ // there is an error, they display a "Could not foo because bar." message
+ // in a dialog with an OK button. If an optional recovery string is
+ // provided, the message is "Could no foo because bar. Do this." message.
+ // If "throwAfter" is true, Errors::Scram is called after the dialog
+ // is dismissed.
+ //
+ // All of these functions bottleneck through DoDialog.
+ //
+ // "operation" and "recovery" are "kPart_Foo" values.
+ // "error" is Mac or Windows error number, or a kError_Foo value.
+ // "err" is a Palm OS error number.
+ // "p" is a pointer to be tested.
+
+ static void ReportIfError (StrCode operation, ErrCode error, StrCode recovery = 0, Bool throwAfter = true);
+ static void ReportIfPalmError (StrCode operation, Err err, StrCode recovery = 0, Bool throwAfter = true);
+ static void ReportIfNULL (StrCode operation, void* p, StrCode recovery = 0, Bool throwAfter = true);
+
+
+ // Report that the indicated error condition occurred. Messages are generally
+ // of the form "<Application> <version> just tried to <foo>. <More explanatory
+ // text>. Report this to the program author."
+
+ // Hardware Exceptions
+
+ static void ReportErrBusError (emuptr address, long size, Bool forRead);
+ static void ReportErrAddressError (emuptr address, long size, Bool forRead);
+ static void ReportErrIllegalInstruction (uint16 opcode);
+ static void ReportErrDivideByZero (void);
+ static void ReportErrCHKInstruction (void);
+ static void ReportErrTRAPVInstruction (void);
+ static void ReportErrPrivilegeViolation (uint16 opcode);
+ static void ReportErrTrace (void);
+ static void ReportErrATrap (uint16 opcode);
+ static void ReportErrFTrap (uint16 opcode);
+ static void ReportErrTRAPx (int exceptionNumber);
+
+ // Special cases to hardware exceptions
+
+ static void ReportErrStorageHeap (emuptr address, long size, Bool forRead);
+ static void ReportErrNoDrawWindow (emuptr address, long size, Bool forRead);
+ static void ReportErrNoGlobals (emuptr address, long size, Bool forRead);
+ static void ReportErrSANE (void);
+ static void ReportErrTRAP0 (void);
+ static void ReportErrTRAP8 (void);
+
+ // Fatal Poser-detected errors
+
+ static void ReportErrStackOverflow (void);
+ static void ReportErrUnimplementedTrap (const SystemCallContext&);
+ static void ReportErrInvalidRefNum (const SystemCallContext&);
+ static void ReportErrCorruptedHeap (ErrCode, emuptr);
+ static void ReportErrInvalidPC (emuptr address, int reason);
+
+ // Non-fatal Poser-detected errors
+
+ static void ReportErrLowMemory (emuptr address, long size, Bool forRead);
+ static void ReportErrSystemGlobals (emuptr address, long size, Bool forRead);
+ static void ReportErrScreen (emuptr address, long size, Bool forRead);
+ static void ReportErrHardwareRegisters (emuptr address, long size, Bool forRead);
+ static void ReportErrROM (emuptr address, long size, Bool forRead);
+ static void ReportErrMemMgrStructures (emuptr address, long size, Bool forRead);
+ static void ReportErrMemMgrLeaks (int leaks);
+ static void ReportErrMemMgrSemaphore (void);
+ static void ReportErrFreeChunk (emuptr address, long size, Bool forRead);
+ static void ReportErrUnlockedChunk (emuptr address, long size, Bool forRead);
+ static void ReportErrLowStack (emuptr stackLow, emuptr stackPointer, emuptr stackHigh, emuptr address, long size, Bool forRead);
+ static void ReportErrStackFull (void);
+ static void ReportErrSizelessObject (uint16 id, const EmRect&);
+ static void ReportErrOffscreenObject (uint16 id, const EmRect&);
+ static void ReportErrFormAccess (emuptr formAddress, emuptr address, long size, Bool forRead);
+ static void ReportErrFormObjectAccess (emuptr objectAddress, emuptr formAddress, emuptr address, long size, Bool forRead);
+ static void ReportErrWindowAccess (emuptr windowAddress, emuptr address, long size, Bool forRead);
+ static void ReportErrBitmapAccess (emuptr bitmapAddress, emuptr address, long size, Bool forRead);
+ static void ReportErrProscribedFunction (const SystemCallContext&);
+ static void ReportErrStepSpy (emuptr writeAddress, int writeBytes, emuptr ssAddress, uint32 ssValue, uint32 newValue);
+ static void ReportErrWatchpoint (emuptr writeAddress, int writeBytes, emuptr watchAddress, uint32 watchBytes);
+
+ // Palm OS-detected errors
+
+ static void ReportErrSysFatalAlert (const char* appMsg);
+ static void ReportErrDbgMessage (const char* appMsg);
+
+ // Helper functions for handling reporting of similar errors.
+
+ static void ReportErrAccessCommon (StrCode, ExceptionNumber, int flags, emuptr address, long size, Bool forRead);
+ static void ReportErrObjectCommon (StrCode, ExceptionNumber, int flags, uint16 id, const EmRect&);
+ static void ReportErrOpcodeCommon (StrCode, ExceptionNumber, int flags, uint16 opcode);
+ static void ReportErrStackCommon (StrCode, ExceptionNumber, int flags);
+ static void ReportErrCommon (StrCode, ExceptionNumber, int flags);
+ static EmDlgItemID ReportErrCommPort (string);
+ static EmDlgItemID ReportErrSockets (string);
+
+ enum
+ {
+ kFatal = 0x01,
+ kEnterDebuggerFirst = 0x02
+ };
+
+ enum EAccessType
+ {
+ kOKAccess,
+
+ kLowMemAccess,
+ kGlobalVarAccess,
+ kScreenAccess,
+ kMemMgrAccess,
+ kLowStackAccess,
+ kFreeChunkAccess,
+ kUnlockedChunkAccess,
+
+ kUnknownAccess
+ };
+
+
+ // Add a user-supplied substitution rule. Parameters are deleted after they
+ // are used (by making a call to ReplaceParameters), so they need to be
+ // re-established after every call to that function.
+
+ static void SetParameter (const string& key, const string& value);
+ static void SetParameter (const string& key, const char* value);
+ static void SetParameter (const string& key, const unsigned char* value);
+ static void SetParameter (const string& key, long);
+ static void ClearParameter (const string& key);
+ static void ClearAllParameters (void);
+ static Bool SetErrorParameters (StrCode operation, ErrCode error, StrCode recovery);
+ static void SetStandardParameters (void);
+
+ // Displays a dialog box using DoDialog, and handles the buttons
+ // in a standard fashion.
+
+ static void HandleDialog (StrCode messageID,
+ ExceptionNumber excNum,
+ EmCommonDialogFlags flags,
+ Bool enterDebuggerFirst);
+
+ // Displays a dialog box with the given message and according to
+ // the given flags. Returns which button was clicked.
+
+ static EmDlgItemID DoDialog (StrCode messageID, EmCommonDialogFlags);
+ static EmDlgItemID DoDialog (const char* msg, EmCommonDialogFlags, StrCode messageID = -1);
+
+
+ // Creates and returns a string based on the string template and
+ // parameter list.
+
+ static string ReplaceParameters (StrCode templateID);
+ static string ReplaceParameters (StrCode templateID, ParamList& params);
+ static string ReplaceParameters (const string&, ParamList& params);
+
+
+ // Convert error numbers into string IDs that describe the error.
+
+ static int GetIDForError (ErrCode error);
+ static int GetIDForRecovery (ErrCode error);
+
+
+ // Get the name and version of the current application.
+
+ static void GetAppName (string& appNameUC,
+ string& appNameLC);
+ static void GetAppVersion (string& appVersion);
+
+ static Bool LooksLikeA5Access (emuptr address, long size, Bool forRead);
+
+
+ // If an error condition is detected, throws an error number.
+ // No message is reported.
+
+ static void Throw (ErrCode error);
+ static void ThrowIfError (ErrCode error);
+ static void ThrowIfPalmError (Err error);
+ static void ThrowIfStdCError (int error);
+ static void ThrowIfNULL (void*);
+
+ // Call this function as a "silent failure" bottleneck.
+ // An exception will be thrown that will unwind the stack
+ // to some top-level, but nothing will be reported.
+
+ static void Scram (void);
+};
+
+class EmDeferredErr
+{
+ public:
+ EmDeferredErr (void);
+ virtual ~EmDeferredErr (void);
+
+ virtual void Do (void) = 0;
+};
+
+class EmDeferredErrAccessCommon : public EmDeferredErr
+{
+ public:
+ EmDeferredErrAccessCommon (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrAccessCommon (void);
+
+ protected:
+ emuptr fAddress;
+ long fSize;
+ Bool fForRead;
+};
+
+class EmDeferredErrLowMemory : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrLowMemory (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrLowMemory (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrSystemGlobals : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrSystemGlobals (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrSystemGlobals (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrScreen : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrScreen (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrScreen (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrHardwareRegisters : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrHardwareRegisters (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrHardwareRegisters (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrROM : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrROM (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrROM (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrMemMgrStructures : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrMemMgrStructures (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrMemMgrStructures (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrMemMgrSemaphore : public EmDeferredErr
+{
+ public:
+ EmDeferredErrMemMgrSemaphore (void);
+ virtual ~EmDeferredErrMemMgrSemaphore (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrFreeChunk : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrFreeChunk (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrFreeChunk (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrUnlockedChunk : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrUnlockedChunk (emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrUnlockedChunk (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrLowStack : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrLowStack (emuptr stackLow, emuptr stackPointer, emuptr stackHigh, emuptr address, long size, Bool forRead);
+ virtual ~EmDeferredErrLowStack (void);
+
+ virtual void Do (void);
+
+ private:
+ emuptr fStackLow;
+ emuptr fStackPointer;
+ emuptr fStackHigh;
+};
+
+class EmDeferredErrStackFull : public EmDeferredErr
+{
+ public:
+ EmDeferredErrStackFull (void);
+ virtual ~EmDeferredErrStackFull (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrObjectCommon : public EmDeferredErr
+{
+ public:
+ EmDeferredErrObjectCommon (uint16 id, const EmRect&);
+ virtual ~EmDeferredErrObjectCommon (void);
+
+ protected:
+ uint16 fID;
+ EmRect fRect;
+};
+
+class EmDeferredErrSizelessObject : public EmDeferredErrObjectCommon
+{
+ public:
+ EmDeferredErrSizelessObject (uint16 id, const EmRect&);
+ virtual ~EmDeferredErrSizelessObject (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrOffscreenObject : public EmDeferredErrObjectCommon
+{
+ public:
+ EmDeferredErrOffscreenObject (uint16 id, const EmRect&);
+ virtual ~EmDeferredErrOffscreenObject (void);
+
+ virtual void Do (void);
+};
+
+class EmDeferredErrFormAccess : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrFormAccess (emuptr formAddress,
+ emuptr address,
+ long size,
+ Bool forRead);
+ virtual ~EmDeferredErrFormAccess (void);
+
+ virtual void Do (void);
+
+ protected:
+ emuptr fFormAddress;
+};
+
+class EmDeferredErrFormObjectAccess : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrFormObjectAccess (emuptr objectAddress,
+ emuptr formAddress,
+ emuptr address,
+ long size,
+ Bool forRead);
+ virtual ~EmDeferredErrFormObjectAccess (void);
+
+ virtual void Do (void);
+
+ protected:
+ emuptr fObjectAddress;
+ emuptr fFormAddress;
+};
+
+class EmDeferredErrWindowAccess : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrWindowAccess (emuptr windowAddress,
+ emuptr address,
+ long size,
+ Bool forRead);
+ virtual ~EmDeferredErrWindowAccess (void);
+
+ virtual void Do (void);
+
+ emuptr fWindowAddress;
+};
+
+class EmDeferredErrBitmapAccess : public EmDeferredErrAccessCommon
+{
+ public:
+ EmDeferredErrBitmapAccess (emuptr bitmapAddress,
+ emuptr address,
+ long size,
+ Bool forRead);
+ virtual ~EmDeferredErrBitmapAccess (void);
+
+ virtual void Do (void);
+
+ emuptr fBitmapAddress;
+};
+
+class EmDeferredErrProscribedFunction : public EmDeferredErr
+{
+ public:
+ EmDeferredErrProscribedFunction (const SystemCallContext&);
+ virtual ~EmDeferredErrProscribedFunction(void);
+
+ virtual void Do (void);
+
+ SystemCallContext fContext;
+};
+
+class EmDeferredErrStepSpy : public EmDeferredErr
+{
+ public:
+ EmDeferredErrStepSpy (emuptr writeAddress,
+ int writeBytes,
+ emuptr ssAddress,
+ uint32 ssValue,
+ uint32 newValue);
+ virtual ~EmDeferredErrStepSpy (void);
+
+ virtual void Do (void);
+
+ protected:
+ emuptr fWriteAddress;
+ int fWriteBytes;
+ emuptr fSSAddress;
+ uint32 fSSValue;
+ uint32 fNewValue;
+};
+
+class EmDeferredErrWatchpoint : public EmDeferredErr
+{
+ public:
+ EmDeferredErrWatchpoint (emuptr writeAddress,
+ int writeBytes,
+ emuptr watchAddress,
+ uint32 watchBytes);
+ virtual ~EmDeferredErrWatchpoint (void);
+
+ virtual void Do (void);
+
+ protected:
+ emuptr fWriteAddress;
+ int fWriteBytes;
+ emuptr fWatchAddress;
+ uint32 fWatchBytes;
+};
+
+#endif /* _ERRORHANDLING_H_ */
+
diff --git a/SrcShared/Gzip/COPYING b/SrcShared/Gzip/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/SrcShared/Gzip/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/SrcShared/Gzip/bits.c b/SrcShared/Gzip/bits.c
new file mode 100644
index 0000000..91e9f62
--- /dev/null
+++ b/SrcShared/Gzip/bits.c
@@ -0,0 +1,207 @@
+/* bits.c -- output variable-length bit strings
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+
+/*
+ * PURPOSE
+ *
+ * Output variable-length bit strings. Compression can be done
+ * to a file or to memory. (The latter is not supported in this version.)
+ *
+ * DISCUSSION
+ *
+ * The PKZIP "deflate" file format interprets compressed file data
+ * as a sequence of bits. Multi-bit strings in the file may cross
+ * byte boundaries without restriction.
+ *
+ * The first bit of each byte is the low-order bit.
+ *
+ * The routines in this file allow a variable-length bit value to
+ * be output right-to-left (useful for literal values). For
+ * left-to-right output (useful for code strings from the tree routines),
+ * the bits must have been reversed first with bi_reverse().
+ *
+ * For in-memory compression, the compressed bit stream goes directly
+ * into the requested output buffer. The input data is read in blocks
+ * by the mem_read() function. The buffer is limited to 64K on 16 bit
+ * machines.
+ *
+ * INTERFACE
+ *
+ * void bi_init (FILE *zipfile)
+ * Initialize the bit string routines.
+ *
+ * void send_bits (int value, int length)
+ * Write out a bit string, taking the source bits right to
+ * left.
+ *
+ * int bi_reverse (int value, int length)
+ * Reverse the bits of a bit string, taking the source bits left to
+ * right and emitting them right to left.
+ *
+ * void bi_windup (void)
+ * Write out any remaining bits in an incomplete byte.
+ *
+ * void copy_block(char *buf, unsigned len, int header)
+ * Copy a stored block to the zip file, storing first the length and
+ * its one's complement if requested.
+ *
+ */
+
+#include "tailor.h"
+#include "gzip.h"
+#include "crypt.h"
+
+#ifdef DEBUG
+# include <stdio.h>
+#endif
+
+#ifdef RCSID
+static char rcsid[] = "$Id: bits.c,v 0.9 1993/06/11 10:16:58 jloup Exp $";
+#endif
+
+/* ===========================================================================
+ * Local data used by the "bit string" routines.
+ */
+
+local file_t zfile; /* output gzip file */
+
+local unsigned short bi_buf;
+/* Output buffer. bits are inserted starting at the bottom (least significant
+ * bits).
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+local int bi_valid;
+/* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+int (*read_buf) OF((char *buf, unsigned size));
+/* Current input function. Set to mem_read for in-memory compression */
+
+#ifdef DEBUG
+ ulg bits_sent; /* bit length of the compressed data */
+#endif
+
+/* ===========================================================================
+ * Initialize the bit string routines.
+ */
+void bi_init (zipfile)
+ file_t zipfile; /* output zip file, NO_FILE for in-memory compression */
+{
+ zfile = zipfile;
+ bi_buf = 0;
+ bi_valid = 0;
+#ifdef DEBUG
+ bits_sent = 0L;
+#endif
+
+#if 0 // POSER
+ /* Set the defaults for file compression. They are set by memcompress
+ * for in-memory compression.
+ */
+ if (zfile != NO_FILE) {
+ read_buf = file_read;
+ }
+#endif
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+void send_bits(value, length)
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+#ifdef DEBUG
+ Tracev((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ bits_sent += (ulg)length;
+#endif
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (bi_valid > (int)Buf_size - length) {
+ bi_buf |= (value << bi_valid);
+ put_short(bi_buf);
+ bi_buf = (ush)value >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ } else {
+ bi_buf |= value << bi_valid;
+ bi_valid += length;
+ }
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Write out any remaining bits in an incomplete byte.
+ */
+void bi_windup()
+{
+ if (bi_valid > 8) {
+ put_short(bi_buf);
+ } else if (bi_valid > 0) {
+ put_byte(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+#ifdef DEBUG
+ bits_sent = (bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block to the zip file, storing first the length and its
+ * one's complement if requested.
+ */
+void copy_block(buf, len, header)
+ char *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(); /* align on byte boundary */
+
+ if (header) {
+ put_short((ush)len);
+ put_short((ush)~len);
+#ifdef DEBUG
+ bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+#ifdef CRYPT
+ int t;
+ if (key) zencode(*buf, t);
+#endif
+ put_byte(*buf++);
+ }
+}
diff --git a/SrcShared/Gzip/crypt.h b/SrcShared/Gzip/crypt.h
new file mode 100644
index 0000000..2a4c203
--- /dev/null
+++ b/SrcShared/Gzip/crypt.h
@@ -0,0 +1,12 @@
+/* crypt.h (dummy version) -- do not perform encryption
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+# undef CRYPT /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN 12 /* length of encryption random header */
+
+#define zencode
+#define zdecode
diff --git a/SrcShared/Gzip/deflate.c b/SrcShared/Gzip/deflate.c
new file mode 100644
index 0000000..7f52b64
--- /dev/null
+++ b/SrcShared/Gzip/deflate.c
@@ -0,0 +1,763 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ * PURPOSE
+ *
+ * Identify new text as repetitions of old text within a fixed-
+ * length sliding window trailing behind the new text.
+ *
+ * DISCUSSION
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many info-zippers for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ * INTERFACE
+ *
+ * void lm_init (int pack_level, ush *flags)
+ * Initialize the "longest match" routines for a new file
+ *
+ * ulg deflate (void)
+ * Processes a new input file and return its compressed length. Sets
+ * the compressed length, crc, deflate flags and internal file
+ * attributes.
+ */
+
+#include <stdio.h>
+
+#include "tailor.h"
+#include "gzip.h"
+#include "lzw.h" /* just for consistency checking */
+
+#ifdef RCSID
+static char rcsid[] = "$Id: deflate.c,v 0.15 1993/06/24 10:53:53 jloup Exp $";
+#endif
+
+/* ===========================================================================
+ * Configuration parameters
+ */
+
+/* Compile with MEDIUM_MEM to reduce the memory requirements or
+ * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
+ * entire input file can be held in memory (not possible on 16 bit systems).
+ * Warning: defining these symbols affects HASH_BITS (see below) and thus
+ * affects the compression ratio. The compressed output
+ * is still correct, and might even be smaller in some cases.
+ */
+
+#ifdef SMALL_MEM
+# define HASH_BITS 13 /* Number of bits used to hash strings */
+#endif
+#ifdef MEDIUM_MEM
+# define HASH_BITS 14
+#endif
+#ifndef HASH_BITS
+# define HASH_BITS 15
+ /* For portability to 16 bit machines, do not use values above 15. */
+#endif
+
+/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and
+ * window with tab_suffix. Check that we can do this:
+ */
+#if (WSIZE<<1) > (1<<BITS)
+ error: cannot overlay window with tab_suffix and prev with tab_prefix0
+#endif
+#if HASH_BITS > BITS-1
+ error: cannot overlay head with tab_prefix1
+#endif
+
+#define HASH_SIZE (unsigned)(1<<HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+#define WMASK (WSIZE-1)
+/* HASH_SIZE and WSIZE must be powers of two */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#define FAST 4
+#define SLOW 2
+/* speed options for the general purpose bit flag */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* ===========================================================================
+ * Local data used by the "longest match" routines.
+ */
+
+typedef ush Pos;
+typedef unsigned IPos;
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+/* DECLARE(uch, window, 2L*WSIZE); */
+/* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least WSIZE
+ * bytes. With this organization, matches are limited to a distance of
+ * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would
+ * be less efficient).
+ */
+
+/* DECLARE(Pos, prev, WSIZE); */
+/* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+/* DECLARE(Pos, head, 1<<HASH_BITS); */
+/* Heads of the hash chains or NIL. */
+
+ulg window_size = (ulg)2*WSIZE;
+/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
+ * input file length plus MIN_LOOKAHEAD.
+ */
+
+long block_start;
+/* window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+local unsigned ins_h; /* hash index of string to be inserted */
+
+#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
+/* Number of bits by which ins_h and del_h must be shifted at each
+ * input step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * H_SHIFT * MIN_MATCH >= HASH_BITS
+ */
+
+unsigned int near prev_length;
+/* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ unsigned near strstart; /* start of string to insert */
+ unsigned near match_start; /* start of matching string */
+local int eofile; /* flag set at end of input file */
+local unsigned lookahead; /* number of valid bytes ahead in window */
+
+unsigned near max_chain_length;
+/* To speed up deflation, hash chains are never searched beyond this length.
+ * A higher limit improves compression ratio but degrades the speed.
+ */
+
+local unsigned int max_lazy_match;
+/* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+#define max_insert_length max_lazy_match
+/* Insert new strings in the hash table only if the match length
+ * is not greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+local int compr_level;
+/* compression level (1..9) */
+
+unsigned near good_match;
+/* Use a faster search when the previous match is longer than this */
+
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+
+typedef struct config {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+} config;
+
+#ifdef FULL_SEARCH
+# define nice_match MAX_MATCH
+#else
+ int near nice_match; /* Stop searching when current match exceeds this */
+#endif
+
+local config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0}, /* store only */
+/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8},
+/* 3 */ {4, 6, 32, 32},
+
+/* 4 */ {4, 4, 16, 16}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32},
+/* 6 */ {8, 16, 128, 128},
+/* 7 */ {8, 32, 128, 256},
+/* 8 */ {32, 128, 258, 1024},
+/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Prototypes for local functions.
+ */
+local void fill_window OF((void));
+local ulg deflate_fast OF((void));
+
+ int longest_match OF((IPos cur_match));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+#endif
+
+#ifdef DEBUG
+local void check_match OF((IPos start, IPos match, int length));
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
+
+/* ===========================================================================
+ * Insert string s in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of s are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, match_head) \
+ (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
+ prev[(s) & WMASK] = match_head = head[ins_h], \
+ head[ins_h] = (s))
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new file
+ */
+void lm_init (pack_level, flags)
+ int pack_level; /* 0: store, 1: best speed, 9: best compression */
+ ush *flags; /* general purpose bit flag */
+{
+ register unsigned j;
+
+ if (pack_level < 1 || pack_level > 9) error("bad pack level");
+ compr_level = pack_level;
+
+ /* Initialize the hash table. */
+#if defined(MAXSEG_64K) && HASH_BITS == 15
+ for (j = 0; j < HASH_SIZE; j++) head[j] = NIL;
+#else
+ memzero((char*)head, HASH_SIZE*sizeof(*head));
+#endif
+ /* prev will be initialized on the fly */
+
+ /* Set the default configuration parameters:
+ */
+ max_lazy_match = configuration_table[pack_level].max_lazy;
+ good_match = configuration_table[pack_level].good_length;
+#ifndef FULL_SEARCH
+ nice_match = configuration_table[pack_level].nice_length;
+#endif
+ max_chain_length = configuration_table[pack_level].max_chain;
+ if (pack_level == 1) {
+ *flags |= FAST;
+ } else if (pack_level == 9) {
+ *flags |= SLOW;
+ }
+ /* ??? reduce max_chain_length for binary files */
+
+ strstart = 0;
+ block_start = 0L;
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+
+ lookahead = read_buf((char*)window,
+ sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
+
+ if (lookahead == 0 || lookahead == (unsigned)EOF) {
+ eofile = 1, lookahead = 0;
+ return;
+ }
+ eofile = 0;
+ /* Make sure that we always have enough lookahead. This is important
+ * if input comes from a device such as a tty.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+
+ ins_h = 0;
+ for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
+ * not important since only literal bytes will be emitted.
+ */
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+#ifndef ASMV
+/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
+ * match.s. The code is functionally equivalent, so you can use the C version
+ * if desired.
+ */
+int longest_match(cur_match)
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = max_chain_length; /* max hash chain length */
+ register uch *scan = window + strstart; /* current string */
+ register uch *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = prev_length; /* best match length so far */
+ IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+
+/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+#if HASH_BITS < 8 || MAX_MATCH != 258
+ error: Code too clever
+#endif
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register uch *strend = window + strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ush*)scan;
+ register ush scan_end = *(ush*)(scan+best_len-1);
+#else
+ register uch *strend = window + strstart + MAX_MATCH;
+ register uch scan_end1 = scan[best_len-1];
+ register uch scan_end = scan[best_len];
+#endif
+
+ /* Do not waste too much time if we already have a good match: */
+ if (prev_length >= good_match) {
+ chain_length >>= 2;
+ }
+ Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
+
+ do {
+ Assert(cur_match < strstart, "no future");
+ match = window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ush*)(match+best_len-1) != scan_end ||
+ *(ush*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ scan++, match++;
+ do {
+ } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ush*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & WMASK]) > limit
+ && --chain_length != 0);
+
+ return best_len;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(start, match, length)
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (memcmp((char*)window + match,
+ (char*)window + start, length) != EQUAL) {
+ fprintf(stderr,
+ " start %d, match %d, length %d\n",
+ start, match, length);
+ error("invalid match");
+ }
+ if (verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead, and sets eofile if end of input file.
+ * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
+ * OUT assertions: at least one byte has been read, or eofile is set;
+ * file reads are performed for at least two bytes (required for the
+ * translate_eol option).
+ */
+local void fill_window()
+{
+ register unsigned n, m;
+ unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
+ /* Amount of free space at the end of the window. */
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (more == (unsigned)EOF) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+ } else if (strstart >= WSIZE+MAX_DIST) {
+ /* By the IN assertion, the window is not empty so we can't confuse
+ * more == 0 with more == 64K on a 16 bit machine.
+ */
+ Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM");
+
+ memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
+ match_start -= WSIZE;
+ strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
+
+ block_start -= (long) WSIZE;
+
+ for (n = 0; n < HASH_SIZE; n++) {
+ m = head[n];
+ head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+ }
+ for (n = 0; n < WSIZE; n++) {
+ m = prev[n];
+ prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ }
+ more += WSIZE;
+ }
+ /* At this point, more >= 2 */
+ if (!eofile) {
+ n = read_buf((char*)window+strstart+lookahead, more);
+ if (n == 0 || n == (unsigned)EOF) {
+ eofile = 1;
+ } else {
+ lookahead += n;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK(eof) \
+ flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
+ (char*)NULL, (long)strstart - block_start, (eof))
+
+/* ===========================================================================
+ * Processes a new input file and return its compressed length. This
+ * function does not perform lazy evaluationof matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local ulg deflate_fast()
+{
+ IPos hash_head; /* head of the hash chain */
+ int flush; /* set if current block must be flushed */
+ unsigned match_length = 0; /* length of best match */
+
+ prev_length = MIN_MATCH-1;
+ while (lookahead != 0) {
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ INSERT_STRING(strstart, hash_head);
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ match_length = longest_match (hash_head);
+ /* longest_match() sets match_start */
+ if (match_length > lookahead) match_length = lookahead;
+ }
+ if (match_length >= MIN_MATCH) {
+ check_match(strstart, match_start, match_length);
+
+ flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);
+
+ lookahead -= match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (match_length <= max_insert_length) {
+ match_length--; /* string at strstart already in hash table */
+ do {
+ strstart++;
+ INSERT_STRING(strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+ * these bytes are garbage, but it does not matter since
+ * the next lookahead bytes will be emitted as literals.
+ */
+ } while (--match_length != 0);
+ strstart++;
+ } else {
+ strstart += match_length;
+ match_length = 0;
+ ins_h = window[strstart];
+ UPDATE_HASH(ins_h, window[strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c",window[strstart]));
+ flush = ct_tally (0, window[strstart]);
+ lookahead--;
+ strstart++;
+ }
+ if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+
+ }
+ return FLUSH_BLOCK(1); /* eof */
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+ulg deflate()
+{
+ IPos hash_head; /* head of hash chain */
+ IPos prev_match; /* previous match */
+ int flush; /* set if current block must be flushed */
+ int match_available = 0; /* set if previous match exists */
+ register unsigned match_length = MIN_MATCH-1; /* length of best match */
+#ifdef DEBUG
+ extern long isize; /* byte length of input file, for debug only */
+#endif
+
+ if (compr_level <= 3) return deflate_fast(); /* optimized for speed */
+
+ /* Process the input block. */
+ while (lookahead != 0) {
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ INSERT_STRING(strstart, hash_head);
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ prev_length = match_length, prev_match = match_start;
+ match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && prev_length < max_lazy_match &&
+ strstart - hash_head <= MAX_DIST) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ match_length = longest_match (hash_head);
+ /* longest_match() sets match_start */
+ if (match_length > lookahead) match_length = lookahead;
+
+ /* Ignore a length 3 match if it is too distant: */
+ if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ match_length--;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (prev_length >= MIN_MATCH && match_length <= prev_length) {
+
+ check_match(strstart-1, prev_match, prev_length);
+
+ flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted.
+ */
+ lookahead -= prev_length-1;
+ prev_length -= 2;
+ do {
+ strstart++;
+ INSERT_STRING(strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+ * these bytes are garbage, but it does not matter since the
+ * next lookahead bytes will always be emitted as literals.
+ */
+ } while (--prev_length != 0);
+ match_available = 0;
+ match_length = MIN_MATCH-1;
+ strstart++;
+ if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+ } else if (match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c",window[strstart-1]));
+ if (ct_tally (0, window[strstart-1])) {
+ FLUSH_BLOCK(0), block_start = strstart;
+ }
+ strstart++;
+ lookahead--;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ match_available = 1;
+ strstart++;
+ lookahead--;
+ }
+ Assert (strstart <= isize && lookahead <= isize, "a bit too far");
+
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+ }
+ if (match_available) ct_tally (0, window[strstart-1]);
+
+ return FLUSH_BLOCK(1); /* eof */
+}
diff --git a/SrcShared/Gzip/gzip.h b/SrcShared/Gzip/gzip.h
new file mode 100644
index 0000000..d506a4b
--- /dev/null
+++ b/SrcShared/Gzip/gzip.h
@@ -0,0 +1,323 @@
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+// POSER
+//#if defined(__STDC__) || defined(PROTO)
+# define OF(args) args
+//#else
+//# define OF(args) ()
+//#endif
+
+// POSER
+//#define DEBUG 1
+
+#ifdef __STDC__
+ typedef void *voidp;
+#else
+ typedef char *voidp;
+#endif
+
+/* I don't like nested includes, but the string and io functions are used
+ * too often
+ */
+#include <stdio.h>
+#if !defined(NO_STRING_H) || defined(STDC_HEADERS)
+# include <string.h>
+# if !defined(STDC_HEADERS) && !defined(NO_MEMORY_H) && !defined(__GNUC__)
+# include <memory.h>
+# endif
+# define memzero(s, n) memset ((voidp)(s), 0, (n))
+#else
+# include <strings.h>
+# define strchr index
+# define strrchr rindex
+# define memcpy(d, s, n) bcopy((s), (d), (n))
+# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
+# define memzero(s, n) bzero((s), (n))
+#endif
+
+#ifndef RETSIGTYPE
+# define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+/* Return codes from gzip */
+#define OK 0
+//#define ERROR 1 // POSER - conflicts with definition in wingdi.h
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED 0
+#define COMPRESSED 1
+#define PACKED 2
+#define LZHED 3
+/* methods 4 to 7 reserved */
+#define DEFLATED 8
+#define MAX_METHODS 9
+extern int method; /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlaid between
+ * the various modules:
+ * deflate: prev+head window d_buf l_buf outbuf
+ * unlzw: tab_prefix tab_suffix stack inbuf outbuf
+ * inflate: window inbuf
+ * unpack: window inbuf prefix_len
+ * unlzh: left+right window c_table inbuf c_len
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef INBUFSIZ
+# ifdef SMALL_MEM
+# define INBUFSIZ 0x2000 /* input buffer size */
+# else
+# define INBUFSIZ 0x8000 /* input buffer size */
+# endif
+#endif
+#define INBUF_EXTRA 64 /* required by unlzw() */
+
+#ifndef OUTBUFSIZ
+# ifdef SMALL_MEM
+# define OUTBUFSIZ 8192 /* output buffer size */
+# else
+# define OUTBUFSIZ 16384 /* output buffer size */
+# endif
+#endif
+#define OUTBUF_EXTRA 2048 /* required by unlzw() */
+
+#ifndef DIST_BUFSIZE
+# ifdef SMALL_MEM
+# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
+# else
+# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+# endif
+#endif
+
+#ifdef DYN_ALLOC
+# define EXTERN(type, array) extern type * near array
+# define DECLARE(type, array, size) type * near array
+# define ALLOC(type, array, size) { \
+ array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
+ if (array == NULL) error("insufficient memory"); \
+ }
+# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+# define EXTERN(type, array) extern type array[]
+# define DECLARE(type, array, size) type array[size]
+# define ALLOC(type, array, size)
+# define FREE(array)
+#endif
+
+EXTERN(uch, inbuf); /* input buffer */
+EXTERN(uch, outbuf); /* output buffer */
+EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
+EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+# define tab_prefix prev /* hash link (see deflate.c) */
+# define head (prev+WSIZE) /* hash head (see deflate.c) */
+ EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
+#else
+# define tab_prefix0 prev
+# define head tab_prefix1
+ EXTERN(ush, tab_prefix0); /* prefix for even codes */
+ EXTERN(ush, tab_prefix1); /* prefix for odd codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr; /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in; /* number of input bytes */
+extern long bytes_out; /* number of output bytes */
+extern long header_bytes;/* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int ifd; /* input file descriptor */
+extern int ofd; /* output file descriptor */
+extern char ifname[]; /* input file name or "stdin" */
+extern char ofname[]; /* output file name or "stdout" */
+extern char *progname; /* program name */
+
+extern long time_stamp; /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+typedef int file_t; /* Do not use stdio */
+#define NO_FILE (-1) /* in memory compression */
+
+
+#define PACK_MAGIC "\037\036" /* Magic header for packed files */
+#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
+#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/
+#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define RESERVED 0xC0 /* bit 6,7: reserved */
+
+/* internal file attribute */
+#define UNKNOWN 0xffff
+#define BINARY 0
+#define ASCII 1
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* at least 32K for zip's deflate method */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt; /* flag to turn on decryption */
+extern int exit_code; /* program exit code */
+extern int verbose; /* be verbose (-v) */
+extern int quiet; /* be quiet (-q) */
+extern int level; /* compression level */
+extern int test; /* check .z file integrity */
+extern int to_stdout; /* output to stdout (-c) */
+extern int save_orig_name; /* set if original name must be saved */
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
+#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
+
+/* put_byte is used for the compressed output, put_ubyte for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_ubyte
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+ flush_outbuf();}
+#define put_ubyte(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+ flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+ outbuf[outcnt++] = (uch) ((w) & 0xff); \
+ outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+ } else { \
+ put_byte((uch)((w) & 0xff)); \
+ put_byte((uch)((ush)(w) >> 8)); \
+ } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+ put_short((n) & 0xffff); \
+ put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable() 0 /* force sequential output */
+#define translate_eol 0 /* no option -a yet */
+
+#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# define Assert(cond,msg) {if(!(cond)) error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+// POSER
+extern int my_fprintf (FILE*, const char*, ...);
+#define fprintf my_fprintf
+
+#define WARN(msg) {if (!quiet) fprintf msg ; \
+ if (exit_code == OK) exit_code = WARNING;}
+
+ /* in zip.c: */
+extern int zip OF((int in, int out));
+extern int file_read OF((char *buf, unsigned size));
+
+ /* in unzip.c */
+extern int unzip OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+ /* in unpack.c */
+extern int unpack OF((int in, int out));
+
+ /* in unlzh.c */
+extern int unlzh OF((int in, int out));
+
+ /* in gzip.c */
+RETSIGTYPE abort_gzip OF((void));
+
+ /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg deflate OF((void));
+
+ /* in trees.c */
+void ct_init OF((ush *attr, int *method));
+int ct_tally OF((int dist, int lc));
+ulg flush_block OF((char *buf, ulg stored_len, int eof));
+
+ /* in bits.c */
+void bi_init OF((file_t zipfile));
+void send_bits OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void bi_windup OF((void));
+void copy_block OF((char *buf, unsigned len, int header));
+extern int (*read_buf) OF((char *buf, unsigned size));
+
+ /* in util.c: */
+extern int copy OF((int in, int out));
+extern ulg updcrc OF((uch *s, unsigned n));
+extern void clear_bufs OF((void));
+extern int fill_inbuf OF((int eof_ok));
+extern void flush_outbuf OF((void));
+extern void flush_window OF((void));
+extern void write_buf OF((int fd, voidp buf, unsigned cnt));
+extern char *strlwr OF((char *s));
+//extern char *basename OF((char *fname)); // POSER - conflicts with basename in GNU string.h
+extern void make_simple_name OF((char *name));
+extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
+extern void error OF((char *m));
+extern void warn OF((char *a, char *b));
+extern void read_error OF((void));
+extern void write_error OF((void));
+extern void display_ratio OF((long num, long den, FILE *file));
+//extern voidp xmalloc OF((unsigned int size)); // POSER
+
+ /* in inflate.c */
+extern int inflate OF((void));
diff --git a/SrcShared/Gzip/inflate.c b/SrcShared/Gzip/inflate.c
new file mode 100644
index 0000000..9fb5bf7
--- /dev/null
+++ b/SrcShared/Gzip/inflate.c
@@ -0,0 +1,954 @@
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+ version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+ prefer that if you modify it and redistribute it that you include
+ comments to that effect with your name and the date. Thank you.
+ [The history has been moved to the file ChangeLog.]
+ */
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor deals with some chunk of data at a time, and
+ decides which method to use on a chunk-by-chunk basis. A chunk might
+ typically be 32K or 64K. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data is compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data is preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block codes up smaller that way (usually for quite small
+ chunks), otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block, and so
+ can code it much better than the pre-determined fixed codes.
+
+ The Huffman codes themselves are decoded using a mutli-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarly, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp $";
+#endif
+
+//#include <sys/types.h> // POSER
+
+#include "tailor.h"
+
+#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
+# include <stdlib.h>
+#endif
+
+#include "gzip.h"
+#define slide window
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+
+/* Function prototypes */
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+/* unsigned wp; current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed, and are initialized at the beginning of a
+ routine that uses these macros from a global bit buffer and count.
+
+ If we assume that EOB will be the longest code, then we will never
+ ask for bits with NEEDBITS that are beyond the end of the stream.
+ So, NEEDBITS should not read any more bytes than are needed to
+ meet the request. Then no bytes need to be "returned" to the buffer
+ at the end of the last block.
+
+ However, this assumption is not true for fixed blocks--the EOB code
+ is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+ (The EOB code is shorter than other codes because fixed blocks are
+ generally short. So, while a block always has an EOB, many other
+ literal/length codes have a significantly lower probability of
+ showing up at all.) However, by making the first table have a
+ lookup of seven bits, the EOB code will be found in that first
+ lookup, and so will not require that too many bits be pulled from
+ the stream.
+ */
+
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+
+ush mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+ uch cc;
+# define NEXTBYTE() \
+ (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+# define NEXTBYTE() (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+int lbits = 9; /* bits in base literal/length lookup table */
+int dbits = 6; /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+unsigned hufts; /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ memzero(c, sizeof(c));
+ p = b; i = n;
+ do {
+ Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"),
+ n-i, *p));
+ c[*p]++; /* assume all entries <= BMAX */
+ p++; /* Can't combine with above line (Solaris bug) */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = (ush)(*p); /* simple code is just the value */
+ p++; /* one compiler does not like *p++ */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free((char*)p);
+ p = q;
+ }
+ return 0;
+}
+
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+ /* inflate the coded data */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ for (;;) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ slide[w++] = (uch)t->v.n;
+ Tracevv((stderr, "%c", slide[w-1]));
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e)
+ Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+ /* do the copy */
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ Tracevv((stderr, "%c", slide[w-1]));
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+ /* done */
+ return 0;
+}
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ slide[w++] = (uch)b;
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+ return 0;
+}
+
+
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ int i; /* temporary variable */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned l[288]; /* length list for huft_build */
+
+
+ /* set up literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ bl = 7;
+ if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+ return i;
+
+
+ /* set up distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ bd = 5;
+ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+ {
+ huft_free(tl);
+ return i;
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask_bits[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+ {
+ if (i == 1) {
+ fprintf(stderr, " incomplete literal tree\n");
+ huft_free(tl);
+ }
+ return i; /* incomplete code set */
+ }
+ bd = dbits;
+ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+ {
+ if (i == 1) {
+ fprintf(stderr, " incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+ }
+#else
+ huft_free(td);
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+#endif
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_block(e)
+int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic();
+ if (t == 0)
+ return inflate_stored();
+ if (t == 1)
+ return inflate_fixed();
+
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+ unsigned h; /* maximum struct huft's malloc'ed */
+
+
+ /* initialize window, bit buffer */
+ wp = 0;
+ bk = 0;
+ bb = 0;
+
+
+ /* decompress until the last block */
+ h = 0;
+ do {
+ hufts = 0;
+ if ((r = inflate_block(&e)) != 0)
+ return r;
+ if (hufts > h)
+ h = hufts;
+ } while (!e);
+
+ /* Undo too much lookahead. The next read will be byte aligned so we
+ * can discard unused bits in the last meaningful byte.
+ */
+ while (bk >= 8) {
+ bk -= 8;
+ inptr--;
+ }
+
+ /* flush out slide */
+ flush_output(wp);
+
+
+ /* return success */
+#ifdef DEBUG
+ fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+ return 0;
+}
diff --git a/SrcShared/Gzip/lzw.h b/SrcShared/Gzip/lzw.h
new file mode 100644
index 0000000..4b7ac86
--- /dev/null
+++ b/SrcShared/Gzip/lzw.h
@@ -0,0 +1,42 @@
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+# include "gzip.h"
+#endif
+
+#ifndef BITS
+# define BITS 16
+#endif
+#define INIT_BITS 9 /* Initial number of bits per code */
+
+#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE 0x80
+/* Block compression: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define CLEAR 256 /* flush the dictionary */
+#define FIRST (CLEAR+1) /* first free entry */
+
+extern int maxbits; /* max bits per code for LZW */
+extern int block_mode; /* block compress mode -C compatible with 2.0 */
+
+extern int lzw OF((int in, int out));
+extern int unlzw OF((int in, int out));
diff --git a/SrcShared/Gzip/revision.h b/SrcShared/Gzip/revision.h
new file mode 100644
index 0000000..f99b65f
--- /dev/null
+++ b/SrcShared/Gzip/revision.h
@@ -0,0 +1,16 @@
+/* revision.h -- define the version number
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#define VERSION "1.2.4"
+#define PATCHLEVEL 0
+#define REVDATE "18 Aug 93"
+
+/* This version does not support compression into old compress format: */
+#ifdef LZW
+# undef LZW
+#endif
+
+/* $Id: revision.h,v 0.25 1993/06/24 08:29:52 jloup Exp $ */
diff --git a/SrcShared/Gzip/tailor.h b/SrcShared/Gzip/tailor.h
new file mode 100644
index 0000000..a97d8be
--- /dev/null
+++ b/SrcShared/Gzip/tailor.h
@@ -0,0 +1,328 @@
+/* tailor.h -- target dependent definitions
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/* The target dependent definitions should be defined here only.
+ * The target dependent functions should be defined in tailor.c.
+ */
+
+/* $Id: tailor.h,v 0.18 1993/06/14 19:32:20 jloup Exp $ */
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+#if defined(__OS2__) && !defined(OS2)
+# define OS2
+#endif
+
+#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
+# undef MSDOS
+#endif
+
+#ifdef MSDOS
+# ifdef __GNUC__
+ /* DJGPP version 1.09+ on MS-DOS.
+ * The DJGPP 1.09 stat() function must be upgraded before gzip will
+ * fully work.
+ * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
+ * implies DIRENT.
+ */
+# define near
+# else
+# define MAXSEG_64K
+# ifdef __TURBOC__
+# define NO_OFF_T
+# ifdef __BORLANDC__
+# define DIRENT
+# else
+# define NO_UTIME
+# endif
+# else /* MSC */
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# endif
+# endif
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 128
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# define NO_SIZE_CHECK
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# include <io.h>
+# define OS_CODE 0x00
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# if !defined(NO_ASM) && !defined(ASMV)
+# define ASMV
+# endif
+#else
+# define near
+#endif
+
+#ifdef OS2
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 260
+# ifdef OS2FAT
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define casemap(c) tolow(c)
+# endif
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# include <io.h>
+# define OS_CODE 0x06
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# ifdef _MSC_VER
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define MAXSEG_64K
+# undef near
+# define near _near
+# endif
+# ifdef __EMX__
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define DIRENT
+# define EXPAND(argc,argv) \
+ {_response(&argc, &argv); _wildcard(&argc, &argv);}
+# endif
+# ifdef __BORLANDC__
+# define DIRENT
+# endif
+# ifdef __ZTC__
+# define NO_DIR
+# define NO_UTIME_H
+# include <dos.h>
+# define EXPAND(argc,argv) \
+ {response_expand(&argc, &argv);}
+# endif
+#endif
+
+#ifdef WIN32 /* Windows NT */
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 260
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# include <io.h>
+# include <malloc.h>
+# ifdef NTFAT
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# endif
+# define OS_CODE 0x0b
+#endif
+
+#ifdef MSDOS
+# ifdef __TURBOC__
+# include <alloc.h>
+# define DYN_ALLOC
+ /* Turbo C 2.0 does not accept static allocations of large arrays */
+ void * fcalloc (unsigned items, unsigned size);
+ void fcfree (void *ptr);
+# else /* MSC */
+# include <malloc.h>
+# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
+# define fcfree(ptr) hfree(ptr)
+# endif
+#else
+# ifdef MAXSEG_64K
+# define fcalloc(items,size) calloc((items),(size))
+# else
+# define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
+# endif
+# define fcfree(ptr) free(ptr)
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define PATH_SEP ']'
+# define PATH_SEP2 ':'
+# define SUFFIX_SEP ';'
+# define NO_MULTIPLE_DOTS
+# define Z_SUFFIX "-gz"
+# define RECORD_IO 1
+# define casemap(c) tolow(c)
+# define OS_CODE 0x02
+# define OPTIONS_VAR "GZIP_OPT"
+# define STDC_HEADERS
+# define NO_UTIME
+# define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
+# include <file.h>
+# define unlink delete
+# ifdef VAXC
+# define NO_FCNTL_H
+# include <unixio.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define PATH_SEP2 ':'
+# define STDC_HEADERS
+# define OS_CODE 0x01
+# define ASMV
+# ifdef __GNUC__
+# define DIRENT
+# define HAVE_UNISTD_H
+# else /* SASC */
+# define NO_STDIN_FSTAT
+# define SYSDIR
+# define NO_SYMLINK
+# define NO_CHOWN
+# define NO_FCNTL_H
+# include <fcntl.h> /* for read() and write() */
+# define direct dirent
+ extern void _expand_args(int *argc, char ***argv);
+# define EXPAND(argc,argv) _expand_args(&argc,&argv);
+# undef O_BINARY /* disable useless --ascii option */
+# endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# ifndef STDC_HEADERS
+# define STDC_HEADERS
+# define HAVE_UNISTD_H
+# define DIRENT
+# endif
+# define ASMV
+# define OS_CODE 0x05
+# ifdef TOSFS
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 128
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define NO_CHOWN
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# define NO_SYMLINK
+# endif
+#endif
+
+#ifdef MACOS
+# define PATH_SEP ':'
+# define DYN_ALLOC
+# define PROTO
+# define NO_STDIN_FSTAT
+# define NO_CHOWN
+# define NO_UTIME
+# define chmod(file, mode) (0)
+# define OPEN(name, flags, mode) open(name, flags)
+# define OS_CODE 0x07
+# ifdef MPW
+# define isatty(fd) ((fd) <= 2)
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define PATH_SEP '>'
+# define STDC_HEADERS
+# define NO_MEMORY_H
+# define NO_UTIME_H
+# define NO_UTIME
+# define NO_CHOWN
+# define NO_STDIN_FSTAT
+# define NO_SIZE_CHECK
+# define NO_SYMLINK
+# define RECORD_IO 1
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# define put_char(c) put_byte((c) & 0x7F)
+# define get_char(c) ascii2pascii(get_byte())
+# define OS_CODE 0x0F /* temporary, subject to change */
+# ifdef SIGTERM
+# undef SIGTERM /* We don't want a signal handler for SIGTERM */
+# endif
+#endif
+
+#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */
+# define NOMEMCPY /* problem with overlapping copies */
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifndef unix
+# define NO_ST_INO /* don't rely on inode numbers */
+#endif
+
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef PATH_SEP
+# define PATH_SEP '/'
+#endif
+
+#ifndef casemap
+# define casemap(c) (c)
+#endif
+
+#ifndef OPTIONS_VAR
+# define OPTIONS_VAR "GZIP"
+#endif
+
+#ifndef Z_SUFFIX
+# define Z_SUFFIX ".gz"
+#endif
+
+#ifdef MAX_EXT_CHARS
+# define MAX_SUFFIX MAX_EXT_CHARS
+#else
+# define MAX_SUFFIX 30
+#endif
+
+#ifndef MAKE_LEGAL_NAME
+# ifdef NO_MULTIPLE_DOTS
+# define MAKE_LEGAL_NAME(name) make_simple_name(name)
+# else
+# define MAKE_LEGAL_NAME(name)
+# endif
+#endif
+
+#ifndef MIN_PART
+# define MIN_PART 3
+ /* keep at least MIN_PART chars between dots in a file name. */
+#endif
+
+#ifndef EXPAND
+# define EXPAND(argc,argv)
+#endif
+
+#ifndef RECORD_IO
+# define RECORD_IO 0
+#endif
+
+#ifndef SET_BINARY_MODE
+# define SET_BINARY_MODE(fd)
+#endif
+
+#ifndef OPEN
+# define OPEN(name, flags, mode) open(name, flags, mode)
+#endif
+
+#ifndef get_char
+# define get_char() get_byte()
+#endif
+
+#ifndef put_char
+# define put_char(c) put_byte(c)
+#endif
diff --git a/SrcShared/Gzip/trees.c b/SrcShared/Gzip/trees.c
new file mode 100644
index 0000000..1058992
--- /dev/null
+++ b/SrcShared/Gzip/trees.c
@@ -0,0 +1,1076 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ * PURPOSE
+ *
+ * Encode various sets of source values using variable-length
+ * binary code trees.
+ *
+ * DISCUSSION
+ *
+ * The PKZIP "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in the ZIP file in a compressed form
+ * which is itself a Huffman encoding of the lengths of
+ * all the code strings (in ascending order by source values).
+ * The actual code strings are reconstructed from the lengths in
+ * the UNZIP process, as described in the "application note"
+ * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
+ *
+ * REFERENCES
+ *
+ * Lynch, Thomas J.
+ * Data Compression: Techniques and Applications, pp. 53-55.
+ * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7.
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ *
+ * INTERFACE
+ *
+ * void ct_init (ush *attr, int *methodp)
+ * Allocate the match buffer, initialize the various tables and save
+ * the location of the internal file attribute (ascii/binary) and
+ * method (DEFLATE/STORE)
+ *
+ * void ct_tally (int dist, int lc);
+ * Save the match info and tally the frequency counts.
+ *
+ * long flush_block (char *buf, ulg stored_len, int eof)
+ * Determine the best encoding for the current block: dynamic trees,
+ * static trees or store, and output the encoded block to the zip
+ * file. Returns the total compressed length for the file so far.
+ *
+ */
+
+#include <ctype.h>
+
+#include "tailor.h"
+#include "gzip.h"
+
+#ifdef RCSID
+static char rcsid[] = "$Id: trees.c,v 0.12 1993/06/10 13:27:54 jloup Exp $";
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+
+local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local int near extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#ifndef LIT_BUFSIZE
+# ifdef SMALL_MEM
+# define LIT_BUFSIZE 0x2000
+# else
+# ifdef MEDIUM_MEM
+# define LIT_BUFSIZE 0x4000
+# else
+# define LIT_BUFSIZE 0x8000
+# endif
+# endif
+#endif
+#ifndef DIST_BUFSIZE
+# define DIST_BUFSIZE LIT_BUFSIZE
+#endif
+/* Sizes of match buffers for literals/lengths and distances. There are
+ * 4 reasons for limiting LIT_BUFSIZE to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input data is
+ * still in the window so we can still emit a stored block even when input
+ * comes from standard input. (This can also be done for all blocks if
+ * LIT_BUFSIZE is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting trees
+ * more frequently.
+ * - I can't count above 4
+ * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
+ * memory at the expense of compression). Some optimizations would be possible
+ * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+#if LIT_BUFSIZE > INBUFSIZ
+ error cannot overlay l_buf and inbuf
+#endif
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+/* ===========================================================================
+ * Local data
+ */
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+local ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */
+
+local ct_data near static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see ct_init
+ * below).
+ */
+
+local ct_data near static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+local ct_data near bl_tree[2*BL_CODES+1];
+/* Huffman tree for the bit lengths */
+
+typedef struct tree_desc {
+ ct_data near *dyn_tree; /* the dynamic tree */
+ ct_data near *static_tree; /* corresponding static tree or NULL */
+ int near *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+ int max_code; /* largest code with non zero frequency */
+} tree_desc;
+
+local tree_desc near l_desc =
+{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0};
+
+local tree_desc near d_desc =
+{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0};
+
+local tree_desc near bl_desc =
+{bl_tree, (ct_data near *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0};
+
+
+local ush near bl_count[MAX_BITS+1];
+/* number of codes at each bit length for an optimal tree */
+
+local uch near bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+local int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+local int heap_len; /* number of elements in the heap */
+local int heap_max; /* element of largest frequency */
+/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+local uch near depth[2*L_CODES+1];
+/* Depth of each subtree used as tie breaker for trees of equal frequency */
+
+local uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+local int near base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int near base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#define l_buf inbuf
+/* DECLARE(uch, l_buf, LIT_BUFSIZE); buffer for literals or lengths */
+
+/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
+
+local uch near flag_buf[(LIT_BUFSIZE/8)];
+/* flag_buf is a bit array distinguishing literals from lengths in
+ * l_buf, thus indicating the presence or absence of a distance.
+ */
+
+local unsigned last_lit; /* running index in l_buf */
+local unsigned last_dist; /* running index in d_buf */
+local unsigned last_flags; /* running index in flag_buf */
+local uch flags; /* current flags not yet saved in flag_buf */
+local uch flag_bit; /* current bit used in flags */
+/* bits are filled in flags starting at bit 0 (least significant).
+ * Note: these flags are overkill in the current code since we don't
+ * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+
+local ulg opt_len; /* bit length of current block with optimal trees */
+local ulg static_len; /* bit length of current block with static trees */
+
+local ulg compressed_len; /* total bit length of compressed file */
+
+local ulg input_len; /* total byte length of input file */
+/* input_len is for debugging only since we can get it by other means. */
+
+ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */
+int *file_method; /* pointer to DEFLATE or STORE */
+
+#ifdef DEBUG
+extern ulg bits_sent; /* bit length of the compressed data */
+extern long isize; /* byte length of input file */
+#endif
+
+extern long block_start; /* window offset of current block */
+extern unsigned near strstart; /* window offset of current string */
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void init_block OF((void));
+local void pqdownheap OF((ct_data near *tree, int k));
+local void gen_bitlen OF((tree_desc near *desc));
+local void gen_codes OF((ct_data near *tree, int max_code));
+local void build_tree OF((tree_desc near *desc));
+local void scan_tree OF((ct_data near *tree, int max_code));
+local void send_tree OF((ct_data near *tree, int max_code));
+local int build_bl_tree OF((void));
+local void send_all_trees OF((int lcodes, int dcodes, int blcodes));
+local void compress_block OF((ct_data near *ltree, ct_data near *dtree));
+local void set_file_type OF((void));
+
+
+#ifndef DEBUG
+# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(c, tree) \
+ { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+#undef MAX // POSER
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Allocate the match buffer, initialize the various tables and save the
+ * location of the internal file attribute (ascii/binary) and method
+ * (DEFLATE/STORE).
+ */
+void ct_init(attr, methodp)
+ ush *attr; /* pointer to internal file attribute */
+ int *methodp; /* pointer to compression method */
+{
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+
+ file_type = attr;
+ file_method = methodp;
+ compressed_len = input_len = 0L;
+
+ if (static_dtree[0].Len != 0) return; /* ct_init already called */
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "ct_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "ct_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "ct_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data near *)static_ltree, L_CODES+1);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse(n, 5);
+ }
+
+ /* Initialize the first block of the first file: */
+ init_block();
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block()
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0;
+
+ dyn_ltree[END_BLOCK].Freq = 1;
+ opt_len = static_len = 0L;
+ last_lit = last_dist = last_flags = 0;
+ flags = 0; flag_bit = 1;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(tree, top) \
+{\
+ top = heap[SMALLEST]; \
+ heap[SMALLEST] = heap[heap_len--]; \
+ pqdownheap(tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(tree, k)
+ ct_data near *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++;
+
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, heap[j])) break;
+
+ /* Exchange v with the smallest son */
+ heap[k] = heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(desc)
+ tree_desc near *desc; /* the tree descriptor */
+{
+ ct_data near *tree = desc->dyn_tree;
+ int near *extra = desc->extra_bits;
+ int base = desc->extra_base;
+ int max_code = desc->max_code;
+ int max_length = desc->max_length;
+ ct_data near *stree = desc->static_tree;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[heap[heap_max]].Len = 0; /* root of the heap */
+
+ for (h = heap_max+1; h < HEAP_SIZE; h++) {
+ n = heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ opt_len += (ulg)f * (bits + xbits);
+ if (stree) static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (bl_count[bits] == 0) bits--;
+ bl_count[bits]--; /* move one leaf down the tree */
+ bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = bl_count[bits];
+ while (n != 0) {
+ m = heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code)
+ ct_data near *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(desc)
+ tree_desc near *desc; /* the tree descriptor */
+{
+ ct_data near *tree = desc->dyn_tree;
+ ct_data near *stree = desc->static_tree;
+ int elems = desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node = elems; /* next internal node of the tree */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ heap_len = 0, heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ heap[++heap_len] = max_code = n;
+ depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (heap_len < 2) {
+ int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[new].Freq = 1;
+ depth[new] = 0;
+ opt_len--; if (stree) static_len -= stree[new].Len;
+ /* new is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ do {
+ pqremove(tree, n); /* n = node of least frequency */
+ m = heap[SMALLEST]; /* m = node of next least frequency */
+
+ heap[--heap_max] = n; /* keep the nodes sorted by frequency */
+ heap[--heap_max] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ heap[SMALLEST] = node++;
+ pqdownheap(tree, SMALLEST);
+
+ } while (heap_len >= 2);
+
+ heap[--heap_max] = heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen((tree_desc near *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data near *)tree, max_code);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree. Updates opt_len to take into account the repeat
+ * counts. (The contribution of the bit length codes will be added later
+ * during the construction of bl_tree.)
+ */
+local void scan_tree (tree, max_code)
+ ct_data near *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) bl_tree[curlen].Freq++;
+ bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ bl_tree[REPZ_3_10].Freq++;
+ } else {
+ bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (tree, max_code)
+ ct_data near *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(curlen, bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(REP_3_6, bl_tree); send_bits(count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);
+
+ } else {
+ send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree()
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree((ct_data near *)dyn_ltree, l_desc.max_code);
+ scan_tree((ct_data near *)dyn_dtree, d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree((tree_desc near *)(&bl_desc));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(lcodes, dcodes, blcodes)
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(dcodes-1, 5);
+ send_bits(blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
+
+ send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
+
+ send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+ulg flush_block(buf, stored_len, eof)
+ char *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
+
+ /* Check if the file is ascii or binary */
+ if (*file_type == (ush)UNKNOWN) set_file_type();
+
+ /* Construct the literal and distance trees */
+ build_tree((tree_desc near *)(&l_desc));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+
+ build_tree((tree_desc near *)(&d_desc));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree();
+
+ /* Determine the best encoding. Compute first the block length in bytes */
+ opt_lenb = (opt_len+3+7)>>3;
+ static_lenb = (static_len+3+7)>>3;
+ input_len += stored_len; /* for debugging only */
+
+ Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+ opt_lenb, opt_len, static_lenb, static_len, stored_len,
+ last_lit, last_dist));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ /* If compression failed and this is the first and last block,
+ * and if the zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef FORCE_METHOD
+ if (level == 1 && eof && compressed_len == 0L) { /* force stored file */
+#else
+ if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
+#endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (char*)0) error ("block vanished");
+
+ copy_block(buf, (unsigned)stored_len, 0); /* without header */
+ compressed_len = stored_len << 3;
+ *file_method = STORED;
+
+#ifdef FORCE_METHOD
+ } else if (level == 2 && buf != (char*)0) { /* force stored block */
+#else
+ } else if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */
+ compressed_len = (compressed_len + 3 + 7) & ~7L;
+ compressed_len += (stored_len + 4) << 3;
+
+ copy_block(buf, (unsigned)stored_len, 1); /* with header */
+
+#ifdef FORCE_METHOD
+ } else if (level == 3) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits((STATIC_TREES<<1)+eof, 3);
+ compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree);
+ compressed_len += 3 + static_len;
+ } else {
+ send_bits((DYN_TREES<<1)+eof, 3);
+ send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
+ compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree);
+ compressed_len += 3 + opt_len;
+ }
+ Assert (compressed_len == bits_sent, "bad compressed size");
+ init_block();
+
+ if (eof) {
+ Assert (input_len == isize, "bad input size");
+ bi_windup();
+ compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3,
+ compressed_len-7*eof));
+
+ return compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ct_tally (dist, lc)
+ int dist; /* distance of matched string */
+ int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ l_buf[last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ dyn_ltree[lc].Freq++;
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match");
+
+ dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+ dyn_dtree[d_code(dist)].Freq++;
+
+ d_buf[last_dist++] = (ush)dist;
+ flags |= flag_bit;
+ }
+ flag_bit <<= 1;
+
+ /* Output the flags if they fill a byte: */
+ if ((last_lit & 7) == 0) {
+ flag_buf[last_flags++] = flags;
+ flags = 0, flag_bit = 1;
+ }
+ /* Try to guess if it is profitable to stop the current block here */
+ if (level > 2 && (last_lit & 0xfff) == 0) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)last_lit*8L;
+ ulg in_length = (ulg)strstart-block_start;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
+ last_lit, last_dist, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (last_dist < last_lit/2 && out_length < in_length/2) return 1;
+ }
+ return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE);
+ /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(ltree, dtree)
+ ct_data near *ltree; /* literal tree */
+ ct_data near *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned dx = 0; /* running index in d_buf */
+ unsigned fx = 0; /* running index in flag_buf */
+ uch flag = 0; /* current flags */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (last_lit != 0) do {
+ if ((lx & 7) == 0) flag = flag_buf[fx++];
+ lc = l_buf[lx++];
+ if ((flag & 1) == 0) {
+ send_code(lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = length_code[lc];
+ send_code(code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(lc, extra); /* send the extra length bits */
+ }
+ dist = d_buf[dx++];
+ /* Here, dist is the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+ flag >>= 1;
+ } while (lx < last_lit);
+
+ send_code(END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Set the file type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_file_type()
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += dyn_ltree[n++].Freq;
+ *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
+ if (*file_type == BINARY && translate_eol) {
+ warn("-l used on binary file", "");
+ }
+}
diff --git a/SrcShared/Gzip/util.c b/SrcShared/Gzip/util.c
new file mode 100644
index 0000000..ebaa053
--- /dev/null
+++ b/SrcShared/Gzip/util.c
@@ -0,0 +1,484 @@
+/* util.c -- utility functions for gzip support
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$Id: util.c,v 0.15 1993/06/15 09:04:13 jloup Exp $";
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+//#include <sys/types.h> // POSER
+
+#include "tailor.h"
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef NO_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
+# include <stdlib.h>
+#else
+ extern int errno;
+#endif
+
+#include "gzip.h"
+#include "crypt.h"
+
+extern ulg crc_32_tab[]; /* crc table, defined below */
+
+/* ===========================================================================
+ * Copy input to output unchanged: zcat == cat with --force.
+ * IN assertion: insize bytes have already been read in inbuf.
+ */
+int copy(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ errno = 0;
+ while (insize != 0 && (int)insize != EOF) {
+ write_buf(out, (char*)inbuf, insize);
+ bytes_out += insize;
+ insize = read(in, (char*)inbuf, INBUFSIZ);
+ }
+ if ((int)insize == EOF && errno != 0) {
+ read_error();
+ }
+ bytes_in = bytes_out;
+ return OK;
+}
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register. If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+ulg updcrc(s, n)
+ uch *s; /* pointer to bytes to pump through */
+ unsigned n; /* number of bytes in s[] */
+{
+ register ulg c; /* temporary variable */
+
+ static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+ if (s == NULL) {
+ c = 0xffffffffL;
+ } else {
+ c = crc;
+ if (n) do {
+ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+ } while (--n);
+ }
+ crc = c;
+ return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+ outcnt = 0;
+ insize = inptr = 0;
+ bytes_in = bytes_out = 0L;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty.
+ */
+int fill_inbuf(eof_ok)
+ int eof_ok; /* set if EOF acceptable as a result */
+{
+ int len;
+
+ /* Read as much as possible */
+ insize = 0;
+ errno = 0;
+ do {
+#if 0 // POSER
+ len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
+#else
+ len = read_buf((char*)inbuf+insize, INBUFSIZ-insize);
+#endif
+ if (len == 0 || len == EOF) break;
+ insize += len;
+ } while (insize < INBUFSIZ);
+
+ if (insize == 0) {
+ if (eof_ok) return EOF;
+ read_error();
+ }
+ bytes_in += (ulg)insize;
+ inptr = 1;
+ return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
+ * (used for the compressed data only)
+ */
+void flush_outbuf()
+{
+ if (outcnt == 0) return;
+
+ write_buf(ofd, (char *)outbuf, outcnt);
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+ if (outcnt == 0) return;
+ updcrc(window, outcnt);
+
+ if (!test) {
+ write_buf(ofd, (char *)window, outcnt);
+ }
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+/* ===========================================================================
+ * Does the same as write(), but also handles partial pipe writes and checks
+ * for error return.
+ */
+void write_buf(fd, buf, cnt)
+ int fd;
+ voidp buf;
+ unsigned cnt;
+{
+#if 0 // POSER
+ unsigned n;
+
+ while ((n = write(fd, buf, cnt)) != cnt) {
+ if (n == (unsigned)(-1)) {
+ write_error();
+ }
+ cnt -= n;
+ buf = (voidp)((char*)buf+n);
+ }
+#else
+ extern int (*write_buf_proc) OF((char *buf, unsigned size));
+ write_buf_proc(buf, cnt);
+#endif
+}
+
+/* ========================================================================
+ * Put string s in lower case, return s.
+ */
+char *strlwr(s)
+ char *s;
+{
+ char *t;
+ for (t = s; *t; t++) *t = tolow(*t);
+ return s;
+}
+
+/* ========================================================================
+ * Return the base name of a file (remove any directory prefix and
+ * any version suffix). For systems with file names that are not
+ * case sensitive, force the base name to lower case.
+ */
+#if 0 // POSER - conflicts with basename in GNU string.h
+char *basename(fname)
+ char *fname;
+{
+ char *p;
+
+ if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
+#ifdef PATH_SEP2
+ if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
+#endif
+#ifdef PATH_SEP3
+ if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
+#endif
+#ifdef SUFFIX_SEP
+ if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
+#endif
+ if (casemap('A') == 'a') strlwr(fname);
+ return fname;
+}
+#endif
+
+/* ========================================================================
+ * Make a file name legal for file systems not allowing file names with
+ * multiple dots or starting with a dot (such as MSDOS), by changing
+ * all dots except the last one into underlines. A target dependent
+ * function can be used instead of this simple function by defining the macro
+ * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
+ * dependent module.
+ */
+void make_simple_name(name)
+ char *name;
+{
+ char *p = strrchr(name, '.');
+ if (p == NULL) return;
+ if (p == name) p++;
+ do {
+ if (*--p == '.') *p = '_';
+ } while (p != name);
+}
+
+
+#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
+
+/* Provide missing strspn and strcspn functions. */
+
+# ifndef __STDC__
+# define const
+# endif
+
+int strspn OF((const char *s, const char *accept));
+int strcspn OF((const char *s, const char *reject));
+
+/* ========================================================================
+ * Return the length of the maximum initial segment
+ * of s which contains only characters in accept.
+ */
+int strspn(s, accept)
+ const char *s;
+ const char *accept;
+{
+ register const char *p;
+ register const char *a;
+ register int count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (a = accept; *a != '\0'; ++a) {
+ if (*p == *a) break;
+ }
+ if (*a == '\0') return count;
+ ++count;
+ }
+ return count;
+}
+
+/* ========================================================================
+ * Return the length of the maximum inital segment of s
+ * which contains no characters from reject.
+ */
+int strcspn(s, reject)
+ const char *s;
+ const char *reject;
+{
+ register int count = 0;
+
+ while (*s != '\0') {
+ if (strchr(reject, *s++) != NULL) return count;
+ ++count;
+ }
+ return count;
+}
+
+#endif /* NO_STRING_H */
+
+/* ========================================================================
+ * Add an environment variable (if any) before argv, and update argc.
+ * Return the expanded environment variable to be freed later, or NULL
+ * if no options were added to argv.
+ */
+#define SEPARATOR " \t" /* separators in env variable */
+
+#if 0 // POSER -- so we don't need xmalloc
+char *add_envopt(argcp, argvp, env)
+ int *argcp; /* pointer to argc */
+ char ***argvp; /* pointer to argv */
+ char *env; /* name of environment variable */
+{
+ char *p; /* running pointer through env variable */
+ char **oargv; /* runs through old argv array */
+ char **nargv; /* runs through new argv array */
+ int oargc = *argcp; /* old argc */
+ int nargc = 0; /* number of arguments in env variable */
+
+ env = (char*)getenv(env);
+ if (env == NULL) return NULL;
+
+ p = (char*)xmalloc(strlen(env)+1);
+ env = strcpy(p, env); /* keep env variable intact */
+
+ for (p = env; *p; nargc++ ) { /* move through env */
+ p += strspn(p, SEPARATOR); /* skip leading separators */
+ if (*p == '\0') break;
+
+ p += strcspn(p, SEPARATOR); /* find end of word */
+ if (*p) *p++ = '\0'; /* mark it */
+ }
+ if (nargc == 0) {
+ free(env);
+ return NULL;
+ }
+ *argcp += nargc;
+ /* Allocate the new argv array, with an extra element just in case
+ * the original arg list did not end with a NULL.
+ */
+ nargv = (char**)calloc(*argcp+1, sizeof(char *));
+ if (nargv == NULL) error("out of memory");
+ oargv = *argvp;
+ *argvp = nargv;
+
+ /* Copy the program name first */
+ if (oargc-- < 0) error("argc<=0");
+ *(nargv++) = *(oargv++);
+
+ /* Then copy the environment args */
+ for (p = env; nargc > 0; nargc--) {
+ p += strspn(p, SEPARATOR); /* skip separators */
+ *(nargv++) = p; /* store start */
+ while (*p++) ; /* skip over word */
+ }
+
+ /* Finally copy the old args and add a NULL (usual convention) */
+ while (oargc--) *(nargv++) = *(oargv++);
+ *nargv = NULL;
+ return env;
+}
+#endif
+
+/* ========================================================================
+ * Error handlers.
+ */
+void error(m)
+ char *m;
+{
+ fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
+
+ abort_gzip();
+}
+
+void warn(a, b)
+ char *a, *b; /* message strings juxtaposed in output */
+{
+ WARN((stderr, "%s: %s: warning: %s%s\n", progname, ifname, a, b));
+}
+
+void read_error()
+{
+ fprintf(stderr, "\n%s: ", progname);
+ if (errno != 0) {
+#if 0 // POSER
+ perror(ifname);
+#endif
+ } else {
+ fprintf(stderr, "%s: unexpected end of file\n", ifname);
+ }
+
+ abort_gzip();
+}
+
+void write_error()
+{
+ fprintf(stderr, "\n%s: ", progname);
+#if 0 // POSER
+ perror(ofname);
+#endif
+
+ abort_gzip();
+}
+
+/* ========================================================================
+ * Display compression ratio on the given stream on 6 characters.
+ */
+void display_ratio(num, den, file)
+ long num;
+ long den;
+ FILE *file;
+{
+ long ratio; /* 1000 times the compression ratio */
+
+ if (den == 0) {
+ ratio = 0; /* no compression */
+ } else if (den < 2147483L) { /* (2**31 -1)/1000 */
+ ratio = 1000L*num/den;
+ } else {
+ ratio = num/(den/1000L);
+ }
+ if (ratio < 0) {
+ putc('-', file);
+ ratio = -ratio;
+ } else {
+ putc(' ', file);
+ }
+ fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
+}
+
+
+/* ========================================================================
+ * Semi-safe malloc -- never returns NULL.
+ */
+#if 0 // POSER
+voidp xmalloc (size)
+ unsigned size;
+{
+ voidp cp = (voidp)malloc (size);
+
+ if (cp == NULL) error("out of memory");
+ return cp;
+}
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by makecrc.c)
+ */
+ulg crc_32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
diff --git a/SrcShared/Hardware/EmBankDRAM.cpp b/SrcShared/Hardware/EmBankDRAM.cpp
new file mode 100644
index 0000000..50b6d18
--- /dev/null
+++ b/SrcShared/Hardware/EmBankDRAM.cpp
@@ -0,0 +1,686 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Includes
+// ---------------------------------------------------------------------------
+
+#include "EmCommon.h"
+#include "EmBankDRAM.h"
+
+#include "DebugMgr.h" // Debug::CheckStepSpy
+#include "EmBankSRAM.h" // gRAMBank_Size, gRAM_Memory, gMemoryAccess
+#include "EmCPU.h" // GetSP
+#include "EmCPU68K.h" // gCPU68K
+#include "EmHAL.h" // EmHAL
+#include "EmMemory.h" // Memory::InitializeBanks, IsPCInRAM (implicitly, through META_CHECK)
+#include "EmPalmFunction.h" // InSysLaunch
+#include "EmPalmOS.h" // EmPalmOS::GetBootStack
+#include "EmPatchState.h" // META_CHECK calls EmPatchState::IsPCInMemMgr
+#include "EmScreen.h" // EmScreen::MarkDirty
+#include "EmSession.h" // gSession
+#include "MetaMemory.h" // MetaMemory
+#include "Profiling.h" // WAITSTATES_DRAM
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Types
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Functions
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Constants
+// ---------------------------------------------------------------------------
+
+const uint32 kMemoryStart = 0x00000000;
+const emuptr kGlobalStart = offsetof (LowMemHdrType, globals);
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Variables
+// ---------------------------------------------------------------------------
+
+// ----- Saved variables -----------------------------------------------------
+
+static uint32 gDynamicHeapSize;
+
+
+// ----- UnSaved variables ---------------------------------------------------
+
+static EmAddressBank gAddressBank =
+{
+ EmBankDRAM::GetLong,
+ EmBankDRAM::GetWord,
+ EmBankDRAM::GetByte,
+ EmBankDRAM::SetLong,
+ EmBankDRAM::SetWord,
+ EmBankDRAM::SetByte,
+ EmBankDRAM::GetRealAddress,
+ EmBankDRAM::ValidAddress,
+ EmBankDRAM::GetMetaAddress,
+ EmBankDRAM::AddOpcodeCycles
+};
+
+
+// ---------------------------------------------------------------------------
+#pragma mark ===== Inlines
+// ---------------------------------------------------------------------------
+
+static inline int InlineValidAddress (emuptr address, size_t size)
+{
+ int result = (address + size) <= gRAMBank_Size;
+
+ return result;
+}
+
+
+static inline uint8* InlineGetRealAddress (emuptr address)
+{
+ return (uint8*) &(gRAM_Memory[address]);
+}
+
+
+static inline uint8* InlineGetMetaAddress (emuptr address)
+{
+ return (uint8*) &(gRAM_MetaMemory[address]);
+}
+
+
+static void PrvReportBelowStackPointerAccess (emuptr address, size_t size, Bool forRead)
+{
+ // Can be NULL during bootup.
+
+ if (gStackLow == EmMemNULL)
+ return;
+
+ // SysLaunch clears out as much RAM as it can, including the area
+ // below the stack pointer.
+
+ if (::InSysLaunch ())
+ return;
+
+ // We can look in the stack for CJ_TAGFENCE, etc.
+
+ if (CEnableFullAccess::AccessOK ())
+ return;
+
+ // If the access is in the boot stack, allow it. There's a lot of memory
+ // allocation going on below the stack pointer, such that it's not too
+ // clear where the current "low end" of stack should be.
+
+ StackRange bootStack = EmPalmOS::GetBootStack ();
+ if (address >= bootStack.fBottom && address < bootStack.fTop)
+ return;
+
+ gSession->ScheduleDeferredError (new EmDeferredErrLowStack (
+ gStackLow, gCPU->GetSP (), gStackHigh,
+ address, size, forRead));
+}
+
+
+static inline void PrvCheckBelowStackPointerAccess (emuptr address, size_t size, Bool forRead)
+{
+#if 1
+ if (address < gCPU->GetSP () && address >= gStackLow)
+ {
+ ::PrvReportBelowStackPointerAccess (address, size, forRead);
+ }
+#endif
+}
+
+
+static inline void PrvScreenCheck (uint8* metaAddress, emuptr address, size_t size)
+{
+#if defined (macintosh)
+
+ if (size == 1 && !MetaMemory::IsScreenBuffer8 (metaAddress))
+ return;
+
+ if (size == 2 && !MetaMemory::IsScreenBuffer16 (metaAddress))
+ return;
+
+ if (size == 4 && !MetaMemory::IsScreenBuffer32 (metaAddress))
+ return;
+
+#else
+
+ if (MetaMemory::IsScreenBuffer (metaAddress, size))
+
+#endif
+
+ {
+ EmScreen::MarkDirty (address, size);
+ }
+}
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ DRAM Bank Accessors
+// ===========================================================================
+// These functions provide fetch and store access to the emulator's random
+// access memory.
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::Initialize (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::Reset (Bool /*hardwareReset*/)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::Load (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDRAM::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankDRAM::SetBankHandlers (void)
+{
+ // First few memory banks are managed by the functions in EmBankDRAM.
+
+ gDynamicHeapSize = EmHAL::GetDynamicHeapSize ();
+
+ if (gDynamicHeapSize > gRAMBank_Size)
+ gDynamicHeapSize = gRAMBank_Size;
+
+ uint32 sixtyFourK = 64 * 1024L;
+ uint32 numBanks = (gDynamicHeapSize + sixtyFourK - 1) / sixtyFourK;
+
+ Memory::InitializeBanks ( gAddressBank,
+ EmMemBankIndex (kMemoryStart),
+ numBanks);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDRAM::GetLong (emuptr address)
+{
+ if (address > gDynamicHeapSize)
+ return EmBankSRAM::GetLong (address);
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMLongRead]++;
+ if (address & 2)
+ gMemoryAccess[kDRAMLongRead2]++;
+#endif
+
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), true);
+ }
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, GetLong, uint32, true);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint32), true);
+
+ if (VALIDATE_DRAM_GET &&
+ gMemAccessFlags.fValidate_DRAMGet &&
+ !InlineValidAddress (address, sizeof (uint32)))
+ {
+ InvalidAccess (address, sizeof (uint32), true);
+ }
+
+#if (HAS_PROFILING)
+ CYCLE_GETLONG (WAITSTATES_DRAM);
+#endif
+
+ return EmMemDoGet32 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDRAM::GetWord (emuptr address)
+{
+ if (address > gDynamicHeapSize)
+ return EmBankSRAM::GetWord (address);
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMWordRead]++;
+#endif
+
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), true);
+ }
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, GetWord, uint16, true);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint16), true);
+
+ if (VALIDATE_DRAM_GET &&
+ gMemAccessFlags.fValidate_DRAMGet &&
+ !InlineValidAddress (address, sizeof (uint16)))
+ {
+ InvalidAccess (address, sizeof (uint16), true);
+ }
+
+#if (HAS_PROFILING)
+ CYCLE_GETWORD (WAITSTATES_DRAM);
+#endif
+
+ return EmMemDoGet16 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDRAM::GetByte (emuptr address)
+{
+ if (address > gDynamicHeapSize)
+ return EmBankSRAM::GetByte (address);
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMByteRead]++;
+#endif
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, GetByte, uint8, true);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint8), true);
+
+ if (VALIDATE_DRAM_GET &&
+ gMemAccessFlags.fValidate_DRAMGet &&
+ !InlineValidAddress (address, sizeof (uint8)))
+ {
+ InvalidAccess (address, sizeof (uint8), true);
+ }
+
+#if (HAS_PROFILING)
+ CYCLE_GETBYTE (WAITSTATES_DRAM);
+#endif
+
+ return EmMemDoGet8 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::SetLong (emuptr address, uint32 value)
+{
+ if (address > gDynamicHeapSize)
+ {
+ EmBankSRAM::SetLong (address, value);
+ return;
+ }
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMLongWrite]++;
+ if (address & 2)
+ gMemoryAccess[kDRAMLongWrite2]++;
+#endif
+
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), false);
+ }
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, SetLong, uint32, false);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint32), false);
+
+ if (VALIDATE_DRAM_SET &&
+ gMemAccessFlags.fValidate_DRAMSet &&
+ !InlineValidAddress (address, sizeof (uint32)))
+ {
+ InvalidAccess (address, sizeof (uint32), false);
+ }
+
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint32));
+
+#if (HAS_PROFILING)
+ CYCLE_PUTLONG (WAITSTATES_DRAM);
+#endif
+
+ EmMemDoPut32 (gRAM_Memory + address, value);
+
+#if FOR_LATER
+ // Mark that this memory location can now be read from.
+
+ MetaMemory::MarkLongInitialized (address);
+#endif
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint32));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::SetWord (emuptr address, uint32 value)
+{
+ if (address > gDynamicHeapSize)
+ {
+ EmBankSRAM::SetWord (address, value);
+ return;
+ }
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMWordWrite]++;
+#endif
+
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), false);
+ }
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, SetWord, uint16, false);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint16), false);
+
+ if (VALIDATE_DRAM_SET &&
+ gMemAccessFlags.fValidate_DRAMSet &&
+ !InlineValidAddress (address, sizeof (uint16)))
+ {
+ InvalidAccess (address, sizeof (uint16), false);
+ }
+
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint16));
+
+#if (HAS_PROFILING)
+ CYCLE_PUTWORD (WAITSTATES_DRAM);
+#endif
+
+ EmMemDoPut16 (gRAM_Memory + address, value);
+
+#if FOR_LATER
+ // Mark that this memory location can now be read from.
+
+ MetaMemory::MarkWordInitialized (address);
+#endif
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint16));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::SetByte (emuptr address, uint32 value)
+{
+ if (address > gDynamicHeapSize)
+ {
+ EmBankSRAM::SetByte (address, value);
+ return;
+ }
+
+#if (PROFILE_MEMORY)
+ gMemoryAccess[kDRAMByteWrite]++;
+#endif
+
+ register uint8* metaAddress = InlineGetMetaAddress (address);
+ META_CHECK (metaAddress, address, SetByte, uint8, false);
+
+ ::PrvCheckBelowStackPointerAccess (address, sizeof (uint8), false);
+
+ if (VALIDATE_DRAM_SET &&
+ gMemAccessFlags.fValidate_DRAMSet &&
+ !InlineValidAddress (address, sizeof (uint8)))
+ {
+ InvalidAccess (address, sizeof (uint8), false);
+ }
+
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint8));
+
+#if (HAS_PROFILING)
+ CYCLE_PUTBYTE (WAITSTATES_DRAM);
+#endif
+
+ EmMemDoPut8 (gRAM_Memory + address, value);
+
+#if FOR_LATER
+ // Mark that this memory location can now be read from.
+
+ MetaMemory::MarkByteInitialized (address);
+#endif
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint8));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankDRAM::ValidAddress (emuptr address, uint32 size)
+{
+ int result = InlineValidAddress (address, size);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankDRAM::GetRealAddress (emuptr address)
+{
+ return InlineGetRealAddress (address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankDRAM::GetMetaAddress (emuptr address)
+{
+ return InlineGetMetaAddress (address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::AddOpcodeCycles (void)
+{
+#if (HAS_PROFILING)
+ CYCLE_GETWORD (WAITSTATES_DRAM);
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::AddressError
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDRAM::ProbableCause
+// ---------------------------------------------------------------------------
+
+void EmBankDRAM::ProbableCause (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gSession);
+
+ Errors::EAccessType whatHappened = MetaMemory::GetWhatHappened (address, size, forRead);
+
+ switch (whatHappened)
+ {
+ case Errors::kOKAccess:
+ break;
+
+ case Errors::kLowMemAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrLowMemory (address, size, forRead));
+ break;
+
+ case Errors::kGlobalVarAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrSystemGlobals (address, size, forRead));
+ break;
+
+ case Errors::kScreenAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrScreen (address, size, forRead));
+ break;
+
+ case Errors::kMemMgrAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrMemMgrStructures (address, size, forRead));
+ break;
+
+ case Errors::kFreeChunkAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrFreeChunk (address, size, forRead));
+ break;
+
+ case Errors::kUnlockedChunkAccess:
+ gSession->ScheduleDeferredError (new EmDeferredErrUnlockedChunk (address, size, forRead));
+ break;
+
+ case Errors::kUnknownAccess:
+ case Errors::kLowStackAccess:
+ EmAssert (false);
+ MetaMemory::GetWhatHappened (address, size, forRead);
+ }
+}
diff --git a/SrcShared/Hardware/EmBankDRAM.h b/SrcShared/Hardware/EmBankDRAM.h
new file mode 100644
index 0000000..c247649
--- /dev/null
+++ b/SrcShared/Hardware/EmBankDRAM.h
@@ -0,0 +1,49 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankDRAM_h
+#define EmBankDRAM_h
+
+
+class SessionFile;
+
+class EmBankDRAM
+{
+ public:
+ static void Initialize (void);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static void AddOpcodeCycles (void);
+
+ private:
+ static void AddressError (emuptr address, long size, Bool forRead);
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+ static void ProbableCause (emuptr address, long size, Bool forRead);
+};
+
+
+#endif /* EmBankDRAM_h */
diff --git a/SrcShared/Hardware/EmBankDummy.cpp b/SrcShared/Hardware/EmBankDummy.cpp
new file mode 100644
index 0000000..356b542
--- /dev/null
+++ b/SrcShared/Hardware/EmBankDummy.cpp
@@ -0,0 +1,326 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmBankDummy.h"
+
+#include "EmBankDRAM.h" // EmBankDRAM::ValidAddress
+#include "EmBankSRAM.h" // EmBankSRAM::GetMemoryStart
+#include "EmCPU68K.h" // gCPU68K
+#include "EmPalmHeap.h" // EmPalmHeap::GetHeapByPtr
+#include "EmMemory.h" // Memory::InitializeBanks
+
+
+// ===========================================================================
+// ¥ Dummy Bank Accessors
+// ===========================================================================
+// Dummy banks are non-existent blocks of memory. Dummy bank accessors do
+// not do anything.
+
+static EmAddressBank gAddressBank =
+{
+ EmBankDummy::GetLong,
+ EmBankDummy::GetWord,
+ EmBankDummy::GetByte,
+ EmBankDummy::SetLong,
+ EmBankDummy::SetWord,
+ EmBankDummy::SetByte,
+ EmBankDummy::GetRealAddress,
+ EmBankDummy::ValidAddress,
+ EmBankDummy::GetMetaAddress,
+ EmBankDummy::AddOpcodeCycles
+};
+
+
+inline Bool HackForHwrGetRAMSize (emuptr address)
+{
+// if ((address & 0xFF000000) == EmBankSRAM::GetMemoryStart ())
+ if (address == EmBankSRAM::GetMemoryStart () + gRAMBank_Size)
+ return true;
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDummy::Initialize (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDummy::Reset (Bool /*hardwareReset*/)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDummy::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDummy::Load (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankDummy::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankDummy::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankDummy::SetBankHandlers (void)
+{
+ Memory::InitializeBanks (gAddressBank, 0, 0xFFFF);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDummy::GetLong (emuptr address)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return 0;
+
+ InvalidAccess (address, sizeof (uint32), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDummy::GetWord (emuptr address)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return 0;
+
+ InvalidAccess (address, sizeof (uint16), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankDummy::GetByte (emuptr address)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return 0;
+
+ InvalidAccess (address, sizeof (uint8), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankDummy::SetLong (emuptr address, uint32)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return;
+
+ InvalidAccess (address, sizeof (uint32), true);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankDummy::SetWord (emuptr address, uint32)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return;
+
+ InvalidAccess (address, sizeof (uint16), true);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankDummy::SetByte (emuptr address, uint32)
+{
+ // Hack to keep HwrGetRAMSize working: it runs off
+ // the end of RAM while testing it.
+
+ if (HackForHwrGetRAMSize (address))
+ return;
+
+ InvalidAccess (address, sizeof (uint8), true);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankDummy::ValidAddress (emuptr, uint32)
+{
+ int result = false;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankDummy::GetRealAddress (emuptr address)
+{
+ return (uint8*) address;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankDummy::GetMetaAddress (emuptr address)
+{
+ UNUSED_PARAM(address)
+
+ static uint8 dummyBits[4] = {0, 0, 0, 0};
+
+ return dummyBits;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankDummy::AddOpcodeCycles (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankDummy::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankDummy::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ if (CEnableFullAccess::AccessOK ())
+ return;
+
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
diff --git a/SrcShared/Hardware/EmBankDummy.h b/SrcShared/Hardware/EmBankDummy.h
new file mode 100644
index 0000000..a6ed0de
--- /dev/null
+++ b/SrcShared/Hardware/EmBankDummy.h
@@ -0,0 +1,47 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankDummy_h
+#define EmBankDummy_h
+
+
+class SessionFile;
+
+class EmBankDummy
+{
+ public:
+ static void Initialize (void);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static void AddOpcodeCycles (void);
+
+ private:
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+};
+
+
+#endif /* EmBankDummy_h */
diff --git a/SrcShared/Hardware/EmBankMapped.cpp b/SrcShared/Hardware/EmBankMapped.cpp
new file mode 100644
index 0000000..8ae284a
--- /dev/null
+++ b/SrcShared/Hardware/EmBankMapped.cpp
@@ -0,0 +1,723 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmBankMapped.h"
+
+#include "EmCPU68K.h" // gCPU68K
+#include "EmMemory.h" // Memory::InitializeBanks
+#include "Profiling.h" // WAITSTATES_DUMMYBANK
+
+#include <vector>
+
+
+// ===========================================================================
+// ¥ Dummy Bank Accessors
+// ===========================================================================
+// Dummy banks are non-existent blocks of memory. Dummy bank accessors do
+// not do anything.
+
+static EmAddressBank gAddressBank =
+{
+ EmBankMapped::GetLong,
+ EmBankMapped::GetWord,
+ EmBankMapped::GetByte,
+ EmBankMapped::SetLong,
+ EmBankMapped::SetWord,
+ EmBankMapped::SetByte,
+ EmBankMapped::GetRealAddress,
+ EmBankMapped::ValidAddress,
+ EmBankMapped::GetMetaAddress,
+ EmBankMapped::AddOpcodeCycles
+};
+
+struct MapRange
+{
+ Bool Contains (const void* addr)
+ {
+ const char* begin = (const char*) this->realAddress;
+ const char* end = begin + this->size;
+
+ return ((addr >= begin) && (addr < end));
+ }
+
+ Bool Contains (emuptr addr)
+ {
+ emuptr begin = this->mappedAddress;
+ emuptr end = begin + this->size;
+
+ return ((addr >= begin) && (addr < end));
+ }
+
+ const void* realAddress; // Address in host's space
+ emuptr mappedAddress; // Address that emulated code sees
+ uint32 size;
+};
+typedef vector<MapRange> MapRangeList;
+
+static MapRangeList gMappedRanges;
+static MapRangeList::iterator gLastIter;
+
+// Map in blocks starting at this address. I used to have it way out of
+// the way at 0x60000000. However, there's a check in SysGetAppInfo to
+// make sure that certain addresses are less than 0x20000000. So set
+// kMemoryStart lower than that.
+//
+// OK...Let's try again. I had changed this to manage 0x18000000 to
+// 0x1FFFFFFF. However, the SED 1375 is mapped to 0x1F000000. So let's
+// make sure we stay out of that range, too.
+//
+// Urm...TRG is mapping some stuff into 0x18000000. Now we have to stay
+// out of its way, too.
+
+const emuptr kMemoryStart = 0x13000000;
+const emuptr kMemoryFinish = 0x18000000;
+const int32 kMemorySize = kMemoryFinish - kMemoryStart; // 80MB
+
+static MapRangeList::iterator PrvGetMappingInfo (const void* addr);
+static MapRangeList::iterator PrvGetMappingInfo (emuptr addr);
+static emuptr PrvEnsureAligned (emuptr candidate, const void* addr);
+static void PrvInvalidateCache (void);
+static void PrvCheckRanges (void);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankMapped::Initialize (void)
+{
+ gMappedRanges.clear ();
+ ::PrvInvalidateCache ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankMapped::Reset (Bool /*hardwareReset*/)
+{
+ // Note: I used to clear out the mapped ranges in this function.
+ // However, this didn't work out too well. While manually resetting
+ // the device (as occurs at the end of a debugging session), there
+ // would be several StMemoryMapper objects instantiated. After the
+ // reset process, these StMemoryMappers would try to destruct
+ // themselves, calling EmBankMapped::UnmapPhysicalMemory in the
+ // process. But since the mapped ranges had been cleared, that
+ // function would throw an assert. So....I can't think of a reason
+ // for clearing out the ranges en masse, so let's no do that anymore.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankMapped::Save (SessionFile&)
+{
+ // The only state we have to save is in gMappedRanges. We shouldn't
+ // have to actually save this because there shouldn't be anything in
+ // there at the moment when we save files. We map in memory ranges
+ // at the following times:
+ //
+ // * Calling system functions
+ // * Loading .prc, etc., files
+ // * Mapping in environment strings
+ //
+ // The first two should not be in "effect" at the time we save a file.
+ // The last one we'll leave up to the HostControl system to re-establish.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankMapped::Load (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankMapped::Dispose (void)
+{
+ gMappedRanges.clear ();
+ ::PrvInvalidateCache ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankMapped::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankMapped::SetBankHandlers (void)
+{
+ Memory::InitializeBanks (gAddressBank, EmMemBankIndex (kMemoryStart), kMemorySize >> 16);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankMapped::GetLong (emuptr address)
+{
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), true);
+ }
+
+#if HAS_PROFILING
+ CYCLE_GETLONG (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return ~0;
+ }
+
+ return (((uint32) p[0]) << 24) | (((uint32) p[1]) << 16) | (((uint32) p[2]) << 8) | p[3];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankMapped::GetWord (emuptr address)
+{
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), true);
+ }
+
+#if HAS_PROFILING
+ CYCLE_GETWORD (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return ~0;
+ }
+
+ return (((uint32) p[0]) << 8) | p[1];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankMapped::GetByte (emuptr address)
+{
+#if HAS_PROFILING
+ CYCLE_GETBYTE (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return ~0;
+ }
+
+ return p[0];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::SetLong (emuptr address, uint32 value)
+{
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), false);
+ }
+
+#if HAS_PROFILING
+ CYCLE_PUTLONG (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p[0] = (uint8) (value >> 24);
+ p[1] = (uint8) (value >> 16);
+ p[2] = (uint8) (value >> 8);
+ p[3] = (uint8) (value >> 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::SetWord (emuptr address, uint32 value)
+{
+ if (CHECK_FOR_ADDRESS_ERROR && (address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), false);
+ }
+
+#if HAS_PROFILING
+ CYCLE_PUTWORD (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p[0] = (uint8) (value >> 8);
+ p[1] = (uint8) (value >> 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::SetByte (emuptr address, uint32 value)
+{
+#if HAS_PROFILING
+ CYCLE_PUTBYTE (WAITSTATES_DUMMYBANK);
+#endif
+
+ uint8* p = GetRealAddress (address);
+
+ if (p == NULL)
+ {
+ return;
+ }
+
+ p[0] = (uint8) (value >> 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankMapped::ValidAddress (emuptr address, uint32)
+{
+ uint8* realAddress = GetRealAddress (address);
+ int result = realAddress != NULL;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankMapped::GetRealAddress (emuptr address)
+{
+ MapRangeList::iterator iter = ::PrvGetMappingInfo (address);
+
+ if (iter == gMappedRanges.end ())
+ return NULL;
+
+ return ((uint8*) iter->realAddress) + (address - iter->mappedAddress);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankMapped::GetMetaAddress (emuptr address)
+{
+ UNUSED_PARAM(address)
+
+ static uint8 dummyBits[4] = {0, 0, 0, 0};
+
+ return dummyBits;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetEmulatedAddress
+// ---------------------------------------------------------------------------
+
+emuptr EmBankMapped::GetEmulatedAddress (const void* address)
+{
+ MapRangeList::iterator iter = ::PrvGetMappingInfo (address);
+
+ if (iter == gMappedRanges.end ())
+ {
+ EmAssert (false);
+ return EmMemNULL;
+ }
+
+ return iter->mappedAddress + ((char*) address - (char*) iter->realAddress);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::AddOpcodeCycles (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::AddressError
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::MapPhysicalMemory
+// ---------------------------------------------------------------------------
+// Maps a range of physical memory to appear at the same location of the
+// emulated Palm OS's virtual memory.
+
+void EmBankMapped::MapPhysicalMemory (const void* addr, uint32 size)
+{
+ if (addr == NULL)
+ return;
+
+ emuptr candidate = ::PrvEnsureAligned (kMemoryStart, addr);
+
+ // If the list is empty, add the item
+
+ if (gMappedRanges.size () == 0)
+ {
+ MapRange range;
+
+ range.realAddress = addr;
+ range.mappedAddress = candidate;
+ range.size = size;
+
+ gLastIter = gMappedRanges.insert (gMappedRanges.begin (), range);
+ ::PrvCheckRanges ();
+
+// ::PrvInvalidateCache ();
+
+ return;
+ }
+
+ // Find an available space for the range.
+
+ MapRangeList::iterator iter = gMappedRanges.begin ();
+
+ while (iter != gMappedRanges.end ())
+ {
+ // If there's room in front of the current block...
+
+ if (iter->mappedAddress >= candidate + size)
+ {
+ // ...insert a map record in front of the current block.
+
+ MapRange range;
+
+ range.realAddress = addr;
+ range.mappedAddress = candidate;
+ range.size = size;
+
+ gLastIter = gMappedRanges.insert (iter, range);
+ ::PrvCheckRanges ();
+
+// ::PrvInvalidateCache ();
+
+ return;
+ }
+
+ // No room at the inn...move onto the next block.
+
+ candidate = ::PrvEnsureAligned (iter->mappedAddress + iter->size, addr);
+ ++iter;
+ }
+
+ // Couldn't find room at the beginning or the middle of the list. Add to the end.
+
+ MapRangeList::iterator last = gMappedRanges.end ();
+ iter = last - 1;
+
+ MapRange range;
+
+ range.realAddress = addr;
+ range.mappedAddress = ::PrvEnsureAligned (iter->mappedAddress + iter->size, addr);
+ range.size = size;
+
+ gLastIter = gMappedRanges.insert (last, range);
+ ::PrvCheckRanges ();
+
+// ::PrvInvalidateCache ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::UnmapPhysicalMemory
+// ---------------------------------------------------------------------------
+// Unmaps a range of physical memory from appearing at the same location of
+// the emulated Palm OS's virtual memory.
+
+void EmBankMapped::UnmapPhysicalMemory (const void* addr)
+{
+ if (addr == NULL)
+ return;
+
+ MapRangeList::iterator iter = ::PrvGetMappingInfo (addr);
+
+ // Take out this assert. Without it, it's possible to unmap ranges
+ // of memory that we may not have actually mapped in. Being able to
+ // do that makes things like Reset and Dispose methods easier to write.
+// EmAssert (iter != gMappedRanges.end ());
+
+ if (iter != gMappedRanges.end ())
+ {
+ gMappedRanges.erase (iter);
+ ::PrvCheckRanges ();
+
+ ::PrvInvalidateCache ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankMapped::GetMappingInfo
+// ---------------------------------------------------------------------------
+
+void EmBankMapped::GetMappingInfo (emuptr addr, void** start, uint32* len)
+{
+ MapRangeList::iterator iter = ::PrvGetMappingInfo (addr);
+
+ if (iter != gMappedRanges.end ())
+ {
+ if (start)
+ *start = (void*) iter->realAddress;
+
+ if (len)
+ *len = iter->size;
+ }
+ else
+ {
+ if (start)
+ *start = NULL;
+
+ if (len)
+ *len = 0;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetMappingInfo
+// ---------------------------------------------------------------------------
+
+MapRangeList::iterator PrvGetMappingInfo (const void* addr)
+{
+ if (gLastIter != gMappedRanges.end () && gLastIter->Contains (addr))
+ return gLastIter;
+
+ MapRangeList::iterator iter = gMappedRanges.begin ();
+ while (iter != gMappedRanges.end ())
+ {
+ if (iter->Contains (addr))
+ break;
+
+ ++iter;
+ }
+
+ gLastIter = iter;
+
+ return iter;
+}
+
+
+MapRangeList::iterator PrvGetMappingInfo (emuptr addr)
+{
+ if (gLastIter != gMappedRanges.end () && gLastIter->Contains (addr))
+ return gLastIter;
+
+ MapRangeList::iterator iter = gMappedRanges.begin ();
+ while (iter != gMappedRanges.end ())
+ {
+ if (iter->Contains (addr))
+ break;
+
+ ++iter;
+ }
+
+ gLastIter = iter;
+
+ return iter;
+}
+
+
+emuptr PrvEnsureAligned (emuptr candidate, const void* addr)
+{
+ // Make sure that "candidate" -- which is the candidate
+ // mapped address -- maintains the same alignment as
+ // the incoming address.
+
+ while ((candidate & 0x03) != ((uint32) addr & 0x03))
+ ++candidate;
+
+ return candidate;
+}
+
+void PrvInvalidateCache (void)
+{
+ gLastIter = gMappedRanges.end ();
+}
+
+void PrvCheckRanges (void)
+{
+#if _DEBUG
+ /*
+ Check for overlaps. We iterate over the container with
+ two iterators: outerIter and innerIter. These two iterators
+ will allow us to compare all possible combinations of
+ elements in the container.
+
+ When checking for overlaps, there are six cases to consider:
+
+ *-----------* Segment A
+
+ *---* Possible segment B's.
+ *----------*
+ *---------------------------*
+ *---*
+ *---------------*
+ *---*
+
+ An overlap occurs if any part of segment B crosses segment A.
+ From the drawing, we can see that the first and last possible
+ segments B's are OK; the others overlap with segment A in
+ some fashion. Thus, Segment B is OK if it's end is less than
+ Segment A's start, or its start is greater than segment A's end.
+ */
+
+ MapRangeList::iterator outerIter = gMappedRanges.begin ();
+ while (outerIter != gMappedRanges.end ())
+ {
+ MapRangeList::iterator innerIter = outerIter + 1;
+ while (innerIter != gMappedRanges.end ())
+ {
+ char* outerStart = (char*) outerIter->realAddress;
+ char* innerStart = (char*) innerIter->realAddress;
+
+ char* outerEnd = outerStart + outerIter->size;
+ char* innerEnd = innerStart + innerIter->size;
+
+ if (innerEnd > outerStart && innerStart < outerEnd)
+ {
+ EmAssert (false);
+ }
+
+ ++innerIter;
+ }
+
+ ++outerIter;
+ }
+#endif
+}
+
diff --git a/SrcShared/Hardware/EmBankMapped.h b/SrcShared/Hardware/EmBankMapped.h
new file mode 100644
index 0000000..033c749
--- /dev/null
+++ b/SrcShared/Hardware/EmBankMapped.h
@@ -0,0 +1,55 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankMapped_h
+#define EmBankMapped_h
+
+
+class SessionFile;
+
+class EmBankMapped
+{
+ public:
+ static void Initialize (void);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static emuptr GetEmulatedAddress (const void* address);
+ static void AddOpcodeCycles (void);
+
+ static void MapPhysicalMemory (const void*, uint32);
+ static void UnmapPhysicalMemory (const void*);
+
+ static void GetMappingInfo (emuptr addr, void** start, uint32* len);
+
+
+ private:
+ static void AddressError (emuptr address, long size, Bool forRead);
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+};
+
+
+#endif /* EmBankMapped_h */
diff --git a/SrcShared/Hardware/EmBankROM.cpp b/SrcShared/Hardware/EmBankROM.cpp
new file mode 100644
index 0000000..67cb46e
--- /dev/null
+++ b/SrcShared/Hardware/EmBankROM.cpp
@@ -0,0 +1,1617 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmBankROM.h"
+
+#include "Byteswapping.h" // ByteswapWords
+#include "EmCPU68K.h" // gCPU68K
+#include "EmErrCodes.h" // kError_UnsupportedROM
+#include "EmHAL.h" // EmHAL
+#include "EmMemory.h" // Memory::InitializeBanks, EmMem_memset
+#include "EmPalmStructs.h" // EmProxyCardHeaderType
+#include "EmSession.h" // GetDevice, ScheduleDeferredError
+#include "ErrorHandling.h" // Errors::Throw
+#include "Miscellaneous.h" // StWordSwapper, NextPowerOf2
+#include "Profiling.h" // WAITSTATES_ROM
+#include "SessionFile.h" // WriteROMFileReference
+#include "Strings.r.h" // kStr_BadChecksum
+
+
+// Private function declarations
+
+
+class Card
+{
+ public:
+ static Bool CheckCardHeader (const EmProxyCardHeaderType& cardHdr);
+ static Bool CheckChecksum (const void* p, uint32 romLength);
+ static Bool Supports328 (const EmAliasCardHeaderType<LAS>& cardHdr);
+ static Bool SupportsEZ (const EmAliasCardHeaderType<LAS>& cardHdr);
+ static Bool SupportsVZ (const EmAliasCardHeaderType<LAS>& cardHdr);
+ static Bool SupportsSZ (const EmAliasCardHeaderType<LAS>& cardHdr);
+};
+
+
+// static member initialization
+
+emuptr EmBankROM::gROMMemoryStart = kDefaultROMMemoryStart;
+
+// ===========================================================================
+// ¥ ROM Bank Accessors
+// ===========================================================================
+// These functions provide fetch and store access to the emulator's read only
+// memory.
+
+static EmAddressBank gROMAddressBank =
+{
+ EmBankROM::GetLong,
+ EmBankROM::GetWord,
+ EmBankROM::GetByte,
+ EmBankROM::SetLong,
+ EmBankROM::SetWord,
+ EmBankROM::SetByte,
+ EmBankROM::GetRealAddress,
+ EmBankROM::ValidAddress,
+ EmBankROM::GetMetaAddress,
+ EmBankROM::AddOpcodeCycles
+};
+
+static uint32 gROMBank_Size;
+static uint32 gManagedROMSize;
+static uint32 gROMImage_Size;
+static uint32 gROMBank_Mask;
+static uint8* gROM_Memory;
+static uint8* gROM_MetaMemory;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankROM::Initialize (EmStream& romStream)
+{
+ // When creating a new session, Initialize is called followed by
+ // Reset. When loading a session, Initialize is called by Load.
+ // So it makes sense to load the ROM image here. However, when
+ // reloading a session as part of a Gremlin Horde, only Load is
+ // called, so it is critical that all parts of a horde use the
+ // same ROM image.
+
+ EmBankROM::LoadROM (romStream);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankROM::Reset (Bool /*hardwareReset*/)
+{
+ memset (gROM_MetaMemory, 0, gROMImage_Size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankROM::Save (SessionFile& f)
+{
+ EmAssert (gSession);
+ Configuration cfg = gSession->GetConfiguration ();
+ f.WriteROMFileReference (cfg.fROMFile);
+
+ StWordSwapper swapper1 (gROM_MetaMemory, gROMImage_Size);
+ f.WriteMetaROMImage (gROM_MetaMemory, gROMImage_Size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankROM::Load (SessionFile& f)
+{
+ // ROM reference was read when the basic configuration was read
+ // and passed to EmSession::Initialize, which then called
+ // EmBankROM::Initialize, which then called EmBankROM::LoadROM.
+
+ EmAssert (gROM_MetaMemory != NULL);
+
+ if (f.ReadMetaROMImage (gROM_MetaMemory))
+ {
+ ByteswapWords (gROM_MetaMemory, gROMImage_Size);
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankROM::Dispose (void)
+{
+ Platform::DisposeMemory (gROM_Memory);
+ Platform::DisposeMemory (gROM_MetaMemory);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankROM::SetBankHandlers (void)
+{
+ if (EmHAL::ChipSelectsConfigured ())
+ {
+ gROMMemoryStart = EmHAL::GetROMBaseAddress ();
+ }
+
+ gManagedROMSize = EmHAL::GetROMSize ();
+
+ // Memory banks gROMMemoryStart to <mumble> are managed by the functions
+ // in EmBankROM. <mumble> is based on the amount of ROM being emulated.
+
+ uint32 first_bank = EmMemBankIndex (EmBankROM::GetMemoryStart ());
+ uint32 last_bank = EmMemBankIndex (EmBankROM::GetMemoryStart () + gManagedROMSize - 1);
+
+ Memory::InitializeBanks ( gROMAddressBank, first_bank,
+ last_bank - first_bank + 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankROM::GetLong (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMLongRead]++;
+ if (address & 2)
+ gMemoryAccess[kROMLongRead2]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (VALIDATE_ROM_GET)
+ if (gMemAccessFlags.fValidate_ROMGet && !ValidAddress (address, sizeof (uint32)))
+ {
+ InvalidAccess (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (PREVENT_USER_ROM_GET || PREVENT_SYSTEM_ROM_GET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_GET && gMemAccessFlags.fProtect_ROMGet)
+ {
+ InvalidAccess (address, sizeof (uint32), true);
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_GET && gMemAccessFlags.fProtect_SysROMGet)
+ {
+ InvalidAccess (address, sizeof (uint32), true);
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETLONG (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ return EmMemDoGet32 (gROM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankROM::GetWord (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMWordRead]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (VALIDATE_ROM_GET)
+ if (gMemAccessFlags.fValidate_ROMGet && !ValidAddress (address, sizeof (uint16)))
+ {
+ InvalidAccess (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (PREVENT_USER_ROM_GET || PREVENT_SYSTEM_ROM_GET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_GET && gMemAccessFlags.fProtect_ROMGet)
+ {
+ InvalidAccess (address, sizeof (uint16), true);
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_GET && gMemAccessFlags.fProtect_SysROMGet)
+ {
+ InvalidAccess (address, sizeof (uint16), true);
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETWORD (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ return EmMemDoGet16 (gROM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankROM::GetByte (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMByteRead]++;
+#endif
+
+#if (VALIDATE_ROM_GET)
+ if (gMemAccessFlags.fValidate_ROMGet && !ValidAddress (address, sizeof (uint8)))
+ {
+ InvalidAccess (address, sizeof (uint8), true);
+ }
+#endif
+
+#if (PREVENT_USER_ROM_GET || PREVENT_SYSTEM_ROM_GET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_GET && gMemAccessFlags.fProtect_ROMGet)
+ {
+ InvalidAccess (address, sizeof (uint8), true);
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_GET && gMemAccessFlags.fProtect_SysROMGet)
+ {
+ InvalidAccess (address, sizeof (uint8), true);
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETBYTE (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ return EmMemDoGet8 (gROM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankROM::SetLong (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMLongWrite]++;
+ if (address & 2)
+ gMemoryAccess[kROMLongWrite2]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), false);
+ }
+#endif
+
+ EmAssert (ValidAddress (address, sizeof (uint32)));
+
+#if (PREVENT_USER_ROM_SET || PREVENT_SYSTEM_ROM_SET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_SET && gMemAccessFlags.fProtect_ROMSet)
+ {
+ InvalidAccess (address, sizeof (uint32), false);
+ return;
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_SET && gMemAccessFlags.fProtect_SysROMSet)
+ {
+ InvalidAccess (address, sizeof (uint32), false);
+ return;
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ // writing to ROM?? don't know what to make of this
+ CYCLE_PUTLONG (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ EmMemDoPut32 (gROM_Memory + address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankROM::SetWord (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMWordWrite]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), false);
+ }
+#endif
+
+ EmAssert (ValidAddress (address, sizeof (uint16)));
+
+#if (PREVENT_USER_ROM_SET || PREVENT_SYSTEM_ROM_SET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_SET && gMemAccessFlags.fProtect_ROMSet)
+ {
+ InvalidAccess (address, sizeof (uint16), false);
+ return;
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_SET && gMemAccessFlags.fProtect_SysROMSet)
+ {
+ InvalidAccess (address, sizeof (uint16), false);
+ return;
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ // writing to ROM?? don't know what to make of this
+ CYCLE_PUTWORD (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ EmMemDoPut16 (gROM_Memory + address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankROM::SetByte (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kROMByteWrite]++;
+#endif
+
+ EmAssert (ValidAddress (address, sizeof (uint8)));
+
+#if (PREVENT_USER_ROM_SET || PREVENT_SYSTEM_ROM_SET)
+ if (EmMemory::IsPCInRAM ())
+ {
+ if (PREVENT_USER_ROM_SET && gMemAccessFlags.fProtect_ROMSet)
+ {
+ InvalidAccess (address, sizeof (uint8), false);
+ return;
+ }
+ }
+ else
+ {
+ if (PREVENT_SYSTEM_ROM_SET && gMemAccessFlags.fProtect_SysROMSet)
+ {
+ InvalidAccess (address, sizeof (uint8), false);
+ return;
+ }
+ }
+#endif
+
+#if HAS_PROFILING
+ // writing to ROM?? don't know what to make of this
+ CYCLE_PUTBYTE (WAITSTATES_ROM);
+#endif
+
+ address &= gROMBank_Mask;
+
+ EmMemDoPut8 (gROM_Memory + address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankROM::ValidAddress (emuptr address, uint32 size)
+{
+ address -= gROMMemoryStart;
+ int result = (address + size) <= (gROMMemoryStart + gROMBank_Size);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankROM::GetRealAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gROMBank_Mask;
+
+ return (uint8*) &gROM_Memory[address];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankROM::GetMetaAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gROMBank_Mask;
+
+ return (uint8*) &(gROM_MetaMemory[address]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankROM::AddOpcodeCycles (void)
+{
+#if (HAS_PROFILING)
+ CYCLE_GETWORD (WAITSTATES_ROM);
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::AddressError
+// ---------------------------------------------------------------------------
+
+void EmBankROM::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankROM::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankROM::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (new EmDeferredErrROM (address, size, forRead));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankROM::LoadROM
+ *
+ * DESCRIPTION: Does the work of actually loading (and validating a ROM
+ * from a stream.
+ *
+ * PARAMETERS: EmStream hROM
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankROM::LoadROM (EmStream& hROM)
+{
+ // Make sure the file is big enough to have a card header.
+
+ if (hROM.GetLength() < (long) EmProxyCardHeaderType::GetSize ())
+ Errors::Throw (kError_BadROM);
+
+ // Read the card header.
+
+ EmProxyCardHeaderType cardHeader;
+ hROM.GetBytes (cardHeader.GetPtr (), cardHeader.GetSize ());
+
+ // Validate the card header.
+
+ if (!Card::CheckCardHeader (cardHeader))
+ Errors::Throw (kError_BadROM);
+
+ // The ROM is made up of two parts: a Big ROM and a Small ROM. ROM image
+ // files can contain both parts or just the Big ROM part. If it contains
+ // both parts, then everything is just fine, and we can use it no problem.
+ // If the Small ROM part is missing, we have to detect that, dummy up a
+ // small ROM for correct operation, and relocate the Big ROM higher in memory.
+
+ // Both the Big ROM and Small ROM start off with a CardHeaderType struct.
+ // We just read in one of them. Let's look at where the Big ROM _should_
+ // be to see if there's another CardHeader there. If so, we have both parts.
+ // If not, we have just the Big ROM.
+
+ int32 bigROMOffset;
+
+ if (cardHeader.hdrVersion == 1)
+ {
+ bigROMOffset = 0x3000;
+ }
+ else
+ {
+ // Version 2 CardHeaders contain a "bigROMOffset" field that contains the
+ // offset from the beginning of the card to where the ROM should
+ // appear in memory. Normally the card appears at 0x10000000 (which
+ // would make bigROMOffset something like 0x00C08000), but that
+ // isn't always the case. The problem is, we don't always know
+ // where the card beginning will be. For now, we'll assume that
+ // the ROM wants to live at 0x10C00000, and that the Big ROM will
+ // want to begin somewhere soon after that. This means we can get by
+ // with using only the lower bits of bigROMOffset.
+
+ bigROMOffset = cardHeader.bigROMOffset;
+ bigROMOffset &= 0x000FFFFF; // Allows for 1 Meg offset.
+ }
+
+ // Make sure the file is big enough to have a Big ROM.
+
+ if (hROM.GetLength() < bigROMOffset)
+ Errors::Throw (kError_BadROM);
+
+ // We'll use bigROMOffset for later to get to some Big ROM data.
+ // But we'll also need a value when we read the ROM image into
+ // memory. This value will be used as an offset into a buffer
+ // where we'll be reading the ROM image. If we have a Small ROM,
+ // the offset will be zero. If we have only a Big ROM, the offset
+ // will be the same value as bigROMOffset.
+
+ uint32 bufferOffset = bigROMOffset;
+
+ // See if there's a card header there, too.
+
+ EmProxyCardHeaderType cardHeader2;
+ hROM.SetMarker (bigROMOffset, kStreamFromStart);
+ hROM.GetBytes (cardHeader2.GetPtr (), cardHeader2.GetSize ());
+
+ if (Card::CheckCardHeader (cardHeader2))
+ {
+ // Looks like, so we don't have to relocate the ROM image.
+
+ bufferOffset = 0;
+ }
+
+ // The ROM size is now the size of the file plus any offset for
+ // any small ROM that we have to add and dummy up.
+
+ gROMImage_Size = hROM.GetLength() + bufferOffset;
+ gROMBank_Size = ::NextPowerOf2 (gROMImage_Size);
+
+ // Read in the ROM image.
+
+ StMemory romImage (gROMImage_Size);
+ StMemory romMetaImage (gROMImage_Size);
+
+ hROM.SetMarker (0, kStreamFromStart);
+ hROM.GetBytes (romImage.Get () + bufferOffset, hROM.GetLength());
+
+
+
+ // See if the big ROM checksum looks OK.
+
+ Card::CheckChecksum (romImage.Get () + bigROMOffset, gROMImage_Size - bigROMOffset);
+
+ // If we only had a Big ROM, dummy up the Small ROM. All we really
+ // need to do here is copy the Big ROM's card header to the Small
+ // ROM area.
+ //
+ // Also, clear out this area to 0xFF to look like new Flash RAM.
+
+ if (bufferOffset)
+ {
+ memset (romImage, 0xFF, bigROMOffset);
+ memcpy (romImage.Get (), romImage.Get () + bigROMOffset, EmProxyCardHeaderType::GetSize ());
+ }
+ else
+ {
+ // See if the small ROM checksum looks OK.
+ // Note that checksumBytes is invalid for v1 card headers,
+ // but in those cases, it's not really used anyway.
+
+ EmAliasCardHeaderType<LAS> cardHdr (romImage.Get ());
+ uint32 smallROMSize = cardHdr.checksumBytes;
+ Card::CheckChecksum (romImage.Get (), smallROMSize);
+ }
+
+
+ // Check that the ROM we just loaded can be run on this device.
+
+ EmAliasCardHeaderType<LAS> cardHdr (romImage.Get ());
+
+ EmAssert (gSession);
+ if (Card::SupportsEZ (cardHdr))
+ {
+ if (!gSession->GetDevice ().Supports68EZ328 ())
+ {
+ /* Make a hack for the Prism, Platinum and Edge below since
+ Handspring seems to report the EZ bit in their ROMs. */
+
+ if (!gSession->GetDevice ().PrismPlatinumEdgeHack ())
+ {
+ Errors::Throw (kError_WrongROMForType);
+ }
+ }
+ }
+ else if (Card::SupportsVZ (cardHdr))
+ {
+ if (!gSession->GetDevice ().Supports68VZ328 ())
+ {
+ Errors::Throw (kError_WrongROMForType);
+ }
+ }
+ else if (Card::SupportsSZ (cardHdr))
+ {
+ if (!gSession->GetDevice ().Supports68SZ328 ())
+ {
+ Errors::Throw (kError_WrongROMForType);
+ }
+ }
+ else
+ {
+ if (!gSession->GetDevice ().Supports68328 ())
+ {
+ Errors::Throw (kError_WrongROMForType);
+ }
+ }
+
+ // Byteswap all the words in the ROM (if necessary). Most accesses
+ // are 16-bit accesses, so we optimize for that case.
+
+ ByteswapWords (romImage.Get (), gROMImage_Size);
+
+ // Everything seems to be OK. Save the ROM data in some global
+ // variables for the CPU emulator to access. Make sure that
+ // gROMBank_Size is a power-of-2. The EmBankROM memory routines
+ // require this.
+
+ EmAssert (gROM_Memory == NULL);
+ EmAssert (gROM_MetaMemory == NULL);
+
+ gROM_Memory = (uint8*) romImage.Release ();
+ gROM_MetaMemory = (uint8*) romMetaImage.Release ();
+ gROMBank_Mask = gROMBank_Size - 1;
+
+ // Guess the default ROM base address.
+ // This will be used until the chip selects are set up.
+ //
+ // (I tried just setting this to zero, but the Palm OS 3.0
+ // startup code probes at 0x10c00008 and 0x10d00008 to see if
+ // it can find signatures there. If we map the ROM to zero,
+ // then we'll get bus errors when those accesses are made.)
+
+ gROMMemoryStart = cardHeader.resetVector & 0xFFF00000;
+
+}
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ Flash Bank Accessors
+// ===========================================================================
+// These functions provide fetch and store access to the emulator's read only
+// memory.
+
+/*
+ There are five types of flash that our flash manager routines identify:
+ Mitsubishi, Hitachi, Intel, AMD, and Fujitsu. Of these, only the last
+ two are really supported right now. Unfortunately, they are the hardest
+ to emulate. :-(
+
+ To identify the kind of flash being used, our ROM routines:
+
+ - Read a word from FLASHBASE
+ - Write 0x00FF to FLASHBASE
+ - Read a word from FLASHBASE
+ - Write 0x0090 to FLASHBASE
+ - Read a manufacturer ID (word) from FLASHBASE
+ - Read a device ID (word) from FLASHBASE + 2
+ - Write 0x00FF to FLASHBASE
+
+ Mitsubishi: manufacturer == 0x001C, device == 0x005E
+ Hitachi: manufacturer == 0x0007, device == 0x0086
+ Intel: manufacturer == 0x0089, device == 0x0091
+
+ If the flash is not one of those, our ROM routines:
+
+ - Read a word from FLASHBASE
+ - Write 0x00F0 to FLASHBASE
+ - Write 0x00AA to FLASHBASE + 0xAAAA
+ - Write 0x0055 to FLASHBASE + 0x5554
+ - Write 0x0090 to FLASHBASE + 0xAAAA
+ - Read a manufacturer ID (word) from FLASHBASE
+ - Read a device ID (word) from FLASHBASE + 2
+ - Write 0x00F0 to FLASHBASE
+
+ AMD: manufacturer == 0x0001, device == 0x0049
+ Fujitsu: manufacturer == 0x0004, device == 0x0049
+
+
+ To erase a word of flash, our ROM routines:
+
+ AMD, Fujitsu:
+
+ - Read a word from FLASHBASE
+ - Write 0x00F0 to FLASHBASE
+ - Write 0x00AA to FLASHBASE + 0xAAAA
+ - Write 0x0055 to FLASHBASE + 0x5554
+ - Write 0x0080 to FLASHBASE + 0xAAAA
+ - Write 0x00AA to FLASHBASE + 0xAAAA
+ - Write 0x0055 to FLASHBASE + 0x5554
+ - Write 0x0030 to location to be erased
+ - Check erase location for 0x0080
+ - Read from FLASHBASE
+ - Write 0x00F0 to FLASHBASE
+
+ Mitsubishi, Hitachi:
+
+ - Read a word from FLASHBASE
+ - Write 0x00FF to FLASHBASE
+ - Write 0x0020 to FLASHBASE
+ - Write 0x00D0 to location to be erased
+ - Check erase location for 0x0080
+ -- If 0x0020 is also set, an error occurred
+ - Read from FLASHBASE
+ - Write 0x00FF to FLASHBASE
+
+ Intel
+
+ - Not supported
+
+ To program a block of flash:
+
+ AMD, Fujitsu:
+
+ - Read a word from FLASHBASE
+ - Write 0x00F0 to FLASHBASE
+ - For each word to write
+ - If the word is already there, continue
+ - Write 0x00AA to FLASHBASE + 0xAAAA
+ - Write 0x0055 to FLASHBASE + 0x5554
+ - Write 0x00A0 to FLASHBASE + 0xAAAA
+ - Write the word to the dest location
+ - Check write location for 0x0080
+ - Read from FLASHBASE
+ - Write 0x00F0 to FLASHBASE
+
+ Mitsubishi, Hitachi, Intel:
+
+ - Not supported
+*/
+
+
+enum
+{
+ kAMDState_Normal, // Read-only mode. Acts like a normal ROM.
+ // Almost any write of 0x00F0 to any address will get us here.
+ // Also enter here automatically after Erase or Program operation.
+ // A write of 0x00AA to 0xAAAA will put us in kAMDState_Unlocked1.
+
+ kAMDState_Unlocked1, // After first unlock cycle (0x00AA written to 0xAAAA)
+ // Looking for the second unlock cycle (0x0055 written to 0x5554);
+ // If we find one, go to kAMDState_Unlocked2.
+ // ??? What happens on other operations?
+
+ kAMDState_Unlocked2, // After second unlock cycle (0x0055 written to 0x5554)
+ // Now looking for a command to be written to 0xAAAA
+ // If we find 0x0090, go to kAMDState_Autoselect.
+ // If we find 0x0080, set gEraseIsSetup and go to kAMDState_Normal. ??? When should gEraseIsSetup get cleared?
+ // If we find 0x0030, if gEraseIsSetup erase the sector and go to kAMDState_EraseDone.
+ // If we fine 0x00A0, go to kAMDState_Program.
+ // ??? What happens on other operations?
+
+ kAMDState_Autoselect, // After a write of 0x0090 to 0x5555.
+ // A read of 0x0000 returns 0x0001 (manufacturer ID).
+ // A read of 0x0002 returns 0x0049 (device ID).
+ // A write of 0x00F0 to any address returns us to kAMDState_Normal.
+ // ??? What happens on other operations?
+
+ kAMDState_Program, // After a program sequence was entered.
+ // Accept any write operation and go to kAMDState_ProgramDone.
+ // ??? What happens on other operations?
+
+ kAMDState_EraseDone, // After a Erase operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+
+ kAMDState_ProgramDone, // After a Program operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+ kAMDState_Dummy
+};
+
+
+static EmAddressBank gFlashAddressBank =
+{
+ EmBankFlash::GetLong,
+ EmBankFlash::GetWord,
+ EmBankFlash::GetByte,
+ EmBankFlash::SetLong,
+ EmBankFlash::SetWord,
+ EmBankFlash::SetByte,
+ EmBankFlash::GetRealAddress,
+ EmBankFlash::ValidAddress,
+ EmBankFlash::GetMetaAddress,
+ EmBankFlash::AddOpcodeCycles
+};
+
+#define FLASHBASE (EmBankROM::GetMemoryStart ())
+
+static int gState = kAMDState_Normal;
+static Bool gEraseIsSetup;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankFlash::Initialize (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankFlash::Reset (Bool hardwareReset)
+{
+ if (hardwareReset)
+ {
+ gState = kAMDState_Normal;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankFlash::Save (SessionFile&)
+{
+ // !!! Save gState && gEraseIsSetup?
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankFlash::Load (SessionFile&)
+{
+ // !!! Load gState && gEraseIsSetup?
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankFlash::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankFlash::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankFlash::SetBankHandlers (void)
+{
+ gManagedROMSize = EmHAL::GetROMSize ();
+
+ // Memory banks gROMMemoryStart to <mumble> are managed by the functions
+ // in EmBankROM. <mumble> is based on the amount of ROM being emulated.
+
+ uint32 first_bank = EmMemBankIndex (EmBankROM::GetMemoryStart ());
+ uint32 last_bank = EmMemBankIndex (EmBankROM::GetMemoryStart () + gManagedROMSize - 1);
+
+ Memory::InitializeBanks ( gFlashAddressBank, first_bank,
+ last_bank - first_bank + 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankFlash::GetLong (emuptr address)
+{
+ return EmBankROM::GetLong (address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankFlash::GetWord (emuptr address)
+{
+ switch (gState)
+ {
+ case kAMDState_Normal:
+ // Read-only mode. Acts like a normal ROM.
+ // Almost any write of 0x00F0 to any address will get us here.
+ // Also enter here automatically after Erase or Program operation.
+ // A write of 0x00AA to 0xAAAA will put us in kAMDState_Unlocked1.
+
+ break;
+
+ case kAMDState_Unlocked1:
+ // After first unlock cycle (0x00AA written to 0xAAAA)
+ // Looking for the second unlock cycle (0x0055 written to 0x5554);
+ // If we find one, go to kAMDState_Unlocked2.
+ // ??? What happens on other operations?
+
+ break;
+
+ case kAMDState_Unlocked2:
+ // After second unlock cycle (0x0055 written to 0x5554)
+ // Now looking for a command to be written to 0xAAAA
+ // If we find 0x0090, go to kAMDState_Autoselect.
+ // If we find 0x0080, set gEraseIsSetup and go to kAMDState_Normal. ??? When should gEraseIsSetup get cleared?
+ // If we find 0x0030, if gEraseIsSetup erase the sector and go to kAMDState_ProgramDone.
+ // If we fine 0x00A0, go to kAMDState_Program.
+ // ??? What happens on other operations?
+
+ break;
+
+ case kAMDState_Autoselect:
+ // After a write of 0x0090 to 0x5555.
+ // A read of 0x0000 returns 0x0001 (manufacturer ID).
+ // A read of 0x0002 returns 0x0049 (device ID).
+ // A write of 0x00F0 to any address returns us to kAMDState_Normal.
+ // ??? What happens on other operations?
+
+ if (address == FLASHBASE)
+ {
+ return 0x0001;
+ }
+ else if (address == FLASHBASE + 2)
+ {
+ return 0x0049;
+ }
+ break;
+
+ case kAMDState_Program:
+ // After a program sequence was entered.
+ // Accept any write operation and go to kAMDState_ProgramDone.
+ // ??? What happens on other operations?
+
+ break;
+
+ case kAMDState_EraseDone:
+ // After a Program or Erase operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+
+ // !!! We should really check that address is the same as the
+ // one specified in the Erase command.
+
+ gState = kAMDState_Normal;
+ return 0x0080;
+
+ case kAMDState_ProgramDone:
+ // After a Program or Erase operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+
+ // !!! We should really check that address is the same as the
+ // one specified in the Program command.
+
+ gState = kAMDState_Normal;
+ return 0x0080 & EmBankROM::GetWord (address);
+ }
+
+ return EmBankROM::GetWord (address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankFlash::GetByte (emuptr address)
+{
+ return EmBankROM::GetByte (address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankFlash::SetLong (emuptr address, uint32 value)
+{
+ EmBankROM::SetLong (address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankFlash::SetWord (emuptr address, uint32 value)
+{
+ switch (gState)
+ {
+ case kAMDState_Normal:
+ // Read-only mode. Acts like a normal ROM.
+ // Almost any write of 0x00F0 to any address will get us here.
+ // Also enter here automatically after Erase or Program operation.
+ // A write of 0x00AA to 0xAAAA will put us in kAMDState_Unlocked1.
+
+ if (address == FLASHBASE + 0xAAAA && value == 0x00AA)
+ {
+ gState = kAMDState_Unlocked1;
+ return;
+ }
+
+ // Allow these. PrvIdentifyFlashCode probes with these values
+ // to determine what Flash part we've got.
+
+ if (address == FLASHBASE && (value == 0x00FF || value == 0x00F0 || value == 0x0090))
+ {
+ return;
+ }
+ break;
+
+ case kAMDState_Unlocked1:
+ // After first unlock cycle (0x00AA written to 0xAAAA)
+ // Looking for the second unlock cycle (0x0055 written to 0x5554);
+ // If we find one, go to kAMDState_Unlocked2.
+ // ??? What happens on other operations?
+
+ if (value == 0x00F0)
+ {
+ gState = kAMDState_Normal;
+ return;
+ }
+ else if (address == FLASHBASE + 0x5554 && value == 0x0055)
+ {
+ gState = kAMDState_Unlocked2;
+ return;
+ }
+ break;
+
+ case kAMDState_Unlocked2:
+ // After second unlock cycle (0x0055 written to 0x5554)
+ // Now looking for a command to be written to 0xAAAA
+ // If we find 0x0090, go to kAMDState_Autoselect.
+ // If we find 0x0080, set gEraseIsSetup and go to kAMDState_Normal. ??? When should gEraseIsSetup get cleared?
+ // If we find 0x0030, if gEraseIsSetup erase the sector and go to kAMDState_EraseDone.
+ // If we fine 0x00A0, go to kAMDState_Program.
+ // ??? What happens on other operations?
+
+ if (value == 0x00F0)
+ {
+ gState = kAMDState_Normal;
+ return;
+ }
+ else if (value == 0x0030 && gEraseIsSetup)
+ {
+ const int kEraseValue = 0xFF;
+#if 0
+ DWord readWriteParmsOffset = EmMemGet32 (0x10C00000 + offsetof (CardHeaderType, readWriteParmsOffset));
+ DWord readWriteParmsSize = EmMemGet32 (0x10C00000 + offsetof (CardHeaderType, readWriteParmsSize));
+ DWord readOnlyParmsOffset = EmMemGet32 (0x10C00000 + offsetof (CardHeaderType, readOnlyParmsOffset));
+ DWord readOnlyParmsSize = 0x00002000;
+ DWord readWriteWorkingOffset = EmMemGet32 (0x10C00000 + offsetof (CardHeaderType, readWriteWorkingOffset));
+ DWord readWriteWorkingSize = EmMemGet32 (0x10C00000 + offsetof (CardHeaderType, readWriteWorkingSize));
+
+ if (address >= 0x10000000 + readWriteParmsOffset &&
+ address < 0x10000000 + readWriteParmsOffset + readWriteParmsSize)
+ {
+ EmMem_memset (0x10000000 + readWriteParmsOffset, kEraseValue, readWriteParmsSize);
+ }
+ else if (address >= 0x10000000 + readOnlyParmsOffset &&
+ address < 0x10000000 + readOnlyParmsOffset + readOnlyParmsSize)
+ {
+ EmMem_memset (0x10000000 + readOnlyParmsOffset, kEraseValue, readOnlyParmsSize);
+ }
+ else if (address >= 0x10000000 + readWriteWorkingOffset &&
+ address < 0x10000000 + readWriteWorkingOffset + readWriteWorkingSize)
+ {
+ EmMem_memset (0x10000000 + readWriteWorkingOffset, kEraseValue, readWriteWorkingSize);
+ }
+#endif
+
+ const unsigned long kSector1Start = 0x10C00000;
+ const unsigned long kSector1Size = 0x00004000;
+ const unsigned long kSector2Start = 0x10C04000;
+ const unsigned long kSector2Size = 0x00002000;
+ const unsigned long kSector3Start = 0x10C06000;
+ const unsigned long kSector3Size = 0x00002000;
+ const unsigned long kSector4Start = 0x10C08000;
+ const unsigned long kSector4Size = 0x00008000;
+
+ CEnableFullAccess munge;
+
+ if (address == kSector1Start)
+ {
+ EmMem_memset (kSector1Start, kEraseValue, kSector1Size);
+ }
+ else if (address == kSector2Start)
+ {
+ EmMem_memset (kSector2Start, kEraseValue, kSector2Size);
+ }
+ else if (address == kSector3Start)
+ {
+ EmMem_memset (kSector3Start, kEraseValue, kSector3Size);
+ }
+ else if (address == kSector4Start)
+ {
+ EmMem_memset (kSector4Start, kEraseValue, kSector4Size);
+ }
+
+ gState = kAMDState_EraseDone;
+ return;
+ }
+ else if (address == FLASHBASE + 0xAAAA)
+ {
+ if (value == 0x0090)
+ {
+ gState = kAMDState_Autoselect;
+ return;
+ }
+ else if (value == 0x0080)
+ {
+ gEraseIsSetup = true;
+ gState = kAMDState_Normal;
+ return;
+ }
+ else if (value == 0x00A0)
+ {
+ gState = kAMDState_Program;
+ return;
+ }
+ }
+ break;
+
+ case kAMDState_Autoselect:
+ // After a write of 0x0090 to 0x5555.
+ // A read of 0x0000 returns 0x0001 (manufacturer ID).
+ // A read of 0x0002 returns 0x0049 (device ID).
+ // A write of 0x00F0 to any address returns us to kAMDState_Normal.
+ // ??? What happens on other operations?
+
+ if (value == 0x00F0)
+ {
+ gState = kAMDState_Normal;
+ return;
+ }
+ break;
+
+ case kAMDState_Program:
+ // After a program sequence was entered.
+ // Accept any write operation and go to kAMDState_ProgramDone.
+ // ??? What happens on other operations?
+
+ address &= gROMBank_Mask;
+ EmMemDoPut16 (gROM_Memory + address, value);
+
+ gState = kAMDState_ProgramDone;
+ return;
+
+ case kAMDState_EraseDone:
+ // After a Program or Erase operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+
+ return;
+
+ case kAMDState_ProgramDone:
+ // After a Program or Erase operation.
+ // On the next read, return successful operation and return to kAMDState_Normal
+ // ??? What happens on other operations?
+
+ return;
+ }
+
+ EmBankROM::SetWord (address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankFlash::SetByte (emuptr address, uint32 value)
+{
+ EmBankROM::SetByte (address, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankFlash::ValidAddress (emuptr address, uint32 size)
+{
+ return EmBankROM::ValidAddress (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankFlash::GetRealAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gROMBank_Mask;
+
+ return (uint8*) &gROM_Memory[address];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankFlash::GetMetaAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gROMBank_Mask;
+
+ return (uint8*) &(gROM_MetaMemory[address]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankFlash::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankFlash::AddOpcodeCycles (void)
+{
+#if (HAS_PROFILING)
+ CYCLE_GETWORD (WAITSTATES_ROM);
+#endif
+}
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ Card
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// ¥ Card::CheckCardHeader
+// ---------------------------------------------------------------------------
+// Determines if the memory pointed to looks like a card header.
+
+Bool Card::CheckCardHeader (const EmProxyCardHeaderType& cardHdr)
+{
+ // Make sure the stack size isn't something ludicrous.
+
+ if (cardHdr.initStack == 0 || cardHdr.initStack > 0x000FFFFF) // 1 Meg
+ return false;
+
+ // Make sure the signature is right.
+
+ if (cardHdr.signature != sysCardSignature)
+ return false;
+
+ // Make sure the header version isn't ludicrous.
+
+ if (cardHdr.hdrVersion == 0 || cardHdr.hdrVersion > 255) // arbitrary value
+ return false;
+
+ // Make sure this isn't a "RAM only" card.
+
+ if (cardHdr.flags & memCardHeaderFlagRAMOnly)
+ return false;
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Card::CheckChecksum
+// ---------------------------------------------------------------------------
+// Determines if the memory pointed to looks like a card header.
+
+Bool Card::CheckChecksum (const void* p, uint32 fileLength)
+{
+ EmAliasCardHeaderType<LAS> cardHdr ((void*) p);
+
+ if (cardHdr.hdrVersion == 1)
+ {
+ static const UInt16 kDebug20 = 0x9BED;
+
+ UInt16 checksumValue = Crc16CalcBigBlock ((/*non-const*/ void*) p, fileLength, 0);
+
+ // Special hack for 2.0 Debug ROMs. The version with this checksum was
+ // bogus, so let's make sure we never load it.
+
+ if (checksumValue == kDebug20)
+ {
+ // Throw a special error for this one.
+
+ Errors::Throw (kError_UnsupportedROM);
+ }
+
+ return true;
+ }
+ else
+ {
+ // The checksum is the cumulative checksum of the ROM image before
+ // the stored checksum value and the ROM image following the checksum
+ // value. First, calculate the first part.
+
+ UInt32 chunkSize = cardHdr.offsetof_checksumValue ();
+ UInt16 checksumValue = Crc16CalcBigBlock (
+ (/*non-const*/ void*) p, chunkSize, 0);
+
+ // Now calculate the second part.
+
+ UInt32 skipSize = chunkSize + cardHdr.checksumValue.GetSize ();
+ checksumValue = Crc16CalcBigBlock (
+ ((char*) p) + skipSize,
+ cardHdr.checksumBytes - skipSize,
+ checksumValue);
+
+ if (checksumValue == cardHdr.checksumValue)
+ {
+ return true;
+ }
+ }
+
+ Errors::DoDialog (kStr_BadChecksum, kDlgFlags_OK);
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Card::Supports328
+// ---------------------------------------------------------------------------
+
+Bool Card::Supports328 (const EmAliasCardHeaderType<LAS>& cardHdr)
+{
+ Bool dbMode = false;
+
+ if (cardHdr.hdrVersion < 3 || (cardHdr.flags & memCardHeaderFlag328))
+ {
+ dbMode = true;
+ }
+
+ return dbMode;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Card::SupportsEZ
+// ---------------------------------------------------------------------------
+
+Bool Card::SupportsEZ (const EmAliasCardHeaderType<LAS>& cardHdr)
+{
+ Bool ezMode = false;
+
+ if (cardHdr.hdrVersion >= 3 && (cardHdr.flags & memCardHeaderFlagEZ))
+ {
+ ezMode = true;
+ }
+
+ return ezMode;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Card::SupportsVZ
+// ---------------------------------------------------------------------------
+#define memCardHeaderFlagVZ 0x0040 // ROM Supports 68VZ328 processor
+
+Bool Card::SupportsVZ (const EmAliasCardHeaderType<LAS>& cardHdr)
+{
+ Bool vzMode = false;
+
+ if (cardHdr.hdrVersion >= 3 && (cardHdr.flags & memCardHeaderFlagVZ))
+ {
+ vzMode = true;
+ }
+
+ return vzMode;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Card::SupportsSZ
+// ---------------------------------------------------------------------------
+#define memCardHeaderFlagSZ 0x0080 // ROM Supports 68SZ328 processor
+
+Bool Card::SupportsSZ (const EmAliasCardHeaderType<LAS>& cardHdr)
+{
+ Bool szMode = false;
+
+ if (cardHdr.hdrVersion >= 3 && (cardHdr.flags & memCardHeaderFlagSZ))
+ {
+ szMode = true;
+ }
+
+ return szMode;
+}
diff --git a/SrcShared/Hardware/EmBankROM.h b/SrcShared/Hardware/EmBankROM.h
new file mode 100644
index 0000000..f29572b
--- /dev/null
+++ b/SrcShared/Hardware/EmBankROM.h
@@ -0,0 +1,81 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankROM_h
+#define EmBankROM_h
+
+class EmStream;
+class SessionFile;
+
+const emuptr kDefaultROMMemoryStart = 0x10C00000;
+
+class EmBankROM
+{
+ public:
+ static void Initialize (EmStream& hROM);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static void AddOpcodeCycles (void);
+
+ static emuptr GetMemoryStart (void) { return gROMMemoryStart; }
+
+ private:
+ static void AddressError (emuptr address, long size, Bool forRead);
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+ static void LoadROM (EmStream& hROM);
+
+ static emuptr gROMMemoryStart;
+};
+
+
+class EmBankFlash
+{
+ public:
+ static void Initialize (void);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static void AddOpcodeCycles (void);
+
+ static emuptr GetMemoryStart (void) { return kDefaultROMMemoryStart; }
+};
+
+
+#endif /* EmBankROM_h */
diff --git a/SrcShared/Hardware/EmBankRegs.cpp b/SrcShared/Hardware/EmBankRegs.cpp
new file mode 100644
index 0000000..c03deb3
--- /dev/null
+++ b/SrcShared/Hardware/EmBankRegs.cpp
@@ -0,0 +1,694 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmBankRegs.h"
+
+#include "DebugMgr.h" // Debug::CheckStepSpy
+#include "EmCPU.h" // GetPC
+#include "EmCPU68K.h" // gCPU68K
+#include "EmMemory.h" // gMemAccessFlags, EmMemory::IsPCInRAM
+#include "EmSession.h" // GetDevice, ScheduleDeferredError
+#include "ErrorHandling.h" // Errors::ReportErrHardwareRegisters
+#include "MetaMemory.h" // MetaMemory::InRAMOSComponent
+#include "Profiling.h" // WAITSTATES_PLD
+
+
+/*
+ When emulating memory, UAE divides up the 4GB address space into
+ 65,536 banks, each of which is 64K long. For more details, see the
+ comments in EmMemory.cpp.
+
+ For our purposes, we sometimes need to divide up each 64K bank in a
+ similar fashion. For instance, in order to support accesses to each
+ of the Dragonball registers, we'd like to assign a handler to each
+ byte, word, or long of memory in the bank that contains the
+ Dragonball registers.
+
+ This module supports that further subdivision. EmBankRegs is a bank
+ handler -- just like the RAM and ROM bank handlers -- in that it is
+ responsible for memory accesses to one or more 64K banks of memory.
+ It divides up each 64K bank by making use of instances of EmRegs
+ subclasses.
+
+ EmRegs subclasses are the moral equivalent of EmBanks, except on a
+ smaller scale. They are responsible for byte, word, and long memory
+ accesses to a small range of memory completely contained within a
+ 64K bank.
+
+ Many such EmRegs instances can be created and installed into the
+ EmBankRegs object. EmBankRegs stores these EmRegs in a list. When
+ in comes time for the EmBanks to register which 64K banks they are
+ responsible for, EmBankRegs iterates over all the EmRegs objects
+ registered with it, and takes responsibility for each 64K bank that
+ contains the EmRegs object memory range (an EmRegs object can be
+ queried as to the memory start and length it is responsible for).
+
+ Later, when a memory access is made to any of the 64K banks
+ EmBankRegs registered for, it again iterates over the EmRegs objects
+ installed into it, looking for one that takes responsibility for the
+ memory address being accessed. When it finds one, it passes off the
+ request to that object. Otherwise, it signals a bus error.
+*/
+
+
+static EmAddressBank gAddressBank =
+{
+ EmBankRegs::GetLong,
+ EmBankRegs::GetWord,
+ EmBankRegs::GetByte,
+ EmBankRegs::SetLong,
+ EmBankRegs::SetWord,
+ EmBankRegs::SetByte,
+ EmBankRegs::GetRealAddress,
+ EmBankRegs::ValidAddress,
+ NULL,
+ NULL
+};
+
+
+EmRegsList EmBankRegs::fgSubBanks;
+EmRegsList EmBankRegs::fgDisabledSubBanks;
+
+static EmRegs* gLastSubBank;
+static uint64 gLastStart;
+static uint32 gLastRange;
+
+static void PrvSwitchBanks (EmRegsList& fromList, EmRegsList& toList, emuptr address);
+
+#pragma mark -
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankRegs::Initialize (void)
+{
+ EmAssert (gSession);
+ gSession->GetDevice ().CreateRegs ();
+
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->Initialize ();
+ ++iter;
+ }
+
+ // Install the handlers for each affected bank.
+
+ EmBankRegs::SetBankHandlers ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankRegs::Reset (Bool hardwareReset)
+{
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->Reset (hardwareReset);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankRegs::Save (SessionFile& f)
+{
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->Save (f);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankRegs::Load (SessionFile& f)
+{
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->Load (f);
+ ++iter;
+ }
+
+ gLastSubBank = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankRegs::Dispose (void)
+{
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->Dispose ();
+ ++iter;
+ }
+
+ while (fgSubBanks.size () > 0)
+ {
+ EmRegs* bank = fgSubBanks[0];
+ fgSubBanks.erase (fgSubBanks.begin ());
+ delete bank;
+ }
+
+ gLastSubBank = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankRegs::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankRegs::SetBankHandlers (void)
+{
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ (*iter)->SetBankHandlers (gAddressBank);
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankRegs::GetLong (emuptr address)
+{
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (PREVENT_USER_REGISTER_GET)
+ if (gMemAccessFlags.fProtect_RegisterGet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_GET)
+ if (gMemAccessFlags.fValidate_RegisterGet && !ValidAddress (address, sizeof (uint32)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint32), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETLONG (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint32));
+
+ if (bank)
+ {
+ return bank->GetLong (address);
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint32), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankRegs::GetWord (emuptr address)
+{
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (PREVENT_USER_REGISTER_GET)
+ if (gMemAccessFlags.fProtect_RegisterGet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_GET)
+ if (gMemAccessFlags.fValidate_RegisterGet && !ValidAddress (address, sizeof (uint16)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint16), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETWORD (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint16));
+
+ if (bank)
+ {
+ return bank->GetWord (address);
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint16), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankRegs::GetByte (emuptr address)
+{
+#if (PREVENT_USER_REGISTER_GET)
+ if (gMemAccessFlags.fProtect_RegisterGet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint8), true);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_GET)
+ if (gMemAccessFlags.fValidate_RegisterGet && !ValidAddress (address, sizeof (uint8)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint8), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETBYTE (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint8));
+
+ if (bank)
+ {
+ return bank->GetByte (address);
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint8), true);
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::SetLong (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kPLDLongWrite]++;
+ if (address & 2)
+ gMemoryAccess[kPLDLongWrite2]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), false);
+ }
+#endif
+
+#if (PREVENT_USER_REGISTER_SET)
+ if (gMemAccessFlags.fProtect_RegisterSet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint32), false);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_SET)
+ if (gMemAccessFlags.fValidate_RegisterSet && !ValidAddress (address, sizeof (uint32)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint32), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTLONG (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint32));
+
+ if (bank)
+ {
+ bank->SetLong (address, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint32));
+
+ return;
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint32), false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::SetWord (emuptr address, uint32 value)
+{
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), false);
+ }
+#endif
+
+#if (PREVENT_USER_REGISTER_SET)
+ if (gMemAccessFlags.fProtect_RegisterSet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint16), false);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_SET)
+ if (gMemAccessFlags.fValidate_RegisterSet && !ValidAddress (address, sizeof (uint16)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint16), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTWORD (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint16));
+
+ if (bank)
+ {
+ bank->SetWord (address, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint16));
+
+ return;
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint16), false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::SetByte (emuptr address, uint32 value)
+{
+#if (PREVENT_USER_REGISTER_SET)
+ if (gMemAccessFlags.fProtect_RegisterSet && EmMemory::IsPCInRAM () && !MetaMemory::InRAMOSComponent (gCPU->GetPC ()))
+ {
+ EmBankRegs::PreventedAccess (address, sizeof (uint8), false);
+ }
+#endif
+
+#if (VALIDATE_REGISTER_SET)
+ if (gMemAccessFlags.fValidate_RegisterSet && !ValidAddress (address, sizeof (uint8)))
+ {
+ EmBankRegs::InvalidAccess (address, sizeof (uint8), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTBYTE (WAITSTATES_PLD);
+#endif
+
+ EmRegs* bank = EmBankRegs::GetSubBank (address, sizeof (uint8));
+
+ if (bank)
+ {
+ bank->SetByte (address, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint8));
+
+ return;
+ }
+
+ EmBankRegs::InvalidAccess (address, sizeof (uint8), false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankRegs::ValidAddress (emuptr address, uint32 size)
+{
+ EmRegs* bank = EmBankRegs::GetSubBank (address, size);
+
+ if (bank)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankRegs::GetRealAddress (emuptr address)
+{
+ EmRegs* bank = EmBankRegs::GetSubBank (address, 0);
+
+ if (bank)
+ {
+ return bank->GetRealAddress (address);
+ }
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::AddSubBank
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::AddSubBank (EmRegs* bank)
+{
+ fgSubBanks.push_back (bank);
+ gLastSubBank = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::EnableSubBank
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::EnableSubBank (emuptr address)
+{
+ PrvSwitchBanks (fgDisabledSubBanks, fgSubBanks, address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::DisableSubBank
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::DisableSubBank (emuptr address)
+{
+ PrvSwitchBanks (fgSubBanks, fgDisabledSubBanks, address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::GetSubBank
+// ---------------------------------------------------------------------------
+
+EmRegs* EmBankRegs::GetSubBank (emuptr address, long size)
+{
+ // Cast address to a 64-bit value in case address + size == 0x1 0000 0000.
+
+ uint64 addrStart64 = address;
+ uint64 addrEnd64 = addrStart64 + size;
+
+ // This cache is a big win. When emulating a Palm IIIc (which uses
+ // three EmRegs-based objects: EmRegsEZPalmIIIc, EmRegsSED1375, and
+ // EmRegsFrameBuffer) and doing a Gremlins run, the cache was hit
+ // 2,356,670 times and missed 19456 times. When doing the same run
+ // on a Palm V, the cache was missed only the first time.
+
+ if (gLastSubBank &&
+ (addrStart64 >= gLastStart) &&
+ (addrEnd64 <= gLastStart + gLastRange))
+ {
+ return gLastSubBank;
+ }
+
+ EmRegsList::iterator iter = fgSubBanks.begin ();
+ while (iter != fgSubBanks.end ())
+ {
+ uint64 start = (*iter)->GetAddressStart ();
+ uint32 range = (*iter)->GetAddressRange ();
+
+ if ((addrStart64 >= start) && (addrEnd64 <= start + range))
+ {
+ gLastSubBank = *iter;
+ gLastStart = start;
+ gLastRange = range;
+
+ return *iter;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::AddressError
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankRegs::PreventedAccess
+// ---------------------------------------------------------------------------
+
+void EmBankRegs::PreventedAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (new EmDeferredErrHardwareRegisters (address, size, forRead));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvSwitchBanks
+// ---------------------------------------------------------------------------
+
+void PrvSwitchBanks (EmRegsList& fromList, EmRegsList& toList, emuptr address)
+{
+ EmRegsList::iterator iter = fromList.begin ();
+ while (iter != fromList.end ())
+ {
+ uint64 start = (*iter)->GetAddressStart ();
+ uint32 range = (*iter)->GetAddressRange ();
+
+ if ((address >= start) && (address <= start + range))
+ {
+ toList.push_back (*iter);
+ fromList.erase (iter);
+ return;
+ }
+
+ ++iter;
+ }
+}
diff --git a/SrcShared/Hardware/EmBankRegs.h b/SrcShared/Hardware/EmBankRegs.h
new file mode 100644
index 0000000..284fe4a
--- /dev/null
+++ b/SrcShared/Hardware/EmBankRegs.h
@@ -0,0 +1,56 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankRegs_h
+#define EmBankRegs_h
+
+#include "EmRegs.h" // EmRegsList
+
+class EmBankRegs
+{
+ public:
+ static void Initialize (void);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+
+ static void AddSubBank (EmRegs*);
+
+ static void EnableSubBank (emuptr address);
+ static void DisableSubBank (emuptr address);
+
+ private:
+ static EmRegs* GetSubBank (emuptr address, long size);
+ static void AddressError (emuptr address, long size, Bool forRead);
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+ static void PreventedAccess (emuptr address, long size, Bool forRead);
+
+ static EmRegsList fgSubBanks;
+ static EmRegsList fgDisabledSubBanks;
+
+ friend class EmRegs; // EmBankRegs::InvalidAccess
+};
+
+#endif /* EmBankRegs_h */
diff --git a/SrcShared/Hardware/EmBankSRAM.cpp b/SrcShared/Hardware/EmBankSRAM.cpp
new file mode 100644
index 0000000..4553131
--- /dev/null
+++ b/SrcShared/Hardware/EmBankSRAM.cpp
@@ -0,0 +1,640 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmBankSRAM.h"
+
+#include "Byteswapping.h" // ByteswapWords
+#include "DebugMgr.h" // Debug::CheckStepSpy
+#include "EmCPU68K.h" // gCPU68K
+#include "EmMemory.h" // gRAMBank_Size, gRAM_Memory, gMemoryAccess
+#include "EmScreen.h" // EmScreen::MarkDirty
+#include "EmSession.h" // GetDevice
+#include "MetaMemory.h" // MetaMemory::
+#include "Miscellaneous.h" // StWordSwapper
+#include "Profiling.h" // WAITSTATES_SRAM
+#include "SessionFile.h" // WriteRAMImage
+
+
+// ===========================================================================
+// ¥ SRAM Bank Accessors
+// ===========================================================================
+// These functions provide fetch and store access to the emulator's random
+// access memory.
+
+static EmAddressBank gAddressBank =
+{
+ EmBankSRAM::GetLong,
+ EmBankSRAM::GetWord,
+ EmBankSRAM::GetByte,
+ EmBankSRAM::SetLong,
+ EmBankSRAM::SetWord,
+ EmBankSRAM::SetByte,
+ EmBankSRAM::GetRealAddress,
+ EmBankSRAM::ValidAddress,
+ EmBankSRAM::GetMetaAddress,
+ EmBankSRAM::AddOpcodeCycles
+};
+
+ // Note: I'd've used hwrCardBase0 here, except that that
+ // changes on different hardware. It's 0x10000000 in some
+ // cases, 0x00000000 in others.
+
+static const emuptr kMemoryStart = 0x10000000;
+static const emuptr kMemoryStartEZ = 0x00000000;
+static const emuptr kMemoryStartVZ = 0x00000000;
+
+emuptr gMemoryStart;
+
+uint32 gRAMBank_Size;
+uint32 gRAMBank_Mask;
+uint8* gRAM_Memory;
+uint8* gRAM_MetaMemory;
+
+#if defined (_DEBUG)
+
+ // In debug mode, define a global variable that points to the
+ // Palm ROM's low-memory globals. That makes it easier to find
+ // out what's going wrong when something goes wrong.
+ //
+ // Keep in mind that on Windows, all values are "wordswapped"
+ // (each pair of bytes is byteswapped).
+
+ LowMemHdrType* gLowMemory;
+
+#endif
+
+
+static inline uint8* InlineGetMetaAddress (emuptr address)
+{
+ return (uint8*) &(gRAM_MetaMemory[address]);
+}
+
+static inline void PrvScreenCheck (uint8* metaAddress, emuptr address, size_t size)
+{
+#if defined (macintosh)
+
+ if (size == 1 && !MetaMemory::IsScreenBuffer8 (metaAddress))
+ return;
+
+ if (size == 2 && !MetaMemory::IsScreenBuffer16 (metaAddress))
+ return;
+
+ if (size == 4 && !MetaMemory::IsScreenBuffer32 (metaAddress))
+ return;
+
+#else
+
+ if (MetaMemory::IsScreenBuffer (metaAddress, size))
+
+#endif
+
+ {
+ EmScreen::MarkDirty (address, size);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::Initialize (RAMSizeType ramSize)
+{
+ EmAssert (gRAM_Memory == NULL);
+ EmAssert (gRAM_MetaMemory == NULL);
+
+ if (ramSize > 0)
+ {
+ gRAMBank_Size = ramSize * 1024;
+ gRAMBank_Mask = gRAMBank_Size - 1;
+ gRAM_Memory = (uint8*) Platform::AllocateMemoryClear (gRAMBank_Size);
+ gRAM_MetaMemory = (uint8*) Platform::AllocateMemoryClear (gRAMBank_Size);
+
+#if defined (_DEBUG)
+ // In debug mode, define a global variable that points to the
+ // Palm ROM's low-memory globals. That makes it easier to find
+ // out what's going wrong when something goes wrong.
+
+ gLowMemory = (LowMemHdrType*) gRAM_Memory;
+#endif
+ }
+
+ EmAssert (gSession);
+
+ if (gSession->GetDevice ().Supports68EZ328 ())
+ {
+ gMemoryStart = kMemoryStartEZ;
+ }
+ else if (gSession->GetDevice ().Supports68VZ328 ())
+ {
+ gMemoryStart = kMemoryStartVZ;
+ }
+ else
+ {
+ gMemoryStart = kMemoryStart;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::Reset (Bool /*hardwareReset*/)
+{
+ memset (gRAM_MetaMemory, 0, gRAMBank_Size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::Save (SessionFile& f)
+{
+ StWordSwapper swapper1 (gRAM_Memory, gRAMBank_Size);
+ f.WriteRAMImage (gRAM_Memory, gRAMBank_Size);
+
+ StWordSwapper swapper2 (gRAM_MetaMemory, gRAMBank_Size);
+ f.WriteMetaRAMImage (gRAM_MetaMemory, gRAMBank_Size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::Load (SessionFile& f)
+{
+ EmAssert (gRAM_Memory);
+ EmAssert (gRAM_MetaMemory);
+
+ if (f.ReadRAMImage (gRAM_Memory))
+ {
+ ByteswapWords (gRAM_Memory, gRAMBank_Size);
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+ if (f.ReadMetaRAMImage (gRAM_MetaMemory))
+ {
+ ByteswapWords (gRAM_MetaMemory, gRAMBank_Size);
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::Dispose (void)
+{
+ Platform::DisposeMemory (gRAM_Memory);
+ Platform::DisposeMemory (gRAM_MetaMemory);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmBankSRAM::SetBankHandlers
+ *
+ * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory
+ * access operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmBankSRAM::SetBankHandlers (void)
+{
+ // Memory banks 0x1000 to <mumble> are managed by the functions
+ // in EmBankSRAM. <mumble> is based on the amount of RAM being emulated.
+
+ long numBanks = EmMemBankIndex (gMemoryStart + gRAMBank_Size - 1) -
+ EmMemBankIndex (gMemoryStart) + 1;
+ Memory::InitializeBanks (gAddressBank, EmMemBankIndex (gMemoryStart), numBanks);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmBankSRAM::GetLong (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMLongRead]++;
+ if (address & 2)
+ gMemoryAccess[kSRAMLongRead2]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (PREVENT_USER_SRAM_GET)
+ if (gMemAccessFlags.fProtect_SRAMGet)
+ {
+ ProtectedAccess (address, sizeof (uint32), true);
+ }
+#endif
+
+#if (VALIDATE_SRAM_GET)
+ if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint32)))
+ {
+ InvalidAccess (address, sizeof (uint32), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETLONG (WAITSTATES_SRAM);
+#endif
+
+ address &= gRAMBank_Mask;
+
+ return EmMemDoGet32 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmBankSRAM::GetWord (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMWordRead]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (PREVENT_USER_SRAM_GET)
+ if (gMemAccessFlags.fProtect_SRAMGet)
+ {
+ ProtectedAccess (address, sizeof (uint16), true);
+ }
+#endif
+
+#if (VALIDATE_SRAM_GET)
+ if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint16)))
+ {
+ InvalidAccess (address, sizeof (uint16), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETWORD (WAITSTATES_SRAM);
+#endif
+
+ address &= gRAMBank_Mask;
+
+ return EmMemDoGet16 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmBankSRAM::GetByte (emuptr address)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMByteRead]++;
+#endif
+
+#if (PREVENT_USER_SRAM_GET)
+ if (gMemAccessFlags.fProtect_SRAMGet)
+ {
+ ProtectedAccess (address, sizeof (uint8), true);
+ }
+#endif
+
+#if (VALIDATE_SRAM_GET)
+ if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint8)))
+ {
+ InvalidAccess (address, sizeof (uint8), true);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_GETBYTE (WAITSTATES_SRAM);
+#endif
+
+ address &= gRAMBank_Mask;
+
+ return EmMemDoGet8 (gRAM_Memory + address);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::SetLong
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::SetLong (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMLongWrite]++;
+ if (address & 2)
+ gMemoryAccess[kSRAMLongWrite2]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint32), false);
+ }
+#endif
+
+#if (PREVENT_USER_SRAM_SET)
+ if (gMemAccessFlags.fProtect_SRAMSet)
+ {
+ ProtectedAccess (address, sizeof (uint32), false);
+ }
+#endif
+
+#if (VALIDATE_SRAM_SET)
+ if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint32)))
+ {
+ InvalidAccess (address, sizeof (uint32), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTLONG (WAITSTATES_SRAM);
+#endif
+
+ emuptr phyAddress = address;
+ phyAddress &= gRAMBank_Mask;
+
+ register uint8* metaAddress = InlineGetMetaAddress (phyAddress);
+// META_CHECK (metaAddress, address, SetLong, uint32, false);
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint32));
+
+ EmMemDoPut32 (gRAM_Memory + phyAddress, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint32));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::SetWord
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::SetWord (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMWordWrite]++;
+#endif
+
+#if (CHECK_FOR_ADDRESS_ERROR)
+ if ((address & 1) != 0)
+ {
+ AddressError (address, sizeof (uint16), false);
+ }
+#endif
+
+#if (PREVENT_USER_SRAM_SET)
+ if (gMemAccessFlags.fProtect_SRAMSet)
+ {
+ ProtectedAccess (address, sizeof (uint16), false);
+ }
+#endif
+
+#if (VALIDATE_SRAM_SET)
+ if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint16)))
+ {
+ InvalidAccess (address, sizeof (uint16), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTWORD (WAITSTATES_SRAM);
+#endif
+
+ emuptr phyAddress = address;
+ phyAddress &= gRAMBank_Mask;
+
+ register uint8* metaAddress = InlineGetMetaAddress (phyAddress);
+// META_CHECK (metaAddress, address, SetLong, uint16, false);
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint16));
+
+ EmMemDoPut16 (gRAM_Memory + phyAddress, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint16));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::SetByte
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::SetByte (emuptr address, uint32 value)
+{
+#if PROFILE_MEMORY
+ gMemoryAccess[kSRAMByteWrite]++;
+#endif
+
+#if (PREVENT_USER_SRAM_SET)
+ if (gMemAccessFlags.fProtect_SRAMSet)
+ {
+ ProtectedAccess (address, sizeof (uint8), false);
+ }
+#endif
+
+#if (VALIDATE_SRAM_SET)
+ if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint8)))
+ {
+ InvalidAccess (address, sizeof (uint8), false);
+ }
+#endif
+
+#if HAS_PROFILING
+ CYCLE_PUTBYTE (WAITSTATES_SRAM);
+#endif
+
+ emuptr phyAddress = address;
+ phyAddress &= gRAMBank_Mask;
+
+ register uint8* metaAddress = InlineGetMetaAddress (phyAddress);
+// META_CHECK (metaAddress, address, SetLong, uint8, false);
+ ::PrvScreenCheck (metaAddress, address, sizeof (uint8));
+
+ EmMemDoPut8 (gRAM_Memory + phyAddress, value);
+
+ // See if any interesting memory locations have changed. If so,
+ // CheckStepSpy will report it.
+
+ Debug::CheckStepSpy (address, sizeof (uint8));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmBankSRAM::ValidAddress (emuptr address, uint32 size)
+{
+ address -= gMemoryStart;
+ int result = (address + size) <= (gMemoryStart + gRAMBank_Size);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankSRAM::GetRealAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gRAMBank_Mask;
+
+ return (uint8*) &(gRAM_Memory[address]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::GetMetaAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmBankSRAM::GetMetaAddress (emuptr address)
+{
+ // Strip the uppermost bit of the address.
+
+ address &= gRAMBank_Mask;
+
+ return (uint8*) &(gRAM_MetaMemory[address]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::AddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::AddOpcodeCycles (void)
+{
+#if (HAS_PROFILING)
+ CYCLE_GETWORD (WAITSTATES_SRAM);
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::AddressError
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::InvalidAccess
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::InvalidAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmBankSRAM::ProtectedAccess
+// ---------------------------------------------------------------------------
+
+void EmBankSRAM::ProtectedAccess (emuptr address, long size, Bool forRead)
+{
+ EmAssert (gCPU68K);
+ gCPU68K->BusError (address, size, forRead);
+}
+
diff --git a/SrcShared/Hardware/EmBankSRAM.h b/SrcShared/Hardware/EmBankSRAM.h
new file mode 100644
index 0000000..8f5cb23
--- /dev/null
+++ b/SrcShared/Hardware/EmBankSRAM.h
@@ -0,0 +1,58 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmBankSRAM_h
+#define EmBankSRAM_h
+
+class SessionFile;
+
+extern emuptr gMemoryStart;
+
+ // These are also accessed by the DRAMBank functions.
+extern uint32 gRAMBank_Size;
+extern uint32 gRAMBank_Mask;
+extern uint8* gRAM_Memory;
+extern uint8* gRAM_MetaMemory;
+
+
+class EmBankSRAM
+{
+ public:
+ static void Initialize (RAMSizeType ramSize);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void SetBankHandlers (void);
+
+ static uint32 GetLong (emuptr address);
+ static uint32 GetWord (emuptr address);
+ static uint32 GetByte (emuptr address);
+ static void SetLong (emuptr address, uint32 value);
+ static void SetWord (emuptr address, uint32 value);
+ static void SetByte (emuptr address, uint32 value);
+ static int ValidAddress (emuptr address, uint32 size);
+ static uint8* GetRealAddress (emuptr address);
+ static uint8* GetMetaAddress (emuptr address);
+ static void AddOpcodeCycles (void);
+
+ static emuptr GetMemoryStart (void) { return gMemoryStart; }
+
+ private:
+ static void AddressError (emuptr address, long size, Bool forRead);
+ static void InvalidAccess (emuptr address, long size, Bool forRead);
+ static void ProtectedAccess (emuptr address, long size, Bool forRead);
+};
+
+#endif /* EmBankSRAM_h */
diff --git a/SrcShared/Hardware/EmCPU.cpp b/SrcShared/Hardware/EmCPU.cpp
new file mode 100644
index 0000000..22c1031
--- /dev/null
+++ b/SrcShared/Hardware/EmCPU.cpp
@@ -0,0 +1,68 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmCPU.h"
+
+
+EmCPU* gCPU;
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU::EmCPU
+// ---------------------------------------------------------------------------
+
+EmCPU::EmCPU (EmSession* session) :
+ fSession (session)
+{
+ EmAssert (gCPU == NULL);
+ gCPU = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU::~EmCPU
+// ---------------------------------------------------------------------------
+
+EmCPU::~EmCPU (void)
+{
+ EmAssert (gCPU == this);
+ gCPU = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU::Reset
+// ---------------------------------------------------------------------------
+
+void EmCPU::Reset (Bool /*hardwareReset*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU::Save
+// ---------------------------------------------------------------------------
+
+void EmCPU::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU::Load
+// ---------------------------------------------------------------------------
+
+void EmCPU::Load (SessionFile&)
+{
+}
diff --git a/SrcShared/Hardware/EmCPU.h b/SrcShared/Hardware/EmCPU.h
new file mode 100644
index 0000000..a884026
--- /dev/null
+++ b/SrcShared/Hardware/EmCPU.h
@@ -0,0 +1,69 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmCPU_h
+#define EmCPU_h
+
+class EmSession;
+class SessionFile;
+
+class EmCPU;
+extern EmCPU* gCPU;
+
+class EmCPU
+{
+ public:
+ // -----------------------------------------------------------------------------
+ // constructor / destructor
+ // -----------------------------------------------------------------------------
+
+ EmCPU (EmSession*);
+ virtual ~EmCPU (void);
+
+ // -----------------------------------------------------------------------------
+ // public methods
+ // -----------------------------------------------------------------------------
+
+ // Standard sub-system methods:
+ // Reset: Resets the state. Called on hardware resets or on
+ // calls to SysReset. Also called from constructor.
+ // Save: Saves the state to the given file.
+ // Load: Loads the state from the given file. Can assume that
+ // Reset has been called first.
+
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+
+ // Execute the main CPU loop until asked to stop.
+
+ virtual void Execute (void) = 0;
+ virtual void CheckAfterCycle (void) = 0;
+
+ // Low-level access to CPU state.
+
+ virtual emuptr GetPC (void) = 0;
+ virtual emuptr GetSP (void) = 0;
+ virtual uint32 GetRegister (int) = 0;
+
+ virtual void SetPC (emuptr) = 0;
+ virtual void SetSP (emuptr) = 0;
+ virtual void SetRegister (int, uint32) = 0;
+
+ virtual Bool Stopped (void) = 0;
+
+ protected:
+ EmSession* fSession;
+};
+
+#endif /* EmCPU_h */
diff --git a/SrcShared/Hardware/EmCPU68K.cpp b/SrcShared/Hardware/EmCPU68K.cpp
new file mode 100644
index 0000000..e3f00e2
--- /dev/null
+++ b/SrcShared/Hardware/EmCPU68K.cpp
@@ -0,0 +1,1849 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmCPU68K.h"
+
+#include "Byteswapping.h" // Canonical
+#include "DebugMgr.h" // gExceptionAddress, gExceptionSize, gExceptionForRead
+#include "EmBankROM.h" // EmBankROM::GetMemoryStart
+#include "EmEventPlayback.h" // EmEventPlayback::ReplayingEvents
+#include "EmHAL.h" // EmHAL::GetInterruptLevel
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmMinimize.h" // IsOn
+#include "EmSession.h" // HandleInstructionBreak
+#include "Logging.h" // LogAppendMsg
+#include "MetaMemory.h" // IsCPUBreak
+#include "Platform.h" // GetMilliseconds
+#include "SessionFile.h" // WriteDBallRegs, etc.
+#include "StringData.h" // kExceptionNames
+#include "UAE.h" // cpuop_func, etc.
+
+#include <algorithm> // find
+
+#if __profile__
+#include <Profiler.h>
+#endif
+
+#if defined (macintosh) && defined (_DEBUG) && 0
+ #define HAS_DEAD_MANS_SWITCH 1
+#else
+ #define HAS_DEAD_MANS_SWITCH 0
+#endif
+
+// !!! Why is this here? Shouldn't it be in Profiling.h?
+#if HAS_PROFILING
+perfRec perftbl[65536];
+#endif
+
+// Define our own flags for regs.spcflag. Please do not let these
+// overlap with UAE-defined flags (should not fall below 0x0002000)
+// and avoid using the high bit just for safety.
+
+#define SPCFLAG_END_OF_CYCLE (0x40000000)
+
+
+// Data needed by UAE.
+
+int areg_byteinc[] = { 1,1,1,1,1,1,1,2 }; // (normally in newcpu.c)
+int imm8_table[] = { 8,1,2,3,4,5,6,7 }; // (normally in newcpu.c)
+
+int movem_index1[256]; // (normally in newcpu.c)
+int movem_index2[256]; // (normally in newcpu.c)
+int movem_next[256]; // (normally in newcpu.c)
+
+cpuop_func* cpufunctbl[65536]; // (normally in newcpu.c)
+
+uint16 last_op_for_exception_3; /* Opcode of faulting instruction */
+emuptr last_addr_for_exception_3; /* PC at fault time */
+emuptr last_fault_for_exception_3; /* Address that generated the exception */
+
+struct regstruct regs; // (normally in newcpu.c)
+struct flag_struct regflags; // (normally in support.c)
+
+
+// These variables should strictly be in a sub-system that implements
+// the stack overflow checking, etc. However, for performance reasons,
+// we need to expose them to UAE (see the CHECK_STACK_POINTER_ASSIGNMENT,
+// et al macros), so define them here.
+//
+// Similar comments for the CheckKernelStack function.
+
+uae_u32 gStackHigh;
+uae_u32 gStackLowWarn;
+uae_u32 gStackLow;
+uae_u32 gKernelStackOverflowed;
+
+
+// Definitions of the stack frames used in EmCPU68K::ProcessException.
+
+#include "PalmPack.h"
+
+struct ExceptionStackFrame1
+{
+ uint16 statusRegister;
+ uint32 programCounter;
+};
+
+struct ExceptionStackFrame2
+{
+ uint16 functionCode;
+ uint32 accessAddress;
+ uint16 instructionRegister;
+ uint16 statusRegister;
+ uint32 programCounter;
+};
+
+#include "PalmPackPop.h"
+
+
+EmCPU68K* gCPU68K;
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Cycle
+// ---------------------------------------------------------------------------
+
+// this guy is a macro instead of an inline function so that "counter" can
+// be declared as a variable local to the calling function. The resulting
+// code can be more efficient if "counter" can be cached in a register
+// instead of being a static or global variable.
+
+#define CYCLE(sleeping) \
+{ \
+ /* Don't do anything if we're in the middle of an ATrap call. We don't */ \
+ /* need interrupts firing or tmr counters incrementing. */ \
+ \
+ EmAssert (session); \
+ if (!session->IsNested ()) \
+ { \
+ /* Perform CPU-specific idling. */ \
+ \
+ EmHAL::Cycle (sleeping); \
+ \
+ /* Perform expensive operations. */ \
+ \
+ if (sleeping || ((++counter & 0x7FFF) == 0)) \
+ { \
+ this->CycleSlowly (sleeping); \
+ } \
+ } \
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::EmCPU68K
+// ---------------------------------------------------------------------------
+
+EmCPU68K::EmCPU68K (EmSession* session) :
+ EmCPU (session),
+ fLastTraceAddress (EmMemNULL),
+ fCycleCount (0),
+// fExceptionHandlers (),
+ fHookJSR (),
+ fHookJSR_Ind (),
+ fHookLINK (),
+ fHookRTE (),
+ fHookRTS (),
+ fHookNewPC (),
+ fHookNewSP ()
+#if REGISTER_HISTORY
+ , fRegHistoryIndex (0)
+// , fRegHistory ()
+#endif
+#if EXCEPTION_HISTORY
+ , fExceptionHistoryIndex (0)
+// , fExceptionHistory ()
+#endif
+{
+ this->InitializeUAETables ();
+
+ EmAssert (gCPU68K == NULL);
+ gCPU68K = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::~EmCPU68K
+// ---------------------------------------------------------------------------
+
+EmCPU68K::~EmCPU68K (void)
+{
+ EmAssert (gCPU68K == this);
+ gCPU68K = NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Reset
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::Reset (Bool hardwareReset)
+{
+ fLastTraceAddress = EmMemNULL;
+ fCycleCount = 0;
+
+#if REGISTER_HISTORY
+ fRegHistoryIndex = 0;
+#endif
+
+#if EXCEPTION_HISTORY
+ fExceptionHistoryIndex = 0;
+#endif
+
+ gStackHigh = EmMemEOM;
+ gStackLowWarn = EmMemNULL;
+ gStackLow = EmMemNULL;
+ gKernelStackOverflowed = false;
+
+ if (hardwareReset)
+ {
+ // (taken from m68k_reset in newcpu.c)
+
+ // !!! I think that we really need to emulate ROM appearing at NULL.
+ // That would break our dependency on EmBankROM.
+
+ emuptr romStart = EmBankROM::GetMemoryStart ();
+ m68k_areg (regs, 7) = EmMemGet32 (romStart);
+ m68k_setpc (EmMemGet32 (romStart + 4));
+
+ // Note, on the 68K, the t0 and m flags must always be zero.
+
+ regs.prefetch = 0x0000;
+ regs.kick_mask = 0xF80000; // (not a 68K register)
+ regs.s = 1; // supervisor/user state
+ regs.m = 0; // master/interrupt state
+ regs.stopped = 0; // (not a 68K register)
+ regs.t1 = 0; // 1 = trace on any instruction
+ regs.t0 = 0; // 1 = trace on change of flow
+ SET_ZFLG (0);
+ SET_XFLG (0);
+ SET_CFLG (0);
+ SET_VFLG (0);
+ SET_NFLG (0);
+ regs.spcflags = 0; // (not a 68K register)
+ regs.intmask = 7; // disable all interrupts
+ regs.vbr = regs.sfc = regs.dfc = 0;
+ regs.fpcr = regs.fpsr = regs.fpiar = 0;
+ }
+
+ Memory::CheckNewPC (m68k_getpc ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Save
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::Save (SessionFile& f)
+{
+ // Write out the CPU Registers
+
+ regstruct tempRegs;
+ this->GetRegisters (tempRegs);
+
+ Canonical (tempRegs);
+ f.WriteDBallRegs (tempRegs);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Load
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::Load (SessionFile& f)
+{
+ // Read in the CPU Registers.
+
+ regstruct tempRegs;
+ f.ReadDBallRegs (tempRegs);
+
+ Canonical (tempRegs);
+ this->SetRegisters (tempRegs);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Execute
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::Execute (void)
+{
+ // This function is the bottleneck for all 68K emulation. It's
+ // important that it run as quickly as possible. To that end,
+ // fine tune register allocation as much as we can by hand.
+
+#if defined(__powerc) || defined(powerc) || \
+ defined(__powerpc) || defined(powerpc) || \
+ defined(__ppc__) || defined(ppc)
+
+ register int counter = 0;
+ register cpuop_func** functable = cpufunctbl;
+
+ register uint8** pc_p_p = &regs.pc_p;
+ register uint8** pc_meta_oldp_p = &regs.pc_meta_oldp;
+ register uint8** pc_oldp_p = &regs.pc_oldp;
+ register uint32* spcflags_p = &regs.spcflags;
+ register EmSession* session = fSession;
+
+ #define pc_p (*pc_p_p)
+ #define pc_meta_oldp (*pc_meta_oldp_p)
+ #define pc_oldp (*pc_oldp_p)
+ #define spcflags (*spcflags_p)
+
+#elif defined(_MSC_VER) && defined(_M_IX86)
+
+ register int counter = 0;
+ register cpuop_func** functable = cpufunctbl;
+
+ #define pc_p (regs.pc_p)
+ #define pc_meta_oldp (regs.pc_meta_oldp)
+ #define pc_oldp (regs.pc_oldp)
+ #define spcflags (regs.spcflags)
+ #define session (fSession)
+
+#else
+
+ register int counter = 0;
+ register cpuop_func** functable = cpufunctbl;
+
+ #define pc_p (regs.pc_p)
+ #define pc_meta_oldp (regs.pc_meta_oldp)
+ #define pc_oldp (regs.pc_oldp)
+ #define spcflags (regs.spcflags)
+ #define session (fSession)
+
+#endif
+
+#if HAS_PROFILING_DEBUG
+ UInt64 readCyclesSaved = 0;
+ UInt64 writeCyclesSaved = 0;
+ UInt64 clockCyclesSaved = 0;
+#endif
+
+#if HAS_DEAD_MANS_SWITCH
+ // -----------------------------------------------------------------------
+ // Put in a little dead-man's switch. If this function doesn't exit for a
+ // long time, let us get into the debugger.
+ // -----------------------------------------------------------------------
+
+ uint32 deadManNow;
+ uint32 deadManStart = Platform::GetMilliseconds ();
+#endif
+
+ // -----------------------------------------------------------------------
+ // Check for the stopped flag before entering the "execute an opcode"
+ // section. It could be that we last exited the loop while still in stop
+ // mode, and we need to wind our way back down to that spot.
+ // -----------------------------------------------------------------------
+
+ if ((spcflags & SPCFLAG_STOP) != 0)
+ goto StoppedLoop;
+
+ while (1)
+ {
+#if REGISTER_HISTORY
+ // -----------------------------------------------------------------------
+ // Save the registers for the post-mortem, but don't record the
+ // instructions we generate when calling the ROM as a subroutine. We want
+ // those to be as transparent as possible. In particular, we don't want
+ // any functions that we call as part of figuring out why a problem
+ // occurred to knock the problem-causing registers off of our array.
+ // -----------------------------------------------------------------------
+
+// if (!session->IsNested ())
+ {
+ ++fRegHistoryIndex;
+ fRegHistory[fRegHistoryIndex & (kRegHistorySize - 1)] = regs;
+ }
+#endif
+
+#if HAS_DEAD_MANS_SWITCH
+ // -----------------------------------------------------------------------
+ // Put in a little dead-man's switch. If this function doesn't exit for a
+ // long time, let us get into the debugger.
+ // -----------------------------------------------------------------------
+
+ deadManNow = Platform::GetMilliseconds ();
+ if ((deadManNow - deadManStart) > 5000)
+ {
+ Platform::Debugger ();
+ }
+#endif
+
+ // -----------------------------------------------------------------------
+ // See if we need to halt CPU execution at this location. We could need
+ // to do this for several reasons, including hitting soft breakpoints or
+ // needing to execute tailpatches.
+ // -----------------------------------------------------------------------
+
+ if (MetaMemory::IsCPUBreak (pc_meta_oldp + (pc_p - pc_oldp)))
+ {
+ EmAssert (session);
+ session->HandleInstructionBreak ();
+ }
+
+#if HAS_PROFILING
+ emuptr pcStart;
+ pcStart = m68k_getpc ();
+
+ if (gProfilingEnabled)
+ {
+ // If detailed, log instruction here
+
+ if (gProfilingDetailed)
+ {
+ ProfileInstructionEnter (pcStart);
+ }
+
+#if HAS_PROFILING_DEBUG
+ readCyclesSaved = gReadCycles;
+ writeCyclesSaved = gWriteCycles;
+ clockCyclesSaved = gClockCycles;
+#endif
+
+ // Turn gProfilingCounted on here so the opcode fetch below is counted.
+
+ gProfilingCounted = true;
+ }
+#endif
+
+ // =======================================================================
+ // Execute the opcode.
+ // -----------------------------------------------------------------------
+ // Interestingly, defining "opcode" as an EmOpcode68K (which is a uint32)
+ // instead of a uint16 (which is all you need to hold the opcode), makes
+ // a big difference in performance (at least, on Intel). The former
+ // generates:
+ //
+ // mov edx, DWORD PTR _regs+92
+ // xor eax, eax
+ // mov ax, WORD PTR [edx]
+ // push eax
+ // call DWORD PTR [edi+eax*4]
+ //
+ // while the latter generates:
+ //
+ // mov edx, DWORD PTR _regs+92
+ // mov ax, WORD PTR [edx]
+ // and eax, 65535 ; 0000ffffH
+ // push eax
+ // call DWORD PTR [edi+eax*4]
+ //
+ // This results in an amazing 5% performance difference. What makes it
+ // even more amazing is that similar optimizations elsewhere don't seem
+ // to help. For instance, in EmCPU68K::Cycle, there's the expression:
+ //
+ // ((++gCounter) & 0x7FFF == 0)
+ //
+ // Changing gCounter to a uint16, or changing the expression to:
+ //
+ // ((uint16) ++gCounter) == 0)
+ //
+ // both result in the period doubling, but also in better code
+ // generation. However, neither gives better performance. Additionally,
+ // I tried like heck to optimize the call to IsCPUBreak above. I added
+ // a preflight check that would skip 70% of the calls to IsCPUBreak (as
+ // well as the calculation of the parameter passed to it) and re-
+ // organized the code so that branch prediction would work. However,
+ // none of that resulted in better performance.
+ // -----------------------------------------------------------------------
+ EmOpcode68K opcode;
+ // opcode = get_iword (0);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ get_word(regs.pc + ((char*) pc_p - (char*) pc_oldp));
+#endif
+ opcode = do_get_mem_word (pc_p);
+ fCycleCount += (functable[opcode]) (opcode);
+ // =======================================================================
+
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ // Add in the extra time taken to execute the instruction.
+
+ ProfileIncrementClock (perftbl[opcode].extraCycles);
+
+ // Detail (instruction level) profiling support
+
+ if (gProfilingDetailed)
+ {
+ ProfileInstructionExit (pcStart);
+ }
+
+#if HAS_PROFILING_DEBUG
+ // Validity check on EmMemory stuff.
+
+ Boolean tryAgain = false;
+
+ if (perftbl[opcode].readCycles != 0xFF &&
+ gReadCycles - readCyclesSaved != perftbl[opcode].readCycles)
+ {
+ gReadMismatch += gReadCycles - readCyclesSaved - perftbl[opcode].readCycles;
+ }
+
+ if (perftbl[opcode].writeCycles != 0xFF &&
+ gWriteCycles - writeCyclesSaved != perftbl[opcode].writeCycles)
+ {
+ gWriteMismatch += gWriteCycles - writeCyclesSaved - perftbl[opcode].writeCycles;
+ }
+
+ if (tryAgain)
+ {
+ (functable[opcode]) (opcode);
+ }
+#endif
+ }
+#endif
+
+ // Perform periodic tasks.
+
+ CYCLE (false);
+
+StoppedLoop:
+
+ // -----------------------------------------------------------------------
+ // Handle special conditions. NB: the code reached by calling
+ // EmCPU68K::ExecuteSpecial used to be inline in this function. Moving it
+ // out (thus simplifying both EmCPU68K::Execute and EmCPU68K::ExecuteSpecial)
+ // sped up the CPU loop by 9%!
+ // -----------------------------------------------------------------------
+
+ if (spcflags)
+ {
+ if (this->ExecuteSpecial ())
+ break;
+ }
+
+#if HAS_PROFILING
+ gProfilingCounted = false;
+#endif
+ } // while (1)
+
+#undef pc_p
+#undef pc_meta_oldp
+#undef pc_oldp
+#undef spcflags
+#undef session
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ExecuteSimple
+// ---------------------------------------------------------------------------
+
+/*
+ This is the same loop with the following removed:
+
+ * Comments
+ * Profiling code
+ * Profiling debugging code
+ * Dead mans's check on Mac
+ * Register history recording
+
+ It's essentially what we get in Release/Non-profile builds.
+*/
+
+#if 0
+
+void EmCPU68K::ExecuteSimple (void)
+{
+ if ((regs.spcflags & SPCFLAG_STOP) != 0)
+ goto StoppedLoop;
+
+ while (1)
+ {
+ if (MetaMemory::IsCPUBreak (regs.pc_meta_oldp + (regs.pc_p - regs.pc_oldp)))
+ {
+ this->HandleInstructionBreak ();
+ }
+
+ EmOpcode68K opcode;
+ opcode = get_iword (0);
+ fCycleCount += cpufunctbl[opcode] (opcode);
+
+ this->Cycle (false);
+
+StoppedLoop:
+ if (regs.spcflags)
+ {
+ if (this->ExecuteSpecial ())
+ break;
+ }
+ }
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ExecuteSpecial
+// ---------------------------------------------------------------------------
+
+Bool EmCPU68K::ExecuteSpecial (void)
+{
+ // If we're making subroutine calls, then all we process are requests
+ // to break from the CPU loop. We don't want interrupts, tracing, etc.
+ // getting in the way.
+
+ EmAssert (fSession);
+ if (fSession->IsNested () != 0)
+ {
+ return this->CheckForBreak ();
+ }
+
+ // Check for Reset first. If this is set, don't do anything else.
+
+ if ((regs.spcflags & SPCFLAG_END_OF_CYCLE))
+ {
+ if (fSession->ExecuteSpecial (true))
+ return true;
+ }
+
+ // Execute UAE spcflags-handling code (from do_specialties in newcpu.c).
+
+ // If we're tracing, execute the trace vector.
+ //
+ // The check for SPCFLAG_STOP was added in Poser. It's needed
+ // if we're re-entering ExecuteStopped loop on the Mac after
+ // exiting in order to handle events.
+
+ if ((regs.spcflags & SPCFLAG_DOTRACE) && !(regs.spcflags & SPCFLAG_STOP))
+ {
+ this->ProcessException (kException_Trace);
+ }
+
+ if (regs.spcflags & SPCFLAG_STOP)
+ {
+ if (this->ExecuteStoppedLoop ())
+ {
+ regs.spcflags &= ~SPCFLAG_BRK;
+ return true;
+ }
+ }
+
+ // Do trace-mode stuff (do_trace from newcpu.c does more,
+ // but it's only needed for CPU_LEVEL > 0)
+
+ if (regs.spcflags & SPCFLAG_TRACE)
+ {
+ if (regs.t1)
+ {
+ fLastTraceAddress = m68k_getpc ();
+ regs.spcflags &= ~SPCFLAG_TRACE;
+ regs.spcflags |= SPCFLAG_DOTRACE;
+ }
+ }
+
+ if ((regs.spcflags & SPCFLAG_DOINT) && !gKernelStackOverflowed)
+ {
+ int32 interruptLevel = EmHAL::GetInterruptLevel ();
+ regs.spcflags &= ~SPCFLAG_DOINT; // was ~(SPCFLAG_INT | SPCFLAG_DOINT) in Greg and Craig, but the latest UAE has this
+ if ((interruptLevel != -1) && (interruptLevel > regs.intmask))
+ {
+ this->ProcessInterrupt (interruptLevel);
+ regs.stopped = 0;
+ }
+ }
+
+ if (regs.spcflags & SPCFLAG_INT)
+ {
+ regs.spcflags &= ~SPCFLAG_INT;
+ regs.spcflags |= SPCFLAG_DOINT;
+ }
+
+ // Check for Poser end-of-cycle operations. This is inserted
+ // before the standard UAE check of the SPCFLAG_BRK flag.
+
+ if ((regs.spcflags & SPCFLAG_END_OF_CYCLE))
+ {
+ regs.spcflags &= ~SPCFLAG_END_OF_CYCLE;
+
+ if (fSession->ExecuteSpecial (false))
+ return true;
+ }
+
+ return this->CheckForBreak ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ExecuteStoppedLoop
+// ---------------------------------------------------------------------------
+
+Bool EmCPU68K::ExecuteStoppedLoop (void)
+{
+ register EmSession* session = fSession;
+
+ EmAssert (session);
+ EmAssert (!session->IsNested ());
+ EmAssert (regs.intmask < 7);
+
+ // If we're running Gremlins and the device goes to sleep (as opposed
+ // to just dozing), pretend the user clicked on the Power button).
+
+ if (EmHAL::GetAsleep () && !session->HasButtonEvent ())
+ {
+ // Turns Hordes off for a moment, as pen events are rejected
+ // when it's running!
+
+ Bool hordesWasOn = false;
+ Bool playbackWasOn = false;
+ Bool minimizationWasOn = false;
+
+ if (Hordes::IsOn ())
+ {
+ Hordes::TurnOn (false);
+ hordesWasOn = true;
+ }
+
+ if (EmEventPlayback::ReplayingEvents ())
+ {
+ EmEventPlayback::ReplayEvents (false);
+ playbackWasOn = true;
+ }
+
+ if (EmMinimize::IsOn ())
+ {
+ EmMinimize::TurnOn (false);
+ minimizationWasOn = true;
+ }
+
+ /*
+ When posting the button down event for the Power button, include
+ a flag that causes the event to be posted to the hardware NOW.
+ Normally, EmSession employs a throttling mechanism that prevents
+ button events from showing up in the hardware too quickly. This
+ throttling allows the time for the OS to wakeup and respond to
+ the hardware interrupt.
+
+ However, the throttling also leads to an incredibly subtle bug
+ if it's used unconditionally. Consider the following sequence
+ of events:
+
+ * Gremlins creates a vchrAutoOff event
+ * The system responds to it and goes to sleep.
+ * Poser notices the device is asleep while running a Gremlin,
+ and posts Power button down/up events.
+ * It's been more than 100msec since the last button event, so
+ the button event is given to the hardware immediately.
+ * The system wakes up, notices that the Power key is down, and
+ sets the flag that says it should stay awake.
+ * Gremlins starts posting events again.
+ * Within 100msecs, Gremlins generates another vchrAutoOff event.
+ * The devices goes to sleep again. Somewhere in the process of
+ dealing with the vchrAutoOff event, the Power-button up event
+ is popped off and handled.
+ * Poser posts Power button down/up events again.
+ * Because it's been within 100msecs of the last time a button
+ event was popped off the queue, these events are held in the
+ queue for a while.
+ * An RTC interrupt occurs.
+ * The device wakes up, notices that the Power is not down, and
+ does NOT set the bit that says to stay awake.
+ * The devices goes back to sleep after processing the RTC
+ interrupt. Note that there are still two Power-button events
+ in EmSession's button queue.
+ * Poser notices that the device is off, and posts *another*
+ pair of Power-button down/up events.
+ * At this point, Poser is in a weird state, where there are too
+ many events in the queue. In fact, the situation will get
+ worse, with more and more events piling up and the system
+ deals with turning itself on and off in response to the pending
+ button events. The result is that the user sees the device
+ flashing on and off.
+
+ In order to avoid this problem, have the Power button posted to
+ the hardware registers immediately, before an interrupt can get
+ in the way.
+
+ Note that there is another potential bug here. We avoid it for
+ now, but be careful not to introduce it later. By passing "true"
+ to PostButtonEvent, we can make the button event available to
+ the hardware immediately. However, the event is not forced onto
+ the hardware. Instead, the hardware polls for any pending button
+ events at some reasonable rate. That is, even if EmSession is
+ prepared to say that there is a pending button event, EmCPU may
+ not pick up on it until some time later based on its checking
+ frequency.
+
+ We avoid this problem for now because the hardware checks for
+ button events in EmHAL::CycleSlowly, which is called
+ unconditionally when the processor is moved out of the "stopped"
+ state.
+ */
+
+ if (hordesWasOn || playbackWasOn || minimizationWasOn)
+ {
+ EmButtonEvent event (kElement_PowerButton, true);
+ session->PostButtonEvent (event, true);
+
+ event.fButtonIsDown = false;
+ session->PostButtonEvent (event);
+ }
+
+ if (hordesWasOn)
+ {
+ Hordes::TurnOn (true);
+ }
+
+ if (playbackWasOn)
+ {
+ EmEventPlayback::ReplayEvents (true);
+ }
+
+ if (minimizationWasOn)
+ {
+ EmMinimize::TurnOn (true);
+ }
+ }
+
+ int counter = 0;
+
+ // While the CPU is stopped (because a STOP instruction was
+ // executed) do some idle tasks.
+
+#if HAS_DEAD_MANS_SWITCH
+ // -----------------------------------------------------------------------
+ // Put in a little dead-man's switch. If this function doesn't
+ // exit for a long time, let us get into the debugger.
+ // -----------------------------------------------------------------------
+
+ uint32 deadManStart = Platform::GetMilliseconds ();
+#endif
+
+ do {
+#if HAS_DEAD_MANS_SWITCH
+ // -----------------------------------------------------------------------
+ // Put in a little dead-man's switch. If this function doesn't
+ // exit for a long time, let us get into the debugger.
+ // -----------------------------------------------------------------------
+
+ uint32 deadManNow = Platform::GetMilliseconds ();
+ if ((deadManNow - deadManStart) > 5000)
+ {
+ Platform::Debugger ();
+ }
+#endif
+
+ // -----------------------------------------------------------------------
+ // Slow down processing so that the timer used
+ // to increment the tickcount doesn't run too quickly.
+ // -----------------------------------------------------------------------
+
+#if __profile__
+ short oldStatus = ProfilerGetStatus ();
+ ProfilerSetStatus (false);
+#endif
+
+ Platform::Delay ();
+
+#if __profile__
+ ProfilerSetStatus (oldStatus);
+#endif
+
+ // Perform periodic tasks.
+
+ CYCLE (true);
+
+ // Process an interrupt (see if it's time to wake up).
+
+ if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT))
+ {
+ int32 interruptLevel = EmHAL::GetInterruptLevel ();
+
+ regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
+
+ if ((interruptLevel != -1) && (interruptLevel > regs.intmask))
+ {
+ this->ProcessInterrupt (interruptLevel);
+ regs.stopped = 0;
+ regs.spcflags &= ~SPCFLAG_STOP;
+ }
+ }
+
+ if (this->CheckForBreak ())
+ {
+ return true;
+ }
+ } while (regs.spcflags & SPCFLAG_STOP);
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::CycleSlowly
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::CycleSlowly (Bool sleeping)
+{
+ EmHAL::CycleSlowly (sleeping);
+
+ // Do some platform-specific stuff.
+
+ Platform::CycleSlowly ();
+
+#if HAS_OMNI_THREAD
+ // Check to see if some external thread has asked us to quit.
+
+ EmAssert (fSession);
+ omni_mutex_lock lock (fSession->fSharedLock);
+
+ if (fSession->fSuspendState.fAllCounters)
+ {
+ this->CheckAfterCycle ();
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::CheckAfterCycle
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::CheckAfterCycle (void)
+{
+ regs.spcflags |= SPCFLAG_END_OF_CYCLE;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::GetPC
+// ---------------------------------------------------------------------------
+
+emuptr EmCPU68K::GetPC (void)
+{
+// return this->GetRegister (e68KRegID_PC);
+ return m68k_getpc ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::GetSP
+// ---------------------------------------------------------------------------
+
+emuptr EmCPU68K::GetSP (void)
+{
+// return this->GetRegister (e68KRegID_SSP);
+ return m68k_areg (regs, 7);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::GetRegister
+// ---------------------------------------------------------------------------
+
+uint32 EmCPU68K::GetRegister (int index)
+{
+ uint32 result = 0;
+
+ switch (index)
+ {
+ case e68KRegID_D0: result = m68k_dreg (regs, 0); break;
+ case e68KRegID_D1: result = m68k_dreg (regs, 1); break;
+ case e68KRegID_D2: result = m68k_dreg (regs, 2); break;
+ case e68KRegID_D3: result = m68k_dreg (regs, 3); break;
+ case e68KRegID_D4: result = m68k_dreg (regs, 4); break;
+ case e68KRegID_D5: result = m68k_dreg (regs, 5); break;
+ case e68KRegID_D6: result = m68k_dreg (regs, 6); break;
+ case e68KRegID_D7: result = m68k_dreg (regs, 7); break;
+ case e68KRegID_A0: result = m68k_areg (regs, 0); break;
+ case e68KRegID_A1: result = m68k_areg (regs, 1); break;
+ case e68KRegID_A2: result = m68k_areg (regs, 2); break;
+ case e68KRegID_A3: result = m68k_areg (regs, 3); break;
+ case e68KRegID_A4: result = m68k_areg (regs, 4); break;
+ case e68KRegID_A5: result = m68k_areg (regs, 5); break;
+ case e68KRegID_A6: result = m68k_areg (regs, 6); break;
+ case e68KRegID_USP: result = m68k_areg (regs, 7); break;
+ case e68KRegID_SSP: result = m68k_areg (regs, 7); break;
+ case e68KRegID_PC: result = m68k_getpc (); break;
+ case e68KRegID_SR:
+ this->UpdateSRFromRegisters ();
+ result = regs.sr;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::SetPC
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::SetPC (emuptr newPC)
+{
+ this->SetRegister (e68KRegID_PC, newPC);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::SetSP
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::SetSP (emuptr newPC)
+{
+ this->SetRegister (e68KRegID_SSP, newPC);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::SetRegister
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::SetRegister (int index, uint32 val)
+{
+ switch (index)
+ {
+ case e68KRegID_D0: m68k_dreg (regs, 0) = val; break;
+ case e68KRegID_D1: m68k_dreg (regs, 1) = val; break;
+ case e68KRegID_D2: m68k_dreg (regs, 2) = val; break;
+ case e68KRegID_D3: m68k_dreg (regs, 3) = val; break;
+ case e68KRegID_D4: m68k_dreg (regs, 4) = val; break;
+ case e68KRegID_D5: m68k_dreg (regs, 5) = val; break;
+ case e68KRegID_D6: m68k_dreg (regs, 6) = val; break;
+ case e68KRegID_D7: m68k_dreg (regs, 7) = val; break;
+ case e68KRegID_A0: m68k_areg (regs, 0) = val; break;
+ case e68KRegID_A1: m68k_areg (regs, 1) = val; break;
+ case e68KRegID_A2: m68k_areg (regs, 2) = val; break;
+ case e68KRegID_A3: m68k_areg (regs, 3) = val; break;
+ case e68KRegID_A4: m68k_areg (regs, 4) = val; break;
+ case e68KRegID_A5: m68k_areg (regs, 5) = val; break;
+ case e68KRegID_A6: m68k_areg (regs, 6) = val; break;
+ case e68KRegID_USP: m68k_areg (regs, 7) = val; break;
+ case e68KRegID_SSP: m68k_areg (regs, 7) = val; break;
+ case e68KRegID_PC: m68k_setpc (val); break;
+ case e68KRegID_SR:
+ regs.sr = val;
+ this->UpdateRegistersFromSR ();
+ break;
+
+ default:
+ EmAssert (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::Stopped
+// ---------------------------------------------------------------------------
+// Return whether or not the CPU itself is halted. This is seperate from
+// whether or not the session (that is, the thread emulating the CPU) is
+// halted.
+
+Bool EmCPU68K::Stopped (void)
+{
+ return regs.stopped;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::CheckForBreak
+// ---------------------------------------------------------------------------
+// Check to see if the conditions tell us to break from the CPU Execute loop.
+
+Bool EmCPU68K::CheckForBreak (void)
+{
+ if ((regs.spcflags & SPCFLAG_BRK) != 0)
+ {
+ regs.spcflags &= ~SPCFLAG_BRK;
+ return true;
+ }
+
+ EmAssert (fSession);
+ return fSession->CheckForBreak ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessInterrupt
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::ProcessInterrupt (int32 interrupt)
+{
+ this->ProcessException ((ExceptionNumber) (EmHAL::GetInterruptBase () + interrupt));
+
+ regs.intmask = interrupt;
+ regs.spcflags |= SPCFLAG_INT; // Check for higher-level interrupts
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessException
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::ProcessException (ExceptionNumber exception)
+{
+ // Make sure the Status Register is up-to-date.
+
+ this->UpdateSRFromRegisters ();
+
+#if EXCEPTION_HISTORY
+ // Save the exception for the post-mortem
+
+ fExceptionHistoryIndex++;
+
+ long index = fExceptionHistoryIndex & (kExceptionHistorySize - 1);
+ fExceptionHistory[index].name = kExceptionNames[exception];
+
+ fExceptionHistory[index].pc = m68k_getpc ();
+ fExceptionHistory[index].sp = m68k_areg (regs, 7);
+#endif
+
+#if HAS_PROFILING
+ // Don't count cycles spent in exception handlers against functions.
+
+ // Get and remember the current PC here. This is important to make the
+ // profiling routines come out right. If Poser decides to completely
+ // handle the exception and profiling is on, then the handler will return
+ // true (setting "handled" to true), and adjust the program counter.
+ // Since "handled" is true, Poser calls ProfileInterruptExit, this time
+ // with the current PC. ProfileInterruptExit sees the adjusted PC, and
+ // determines that the funky TRAP $F thing is going on, resulting in it
+ // pushing a new function-call record on its stack. However, since Poser
+ // has completely handled the interrupt, we don't want that to happen.
+ // All we want is to remove the entry recorded by ProfileInterruptEnter.
+ // By saving the current PC value here and passing it to ProfileInterruptExit
+ // later, we achieve that affect. ProfileInterruptExit will record an
+ // "interrupt mismatch", but I can live with that...
+
+ emuptr curpc = m68k_getpc ();
+
+ if (gProfilingEnabled)
+ {
+ ProfileInterruptEnter (exception, curpc);
+ }
+#endif
+
+ // Let any custom exception handler have a go at it. If it returns
+ // true, it handled it completely, and we don't have anything else to do.
+ //
+ // By "handled it completely", we could mean one of two things. (1)
+ // that Poser completely replaced the system function and the ROM
+ // function was skipped, or (2) Poser dealt with the trap dispatch
+ // process, setting the PC to the function entry point.
+ //
+ // If profiling is on, (2) never occurs because we want to profile the
+ // trap dispatcher itself. Therefore, only (1) is possible.
+
+ Bool handled = false;
+ Hook68KExceptionList& fns = fExceptionHandlers[exception];
+ Hook68KExceptionList::iterator iter = fns.begin ();
+ while (iter != fns.end ())
+ {
+ if ((*iter) (exception))
+ {
+ handled = true;
+ }
+
+ ++iter;
+ }
+
+ if (handled)
+ {
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ {
+ ProfileInterruptExit (curpc);
+ }
+#endif
+ return;
+ }
+
+ // The following is vaguely modelled after Exception() from newcpu.c
+ // (The call to MakeSR appears at the start of this method).
+
+ // If not in supervisor mode, set the usp, restore A7 from the isp,
+ // and transfer to supervisor mode.
+
+ if (!regs.s)
+ {
+ regs.usp = m68k_areg (regs, 7);
+ m68k_areg (regs, 7) = regs.isp;
+ regs.s = 1;
+ }
+
+ // Set up the stack frame.
+ // !!! If we're handling a trace exception, I think that fLastTraceAddress
+ // comes into play here instead of m68k_getpc.
+ // !!! Manage this with EmPalmStructs...
+
+ if (exception == kException_BusErr || exception == kException_AddressErr)
+ {
+ COMPILE_TIME_ASSERT (sizeof (ExceptionStackFrame2) == 14);
+ m68k_areg (regs, 7) -= sizeof (ExceptionStackFrame2);
+ CHECK_STACK_POINTER_DECREMENT ();
+
+ emuptr frame = m68k_areg (regs, 7);
+
+ // Eh...Palm OS doesn't use these 3 anyway...
+ EmMemPut16 (frame + offsetof (ExceptionStackFrame2, functionCode), 0);
+ EmMemPut32 (frame + offsetof (ExceptionStackFrame2, accessAddress), 0);
+ EmMemPut16 (frame + offsetof (ExceptionStackFrame2, instructionRegister), 0);
+
+ EmMemPut16 (frame + offsetof (ExceptionStackFrame2, statusRegister), regs.sr);
+ EmMemPut32 (frame + offsetof (ExceptionStackFrame2, programCounter), m68k_getpc ());
+ }
+ else
+ {
+ COMPILE_TIME_ASSERT (sizeof (ExceptionStackFrame1) == 6);
+ m68k_areg (regs, 7) -= sizeof (ExceptionStackFrame1);
+ CHECK_STACK_POINTER_DECREMENT ();
+
+ emuptr frame = m68k_areg (regs, 7);
+
+ EmMemPut16 (frame + offsetof (ExceptionStackFrame1, statusRegister), regs.sr);
+ EmMemPut32 (frame + offsetof (ExceptionStackFrame1, programCounter), m68k_getpc ());
+ }
+
+ emuptr newpc;
+ {
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // Get the exception handler address.
+ newpc = EmMemGet32 (regs.vbr + 4 * exception);
+ }
+
+ // Check the exception handler address and jam it into the PC.
+
+ this->CheckNewPC (newpc);
+ m68k_setpc (newpc);
+
+ // Turn tracing off.
+
+ regs.t1 = regs.t0 = regs.m = 0;
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessIllegalInstruction
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::ProcessIllegalInstruction (EmOpcode68K opcode)
+{
+ // This function is loosely based on op_illg in newcpu.c
+
+ // Process an FTrap.
+
+ if ((opcode & 0xF000) == 0xF000)
+ {
+ this->ProcessException (kException_FTrap);
+ }
+
+ // Process an ATrap.
+
+ else if ((opcode & 0xF000) == 0xA000)
+ {
+ this->ProcessException (kException_ATrap);
+ }
+
+ // Process all other opcodes.
+
+ else
+ {
+ this->ProcessException (kException_IllegalInstr);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessJSR
+// ---------------------------------------------------------------------------
+
+int EmCPU68K::ProcessJSR (emuptr oldPC, emuptr dest)
+{
+ int handled = false;
+
+ Hook68KJSRList::iterator iter = fHookJSR.begin ();
+ while (iter != fHookJSR.end ())
+ {
+ if ((*iter) (oldPC, dest))
+ {
+ handled = true;
+ }
+
+ ++iter;
+ }
+
+ return handled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessJSR_Ind
+// ---------------------------------------------------------------------------
+
+int EmCPU68K::ProcessJSR_Ind (emuptr oldPC, emuptr dest)
+{
+ int handled = false;
+
+ Hook68KJSR_IndList::iterator iter = fHookJSR_Ind.begin ();
+ while (iter != fHookJSR_Ind.end ())
+ {
+ if ((*iter) (oldPC, dest))
+ {
+ handled = true;
+ }
+
+ ++iter;
+ }
+
+ return handled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessLINK
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::ProcessLINK (int linkSize)
+{
+ Hook68KLINKList::iterator iter = fHookLINK.begin ();
+ while (iter != fHookLINK.end ())
+ {
+ (*iter) (linkSize);
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessRTE
+// ---------------------------------------------------------------------------
+
+int EmCPU68K::ProcessRTE (emuptr dest)
+{
+ int handled = false;
+
+ Hook68KRTEList::iterator iter = fHookRTE.begin ();
+ while (iter != fHookRTE.end ())
+ {
+ if ((*iter) (dest))
+ {
+ handled = true;
+ }
+
+ ++iter;
+ }
+
+ return handled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::ProcessRTS
+// ---------------------------------------------------------------------------
+
+int EmCPU68K::ProcessRTS (emuptr dest)
+{
+ int handled = false;
+
+ Hook68KRTSList::iterator iter = fHookRTS.begin ();
+ while (iter != fHookRTS.end ())
+ {
+ if ((*iter) (dest))
+ {
+ handled = true;
+ }
+
+ ++iter;
+ }
+
+ return handled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::CheckNewPC
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::CheckNewPC (emuptr dest)
+{
+ Hook68KNewPCList::iterator iter = fHookNewPC.begin ();
+ while (iter != fHookNewPC.end ())
+ {
+ (*iter) (dest);
+
+ ++iter;
+ }
+
+ EmMemory::CheckNewPC (dest);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::CheckNewSP
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::CheckNewSP (EmStackChangeType type)
+{
+ Hook68KNewSPList::iterator iter = fHookNewSP.begin ();
+ while (iter != fHookNewSP.end ())
+ {
+ (*iter) (type);
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::InstallHookException
+// ¥ EmCPU68K::InstallHookJSR
+// ¥ EmCPU68K::InstallHookJSR_Ind
+// ¥ EmCPU68K::InstallHookLINK
+// ¥ EmCPU68K::InstallHookRTE
+// ¥ EmCPU68K::InstallHookRTS
+// ¥ EmCPU68K::InstallHookNewPC
+// ¥ EmCPU68K::InstallHookNewSP
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::InstallHookException (ExceptionNumber exceptionNumber,
+ Hook68KException fn)
+{
+ fExceptionHandlers[exceptionNumber].push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookJSR (Hook68KJSR fn)
+{
+ fHookJSR.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookJSR_Ind (Hook68KJSR_Ind fn)
+{
+ fHookJSR_Ind.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookLINK (Hook68KLINK fn)
+{
+ fHookLINK.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookRTE (Hook68KRTE fn)
+{
+ fHookRTE.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookRTS (Hook68KRTS fn)
+{
+ fHookRTS.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookNewPC (Hook68KNewPC fn)
+{
+ fHookNewPC.push_back (fn);
+}
+
+
+void EmCPU68K::InstallHookNewSP (Hook68KNewSP fn)
+{
+ fHookNewSP.push_back (fn);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::RemoveHookException
+// ¥ EmCPU68K::RemoveHookJSR
+// ¥ EmCPU68K::RemoveHookJSR_Ind
+// ¥ EmCPU68K::RemoveHookLINK
+// ¥ EmCPU68K::RemoveHookRTE
+// ¥ EmCPU68K::RemoveHookRTS
+// ¥ EmCPU68K::RemoveHookNewPC
+// ¥ EmCPU68K::RemoveHookNewSP
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::RemoveHookException (ExceptionNumber exceptionNumber,
+ Hook68KException fn)
+{
+ Hook68KExceptionList::iterator iter = find (
+ fExceptionHandlers[exceptionNumber].begin (),
+ fExceptionHandlers[exceptionNumber].end (),
+ fn);
+
+ if (iter != fExceptionHandlers[exceptionNumber].end ())
+ {
+ fExceptionHandlers[exceptionNumber].erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookJSR (Hook68KJSR fn)
+{
+ Hook68KJSRList::iterator iter = find (fHookJSR.begin (), fHookJSR.end (), fn);
+
+ if (iter != fHookJSR.end ())
+ {
+ fHookJSR.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookJSR_Ind (Hook68KJSR_Ind fn)
+{
+ Hook68KJSR_IndList::iterator iter = find (fHookJSR_Ind.begin (), fHookJSR_Ind.end (), fn);
+
+ if (iter != fHookJSR_Ind.end ())
+ {
+ fHookJSR_Ind.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookLINK (Hook68KLINK fn)
+{
+ Hook68KLINKList::iterator iter = find (fHookLINK.begin (), fHookLINK.end (), fn);
+
+ if (iter != fHookLINK.end ())
+ {
+ fHookLINK.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookRTE (Hook68KRTE fn)
+{
+ Hook68KRTEList::iterator iter = find (fHookRTE.begin (), fHookRTE.end (), fn);
+
+ if (iter != fHookRTE.end ())
+ {
+ fHookRTE.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookRTS (Hook68KRTS fn)
+{
+ Hook68KRTSList::iterator iter = find (fHookRTS.begin (), fHookRTS.end (), fn);
+
+ if (iter != fHookRTS.end ())
+ {
+ fHookRTS.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookNewPC (Hook68KNewPC fn)
+{
+ Hook68KNewPCList::iterator iter = find (fHookNewPC.begin (), fHookNewPC.end (), fn);
+
+ if (iter != fHookNewPC.end ())
+ {
+ fHookNewPC.erase (iter);
+ }
+}
+
+
+void EmCPU68K::RemoveHookNewSP (Hook68KNewSP fn)
+{
+ Hook68KNewSPList::iterator iter = find (fHookNewSP.begin (), fHookNewSP.end (), fn);
+
+ if (iter != fHookNewSP.end ())
+ {
+ fHookNewSP.erase (iter);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::GetRegisters
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::GetRegisters (regstruct& registers)
+{
+ this->UpdateSRFromRegisters ();
+
+ registers = regs;
+ registers.pc = m68k_getpc ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::SetRegisters
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::SetRegisters (regstruct& registers)
+{
+ regs = registers;
+ this->UpdateRegistersFromSR ();
+
+ m68k_setpc (registers.pc);
+
+ this->CheckNewSP (kStackPointerChanged);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::UpdateSRFromRegisters
+// ---------------------------------------------------------------------------
+// Create a 16-bit status register value from the broken out fields. In
+// general, we keep the various fields separate for speed of access. However,
+// there are times when we need the packed 16-bit field.
+//
+// This function is called any time the 16-bit representation of the SR is
+// needed:
+//
+// on EORSR
+// on ORSR
+// on ANDSR
+// on MVSR2
+// on MV2SR
+// on RTR
+// when processing exceptions (EmCPU68K::ProcessException)
+//
+// SystemPacket::GetRegs
+// EmCPU68K::GetRegisters
+
+void EmCPU68K::UpdateSRFromRegisters (void)
+{
+ // (taken from MakeSR in newcpu.c)
+
+ regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
+ | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
+ | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1)
+ | GET_CFLG);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::UpdateRegistersFromSR
+// ---------------------------------------------------------------------------
+// Break out all of the fields from the 16-bit status register into their own
+// separate variables.
+//
+// This function is called any time the SR has been update and needs to be
+// re-expanded:
+//
+// on EORSR
+// on ORSR
+// on ANDSR
+// on MV2SR
+// on STOP
+// on RTE
+// on RTR
+//
+// SystemPacket::SetRegs
+// EmCPU68K::SetRegisters
+
+void EmCPU68K::UpdateRegistersFromSR (void)
+{
+ // (taken from MakeFromSR in newcpu.c)
+
+// int oldm = regs.m;
+ int olds = regs.s;
+
+ regs.t1 = (regs.sr >> 15) & 1;
+ regs.t0 = (regs.sr >> 14) & 1;
+ regs.s = (regs.sr >> 13) & 1;
+ regs.m = (regs.sr >> 12) & 1;
+ regs.intmask = (regs.sr >> 8) & 7;
+
+ SET_XFLG ((regs.sr >> 4) & 1);
+ SET_NFLG ((regs.sr >> 3) & 1);
+ SET_ZFLG ((regs.sr >> 2) & 1);
+ SET_VFLG ((regs.sr >> 1) & 1);
+ SET_CFLG (regs.sr & 1);
+
+ if (olds != regs.s)
+ {
+ if (olds)
+ {
+ regs.isp = m68k_areg(regs, 7);
+ m68k_areg(regs, 7) = regs.usp;
+ }
+ else
+ {
+ regs.usp = m68k_areg(regs, 7);
+ m68k_areg(regs, 7) = regs.isp;
+ }
+ }
+
+ regs.spcflags |= SPCFLAG_INT;
+
+ if (regs.t1 || regs.t0)
+ {
+ regs.spcflags |= SPCFLAG_TRACE;
+ }
+ else
+ {
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::GetCycleCount
+// ---------------------------------------------------------------------------
+
+uint32 EmCPU68K::GetCycleCount (void)
+{
+ return fCycleCount;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::BusError
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::BusError (emuptr address, long size, Bool forRead)
+{
+ gExceptionAddress = address;
+ gExceptionSize = size;
+ gExceptionForRead = forRead;
+
+ this->ProcessException (kException_BusErr);
+
+ EmAssert (false); // Should never get this far.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::AddressError
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::AddressError (emuptr address, long size, Bool forRead)
+{
+ gExceptionAddress = address;
+ gExceptionSize = size;
+ gExceptionForRead = forRead;
+
+ this->ProcessException (kException_AddressErr);
+
+ EmAssert (false); // Should never get this far.
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPU68K::InitializeUAETables
+// ---------------------------------------------------------------------------
+
+void EmCPU68K::InitializeUAETables (void)
+{
+ static int initialized;
+
+ // All of the stuff in this function needs to be done only once;
+ // it doesn't need to be executed every time we create a new CPU.
+
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ // Initialize some CPU-related tables
+ // (This initialization code is taken from init_m68k in newcpu.c)
+
+ int i, j;
+
+ for (i = 0 ; i < 256 ; i++)
+ {
+ for (j = 0 ; j < 8 ; j++)
+ {
+ if (i & (1 << j))
+ {
+ break;
+ }
+ }
+
+ movem_index1[i] = j;
+ movem_index2[i] = 7-j;
+ movem_next[i] = i & (~(1 << j));
+ }
+
+ read_table68k ();
+ do_merges ();
+
+ // The rest of this code is based on build_cpufunctbl in newcpu.c.
+
+ unsigned long opcode;
+ struct cputbl* tbl = op_smalltbl_3;
+
+ for (opcode = 0; opcode < 65536; opcode++)
+ {
+ cpufunctbl[opcode] = op_illg;
+ }
+
+ for (i = 0; tbl[i].handler != NULL; i++)
+ {
+ if (!tbl[i].specific)
+ {
+ cpufunctbl[tbl[i].opcode] = tbl[i].handler;
+#if HAS_PROFILING
+ perftbl[tbl[i].opcode] = tbl[i].perf;
+#endif
+ }
+ }
+
+ for (opcode = 0; opcode < 65536; opcode++)
+ {
+ cpuop_func* f;
+
+ if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > 0)
+ {
+ continue;
+ }
+
+ if (table68k[opcode].handler != -1)
+ {
+ f = cpufunctbl[table68k[opcode].handler];
+ if (f == op_illg)
+ {
+ abort ();
+ }
+
+ cpufunctbl[opcode] = f;
+#if HAS_PROFILING
+ perftbl[opcode] = perftbl[table68k[opcode].handler];
+#endif
+
+ }
+ }
+
+ for (i = 0; tbl[i].handler != NULL; i++)
+ {
+ if (tbl[i].specific)
+ {
+ cpufunctbl[tbl[i].opcode] = tbl[i].handler;
+#if HAS_PROFILING
+ perftbl[tbl[i].opcode] = tbl[i].perf;
+#endif
+ }
+ }
+
+ // (hey readcpu doesn't free this guy!)
+
+ Platform::DisposeMemory (table68k);
+}
diff --git a/SrcShared/Hardware/EmCPU68K.h b/SrcShared/Hardware/EmCPU68K.h
new file mode 100644
index 0000000..1cdfa08
--- /dev/null
+++ b/SrcShared/Hardware/EmCPU68K.h
@@ -0,0 +1,334 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmCPU68K_h
+#define EmCPU68K_h
+
+#include "EmCPU.h" // EmCPU
+
+#include <vector> // vector
+
+#if REGISTER_HISTORY
+#include "UAE.h" // regstruct
+#else
+struct regstruct;
+#endif
+
+const uint16 kATrapReturnTrapNum = 0x0C;
+
+/*---------------------------------------------------------------------
+ * Register numbering for 68K. Each register must have a unique
+ * non-zero register number.
+ *--------------------------------------------------------------------*/
+enum EmCPU68KRegID
+{
+ e68KRegID_Invalid = 0, /* Zero is an invalid register number */
+ e68KRegID_D0 = 1,
+ e68KRegID_D1 = 2,
+ e68KRegID_D2 = 3,
+ e68KRegID_D3 = 4,
+ e68KRegID_D4 = 5,
+ e68KRegID_D5 = 6,
+ e68KRegID_D6 = 7,
+ e68KRegID_D7 = 8,
+ e68KRegID_A0 = 9,
+ e68KRegID_A1 = 10,
+ e68KRegID_A2 = 11,
+ e68KRegID_A3 = 12,
+ e68KRegID_A4 = 13,
+ e68KRegID_A5 = 14,
+ e68KRegID_A6 = 15,
+ e68KRegID_USP = 16,
+ e68KRegID_SSP = 17,
+ e68KRegID_PC = 18,
+ e68KRegID_SR = 19
+};
+
+
+enum ExceptionNumber
+{
+ kException_BusErr = 2, // 08 / 2
+ kException_AddressErr, // 0C / 3
+ kException_IllegalInstr, // 10 / 4
+ kException_DivideByZero, // 14 / 5
+ kException_Chk, // 18 / 6
+ kException_Trap, // 1C / 7
+ kException_Privilege, // 20 / 8
+ kException_Trace, // 24 / 9
+ kException_ATrap, // 28 / A
+ kException_FTrap, // 2C / B
+ kException_Reseved12, // 30 / C
+ kException_Coproc, // 34 / D
+ kException_FormatErr, // 38 / E
+ kException_UninitializedInt, // 3C / F
+
+ kException_Reserved0, // 40-5C / 10-17
+ kException_Reserved1,
+ kException_Reserved2,
+ kException_Reserved3,
+ kException_Reserved4,
+ kException_Reserved5,
+ kException_Reserved6,
+ kException_Reserved7,
+
+ kException_SpuriousInt, // 60 / 18
+ kException_AutoVec1, // 64 / 19
+ kException_AutoVec2, // 68 / 1A
+ kException_AutoVec3, // 6C / 1B
+ kException_AutoVec4, // 70 / 1C
+ kException_AutoVec5, // 74 / 1D
+ kException_AutoVec6, // 78 / 1E
+ kException_AutoVec7, // 7C / 1F
+
+ kException_Trap0, // 80 - BC / 20 - 2F // For soft breakpoints
+ kException_Trap1,
+ kException_Trap2,
+ kException_Trap3,
+ kException_Trap4,
+ kException_Trap5,
+ kException_Trap6,
+ kException_Trap7,
+ kException_Trap8, // For compiled breakpoints
+ kException_Trap9,
+ kException_Trap10,
+ kException_Trap11,
+ kException_Trap12,
+ kException_Trap13, // ATrap returns (emulator convention)
+ kException_Trap14,
+ kException_Trap15, // Trap dispatcher
+
+ kException_Unassigned0, // C0 - FC / 30 - 3F
+ kException_Unassigned1,
+ kException_Unassigned2,
+ kException_Unassigned3,
+ kException_Unassigned4,
+ kException_Unassigned5,
+ kException_Unassigned6,
+ kException_Unassigned7,
+ kException_Unassigned8,
+ kException_Unassigned9,
+ kException_Unassigned10,
+ kException_Unassigned11,
+ kException_Unassigned12,
+ kException_Unassigned13,
+ kException_Unassigned14,
+ kException_Unassigned15,
+
+ kException_LastException,
+
+ kException_SoftBreak = kException_Trap0 + sysDbgBreakpointTrapNum,
+ kException_HardBreak = kException_Trap0 + sysDbgTrapNum,
+ kException_SysCall = kException_Trap0 + sysDispatchTrapNum,
+ kException_ATrapReturn = kException_Trap0 + kATrapReturnTrapNum
+};
+
+/*
+ Grr...this function doesn't appear to be "seen" by VC++. Even in its
+ presence, an expression involving an ExceptionNumber and an int
+ results in the message "error C2440: 'initializing' : cannot convert
+ from 'const int' to 'const enum ExceptionNumber'"
+
+inline ExceptionNumber operator+ (ExceptionNumber left, int right)
+{
+ // NB: cast "left" to an integer, or this routine will recurse!
+ return (ExceptionNumber) ((int) left + right);
+}
+*/
+
+#if EXCEPTION_HISTORY
+
+struct ExceptionHistoryType
+{
+ const char* name;
+ uint32 pc;
+ uint32 sp;
+};
+
+#endif
+
+// Using uint32 instead of uint16 generates slightly better code.
+typedef uint32 EmOpcode68K;
+
+enum EmStackChangeType
+{
+ kStackPointerChanged,
+ kStackPointerIncremented,
+ kStackPointerDecremented,
+ kStackPointerKernelStackHack
+};
+
+class EmCPU68K;
+typedef Bool (*Hook68KException) (ExceptionNumber);
+typedef Bool (*Hook68KJSR) (emuptr oldPC, emuptr dest);
+typedef Bool (*Hook68KJSR_Ind) (emuptr oldPC, emuptr dest);
+typedef void (*Hook68KLINK) (int linkSize);
+typedef Bool (*Hook68KRTE) (emuptr dest);
+typedef Bool (*Hook68KRTS) (emuptr dest);
+typedef void (*Hook68KNewPC) (emuptr dest);
+typedef void (*Hook68KNewSP) (EmStackChangeType);
+
+typedef vector<Hook68KException> Hook68KExceptionList;
+typedef vector<Hook68KJSR> Hook68KJSRList;
+typedef vector<Hook68KJSR_Ind> Hook68KJSR_IndList;
+typedef vector<Hook68KLINK> Hook68KLINKList;
+typedef vector<Hook68KRTE> Hook68KRTEList;
+typedef vector<Hook68KRTS> Hook68KRTSList;
+typedef vector<Hook68KNewPC> Hook68KNewPCList;
+typedef vector<Hook68KNewSP> Hook68KNewSPList;
+
+class EmCPU68K;
+extern EmCPU68K* gCPU68K;
+
+// These variables should strictly be in a sub-system that implements
+// the stack overflow checking, etc. However, for performance reasons,
+// we need to expose them to UAE (see the CHECK_STACK_POINTER_ASSIGNMENT,
+// et al macros), so define them here.
+//
+// Similar comments for the CheckKernelStack function.
+
+extern "C" uint32 gStackHigh;
+extern "C" uint32 gStackLowWarn;
+extern "C" uint32 gStackLow;
+extern "C" uint32 gKernelStackOverflowed;
+
+
+class EmCPU68K : public EmCPU
+{
+ public:
+ // -----------------------------------------------------------------------------
+ // constructor / destructor
+ // -----------------------------------------------------------------------------
+
+ EmCPU68K (EmSession*);
+ virtual ~EmCPU68K (void);
+
+ // -----------------------------------------------------------------------------
+ // public methods
+ // -----------------------------------------------------------------------------
+
+ // Standard sub-system methods:
+ // Reset: Resets the state. Called on hardware resets or on
+ // calls to SysReset. Also called from constructor.
+ // Save: Saves the state to the given file.
+ // Load: Loads the state from the given file. Can assume that
+ // Reset has been called first.
+
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+
+ // Execute the main CPU loop until asked to stop.
+
+ virtual void Execute (void);
+ virtual void CheckAfterCycle (void);
+
+ // Low-level access to CPU state.
+
+ virtual emuptr GetPC (void);
+ virtual emuptr GetSP (void);
+ virtual uint32 GetRegister (int);
+
+ virtual void SetPC (emuptr);
+ virtual void SetSP (emuptr);
+ virtual void SetRegister (int, uint32);
+
+ virtual Bool Stopped (void);
+
+ // Called from routines in EmUAEGlue.cpp
+
+ void ProcessException (ExceptionNumber);
+ void ProcessIllegalInstruction (EmOpcode68K opcode);
+ int ProcessJSR (emuptr oldPC, emuptr dest);
+ int ProcessJSR_Ind (emuptr oldPC, emuptr dest);
+ void ProcessLINK (int linkSize);
+ int ProcessRTE (emuptr dest);
+ int ProcessRTS (emuptr dest);
+ void CheckNewPC (emuptr dest);
+ void CheckNewSP (EmStackChangeType);
+
+ // Called by CPU clients who need to be notified when certain
+ // actions occur.
+
+ void InstallHookException (ExceptionNumber,
+ Hook68KException);
+
+ void InstallHookJSR (Hook68KJSR);
+ void InstallHookJSR_Ind (Hook68KJSR_Ind);
+ void InstallHookLINK (Hook68KLINK);
+ void InstallHookRTS (Hook68KRTE);
+ void InstallHookRTE (Hook68KRTS);
+ void InstallHookNewPC (Hook68KNewPC);
+ void InstallHookNewSP (Hook68KNewSP);
+
+ void RemoveHookException (ExceptionNumber,
+ Hook68KException);
+
+ void RemoveHookJSR (Hook68KJSR);
+ void RemoveHookJSR_Ind (Hook68KJSR_Ind);
+ void RemoveHookLINK (Hook68KLINK);
+ void RemoveHookRTS (Hook68KRTE);
+ void RemoveHookRTE (Hook68KRTS);
+ void RemoveHookNewPC (Hook68KNewPC);
+ void RemoveHookNewSP (Hook68KNewSP);
+
+ // Register management. Clients should call Get/SetRegisters for
+ // the most part. UpdateXFromY are here so that MakeSR and
+ // MakeFromSR (UAE glue functions) can call them.
+
+ void GetRegisters (regstruct& registers);
+ void SetRegisters (regstruct& registers);
+ void UpdateSRFromRegisters (void);
+ void UpdateRegistersFromSR (void);
+
+ uint32 GetCycleCount (void);
+
+ void BusError (emuptr address, long size, Bool forRead);
+ void AddressError (emuptr address, long size, Bool forRead);
+
+ private:
+ Bool ExecuteSpecial (void);
+ Bool ExecuteStoppedLoop (void);
+
+ void CycleSlowly (Bool sleeping);
+ Bool CheckForBreak (void);
+
+ void ProcessInterrupt (int32 interrupt);
+
+ void InitializeUAETables (void);
+
+ private:
+ emuptr fLastTraceAddress;
+ uint32 fCycleCount;
+ Hook68KExceptionList fExceptionHandlers[kException_LastException];
+ Hook68KJSRList fHookJSR;
+ Hook68KJSR_IndList fHookJSR_Ind;
+ Hook68KLINKList fHookLINK;
+ Hook68KRTEList fHookRTE;
+ Hook68KRTSList fHookRTS;
+ Hook68KNewPCList fHookNewPC;
+ Hook68KNewSPList fHookNewSP;
+
+#if REGISTER_HISTORY
+ #define kRegHistorySize 512
+ long fRegHistoryIndex;
+ struct regstruct fRegHistory[kRegHistorySize];
+#endif
+
+#if EXCEPTION_HISTORY
+ #define kExceptionHistorySize 512
+ long fExceptionHistoryIndex;
+ struct ExceptionHistoryType fExceptionHistory[kExceptionHistorySize];
+#endif
+};
+
+#endif // EmCPU68K_h
diff --git a/SrcShared/Hardware/EmCPUARM.cpp b/SrcShared/Hardware/EmCPUARM.cpp
new file mode 100644
index 0000000..3d57510
--- /dev/null
+++ b/SrcShared/Hardware/EmCPUARM.cpp
@@ -0,0 +1,398 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmCPUARM.h"
+
+#include "EmSession.h" // ExecuteSpecial
+
+/*
+ This file interfaces between the Palm OS Emulator and the embedded
+ instance of the ARMulator.
+
+ This version of the ARMulator comes from gdb 5.0, which in turn was
+ derived from the ARM6 ARMulator from ARM, Inc. ARM apparently no
+ longer makes public source-code to their version of ARMulator
+ available, so the version here is probably just a distant cousin
+ of that version.
+
+ The ARMulator here comes with the following files:
+
+ * armcopro.c
+
+ ARM coprocessor emulation
+
+ * armemu.c
+
+ Main ARM processor emulation. It can be compiled for either
+ 26-bit or 32-bit modes.
+
+ * arminit.c
+
+ Contains routines to perform one-time initialization of
+ ARMulator, create an emulator instance, select a processor,
+ reset a processor, run one or more instructions, or trigger
+ an abort.
+
+ * armos.c
+
+ (Something to do with knowledge of an ARM-based OS)
+
+ * armrdi.c
+
+ Implements the ARM RDI (Remote Debugger Interface). All
+ functions are exported via an RDI 1.0 RDIProcVec table
+ (armul_rdi).
+
+ * armsupp.c
+
+ Support routines for common actions like determining addressing
+ modes, reading and writing bytes, reading and writing registers, etc.
+
+ * armvirt.c
+
+ A simple memory emulator that maps in RAM pages on demand.
+
+ * bag.c
+
+ A simple dictionary data structure. Used by kid.c to manage
+ breakpoints. (!!!Why are they managed there and not in armrdi?)
+
+ * communicate.c
+
+ Utility routines to read and write bytes, words, and strings
+ over a socket.
+
+ * gdbhost.c
+
+ Interface routines between gdb and ARMulator. ARMulator calls
+ these functions to invoke gdb console facilities.
+
+ * kid.c
+
+ Infinite loops that listens on a socket for ADP packets. It
+ reads these and invokes the appropriate RDI functions in armrdi.c.
+
+ * main.c
+
+ Front-end application that sits between gdb and ARMulator, intercepting
+ packets and passing them on. (!!! It's not clear to me why this
+ intermediary -- implemented in parent.c -- is required.)
+
+ * parent.c
+
+ Implements the loop that listens for packets from either gdb
+ or ARMulator and forwards them on to the other.
+
+ * thumbemu.c
+
+ Emulator of the Thumb sub-cell. Translates Thumb opcodes into
+ ARM opcodes, and then invokes the ARM opcode emulator.
+
+ * wrapper.c
+
+ ARMulator wrapper that allows it to be incorporated into the gdb
+ Simulator system. This includes implementing functions that
+ respond to the gdb set of remote debugger commands.
+
+ When incorporated into the gdb Simulator system, only the files armcopro.c,
+ armemu.c, arminit.c, armos.c, armsupp.c, armvirt.c, bag.c thumbemu.c, and
+ wrapper.c seem to be used. (!!! Why bag.c, when it's only used by kid.c?)
+*/
+
+#if 0
+
+extern "C"
+{
+#include "armdefs.h"
+#include "armemu.h"
+#include "arm/dbg_rdi.h" // RDIProcVec
+#include "arm/dbg_hif.h" // Dbg_HostosInterface (struct)
+#include "arm/dbg_conf.h" // Dbg_ConfigBlock, Dbg_HostosInterface (typdef)
+}
+
+extern "C"
+{
+
+int stop_simulator; // Referenced in ARMul_Emulate32 loop
+
+int mumkid[2] = {1, 2}; // Referenced in kid.c
+int kidmum[2] = {3, 4}; // Referenced in kid.c, armrdi.c
+
+/* RDI interface */
+extern const struct RDIProcVec armul_rdi;
+
+void ARMul_CheckAfterCycle (void);
+void ARMul_SetSession (void* session);
+
+void EmCPUARM_CheckAfterCycle (void* session)
+{
+ ((EmSession*) session)->ExecuteSpecial (false);
+}
+
+
+/***************************************************************************\
+* Time for the Operating System to initialise itself. *
+\***************************************************************************/
+
+// Referenced in RDI_open in armrdi.c
+
+unsigned
+ARMul_OSInit (ARMul_State * state)
+{
+ return (TRUE);
+}
+
+// Referenced in RDI_close in armrdi.c
+
+void
+ARMul_OSExit (ARMul_State * state)
+{
+}
+
+/***************************************************************************\
+* Return the last Operating System Error. *
+\***************************************************************************/
+
+// Referenced in RDI_info in armrdi.c
+
+ARMword ARMul_OSLastErrorP (ARMul_State * state)
+{
+ return 0;
+}
+
+/***************************************************************************\
+* The emulator calls this routine when a SWI instruction is encuntered. The *
+* parameter passed is the SWI number (lower 24 bits of the instruction). *
+\***************************************************************************/
+
+// Referenced in "case 0x7f" of ARMul_Emulate32 in armemu.c
+// Referenced in "case 0xf0..0xff" of ARMul_Emulate32 in armemu.c
+
+unsigned
+ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
+{
+ return (FALSE);
+}
+
+/***************************************************************************\
+* The emulator calls this routine when an Exception occurs. The second *
+* parameter is the address of the relevant exception vector. Returning *
+* FALSE from this routine causes the trap to be taken, TRUE causes it to *
+* be ignored (so set state->Emulate to FALSE!). *
+\***************************************************************************/
+
+// Referenced in ARMul_Abort in arminit.c
+
+unsigned
+ARMul_OSException (ARMul_State * state, ARMword vector, ARMword pc)
+{
+ return (FALSE);
+}
+
+}
+
+#endif
+
+
+#pragma mark -
+
+EmCPUARM* gCPUARM;
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::EmCPUARM
+// ---------------------------------------------------------------------------
+
+EmCPUARM::EmCPUARM (EmSession* session) :
+ EmCPU (session)
+{
+ this->DoReset (true);
+
+ EmAssert (gCPUARM == NULL);
+ gCPUARM = this;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::~EmCPUARM
+// ---------------------------------------------------------------------------
+
+EmCPUARM::~EmCPUARM (void)
+{
+#if 0
+ /* int i = */ armul_rdi.close ();
+#endif
+
+ EmAssert (gCPUARM == this);
+ gCPUARM = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::Reset
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::Reset (Bool hardwareReset)
+{
+ if (hardwareReset)
+ {
+ this->DoReset (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::Save
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::Load
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::Execute
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::Execute (void)
+{
+#if 0
+ PointHandle point;
+ /* int i = */ armul_rdi.execute (&point);
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::CheckAfterCycle
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::CheckAfterCycle (void)
+{
+#if 0
+ ARMul_CheckAfterCycle ();
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::GetPC
+// ---------------------------------------------------------------------------
+
+emuptr EmCPUARM::GetPC (void)
+{
+ return EmMemNULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::GetSP
+// ---------------------------------------------------------------------------
+
+emuptr EmCPUARM::GetSP (void)
+{
+ return EmMemNULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::GetRegister
+// ---------------------------------------------------------------------------
+
+uint32 EmCPUARM::GetRegister (int /*index*/)
+{
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::SetPC
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::SetPC (emuptr /*newPC*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::SetSP
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::SetSP (emuptr /*newPC*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::SetRegister
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::SetRegister (int /*index*/, uint32 /*val*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::Stopped
+// ---------------------------------------------------------------------------
+// Return whether or not the CPU itself is halted. This is seperate from
+// whether or not the session (that is, the thread emulating the CPU) is
+// halted.
+
+Bool EmCPUARM::Stopped (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCPUARM::DoReset
+// ---------------------------------------------------------------------------
+
+void EmCPUARM::DoReset (Bool /*cold*/)
+{
+#if 0
+ // Taken from RDP_Start in kid.c
+
+ Dbg_ConfigBlock config;
+ config.processor = 0;
+ config.memorysize = 1024 * 1024L;
+ config.bytesex = RDISex_Little;
+
+ Dbg_HostosInterface hostif;
+
+ hostif.dbgprint = NULL; // myprint; // Called in ARMul_DebugPrint, ARMul_DebugPrint_i, which are called only if RDI_VERBOSE is defined.
+ hostif.dbgpause = NULL; // mypause; // Called in ARMul_DebugPause, which in turn is not called.
+ hostif.dbgarg = NULL; // stdout; // Passed to dbgprint and dbgpause.
+ hostif.writec = NULL; // mywritec;// Not called
+ hostif.readc = NULL; // myreadc; // Not called
+ hostif.write = NULL; // mywrite; // Not called
+ hostif.gets = NULL; // mygets; // Not called
+ hostif.hostosarg = NULL; // Not referenced
+ hostif.reset = NULL; // mypause; // Not referenced
+ hostif.resetarg = NULL; // Not referenced
+
+ /* int i = */ armul_rdi.open (cold ? 0 : 1, &config, &hostif, NULL);
+
+ ARMul_SetSession (fSession);
+#endif
+}
diff --git a/SrcShared/Hardware/EmCPUARM.h b/SrcShared/Hardware/EmCPUARM.h
new file mode 100644
index 0000000..73c8304
--- /dev/null
+++ b/SrcShared/Hardware/EmCPUARM.h
@@ -0,0 +1,731 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmCPUARM_h
+#define EmCPUARM_h
+
+#include "EmCPU.h" // EmCPU
+
+/*---------------------------------------------------------------------
+ * ARM Register IDs. All register IDs must be unique even if registers
+ * are in a different group such as FPU registers.
+ *--------------------------------------------------------------------*/
+enum EmCPUARMRegID
+{
+ eARMRegID_Invalid = 0, /* Zero is an invalid register number */
+
+ /*-----------------------------------------------------------
+ // User mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R0 = 1,
+ eARMRegID_R1,
+ eARMRegID_R2,
+ eARMRegID_R3,
+ eARMRegID_R4,
+ eARMRegID_R5,
+ eARMRegID_R6,
+ eARMRegID_R7,
+ eARMRegID_R8,
+ eARMRegID_R9,
+ eARMRegID_R10,
+ eARMRegID_R11,
+ eARMRegID_R12,
+ eARMRegID_SP, eARMRegID_R13 = eARMRegID_SP,
+ eARMRegID_LR, eARMRegID_R14 = eARMRegID_LR,
+ eARMRegID_PC, eARMRegID_R15 = eARMRegID_PC,
+ eARMRegID_CPSR,
+
+ /*-----------------------------------------------------------
+ // FIQ mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R8_fiq,
+ eARMRegID_R9_fiq,
+ eARMRegID_R10_fiq,
+ eARMRegID_R11_fiq,
+ eARMRegID_R12_fiq,
+ eARMRegID_R13_fiq,
+ eARMRegID_R14_fiq,
+ eARMRegID_SPSR_fiq,
+
+ /*-----------------------------------------------------------
+ // IRQ mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R13_irq,
+ eARMRegID_R14_irq,
+ eARMRegID_SPSR_irq,
+
+ /*-----------------------------------------------------------
+ // Supervisor mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R13_svc,
+ eARMRegID_R14_svc,
+ eARMRegID_SPSR_svc,
+
+ /*-----------------------------------------------------------
+ // Abort mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R13_abt,
+ eARMRegID_R14_abt,
+ eARMRegID_SPSR_abt,
+
+
+ /*-----------------------------------------------------------
+ // Undefined mode registers
+ //----------------------------------------------------------*/
+ eARMRegID_R13_und,
+ eARMRegID_R14_und,
+ eARMRegID_SPSR_und,
+
+ /*-----------------------------------------------------------
+ // SB register (static base).
+ //
+ // Any references to R9 can be remapped (in debugger plugin
+ // preferences) to access this SB register which can be
+ // described by an expression in the preferences. The
+ // expression should not contain any references to R9 (since
+ // this will create an infinite loop (since R9 has been
+ // remapped to SB)). Any need for the actual value of R9 in
+ // the SB expression should use the "genreg_gp1" (which means
+ // "General Register Global Pointer 1") opcode which
+ // will actually read R9.
+ //----------------------------------------------------------*/
+ eARMRegID_SB,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 0 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP0_R0,
+ eARMRegID_CP0_R1,
+ eARMRegID_CP0_R2,
+ eARMRegID_CP0_R3,
+ eARMRegID_CP0_R4,
+ eARMRegID_CP0_R5,
+ eARMRegID_CP0_R6,
+ eARMRegID_CP0_R7,
+ eARMRegID_CP0_R8,
+ eARMRegID_CP0_R9,
+ eARMRegID_CP0_R10,
+ eARMRegID_CP0_R11,
+ eARMRegID_CP0_R12,
+ eARMRegID_CP0_R13,
+ eARMRegID_CP0_R14,
+ eARMRegID_CP0_R15,
+ eARMRegID_CP0_R16,
+ eARMRegID_CP0_R17,
+ eARMRegID_CP0_R18,
+ eARMRegID_CP0_R19,
+ eARMRegID_CP0_R20,
+ eARMRegID_CP0_R21,
+ eARMRegID_CP0_R22,
+ eARMRegID_CP0_R23,
+ eARMRegID_CP0_R24,
+ eARMRegID_CP0_R25,
+ eARMRegID_CP0_R26,
+ eARMRegID_CP0_R27,
+ eARMRegID_CP0_R28,
+ eARMRegID_CP0_R29,
+ eARMRegID_CP0_R30,
+ eARMRegID_CP0_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 1 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP1_R0,
+ eARMRegID_CP1_R1,
+ eARMRegID_CP1_R2,
+ eARMRegID_CP1_R3,
+ eARMRegID_CP1_R4,
+ eARMRegID_CP1_R5,
+ eARMRegID_CP1_R6,
+ eARMRegID_CP1_R7,
+ eARMRegID_CP1_R8,
+ eARMRegID_CP1_R9,
+ eARMRegID_CP1_R10,
+ eARMRegID_CP1_R11,
+ eARMRegID_CP1_R12,
+ eARMRegID_CP1_R13,
+ eARMRegID_CP1_R14,
+ eARMRegID_CP1_R15,
+ eARMRegID_CP1_R16,
+ eARMRegID_CP1_R17,
+ eARMRegID_CP1_R18,
+ eARMRegID_CP1_R19,
+ eARMRegID_CP1_R20,
+ eARMRegID_CP1_R21,
+ eARMRegID_CP1_R22,
+ eARMRegID_CP1_R23,
+ eARMRegID_CP1_R24,
+ eARMRegID_CP1_R25,
+ eARMRegID_CP1_R26,
+ eARMRegID_CP1_R27,
+ eARMRegID_CP1_R28,
+ eARMRegID_CP1_R29,
+ eARMRegID_CP1_R30,
+ eARMRegID_CP1_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 2 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP2_R0,
+ eARMRegID_CP2_R1,
+ eARMRegID_CP2_R2,
+ eARMRegID_CP2_R3,
+ eARMRegID_CP2_R4,
+ eARMRegID_CP2_R5,
+ eARMRegID_CP2_R6,
+ eARMRegID_CP2_R7,
+ eARMRegID_CP2_R8,
+ eARMRegID_CP2_R9,
+ eARMRegID_CP2_R10,
+ eARMRegID_CP2_R11,
+ eARMRegID_CP2_R12,
+ eARMRegID_CP2_R13,
+ eARMRegID_CP2_R14,
+ eARMRegID_CP2_R15,
+ eARMRegID_CP2_R16,
+ eARMRegID_CP2_R17,
+ eARMRegID_CP2_R18,
+ eARMRegID_CP2_R19,
+ eARMRegID_CP2_R20,
+ eARMRegID_CP2_R21,
+ eARMRegID_CP2_R22,
+ eARMRegID_CP2_R23,
+ eARMRegID_CP2_R24,
+ eARMRegID_CP2_R25,
+ eARMRegID_CP2_R26,
+ eARMRegID_CP2_R27,
+ eARMRegID_CP2_R28,
+ eARMRegID_CP2_R29,
+ eARMRegID_CP2_R30,
+ eARMRegID_CP2_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 3 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP3_R0,
+ eARMRegID_CP3_R1,
+ eARMRegID_CP3_R2,
+ eARMRegID_CP3_R3,
+ eARMRegID_CP3_R4,
+ eARMRegID_CP3_R5,
+ eARMRegID_CP3_R6,
+ eARMRegID_CP3_R7,
+ eARMRegID_CP3_R8,
+ eARMRegID_CP3_R9,
+ eARMRegID_CP3_R10,
+ eARMRegID_CP3_R11,
+ eARMRegID_CP3_R12,
+ eARMRegID_CP3_R13,
+ eARMRegID_CP3_R14,
+ eARMRegID_CP3_R15,
+ eARMRegID_CP3_R16,
+ eARMRegID_CP3_R17,
+ eARMRegID_CP3_R18,
+ eARMRegID_CP3_R19,
+ eARMRegID_CP3_R20,
+ eARMRegID_CP3_R21,
+ eARMRegID_CP3_R22,
+ eARMRegID_CP3_R23,
+ eARMRegID_CP3_R24,
+ eARMRegID_CP3_R25,
+ eARMRegID_CP3_R26,
+ eARMRegID_CP3_R27,
+ eARMRegID_CP3_R28,
+ eARMRegID_CP3_R29,
+ eARMRegID_CP3_R30,
+ eARMRegID_CP3_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 4 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP4_R0,
+ eARMRegID_CP4_R1,
+ eARMRegID_CP4_R2,
+ eARMRegID_CP4_R3,
+ eARMRegID_CP4_R4,
+ eARMRegID_CP4_R5,
+ eARMRegID_CP4_R6,
+ eARMRegID_CP4_R7,
+ eARMRegID_CP4_R8,
+ eARMRegID_CP4_R9,
+ eARMRegID_CP4_R10,
+ eARMRegID_CP4_R11,
+ eARMRegID_CP4_R12,
+ eARMRegID_CP4_R13,
+ eARMRegID_CP4_R14,
+ eARMRegID_CP4_R15,
+ eARMRegID_CP4_R16,
+ eARMRegID_CP4_R17,
+ eARMRegID_CP4_R18,
+ eARMRegID_CP4_R19,
+ eARMRegID_CP4_R20,
+ eARMRegID_CP4_R21,
+ eARMRegID_CP4_R22,
+ eARMRegID_CP4_R23,
+ eARMRegID_CP4_R24,
+ eARMRegID_CP4_R25,
+ eARMRegID_CP4_R26,
+ eARMRegID_CP4_R27,
+ eARMRegID_CP4_R28,
+ eARMRegID_CP4_R29,
+ eARMRegID_CP4_R30,
+ eARMRegID_CP4_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 5 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP5_R0,
+ eARMRegID_CP5_R1,
+ eARMRegID_CP5_R2,
+ eARMRegID_CP5_R3,
+ eARMRegID_CP5_R4,
+ eARMRegID_CP5_R5,
+ eARMRegID_CP5_R6,
+ eARMRegID_CP5_R7,
+ eARMRegID_CP5_R8,
+ eARMRegID_CP5_R9,
+ eARMRegID_CP5_R10,
+ eARMRegID_CP5_R11,
+ eARMRegID_CP5_R12,
+ eARMRegID_CP5_R13,
+ eARMRegID_CP5_R14,
+ eARMRegID_CP5_R15,
+ eARMRegID_CP5_R16,
+ eARMRegID_CP5_R17,
+ eARMRegID_CP5_R18,
+ eARMRegID_CP5_R19,
+ eARMRegID_CP5_R20,
+ eARMRegID_CP5_R21,
+ eARMRegID_CP5_R22,
+ eARMRegID_CP5_R23,
+ eARMRegID_CP5_R24,
+ eARMRegID_CP5_R25,
+ eARMRegID_CP5_R26,
+ eARMRegID_CP5_R27,
+ eARMRegID_CP5_R28,
+ eARMRegID_CP5_R29,
+ eARMRegID_CP5_R30,
+ eARMRegID_CP5_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 6 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP6_R0,
+ eARMRegID_CP6_R1,
+ eARMRegID_CP6_R2,
+ eARMRegID_CP6_R3,
+ eARMRegID_CP6_R4,
+ eARMRegID_CP6_R5,
+ eARMRegID_CP6_R6,
+ eARMRegID_CP6_R7,
+ eARMRegID_CP6_R8,
+ eARMRegID_CP6_R9,
+ eARMRegID_CP6_R10,
+ eARMRegID_CP6_R11,
+ eARMRegID_CP6_R12,
+ eARMRegID_CP6_R13,
+ eARMRegID_CP6_R14,
+ eARMRegID_CP6_R15,
+ eARMRegID_CP6_R16,
+ eARMRegID_CP6_R17,
+ eARMRegID_CP6_R18,
+ eARMRegID_CP6_R19,
+ eARMRegID_CP6_R20,
+ eARMRegID_CP6_R21,
+ eARMRegID_CP6_R22,
+ eARMRegID_CP6_R23,
+ eARMRegID_CP6_R24,
+ eARMRegID_CP6_R25,
+ eARMRegID_CP6_R26,
+ eARMRegID_CP6_R27,
+ eARMRegID_CP6_R28,
+ eARMRegID_CP6_R29,
+ eARMRegID_CP6_R30,
+ eARMRegID_CP6_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 7 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP7_R0,
+ eARMRegID_CP7_R1,
+ eARMRegID_CP7_R2,
+ eARMRegID_CP7_R3,
+ eARMRegID_CP7_R4,
+ eARMRegID_CP7_R5,
+ eARMRegID_CP7_R6,
+ eARMRegID_CP7_R7,
+ eARMRegID_CP7_R8,
+ eARMRegID_CP7_R9,
+ eARMRegID_CP7_R10,
+ eARMRegID_CP7_R11,
+ eARMRegID_CP7_R12,
+ eARMRegID_CP7_R13,
+ eARMRegID_CP7_R14,
+ eARMRegID_CP7_R15,
+ eARMRegID_CP7_R16,
+ eARMRegID_CP7_R17,
+ eARMRegID_CP7_R18,
+ eARMRegID_CP7_R19,
+ eARMRegID_CP7_R20,
+ eARMRegID_CP7_R21,
+ eARMRegID_CP7_R22,
+ eARMRegID_CP7_R23,
+ eARMRegID_CP7_R24,
+ eARMRegID_CP7_R25,
+ eARMRegID_CP7_R26,
+ eARMRegID_CP7_R27,
+ eARMRegID_CP7_R28,
+ eARMRegID_CP7_R29,
+ eARMRegID_CP7_R30,
+ eARMRegID_CP7_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 8 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP8_R0,
+ eARMRegID_CP8_R1,
+ eARMRegID_CP8_R2,
+ eARMRegID_CP8_R3,
+ eARMRegID_CP8_R4,
+ eARMRegID_CP8_R5,
+ eARMRegID_CP8_R6,
+ eARMRegID_CP8_R7,
+ eARMRegID_CP8_R8,
+ eARMRegID_CP8_R9,
+ eARMRegID_CP8_R10,
+ eARMRegID_CP8_R11,
+ eARMRegID_CP8_R12,
+ eARMRegID_CP8_R13,
+ eARMRegID_CP8_R14,
+ eARMRegID_CP8_R15,
+ eARMRegID_CP8_R16,
+ eARMRegID_CP8_R17,
+ eARMRegID_CP8_R18,
+ eARMRegID_CP8_R19,
+ eARMRegID_CP8_R20,
+ eARMRegID_CP8_R21,
+ eARMRegID_CP8_R22,
+ eARMRegID_CP8_R23,
+ eARMRegID_CP8_R24,
+ eARMRegID_CP8_R25,
+ eARMRegID_CP8_R26,
+ eARMRegID_CP8_R27,
+ eARMRegID_CP8_R28,
+ eARMRegID_CP8_R29,
+ eARMRegID_CP8_R30,
+ eARMRegID_CP8_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 9 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP9_R0,
+ eARMRegID_CP9_R1,
+ eARMRegID_CP9_R2,
+ eARMRegID_CP9_R3,
+ eARMRegID_CP9_R4,
+ eARMRegID_CP9_R5,
+ eARMRegID_CP9_R6,
+ eARMRegID_CP9_R7,
+ eARMRegID_CP9_R8,
+ eARMRegID_CP9_R9,
+ eARMRegID_CP9_R10,
+ eARMRegID_CP9_R11,
+ eARMRegID_CP9_R12,
+ eARMRegID_CP9_R13,
+ eARMRegID_CP9_R14,
+ eARMRegID_CP9_R15,
+ eARMRegID_CP9_R16,
+ eARMRegID_CP9_R17,
+ eARMRegID_CP9_R18,
+ eARMRegID_CP9_R19,
+ eARMRegID_CP9_R20,
+ eARMRegID_CP9_R21,
+ eARMRegID_CP9_R22,
+ eARMRegID_CP9_R23,
+ eARMRegID_CP9_R24,
+ eARMRegID_CP9_R25,
+ eARMRegID_CP9_R26,
+ eARMRegID_CP9_R27,
+ eARMRegID_CP9_R28,
+ eARMRegID_CP9_R29,
+ eARMRegID_CP9_R30,
+ eARMRegID_CP9_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 10 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP10_R0,
+ eARMRegID_CP10_R1,
+ eARMRegID_CP10_R2,
+ eARMRegID_CP10_R3,
+ eARMRegID_CP10_R4,
+ eARMRegID_CP10_R5,
+ eARMRegID_CP10_R6,
+ eARMRegID_CP10_R7,
+ eARMRegID_CP10_R8,
+ eARMRegID_CP10_R9,
+ eARMRegID_CP10_R10,
+ eARMRegID_CP10_R11,
+ eARMRegID_CP10_R12,
+ eARMRegID_CP10_R13,
+ eARMRegID_CP10_R14,
+ eARMRegID_CP10_R15,
+ eARMRegID_CP10_R16,
+ eARMRegID_CP10_R17,
+ eARMRegID_CP10_R18,
+ eARMRegID_CP10_R19,
+ eARMRegID_CP10_R20,
+ eARMRegID_CP10_R21,
+ eARMRegID_CP10_R22,
+ eARMRegID_CP10_R23,
+ eARMRegID_CP10_R24,
+ eARMRegID_CP10_R25,
+ eARMRegID_CP10_R26,
+ eARMRegID_CP10_R27,
+ eARMRegID_CP10_R28,
+ eARMRegID_CP10_R29,
+ eARMRegID_CP10_R30,
+ eARMRegID_CP10_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 11 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP11_R0,
+ eARMRegID_CP11_R1,
+ eARMRegID_CP11_R2,
+ eARMRegID_CP11_R3,
+ eARMRegID_CP11_R4,
+ eARMRegID_CP11_R5,
+ eARMRegID_CP11_R6,
+ eARMRegID_CP11_R7,
+ eARMRegID_CP11_R8,
+ eARMRegID_CP11_R9,
+ eARMRegID_CP11_R10,
+ eARMRegID_CP11_R11,
+ eARMRegID_CP11_R12,
+ eARMRegID_CP11_R13,
+ eARMRegID_CP11_R14,
+ eARMRegID_CP11_R15,
+ eARMRegID_CP11_R16,
+ eARMRegID_CP11_R17,
+ eARMRegID_CP11_R18,
+ eARMRegID_CP11_R19,
+ eARMRegID_CP11_R20,
+ eARMRegID_CP11_R21,
+ eARMRegID_CP11_R22,
+ eARMRegID_CP11_R23,
+ eARMRegID_CP11_R24,
+ eARMRegID_CP11_R25,
+ eARMRegID_CP11_R26,
+ eARMRegID_CP11_R27,
+ eARMRegID_CP11_R28,
+ eARMRegID_CP11_R29,
+ eARMRegID_CP11_R30,
+ eARMRegID_CP11_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 12 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP12_R0,
+ eARMRegID_CP12_R1,
+ eARMRegID_CP12_R2,
+ eARMRegID_CP12_R3,
+ eARMRegID_CP12_R4,
+ eARMRegID_CP12_R5,
+ eARMRegID_CP12_R6,
+ eARMRegID_CP12_R7,
+ eARMRegID_CP12_R8,
+ eARMRegID_CP12_R9,
+ eARMRegID_CP12_R10,
+ eARMRegID_CP12_R11,
+ eARMRegID_CP12_R12,
+ eARMRegID_CP12_R13,
+ eARMRegID_CP12_R14,
+ eARMRegID_CP12_R15,
+ eARMRegID_CP12_R16,
+ eARMRegID_CP12_R17,
+ eARMRegID_CP12_R18,
+ eARMRegID_CP12_R19,
+ eARMRegID_CP12_R20,
+ eARMRegID_CP12_R21,
+ eARMRegID_CP12_R22,
+ eARMRegID_CP12_R23,
+ eARMRegID_CP12_R24,
+ eARMRegID_CP12_R25,
+ eARMRegID_CP12_R26,
+ eARMRegID_CP12_R27,
+ eARMRegID_CP12_R28,
+ eARMRegID_CP12_R29,
+ eARMRegID_CP12_R30,
+ eARMRegID_CP12_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 13 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP13_R0,
+ eARMRegID_CP13_R1,
+ eARMRegID_CP13_R2,
+ eARMRegID_CP13_R3,
+ eARMRegID_CP13_R4,
+ eARMRegID_CP13_R5,
+ eARMRegID_CP13_R6,
+ eARMRegID_CP13_R7,
+ eARMRegID_CP13_R8,
+ eARMRegID_CP13_R9,
+ eARMRegID_CP13_R10,
+ eARMRegID_CP13_R11,
+ eARMRegID_CP13_R12,
+ eARMRegID_CP13_R13,
+ eARMRegID_CP13_R14,
+ eARMRegID_CP13_R15,
+ eARMRegID_CP13_R16,
+ eARMRegID_CP13_R17,
+ eARMRegID_CP13_R18,
+ eARMRegID_CP13_R19,
+ eARMRegID_CP13_R20,
+ eARMRegID_CP13_R21,
+ eARMRegID_CP13_R22,
+ eARMRegID_CP13_R23,
+ eARMRegID_CP13_R24,
+ eARMRegID_CP13_R25,
+ eARMRegID_CP13_R26,
+ eARMRegID_CP13_R27,
+ eARMRegID_CP13_R28,
+ eARMRegID_CP13_R29,
+ eARMRegID_CP13_R30,
+ eARMRegID_CP13_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 14 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP14_R0,
+ eARMRegID_CP14_R1,
+ eARMRegID_CP14_R2,
+ eARMRegID_CP14_R3,
+ eARMRegID_CP14_R4,
+ eARMRegID_CP14_R5,
+ eARMRegID_CP14_R6,
+ eARMRegID_CP14_R7,
+ eARMRegID_CP14_R8,
+ eARMRegID_CP14_R9,
+ eARMRegID_CP14_R10,
+ eARMRegID_CP14_R11,
+ eARMRegID_CP14_R12,
+ eARMRegID_CP14_R13,
+ eARMRegID_CP14_R14,
+ eARMRegID_CP14_R15,
+ eARMRegID_CP14_R16,
+ eARMRegID_CP14_R17,
+ eARMRegID_CP14_R18,
+ eARMRegID_CP14_R19,
+ eARMRegID_CP14_R20,
+ eARMRegID_CP14_R21,
+ eARMRegID_CP14_R22,
+ eARMRegID_CP14_R23,
+ eARMRegID_CP14_R24,
+ eARMRegID_CP14_R25,
+ eARMRegID_CP14_R26,
+ eARMRegID_CP14_R27,
+ eARMRegID_CP14_R28,
+ eARMRegID_CP14_R29,
+ eARMRegID_CP14_R30,
+ eARMRegID_CP14_R31,
+
+ /*-----------------------------------------------------------
+ // Coprocessor 15 registers
+ //----------------------------------------------------------*/
+ eARMRegID_CP15_R0,
+ eARMRegID_CP15_R1,
+ eARMRegID_CP15_R2,
+ eARMRegID_CP15_R3,
+ eARMRegID_CP15_R4,
+ eARMRegID_CP15_R5,
+ eARMRegID_CP15_R6,
+ eARMRegID_CP15_R7,
+ eARMRegID_CP15_R8,
+ eARMRegID_CP15_R9,
+ eARMRegID_CP15_R10,
+ eARMRegID_CP15_R11,
+ eARMRegID_CP15_R12,
+ eARMRegID_CP15_R13,
+ eARMRegID_CP15_R14,
+ eARMRegID_CP15_R15,
+ eARMRegID_CP15_R16,
+ eARMRegID_CP15_R17,
+ eARMRegID_CP15_R18,
+ eARMRegID_CP15_R19,
+ eARMRegID_CP15_R20,
+ eARMRegID_CP15_R21,
+ eARMRegID_CP15_R22,
+ eARMRegID_CP15_R23,
+ eARMRegID_CP15_R24,
+ eARMRegID_CP15_R25,
+ eARMRegID_CP15_R26,
+ eARMRegID_CP15_R27,
+ eARMRegID_CP15_R28,
+ eARMRegID_CP15_R29,
+ eARMRegID_CP15_R30,
+ eARMRegID_CP15_R31
+};
+
+
+class EmCPUARM;
+extern EmCPUARM* gCPUARM;
+
+class EmCPUARM : public EmCPU
+{
+ public:
+ // -----------------------------------------------------------------------------
+ // constructor / destructor
+ // -----------------------------------------------------------------------------
+
+ EmCPUARM (EmSession*);
+ virtual ~EmCPUARM (void);
+
+ // -----------------------------------------------------------------------------
+ // public methods
+ // -----------------------------------------------------------------------------
+
+ // Standard sub-system methods:
+ // Reset: Resets the state. Called on hardware resets or on
+ // calls to SysReset. Also called from constructor.
+ // Save: Saves the state to the given file.
+ // Load: Loads the state from the given file. Can assume that
+ // Reset has been called first.
+
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+
+ // Execute the main CPU loop until asked to stop.
+
+ virtual void Execute (void);
+ virtual void CheckAfterCycle (void);
+
+ // Low-level access to CPU state.
+
+ virtual emuptr GetPC (void);
+ virtual emuptr GetSP (void);
+ virtual uint32 GetRegister (int);
+
+ virtual void SetPC (emuptr);
+ virtual void SetSP (emuptr);
+ virtual void SetRegister (int, uint32);
+
+ virtual Bool Stopped (void);
+
+ private:
+ void DoReset (Bool cold);
+};
+
+#endif // EmCPUARM_h
diff --git a/SrcShared/Hardware/EmHAL.cpp b/SrcShared/Hardware/EmHAL.cpp
new file mode 100644
index 0000000..a4b0030
--- /dev/null
+++ b/SrcShared/Hardware/EmHAL.cpp
@@ -0,0 +1,939 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmHAL.h"
+
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "ErrorHandling.h" // Errors::ReportErrCommPort
+#include "PreferenceMgr.h" // gEmuPrefs
+
+#include "Logging.h"
+
+
+EmHALHandler* EmHAL::fgRootHandler;
+
+#define PRINTF if (!0) ; else LogAppendMsg
+
+static void PrvHandlePortOpenErrors (ErrCode err, string errString);
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::AddHandler
+// ---------------------------------------------------------------------------
+
+void EmHAL::AddHandler (EmHALHandler* handler)
+{
+ EmAssert (handler->fNextHandler == NULL);
+ EmAssert (handler->fPrevHandler == NULL);
+ EmAssert (fgRootHandler == NULL || fgRootHandler->fPrevHandler == NULL);
+
+ if (fgRootHandler != NULL)
+ {
+ fgRootHandler->fPrevHandler = handler;
+ handler->fNextHandler = fgRootHandler;
+ }
+
+ fgRootHandler = handler;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::RemoveHandler
+// ---------------------------------------------------------------------------
+
+void EmHAL::RemoveHandler (EmHALHandler* handler)
+{
+ if (handler->fNextHandler)
+ {
+ handler->fNextHandler->fPrevHandler = handler->fPrevHandler;
+ }
+
+ if (handler->fPrevHandler)
+ {
+ handler->fPrevHandler->fNextHandler = handler->fNextHandler;
+ }
+ else
+ {
+ fgRootHandler = handler->fNextHandler;
+ }
+
+ handler->fNextHandler = NULL;
+ handler->fPrevHandler = NULL;
+
+ EmAssert (handler->fNextHandler == NULL);
+ EmAssert (handler->fPrevHandler == NULL);
+ EmAssert (fgRootHandler == NULL || fgRootHandler->fPrevHandler == NULL);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::RemoveHandler
+// ---------------------------------------------------------------------------
+
+void EmHAL::EnsureCoverage (void)
+{
+#if 0
+ // Rats...can't get this work...
+
+ Bool isHandled[20];
+ EmHALHandler* thisHandler = fgRootHandler;
+ EmHALHandler baseHandler;
+
+ while (thisHandler)
+ {
+ typedef void (EmHALHandler::*CycleHandler)(Bool);
+ CycleHandler p1 = (thisHandler->Cycle);
+ CycleHandler p2 = (baseHandler.Cycle);
+
+ if (p1 != p2)
+ {
+ isHandled[0] = true;
+ }
+
+ thisHandler = thisHandler->fNextHandler;
+ }
+
+ for (int ii = 0; ii < sizeof (isHandled); ++ii)
+ {
+ EmAssert (isHandled[ii]);
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::Cycle
+// ---------------------------------------------------------------------------
+
+#if 0 // It's inline
+void EmHAL::Cycle (Bool sleeping)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->Cycle (sleeping);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::CycleSlowly
+// ---------------------------------------------------------------------------
+
+void EmHAL::CycleSlowly (Bool sleeping)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->CycleSlowly (sleeping);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::ButtonEvent
+// ---------------------------------------------------------------------------
+
+void EmHAL::ButtonEvent (SkinElementType button, Bool buttonIsDown)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->ButtonEvent (button, buttonIsDown);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::TurnSoundOff
+// ---------------------------------------------------------------------------
+
+void EmHAL::TurnSoundOff (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->TurnSoundOff ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::ResetTimer
+// ---------------------------------------------------------------------------
+
+void EmHAL::ResetTimer (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->ResetTimer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::ResetRTC
+// ---------------------------------------------------------------------------
+
+void EmHAL::ResetRTC (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->ResetRTC ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmHAL::GetInterruptLevel (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetInterruptLevel ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetInterruptBase
+// ---------------------------------------------------------------------------
+
+int32 EmHAL::GetInterruptBase (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetInterruptBase ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+// Called in various portXDataWrite methods to determine if Screen::InvalidateAll
+// needs to be called. Typically implemented in the EmRegs<Product> or
+// EmRegs<LCDDriver> subclass.
+
+Bool EmHAL::GetLCDScreenOn (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetLCDScreenOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+// Called in various portXDataWrite methods to determine if Screen::InvalidateAll
+// needs to be called. Typically implemented in the EmRegs<Product> or
+// EmRegs<LCDDriver> subclass.
+
+Bool EmHAL::GetLCDBacklightOn (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetLCDBacklightOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+// Called by host LCD code to know if it needs to draw a 2-pixel white frame.
+// Typically implemented in the EmRegs<Processor> or EmRegs<LCDDriver> subclass.
+
+Bool EmHAL::GetLCDHasFrame (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetLCDHasFrame ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+// Called by Screen class in order to mark the memory used for the framebuffer.
+// Typically implemented in the EmRegs<Processor> or EmRegs<LCDDriver> subclass.
+
+void EmHAL::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->GetLCDBeginEnd (begin, end);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLCDScanlines
+// ---------------------------------------------------------------------------
+// Fill in the output fields of EmScreenUpdateInfo. Typically implemented in
+// the EmRegs<Processor> or EmRegs<LCDDriver> subclass.
+
+void EmHAL::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->GetLCDScanlines (info);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetDynamicHeapSize
+// ---------------------------------------------------------------------------
+
+int32 EmHAL::GetDynamicHeapSize (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetDynamicHeapSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmHAL::GetROMSize (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetROMSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetROMBaseAddress
+// ---------------------------------------------------------------------------
+
+emuptr EmHAL::GetROMBaseAddress (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetROMBaseAddress ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::ChipSelectsConfigured
+// ---------------------------------------------------------------------------
+
+Bool EmHAL::ChipSelectsConfigured (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->ChipSelectsConfigured ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetSystemClockFrequency
+// ---------------------------------------------------------------------------
+
+int32 EmHAL::GetSystemClockFrequency (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetSystemClockFrequency ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetCanStop
+// ---------------------------------------------------------------------------
+
+Bool EmHAL::GetCanStop (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetCanStop ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetAsleep
+// ---------------------------------------------------------------------------
+
+Bool EmHAL::GetAsleep (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetAsleep ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetPortInputValue
+// ---------------------------------------------------------------------------
+
+uint8 EmHAL::GetPortInputValue (int port)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetPortInputValue (port);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetPortInternalValue
+// ---------------------------------------------------------------------------
+
+uint8 EmHAL::GetPortInternalValue (int port)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetPortInternalValue (port);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::PortDataChanged
+// ---------------------------------------------------------------------------
+
+void EmHAL::PortDataChanged (int port, uint8 oldVal, uint8 newVal)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->PortDataChanged (port, oldVal, newVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmHAL::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->GetKeyInfo (numRows, numCols, keyMap, rows);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::LineDriverChanged
+// ---------------------------------------------------------------------------
+// Open or close the transports in response to their line drivers being
+// enabled or disabled.
+
+void EmHAL::LineDriverChanged (EmUARTDeviceType type)
+{
+ ErrCode err = errNone;
+ EmTransport* transport = gEmuPrefs->GetTransportForDevice (type);
+
+ if (transport)
+ {
+ if (EmHAL::GetLineDriverState (type))
+ {
+ err = transport->Open ();
+ }
+ else
+ {
+ /* err = */ transport->Close ();
+ }
+
+ if (err != errNone)
+ {
+ string errString (transport->GetSpecificName ());
+ ::PrvHandlePortOpenErrors (err, errString);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmHAL::GetLineDriverState (EmUARTDeviceType type)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetLineDriverState (type);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmHAL::GetUARTDevice (int uartNum)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetUARTDevice (uartNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLineDriverStates
+// ---------------------------------------------------------------------------
+// Collect all the states of all the driver types we know about. Pass in to
+// this routine a variable of type Bool[kUARTEnd].
+
+void EmHAL::GetLineDriverStates (Bool* states)
+{
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ states[ii] = EmHAL::GetLineDriverState (ii);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::CompareLineDriverStates
+// ---------------------------------------------------------------------------
+// Collect the current state of all the line drivers, and compare them to
+// a previously-saved snapshot. For any differences, call LineDriverChanged.
+
+void EmHAL::CompareLineDriverStates (const Bool* oldStates)
+{
+ Bool newStates[kUARTEnd];
+ EmHAL::GetLineDriverStates (newStates);
+
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ if (newStates[ii] != oldStates[ii])
+ {
+ EmHAL::LineDriverChanged (ii);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetDTR
+// ---------------------------------------------------------------------------
+// DTR is "Data Terminal Ready". In the same way that the RTS signal is
+// typically hooked up to the external device's CTS signal, our DTR pin is
+// hooked up to the external device's DSR pin. It can be modified in order
+// to tell the external device if we can accept any data.
+
+Bool EmHAL::GetDTR (int uartNum)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetDTR (uartNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::DTRChanged
+// ---------------------------------------------------------------------------
+// Called when the Palm OS changes the setting of the DTR pin. We respond
+// to this change by reflecting the setting in the host's DTR pin.
+
+void EmHAL::DTRChanged (int uartNum)
+{
+ EmUARTDeviceType type = EmHAL::GetUARTDevice (uartNum);
+ EmTransport* transport = gEmuPrefs->GetTransportForDevice (type);
+ EmTransportSerial* serTransport = dynamic_cast<EmTransportSerial*> (transport);
+
+ if (serTransport)
+ {
+ Bool state = EmHAL::GetDTR (uartNum);
+ PRINTF ("EmHAL::DTRChanged: DTR changed in emulated port to %d.", (int) state);
+ serTransport->SetDTR (state);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetVibrateOn
+// ---------------------------------------------------------------------------
+
+Bool EmHAL::GetVibrateOn (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetVibrateOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHAL::GetLEDState
+// ---------------------------------------------------------------------------
+
+uint16 EmHAL::GetLEDState (void)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ return EmHAL::GetRootHandler()->GetLEDState ();
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::EmHALHandler
+// ---------------------------------------------------------------------------
+
+EmHALHandler::EmHALHandler (void) :
+ fNextHandler (NULL),
+ fPrevHandler (NULL)
+{
+ EmHAL::AddHandler (this);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::~EmHALHandler
+// ---------------------------------------------------------------------------
+
+EmHALHandler::~EmHALHandler (void)
+{
+ EmHAL::RemoveHandler (this);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::Cycle
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::Cycle (Bool sleeping)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->Cycle (sleeping);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::CycleSlowly
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::CycleSlowly (Bool sleeping)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->CycleSlowly (sleeping);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::ButtonEvent
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::ButtonEvent (SkinElementType button, Bool buttonIsDown)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->ButtonEvent (button, buttonIsDown);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::TurnSoundOff
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::TurnSoundOff (void)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->TurnSoundOff ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::ResetTimer
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::ResetTimer (void)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->ResetTimer ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::ResetRTC
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::ResetRTC (void)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->ResetRTC ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmHALHandler::GetInterruptLevel (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetInterruptLevel ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetInterruptBase
+// ---------------------------------------------------------------------------
+
+int32 EmHALHandler::GetInterruptBase (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetInterruptBase ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetLCDScreenOn (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetLCDScreenOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetLCDBacklightOn (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetLCDBacklightOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetLCDHasFrame (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetLCDHasFrame ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->GetLCDBeginEnd (begin, end);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->GetLCDScanlines (info);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetDynamicHeapSize
+// ---------------------------------------------------------------------------
+
+int32 EmHALHandler::GetDynamicHeapSize (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetDynamicHeapSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmHALHandler::GetROMSize (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetROMSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetROMBaseAddress
+// ---------------------------------------------------------------------------
+
+emuptr EmHALHandler::GetROMBaseAddress (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetROMBaseAddress ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::ChipSelectsConfigured
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::ChipSelectsConfigured (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->ChipSelectsConfigured ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetSystemClockFrequency
+// ---------------------------------------------------------------------------
+
+int32 EmHALHandler::GetSystemClockFrequency (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetSystemClockFrequency ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetCanStop
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetCanStop (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetCanStop ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetAsleep
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetAsleep (void)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetAsleep ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetPortInputValue
+// ---------------------------------------------------------------------------
+
+uint8 EmHALHandler::GetPortInputValue (int port)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetPortInputValue (port);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetPortInternalValue
+// ---------------------------------------------------------------------------
+
+uint8 EmHALHandler::GetPortInternalValue (int port)
+{
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetPortInternalValue (port);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::PortDataChanged
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::PortDataChanged (int port, uint8 oldVal, uint8 newVal)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->PortDataChanged (port, oldVal, newVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmHALHandler::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ EmAssert (this->GetNextHandler());
+ this->GetNextHandler()->GetKeyInfo (numRows, numCols, keyMap, rows);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmHALHandler::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (EmHALHandler::GetNextHandler())
+ {
+ return EmHALHandler::GetNextHandler()->GetLineDriverState (type);
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmHALHandler::GetUARTDevice (int uartNum)
+{
+ if (EmHALHandler::GetNextHandler())
+ {
+ return EmHALHandler::GetNextHandler()->GetUARTDevice (uartNum);
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetDTR
+// ---------------------------------------------------------------------------
+// DTR is "Data Terminal Ready". In the same way that the RTS signal is
+// typically hooked up to the external device's CTS signal, our DTR pin is
+// hooked up to the external device's DSR pin. It can be modified in order
+// to tell the external device if we can accept any data.
+
+Bool EmHALHandler::GetDTR (int uartNum)
+{
+ if (EmHALHandler::GetNextHandler())
+ {
+ return EmHALHandler::GetNextHandler()->GetDTR (uartNum);
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetVibrateOn
+// ---------------------------------------------------------------------------
+
+Bool EmHALHandler::GetVibrateOn (void)
+{
+ if (!this->GetNextHandler())
+ return false;
+
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetVibrateOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmHALHandler::GetLEDState
+// ---------------------------------------------------------------------------
+
+uint16 EmHALHandler::GetLEDState (void)
+{
+ if (!this->GetNextHandler())
+ return 0;
+
+ EmAssert (this->GetNextHandler());
+ return this->GetNextHandler()->GetLEDState ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandlePortOpenErrors
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing, but displays one of two warnings if its cases
+ * are tripped.
+ *
+ ***********************************************************************/
+
+void PrvHandlePortOpenErrors (ErrCode err, string errString)
+{
+ switch (err)
+ {
+ // access denied, comm port, on Win32
+ case 5:
+ Errors::ReportErrCommPort (errString);
+ break;
+
+ // comm port error on Mac
+ case -97:
+ Errors::ReportErrCommPort (errString);
+ break;
+ }
+}
diff --git a/SrcShared/Hardware/EmHAL.h b/SrcShared/Hardware/EmHAL.h
new file mode 100644
index 0000000..4f01752
--- /dev/null
+++ b/SrcShared/Hardware/EmHAL.h
@@ -0,0 +1,164 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmHAL_h
+#define EmHAL_h
+
+#include "Skins.h" // SkinElementType
+
+class EmHAL;
+class EmPixMap;
+class EmScreenUpdateInfo;
+
+enum
+{
+ kLEDOff = 0x00,
+ kLEDGreen = 0x01,
+ kLEDRed = 0x02
+};
+
+enum EmUARTDeviceType
+{
+ kUARTBegin = 0,
+
+ kUARTSerial = kUARTBegin,
+ kUARTIR,
+ kUARTBluetooth,
+ kUARTMystery,
+ kUARTNone,
+
+ kUARTEnd
+};
+
+DEFINE_SCALAR_MODIFIERS (EmUARTDeviceType)
+
+class EmHALHandler
+{
+ public:
+ EmHALHandler (void);
+ virtual ~EmHALHandler (void);
+
+ virtual void Cycle (Bool sleeping);
+ virtual void CycleSlowly (Bool sleeping);
+
+ virtual void ButtonEvent (SkinElementType, Bool buttonIsDown);
+ virtual void TurnSoundOff (void);
+ virtual void ResetTimer (void);
+ virtual void ResetRTC (void);
+
+ virtual int32 GetInterruptLevel (void);
+ virtual int32 GetInterruptBase (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr&, emuptr&);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ virtual int32 GetDynamicHeapSize (void);
+ virtual int32 GetROMSize (void);
+ virtual emuptr GetROMBaseAddress (void);
+ virtual Bool ChipSelectsConfigured (void);
+ virtual int32 GetSystemClockFrequency (void);
+ virtual Bool GetCanStop (void);
+ virtual Bool GetAsleep (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void PortDataChanged (int, uint8, uint8);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ virtual Bool GetLineDriverState (EmUARTDeviceType);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ virtual Bool GetDTR (int uartNum);
+
+ virtual Bool GetVibrateOn (void);
+ virtual uint16 GetLEDState (void);
+
+ protected:
+ EmHALHandler* GetNextHandler (void) { return fNextHandler; }
+
+ private:
+ EmHALHandler* fNextHandler;
+ EmHALHandler* fPrevHandler;
+
+ friend class EmHAL;
+};
+
+
+class EmHAL
+{
+ public:
+ static void AddHandler (EmHALHandler*);
+ static void RemoveHandler (EmHALHandler*);
+ static void EnsureCoverage (void);
+
+ static void Cycle (Bool sleeping);
+ static void CycleSlowly (Bool sleeping);
+
+ static void ButtonEvent (SkinElementType, Bool buttonIsDown);
+ static void TurnSoundOff (void);
+ static void ResetTimer (void);
+ static void ResetRTC (void);
+
+ static int32 GetInterruptLevel (void);
+ static int32 GetInterruptBase (void);
+
+ static Bool GetLCDScreenOn (void);
+ static Bool GetLCDBacklightOn (void);
+ static Bool GetLCDHasFrame (void);
+ static void GetLCDBeginEnd (emuptr&, emuptr&);
+ static void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ static int32 GetDynamicHeapSize (void);
+ static int32 GetROMSize (void);
+ static emuptr GetROMBaseAddress (void);
+ static Bool ChipSelectsConfigured (void);
+ static int32 GetSystemClockFrequency (void);
+ static Bool GetCanStop (void);
+ static Bool GetAsleep (void);
+
+ static uint8 GetPortInputValue (int);
+ static uint8 GetPortInternalValue (int);
+ static void PortDataChanged (int, uint8, uint8);
+ static void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ static void LineDriverChanged (EmUARTDeviceType);
+ static Bool GetLineDriverState (EmUARTDeviceType);
+ static EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ static void GetLineDriverStates (Bool* states);
+ static void CompareLineDriverStates (const Bool* oldStates);
+
+ static Bool GetDTR (int uartNum);
+ static void DTRChanged (int uartNum);
+
+ static Bool GetVibrateOn (void);
+ static uint16 GetLEDState (void);
+
+ private:
+ static EmHALHandler* GetRootHandler (void) { return fgRootHandler; }
+ static EmHALHandler* fgRootHandler;
+};
+
+inline void EmHAL::Cycle (Bool sleeping)
+{
+ EmAssert (EmHAL::GetRootHandler());
+ EmHAL::GetRootHandler()->Cycle (sleeping);
+}
+
+
+#endif /* EmHAL_h */
diff --git a/SrcShared/Hardware/EmMemory.cpp b/SrcShared/Hardware/EmMemory.cpp
new file mode 100644
index 0000000..90051ac
--- /dev/null
+++ b/SrcShared/Hardware/EmMemory.cpp
@@ -0,0 +1,1342 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmMemory.h"
+
+#include "EmBankDRAM.h" // EmBankDRAM::Initialize
+#include "EmBankDummy.h" // EmBankDummy::Initialize
+#include "EmBankMapped.h" // EmBankMapped::Initialize
+#include "EmBankRegs.h" // EmBankRegs::Initialize
+#include "EmBankROM.h" // EmBankROM::Initialize
+#include "EmBankSRAM.h" // EmBankSRAM::Initialize
+#include "EmSession.h" // gSession, GetDevice
+#include "MetaMemory.h" // MetaMemory::Initialize
+
+
+#if HAS_PROFILING
+#include "Profiling.h" // gProfilingCounted
+#endif
+
+
+/*
+ Hitchhiker's Guide To Accessing Memory
+
+ When emulating CPU instructions, all memory access must be emulated as
+ well. Additionally, the memory location that the emulated instruction
+ is accessing is not necessarily the same as the memory location in the
+ emulator's address space. That is, memory location 0x00001234 in the
+ emulated process's address space is not the same as memory location
+ 0x00001234 in the emulator's address space. Instead, the emulated
+ 0x00001234 is actually 0x00001234 bytes into some buffer that we've
+ allocate for the purpose of holding the emulated address space's contents.
+
+ There are several ranges of Palm OS memory that we need to emulate:
+
+ - Low-memory RAM (for the dynamic heap)
+ - High-memory RAM (for the storage heap)
+ - ROM
+ - Dragonball and other memory-mapped registers
+ - Everything else
+
+ Each of these ranges (except for the last one) is managed by a set of
+ functions for reading from and writing to that memory and a chunk of
+ memory that we allocate as a "backing store" for that memory.
+
+ Thus, for each of these ranges, we need to quickly determine what set of
+ functions need to be called. The method for doing this is to divide the
+ entire 4GB address space into 64K banks, each 64K long.
+
+ Each 64K bank is managed by a set of functions. These functions handle
+ reading from and writing to that 64K bank, handling 1-byte, 2-byte, and
+ 4-byte accesses. They also manage mapping from the emulated addres space
+ to the physical space as viewed by the emulator, and validate memory
+ addresses.
+
+ Because there are 64K of these 64K banks, the functions that manage each
+ bank are stored in an array of 64K elements. When we need to invoke a
+ function for a particular bank, the upper word of the prospective memory
+ address is used as a "bank index" into this array. From that, the right
+ set of functions is found, and the desired function from that set of
+ functions is called.
+
+ This 64K array is very sparse. There are one to four entries for managing
+ the dynamic heap (depending on whether the dynamic heap is 64K, 96K, 128K,
+ or 256K), 2 to 128 entries for the storage heap (depending on whether the
+ storage heap is 128K to 8Meg), 8 to 32 entries for the ROM (again,
+ depending on its size), and 1 for the Dragonball registers. That leaves
+ the remaining 64K - 12 entries to be managed by a set of functions that do
+ little but signal an address error if the memory they manage is being
+ accessed.
+
+ Pictorally, it looks like this:
+
+ Emulated 4G space: Memory function array Address Bank functions
+
+ 0x00000000 +--------------+ +--------------------------------+
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x00010000 +--------------+ +--------------------------------+ |
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x00020000 +--------------+ +--------------------------------+ |
+ | 64K | +-----> EmBankDRAM::GetLong, EmBankDRAM::SetLong
+ \/\/\/\/\/\/\/\/ EmBankDRAM::GetWord, EmBankDRAM::SetWord
+ \/\/\/\/\/\/\/\/ EmBankDRAM::GetByte, EmBankDRAM::SetByte
+ | 64K | etc.
+ 0x10000000 +--------------+ +--------------------------------+
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x10010000 +--------------+ +--------------------------------+ |
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x10020000 +--------------+ +--------------------------------+ |
+ | 64K | +-----> EmBankSRAM::GetLong, EmBankSRAM::SetLong
+ \/\/\/\/\/\/\/\/ EmBankSRAM::GetWord, EmBankSRAM::SetWord
+ \/\/\/\/\/\/\/\/ EmBankSRAM::GetByte, EmBankSRAM::SetByte
+ | 64K | etc.
+ 0x10C00000 +--------------+ +--------------------------------+
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x10C10000 +--------------+ +--------------------------------+ |
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0x10C20000 +--------------+ +--------------------------------+ |
+ | 64K | +-----> EmBankROM::GetLong, EmBankROM::SetLong
+ \/\/\/\/\/\/\/\/ EmBankROM::GetWord, EmBankROM::SetWord
+ \/\/\/\/\/\/\/\/ EmBankROM::GetByte, EmBankROM::SetByte
+ | 64K | etc.
+ 0xFFFE0000 +--------------+ +--------------------------------+
+ | 64K |<---| Ptr to fns that mng this range |
+ 0xFFFF0000 +--------------+ +--------------------------------+
+ | 64K |<---| Ptr to fns that mng this range |------+
+ 0xFFFFFFFF +--------------+ +--------------------------------+ |
+ +-----> EmRegs::GetLong, EmRegs::SetLong
+ EmRegs::GetWord, EmRegs::SetWord
+ EmRegs::GetByte, EmRegs::SetByte
+ etc.
+
+ All of the remaining memory function array entries are initialized with
+ pointers to the EmBankDummy::GetLong, EmBankDummy::SetLong, etc., set of
+ functions.
+
+ Using EmBankMapped accessors, we also have the facility for mapping memory
+ from the emulator's address space directly into the emulated address
+ space. This memory appears as additional RAM that magically appears out
+ of nowhere. This mechanism makes it easy for us to "inject" data into the
+ emulated address space. It also makes it easier to call emulated ROM
+ functions as subroutines. Some ROM functions take as parameters pointers
+ to memory locations that are to receive values (for example, pointers to
+ local variables). For those functions, we just map the emulator's stack
+ into the emulated address space. After that's done, we can pass pointers
+ to stack-based variables with impunity.
+
+ A 64K bank can be further sub-divided into 1, 2, or 4 byte chunks
+ spanning any range of the 64K chunk. EmBankRegs manages a collection
+ of EmRegs objects. The EmRegs abstract base class is sub-classed into
+ classes that specify the sub-range of the 64K for which they are
+ responsible and dispatch memory accesses to individual functions
+ that handle accesses at more-or-less a byte level.
+
+ Mapping from emulated addresses to "real" addresses (that is, the
+ corresponding memory locations within the buffers we've allocated to
+ "stand in" for the emulated memory) is performed via macros and inline
+ functions, described below.
+
+ Executive summary:
+
+ - use EmMemGetFoo if you want the address checked for even/oddness.
+ - use EmMemDoGetFoo to actually get the value using a physical address.
+
+ EmMemGet32, EmMemGet16, EmMemGet8
+ EmMemPut32, EmMemPut16, EmMemPut8
+ Inline functions that dispatch to the right bank of functions
+ using EmMemCallGetFunc, EmMemGetBank, and EmMemBankIndex.
+
+ EmMemBankIndex
+ Returns a bank index for the given address.
+
+ EmMemGetBank
+ Gets the right EmAddressBank object.
+
+ EmMemCallGetFunc
+ Merely calls the given function through the EmAddressBank fn ptr.
+
+ EmMemDoGet32, EmMemDoGet16, EmMemDoGet8
+ EmMemDoPut32, EmMemDoPut16, EmMemDoPut8
+ Very low-level memory access. They return the value at the
+ given physical location, byte-swapping if needed.
+*/
+
+// Types.
+
+#pragma mark Types
+
+// Globals.
+
+#pragma mark Globals
+
+EmAddressBank* gEmMemBanks[65536]; // (normally defined in memory.c)
+
+Bool gPCInRAM;
+Bool gPCInROM;
+
+MemAccessFlags gMemAccessFlags =
+{
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+ MASTER_RUNTIME_VALIDATE_SWITCH,
+
+ // User prevention flags.
+
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+ false, // SRAM-get
+ true, // SRAM-set
+ false, // ROM-get
+ true, // ROM-set (HACK: We really want it to be true!)
+ MASTER_RUNTIME_PREVENT_SWITCH,
+ MASTER_RUNTIME_PREVENT_SWITCH,
+
+// false, // fCheck_UserChunkGet
+// false, // fCheck_UserChunkSet
+// false, // fCheck_SysChunkGet
+// false, // fCheck_SysChunkSet
+
+ // System prevention flags.
+
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// false, // SRAM-get
+// true, // SRAM-set
+ false, // ROM-get
+ true, // ROM-set (HACK: We really want it to be true!)
+// MASTER_RUNTIME_PREVENT_SWITCH,
+// MASTER_RUNTIME_PREVENT_SWITCH
+};
+
+MemAccessFlags kZeroMemAccessFlags;
+
+
+#if PROFILE_MEMORY
+/*
+ After 12 Million instructions executed...
+
+ kDRAMLongRead, // 2,797,111
+ kDRAMLongRead2, //
+ kDRAMWordRead, // 1,334,295
+ kDRAMByteRead, // 427,936
+
+ kDRAMLongWrite, // 1,960,933
+ kDRAMLongWrite2, //
+ kDRAMWordWrite, // 800,780
+ kDRAMByteWrite, // 213,029
+
+ kSRAMLongRead, // 4,167
+ kSRAMLongRead2, // 4,167
+ kSRAMWordRead, // 10,768
+ kSRAMByteRead, // 6,295 (jumped WAY up (5-fold) after playing with Address Book / 20 Million instructions)
+
+ kSRAMLongWrite, // 516,246 (stable after boot?)
+ kSRAMLongWrite2, //
+ kSRAMWordWrite, // 5,112
+ kSRAMByteWrite, // 2,183
+
+ kROMLongRead, // 10,156
+ kROMLongRead2, //
+ kROMWordRead, // 557,062
+ kROMByteRead, // 15,516
+
+ kROMLongWrite, // 0
+ kROMLongWrite2, //
+ kROMWordWrite, // 0
+ kROMByteWrite, // 0
+
+ kREGLongRead, // 16,638
+ kREGLongRead2, //
+ kREGWordRead, // 30,477
+ kREGByteRead, // 3,553
+
+ kREGLongWrite, // 9,472
+ kREGLongWrite2, //
+ kREGWordWrite, // 20,709
+ kREGByteWrite, // 12,656
+
+
+ After 32,439,154 instructions:
+
+ kDRAMLongRead, // 6,466,064
+ kDRAMWordRead, // 3,342,826
+ kDRAMByteRead, // 940,345
+
+ kDRAMLongWrite, // 4,136,635
+ kDRAMWordWrite, // 1,462,995
+ kDRAMByteWrite, // 509,189
+
+ kSRAMLongRead, // 24,355
+ kSRAMWordRead, // 32,190
+ kSRAMByteRead, // 75,917
+
+ kSRAMLongWrite, // 2,074,137 (8-Meg ROM)
+ kSRAMWordWrite, // 42,050
+ kSRAMByteWrite, // 11,292
+
+ kROMLongRead, // 25,806
+ kROMWordRead, // 1,302,897
+ kROMByteRead, // 63,590
+
+ kROMLongWrite, // 0
+ kROMWordWrite, // 0
+ kROMByteWrite, // 0
+
+ kREGLongRead, // 32,037
+ kREGWordRead, // 74,299
+ kREGByteRead, // 91,930
+
+ kREGLongWrite, // 20,358
+ kREGWordWrite, // 57,879
+ kREGByteWrite, // 22,592
+*/
+
+long gMemoryAccess[kLastEnum];
+#endif
+
+
+#pragma mark -
+
+
+// ===========================================================================
+// ¥ Memory
+// ===========================================================================
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::Initialize
+// ---------------------------------------------------------------------------
+// Initializes the RAM, ROM, and special memory areas of the emulator. Takes
+// a stream handle to the ROM.
+
+void Memory::Initialize ( EmStream& hROM,
+ RAMSizeType ramSize)
+{
+ // Clear everything out.
+
+ memset (gEmMemBanks, 0, sizeof (gEmMemBanks));
+
+ // Initialize the valid memory banks.
+
+ EmBankDummy::Initialize ();
+
+ // Initialize the Hardware registers memory bank. Do this
+ // *before* initializing the other RAM banks so that we
+ // know how memory is laid out from the chip selects.
+
+ EmBankRegs::Initialize ();
+
+ // Initialize EmBankDRAM after initializing the EmBankSRAM. The order is
+ // important for DragonballEZ. On Dragonball devices, DRAM is
+ // at 0x00000000, and SRAM is at 0x10000000. But on EZ devices,
+ // both start at 0x00000000. By calling EmBankDRAM::Initialize
+ // second, we allow it to overwrite the EmAddressBank handlers
+ // for the part of memory where they overlap.
+
+ EmBankSRAM::Initialize (ramSize);
+ EmBankDRAM::Initialize ();
+
+ EmBankROM::Initialize (hROM);
+
+ EmBankMapped::Initialize ();
+
+ EmAssert (gSession);
+ if (gSession->GetDevice ().HasFlash ())
+ EmBankFlash::Initialize ();
+
+ MetaMemory::Initialize ();
+
+// Memory::ResetBankHandlers (); // Can't do this yet. We can't set the
+ // bank handlers until we know how memory
+ // is laid out, and that information isn't
+ // determined until reset.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Memory::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Memory::Reset (Bool hardwareReset)
+{
+ EmBankDummy::Reset (hardwareReset);
+ EmBankRegs::Reset (hardwareReset);
+ EmBankSRAM::Reset (hardwareReset);
+ EmBankDRAM::Reset (hardwareReset);
+ EmBankROM::Reset (hardwareReset);
+ EmBankMapped::Reset (hardwareReset);
+
+ EmAssert (gSession);
+ if (gSession->GetDevice ().HasFlash ())
+ EmBankFlash::Reset (hardwareReset);
+
+ Memory::ResetBankHandlers ();
+
+ MetaMemory::Reset ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Memory::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Memory::Save (SessionFile& f)
+{
+ EmBankDummy::Save (f);
+ EmBankRegs::Save (f);
+ EmBankSRAM::Save (f);
+ EmBankDRAM::Save (f);
+ EmBankROM::Save (f);
+ EmBankMapped::Save (f);
+
+ EmAssert (gSession);
+ if (gSession->GetDevice ().HasFlash ())
+ EmBankFlash::Save (f);
+
+ MetaMemory::Save (f);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Memory::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Memory::Load (SessionFile& f)
+{
+ EmBankDummy::Load (f);
+ EmBankRegs::Load (f);
+ EmBankSRAM::Load (f);
+ EmBankDRAM::Load (f);
+ EmBankROM::Load (f);
+ EmBankMapped::Load (f);
+
+ EmAssert (gSession);
+ if (gSession->GetDevice ().HasFlash ())
+ EmBankFlash::Load (f);
+
+ MetaMemory::Load (f);
+
+ Memory::ResetBankHandlers ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Memory::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Memory::Dispose (void)
+{
+ EmBankDummy::Dispose ();
+ EmBankRegs::Dispose ();
+ EmBankSRAM::Dispose ();
+ EmBankDRAM::Dispose ();
+ EmBankROM::Dispose ();
+ EmBankMapped::Dispose ();
+
+ // We can't reliably call GetDevice here. That's because the
+ // session may not have been initialized (we could be disposing
+ // of everything because an error condition occurred), and so
+ // there may be no assigned device yet. So we can't ask that
+ // device if there's flash. However, EmBankFlash::Dispose
+ // doesn't do anything, so we don'thave to worry about it
+ // being called.
+
+// EmAssert (gSession);
+// if (gSession->GetDevice ().HasFlash ())
+// EmBankFlash::Dispose ();
+
+ MetaMemory::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::InitializeBanks
+// ---------------------------------------------------------------------------
+// Initializes the specified memory banks with the given data.
+
+void Memory::InitializeBanks ( EmAddressBank& iBankInitializer,
+ int32 iStartingBankIndex,
+ int32 iNumberOfBanks)
+{
+ for (int32 aBankIndex = iStartingBankIndex;
+ aBankIndex < iStartingBankIndex + iNumberOfBanks;
+ aBankIndex++)
+ {
+ gEmMemBanks[aBankIndex] = &iBankInitializer;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::ResetBankHandlers
+// ---------------------------------------------------------------------------
+// Reset the memory bank handlers in response to the chip selects changing.
+// Also called on Initialize, Reset, and Load, just to make sure everything's
+// nailed down.
+
+void Memory::ResetBankHandlers (void)
+{
+ EmBankDummy::SetBankHandlers ();
+ EmBankRegs::SetBankHandlers ();
+ EmBankSRAM::SetBankHandlers ();
+ EmBankDRAM::SetBankHandlers ();
+ EmBankROM::SetBankHandlers ();
+ EmBankMapped::SetBankHandlers ();
+
+ if (gSession->GetDevice ().HardwareID () == 0x0a /*halModelIDVisorPrism*/)
+ {
+ // Run this one again. Visor Prism has this thing where the USB
+ // controller is at 0x10800000, but it sets up the ROM chip select
+ // for 0x10000000 to 0x10FFFFFF. In order to not have EmBankROM
+ // take control over the USB chip, have EmBankRegs install *after*
+ // EmBankROM.
+ EmBankRegs::SetBankHandlers ();
+ }
+
+ EmAssert (gSession);
+ if (gSession->GetDevice ().HasFlash ())
+ EmBankFlash::SetBankHandlers ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::MapPhysicalMemory
+// ---------------------------------------------------------------------------
+// Maps a range of physical memory to appear at the same location of the
+// emulated Palm OS's virtual memory.
+
+void Memory::MapPhysicalMemory (const void* addr, uint32 size)
+{
+ EmBankMapped::MapPhysicalMemory (addr, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::UnmapPhysicalMemory
+// ---------------------------------------------------------------------------
+// Unmaps a range of physical memory from appearing at the same location of
+// the emulated Palm OS's virtual memory.
+
+void Memory::UnmapPhysicalMemory (const void* addr)
+{
+ EmBankMapped::UnmapPhysicalMemory (addr);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::GetMappingInfo
+// ---------------------------------------------------------------------------
+
+void Memory::GetMappingInfo (emuptr addr, void** start, uint32* len)
+{
+ EmBankMapped::GetMappingInfo (addr, start, len);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Memory::CheckNewPC
+// ---------------------------------------------------------------------------
+
+void Memory::CheckNewPC (emuptr newPC)
+{
+ gPCInRAM = newPC < EmBankROM::GetMemoryStart ();
+ gPCInROM = newPC >= EmBankROM::GetMemoryStart ();
+}
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ CEnableFullAccess
+// ===========================================================================
+
+long CEnableFullAccess::fgAccessCount = 0;
+
+
+// ---------------------------------------------------------------------------
+// ¥ CEnableFullAccess::CEnableFullAccess
+// ---------------------------------------------------------------------------
+
+CEnableFullAccess::CEnableFullAccess (void) :
+ fOldMemAccessFlags (gMemAccessFlags)
+#if HAS_PROFILING
+ , fOldProfilingCounted (gProfilingCounted)
+#endif
+{
+ gMemAccessFlags = kZeroMemAccessFlags;
+
+#if HAS_PROFILING
+ gProfilingCounted = false;
+#endif
+
+ ++fgAccessCount;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CEnableFullAccess::~CEnableFullAccess
+// ---------------------------------------------------------------------------
+
+CEnableFullAccess::~CEnableFullAccess (void)
+{
+ gMemAccessFlags = fOldMemAccessFlags;
+
+#if HAS_PROFILING
+ gProfilingCounted = fOldProfilingCounted;
+#endif
+
+ --fgAccessCount;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CEnableFullAccess::AccessOK
+// ---------------------------------------------------------------------------
+
+Bool CEnableFullAccess::AccessOK (void)
+{
+ return fgAccessCount > 0;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// These functions with two kinds of "pointers": emuptr's
+// and void*'s. Accessing memory for each kind of pointer is different.
+// Since the functions are template functions, we can't know at the time we
+// write the function what kind of pointer we'll be dealing with, so we can't
+// hard-code the memory-accessing method. Instead, we provide all of these
+// inline accessors and let the compiler sort it out.
+// ---------------------------------------------------------------------------
+
+inline char _get_byte(const void* p)
+{
+ return *(char*) p;
+}
+
+inline char _get_byte(emuptr p)
+{
+ return (char) EmMemGet8(p);
+}
+
+inline void _put_byte(void* p, const uint8 v)
+{
+ *(uint8*) p = v;
+}
+
+inline void _put_byte(emuptr p, const uint8 v)
+{
+ EmMemPut8(p, v);
+}
+
+inline uint16 _get_word(const void* p)
+{
+ return *(uint16*) p;
+}
+
+inline uint16 _get_word(emuptr p)
+{
+ return (uint16) EmMemGet16(p);
+}
+
+inline void _put_word(void* p, const uint16 v)
+{
+ *(uint16*) p = v;
+}
+
+inline void _put_word(emuptr p, const uint16 v)
+{
+ EmMemPut16(p, v);
+}
+
+inline uint32 _get_long(const void* p)
+{
+ return *(uint32*) p;
+}
+
+inline uint32 _get_long(emuptr p)
+{
+ return (uint32) EmMemGet32(p);
+}
+
+inline void _put_long(void* p, const uint32 v)
+{
+ *(uint32*) p = v;
+}
+
+inline void _put_long(emuptr p, const uint32 v)
+{
+ EmMemPut32(p, v);
+}
+
+inline const void* _get_real_address(const void* p)
+{
+ return p;
+}
+
+inline const void* _get_real_address(emuptr p)
+{
+ return EmMemGetRealAddress(p);
+}
+
+template <class T>
+inline void _add_delta (T*& v, long delta)
+{
+ v = (T*) (((char*) v) + delta);
+}
+
+inline void _add_delta (emuptr& v, long delta)
+{
+ v += delta;
+}
+
+template <class T>
+inline void _increment (T& v)
+{
+ _add_delta (v, 1);
+}
+
+template <class T>
+inline void _decrement (T& v)
+{
+ _add_delta (v, -1);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_memset
+ *
+ * DESCRIPTION: Same as Std C Library memset function.
+ *
+ * PARAMETERS: Same as Std C Library memset function.
+ *
+ * RETURNED: Same as Std C Library memset function.
+ *
+ ***********************************************************************/
+
+emuptr EmMem_memset(emuptr dst, int val, size_t len)
+{
+ emuptr q = dst;
+
+ uint32 longVal = val;
+ longVal |= (longVal << 8);
+ longVal |= (longVal << 16);
+
+ EmMemPutFunc longPutter = EmMemGetBank(dst).lput;
+ EmMemPutFunc bytePutter = EmMemGetBank(dst).bput;
+
+ while ((q & 3) && len > 0) // while there are leading bytes
+ {
+ bytePutter(q, val);
+ q += sizeof (char);
+ len -= sizeof (char);
+ }
+
+ while (len >= sizeof (long)) // while there are middle longs
+ {
+ longPutter(q, longVal);
+ q += sizeof (long);
+ len -= sizeof (long);
+ }
+
+ while (len > 0) // while there are trailing bytes
+ {
+ bytePutter(q, val);
+ q += sizeof (char);
+ len -= sizeof (char);
+ }
+
+ return dst;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_memchr
+ *
+ * DESCRIPTION: Same as Std C Library memchr function.
+ *
+ * PARAMETERS: Same as Std C Library memchr function.
+ *
+ * RETURNED: Same as Std C Library memchr function.
+ *
+ ***********************************************************************/
+
+emuptr EmMem_memchr(emuptr src, int val, size_t len)
+{
+ emuptr p = src;
+
+ ++len;
+
+ while (--len)
+ {
+ if (_get_byte (p) == val)
+ return p;
+
+ _increment (p);
+ }
+
+ return EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_memcmp
+ *
+ * DESCRIPTION: Same as Std C Library memcmp function.
+ *
+ * PARAMETERS: Same as Std C Library memcmp function.
+ *
+ * RETURNED: Same as Std C Library memcmp function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+int EmMem_memcmp(T1 src1, T2 src2, size_t len)
+{
+ T1 p1 = src1;
+ T2 p2 = src2;
+
+ ++len;
+
+ while (--len)
+ {
+ unsigned char ch1 = _get_byte (p1);
+ unsigned char ch2 = _get_byte (p2);
+
+ if (ch1 != ch2)
+ return (ch1 < ch2) ? -1 : 1;
+
+ _increment (p1);
+ _increment (p2);
+ }
+
+ return 0;
+}
+
+ // Instantiate EmMem_memcmp's that work with:
+ //
+ // dest source
+ // ------ ------
+ // void* emuptr
+ // const void* emuptr
+ // emuptr void*
+ // emuptr const void*
+ // emuptr emuptr
+
+template int EmMem_memcmp<void*, emuptr> (void* dst, emuptr src, size_t len);
+template int EmMem_memcmp<const void*, emuptr> (const void* dst, emuptr src, size_t len);
+template int EmMem_memcmp<emuptr, void*> (emuptr dst, void* src, size_t len);
+template int EmMem_memcmp<emuptr, const void*> (emuptr dst, const void* src, size_t len);
+template int EmMem_memcmp<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_memcpy
+ *
+ * DESCRIPTION: Same as Std C Library memcpy function.
+ *
+ * PARAMETERS: Same as Std C Library memcpy function.
+ *
+ * RETURNED: Same as Std C Library memcpy function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_memcpy (T1 dst, T2 src, size_t len)
+{
+ T1 q = dst;
+ T2 p = src;
+
+ while (len--)
+ {
+ _put_byte(q, _get_byte(p));
+ _increment (q);
+ _increment (p);
+ }
+
+ return dst;
+}
+
+ // Instantiate EmMem_memcpy's that work with:
+ //
+ // dest source
+ // ------ ------
+ // void* emuptr
+ // emuptr void*
+ // emuptr const void*
+ // emuptr emuptr
+
+template void* EmMem_memcpy<void*, emuptr> (void* dst, emuptr src, size_t len);
+template emuptr EmMem_memcpy<emuptr, void*> (emuptr dst, void* src, size_t len);
+template emuptr EmMem_memcpy<emuptr, const void*> (emuptr dst, const void* src, size_t len);
+template emuptr EmMem_memcpy<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_memmove
+ *
+ * DESCRIPTION: Same as Std C Library memmove function.
+ *
+ * PARAMETERS: Same as Std C Library memmove function.
+ *
+ * RETURNED: Same as Std C Library memmove function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_memmove (T1 dst, T2 src, size_t len)
+{
+ T1 q = dst;
+ T2 p = src;
+
+ Bool backward = _get_real_address(dst) <= _get_real_address(src);
+
+ if (backward)
+ {
+ while (len--)
+ {
+ _put_byte(q, _get_byte(p));
+ _increment (q);
+ _increment (p);
+ }
+ }
+ else
+ {
+ _add_delta (q, len);
+ _add_delta (p, len);
+
+ while (len--)
+ {
+ _decrement (q);
+ _decrement (p);
+ _put_byte(q, _get_byte(p));
+ }
+ }
+
+ return dst;
+}
+
+ // Instantiate EmMem_memmove's that work with:
+ //
+ // dest source
+ // ------ ------
+ // void* emuptr
+ // emuptr void*
+ // emuptr const void*
+ // emuptr emuptr
+
+template void* EmMem_memmove<void*, emuptr> (void* dst, emuptr src, size_t len);
+template emuptr EmMem_memmove<emuptr, void*> (emuptr dst, void* src, size_t len);
+template emuptr EmMem_memmove<emuptr, const void*> (emuptr dst, const void* src, size_t len);
+template emuptr EmMem_memmove<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strlen
+ *
+ * DESCRIPTION: Same as Std C Library strlen function.
+ *
+ * PARAMETERS: Same as Std C Library strlen function.
+ *
+ * RETURNED: Same as Std C Library strlen function.
+ *
+ ***********************************************************************/
+
+size_t EmMem_strlen(emuptr str)
+{
+ emuptr eos = str;
+
+ while (_get_byte(eos))
+ _increment (eos);
+
+ return ((size_t) (eos - str));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strcpy
+ *
+ * DESCRIPTION: Same as Std C Library strcpy function.
+ *
+ * PARAMETERS: Same as Std C Library strcpy function.
+ *
+ * RETURNED: Same as Std C Library strcpy function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_strcpy(T1 dst, T2 src)
+{
+ T1 q = dst;
+ T2 p = src;
+ char ch;
+
+ do {
+ ch = _get_byte (p);
+ _increment (p);
+ _put_byte (q, ch);
+ _increment (q);
+ } while (ch);
+
+ return dst;
+}
+
+ // Instantiate EmMem_strcpy's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template char* EmMem_strcpy<char*, emuptr> (char* dst, emuptr src);
+template emuptr EmMem_strcpy<emuptr, char*> (emuptr dst, char* src);
+template emuptr EmMem_strcpy<emuptr, const char*> (emuptr dst, const char* src);
+template emuptr EmMem_strcpy<emuptr, emuptr> (emuptr dst, emuptr src);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strncpy
+ *
+ * DESCRIPTION: Same as Std C Library strncpy function.
+ *
+ * PARAMETERS: Same as Std C Library strncpy function.
+ *
+ * RETURNED: Same as Std C Library strncpy function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_strncpy(T1 dst, T2 src, size_t len)
+{
+ T1 q = dst;
+ T2 p = src;
+
+ ++len;
+
+ while (--len)
+ {
+ char ch = _get_byte(p);
+ _increment (p);
+
+ _put_byte (q, ch);
+ _increment (q);
+
+ if (!ch)
+ {
+ while (--len)
+ {
+ _put_byte (q, 0);
+ _increment (q);
+ }
+
+ break;
+ }
+ }
+
+ return dst;
+}
+
+ // Instantiate EmMem_strncpy's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template char* EmMem_strncpy<char*, emuptr> (char* dst, emuptr src, size_t len);
+template emuptr EmMem_strncpy<emuptr, char*> (emuptr dst, char* src, size_t len);
+template emuptr EmMem_strncpy<emuptr, const char*> (emuptr dst, const char* src, size_t len);
+template emuptr EmMem_strncpy<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strcat
+ *
+ * DESCRIPTION: Same as Std C Library strcat function.
+ *
+ * PARAMETERS: Same as Std C Library strcat function.
+ *
+ * RETURNED: Same as Std C Library strcat function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_strcat(T1 dst, T2 src)
+{
+ T1 q = dst;
+ T2 p = src;
+
+ while (_get_byte (q))
+ _increment(q);
+
+ while (_get_byte (p))
+ {
+ _put_byte (q, _get_byte (p));
+ _increment(q);
+ _increment(p);
+ }
+
+ _put_byte (q, 0);
+
+ return dst;
+}
+
+ // Instantiate EmMem_strcat's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template char* EmMem_strcat<char*, emuptr> (char* dst, emuptr src);
+template emuptr EmMem_strcat<emuptr, char*> (emuptr dst, char* src);
+template emuptr EmMem_strcat<emuptr, const char*> (emuptr dst, const char* src);
+template emuptr EmMem_strcat<emuptr, emuptr> (emuptr dst, emuptr src);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strncat
+ *
+ * DESCRIPTION: Same as Std C Library strncat function.
+ *
+ * PARAMETERS: Same as Std C Library strncat function.
+ *
+ * RETURNED: Same as Std C Library strncat function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+T1 EmMem_strncat(T1 dst, T2 src, size_t len)
+{
+ T1 q = dst;
+ T2 p = src;
+
+ while (_get_byte (q))
+ _increment (q);
+
+ ++len;
+
+ while (--len)
+ {
+ char ch = _get_byte(p);
+ _increment (p);
+
+ _put_byte (q, ch);
+ _increment (q);
+
+ if (!ch)
+ return dst;
+ }
+
+ _put_byte (q, 0);
+
+ return dst;
+}
+
+ // Instantiate EmMem_strncat's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template char* EmMem_strncat<char*, emuptr> (char* dst, emuptr src, size_t len);
+template emuptr EmMem_strncat<emuptr, char*> (emuptr dst, char* src, size_t len);
+template emuptr EmMem_strncat<emuptr, const char*> (emuptr dst, const char* src, size_t len);
+template emuptr EmMem_strncat<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strcmp
+ *
+ * DESCRIPTION: Same as Std C Library strcmp function.
+ *
+ * PARAMETERS: Same as Std C Library strcmp function.
+ *
+ * RETURNED: Same as Std C Library strcmp function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+int EmMem_strcmp(T1 dst, T2 src)
+{
+ T1 p1 = dst;
+ T2 p2 = src;
+
+ while (1)
+ {
+ unsigned char c1 = _get_byte (p1);
+ unsigned char c2 = _get_byte (p2);
+
+ if (c1 != c2)
+ return (c1 - c2);
+ else if (!c1)
+ break;
+
+ _increment (p1);
+ _increment (p2);
+ }
+
+ return 0;
+}
+
+ // Instantiate EmMem_strcmp's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // const char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template int EmMem_strcmp<char*, emuptr> (char* dst, emuptr src);
+template int EmMem_strcmp<const char*, emuptr> (const char* dst, emuptr src);
+template int EmMem_strcmp<emuptr, char*> (emuptr dst, char* src);
+template int EmMem_strcmp<emuptr, const char*> (emuptr dst, const char* src);
+template int EmMem_strcmp<emuptr, emuptr> (emuptr dst, emuptr src);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmMem_strncmp
+ *
+ * DESCRIPTION: Same as Std C Library strncmp function.
+ *
+ * PARAMETERS: Same as Std C Library strncmp function.
+ *
+ * RETURNED: Same as Std C Library strncmp function.
+ *
+ ***********************************************************************/
+
+template <class T1, class T2>
+int EmMem_strncmp(T1 dst, T2 src, size_t len)
+{
+ T1 p1 = dst;
+ T2 p2 = src;
+
+ ++len;
+
+ while (--len)
+ {
+ unsigned char c1 = _get_byte (p1);
+ unsigned char c2 = _get_byte (p2);
+
+ if (c1 != c2)
+ return (c1 - c2);
+ else if (!c1)
+ break;
+
+ _increment (p1);
+ _increment (p2);
+ }
+
+ return 0;
+}
+
+ // Instantiate EmMem_strncmp's that work with:
+ //
+ // dest source
+ // ------ ------
+ // char* emuptr
+ // const char* emuptr
+ // emuptr char*
+ // emuptr const char*
+ // emuptr emuptr
+
+template int EmMem_strncmp<char*, emuptr> (char* dst, emuptr src, size_t len);
+template int EmMem_strncmp<const char*, emuptr> (const char* dst, emuptr src, size_t len);
+template int EmMem_strncmp<emuptr, char*> (emuptr dst, char* src, size_t len);
+template int EmMem_strncmp<emuptr, const char*> (emuptr dst, const char* src, size_t len);
+template int EmMem_strncmp<emuptr, emuptr> (emuptr dst, emuptr src, size_t len);
diff --git a/SrcShared/Hardware/EmMemory.h b/SrcShared/Hardware/EmMemory.h
new file mode 100644
index 0000000..f10b749
--- /dev/null
+++ b/SrcShared/Hardware/EmMemory.h
@@ -0,0 +1,457 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmMemory_h
+#define EmMemory_h
+
+// Normally, I'd assume that these includes were pulled in
+// by EmCommon.h. However, EmMemory.h gets included by UAE,
+// which doesn't pull in EmCommon.h. So I have to explicitly
+// make sure they're included.
+
+#include "Switches.h" // WORDSWAP_MEMORY, UNALIGNED_LONG_ACCESS
+#include "EmTypes.h" // uint32, etc.
+#include "EmAssert.h" // EmAssert
+
+#include "sysconfig.h" // STATIC_INLINE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+// ¥ EmAddressBank
+// ---------------------------------------------------------------------------
+
+typedef uint32 (*EmMemGetFunc) (emuptr);
+typedef void (*EmMemPutFunc) (emuptr, uint32);
+typedef uint8* (*EmMemTranslateFunc) (emuptr);
+typedef int (*EmMemCheckFunc) (emuptr, uint32);
+typedef void (*EmMemCycleFunc) (void);
+typedef uint8* (*EmMemTranslateMetaFunc) (emuptr);
+
+typedef struct EmAddressBank
+{
+ /* These ones should be self-explanatory... */
+ EmMemGetFunc lget, wget, bget;
+ EmMemPutFunc lput, wput, bput;
+
+ /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
+ * be used to address memory without calling the wget/wput functions.
+ * This doesn't work for all memory banks, so this function may call
+ * abort(). */
+ EmMemTranslateFunc xlateaddr;
+
+ /* To prevent calls to abort(), use check before calling xlateaddr.
+ * It checks not only that the memory bank can do xlateaddr, but also
+ * that the pointer points to an area of at least the specified size.
+ * This is used for example to translate bitplane pointers in custom.c */
+ EmMemCheckFunc checkaddr;
+
+ EmMemTranslateMetaFunc xlatemetaaddr;
+ EmMemCycleFunc EmMemAddOpcodeCycles;
+} EmAddressBank;
+
+
+#ifndef ECM_DYNAMIC_PATCH
+
+ extern EmAddressBank* gEmMemBanks[65536];
+
+#else // ECM_DYNAMIC_PATCH
+
+ extern EmAddressBank** gDynEmMemBanksP;
+
+#endif // ECM_DYNAMIC_PATCH
+
+
+// ---------------------------------------------------------------------------
+// ¥ Support macros
+// ---------------------------------------------------------------------------
+
+#ifndef ECM_DYNAMIC_PATCH
+
+ #define EmMemBankIndex(addr) (((emuptr)(addr)) >> 16)
+
+ #define EmMemGetBank(addr) (*gEmMemBanks[EmMemBankIndex(addr)])
+ #define EmMemPutBank(addr, b) (gEmMemBanks[EmMemBankIndex(addr)] = (b))
+
+#else // ECM_DYNAMIC_PATCH
+
+ #define EmMemBankIndex(addr) (((unsigned long)(addr)) >> 16)
+
+ #define EmMemGetBank(addr) (*((gDynEmMemBanksP)[EmMemBankIndex(addr)]))
+ #define EmMemPutBank(addr, b) ((gDynEmMemBanksP)[EmMemBankIndex(addr)] = (b))
+
+#endif // ECM_DYNAMIC_PATCH
+
+#define EmMemCallGetFunc(func, addr) ((*EmMemGetBank(addr).func)(addr))
+#define EmMemCallPutFunc(func, addr, v) ((*EmMemGetBank(addr).func)(addr, v))
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet32(emuptr addr)
+{
+ return EmMemCallGetFunc(lget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet16(emuptr addr)
+{
+ return EmMemCallGetFunc(wget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet8(emuptr addr)
+{
+ return EmMemCallGetFunc(bget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut32(emuptr addr, uint32 l)
+{
+ EmMemCallPutFunc(lput, addr, l);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut16(emuptr addr, uint32 w)
+{
+ EmMemCallPutFunc(wput, addr, w);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut8(emuptr addr, uint32 b)
+{
+ EmMemCallPutFunc(bput, addr, b);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGetRealAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8* EmMemGetRealAddress(emuptr addr)
+{
+ return EmMemGetBank(addr).xlateaddr(addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemCheckAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE int EmMemCheckAddress(emuptr addr, uint32 size)
+{
+ return EmMemGetBank(addr).checkaddr(addr, size);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemAddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemAddOpcodeCycles(emuptr addr)
+{
+ EmAssert (EmMemGetBank(addr).EmMemAddOpcodeCycles);
+ EmMemGetBank(addr).EmMemAddOpcodeCycles();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGetMetaAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8* EmMemGetMetaAddress(emuptr addr)
+{
+ EmAssert(EmMemGetBank(addr).xlatemetaaddr);
+ return EmMemGetBank(addr).xlatemetaaddr(addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemDoGet32 (void* a)
+{
+#if WORDSWAP_MEMORY || !UNALIGNED_LONG_ACCESS
+ return (((uint32) *(((uint16*) a) + 0)) << 16) |
+ (((uint32) *(((uint16*) a) + 1)));
+#else
+ return *(uint32*) a;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint16 EmMemDoGet16 (void* a)
+{
+ return *(uint16*) a;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8 EmMemDoGet8 (void* a)
+{
+#if WORDSWAP_MEMORY
+ return *(uint8*) ((long) a ^ 1);
+#else
+ return *(uint8*) a;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut32 (void* a, uint32 v)
+{
+#if WORDSWAP_MEMORY || !UNALIGNED_LONG_ACCESS
+ *(((uint16*) a) + 0) = (uint16) (v >> 16);
+ *(((uint16*) a) + 1) = (uint16) (v);
+#else
+ *(uint32*) a = v;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut16 (void* a, uint16 v)
+{
+ *(uint16*) a = v;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut8 (void* a, uint8 v)
+{
+#if WORDSWAP_MEMORY
+ *(uint8*) ((long) a ^ 1) = v;
+#else
+ *(uint8*) a = v;
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+
+class EmStream;
+
+
+// Types.
+
+// This struct is used to control access to memory. The first set of fields
+// are booleans which, when set to true, turn on address validation for the
+// various ranges of memory. The second second set of fields are booleans
+// which, when set to true, prevent access by user applications to the various
+// ranges of memory.
+
+struct MemAccessFlags
+{
+ Bool fValidate_DummyGet;
+ Bool fValidate_DummySet;
+ Bool fValidate_RegisterGet;
+ Bool fValidate_RegisterSet;
+ Bool fValidate_DRAMGet;
+ Bool fValidate_DRAMSet;
+ Bool fValidate_SRAMGet;
+ Bool fValidate_SRAMSet;
+ Bool fValidate_ROMGet;
+ Bool fValidate_ROMSet;
+
+// Bool fProtect_LowMemGet;
+// Bool fProtect_LowMemSet;
+// Bool fProtect_GlobalGet;
+// Bool fProtect_GlobalSet;
+// Bool fProtect_ScreenGet;
+// Bool fProtect_ScreenSet;
+ Bool fProtect_SRAMGet;
+ Bool fProtect_SRAMSet;
+ Bool fProtect_ROMGet;
+ Bool fProtect_ROMSet;
+ Bool fProtect_RegisterGet;
+ Bool fProtect_RegisterSet;
+
+// Bool fCheck_UserChunkGet;
+// Bool fCheck_UserChunkSet;
+// Bool fCheck_SysChunkGet;
+// Bool fCheck_SysChunkSet;
+
+// Bool fProtect_SysLowMemGet;
+// Bool fProtect_SysLowMemSet;
+// Bool fProtect_SysGlobalGet;
+// Bool fProtect_SysGlobalSet;
+// Bool fProtect_SysScreenGet;
+// Bool fProtect_SysScreenSet;
+// Bool fProtect_SysSRAMGet;
+// Bool fProtect_SysSRAMSet;
+ Bool fProtect_SysROMGet;
+ Bool fProtect_SysROMSet;
+// Bool fProtect_SysRegisterGet;
+// Bool fProtect_SysRegisterSet;
+};
+
+
+// Globals.
+
+extern MemAccessFlags gMemAccessFlags;
+extern Bool gPCInRAM;
+extern Bool gPCInROM;
+
+#if PROFILE_MEMORY
+enum
+{
+ kDRAMLongRead, kDRAMLongRead2, kDRAMWordRead, kDRAMByteRead,
+ kDRAMLongWrite, kDRAMLongWrite2, kDRAMWordWrite, kDRAMByteWrite,
+ kSRAMLongRead, kSRAMLongRead2, kSRAMWordRead, kSRAMByteRead,
+ kSRAMLongWrite, kSRAMLongWrite2, kSRAMWordWrite, kSRAMByteWrite,
+ kROMLongRead, kROMLongRead2, kROMWordRead, kROMByteRead,
+ kROMLongWrite, kROMLongWrite2, kROMWordWrite, kROMByteWrite,
+ kREGLongRead, kREGLongRead2, kREGWordRead, kREGByteRead,
+ kREGLongWrite, kREGLongWrite2, kREGWordWrite, kREGByteWrite,
+
+ kSED1375LongRead, kSED1375LongRead2, kSED1375WordRead, kSED1375ByteRead,
+ kSED1375LongWrite, kSED1375LongWrite2, kSED1375WordWrite, kSED1375ByteWrite,
+
+ kLastEnum
+};
+extern long gMemoryAccess[];
+#endif
+
+struct EmAddressBank;
+class SessionFile;
+
+// Function prototypes.
+
+class Memory
+{
+ public:
+ static void Initialize (EmStream& hROM,
+ RAMSizeType ramSize);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void InitializeBanks (EmAddressBank& iBankInitializer,
+ int32 iStartingBankIndex,
+ int32 iNumberOfBanks);
+
+ static void ResetBankHandlers (void);
+
+ static void MapPhysicalMemory (const void*, uint32);
+ static void UnmapPhysicalMemory (const void*);
+ static void GetMappingInfo (emuptr, void**, uint32*);
+
+ static void CheckNewPC (emuptr newPC);
+ static int IsPCInRAM (void) { return gPCInRAM; }
+ static int IsPCInROM (void) { return gPCInROM; }
+};
+
+typedef Memory EmMemory;
+
+
+// There are places within the emulator where we'd like to access low-memory
+// and/or Dragonball registers. If the PC happens to be in RAM, then
+// the checks implied by the above booleans and switches will flag our
+// access as an error. Before making such accesses, create an instance
+// of CEnableFullAccess to suspend and restore the checks.
+//
+// Since such accesses are typically "meta" accesses where the emulator is
+// accessing memory outside the normal execution of an opcode, we also
+// turn off the profiling variable that controls whether or not cycles
+// spent accessing memory are counted.
+
+class CEnableFullAccess
+{
+ public:
+ CEnableFullAccess (void);
+ ~CEnableFullAccess (void);
+
+ static Bool AccessOK (void);
+
+ private:
+ MemAccessFlags fOldMemAccessFlags;
+
+#if HAS_PROFILING
+ Bool fOldProfilingCounted;
+#endif
+
+ static long fgAccessCount;
+};
+
+
+// Std C Library-ish routines for manipulating data
+// in emulated memory.
+
+emuptr EmMem_memset(emuptr dst, int val, size_t len);
+
+emuptr EmMem_memchr(emuptr src, int val, size_t len);
+
+template <class T1, class T2>
+int EmMem_memcmp(T1 src1, T2 src2, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_memcpy (T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_memmove (T1 dst, T2 src, size_t len);
+
+size_t EmMem_strlen(emuptr str);
+
+template <class T1, class T2>
+T1 EmMem_strcpy(T1 dst, T2 src);
+
+template <class T1, class T2>
+T1 EmMem_strncpy(T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_strcat(T1 dst, T2 src);
+
+template <class T1, class T2>
+T1 EmMem_strncat(T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+int EmMem_strcmp(T1 dst, T2 src);
+
+template <class T1, class T2>
+int EmMem_strncmp(T1 dst, T2 src, size_t len);
+
+#endif // __cplusplus
+
+#endif /* EmMemory_h */
diff --git a/SrcShared/Hardware/EmRegs.cpp b/SrcShared/Hardware/EmRegs.cpp
new file mode 100644
index 0000000..bd1c50a
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs.cpp
@@ -0,0 +1,499 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegs.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmBankRegs.h" // EmBankRegs::InvalidAccess
+#include "EmMemory.h" // Memory::InitializeBanks, EmMemBankIndex
+
+/*
+ EmRegs is a base class for subclasses that manage the accessing of
+ emulated memory at a byte, word, or long level. See comments in
+ EmRegsBank.cpp for a description on how EmRegs objects are managed,
+ and EmMemory for how memory in general is emulated.
+
+ EmRegs subclasses are suited for managing hardware registers, such
+ as the Dragonball [EZ | VZ] hardware registers, the USB registers
+ in the Handspring Visor, or the special PLD registers in some of the
+ Palm VII devices.
+
+ To create a new EmRegs subclass that can handle accesses to a special
+ range of memory, do the following:
+
+ * Create a subclass of EmRegs
+
+ * Provide implementations for the pure virtual functions:
+
+ * SetSubBankHandlers: this method needs to call EmRegs::SetHandler
+ to install a read and write function for each memory location
+ that can be accessed. It should also first call the base
+ class SetSubBankHandlers in order to install default handlers
+ for all memory locations in the memory range the subclass manages.
+
+ * GetRealAddress: given an address in emulated space, this function
+ returns the real address from the point of view of the emulator.
+ For instance, if your EmRegs subclass manages the memory range
+ 0x17000000 to 0x17001000, and you have created a 4K buffer to
+ represent this memory range, then GetRealAddress would be like:
+
+ return &fMyBuffer[address - 0x17000000];
+
+ * GetAddressStart: returns the base address of the memory range
+ managed by this class. In the example above, this method would
+ return 0x17000000.
+
+ * GetAddressRange: returns the range of memory managed by this
+ class. In the example above, this method would return 0x1000.
+
+ * Define read and write function handlers for each memory location
+ in the managed range. These functions handlers are installed in
+ your SetSubBankHandlers override. EmBankRegs will call these
+ handlers as appropriate.
+
+ * Optionally implement Initialize, Reset, Save, Load, and Dispose
+ overrides. You will usually override Initialize to create any
+ buffers required to hold your data, and correspondingly dispose
+ of those resources in a Dispose override. Most subclasses will
+ need to override Reset in order to initialize their emulated
+ registers. And override Save and Load if you want to save and
+ restore your registers to the session (.psf) file.
+
+ * In the appropriate case statement in EmDevice::CreateRegs, create
+ an instance of your EmRegs class and install it by calling
+ EmBankRegs::AddSubBank.
+*/
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::EmRegs
+// ---------------------------------------------------------------------------
+
+EmRegs::EmRegs (void) :
+ fReadFunctions (),
+ fWriteFunctions ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::~EmRegs
+// ---------------------------------------------------------------------------
+
+EmRegs::~EmRegs (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegs::Initialize (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegs::Reset (Bool /*hardwareReset*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::Save
+// ---------------------------------------------------------------------------
+
+void EmRegs::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::Load
+// ---------------------------------------------------------------------------
+
+void EmRegs::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegs::Dispose (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetBankHandlers (EmAddressBank& bank)
+{
+ emuptr address = this->GetAddressStart ();
+ uint32 range = this->GetAddressRange ();
+ uint32 numBanks = EmMemBankIndex (address + range - 1) - EmMemBankIndex (address) + 1;
+
+ Memory::InitializeBanks (bank, EmMemBankIndex (address), numBanks);
+
+ this->SetSubBankHandlers ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetSubBankHandlers (void)
+{
+ this->SetHandler (&EmRegs::UnsupportedRead, &EmRegs::UnsupportedWrite,
+ this->GetAddressStart (), this->GetAddressRange ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs::GetLong (emuptr address)
+{
+// EmAssert (this->ValidAddress (address, 4));
+
+ long offset = address - this->GetAddressStart ();
+ ReadFunction fn = fReadFunctions [offset];
+ EmAssert (fn);
+
+ return (this->*fn) (address, 4);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs::GetWord (emuptr address)
+{
+// EmAssert (this->ValidAddress (address, 2));
+
+ long offset = address - this->GetAddressStart ();
+ ReadFunction fn = fReadFunctions [offset];
+ EmAssert (fn);
+
+ return (this->*fn) (address, 2);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs::GetByte (emuptr address)
+{
+// EmAssert (this->ValidAddress (address, 1));
+
+ long offset = address - this->GetAddressStart ();
+ ReadFunction fn = fReadFunctions [offset];
+ EmAssert (fn);
+
+ return (this->*fn) (address, 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetLong
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetLong (emuptr address, uint32 value)
+{
+// EmAssert (this->ValidAddress (address, 4));
+
+ long offset = address - this->GetAddressStart ();
+ WriteFunction fn = fWriteFunctions [offset];
+ EmAssert (fn);
+
+ (this->*fn) (address, 4, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetWord
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetWord (emuptr address, uint32 value)
+{
+// EmAssert (this->ValidAddress (address, 2));
+
+ long offset = address - this->GetAddressStart ();
+ WriteFunction fn = fWriteFunctions [offset];
+ EmAssert (fn);
+
+ (this->*fn) (address, 2, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetByte
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetByte (emuptr address, uint32 value)
+{
+// EmAssert (this->ValidAddress (address, 1));
+
+ long offset = address - this->GetAddressStart ();
+ WriteFunction fn = fWriteFunctions [offset];
+ EmAssert (fn);
+
+ (this->*fn) (address, 1, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmRegs::ValidAddress (emuptr address, uint32 size)
+{
+ UNUSED_PARAM (size);
+
+ int result = false;
+ unsigned long offset = address - this->GetAddressStart ();
+
+ if (offset < fReadFunctions.size ())
+ {
+ ReadFunction fn = fReadFunctions [offset];
+ result = (fn != &EmRegs::UnsupportedRead);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegs::GetRealAddress (emuptr address)
+{
+ UNUSED_PARAM (address);
+
+ // Sub-class's responsibility.
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::SetHandler
+// ---------------------------------------------------------------------------
+
+void EmRegs::SetHandler (ReadFunction read, WriteFunction write,
+ uint32 start, int count)
+{
+ if (fReadFunctions.size () == 0)
+ {
+ uint32 range = this->GetAddressRange ();
+
+ fReadFunctions.resize (range, &EmRegs::UnsupportedRead);
+ fWriteFunctions.resize (range, &EmRegs::UnsupportedWrite);
+ }
+
+ int index = start - this->GetAddressStart ();
+
+ EmAssert (index >= 0);
+ EmAssert (index < (long) fReadFunctions.size ());
+
+ for (int ii = 0; ii < count; ++ii, ++index)
+ {
+ fReadFunctions[index] = read;
+ fWriteFunctions[index] = write;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::UnsupportedRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs::UnsupportedRead (emuptr address, int size)
+{
+ if (!CEnableFullAccess::AccessOK ())
+ {
+ EmBankRegs::PreventedAccess (address, size, true);
+ }
+
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::UnsupportedWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs::UnsupportedWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(value)
+
+ if (!CEnableFullAccess::AccessOK ())
+ {
+ EmBankRegs::PreventedAccess (address, size, false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::StdReadBE
+// ---------------------------------------------------------------------------
+// Read registers in a strict Big Endian fashion.
+
+uint32 EmRegs::StdReadBE (emuptr address, int size)
+{
+ uint8* realAddr = this->GetRealAddress (address);
+
+ if (size == 1)
+ return *(uint8*) realAddr;
+
+ if (size == 2)
+ {
+ uint16 result16 = *(uint16*) realAddr;
+ Canonical (result16);
+ return result16;
+ }
+
+#if UNALIGNED_LONG_ACCESS
+
+ uint32 result32 = *(uint32*) realAddr;
+ Canonical (result32);
+ return result32;
+
+#else
+
+ return (realAddr[0] << 24) |
+ (realAddr[1] << 16) |
+ (realAddr[2] << 8) |
+ (realAddr[3] << 0);
+
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::StdWriteBE
+// ---------------------------------------------------------------------------
+// Write registers in a strict Big Endian fashion.
+
+void EmRegs::StdWriteBE (emuptr address, int size, uint32 value)
+{
+ uint8* realAddr = this->GetRealAddress (address);
+
+ if (size == 1)
+ {
+ *(uint8*) realAddr = value;
+ }
+
+ else if (size == 2)
+ {
+ uint16 value16 = value;
+ Canonical (value16);
+ *(uint16*) realAddr = value16;
+ }
+
+ else if (size == 4)
+ {
+#if UNALIGNED_LONG_ACCESS
+
+ Canonical (value);
+ *(uint32*) realAddr = value;
+
+#else
+
+ realAddr[0] = (uint8) (value >> 24);
+ realAddr[1] = (uint8) (value >> 16);
+ realAddr[2] = (uint8) (value >> 8);
+ realAddr[3] = (uint8) (value >> 0);
+
+#endif
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::StdRead
+// ---------------------------------------------------------------------------
+// Read registers using the routines in maccess.h
+
+uint32 EmRegs::StdRead (emuptr address, int size)
+{
+ uint8* realAddr = this->GetRealAddress (address);
+
+ if (size == 1)
+ return EmMemDoGet8 (realAddr);
+
+ if (size == 2)
+ return EmMemDoGet16 (realAddr);
+
+ return EmMemDoGet32 (realAddr);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::StdWrite
+// ---------------------------------------------------------------------------
+// Write registers using the routines in maccess.h
+
+void EmRegs::StdWrite (emuptr address, int size, uint32 value)
+{
+ uint8* realAddr = this->GetRealAddress (address);
+
+ if (size == 1)
+ EmMemDoPut8 (realAddr, value);
+
+ else if (size == 2)
+ EmMemDoPut16 (realAddr, value);
+
+ else
+ EmMemDoPut32 (realAddr, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::ZeroRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs::ZeroRead (emuptr address, int size)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs::NullWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs::NullWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+ UNUSED_PARAM(value)
+
+ // Do nothing (for read-only registers).
+}
diff --git a/SrcShared/Hardware/EmRegs.h b/SrcShared/Hardware/EmRegs.h
new file mode 100644
index 0000000..1a48907
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs.h
@@ -0,0 +1,77 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs_h
+#define EmRegs_h
+
+#include <vector>
+
+class SessionFile;
+struct EmAddressBank;
+
+class EmRegs
+{
+ public:
+ EmRegs (void);
+ virtual ~EmRegs (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ void SetBankHandlers (EmAddressBank&);
+ virtual void SetSubBankHandlers (void) = 0;
+
+ virtual uint32 GetLong (emuptr address);
+ virtual uint32 GetWord (emuptr address);
+ virtual uint32 GetByte (emuptr address);
+ virtual void SetLong (emuptr address, uint32 value);
+ virtual void SetWord (emuptr address, uint32 value);
+ virtual void SetByte (emuptr address, uint32 value);
+ virtual int ValidAddress (emuptr address, uint32 size);
+ virtual uint8* GetRealAddress (emuptr address) = 0;
+ virtual emuptr GetAddressStart (void) = 0;
+ virtual uint32 GetAddressRange (void) = 0;
+
+ protected:
+ typedef uint32 (EmRegs::*ReadFunction) (emuptr address, int size);
+ typedef void (EmRegs::*WriteFunction) (emuptr address, int size, uint32 value);
+
+ void SetHandler (ReadFunction read,
+ WriteFunction write,
+ uint32 start, int count);
+
+ uint32 UnsupportedRead (emuptr address, int size);
+ uint32 StdRead (emuptr address, int size);
+ uint32 StdReadBE (emuptr address, int size);
+ uint32 ZeroRead (emuptr address, int size);
+
+ void UnsupportedWrite (emuptr address, int size, uint32 value);
+ void StdWrite (emuptr address, int size, uint32 value);
+ void StdWriteBE (emuptr address, int size, uint32 value);
+ void NullWrite (emuptr address, int size, uint32 value);
+
+ private:
+ typedef vector<ReadFunction> ReadFunctionList;
+ typedef vector<WriteFunction> WriteFunctionList;
+
+ ReadFunctionList fReadFunctions;
+ WriteFunctionList fWriteFunctions;
+};
+
+
+typedef vector<EmRegs*> EmRegsList;
+
+#endif /* EmRegs_h */
diff --git a/SrcShared/Hardware/EmRegs328.cpp b/SrcShared/Hardware/EmRegs328.cpp
new file mode 100644
index 0000000..0f33398
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328.cpp
@@ -0,0 +1,2803 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegs328.h"
+#include "EmRegs328Prv.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmHAL.h" // EmHAL
+#include "EmMemory.h" // gMemAccessFlags, EmMem_memcpy
+#include "EmPixMap.h" // SetSize, SetRowBytes, etc.
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmSession.h" // GetDevice
+#include "Hordes.h" // Hordes::IsOn
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // GetHostTime
+#include "PreferenceMgr.h" // Preference
+#include "SessionFile.h" // WriteHwrDBallType, etc.
+#include "UAE.h" // regs, SPCFLAG_INT
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "HwrMiscFlags.h" // hwrMiscFlagID1
+
+ // Some platform-specific -- yet fairly portable -- defines.
+ #define hwrTD1PortENoBacklight 0x80 // (H) high if no backlight present
+
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+/*
+ This file controls the emulation of the Dragonball registers.
+
+ As a subclass of EmRegs, EmRegs328 registers with EmBankRegs
+ for control of the memory range 0xFFFFF000 to 0xFFFFFB14. If
+ an application accesses a memory location in that range,
+ EmBankRegs calls on of the Set/GetLong/Word/Byte methods of
+ this class.
+
+ EmRegs328 provides handlers when particular memory addresses
+ are accessed. For instance, if the UART TX register is written
+ to, EmRegs328 will arrange for any data byte to be sent out
+ the host computer's serial port. If the UART RX register is
+ read, EmRegs328 will respond with any byte in the buffer that
+ contains data received from the host computer's serial port.
+
+ Not all Dragonball registers are emulated the same way as on
+ an actual device. Some registers control hardware that exists
+ on the device only, there being no analog on the host computer.
+ For those registers, simple handlers are installed that write
+ the specified value to the register and return that value later
+ when the register is read.
+
+ Other registers require extensive support. The UART registers
+ are examples of that, as the above text indicates.
+
+ In the Palm OS source code, the Dragonball registers are
+ represented by th HwrM68328Type data type. We use this same type
+ in Poser to provide the "backing memory" for the registers. That
+ is, if some emulated code writes to a Dragonball register, we
+ store that value in a variable of type HwrM68328Type.
+
+ (Note that there's really no guarantee that the compiler used to
+ build Poser will lay out the fields of HwrM68328Type in the same
+ way expected by the Palm OS. Poser has a mechanism for creating
+ buffers with fields that have the same layout as Palm OS-defined
+ structs (see EmPalmStructs.h). However, using that mechanism in
+ this module is deadly to performance. In particular, the Cycle
+ method is called after every opcode is executed, and making that
+ method go through the indirection and byteswapping required by
+ the EmPalmStructs facilities totally kills performance. In one
+ test, a Gremlins run increased from 1m 24s to 1m 56s, or by about
+ 30%. With targetted caching of the fields used in Cycle, we can
+ regain most of that performance. However, not all the performance
+ is regained, and the resulting code is not very maintainable.)
+*/
+
+ #define hwr328chipID328 0x33
+ #define hwr328maskID1H58B 0x30
+
+static const uint32 ADDRESS_MASK = 0x0000FFF0;
+
+#define PRINTF if (1) ; else LogAppendMsg
+
+// Values used to initialize the DragonBall registers.
+
+const HwrM68328Type kInitial68328RegisterValues =
+{
+ 0x0C, // Byte scr; // $000: System Control Register
+ { 0 }, // Byte ___filler0[0x004-0x001];
+
+ // The following ID stuff is not present on earlier chips (before ??)
+ hwr328chipID328, // Byte chipID; // $004: Chip ID Register
+ hwr328maskID1H58B, // Byte maskID; // $005: Mask ID Register
+ 0x00, // Word swID; // $006: Software ID Register
+ { 0 }, // Byte ___filler1[0x100-0x008];
+
+ 0x0000, // Word csAGroupBase; // $100: Chip Select Group A Base Register
+ 0x0000, // Word csBGroupBase; // $102: Chip Select Group B Base Register
+ 0x0000, // Word csCGroupBase; // $104: Chip Select Group C Base Register
+ 0x0000, // Word csDGroupBase; // $106: Chip Select Group D Base Register
+
+ 0x0000, // Word csAGroupMask; // $108: Chip Select Group A Mask Register
+ 0x0000, // Word csBGroupMask; // $10A: Chip Select Group B Mask Register
+ 0x0000, // Word csCGroupMask; // $10C: Chip Select Group C Mask Register
+ 0x0000, // Word csDGroupMask; // $10E: Chip Select Group D Mask Register
+
+ 0x00010006, // DWord csASelect0; // $110: Group A Chip Select 0 Register
+ 0x00010006, // DWord csASelect1; // $114: Group A Chip Select 1 Register
+ 0x00010006, // DWord csASelect2; // $118: Group A Chip Select 2 Register
+ 0x00010006, // DWord csASelect3; // $11C: Group A Chip Select 3 Register
+
+ 0x00000000, // DWord csBSelect0; // $120: Group B Chip Select 0 Register
+ 0x00000000, // DWord csBSelect1; // $124: Group B Chip Select 1 Register
+ 0x00000000, // DWord csBSelect2; // $128: Group B Chip Select 2 Register
+ 0x00000000, // DWord csBSelect3; // $12C: Group B Chip Select 3 Register
+
+ 0x00010006, // DWord csCSelect0; // $130: Group C Chip Select 0 Register
+ 0x00010006, // DWord csCSelect1; // $134: Group C Chip Select 1 Register
+ 0x00010006, // DWord csCSelect2; // $138: Group C Chip Select 2 Register
+ 0x00010006, // DWord csCSelect3; // $13C: Group C Chip Select 3 Register
+
+ 0x00000000, // DWord csDSelect0; // $140: Group D Chip Select 0 Register
+ 0x00000000, // DWord csDSelect1; // $144: Group D Chip Select 1 Register
+ 0x00000000, // DWord csDSelect2; // $148: Group D Chip Select 2 Register
+ 0x00000000, // DWord csDSelect3; // $14C: Group D Chip Select 3 Register
+
+ 0x0000, // Word csDebug; // $150: Chip Select debug register
+ { 0 }, // Byte ___filler2[0x200-0x152];
+
+ 0x2400, // Word pllControl; // $200: PLL Control Register
+ 0x0123, // Word pllFreqSel; // $202: PLL Frequency Select Register
+ 0x0000, // Word pllTest; // $204: PLL Test Register
+ { 0 }, // Byte __filler44;
+ 0x1F, // Byte pwrControl; // $207: Power Control Register
+
+ { 0 }, // Byte ___filler3[0x300-0x208];
+
+ 0x00, // Byte intVector; // $300: Interrupt Vector Register
+ { 0 }, // Byte ___filler4;
+ 0x0000, // Word intControl; // $302: Interrupt Control Register
+ 0x00FF, // Word intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ 0xFFFF, // Word intMaskLo; // $306: Interrupt Mask Register/LOW word
+ 0x00FF, // Word intWakeupEnHi; // $308: Interrupt Wakeup Enable Register
+ 0xFFFF, // Word intWakeupEnLo; // $30A: Interrupt Wakeup Enable Register
+ 0x0000, // Word intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ 0x0000, // Word intStatusLo; // $30E: Interrupt Status Register/LOW word
+ 0x0000, // Word intPendingHi; // $310: Interrupt Pending Register
+ 0x0000, // Word intPendingLo; // $312: Interrupt Pending Register
+
+ { 0 }, // Byte ___filler4a[0x400-0x314];
+
+ 0x00, // Byte portADir; // $400: Port A Direction Register
+ 0x00, // Byte portAData; // $401: Port A Data Register
+ { 0 }, // Byte ___filler5;
+ 0x00, // Byte portASelect; // $403: Port A Select Register
+
+ { 0 }, // Byte ___filler6[4];
+
+ 0x00, // Byte portBDir; // $408: Port B Direction Register
+ 0x00, // Byte portBData; // $409: Port B Data Register
+ { 0 }, // Byte ___filler7;
+ 0x00, // Byte portBSelect; // $40B: Port B Select Register
+
+ { 0 }, // Byte ___filler8[4];
+
+ 0x00, // Byte portCDir; // $410: Port C Direction Register
+ 0x00, // Byte portCData; // $411: Port C Data Register
+ { 0 }, // Byte ___filler9;
+ 0x00, // Byte portCSelect; // $413: Port C Select Register
+
+ { 0 }, // Byte ___filler10[4];
+
+ 0x00, // Byte portDDir; // $418: Port D Direction Register
+ 0x00, // Byte portDData; // $419: Port D Data Register
+ 0xFF, // Byte portDPullupEn; // $41A: Port D Pull-up Enable
+ { 0 }, // Byte ___filler11;
+ 0x00, // Byte portDPolarity; // $41C: Port D Polarity Register
+ 0x00, // Byte portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ { 0 }, // Byte ___filler12;
+ 0x00, // Byte portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ 0x00, // Byte portEDir; // $420: Port E Direction Register
+ 0x00, // Byte portEData; // $421: Port E Data Register
+ 0x80, // Byte portEPullupEn; // $422: Port E Pull-up Enable
+ 0x80, // Byte portESelect; // $423: Port E Select Register
+
+ { 0 }, // Byte ___filler14[4];
+
+ 0x00, // Byte portFDir; // $428: Port F Direction Register
+ 0x00, // Byte portFData; // $429: Port F Data Register
+ 0xFF, // Byte portFPullupEn; // $42A: Port F Pull-up Enable
+ 0xFF, // Byte portFSelect; // $42B: Port F Select Register
+
+ { 0 }, // Byte ___filler16[4];
+
+ 0x00, // Byte portGDir; // $430: Port G Direction Register
+ 0x00, // Byte portGData; // $431: Port G Data Register
+ 0xFF, // Byte portGPullupEn; // $432: Port G Pull-up Enable
+ 0xFF, // Byte portGSelect; // $433: Port G Select Register
+
+ { 0 }, // Byte ___filler18[4];
+
+ 0x00, // Byte portJDir; // $438: Port J Direction Register
+ 0x00, // Byte portJData; // $439: Port J Data Register
+ { 0 }, // Byte ___filler19;
+ 0x00, // Byte portJSelect; // $43B: Port J Select Register
+
+ { 0 }, // Byte ___filler19a[4];
+
+ 0x00, // Byte portKDir; // $440: Port K Direction Register
+ 0x00, // Byte portKData; // $441: Port K Data Register
+ 0x3F, // Byte portKPullupEn; // $442: Port K Pull-up Enable
+ 0x3F, // Byte portKSelect; // $443: Port K Select Register
+
+ { 0 }, // Byte ___filler21[4];
+
+ 0x00, // Byte portMDir; // $448: Port M Direction Register
+ 0x00, // Byte portMData; // $449: Port M Data Register
+ 0xFF, // Byte portMPullupEn; // $44A: Port M Pull-up Enable Register
+ 0x02, // Byte portMSelect; // $44B: Port M Select Register
+
+ { 0 }, // Byte ___filler22[4];
+
+ { 0 }, // Byte ___filler23[0x500-0x450];
+
+ 0x0000, // Word pwmControl; // $500: PWM Control Register
+ 0x0000, // Word pwmPeriod; // $502: PWM Period Register
+ 0x0000, // Word pwmWidth; // $504: PWM Width Register
+ 0x0000, // Word pwmCounter; // $506: PWM Counter
+
+ { 0 }, // Byte ___filler24[0x600-0x508];
+
+ 0x0000, // Word tmr1Control; // $600: Timer 1 Control Register
+ 0x0000, // Word tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ 0xFFFF, // Word tmr1Compare; // $604: Timer 1 Compare Register
+ 0x0000, // Word tmr1Capture; // $606: Timer 1 Capture Register
+ 0x0000, // Word tmr1Counter; // $608: Timer 1 Counter Register
+ 0x0000, // Word tmr1Status; // $60A: Timer 1 Status Register
+
+ 0x0000, // Word tmr2Control; // $60C: Timer 2 Control Register
+ 0x0000, // Word tmr2Prescaler; // $60E: Timer 2 Prescaler Register
+ 0xFFFF, // Word tmr2Compare; // $610: Timer 2 Compare Register
+ 0x0000, // Word tmr2Capture; // $612: Timer 2 Capture Register
+ 0x0000, // Word tmr2Counter; // $614: Timer 2 Counter Register
+ 0x0000, // Word tmr2Status; // $616: Timer 2 Status Register
+
+ 0x0000, // Word wdControl; // $618: Watchdog Control Register
+ 0x0000, // Word wdReference; // $61A: Watchdog Reference Register
+ 0x0000, // Word wdCounter; // $61C: Watchdog Counter
+
+ { 0 }, // Byte ___filler25[0x700-0x61E];
+
+ 0x0000, // Word spiSlave; // $700: SPI Slave Register
+
+ { 0 }, // Byte ___filler26[0x800-0x702];
+
+ 0x0000, // Word spiMasterData; // $800: SPI Master Data Register
+ 0x0000, // Word spiMasterControl; // $802: SPI Master Control Register
+
+ { 0 }, // Byte ___filler27[0x900-0x804];
+
+ 0x0000, // Word uControl; // $900: Uart Control Register
+ 0x003F, // Word uBaud; // $902: Uart Baud Control Register
+ 0x0000, // Word uReceive; // $904: Uart Receive Register
+ 0x0000, // Word uTransmit; // $906: Uart Transmit Register
+ 0x0000, // Word uMisc; // $908: Uart Miscellaneous Register
+
+ { 0 }, // Byte ___filler28[0xA00-0x90A];
+
+ 0x00000000, // DWord lcdStartAddr; // $A00: Screen Starting Address Register
+ { 0 }, // Byte ___filler29;
+ 0xFF, // Byte lcdPageWidth; // $A05: Virtual Page Width Register
+ { 0 }, // Byte ___filler30[2];
+ 0x03FF, // Word lcdScreenWidth; // $A08: Screen Width Register
+ 0x01FF, // Word lcdScreenHeight; // $A0A: Screen Height Register
+ { 0 }, // Byte ___filler31[0xA18-0xA0C];
+ 0x0000, // Word lcdCursorXPos; // $A18: Cursor X Position
+ 0x0000, // Word lcdCursorYPos; // $A1A: Cursor Y Position
+ 0x0101, // Word lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ { 0 }, // Byte ___filler32;
+ 0x7F, // Byte lcdBlinkControl; // $A1F: Blink Control Register
+ 0x00, // Byte lcdPanelControl; // $A20: Panel Interface Control Register
+ 0x00, // Byte lcdPolarity; // $A21: Polarity Config Register
+ 0x00, // Byte ___filler33;
+ 0x00, // Byte lcdACDRate; // $A23: ACD (M) Rate Control Register
+ 0x00, // Byte ___filler34;
+ 0x00, // Byte lcdPixelClock; // $A25: Pixel Clock Divider Register
+ 0x00, // Byte ___filler35;
+ 0x40, // Byte lcdClockControl; // $A27: Clocking Control Register
+ 0x00, // Byte ___filler36;
+ 0x3E, // Byte lcdLastBufferAddr; // $A29: Last Buffer Address Register
+ 0x00, // Byte ___filler37;
+ 0x3F, // Byte lcdOctetTermCount; // $A2B: Octet Terminal Count Register
+ 0x00, // Byte ___filler38;
+ 0x00, // Byte lcdPanningOffset; // $A2D: Panning Offset Register
+ { 0 }, // Byte ___filler39[3];
+ 0xB9, // Byte lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ 0x1073, // Word lcdGrayPalette; // $A32: Gray Palette Mapping Register
+ 0x00, // Byte lcdReserved; // $A34: Reserved
+
+ { 0 }, // Byte ___filler40[0xB00-0xA35];
+
+ 0x00000000, // DWord rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ 0x00000000, // DWord rtcAlarm; // $B04: RTC Alarm Register
+ 0x00000000, // DWord rtcReserved; // $B08: RTC Reserved
+ 0x0000, // Word rtcControl; // $B0C: RTC Control Register
+ 0x0000, // Word rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ 0x0000, // Word rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ 0x0000 // Word stopWatch; // $B12: Stopwatch Minutes
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::EmRegs328
+// ---------------------------------------------------------------------------
+
+EmRegs328::EmRegs328 (void) :
+ EmRegs (),
+ f68328Regs (),
+ fHotSyncButtonDown (0),
+ fTmr2CurrentMilliseconds (0),
+ fTmr2StartMilliseconds (0),
+ fKeyBits (0),
+ fLastTmr1Status (0),
+ fLastTmr2Status (0),
+ fPortDEdge (0),
+ fPortDDataCount (0),
+ fHour (0),
+ fMin (0),
+ fSec (0),
+ fTick (0),
+ fCycle (0),
+ fUART (NULL)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::~EmRegs328
+// ---------------------------------------------------------------------------
+
+EmRegs328::~EmRegs328 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegs328::Initialize (void)
+{
+ EmRegs::Initialize ();
+
+ fUART = new EmUARTDragonball (EmUARTDragonball::kUART_Dragonball, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegs328::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ f68328Regs = kInitial68328RegisterValues;
+
+ // Byteswap all the words in the Dragonball registers (if necessary).
+
+ Canonical (f68328Regs);
+ ByteswapWords (&f68328Regs, sizeof(f68328Regs));
+
+ fKeyBits = 0;
+ fLastTmr1Status = 0;
+ fLastTmr2Status = 0;
+ fPortDEdge = 0;
+ fPortDDataCount = 0;
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegs328::UARTStateChanged (sendTxData);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Save
+// ---------------------------------------------------------------------------
+
+void EmRegs328::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ StWordSwapper swapper1 (&f68328Regs, sizeof(f68328Regs));
+ f.WriteHwrDBallType (f68328Regs);
+ f.FixBug (SessionFile::kBugByteswappedStructs);
+
+ const long kCurrentVersion = 4;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+ s << fHotSyncButtonDown;
+ s << fLastTmr1Status;
+ s << fLastTmr2Status;
+ s << fPortDEdge;
+
+ // Added in version 2.
+
+ s << fKeyBits;
+
+ // Added in version 3.
+
+ s << fHour;
+ s << fMin;
+ s << fSec;
+ s << fTick;
+ s << fCycle;
+
+ // Added in version 4.
+
+ s << fPortDDataCount;
+
+ f.WriteDBallState (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Load
+// ---------------------------------------------------------------------------
+
+void EmRegs328::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ if (f.ReadHwrDBallType (f68328Regs))
+ {
+ // The Windows version of Poser 2.1d29 and earlier did not write
+ // out structs in the correct format. The fields of the struct
+ // were written out in Little-Endian format, not Big-Endian. To
+ // address this problem, the bug has been fixed, and a new field
+ // is added to the file format indicating that the bug has been
+ // fixed. With the new field (the "bug bit"), Poser can identify
+ // old files from new files and read them in accordingly.
+ //
+ // With the bug fixed, the .psf files should now be interchangeable
+ // across platforms (modulo other bugs...).
+
+ if (!f.IncludesBugFix (SessionFile::kBugByteswappedStructs))
+ {
+ Canonical (f68328Regs);
+ }
+ ByteswapWords (&f68328Regs, sizeof(f68328Regs));
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegs328::UARTStateChanged (sendTxData);
+
+ // Reset gMemAccessFlags.fProtect_SRAMSet
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csASelect1) & 0x0008) != 0;
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+ Chunk chunk;
+ if (f.ReadDBallState (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> fHotSyncButtonDown;
+ s >> fTmr2CurrentMilliseconds;
+ s >> fTmr2StartMilliseconds;
+ s >> fLastTmr1Status;
+ s >> fLastTmr2Status;
+ s >> fPortDEdge;
+ }
+
+ if (version >= 2)
+ {
+ s >> fKeyBits;
+ }
+
+ if (version >= 3)
+ {
+ s >> fHour;
+ s >> fMin;
+ s >> fSec;
+ s >> fTick;
+ s >> fCycle;
+ }
+
+ if (version >= 4)
+ {
+ s >> fPortDDataCount;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegs328::Dispose (void)
+{
+ delete fUART;
+ fUART = NULL;
+
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegs328::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdRead, StdWrite, scr);
+
+ INSTALL_HANDLER (StdRead, NullWrite, chipID);
+ INSTALL_HANDLER (StdRead, NullWrite, maskID);
+ INSTALL_HANDLER (StdRead, NullWrite, swID);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csAGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csBGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csCGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csDGroupBase);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csAGroupMask);
+ INSTALL_HANDLER (StdRead, StdWrite, csBGroupMask);
+ INSTALL_HANDLER (StdRead, StdWrite, csCGroupMask);
+ INSTALL_HANDLER (StdRead, StdWrite, csDGroupMask);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csASelect0);
+ INSTALL_HANDLER (StdRead, csASelect1Write, csASelect1);
+ INSTALL_HANDLER (StdRead, StdWrite, csASelect2);
+ INSTALL_HANDLER (StdRead, StdWrite, csASelect3);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect0);
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect1);
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect2);
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect3);
+
+ INSTALL_HANDLER (StdRead, csCSelect0Write, csCSelect0);
+ INSTALL_HANDLER (StdRead, csCSelect1Write, csCSelect1);
+ INSTALL_HANDLER (StdRead, StdWrite, csCSelect2);
+ INSTALL_HANDLER (StdRead, StdWrite, csCSelect3);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csDSelect0);
+ INSTALL_HANDLER (StdRead, StdWrite, csDSelect1);
+ INSTALL_HANDLER (StdRead, StdWrite, csDSelect2);
+ INSTALL_HANDLER (StdRead, StdWrite, csDSelect3);
+ INSTALL_HANDLER (StdRead, StdWrite, csDebug);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pllControl);
+ INSTALL_HANDLER (pllFreqSelRead, StdWrite, pllFreqSel);
+ INSTALL_HANDLER (StdRead, StdWrite, pllTest);
+ INSTALL_HANDLER (StdRead, StdWrite, pwrControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, intVector);
+ INSTALL_HANDLER (StdRead, StdWrite, intControl);
+ INSTALL_HANDLER (StdRead, intMaskHiWrite, intMaskHi);
+ INSTALL_HANDLER (StdRead, intMaskLoWrite, intMaskLo);
+ INSTALL_HANDLER (StdRead, StdWrite, intWakeupEnHi);
+ INSTALL_HANDLER (StdRead, StdWrite, intWakeupEnLo);
+ INSTALL_HANDLER (StdRead, intStatusHiWrite, intStatusHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intStatusLo);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingLo);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portADir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portAData);
+ INSTALL_HANDLER (StdRead, StdWrite, portASelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portBDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portBData);
+ INSTALL_HANDLER (StdRead, StdWrite, portBSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portCDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portCData);
+ INSTALL_HANDLER (StdRead, StdWrite, portCSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portDDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portDData);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPolarity);
+ INSTALL_HANDLER (StdRead, portDIntReqEnWrite, portDIntReqEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDIntEdge);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portEDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portEData);
+ INSTALL_HANDLER (StdRead, StdWrite, portEPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portESelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portFDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portFData);
+ INSTALL_HANDLER (StdRead, StdWrite, portFPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portFSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portGDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portGData);
+ INSTALL_HANDLER (StdRead, StdWrite, portGPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portGSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portJDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portJData);
+ INSTALL_HANDLER (StdRead, StdWrite, portJSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portKDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portKData);
+ INSTALL_HANDLER (StdRead, StdWrite, portKPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portKSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portMDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portMData);
+ INSTALL_HANDLER (StdRead, StdWrite, portMPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portMSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pwmControl);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmPeriod);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmWidth);
+ INSTALL_HANDLER (StdRead, NullWrite, pwmCounter);
+
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Control);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Prescaler);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Compare);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Capture);
+ INSTALL_HANDLER (StdRead, NullWrite, tmr1Counter);
+ INSTALL_HANDLER (tmr1StatusRead, tmr1StatusWrite, tmr1Status);
+
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Control);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Prescaler);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Compare);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Capture);
+ INSTALL_HANDLER (StdRead, NullWrite, tmr2Counter);
+ INSTALL_HANDLER (tmr2StatusRead, tmr2StatusWrite, tmr2Status);
+
+ INSTALL_HANDLER (StdRead, StdWrite, wdControl);
+ INSTALL_HANDLER (StdRead, StdWrite, wdReference);
+ INSTALL_HANDLER (StdRead, wdCounterWrite, wdCounter);
+
+ INSTALL_HANDLER (StdRead, StdWrite, spiSlave);
+ INSTALL_HANDLER (StdRead, StdWrite, spiMasterData);
+ INSTALL_HANDLER (StdRead, spiMasterControlWrite, spiMasterControl);
+
+ INSTALL_HANDLER (uartRead, uartWrite, uControl);
+ INSTALL_HANDLER (uartRead, uartWrite, uBaud);
+ INSTALL_HANDLER (uartRead, uartWrite, uReceive);
+ INSTALL_HANDLER (uartRead, uartWrite, uTransmit);
+ INSTALL_HANDLER (uartRead, uartWrite, uMisc);
+
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdStartAddr);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPageWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorXPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorYPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorWidthHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdBlinkControl);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPanelControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPolarity);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdACDRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPixelClock);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdClockControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdLastBufferAddr);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdOctetTermCount);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPanningOffset);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdFrameRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdGrayPalette);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdReserved);
+
+ INSTALL_HANDLER (rtcHourMinSecRead, StdWrite, rtcHourMinSec);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcAlarm);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcReserved);
+ INSTALL_HANDLER (StdRead, rtcControlWrite, rtcControl);
+ INSTALL_HANDLER (StdRead, rtcIntStatusWrite, rtcIntStatus);
+ INSTALL_HANDLER (StdRead, rtcIntEnableWrite, rtcIntEnable);
+ INSTALL_HANDLER (StdRead, StdWrite, stopWatch);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegs328::GetRealAddress (emuptr address)
+{
+ uint8* loc = ((uint8*) &f68328Regs) + (address - kMemoryStart);
+
+ return loc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegs328::GetAddressStart (void)
+{
+ return kMemoryStart;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::GetAddressRange (void)
+{
+ COMPILE_TIME_ASSERT (kMemorySize == 0x0B14);
+
+ return kMemorySize;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::Cycle
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+#if 0
+static int calibrated;
+static int increment;
+static int timesCalled;
+static uint32 startingTime;
+
+static void PrvCalibrate (uint16 tmrCompare)
+{
+ // Calibrate the the value by which we increment the counter.
+ // The counter is set up so that it times out after 10 milliseconds
+ // so that it can increment the Palm OS's tick counter 100 times
+ // a second. We would like tmrCounter to surpass tmrCompare
+ // after 10 milliseconds. So figure out by how much we need to
+ // increment it in order for that to happen.
+
+ // If timer is disabled; reset calibration.
+
+ if (tmrCompare == 0xFFFF)
+ {
+ startingTime = 0;
+ }
+
+ // If timer is enabled, restart calibration.
+
+ else if (startingTime == 0)
+ {
+ startingTime = Platform::GetMilliseconds();
+ timesCalled = 0;
+ increment = 1;
+ }
+
+ // If calibration is started, continue it.
+
+ else
+ {
+ timesCalled++;
+
+ uint32 now = Platform::GetMilliseconds();
+ if (now - startingTime > 100)
+ {
+ calibrated = true;
+ increment = tmrCompare / (timesCalled / 10);
+ }
+ }
+}
+#endif
+
+void EmRegs328::Cycle (Bool sleeping)
+{
+#if 0
+ // Cycle is *very* sensitive to timing issue. With this section
+ // of code, a Gremlins run can slow down by 5%.
+ if (!calibrated)
+ {
+ ::PrvCalibrate (READ_REGISTER (tmr2Compare));
+ }
+#else
+ #if _DEBUG
+ #define increment 20
+ #else
+ #define increment 4
+ #endif
+#endif
+
+ // Determine whether timer 2 is enabled.
+
+ if ((READ_REGISTER (tmr2Control) & hwr328TmrControlEnable) != 0)
+ {
+ // If so, increment the timer.
+
+ WRITE_REGISTER (tmr2Counter, READ_REGISTER (tmr2Counter) + (sleeping ? 1 : increment));
+
+ // Determine whether the timer has reached the specified count.
+
+ if (sleeping || READ_REGISTER (tmr2Counter) > READ_REGISTER (tmr2Compare))
+ {
+ // Flag the occurrence of the successful comparison.
+
+ WRITE_REGISTER (tmr2Status, READ_REGISTER (tmr2Status) | hwr328TmrStatusCompare);
+
+ // If the Free Run/Restart flag is not set, clear the counter.
+
+ if ((READ_REGISTER (tmr2Control) & hwr328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr2Counter, 0);
+ }
+
+ // If the timer interrupt is enabled, post an interrupt.
+
+ if ((READ_REGISTER (tmr2Control) & hwr328TmrControlEnInterrupt) != 0)
+ {
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwr328IntLoTimer2);
+ EmRegs328::UpdateInterrupts ();
+ }
+ }
+ }
+
+ if ((fCycle += increment) > READ_REGISTER (tmr2Compare))
+ {
+ fCycle = 0;
+
+ if (++fTick >= 100)
+ {
+ fTick = 0;
+
+ if (++fSec >= 60)
+ {
+ fSec = 0;
+
+ if (++fMin >= 60)
+ {
+ fMin = 0;
+
+ if (++fHour >= 24)
+ {
+ fHour = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::CycleSlowly
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+void EmRegs328::CycleSlowly (Bool sleeping)
+{
+ UNUSED_PARAM(sleeping)
+
+ // See if a hard button is pressed.
+
+ EmAssert (gSession);
+ if (gSession->HasButtonEvent ())
+ {
+ EmButtonEvent event = gSession->GetButtonEvent ();
+ if (event.fButton == kElement_CradleButton)
+ {
+ EmRegs328::HotSyncEvent (event.fButtonIsDown);
+ }
+ else
+ {
+ EmRegs328::ButtonEvent (event.fButton, event.fButtonIsDown);
+ }
+ }
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegs328::UpdateUARTState (false);
+
+ // Check to see if the RTC alarm is ready to go off. First see
+ // if the RTC is enabled, and that the alarm event isn't already
+ // registered (the latter check is just an optimization).
+
+ if ((READ_REGISTER (rtcIntEnable) & hwr328RTCIntEnableAlarm) != 0 &&
+ (READ_REGISTER (rtcIntStatus) & hwr328RTCIntStatusAlarm) == 0)
+ {
+ uint32 rtcAlarm = READ_REGISTER (rtcAlarm);
+
+ long almHour = (rtcAlarm & hwr328RTCAlarmHoursMask) >> hwr328RTCAlarmHoursOffset;
+ long almMin = (rtcAlarm & hwr328RTCAlarmMinutesMask) >> hwr328RTCAlarmMinutesOffset;
+ long almSec = (rtcAlarm & hwr328RTCAlarmSecondsMask) >> hwr328RTCAlarmSecondsOffset;
+ long almInSeconds = (almHour * 60 * 60) + (almMin * 60) + almSec;
+
+ long nowHour;
+ long nowMin;
+ long nowSec;
+ ::GetHostTime (&nowHour, &nowMin, &nowSec);
+ long nowInSeconds = (nowHour * 60 * 60) + (nowMin * 60) + nowSec;
+
+ if (almInSeconds <= nowInSeconds)
+ {
+ WRITE_REGISTER (rtcIntStatus, READ_REGISTER (rtcIntStatus) | hwr328RTCIntStatusAlarm);
+ EmRegs328::UpdateRTCInterrupts ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::TurnSoundOff
+// ---------------------------------------------------------------------------
+
+void EmRegs328::TurnSoundOff (void)
+{
+ uint16 pwmControl = READ_REGISTER (pwmControl);
+ WRITE_REGISTER (pwmControl, pwmControl & ~hwr328PWMControlEnable);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::ResetTimer
+// ---------------------------------------------------------------------------
+
+void EmRegs328::ResetTimer (void)
+{
+ WRITE_REGISTER (tmr2Counter, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::ResetRTC
+// ---------------------------------------------------------------------------
+
+void EmRegs328::ResetRTC (void)
+{
+ fHour = 15;
+ fMin = 0;
+ fSec = 0;
+ fTick = 0;
+ fCycle = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmRegs328::GetInterruptLevel (void)
+{
+ uint16 intStatusHi = READ_REGISTER (intStatusHi);
+ uint16 intStatusLo = READ_REGISTER (intStatusLo);
+
+ // Level 7 = IRQ7.
+
+ if ((intStatusHi & hwr328IntHiNMI) != 0)
+ return 7;
+
+ // Level 6 = SPIS, TMR1, IRQ6.
+
+ if ((intStatusHi & (hwr328IntHiTimer1 | hwr328IntHiSPIS | hwr328IntHiIRQ6)) != 0)
+ return 6;
+
+ // Level 5 = PEN.
+
+ if ((intStatusHi & hwr328IntHiPen) != 0)
+ return 5;
+
+ // Level 4 = SPIM, TMR2, UART, WDT, RTC, KB, PWM, INT0 - INT7.
+
+ if ((intStatusLo & ( hwr328IntLoAllKeys |
+ hwr328IntLoPWM |
+ hwr328IntLoKbd |
+ // hwr328IntLoLCDC |
+ hwr328IntLoRTC |
+ hwr328IntLoWDT |
+ hwr328IntLoTimer2 |
+ hwr328IntLoSPIM)) != 0)
+ return 4;
+
+ // Level 3 = IRQ3.
+
+ if ((intStatusHi & hwr328IntHiIRQ3) != 0)
+ return 3;
+
+ // Level 2 = IRQ2.
+
+ if ((intStatusHi & hwr328IntHiIRQ2) != 0)
+ return 2;
+
+ // Level 1 = IRQ1.
+
+ if ((intStatusHi & hwr328IntHiIRQ1) != 0)
+ return 1;
+
+ // Level 0.
+
+ return -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetInterruptBase
+// ---------------------------------------------------------------------------
+
+int32 EmRegs328::GetInterruptBase (void)
+{
+ return READ_REGISTER (intVector) & 0xF8;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328::GetLCDHasFrame (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegs328::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+ int rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ int height = READ_REGISTER (lcdScreenHeight) + 1;
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegs328::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x01);
+ int32 width = READ_REGISTER (lcdScreenWidth) + 1;
+ int32 height = READ_REGISTER (lcdScreenHeight) + 1;
+ int32 rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+
+ info.fLeftMargin = READ_REGISTER (lcdPanningOffset) & 0x0F;
+
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegs328::GetUARTDevice (int /*uartNum*/)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetDynamicHeapSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegs328::GetDynamicHeapSize (void)
+{
+ uint32 result = 0;
+
+ uint32 csCSelect0 = READ_REGISTER (csCSelect0) & ADDRESS_MASK;
+ uint32 csCSelect1 = READ_REGISTER (csCSelect1) & ADDRESS_MASK;
+
+ if (csCSelect0 == 0x0000 && csCSelect1 == 0x0000)
+ {
+ result = 0 * 1024L;
+ }
+ else if (csCSelect0 == 0x0070 && csCSelect1 == 0x0000)
+ {
+ result = 32 * 1024L;
+ }
+ else if (csCSelect0 == 0x00F0 && csCSelect1 == 0x0000)
+ {
+ result = 64 * 1024L;
+ }
+ else if (csCSelect0 == 0x0070 && csCSelect1 == 0x0070)
+ {
+ // This one's odd, but the Symbol seems to (temporarily)
+ // set up this configuration when running with 2Meg of RAM.
+ result = 96 * 1024L;
+ }
+ else if (csCSelect0 == 0x00F0 && csCSelect1 == 0x0070)
+ {
+ result = 96 * 1024L;
+ }
+ else if (csCSelect0 == 0x01F0 && csCSelect1 == 0x0000)
+ {
+ result = 128 * 1024L;
+ }
+ else if (csCSelect0 == 0x03F0 && csCSelect1 == 0x0000)
+ {
+ result = 256 * 1024L;
+ }
+ else
+ {
+ EmAssert (false);
+ }
+
+ if (!ChipSelectsConfigured())
+ {
+ result = 16 * 1024L * 1024L;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegs328::GetROMSize (void)
+{
+ uint32 result = 2 * 1024L * 1024L;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetROMBaseAddress
+// ---------------------------------------------------------------------------
+
+emuptr EmRegs328::GetROMBaseAddress (void)
+{
+ if (!this->ChipSelectsConfigured())
+ {
+ return 0xFFFFFFFF;
+ }
+
+ return 0x10C00000; // use known value
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::ChipSelectsConfigured
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328::ChipSelectsConfigured (void)
+{
+ return READ_REGISTER (csAGroupBase) & 0x0001;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetSystemClockFrequency
+// ---------------------------------------------------------------------------
+
+int32 EmRegs328::GetSystemClockFrequency (void)
+{
+ uint16 pllControl = READ_REGISTER (pllControl);
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel);
+
+ uint16 PC = (pllFreqSel & 0x00FF);
+ uint16 QC = (pllFreqSel & 0x0F00) >> 8;
+
+ uint32 result = 32768L * (14 * (PC + 1) + QC + 1);
+
+ // Divide by the system clock scaler, if needed.
+
+ switch (pllControl & 0x0F00)
+ {
+ case hwr328PLLControlSysVCODiv2:
+ result /= 2;
+ break;
+
+ case hwr328PLLControlSysVCODiv4:
+ result /= 4;
+ break;
+
+ case hwr328PLLControlSysVCODiv8:
+ result /= 8;
+ break;
+
+ case hwr328PLLControlSysVCODiv16:
+ result /= 16;
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetCanStop
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328::GetCanStop (void)
+{
+ // Make sure Timer 2 is enabled or the RTC interrupt is enabled.
+
+ if ((READ_REGISTER (tmr2Control) & hwr328TmrControlEnable) != 0)
+ return true;
+
+ if ((READ_REGISTER (rtcIntEnable) & hwr328RTCIntEnableAlarm) != 0)
+ return true;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetAsleep
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328::GetAsleep (void)
+{
+ return ((READ_REGISTER (pllControl) & hwr328PLLControlDisable) != 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegs328::GetPortInputValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'D')
+ {
+ result = this->GetPortInternalValue (port);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegs328::GetPortInternalValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'C')
+ {
+ // This makes the power on key work. If the signal is not asserted, the
+ // unit will not transition between asleep and awake (cf. HwrSleep, HwrWake).
+
+ result |= hwr328PortCNMI;
+ }
+
+ else if (port == 'D')
+ {
+ // If the ID_DETECT pin is asserted, load the data lines with the
+ // hardware ID.
+
+ if (EmRegs328::IDDetectAsserted ())
+ {
+ result |= EmRegs328::GetHardwareID ();
+ }
+
+ // Otherwise, load the lines with keyboard information.
+
+ else
+ {
+ // Get the INT bits that need to be set.
+
+ result |= this->GetKeyBits ();
+ }
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::PortDataChanged
+// ---------------------------------------------------------------------------
+
+void EmRegs328::PortDataChanged (int port, uint8, uint8 newValue)
+{
+ if (port == 'D')
+ {
+ // Clear the interrupt bits that are having a 1 written to them.
+ // Only clear them if they're configured as edge-senstive.
+
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+ PRINTF ("EmRegs328::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+ PRINTF ("EmRegs328::PortDataChanged (D): portDIntEdge = 0x%02lX", (uint32) (uint8) portDIntEdge);
+ PRINTF ("EmRegs328::PortDataChanged (D): newValue = 0x%02lX", (uint32) (uint8) newValue);
+
+ fPortDEdge &= ~(newValue & portDIntEdge);
+
+ PRINTF ("EmRegs328::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegs328::UpdatePortDInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::pllFreqSelRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::pllFreqSelRead (emuptr address, int size)
+{
+ // Simulate the rising and falling of the CLK32 signal so that functions
+ // like HwrPreRAMInit, HwrShutDownPLL, PrvSetPLL, and PrvShutDownPLL
+ // won't hang.
+
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel) ^ 0x8000;
+ WRITE_REGISTER (pllFreqSel, pllFreqSel);
+
+ // Finish up by doing a standard read.
+
+ return EmRegs328::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::portXDataRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::portXDataRead (emuptr address, int)
+{
+ // The value read can come from three different places:
+ //
+ // - the value what was written to the data register
+ // - any dedicated inputs
+ // - any GPIO inputs
+ //
+ // The value returned depends on the settings of the SEL and DIR
+ // registers. So let's get those settings, the values from the three
+ // input sources, and build up a return value based on those.
+
+ int port = GetPort (address);
+
+ uint8 sel = StdRead (address + 2, 1);
+ uint8 dir = StdRead (address - 1, 1);
+ uint8 output = StdRead (address + 0, 1);
+ uint8 input = EmHAL::GetPortInputValue (port);
+ uint8 intFn = EmHAL::GetPortInternalValue (port);
+
+ uint8 xsel = sel;
+ uint8 xdir = dir;
+ uint8 xoutput = output;
+ uint8 xinput = input;
+ uint8 xintFn = intFn;
+
+ if (port == 'D')
+ {
+ sel = 0xFF; // No "select" bit in low nybble, so set for IO values.
+
+ // The system will poll portD twice in KeyBootKeys to see
+ // if any keys are down. Wait at least that long before
+ // letting up any boot keys maintained by the session. When we
+ // do call ReleaseBootKeys, set our counter to -1 as a flag not
+ // to call it any more.
+
+ if (fPortDDataCount != 0xFFFFFFFF && ++fPortDDataCount >= 2 * 2)
+ {
+ fPortDDataCount = 0xFFFFFFFF;
+ gSession->ReleaseBootKeys ();
+ }
+ }
+
+ // Use the internal chip function bits if the "sel" bits are zero.
+
+ intFn &= ~sel;
+
+ // Otherwise, use the I/O bits.
+
+ output &= sel & dir; // Use the output bits if the "dir" is one.
+ input &= sel & ~dir; // Use the input bits if the "dir" is zero.
+
+ // Assert that there are no overlaps.
+
+ EmAssert ((output & input) == 0);
+ EmAssert ((output & intFn) == 0);
+ EmAssert ((input & intFn) == 0);
+
+ // Mush everything together.
+
+ uint8 result = output | input | intFn;
+
+ // If this is port D, flip the bits if the POLARITY register says to.
+ // (!!! Does this inversion apply only to input bits? That is, the
+ // bits where the "dir" register has 0 bits?)
+
+ if (0 && port == 'D')
+ {
+ uint8 polarity = READ_REGISTER (portDPolarity);
+ PRINTF ("EmRegs328::portXDataRead: polarity = 0x%02lX", (uint32) polarity);
+ result ^= polarity;
+ }
+
+ PRINTF ("EmRegs328::port%cDataRead: sel dir output input intFn result", (char) port);
+ PRINTF ("EmRegs328::port%cDataRead: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (char) port, (uint32) xsel, (uint32) xdir, (uint32) xoutput, (uint32) xinput, (uint32) xintFn, (uint32) result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::tmr1StatusRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::tmr1StatusRead (emuptr address, int size)
+{
+ uint16 tmr1Counter = READ_REGISTER (tmr1Counter) + 16;
+ uint16 tmr1Compare = READ_REGISTER (tmr1Compare);
+ uint16 tmr1Control = READ_REGISTER (tmr1Control);
+
+ // Increment the timer.
+
+ WRITE_REGISTER (tmr1Counter, tmr1Counter);
+
+ // If the timer has passed the specified value...
+
+ if ( (tmr1Counter - tmr1Compare) < 16 )
+ {
+ // Set the flag saying the timer timed out.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status) | hwr328TmrStatusCompare;
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ // If it's not a free-running timer, reset it to zero.
+
+ if ((tmr1Control & hwr328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr1Counter, 0);
+ }
+ }
+
+ // Remember this guy for later (see EmRegs328::tmr1StatusWrite())
+
+ fLastTmr1Status |= READ_REGISTER (tmr1Status);
+
+ // Finish up by doing a standard read.
+
+ return EmRegs328::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::tmr2StatusRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::tmr2StatusRead (emuptr address, int size)
+{
+#if 0 // (Greg doesn't do this for Timer 2...I wonder why)
+
+ /*
+ ram_rom.cpp: DBReg::tmr2StatusRead: Hmm, I don't update the TMR2 count
+ value. As with everything else that's missing in my DragonBall
+ emulation, it's probably because I never found anything that needed it.
+ If you know otherwise, by all means implement it. Also, the magic value
+ of 16 counts per status read seemed to be about right for the programmed
+ timer 1 frequency. It isn't likely to be right for timer 2.
+
+ -- Greg
+ */
+
+ uint16 tmr2Counter = READ_REGISTER (tmr2Counter) + 16;
+ uint16 tmr2Compare = READ_REGISTER (tmr2Compare);
+ uint16 tmr2Control = READ_REGISTER (tmr2Control);
+
+ // Increment the timer.
+
+ WRITE_REGISTER (tmr2Counter, tmr2Counter);
+
+ // If the timer has passed the specified value...
+
+ if ( (tmr2Counter - tmr2Compare) < 16 )
+ {
+ // Set the flag saying the timer timed out.
+
+ uint16 tmr2Status = READ_REGISTER (tmr1Status) | hwr328TmrStatusCompare;
+ WRITE_REGISTER (tmr2Status, tmr2Status);
+
+ // If it's not a free-running timer, reset it to zero.
+
+ if ( (tmr2Control & hwr328TmrControlFreeRun) == 0 )
+ WRITE_REGISTER (tmr2Counter, 0);
+ }
+#endif
+
+ fLastTmr2Status |= READ_REGISTER (tmr2Status); // remember this guy for later (see EmRegs328::tmr2StatusWrite())
+
+ // Finish up by doing a standard read.
+
+ return EmRegs328::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::uartRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::uartRead (emuptr address, int size)
+{
+ // If this is a full read, get the next byte from the FIFO.
+
+ Bool refreshRxData = (address == addressof (uReceive)) && (size == 2);
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegs328::UpdateUARTState (refreshRxData);
+
+ // Finish up by doing a standard read.
+
+ return EmRegs328::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::rtcHourMinSecRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegs328::rtcHourMinSecRead (emuptr address, int size)
+{
+ // Get the desktop machine's time.
+
+ long hour, min, sec;
+
+ if (Hordes::IsOn ())
+ {
+ hour = fHour;
+ min = fMin;
+ sec = fSec;
+ }
+ else
+ {
+ ::GetHostTime (&hour, &min, &sec);
+ }
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcHourMinSec, (hour << hwr328RTCHourMinSecHoursOffset)
+ | (min << hwr328RTCHourMinSecMinutesOffset)
+ | (sec << hwr328RTCHourMinSecSecondsOffset));
+
+ // Finish up by doing a standard read.
+
+ return EmRegs328::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::csASelect1Write
+// ---------------------------------------------------------------------------
+
+void EmRegs328::csASelect1Write (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Check its new state and update our ram-protect flag.
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csASelect1) & 0x0008) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::csCSelect0Write
+// ---------------------------------------------------------------------------
+
+void EmRegs328::csCSelect0Write (emuptr address, int size, uint32 value)
+{
+ uint32 csCSelect0 = READ_REGISTER (csCSelect0);
+
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csCSelect0 & ADDRESS_MASK) != (READ_REGISTER (csCSelect0) & ADDRESS_MASK))
+ {
+ EmAssert (gSession);
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::csCSelect1Write
+// ---------------------------------------------------------------------------
+
+void EmRegs328::csCSelect1Write (emuptr address, int size, uint32 value)
+{
+ uint32 csCSelect1 = READ_REGISTER (csCSelect1);
+
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csCSelect1 & ADDRESS_MASK) != (READ_REGISTER (csCSelect1) & ADDRESS_MASK))
+ {
+ EmAssert (gSession);
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::intMaskHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::intMaskHiWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::intMaskLoWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::intMaskLoWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::intStatusHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::intStatusHiWrite (emuptr address, int size, uint32 value)
+{
+ // IRQ1, IRQ2, IRQ3, IRQ6 and IRQ7 are cleared by writing to their
+ // respective status bits. We handle those there. Since there are
+ // no interrupt status bits like this in intStatusLo, we don't need
+ // a handler for that register; we only handle intStatusHi.
+
+ // Even though this is a 16-bit register as defined by the Palm headers,
+ // it's a 32-bit register according to Dragonball docs, and is in fact
+ // accessed that way in the kernal files (cf. HwrIRQ4Handler). In those
+ // cases, we're still only interested in access to the IRQ# bits, so we
+ // can turn 4-byte accesses into 2-byte accesses.
+
+ if (size == 4)
+ value >>= 16;
+
+ // Take into account the possibility of 1-byte accesses, too. If we're
+ // accessing the upper byte, just return. If we're accessing the lower
+ // byte, we can treat it as a 2-byte access.
+
+ else if (size == 1 && address == addressof (intStatusHi))
+ return;
+
+ // Now we can treat the rest of this function as a word-write to intStatusHi.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ // For each interrupt:
+ // If we're writing to that interrupt's status bit and its edge bit is set:
+ // - clear the interrupt's pending bit
+ // - respond to the new interrupt state.
+
+ #undef CLEAR_PENDING_INTERRUPT
+ #define CLEAR_PENDING_INTERRUPT(edge, irq) \
+ if ( (READ_REGISTER (intControl) & edge) && (value & (irq)) ) \
+ { \
+ intPendingHi &= ~(irq); \
+ }
+
+ CLEAR_PENDING_INTERRUPT (hwr328IntCtlEdge1, hwr328IntHiIRQ1);
+ CLEAR_PENDING_INTERRUPT (hwr328IntCtlEdge2, hwr328IntHiIRQ2);
+ CLEAR_PENDING_INTERRUPT (hwr328IntCtlEdge3, hwr328IntHiIRQ3);
+ CLEAR_PENDING_INTERRUPT (hwr328IntCtlEdge6, hwr328IntHiIRQ6);
+
+ // IRQ7 is not edge-programmable, so clear it if we're merely writing to it.
+
+ if (value & hwr328IntHiNMI)
+ {
+ intPendingHi &= ~(hwr328IntHiNMI);
+ }
+
+ // If we're emulating the user pressing the hotsync button, make sure the
+ // interrupt stays asserted. (!!! Should we use the same technique for
+ // other buttons, too? It doesn't seem to be needed right now, but doing
+ // that may more closely mirror the hardware.)
+
+ if (fHotSyncButtonDown)
+ {
+ intPendingHi |= hwr328IntHiIRQ1;
+ }
+ else
+ {
+ intPendingHi &= ~hwr328IntHiIRQ1;
+ }
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::portXDataWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::portXDataWrite (emuptr address, int size, uint32 value)
+{
+ // Get the old value before updating it.
+
+ uint8 oldValue = StdRead (address, size);
+
+ // Take a snapshot of the line driver states.
+
+ Bool driverStates[kUARTEnd];
+ EmHAL::GetLineDriverStates (driverStates);
+
+ // Now update the value with a standard write.
+
+ StdWrite (address, size, value);
+
+ // Let anyone know that it's changed.
+
+ int port = GetPort (address);
+ PRINTF ("EmRegs328::port%cDataWrite: oldValue = 0x%02lX", (char) port, (uint32) (uint8) oldValue);
+ PRINTF ("EmRegs328::port%cDataWrite: newValue = 0x%02lX", (char) port, (uint32) (uint8) value);
+
+ EmHAL::PortDataChanged (port, oldValue, value);
+
+ // Respond to any changes in the line driver states.
+
+ EmHAL::CompareLineDriverStates (driverStates);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::portDIntReqEnWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::portDIntReqEnWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Set the new interrupt state.
+
+ EmRegs328::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::tmr1StatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::tmr1StatusWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ EmAssert (size == 2); // This function's a hell of a lot easier to write if
+ // we assume only full-register access.
+
+ // Get the current value.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status);
+
+ // If the user had previously read the status bits while they
+ // were set, then it's OK for them to be clear now. Otherwise,
+ // we have to merge any set status bits back in.
+
+ tmr1Status &= value | ~fLastTmr1Status; // fLastTmr1Status was set in EmRegs328::tmr1StatusRead()
+
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ fLastTmr1Status = 0;
+ if ((tmr1Status & hwr328TmrStatusCompare) == 0)
+ {
+ uint16 intPendingHi = READ_REGISTER (intPendingHi) & ~hwr328IntHiTimer1;
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::tmr2StatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::tmr2StatusWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ EmAssert (size == 2); // This function's a hell of a lot easier to write if
+ // we assume only full-register access.
+
+ // Get the current value.
+
+ uint16 tmr2Status = READ_REGISTER (tmr2Status);
+
+ // If the user had previously read the status bits while they
+ // were set, then it's OK for them to be clear now. Otherwise,
+ // we have to merge any set status bits back in.
+
+ tmr2Status &= value | ~fLastTmr2Status; // fLastTmr2Status was set in EmRegs328::tmr2StatusRead()
+
+ WRITE_REGISTER (tmr2Status, tmr2Status);
+
+ fLastTmr2Status = 0;
+ if ( (tmr2Status & hwr328TmrStatusCompare) == 0 )
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwr328IntLoTimer2;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::wdCounterWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::wdCounterWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+ UNUSED_PARAM(value)
+
+ // Always set it to zero (a write to this register always resets it).
+
+ WRITE_REGISTER (wdCounter, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::spiMasterControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::spiMasterControlWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Get the current value.
+
+ uint16 spiMasterControl = READ_REGISTER (spiMasterControl);
+
+ // Check to see if data exchange and interrupts are enabled.
+
+ #define BIT_MASK (hwr328SPIMControlExchange | hwr328SPIMControlIntEnable)
+ if ((spiMasterControl & BIT_MASK) != 0)
+ {
+ // If so, assert the interrupt and clear the exchange bit.
+
+ spiMasterControl |= hwr328SPIMControlIntStatus;
+ spiMasterControl &= ~hwr328SPIMControlExchange;
+
+ WRITE_REGISTER (spiMasterControl, spiMasterControl);
+
+/*
+ // If we wanted digitizer data, load it into the SPIM data register.
+
+ switch (READ_REGISTER (portFData) & hwrTD1PortFPanelMask)
+ {
+ case (hwrTD1PortFPanelCfgXMeas):
+ WRITE_REGISTER (spiMasterData, (0xFF - Hardware::fgPen_HorzLocation) * 2);
+ break;
+
+ case (hwrTD1PortFPanelCfgYMeas):
+ WRITE_REGISTER (spiMasterData, (0xFF - Hardware::fgPen_VertLocation) * 2);
+ break;
+ }
+*/
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::uartWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::uartWrite(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // If this write included the TX_DATA field, signal that it needs to
+ // be transmitted.
+
+ Bool sendTxData =
+ ((address == addressof (uTransmit)) && (size == 2)) ||
+ ((address == addressof (uTransmit) + 1) && (size == 1));
+
+ // React to any changes.
+
+ EmRegs328::UARTStateChanged (sendTxData);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::lcdRegisterWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::lcdRegisterWrite(emuptr address, int size, uint32 value)
+{
+ // First, get the old value in case we need to see what changed.
+
+ uint32 oldValue = EmRegs328::StdRead (address, size);
+
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Note what changed.
+
+ if (address == addressof (lcdScreenWidth))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdScreenHeight))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPanelControl))
+ {
+ if (((value ^ oldValue) & hwr328LcdPanelControlGrayScale) != 0)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+ else if (address == addressof (lcdStartAddr))
+ {
+ // Make sure the low-bit is always zero.
+
+ uint32 lcdStartAddr = READ_REGISTER (lcdStartAddr) & 0xFFFFFFFE;
+ WRITE_REGISTER (lcdStartAddr, lcdStartAddr);
+
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPageWidth))
+ {
+ if (value != oldValue)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::rtcControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::rtcControlWrite(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::rtcIntStatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::rtcIntStatusWrite(emuptr address, int size, uint32 value)
+{
+ // Status bits are cleared by writing ones to them.
+
+ // If we're doing a byte-write to the upper byte, shift the byte
+ // so that we can treat the operation as a word write. If we're
+ // doing a byte-write to the lower byte, this extension will happen
+ // automatically.
+
+ if (address == addressof (rtcIntStatus) && size == 1)
+ value <<= 8;
+
+ // Get the current value.
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+
+ // Clear the requested bits.
+
+ rtcIntStatus &= ~value;
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcIntStatus, rtcIntStatus);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::rtcIntEnableWrite
+// ---------------------------------------------------------------------------
+
+void EmRegs328::rtcIntEnableWrite(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegs328::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::ButtonEvent
+// ---------------------------------------------------------------------------
+// Handles a Palm device button event by updating the appropriate registers.
+
+void EmRegs328::ButtonEvent (SkinElementType button, Bool buttonIsDown)
+{
+ uint16 bitNumber = this->ButtonToBits (button);
+
+ // Get the bits that should have been set with the previous set
+ // of pressed keys. We use this old value to update the port D interrupts.
+
+ uint8 oldBits = this->GetKeyBits ();
+
+ // Update the set of keys that are currently pressed.
+
+ if (buttonIsDown)
+ {
+ fKeyBits |= bitNumber; // Remember the key bit
+ }
+ else
+ {
+ fKeyBits &= ~bitNumber; // Forget the key bit
+ }
+
+ // Now get the new set of bits that should be set.
+
+ uint8 newBits = this->GetKeyBits ();
+
+ PRINTF ("EmRegs328::ButtonEvent: fKeyBits = 0x%04lX", (uint32) fKeyBits);
+ PRINTF ("EmRegs328::ButtonEvent: oldBits = 0x%02lX", (uint32) oldBits);
+ PRINTF ("EmRegs328::ButtonEvent: newBits = 0x%02lX", (uint32) newBits);
+
+ // Set the interrupt bits for the bits that went from off to on.
+ // These get cleared when portDData is written to.
+
+ fPortDEdge |= newBits & ~oldBits;
+
+ PRINTF ("EmRegs328::ButtonEvent: fPortDEdge = 0x%02lX", (uint32) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegs328::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::HotSyncEvent
+// ---------------------------------------------------------------------------
+// Handles a HotSync button event by updating the appropriate registers.
+
+void EmRegs328::HotSyncEvent (Bool iButton_IsDown)
+{
+ // If the button changes state, set or clear the HotSync interrupt.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ if (iButton_IsDown)
+ {
+ intPendingHi |= hwr328IntHiIRQ1;
+ fHotSyncButtonDown = true;
+ }
+ else
+ {
+ intPendingHi &= ~hwr328IntHiIRQ1;
+ fHotSyncButtonDown = false;
+ }
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetKeyBits
+// ---------------------------------------------------------------------------
+
+uint8 EmRegs328::GetKeyBits (void)
+{
+ // Return the key bits
+
+ uint8 portDPullupEn = READ_REGISTER (portDPullupEn); // Interested where bits are one
+ uint8 keyBits = portDPullupEn & fKeyBits;
+
+ PRINTF ("EmRegs328::GetKeyBits: keyBits = 0x%02lX", (uint32) keyBits);
+
+ return keyBits;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::ButtonToBits
+// ---------------------------------------------------------------------------
+
+uint16 EmRegs328::ButtonToBits (SkinElementType button)
+{
+ uint16 bitNumber = 0;
+ switch (button)
+ {
+ case kElement_None: break;
+
+ case kElement_PowerButton: bitNumber = keyBitPower; break;
+ case kElement_UpButton: bitNumber = keyBitPageUp; break;
+ case kElement_DownButton: bitNumber = keyBitPageDown; break;
+ case kElement_App1Button: bitNumber = keyBitHard1; break;
+ case kElement_App2Button: bitNumber = keyBitHard2; break;
+ case kElement_App3Button: bitNumber = keyBitHard3; break;
+ case kElement_App4Button: bitNumber = keyBitHard4; break;
+ case kElement_CradleButton: bitNumber = keyBitCradle; break;
+ case kElement_Antenna: bitNumber = keyBitAntenna; break;
+ case kElement_ContrastButton: bitNumber = keyBitContrast; break;
+
+/*
+ // Symbol-specific
+ case kElement_TriggerLeft: bitNumber = keyBitTrigLeft; break;
+ case kElement_TriggerCenter: bitNumber = keyBitTrigCenter; break;
+ case kElement_TriggerRight: bitNumber = keyBitTrigRight; break;
+ case kElement_UpButtonLeft: bitNumber = keyBitPageUpLeft; break;
+ case kElement_UpButtonRight: bitNumber = keyBitPageUpRight; break;
+ case kElement_DownButtonLeft: bitNumber = keyBitPageDownLeft; break;
+ case kElement_DownButtonRight: bitNumber = keyBitPageDownRight; break;
+*/
+ default: EmAssert (false);
+ }
+
+ return bitNumber;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UpdateInterrupts
+// ---------------------------------------------------------------------------
+// Determines whether an interrupt has occurred by copying the Interrupt
+// Pending Register to the Interrupt Status Register.
+
+void EmRegs328::UpdateInterrupts (void)
+{
+ // Copy the Interrupt Pending Register to the Interrupt Status
+ // Register, but ignore interrupts that are being masked.
+
+ // Note: this function is not sensitive to the byte ordering of the registers,
+ // so their contents don't need to be accessed via READ_REGISTER or WRITE_REGISTER.
+
+ f68328Regs.intStatusHi = f68328Regs.intPendingHi & ~f68328Regs.intMaskHi;
+ f68328Regs.intStatusLo = f68328Regs.intPendingLo & ~f68328Regs.intMaskLo;
+
+ PRINTF ("EmRegs328::UpdateInterrupts: intMask = 0x%04lX %04lX",
+ (uint32) f68328Regs.intMaskHi, (uint32) f68328Regs.intMaskLo);
+
+ PRINTF ("EmRegs328::UpdateInterrupts: intPending = 0x%04lX %04lX",
+ (uint32) f68328Regs.intPendingHi, (uint32) f68328Regs.intPendingLo);
+
+ // If the Interrupt Status Register isn't clear, flag an interrupt.
+
+ if (f68328Regs.intStatusHi || f68328Regs.intStatusLo)
+ {
+ regs.spcflags |= SPCFLAG_INT;
+
+ PRINTF ("EmRegs328::UpdateInterrupts: intStatus = 0x%04lX %04lX",
+ (uint32) f68328Regs.intStatusHi, (uint32) f68328Regs.intStatusLo);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UpdatePortDInterrupts
+// ---------------------------------------------------------------------------
+// Determine what interrupts need to be generated based on the current
+// settings in portDData and fPortDEdge.
+
+void EmRegs328::UpdatePortDInterrupts (void)
+{
+ // Update INT0-INT7 of the Interrupt-Pending register (bits 8-15 of the low word).
+
+ // First, get those bits and clear them out.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwr328IntLoAllKeys;
+
+
+ // Initialize the variable to hold the new interrupt settings.
+
+ uint8 newBits = 0;
+
+
+ // Get some other values we're going to need:
+
+ uint8 portDDir = READ_REGISTER (portDDir); // Interrupt on inputs only (when pin is low)
+ uint8 portDData = EmHAL::GetPortInputValue ('D');
+ uint8 portDPolarity = READ_REGISTER (portDPolarity);
+ uint8 portDIntReqEn = READ_REGISTER (portDIntReqEn);
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+
+ // We have a line-level interrupt if:
+ //
+ // - line-level interrupts are requested
+ // - the GPIO bit matches the polarity bit
+
+ newBits |= ~portDIntEdge & portDData & portDPolarity;
+ newBits |= ~portDIntEdge & ~portDData & ~portDPolarity;
+
+
+ // We have an edge interrupt if:
+ //
+ // - edge interrupts are requested
+ // - an edge has been recorded
+ //
+ // Note that we should distinguish between rising and falling edges.
+ // For historical reasons, that's not done, and the Palm OS doesn't
+ // look for them, so it's OK for now.
+
+ newBits |= portDIntEdge & fPortDEdge & portDPolarity;
+ newBits |= portDIntEdge & 0 & ~portDPolarity;
+
+
+ // Only have interrupts if they're enabled and the pin is configured for input.
+
+ newBits &= portDIntReqEn & ~portDDir;
+
+ PRINTF ("EmRegs328::UpdatePortDInterrupts: Dir Data Pol Req Edg PDE bits");
+ PRINTF ("EmRegs328::UpdatePortDInterrupts: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (uint32) portDDir, (uint32) portDData, (uint32) portDPolarity, (uint32) portDIntReqEn, (uint32) portDIntEdge,
+ (uint32) fPortDEdge, (uint32) newBits);
+
+
+ // Merge in the new values and write out the result.
+
+ intPendingLo |= (((uint16) newBits) << 8) & hwr328IntLoAllKeys;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UpdateRTCInterrupts
+// ---------------------------------------------------------------------------
+// Determine whether to set or clear the RTC bit in the interrupt pending
+// register based on the current RTC register values.
+
+void EmRegs328::UpdateRTCInterrupts (void)
+{
+ // See if the RTC is enabled.
+
+ Bool rtcEnabled = (READ_REGISTER (rtcControl) & hwr328RTCControlRTCEnable) != 0;
+
+ // See if there are any RTC events that need to trigger an interrupt.
+
+#define BITS_TO_CHECK ( \
+ hwr328RTCIntEnableSec | \
+ hwr328RTCIntEnable24Hr | \
+ hwr328RTCIntEnableAlarm | \
+ hwr328RTCIntEnableMinute | \
+ hwr328RTCIntEnableStopWatch )
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+ uint16 rtcIntEnable = READ_REGISTER (rtcIntEnable);
+ uint16 rtcIntPending = rtcIntStatus & rtcIntEnable & BITS_TO_CHECK;
+
+ Bool havePendingEvents = rtcIntPending != 0;
+
+ // If the RTC is enabled and there are pending events, set the interrupt.
+ // Otherwise, clear the interrupt.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo);
+
+ if (rtcEnabled && havePendingEvents)
+ {
+ intPendingLo |= hwr328IntLoRTC; // have events, so set interrupt
+ }
+ else
+ {
+ intPendingLo &= ~hwr328IntLoRTC; // no events, so clear interrupt
+ }
+
+ // Update the interrupt pending register.
+
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::IDDetectAsserted
+// ---------------------------------------------------------------------------
+// cf. HwrIdentifyFeatures and HwrPreRAMInit.
+
+Bool EmRegs328::IDDetectAsserted (void)
+{
+ uint8 portEDir = READ_REGISTER (portEDir);
+ uint8 portEData = READ_REGISTER (portEData);
+ uint8 portEPullupEn = READ_REGISTER (portEPullupEn);
+ const uint8 kMask = hwrTD1PortENoBacklight;
+
+ return (portEDir & kMask) == kMask &&
+ (portEData & kMask) == 0 &&
+ (portEPullupEn & kMask) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetHardwareID
+// ---------------------------------------------------------------------------
+
+UInt8 EmRegs328::GetHardwareID (void)
+{
+ // Determine the hardware ID.
+
+ // Note: Because of a Poser bug, I don't think any of the following actually
+ // gets executed. 328 ROMs first check to see if they're on a PalmPilot
+ // by executing the following:
+ //
+ // if (!(baseP->portEData & hwrTD1PortENoBacklight)) {
+ // ...on PalmPilot...
+ // } else {
+ // ...execute ID DETECT...
+ // }
+ //
+ // In Poser, hwrTD1PortENoBacklight is always zero (that's the bug), and
+ // so we always think we're on a PalmPilot, regardless of what 328 device
+ // we selected.
+
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ long miscFlags = device.HardwareID ();
+
+ // Reverse map the following:
+// GHwrMiscFlags = 0;
+// if ( (keyState & keyBitHard1) == 0) GHwrMiscFlags |= hwrMiscFlagID1;
+// if ( (keyState & keyBitHard2) == 0) GHwrMiscFlags |= hwrMiscFlagID2;
+// if ( (keyState & keyBitHard3) == 0) GHwrMiscFlags |= hwrMiscFlagID3;
+// if ( (keyState & keyBitHard4) == 0) GHwrMiscFlags |= hwrMiscFlagID4;
+
+ uint8 keyState = ~0;
+
+ if ((miscFlags & hwrMiscFlagID1) != 0) keyState &= ~keyBitHard1;
+ if ((miscFlags & hwrMiscFlagID2) != 0) keyState &= ~keyBitHard2;
+ if ((miscFlags & hwrMiscFlagID3) != 0) keyState &= ~keyBitHard3;
+ if ((miscFlags & hwrMiscFlagID4) != 0) keyState &= ~keyBitHard4;
+
+ return keyState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UARTStateChanged
+// ---------------------------------------------------------------------------
+
+void EmRegs328::UARTStateChanged (Bool sendTxData)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_Dragonball);
+
+ EmRegs328::MarshalUARTState (state);
+ fUART->StateChanged (state, sendTxData);
+ EmRegs328::UnmarshalUARTState (state);
+
+ EmRegs328::UpdateUARTInterrupts (state);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UpdateUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegs328::UpdateUARTState (Bool refreshRxData)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_Dragonball);
+
+ EmRegs328::MarshalUARTState (state);
+ fUART->UpdateState (state, refreshRxData);
+ UnmarshalUARTState (state);
+
+ EmRegs328::UpdateUARTInterrupts (state);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UpdateUARTInterrupts
+// ---------------------------------------------------------------------------
+
+void EmRegs328::UpdateUARTInterrupts (const EmUARTDragonball::State& state)
+{
+ // Generate the appropriate interrupts.
+
+ if (state.RX_FULL_ENABLE && state.RX_FIFO_FULL ||
+ state.RX_HALF_ENABLE && state.RX_FIFO_HALF ||
+ state.RX_RDY_ENABLE && state.DATA_READY ||
+ state.TX_EMPTY_ENABLE && state.TX_FIFO_EMPTY ||
+ state.TX_HALF_ENABLE && state.TX_FIFO_HALF ||
+ state.TX_AVAIL_ENABLE && state.TX_AVAIL)
+ {
+ // Set the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwr328IntLoUART);
+ }
+ else
+ {
+ // Clear the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) & ~hwr328IntLoUART);
+ }
+
+ // Respond to the new interrupt state.
+
+ EmRegs328::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::MarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegs328::MarshalUARTState (EmUARTDragonball::State& state)
+{
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uBaud = READ_REGISTER (uBaud);
+ uint16 uReceive = READ_REGISTER (uReceive);
+ uint16 uTransmit = READ_REGISTER (uTransmit);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ state.UART_ENABLE = (uControl & hwr328UControlUARTEnable) != 0;
+ state.RX_ENABLE = (uControl & hwr328UControlRxEnable) != 0;
+ state.TX_ENABLE = (uControl & hwr328UControlTxEnable) != 0;
+ state.RX_CLK_CONT = (uControl & hwr328UControlRxClock1x) != 0;
+ state.PARITY_EN = (uControl & hwr328UControlParityEn) != 0;
+ state.ODD_EVEN = (uControl & hwr328UControlParityOdd) != 0;
+ state.STOP_BITS = (uControl & hwr328UControlStopBits2) != 0;
+ state.CHAR8_7 = (uControl & hwr328UControlDataBits8) != 0;
+ state.GPIO_DELTA_ENABLE = (uControl & hwr328UControlGPIODeltaEn) != 0; // 68328 only
+// state.OLD_ENABLE = (uControl & hwrEZ328UControlOldDataEn) != 0; // 68EZ328 only
+ state.CTS_DELTA_ENABLE = (uControl & hwr328UControlCTSDeltaEn) != 0;
+ state.RX_FULL_ENABLE = (uControl & hwr328UControlRxFullEn) != 0;
+ state.RX_HALF_ENABLE = (uControl & hwr328UControlRxHalfEn) != 0;
+ state.RX_RDY_ENABLE = (uControl & hwr328UControlRxRdyEn) != 0;
+ state.TX_EMPTY_ENABLE = (uControl & hwr328UControlTxEmptyEn) != 0;
+ state.TX_HALF_ENABLE = (uControl & hwr328UControlTxHalfEn) != 0;
+ state.TX_AVAIL_ENABLE = (uControl & hwr328UControlTxAvailEn) != 0;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+ state.GPIO_DELTA = (uBaud & hwr328UBaudGPIODelta) != 0; // 68328 only
+ state.GPIO = (uBaud & hwr328UBaudGPIOData) != 0; // 68328 only
+ state.GPIO_DIR = (uBaud & hwr328UBaudGPIODirOut) != 0; // 68328 only
+ state.GPIO_SRC = (uBaud & hwr328UBaudGPIOSrcBaudGen) != 0; // 68328 only
+// state.UCLK_DIR = (uBaud & hwrEZ328UBaudUCLKDirOut) != 0; // 68EZ328 only
+ state.BAUD_SRC = (uBaud & hwr328UBaudBaudSrcGPIO) != 0;
+ state.DIVIDE = (uBaud & hwr328UBaudDivider) >> hwr328UBaudDivideBitOffset;
+ state.PRESCALER = (uBaud & hwr328UBaudPrescaler);
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ state.RX_FIFO_FULL = (uReceive & hwr328UReceiveFIFOFull) != 0;
+ state.RX_FIFO_HALF = (uReceive & hwr328UReceiveFIFOHalf) != 0;
+ state.DATA_READY = (uReceive & hwr328UReceiveDataRdy) != 0;
+// state.OLD_DATA = (uReceive & hwrEZ328UReceiveOldData) != 0; // 68EZ328 only
+ state.OVRUN = (uReceive & hwr328UReceiveOverrunErr) != 0;
+ state.FRAME_ERROR = (uReceive & hwr328UReceiveFrameErr) != 0;
+ state.BREAK = (uReceive & hwr328UReceiveBreakErr) != 0;
+ state.PARITY_ERROR = (uReceive & hwr328UReceiveParityErr) != 0;
+ state.RX_DATA = (uReceive & hwr328UReceiveData);
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ state.TX_FIFO_EMPTY = (uTransmit & hwr328UTransmitFIFOEmpty) != 0;
+ state.TX_FIFO_HALF = (uTransmit & hwr328UTransmitFIFOHalf) != 0;
+ state.TX_AVAIL = (uTransmit & hwr328UTransmitTxAvail) != 0;
+ state.SEND_BREAK = (uTransmit & hwr328UTransmitSendBreak) != 0;
+ state.IGNORE_CTS = (uTransmit & hwr328UTransmitIgnoreCTS) != 0;
+// state.BUSY = (uTransmit & hwrEZ328UTransmitBusy) != 0; // 68EZ328 only
+ state.CTS_STATUS = (uTransmit & hwr328UTransmitCTSStatus) != 0;
+ state.CTS_DELTA = (uTransmit & hwr328UTransmitCTSDelta) != 0;
+ state.TX_DATA = (uTransmit & hwr328UTransmitData);
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+// state.BAUD_TEST = (uMisc & hwrEZ328UMiscBaudTest) != 0; // 68EZ328 only
+ state.CLK_SRC = (uMisc & hwr328UMiscClkSrcGPIO) != 0;
+ state.FORCE_PERR = (uMisc & hwr328UMiscForceParityErr) != 0;
+ state.LOOP = (uMisc & hwr328UMiscLoopback) != 0;
+// state.BAUD_RESET = (uMisc & hwrEZ328UMiscBaudReset) != 0; // 68EZ328 only
+// state.IR_TEST = (uMisc & hwrEZ328UMiscIRTestEn) != 0; // 68EZ328 only
+ state.RTS_CONT = (uMisc & hwr328UMiscRTSThruFIFO) != 0;
+ state.RTS = (uMisc & hwr328UMiscRTSOut) != 0;
+ state.IRDA_ENABLE = (uMisc & hwr328UMiscIRDAEn) != 0;
+ state.IRDA_LOOP = (uMisc & hwr328UMiscLoopIRDA) != 0;
+// state.RX_POL = (uMisc & hwrEZ328UMiscRXPolarityInv) != 0; // 68EZ328 only
+// state.TX_POL = (uMisc & hwrEZ328UMiscTXPolarityInv) != 0; // 68EZ328 only
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::UnmarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegs328::UnmarshalUARTState (const EmUARTDragonball::State& state)
+{
+ uint16 uControl = 0;
+ uint16 uBaud = 0;
+ uint16 uReceive = 0;
+ uint16 uTransmit = 0;
+ uint16 uMisc = 0;
+
+ if (state.UART_ENABLE) uControl |= hwr328UControlUARTEnable;
+ if (state.RX_ENABLE) uControl |= hwr328UControlRxEnable;
+ if (state.TX_ENABLE) uControl |= hwr328UControlTxEnable;
+ if (state.RX_CLK_CONT) uControl |= hwr328UControlRxClock1x;
+ if (state.PARITY_EN) uControl |= hwr328UControlParityEn;
+ if (state.ODD_EVEN) uControl |= hwr328UControlParityOdd;
+ if (state.STOP_BITS) uControl |= hwr328UControlStopBits2;
+ if (state.CHAR8_7) uControl |= hwr328UControlDataBits8;
+ if (state.GPIO_DELTA_ENABLE)uControl |= hwr328UControlGPIODeltaEn; // 68328 only
+// if (state.OLD_ENABLE) uControl |= hwrEZ328UControlOldDataEn; // 68EZ328 only
+ if (state.CTS_DELTA_ENABLE) uControl |= hwr328UControlCTSDeltaEn;
+ if (state.RX_FULL_ENABLE) uControl |= hwr328UControlRxFullEn;
+ if (state.RX_HALF_ENABLE) uControl |= hwr328UControlRxHalfEn;
+ if (state.RX_RDY_ENABLE) uControl |= hwr328UControlRxRdyEn;
+ if (state.TX_EMPTY_ENABLE) uControl |= hwr328UControlTxEmptyEn;
+ if (state.TX_HALF_ENABLE) uControl |= hwr328UControlTxHalfEn;
+ if (state.TX_AVAIL_ENABLE) uControl |= hwr328UControlTxAvailEn;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+ if (state.GPIO_DELTA) uBaud |= hwr328UBaudGPIODelta; // 68328 only
+ if (state.GPIO) uBaud |= hwr328UBaudGPIOData; // 68328 only
+ if (state.GPIO_DIR) uBaud |= hwr328UBaudGPIODirOut; // 68328 only
+ if (state.GPIO_SRC) uBaud |= hwr328UBaudGPIOSrcBaudGen; // 68328 only
+// if (state.UCLK_DIR) uBaud |= hwrEZ328UBaudUCLKDirOut; // 68EZ328 only
+ if (state.BAUD_SRC) uBaud |= hwr328UBaudBaudSrcGPIO;
+
+ uBaud |= (state.DIVIDE << hwr328UBaudDivideBitOffset) & hwr328UBaudDivider;
+ uBaud |= (state.PRESCALER) & hwr328UBaudPrescaler;
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ if (state.RX_FIFO_FULL) uReceive |= hwr328UReceiveFIFOFull;
+ if (state.RX_FIFO_HALF) uReceive |= hwr328UReceiveFIFOHalf;
+ if (state.DATA_READY) uReceive |= hwr328UReceiveDataRdy;
+// if (state.OLD_DATA) uReceive |= hwrEZ328UReceiveOldData; // 68EZ328 only
+ if (state.OVRUN) uReceive |= hwr328UReceiveOverrunErr;
+ if (state.FRAME_ERROR) uReceive |= hwr328UReceiveFrameErr;
+ if (state.BREAK) uReceive |= hwr328UReceiveBreakErr;
+ if (state.PARITY_ERROR) uReceive |= hwr328UReceiveParityErr;
+
+ uReceive |= (state.RX_DATA) & hwr328UReceiveData;
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ if (state.TX_FIFO_EMPTY) uTransmit |= hwr328UTransmitFIFOEmpty;
+ if (state.TX_FIFO_HALF) uTransmit |= hwr328UTransmitFIFOHalf;
+ if (state.TX_AVAIL) uTransmit |= hwr328UTransmitTxAvail;
+ if (state.SEND_BREAK) uTransmit |= hwr328UTransmitSendBreak;
+ if (state.IGNORE_CTS) uTransmit |= hwr328UTransmitIgnoreCTS;
+// if (state.BUSY) uTransmit |= hwrEZ328UTransmitBusy; // 68EZ328 only
+ if (state.CTS_STATUS) uTransmit |= hwr328UTransmitCTSStatus;
+ if (state.CTS_DELTA) uTransmit |= hwr328UTransmitCTSDelta;
+
+ uTransmit |= (state.TX_DATA) & hwr328UTransmitData;
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+// if (state.BAUD_TEST) uMisc |= hwrEZ328UMiscBaudTest; // 68EZ328 only
+ if (state.CLK_SRC) uMisc |= hwr328UMiscClkSrcGPIO;
+ if (state.FORCE_PERR) uMisc |= hwr328UMiscForceParityErr;
+ if (state.LOOP) uMisc |= hwr328UMiscLoopback;
+// if (state.BAUD_RESET) uMisc |= hwrEZ328UMiscBaudReset; // 68EZ328 only
+// if (state.IR_TEST) uMisc |= hwrEZ328UMiscIRTestEn; // 68EZ328 only
+ if (state.RTS_CONT) uMisc |= hwr328UMiscRTSThruFIFO;
+ if (state.RTS) uMisc |= hwr328UMiscRTSOut;
+ if (state.IRDA_ENABLE) uMisc |= hwr328UMiscIRDAEn;
+ if (state.IRDA_LOOP) uMisc |= hwr328UMiscLoopIRDA;
+// if (state.RX_POL) uMisc |= hwrEZ328UMiscRXPolarityInv; // 68EZ328 only
+// if (state.TX_POL) uMisc |= hwrEZ328UMiscTXPolarityInv; // 68EZ328 only
+
+ WRITE_REGISTER (uControl, uControl);
+ WRITE_REGISTER (uBaud, uBaud);
+ WRITE_REGISTER (uReceive, uReceive);
+ WRITE_REGISTER (uTransmit, uTransmit);
+ WRITE_REGISTER (uMisc, uMisc);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::GetPort
+// ---------------------------------------------------------------------------
+// Given an address, return a value indicating what port it is associated with.
+
+int EmRegs328::GetPort (emuptr address)
+{
+ const long MASK = 0x00000FF8;
+
+ switch (address & MASK)
+ {
+ case 0x0400: return 'A';
+ case 0x0408: return 'B';
+ case 0x0410: return 'C';
+ case 0x0418: return 'D';
+ case 0x0420: return 'E';
+ case 0x0428: return 'F';
+ case 0x0430: return 'G';
+ case 0x0438: return 'J';
+ case 0x0440: return 'K';
+ case 0x0448: return 'M';
+ }
+
+ EmAssert (false);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegs328::PrvGetPalette (RGBList& thePalette)
+{
+ // !!! TBD
+ Preference<RGBType> pref1 (kPrefKeyBackgroundColor);
+ Preference<RGBType> pref2 (kPrefKeyHighlightColor);
+
+ RGBType foreground (0, 0, 0);
+ RGBType background;
+
+ if (this->GetLCDBacklightOn ())
+ {
+ if (pref2.Loaded ())
+ background = *pref2;
+ else
+ background = ::SkinGetHighlightColor ();
+ }
+ else
+ {
+ if (pref1.Loaded ())
+ background = *pref1;
+ else
+ background = ::SkinGetBackgroundColor ();
+ }
+
+ long br = ((long) background.fRed);
+ long bg = ((long) background.fGreen);
+ long bb = ((long) background.fBlue);
+
+ long dr = ((long) foreground.fRed) - ((long) background.fRed);
+ long dg = ((long) foreground.fGreen) - ((long) background.fGreen);
+ long db = ((long) foreground.fBlue) - ((long) background.fBlue);
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x01);
+ int32 numColors = 1 << bpp;
+ thePalette.resize (numColors);
+
+ for (int color = 0; color < numColors; ++color)
+ {
+ thePalette[color].fRed = (UInt8) (br + dr * color / (numColors - 1));
+ thePalette[color].fGreen = (UInt8) (bg + dg * color / (numColors - 1));
+ thePalette[color].fBlue = (UInt8) (bb + db * color / (numColors - 1));
+ }
+}
+
+
diff --git a/SrcShared/Hardware/EmRegs328.h b/SrcShared/Hardware/EmRegs328.h
new file mode 100644
index 0000000..2ea7011
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328.h
@@ -0,0 +1,146 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328_h
+#define EmRegs328_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmRegs.h" // EmRegs
+#include "EmStructs.h" // RGBList
+#include "EmUARTDragonball.h" // EmUARTDragonball::State
+
+class EmScreenUpdateInfo;
+
+
+class EmRegs328 : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegs328 (void);
+ virtual ~EmRegs328 (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHALHandler overrides
+ virtual void Cycle (Bool sleeping);
+ virtual void CycleSlowly (Bool sleeping);
+
+ virtual void ButtonEvent (SkinElementType, Bool buttonIsDown);
+ virtual void TurnSoundOff (void);
+ virtual void ResetTimer (void);
+ virtual void ResetRTC (void);
+
+ virtual int32 GetInterruptLevel (void);
+ virtual int32 GetInterruptBase (void);
+
+ virtual Bool GetLCDScreenOn (void) = 0;
+ virtual Bool GetLCDBacklightOn (void) = 0;
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr&, emuptr&);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+ virtual int32 GetDynamicHeapSize (void);
+ virtual int32 GetROMSize (void);
+ virtual emuptr GetROMBaseAddress (void);
+ virtual Bool ChipSelectsConfigured (void);
+ virtual int32 GetSystemClockFrequency (void);
+ virtual Bool GetCanStop (void);
+ virtual Bool GetAsleep (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void PortDataChanged (int, uint8, uint8);
+
+ private:
+ uint32 pllFreqSelRead (emuptr address, int size);
+ uint32 portXDataRead (emuptr address, int size);
+ uint32 tmr1StatusRead (emuptr address, int size);
+ uint32 tmr2StatusRead (emuptr address, int size);
+ uint32 uartRead (emuptr address, int size);
+ uint32 rtcHourMinSecRead (emuptr address, int size);
+
+ void csASelect1Write (emuptr address, int size, uint32 value);
+ void csCSelect0Write (emuptr address, int size, uint32 value);
+ void csCSelect1Write (emuptr address, int size, uint32 value);
+ void intMaskHiWrite (emuptr address, int size, uint32 value);
+ void intMaskLoWrite (emuptr address, int size, uint32 value);
+ void intStatusHiWrite (emuptr address, int size, uint32 value);
+ void portXDataWrite (emuptr address, int size, uint32 value);
+ void portDIntReqEnWrite (emuptr address, int size, uint32 value);
+ void tmr1StatusWrite (emuptr address, int size, uint32 value);
+ void tmr2StatusWrite (emuptr address, int size, uint32 value);
+ void wdCounterWrite (emuptr address, int size, uint32 value);
+ void spiMasterControlWrite (emuptr address, int size, uint32 value);
+ void uartWrite (emuptr address, int size, uint32 value);
+ void lcdRegisterWrite (emuptr address, int size, uint32 value);
+ void rtcControlWrite (emuptr address, int size, uint32 value);
+ void rtcIntStatusWrite (emuptr address, int size, uint32 value);
+ void rtcIntEnableWrite (emuptr address, int size, uint32 value);
+
+ protected:
+ void HotSyncEvent (Bool buttonIsDown);
+
+ virtual uint8 GetKeyBits (void);
+ virtual uint16 ButtonToBits (SkinElementType);
+
+ protected:
+ void UpdateInterrupts (void);
+ void UpdatePortDInterrupts (void);
+ void UpdateRTCInterrupts (void);
+
+ protected:
+ Bool IDDetectAsserted (void);
+ UInt8 GetHardwareID (void);
+
+ protected:
+ void UARTStateChanged (Bool sendTxData);
+ void UpdateUARTState (Bool refreshRxData);
+ void UpdateUARTInterrupts (const EmUARTDragonball::State& state);
+ void MarshalUARTState (EmUARTDragonball::State& state);
+ void UnmarshalUARTState (const EmUARTDragonball::State& state);
+
+ protected:
+ int GetPort (emuptr address);
+ void PrvGetPalette (RGBList& thePalette);
+
+ protected:
+ HwrM68328Type f68328Regs;
+ bool fHotSyncButtonDown;
+ uint32 fTmr2CurrentMilliseconds;
+ uint32 fTmr2StartMilliseconds;
+ uint16 fKeyBits;
+ uint16 fLastTmr1Status;
+ uint16 fLastTmr2Status;
+ uint8 fPortDEdge;
+ uint32 fPortDDataCount;
+
+ uint32 fHour;
+ uint32 fMin;
+ uint32 fSec;
+ uint32 fTick;
+ uint32 fCycle;
+
+ EmUARTDragonball* fUART;
+};
+
+#endif /* EmRegs328_h */
diff --git a/SrcShared/Hardware/EmRegs328PalmIII.h b/SrcShared/Hardware/EmRegs328PalmIII.h
new file mode 100644
index 0000000..67e39b0
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328PalmIII.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328PalmIII_h
+#define EmRegs328PalmIII_h
+
+#include "EmRegs328PalmPilot.h" // EmRegs328PalmPilot
+
+typedef EmRegs328PalmPilot EmRegs328PalmIII;
+
+#endif /* EmRegs328PalmIII_h */
diff --git a/SrcShared/Hardware/EmRegs328PalmPilot.cpp b/SrcShared/Hardware/EmRegs328PalmPilot.cpp
new file mode 100644
index 0000000..25ce276
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328PalmPilot.cpp
@@ -0,0 +1,82 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegs328PalmPilot.h"
+#include "EmRegs328Prv.h"
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "328Jerry/IncsPrv/HardwareTD1.h" // hwrTD1PortFLCDEnableOn, etc.
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328PalmPilot::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328PalmPilot::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portFData) & hwrTD1PortFLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328PalmPilot::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegs328PalmPilot::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrTD1PortGBacklightOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328PalmPilot::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegs328PalmPilot::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portGData) & hwrTD1PortGSerialOn) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portJData) & hwrTD1PortJIrOn) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328PalmPilot::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegs328PalmPilot::GetPortInputValue (int port)
+{
+ uint8 result = EmRegs328::GetPortInputValue (port);
+
+ if (port == 'M')
+ {
+ // Ensure that bit hwrTD1PortMDockIn is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ result |= hwrTD1PortMDockIn;
+ }
+
+ return result;
+}
diff --git a/SrcShared/Hardware/EmRegs328PalmPilot.h b/SrcShared/Hardware/EmRegs328PalmPilot.h
new file mode 100644
index 0000000..00d2e75
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328PalmPilot.h
@@ -0,0 +1,30 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328PalmPilot_h
+#define EmRegs328PalmPilot_h
+
+#include "EmRegs328.h" // EmRegs328
+
+
+class EmRegs328PalmPilot : public EmRegs328
+{
+ public:
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType);
+
+ virtual uint8 GetPortInputValue (int);
+};
+
+#endif /* EmRegs328PalmPilot_h */
diff --git a/SrcShared/Hardware/EmRegs328PalmVII.h b/SrcShared/Hardware/EmRegs328PalmVII.h
new file mode 100644
index 0000000..4763967
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328PalmVII.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328PalmVII_h
+#define EmRegs328PalmVII_h
+
+#include "EmRegs328PalmPilot.h" // EmRegs328PalmPilot
+
+typedef EmRegs328PalmPilot EmRegs328PalmVII;
+
+#endif /* EmRegs328PalmVII_h */
diff --git a/SrcShared/Hardware/EmRegs328Pilot.h b/SrcShared/Hardware/EmRegs328Pilot.h
new file mode 100644
index 0000000..d380978
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328Pilot.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328Pilot_h
+#define EmRegs328Pilot_h
+
+#include "EmRegs328PalmPilot.h" // EmRegs328PalmPilot
+
+typedef EmRegs328PalmPilot EmRegs328Pilot;
+
+#endif /* EmRegs328Pilot_h */
diff --git a/SrcShared/Hardware/EmRegs328Prv.h b/SrcShared/Hardware/EmRegs328Prv.h
new file mode 100644
index 0000000..8b09f33
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328Prv.h
@@ -0,0 +1,45 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328Prv_h
+#define EmRegs328Prv_h
+
+#include "EmRegsPrv.h"
+
+// Location and range of registers
+
+const uint32 kMemoryStart = 0xFFFFF000;
+const uint32 kMemorySize = sizeof (HwrM68328Type);
+
+
+// Macro to return the Dragonball address of the specified register
+
+#define addressof(x) (kMemoryStart + offsetof(HwrM68328Type, x))
+
+
+// Macros for reading/writing Dragonball registers.
+
+#define READ_REGISTER(reg) \
+ _get_reg (&f68328Regs.reg)
+
+#define WRITE_REGISTER(reg, value) \
+ _put_reg (&f68328Regs.reg, value)
+
+
+// Macro for installing Dragonball register handlers
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ((ReadFunction) &EmRegs328::read, (WriteFunction) &EmRegs328::write, addressof (reg), sizeof (f68328Regs.reg))
+
+
+#endif /* EmRegs328Prv_h */
diff --git a/SrcShared/Hardware/EmRegs328Symbol1700.cpp b/SrcShared/Hardware/EmRegs328Symbol1700.cpp
new file mode 100644
index 0000000..0b5a305
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328Symbol1700.cpp
@@ -0,0 +1,121 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegs328Symbol1700.h"
+#include "EmRegs328Prv.h"
+
+#define keyBitTrigLeft 0x0400
+#define keyBitTrigCenter 0x0800
+#define keyBitTrigRight 0x1000
+#define keyBitPageUpLeft keyBitPageUp
+#define keyBitPageUpRight keyBitPageDown
+#define keyBitPageDownLeft 0x2000
+#define keyBitPageDownRight 0x4000
+
+
+#define keyBitMask 0x0F // Which bits in port D we use for keys
+
+#define portDKbdCols 0xF0
+#define portDKbdRows 0x0F
+
+#define portDKbdCol0 0x10
+#define portDKbdCol1 0x20
+#define portDKbdCol2 0x40
+#define portDKbdCol3 0x80
+
+#define portDKbdRow0 0x01
+#define portDKbdRow1 0x02
+#define portDKbdRow2 0x04
+#define portDKbdRow3 0x08
+
+
+const int kNumButtonRows = 4;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitPower, keyBitTrigLeft, keyBitTrigCenter, keyBitTrigRight },
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUpLeft, keyBitPageUpRight, keyBitPageDownLeft, keyBitPageDownRight },
+ { keyBitContrast, 0, 0, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328Symbol1700::GetKeyBits
+// ---------------------------------------------------------------------------
+
+uint8 EmRegs328Symbol1700::GetKeyBits (void)
+{
+ uint8 portDData = READ_REGISTER (portDData);
+
+ Bool cols[4];
+ cols[0] = (portDData & portDKbdCol0) == 0;
+ cols[1] = (portDData & portDKbdCol1) == 0;
+ cols[2] = (portDData & portDKbdCol2) == 0;
+ cols[3] = (portDData & portDKbdCol3) == 0;
+
+ uint8 keyData = 0;
+
+ // Walk the columns, looking for one that is requested.
+
+ for (int col = 0; col < kNumButtonCols; ++col)
+ {
+ if (cols[col])
+ {
+ // Walk the rows.
+
+ for (int row = 0; row < kNumButtonRows; ++row)
+ {
+ // Get the key corresponding to this row and column.
+ // If we've recorded (in fgKeyBits) that this key is
+ // pressed, then set its row bit.
+
+ if ((fKeyBits & kButtonMap[row][col]) != 0)
+ {
+ keyData |= 1 << (col + 4);
+ keyData |= 1 << row;
+ }
+ }
+ }
+ }
+
+ return keyData;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs328Symbol1700::ButtonToBits
+// ---------------------------------------------------------------------------
+
+uint16 EmRegs328Symbol1700::ButtonToBits (SkinElementType button)
+{
+ uint16 bitNumber = 0;
+ switch (button)
+ {
+ default:
+ bitNumber = EmRegs328PalmPilot::ButtonToBits (button);
+ break;
+
+ case kElement_TriggerLeft: bitNumber = keyBitTrigLeft; break;
+ case kElement_TriggerCenter: bitNumber = keyBitTrigCenter; break;
+ case kElement_TriggerRight: bitNumber = keyBitTrigRight; break;
+ case kElement_UpButtonLeft: bitNumber = keyBitPageUpLeft; break;
+ case kElement_UpButtonRight: bitNumber = keyBitPageUpRight; break;
+ case kElement_DownButtonLeft: bitNumber = keyBitPageDownLeft; break;
+ case kElement_DownButtonRight: bitNumber = keyBitPageDownRight; break;
+ }
+
+ return bitNumber;
+}
diff --git a/SrcShared/Hardware/EmRegs328Symbol1700.h b/SrcShared/Hardware/EmRegs328Symbol1700.h
new file mode 100644
index 0000000..8690c80
--- /dev/null
+++ b/SrcShared/Hardware/EmRegs328Symbol1700.h
@@ -0,0 +1,26 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegs328Symbol1700_h
+#define EmRegs328Symbol1700_h
+
+#include "EmRegs328PalmPilot.h" // EmRegs328PalmPilot
+
+class EmRegs328Symbol1700 : public EmRegs328PalmPilot
+{
+ public:
+ virtual uint8 GetKeyBits (void);
+ virtual uint16 ButtonToBits (SkinElementType);
+};
+
+#endif /* EmRegs328Symbol1700_h */
diff --git a/SrcShared/Hardware/EmRegsASICSymbol1700.cpp b/SrcShared/Hardware/EmRegsASICSymbol1700.cpp
new file mode 100644
index 0000000..ff2ab2f
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsASICSymbol1700.cpp
@@ -0,0 +1,168 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsASICSymbol1700.h"
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsASICSymbol1700::read, \
+ (WriteFunction) &EmRegsASICSymbol1700::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::EmRegsASICSymbol1700
+// ---------------------------------------------------------------------------
+
+EmRegsASICSymbol1700::EmRegsASICSymbol1700 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::~EmRegsASICSymbol1700
+// ---------------------------------------------------------------------------
+
+EmRegsASICSymbol1700::~EmRegsASICSymbol1700 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsASICSymbol1700::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ // Install the first three by hand instead of using our
+ // INSTALL_HANDLER macro. That macro doesn't support the
+ // installation of a field that's an array.
+ this->SetHandler ( (ReadFunction) &EmRegsASICSymbol1700::StdReadBE, \
+ (WriteFunction) &EmRegsASICSymbol1700::StdWriteBE, \
+ addressof (S24IO), \
+ 64);
+ this->SetHandler ( (ReadFunction) &EmRegsASICSymbol1700::StdReadBE, \
+ (WriteFunction) &EmRegsASICSymbol1700::StdWriteBE, \
+ addressof (S24Attribute), \
+ 32);
+ this->SetHandler ( (ReadFunction) &EmRegsASICSymbol1700::StdReadBE, \
+ (WriteFunction) &EmRegsASICSymbol1700::StdWriteBE, \
+ addressof (UART8251MacroSelect),\
+ 4);
+
+// INSTALL_HANDLER (StdReadBE, StdWriteBE, S24IO);
+// INSTALL_HANDLER (StdReadBE, StdWriteBE, S24Attribute);
+// INSTALL_HANDLER (StdReadBE, StdWriteBE, UART8251MacroSelect);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, ScannerDecoderControl);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, Control);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOData);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIODirection);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsASICSymbol1700::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsASICSymbol1700::GetAddressStart (void)
+{
+ return 0x11000000;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsASICSymbol1700::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsASICSymbol1700::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
diff --git a/SrcShared/Hardware/EmRegsASICSymbol1700.h b/SrcShared/Hardware/EmRegsASICSymbol1700.h
new file mode 100644
index 0000000..6b15d33
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsASICSymbol1700.h
@@ -0,0 +1,44 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsASICSymbol1700_h
+#define EmRegsASICSymbol1700_h
+
+#include "EmPalmStructs.h"
+#include "EmRegs.h"
+
+class SessionFile;
+
+
+class EmRegsASICSymbol1700 : public EmRegs
+{
+ public:
+ EmRegsASICSymbol1700 (void);
+ virtual ~EmRegsASICSymbol1700 (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ private:
+ EmProxyHwrSymbolASICType fRegs;
+};
+
+#endif /* EmRegsASICSymbol1700_h */
diff --git a/SrcShared/Hardware/EmRegsEZ.cpp b/SrcShared/Hardware/EmRegsEZ.cpp
new file mode 100644
index 0000000..f56144d
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZ.cpp
@@ -0,0 +1,2655 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZ.h"
+#include "EmRegsEZPrv.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmHAL.h" // EmHAL
+#include "EmMemory.h" // gMemAccessFlags, EmMem_memcpy
+#include "EmPixMap.h" // SetSize, SetRowBytes, etc.
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmSession.h" // GetDevice
+#include "EmSPISlave.h" // DoExchange
+#include "Hordes.h" // Hordes::IsOn
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // GetHostTime
+#include "PreferenceMgr.h" // Preference
+#include "SessionFile.h" // WriteHwrDBallEZType, etc.
+#include "UAE.h" // regs, SPCFLAG_INT
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "HwrMiscFlags.h" // hwrMiscFlagID1
+
+ #define hwrEZ328maskID1J83G 0x05
+
+ // Some platform-specific -- yet fairly portable -- defines.
+ #define hwrEZPortGIDDetect 0x04 // (L) ID select (drives kbd)
+ #define hwrEZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+ #define hwrEZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+ #define hwrEZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+ #define hwrEZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+ #define hwrEZPortDKeyBits 0x0F // (H) All Keyboard Columns
+
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+static const uint16 UPSIZ = 0x1800; // Mask to get the unprotected memory size from csDSelect.
+static const uint16 SIZ = 0x000E; // Mask to get the memory size from csASelect.
+static const uint16 EN = 0x0001; // Mask to get the enable bit from csASelect.
+
+static const uint16 gBaseAddressShift = 13; // Shift to get base address from CSGBx register value
+
+#define PRINTF if (1) ; else LogAppendMsg
+
+// Values used to initialize the DragonBallEZ registers.
+
+static const HwrM68EZ328Type kInitial68EZ328RegisterValues =
+{
+ 0x1C, // Byte scr; // $000: System Control Register
+ { 0 }, // Byte ___filler0[0x004-0x001];
+ hwrEZ328chipIDEZ, // Byte chipID; // $004: Chip ID Register
+ hwrEZ328maskID1J83G, // Byte maskID; // $005: Mask ID Register
+ 0x00, // Word swID; // $006: Software ID Register
+ { 0 }, // Byte ___filler1[0x100-0x008];
+
+ 0x0000, // Word csAGroupBase; // $100: Chip Select Group A Base Register
+ 0x0000, // Word csBGroupBase; // $102: Chip Select Group B Base Register
+ 0x0000, // Word csCGroupBase; // $104: Chip Select Group C Base Register
+ 0x0000, // Word csDGroupBase; // $106: Chip Select Group D Base Register
+
+ { 0 }, // Byte ___filler6[0x110-0x108];
+
+ 0x00E0, // Word csASelect; // $110: Group A Chip Select Register
+ 0x0000, // Word csBSelect; // $112: Group B Chip Select Register
+ 0x0000, // Word csCSelect; // $114: Group C Chip Select Register
+ 0x0000, // Word csDSelect; // $116: Group D Chip Select Register
+
+ 0x0060, // Word emuCS; // $118: EMU Chip Select Register
+
+ { 0 }, // Byte ___filler2[0x200-0x11A];
+
+ 0x2430, // Word pllControl; // $200: PLL Control Register
+ 0x0123, // Word pllFreqSel; // $202: PLL Frequency Select Register
+ 0, // !!! ---> Marked as reserved in 1.4 Word pllTest; // $204: PLL Test Register (do not access)
+ { 0 }, // Byte ___filler44;
+ 0x1F, // Byte pwrControl; // $207: Power Control Register
+
+ { 0 }, // Byte ___filler3[0x300-0x208];
+
+ 0x00, // Byte intVector; // $300: Interrupt Vector Register
+ { 0 }, // Byte ___filler4;
+ 0x0000, // Word intControl; // $302: Interrupt Control Register
+ 0x00FF, // Word intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ 0xFFFF, // Word intMaskLo; // $306: Interrupt Mask Register/LOW word
+ { 0 }, // Byte ___filler7[0x30c-0x308];
+ 0x0000, // Word intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ 0x0000, // Word intStatusLo; // $30E: Interrupt Status Register/LOW word
+ 0x0000, // Word intPendingHi; // $310: Interrupt Pending Register
+ 0x0000, // Word intPendingLo; // $312: Interrupt Pending Register
+
+ { 0 }, // Byte ___filler4a[0x400-0x314];
+
+ 0x00, // Byte portADir; // $400: Port A Direction Register
+ 0x00, // Byte portAData; // $401: Port A Data Register
+ 0xFF, // Byte portAPullupEn; // $402: Port A Pullup Enable (similar to Select on DB)
+ { 0 }, // Byte ___filler8[5];
+
+ 0x00, // Byte portBDir; // $408: Port B Direction Register
+ 0x00, // Byte portBData; // $409: Port B Data Register
+ 0xFF, // Byte portBPullupEn; // $40A: Port B Pullup Enable
+ 0xFF, // Byte portBSelect; // $40B: Port B Select Register
+
+ { 0 }, // Byte ___filler9[4];
+
+ 0x00, // Byte portCDir; // $410: Port C Direction Register
+ 0x00, // Byte portCData; // $411: Port C Data Register
+ 0xFF, // Byte portCPulldnEn; // $412: Port C Pulldown Enable
+ 0xFF, // Byte portCSelect; // $413: Port C Select Register
+
+ { 0 }, // Byte ___filler10[4];
+
+ 0x00, // Byte portDDir; // $418: Port D Direction Register
+ 0x00, // Byte portDData; // $419: Port D Data Register
+ 0xFF, // Byte portDPullupEn; // $41A: Port D Pull-up Enable
+ 0xF0, // Byte portDSelect; // $41B: Port D Select Register
+ 0x00, // Byte portDPolarity; // $41C: Port D Polarity Register
+ 0x00, // Byte portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ 0x00, // Byte portDKbdIntEn; // $41E: Port D Keyboard Interrupt Enable
+ 0x00, // Byte portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ 0x00, // Byte portEDir; // $420: Port E Direction Register
+ 0x00, // Byte portEData; // $421: Port E Data Register
+ 0xFF, // Byte portEPullupEn; // $422: Port E Pull-up Enable
+ 0xFF, // Byte portESelect; // $423: Port E Select Register
+
+ { 0 }, // Byte ___filler14[4];
+
+ 0x00, // Byte portFDir; // $428: Port F Direction Register
+ 0x00, // Byte portFData; // $429: Port F Data Register
+ 0xFF, // Byte portFPullupdnEn; // $42A: Port F Pull-up/down Enable
+ 0x00, // Byte portFSelect; // $42B: Port F Select Register
+
+ { 0 }, // Byte ___filler16[4];
+
+ 0x00, // Byte portGDir; // $430: Port G Direction Register
+ 0x00, // Byte portGData; // $431: Port G Data Register
+ 0x3D, // Byte portGPullupEn; // $432: Port G Pull-up Enable
+ 0x08, // Byte portGSelect; // $433: Port G Select Register
+
+ { 0 }, // Byte ___filler2000[0x500-0x434];
+
+ 0x0020, // Word pwmControl; // $500: PWM Control Register
+ 0x00, // Byte pwmSampleHi; // $502: PWM Sample - high byte
+ 0x00, // Byte pwmSampleLo; // $503: PWM Sample - low byte
+ 0xFE, // Byte pwmPeriod; // $504: PWM Period
+ 0x00, // Byte pwmCounter; // $505: PWM Counter
+
+ { 0 }, // Byte ___filler24[0x600-0x506];
+
+ 0x0000, // Word tmr1Control; // $600: Timer 1 Control Register
+ 0x0000, // Word tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ 0xFFFF, // Word tmr1Compare; // $604: Timer 1 Compare Register
+ 0x0000, // Word tmr1Capture; // $606: Timer 1 Capture Register
+ 0x0000, // Word tmr1Counter; // $608: Timer 1 Counter Register
+ 0x0000, // Word tmr1Status; // $60A: Timer 1 Status Register
+
+ { 0 }, // Byte ___filler25[0x800-0x61E];
+
+ 0x0000, // Word spiMasterData; // $800: SPI Master Data Register
+ 0x0000, // Word spiMasterControl; // $802: SPI Master Control Register
+
+ { 0 }, // Byte ___filler27[0x900-0x804];
+
+ 0x0000, // Word uControl; // $900: Uart Control Register
+ 0x003F, // Word uBaud; // $902: Uart Baud Control Register
+ 0x0000, // Word uReceive; // $904: Uart Receive Register
+ 0x0000, // Word uTransmit; // $906: Uart Transmit Register
+ 0x0000, // Word uMisc; // $908: Uart Miscellaneous Register
+ 0x0000, // Word uNonIntPresc; // $90A: Uart IRDA Non-Integer Prescaler
+
+ { 0 }, // Byte ___filler28[0xA00-0x90C];
+
+ 0x00000000, // DWord lcdStartAddr; // $A00: Screen Starting Address Register
+ { 0 }, // Byte ___filler29;
+ 0xFF, // Byte lcdPageWidth; // $A05: Virtual Page Width Register
+ { 0 }, // Byte ___filler30[2];
+ 0x03FF, // Word lcdScreenWidth; // $A08: Screen Width Register
+ 0x01FF, // Word lcdScreenHeight; // $A0A: Screen Height Register
+ { 0 }, // Byte ___filler31[0xA18-0xA0C];
+ 0x0000, // Word lcdCursorXPos; // $A18: Cursor X Position
+ 0x0000, // Word lcdCursorYPos; // $A1A: Cursor Y Position
+ 0x0101, // Word lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ { 0 }, // Byte ___filler32;
+ 0x7F, // Byte lcdBlinkControl; // $A1F: Blink Control Register
+ 0x00, // Byte lcdPanelControl; // $A20: Panel Interface Control Register
+ 0x00, // Byte lcdPolarity; // $A21: Polarity Config Register
+ { 0 }, // Byte ___filler33;
+ 0x00, // Byte lcdACDRate; // $A23: ACD (M) Rate Control Register
+ { 0 }, // Byte ___filler34;
+ 0x00, // Byte lcdPixelClock; // $A25: Pixel Clock Divider Register
+ { 0 }, // Byte ___filler35;
+ 0x40, // Byte lcdClockControl; // $A27: Clocking Control Register
+ { 0 }, // Byte ___filler36;
+ 0xFF, // Byte lcdRefreshRateAdj; // $A29: Refresh Rate Adjustment Register
+ { 0 }, // Byte ___filler2003[0xA2D-0xA2A];
+ 0x00, // Byte lcdPanningOffset; // $A2D: Panning Offset Register
+
+ { 0 }, // Byte ___filler37[0xA31-0xA2E];
+
+ 0xB9, // Byte lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ { 0 }, // Byte ___filler2004;
+ 0x84, // Byte lcdGrayPalette; // $A33: Gray Palette Mapping Register
+ 0x00, // Byte lcdReserved; // $A34: Reserved
+ { 0 }, // Byte ___filler2005;
+ 0x0000, // Word lcdContrastControlPWM; // $A36: Contrast Control
+
+ { 0 }, // Byte ___filler40[0xB00-0xA38];
+
+ 0x00000000, // DWord rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ 0x00000000, // DWord rtcAlarm; // $B04: RTC Alarm Register
+ { 0 }, // Byte ___filler2001[0xB0A-0xB08];
+ 0x0001, // Word rtcWatchDog; // $B0A: RTC Watchdog Timer
+ 0x00, // Word rtcControl; // $B0C: RTC Control Register
+ 0x00, // Word rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ 0x00, // Word rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ 0x00, // Word stopWatch; // $B12: Stopwatch Minutes
+ { 0 }, // Byte ___filler2002[0xB1A-0xB14];
+ 0x0000, // Word rtcDay; // $B1A: RTC Day
+ 0x0000, // Word rtcDayAlarm; // $B1C: RTC Day Alarm
+
+ { 0 }, // Byte ___filler41[0xC00-0xB1E];
+
+ 0x0000, // Word dramConfig; // $C00: DRAM Memory Config Register
+ 0x0000, // Word dramControl; // $C02: DRAM Control Register
+
+ { 0 }, // Byte ___filler42[0xD00-0xC04];
+
+ 0x00000000, // DWord emuAddrCompare; // $D00: Emulation Address Compare Register
+ 0x00000000, // DWord emuAddrMask; // $D04: Emulation Address Mask Register
+ 0x0000, // Word emuControlCompare; // $D08: Emulation Control Compare Register
+ 0x0000, // Word emuControlMask; // $D0A: Emulation Control Mask Register
+ 0x0000, // Word emuControl; // $DOC: Emulation Control Register
+ 0x0000 // Word emuStatus; // $D0E: Emulation Status Register
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::EmRegsEZ
+// ---------------------------------------------------------------------------
+
+EmRegsEZ::EmRegsEZ (void) :
+ EmRegs (),
+ f68EZ328Regs (),
+ fHotSyncButtonDown (0),
+ fKeyBits (0),
+ fLastTmr1Status (0),
+ fPortDEdge (0),
+ fPortDDataCount (0),
+ fHour (0),
+ fMin (0),
+ fSec (0),
+ fTick (0),
+ fCycle (0),
+ fUART (NULL)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::~EmRegsEZ
+// ---------------------------------------------------------------------------
+
+EmRegsEZ::~EmRegsEZ (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::Initialize (void)
+{
+ EmRegs::Initialize ();
+
+ fUART = new EmUARTDragonball (EmUARTDragonball::kUART_DragonballEZ, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ f68EZ328Regs = kInitial68EZ328RegisterValues;
+
+ // Byteswap all the words in the DragonballEZ registers (if necessary).
+
+ Canonical (f68EZ328Regs);
+ ByteswapWords (&f68EZ328Regs, sizeof(f68EZ328Regs));
+
+ fKeyBits = 0;
+ fLastTmr1Status = 0;
+ fPortDEdge = 0;
+ fPortDDataCount = 0;
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegsEZ::UARTStateChanged (sendTxData);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ StWordSwapper swapper1 (&f68EZ328Regs, sizeof(f68EZ328Regs));
+// StCanonical<HwrM68EZ328Type> swapper2 (f68EZ328Regs);
+ f.WriteHwrDBallEZType (f68EZ328Regs);
+ f.FixBug (SessionFile::kBugByteswappedStructs);
+
+ const long kCurrentVersion = 3;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ s << fHotSyncButtonDown;
+ s << fKeyBits;
+ s << fLastTmr1Status;
+ s << fPortDEdge;
+
+
+ // Added in version 2.
+
+ s << fHour;
+ s << fMin;
+ s << fSec;
+ s << fTick;
+ s << fCycle;
+
+ // Added in version 3.
+
+ s << fPortDDataCount;
+
+ f.WriteDBallEZState (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ if (f.ReadHwrDBallEZType (f68EZ328Regs))
+ {
+ // The Windows version of Poser 2.1d29 and earlier did not write
+ // out structs in the correct format. The fields of the struct
+ // were written out in Little-Endian format, not Big-Endian. To
+ // address this problem, the bug has been fixed, and a new field
+ // is added to the file format indicating that the bug has been
+ // fixed. With the new field (the "bug bit"), Poser can identify
+ // old files from new files and read them in accordingly.
+ //
+ // With the bug fixed, the .psf files should now be interchangeable
+ // across platforms (modulo other bugs...).
+
+ if (!f.IncludesBugFix (SessionFile::kBugByteswappedStructs))
+ {
+ Canonical (f68EZ328Regs);
+ }
+ ByteswapWords (&f68EZ328Regs, sizeof(f68EZ328Regs));
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegsEZ::UARTStateChanged (sendTxData);
+
+ // Reset gMemAccessFlags.fProtect_SRAMSet
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csDSelect) & 0x2000) != 0;
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+ Chunk chunk;
+ if (f.ReadDBallEZState (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> fHotSyncButtonDown;
+ s >> fKeyBits;
+ s >> fLastTmr1Status;
+ s >> fPortDEdge;
+ }
+
+ if (version >= 2)
+ {
+ s >> fHour;
+ s >> fMin;
+ s >> fSec;
+ s >> fTick;
+ s >> fCycle;
+ }
+
+ if (version >= 3)
+ {
+ s >> fPortDDataCount;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::Dispose (void)
+{
+ delete fUART;
+ fUART = NULL;
+
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdRead, StdWrite, scr);
+
+ INSTALL_HANDLER (StdRead, NullWrite, chipID);
+ INSTALL_HANDLER (StdRead, NullWrite, maskID);
+ INSTALL_HANDLER (StdRead, NullWrite, swID);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csAGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csBGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csCGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csDGroupBase);
+
+ INSTALL_HANDLER (StdRead, csASelectWrite, csASelect);
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect);
+ INSTALL_HANDLER (StdRead, StdWrite, csCSelect);
+ INSTALL_HANDLER (StdRead, csDSelectWrite, csDSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, emuCS);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pllControl);
+ INSTALL_HANDLER (pllFreqSelRead, StdWrite, pllFreqSel);
+ INSTALL_HANDLER (StdRead, StdWrite, pllTest);
+ INSTALL_HANDLER (StdRead, StdWrite, pwrControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, intVector);
+ INSTALL_HANDLER (StdRead, StdWrite, intControl);
+ INSTALL_HANDLER (StdRead, intMaskHiWrite, intMaskHi);
+ INSTALL_HANDLER (StdRead, intMaskLoWrite, intMaskLo);
+ INSTALL_HANDLER (StdRead, intStatusHiWrite, intStatusHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intStatusLo);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingLo);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portADir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portAData);
+ INSTALL_HANDLER (StdRead, StdWrite, portAPullupEn);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portBDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portBData);
+ INSTALL_HANDLER (StdRead, StdWrite, portBPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portBSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portCDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portCData);
+ INSTALL_HANDLER (StdRead, StdWrite, portCPulldnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portCSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portDDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portDData);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDSelect);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPolarity);
+ INSTALL_HANDLER (StdRead, portDIntReqEnWrite, portDIntReqEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDKbdIntEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDIntEdge);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portEDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portEData);
+ INSTALL_HANDLER (StdRead, StdWrite, portEPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portESelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portFDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portFData);
+ INSTALL_HANDLER (StdRead, StdWrite, portFPullupdnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portFSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portGDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portGData);
+ INSTALL_HANDLER (StdRead, StdWrite, portGPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portGSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pwmControl);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmSampleHi);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmSampleLo);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmPeriod);
+ INSTALL_HANDLER (StdRead, NullWrite, pwmCounter);
+
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Control);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Prescaler);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Compare);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Capture);
+ INSTALL_HANDLER (StdRead, NullWrite, tmr1Counter);
+ INSTALL_HANDLER (tmr1StatusRead, tmr1StatusWrite, tmr1Status);
+
+ INSTALL_HANDLER (StdRead, StdWrite, spiMasterData);
+ INSTALL_HANDLER (StdRead, spiMasterControlWrite, spiMasterControl);
+
+ INSTALL_HANDLER (uartRead, uartWrite, uControl);
+ INSTALL_HANDLER (uartRead, uartWrite, uBaud);
+ INSTALL_HANDLER (uartRead, uartWrite, uReceive);
+ INSTALL_HANDLER (uartRead, uartWrite, uTransmit);
+ INSTALL_HANDLER (uartRead, uartWrite, uMisc);
+ INSTALL_HANDLER (uartRead, uartWrite, uNonIntPresc);
+
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdStartAddr);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPageWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorXPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorYPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorWidthHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdBlinkControl);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPanelControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPolarity);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdACDRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPixelClock);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdClockControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdRefreshRateAdj);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPanningOffset);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdFrameRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdGrayPalette);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdContrastControlPWM);
+ INSTALL_HANDLER (rtcHourMinSecRead, StdWrite, rtcHourMinSec);
+
+ INSTALL_HANDLER (StdRead, StdWrite, rtcAlarm);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcWatchDog);
+ INSTALL_HANDLER (StdRead, rtcControlWrite, rtcControl);
+ INSTALL_HANDLER (StdRead, rtcIntStatusWrite, rtcIntStatus);
+ INSTALL_HANDLER (StdRead, rtcIntEnableWrite, rtcIntEnable);
+ INSTALL_HANDLER (StdRead, StdWrite, stopWatch);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcDay);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcDayAlarm);
+
+ INSTALL_HANDLER (StdRead, StdWrite, dramConfig);
+ INSTALL_HANDLER (StdRead, StdWrite, dramControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, emuAddrCompare);
+ INSTALL_HANDLER (StdRead, StdWrite, emuAddrMask);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControlCompare);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControlMask);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControl);
+ INSTALL_HANDLER (StdRead, StdWrite, emuStatus);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsEZ::GetRealAddress (emuptr address)
+{
+ uint8* loc = ((uint8*) &f68EZ328Regs) + (address - kMemoryStart);
+
+ return loc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsEZ::GetAddressStart (void)
+{
+ return kMemoryStart;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::GetAddressRange (void)
+{
+ return kMemorySize;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::Cycle
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+void EmRegsEZ::Cycle (Bool sleeping)
+{
+#if _DEBUG
+ #define increment 20
+#else
+ #define increment 4
+#endif
+
+ // Determine whether timer is enabled.
+
+ if ((READ_REGISTER (tmr1Control) & hwrEZ328TmrControlEnable) != 0)
+ {
+ // If so, increment the timer.
+
+ WRITE_REGISTER (tmr1Counter, READ_REGISTER (tmr1Counter) + (sleeping ? 1 : increment));
+
+ // Determine whether the timer has reached the specified count.
+
+ if (sleeping || READ_REGISTER (tmr1Counter) > READ_REGISTER (tmr1Compare))
+ {
+ // Flag the occurrence of the successful comparison.
+
+ WRITE_REGISTER (tmr1Status, READ_REGISTER (tmr1Status) | hwrEZ328TmrStatusCompare);
+
+ // If the Free Run/Restart flag is not set, clear the counter.
+
+ if ((READ_REGISTER (tmr1Control) & hwrEZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr1Counter, 0);
+ }
+
+ // If the timer interrupt is enabled, post an interrupt.
+
+ if ((READ_REGISTER (tmr1Control) & hwrEZ328TmrControlEnInterrupt) != 0)
+ {
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwrEZ328IntLoTimer);
+ EmRegsEZ::UpdateInterrupts ();
+ }
+ }
+ }
+
+ if ((fCycle += increment) > READ_REGISTER (tmr1Compare))
+ {
+ fCycle = 0;
+
+ if (++fTick >= 100)
+ {
+ fTick = 0;
+
+ if (++fSec >= 60)
+ {
+ fSec = 0;
+
+ if (++fMin >= 60)
+ {
+ fMin = 0;
+
+ if (++fHour >= 24)
+ {
+ fHour = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::CycleSlowly
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+void EmRegsEZ::CycleSlowly (Bool sleeping)
+{
+ UNUSED_PARAM(sleeping)
+
+ // See if a hard button is pressed.
+
+
+ EmAssert (gSession);
+ if (gSession->HasButtonEvent ())
+ {
+ EmButtonEvent event = gSession->GetButtonEvent ();
+ if (event.fButton == kElement_CradleButton)
+ {
+ EmRegsEZ::HotSyncEvent (event.fButtonIsDown);
+ }
+ else
+ {
+ EmRegsEZ::ButtonEvent (event.fButton, event.fButtonIsDown);
+ }
+ }
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegsEZ::UpdateUARTState (false);
+
+ // Check to see if the RTC alarm is ready to go off. First see
+ // if the RTC is enabled, and that the alarm event isn't already
+ // registered (the latter check is just an optimization).
+
+ if ((READ_REGISTER (rtcIntEnable) & hwrEZ328RTCIntEnableAlarm) != 0 &&
+ (READ_REGISTER (rtcIntStatus) & hwrEZ328RTCIntStatusAlarm) == 0)
+ {
+ uint32 rtcAlarm = READ_REGISTER (rtcAlarm);
+
+ long almHour = (rtcAlarm & hwrEZ328RTCAlarmHoursMask) >> hwrEZ328RTCAlarmHoursOffset;
+ long almMin = (rtcAlarm & hwrEZ328RTCAlarmMinutesMask) >> hwrEZ328RTCAlarmMinutesOffset;
+ long almSec = (rtcAlarm & hwrEZ328RTCAlarmSecondsMask) >> hwrEZ328RTCAlarmSecondsOffset;
+ long almInSeconds = (almHour * 60 * 60) + (almMin * 60) + almSec;
+
+ long nowHour;
+ long nowMin;
+ long nowSec;
+ ::GetHostTime (&nowHour, &nowMin, &nowSec);
+ long nowInSeconds = (nowHour * 60 * 60) + (nowMin * 60) + nowSec;
+
+ if (almInSeconds <= nowInSeconds)
+ {
+ WRITE_REGISTER (rtcIntStatus, READ_REGISTER (rtcIntStatus) | hwrEZ328RTCIntStatusAlarm);
+ EmRegsEZ::UpdateRTCInterrupts ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::TurnSoundOff
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::TurnSoundOff (void)
+{
+ uint16 pwmControl = READ_REGISTER (pwmControl);
+ WRITE_REGISTER (pwmControl, pwmControl & ~hwrEZ328PWMControlEnable);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::ResetTimer
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::ResetTimer (void)
+{
+ WRITE_REGISTER (tmr1Counter, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::ResetRTC
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::ResetRTC (void)
+{
+ fHour = 15;
+ fMin = 0;
+ fSec = 0;
+ fTick = 0;
+ fCycle = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmRegsEZ::GetInterruptLevel (void)
+{
+ uint16 intStatusHi = READ_REGISTER (intStatusHi);
+ uint16 intStatusLo = READ_REGISTER (intStatusLo);
+
+ // Level 7 = EMUIRQ.
+
+ if ((intStatusHi & hwrEZ328IntHiEMU) != 0)
+ return 7;
+
+ // Level 6 = IRQ6, TMR, PWM.
+
+ if ((intStatusHi & (hwrEZ328IntHiIRQ6)) != 0)
+ return 6;
+
+ if ((intStatusLo & (hwrEZ328IntLoTimer | hwrEZ328IntLoPWM)) != 0)
+ return 6;
+
+ // Level 5 = PEN.
+
+ if ((intStatusHi & hwrEZ328IntHiPen) != 0)
+ return 5;
+
+ // Level 4 = SPIM, UART, WDT, RTC, RTC Sample, KB, INT0 - INT3.
+
+ if ((intStatusLo & ( hwrEZ328IntLoSPIM |
+ hwrEZ328IntLoUART |
+ hwrEZ328IntLoWDT |
+ hwrEZ328IntLoRTC |
+ hwrEZ328IntLoKbd |
+ hwrEZ328IntLoInt3 |
+ hwrEZ328IntLoInt2 |
+ hwrEZ328IntLoInt1 |
+ hwrEZ328IntLoInt0)) != 0)
+ return 4;
+
+ if ((intStatusHi & hwrEZ328IntHiSampleTimer) != 0)
+ return 4;
+
+ // Level 3 = IRQ3.
+
+ if ((intStatusHi & hwrEZ328IntHiIRQ3) != 0)
+ return 3;
+
+ // Level 2 = IRQ2.
+
+ if ((intStatusHi & hwrEZ328IntHiIRQ2) != 0)
+ return 2;
+
+ // Level 1 = IRQ1.
+
+ if ((intStatusHi & hwrEZ328IntHiIRQ1) != 0)
+ return 1;
+
+ // Level 0.
+
+ return -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetInterruptBase
+// ---------------------------------------------------------------------------
+
+int32 EmRegsEZ::GetInterruptBase (void)
+{
+ return READ_REGISTER (intVector) & 0xF8;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZ::GetLCDHasFrame (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+ int rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ int height = READ_REGISTER (lcdScreenHeight) + 1;
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x03);
+ int32 width = READ_REGISTER (lcdScreenWidth);
+ int32 height = READ_REGISTER (lcdScreenHeight) + 1;
+ int32 rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+
+ info.fLeftMargin = READ_REGISTER (lcdPanningOffset) & 0x0F;
+
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ emuptr firstLineAddr = baseAddr + (info.fFirstLine * rowBytes);
+ emuptr lastLineAddr = baseAddr + (info.fLastLine * rowBytes);
+
+ // TODO: probably move to <M68EZ328Hwr.h>
+ const long hwrEZ328LcdPageSize = 0x00020000; // 128K
+ const long hwrEZ328LcdPageMask = 0xFFFE0000;
+
+ uint8* dst = ((uint8*) info.fImage.GetBits () + firstLineAddr - baseAddr);
+ emuptr boundaryAddr = ((baseAddr & hwrEZ328LcdPageMask) + hwrEZ328LcdPageSize);
+
+ if (lastLineAddr <= boundaryAddr)
+ {
+ // Bits don't cross the 128K boundary
+ }
+ else if (firstLineAddr >= boundaryAddr)
+ {
+ // Bits are all beyond the 128K boundary
+
+ firstLineAddr -= hwrEZ328LcdPageSize; // wrap around
+ lastLineAddr -= hwrEZ328LcdPageSize;
+ }
+ else
+ {
+ // Bits straddle the 128K boundary;
+ // copy the first part here, the wrapped part below
+
+ EmMem_memcpy ((void*) dst, firstLineAddr, boundaryAddr - firstLineAddr);
+ dst += (boundaryAddr - firstLineAddr);
+
+ firstLineAddr = boundaryAddr - hwrEZ328LcdPageSize;
+ lastLineAddr -= hwrEZ328LcdPageSize; // wrap around
+ }
+
+ EmMem_memcpy ((void*) dst, firstLineAddr, lastLineAddr - firstLineAddr);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsEZ::GetUARTDevice (int /*uartNum*/)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetDynamicHeapSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegsEZ::GetDynamicHeapSize (void)
+{
+ int32 result = 0;
+
+ uint16 csDSelect = READ_REGISTER (csDSelect);
+
+ switch (csDSelect & UPSIZ)
+ {
+ case 0x0000:
+ result = 32 * 1024L;
+ break;
+
+ case 0x0800:
+ result = 64 * 1024L;
+ break;
+
+ case 0x1000:
+ result = 128 * 1024L;
+ break;
+
+ case 0x1800:
+ result = 256 * 1024L;
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegsEZ::GetROMSize (void)
+{
+ /*
+ SIZ Chip-Select Size
+
+ This field determines the memory range of the chip-select. For CSA
+ and CSB, chip-select size is between 128K and 16M. For CSC and CSD,
+ chip-select size is between 32K and 4M.
+
+ 000 = 128K (32K for CSC and CSD).
+ 001 = 256K (64K for CSC and CSD).
+ 010 = 512K (128K for CSC and CSD).
+ 011 = 1M (256K for CSC and CSD).
+ 100 = 2M (512K for CSC and CSD).
+ 101 = 4M (1M for CSC and CSD).
+ 110 = 8M (2M for CSC and CSD).
+ 111 = 16M (4M for CSC and CSD).
+ */
+
+ uint16 csASelect = READ_REGISTER (csASelect);
+ uint32 result = (128 * 1024L) << ((csASelect & SIZ) >> 1);
+
+ if ((csASelect & EN) == 0)
+ {
+ result = 16 * 1024L * 1024L;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetROMBaseAddress
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::GetROMBaseAddress (void)
+{
+ /*
+ csAGroupBase: Chip-select Group Base Address register
+
+ The csAGroupBase register stores the base address (bits 14-28 of
+ the address) in the top 15 bits. The low bit is always zero.
+ Shifting this value by 13 gives the ROM base address.
+
+ E.g: If the base address is 0x10C00000, then csAGroupBase will
+ contain 0x10C00000 >> 13 (base 10) = 0x8600.
+
+ If the enable bit of the CSA register is low, the chip selects
+ have not yet been set up. In this case, return an invalid value.
+ */
+
+ if (!this->ChipSelectsConfigured())
+ {
+ return 0xFFFFFFFF;
+ }
+
+ uint16 csAGroupBase = READ_REGISTER (csAGroupBase);
+ uint32 result = csAGroupBase << gBaseAddressShift;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::ChipSelectsConfigured
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZ::ChipSelectsConfigured (void)
+{
+ return READ_REGISTER (csASelect) & EN;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetSystemClockFrequency
+// ---------------------------------------------------------------------------
+
+int32 EmRegsEZ::GetSystemClockFrequency (void)
+{
+ uint16 pllControl = READ_REGISTER (pllControl);
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel);
+
+ // Convert the 32.768KHz clock (CLK32) into the PLLCLK frequency.
+
+ uint16 PC = (pllFreqSel & 0x00FF);
+ uint16 QC = (pllFreqSel & 0x0F00) >> 8;
+
+ uint32 result = 32768L * (14 * (PC + 1) + QC + 1);
+
+ // Divide by the prescaler, if needed.
+
+ if ((pllControl & 0x0020) != 0)
+ {
+ result /= 2;
+ }
+
+ // Divide by the system clock scaler, if needed.
+
+ switch (pllControl & 0x0F00)
+ {
+ case hwrEZ328PLLControlSysDMADiv2:
+ result /= 2;
+ break;
+
+ case hwrEZ328PLLControlSysDMADiv4:
+ result /= 4;
+ break;
+
+ case hwrEZ328PLLControlSysDMADiv8:
+ result /= 8;
+ break;
+
+ case hwrEZ328PLLControlSysDMADiv16:
+ result /= 16;
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetCanStop
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZ::GetCanStop (void)
+{
+ // Make sure Timer is enabled or the RTC interrupt is enabled.
+
+ if ((READ_REGISTER (tmr1Control) & hwrEZ328TmrControlEnable) != 0)
+ return true;
+
+ if ((READ_REGISTER (rtcIntEnable) & hwrEZ328RTCIntEnableAlarm) != 0)
+ return true;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetAsleep
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZ::GetAsleep (void)
+{
+ return ((READ_REGISTER (pllControl) & hwrEZ328PLLControlDisable) != 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZ::GetPortInputValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'D')
+ {
+ result = this->GetPortInternalValue (port);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZ::GetPortInternalValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'D')
+ {
+ // If the ID_DETECT pin is asserted, load the data lines with the
+ // hardware ID.
+
+ if (EmRegsEZ::IDDetectAsserted ())
+ {
+ result = EmRegsEZ::GetHardwareID ();
+ }
+
+ // Otherwise, load the lines with keyboard information.
+
+ else
+ {
+ // Get the INT bits that need to be set.
+
+ result = this->GetKeyBits ();
+ }
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::PortDataChanged
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::PortDataChanged (int port, uint8, uint8 newValue)
+{
+ if (port == 'D')
+ {
+ // Clear the interrupt bits that are having a 1 written to them.
+ // Only clear them if they're configured as edge-senstive.
+
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+ PRINTF ("EmRegsEZ::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+ PRINTF ("EmRegsEZ::PortDataChanged (D): portDIntEdge = 0x%02lX", (uint32) (uint8) portDIntEdge);
+ PRINTF ("EmRegsEZ::PortDataChanged (D): newValue = 0x%02lX", (uint32) (uint8) newValue);
+
+ fPortDEdge &= ~(newValue & portDIntEdge);
+
+ PRINTF ("EmRegsEZ::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegsEZ::UpdatePortDInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::pllFreqSelRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::pllFreqSelRead (emuptr address, int size)
+{
+ // Simulate the rising and falling of the CLK32 signal so that functions
+ // like HwrPreRAMInit, HwrShutDownPLL, PrvSetPLL, and PrvShutDownPLL
+ // won't hang.
+
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel) ^ 0x8000;
+ WRITE_REGISTER (pllFreqSel, pllFreqSel);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsEZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::portXDataRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::portXDataRead (emuptr address, int)
+{
+ // The value read can come from three different places:
+ //
+ // - the value what was written to the data register
+ // - any dedicated inputs
+ // - any GPIO inputs
+ //
+ // The value returned depends on the settings of the SEL and DIR
+ // registers. So let's get those settings, the values from the three
+ // input sources, and build up a return value based on those.
+
+ int port = GetPort (address);
+
+ uint8 sel = StdRead (address + 2, 1);
+ uint8 dir = StdRead (address - 1, 1);
+ uint8 output = StdRead (address + 0, 1);
+ uint8 input = EmHAL::GetPortInputValue (port);
+ uint8 intFn = EmHAL::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ sel |= 0x0F; // No "select" bit in low nybble, so set for IO values.
+
+ // The system will poll portD 18 times in KeyBootKeys to see
+ // if any keys are down. Wait at least that long before
+ // letting up any boot keys maintained by the session. When we
+ // do call ReleaseBootKeys, set our counter to -1 as a flag not
+ // to call it any more.
+
+ if (fPortDDataCount != 0xFFFFFFFF && ++fPortDDataCount >= 18 * 2)
+ {
+ fPortDDataCount = 0xFFFFFFFF;
+ gSession->ReleaseBootKeys ();
+ }
+ }
+
+ // Use the internal chip function bits if the "sel" bits are zero.
+
+ intFn &= ~sel;
+
+ // Otherwise, use the I/O bits.
+
+ output &= sel & dir; // Use the output bits if the "dir" is one.
+ input &= sel & ~dir; // Use the input bits if the "dir" is zero.
+
+ // Assert that there are no overlaps.
+
+ EmAssert ((output & input) == 0);
+ EmAssert ((output & intFn) == 0);
+ EmAssert ((input & intFn) == 0);
+
+ // Mush everything together.
+
+ uint8 result = output | input | intFn;
+
+ // If this is port D, flip the bits if the POLARITY register says to.
+ // (!!! Does this inversion apply only to input bits? That is, the
+ // bits where the "dir" register has 0 bits?)
+
+ if (0 && port == 'D')
+ {
+ uint8 polarity = READ_REGISTER (portDPolarity);
+ PRINTF ("EmRegsEZ::portXDataRead: polarity = 0x%02lX", (uint32) polarity);
+ result ^= polarity;
+ }
+
+ PRINTF ("EmRegsEZ::port%cDataRead: sel dir output input intFn result", (char) port);
+ PRINTF ("EmRegsEZ::port%cDataRead: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (char) port, (uint32) sel, (uint32) dir, (uint32) output, (uint32) input, (uint32) intFn, (uint32) result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::tmr1StatusRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::tmr1StatusRead (emuptr address, int size)
+{
+ uint16 tmr1Counter = READ_REGISTER (tmr1Counter) + 16;
+ uint16 tmr1Compare = READ_REGISTER (tmr1Compare);
+ uint16 tmr1Control = READ_REGISTER (tmr1Control);
+
+ // Increment the timer.
+
+ WRITE_REGISTER (tmr1Counter, tmr1Counter);
+
+ // If the timer has passed the specified value...
+
+ if ((tmr1Counter - tmr1Compare) < 16)
+ {
+ // Set the flag saying the timer timed out.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status) | hwrEZ328TmrStatusCompare;
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ // If it's not a free-running timer, reset it to zero.
+
+ if ((tmr1Control & hwrEZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr1Counter, 0);
+ }
+ }
+
+ // Remember this guy for later (see EmRegsEZ::tmr1StatusWrite())
+
+ fLastTmr1Status |= READ_REGISTER (tmr1Status);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsEZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::uartRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::uartRead (emuptr address, int size)
+{
+ // If this is a full read, get the next byte from the FIFO.
+
+ Bool refreshRxData = (address == addressof (uReceive)) && (size == 2);
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegsEZ::UpdateUARTState (refreshRxData);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsEZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::rtcHourMinSecRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsEZ::rtcHourMinSecRead (emuptr address, int size)
+{
+ // Get the desktop machine's time.
+
+ long hour, min, sec;
+
+ if (Hordes::IsOn ())
+ {
+ hour = fHour;
+ min = fMin;
+ sec = fSec;
+ }
+ else
+ {
+ ::GetHostTime (&hour, &min, &sec);
+ }
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcHourMinSec, (hour << hwrEZ328RTCHourMinSecHoursOffset)
+ | (min << hwrEZ328RTCHourMinSecMinutesOffset)
+ | (sec << hwrEZ328RTCHourMinSecSecondsOffset));
+
+ // Finish up by doing a standard read.
+
+ return EmRegsEZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::csASelectWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::csASelectWrite (emuptr address, int size, uint32 value)
+{
+ // Get the current value.
+
+ uint16 csASelect = READ_REGISTER (csASelect);
+
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csASelect & SIZ) != (READ_REGISTER (csASelect) & SIZ))
+ {
+ EmAssert (gSession);
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::csDSelectWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::csDSelectWrite (emuptr address, int size, uint32 value)
+{
+ // Get the current value.
+
+ uint16 csDSelect = READ_REGISTER (csDSelect);
+
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Check its new state and update our ram-protect flag.
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csDSelect) & 0x2000) != 0;
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csDSelect & UPSIZ) != (READ_REGISTER (csDSelect) & UPSIZ))
+ {
+ EmAssert (gSession);
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::intMaskHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::intMaskHiWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::intMaskLoWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::intMaskLoWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::intStatusHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::intStatusHiWrite (emuptr address, int size, uint32 value)
+{
+ // IRQ1, IRQ2, IRQ3, IRQ6 and IRQ7 are cleared by writing to their
+ // respective status bits. We handle those there. Since there are
+ // no interrupt status bits like this in intStatusLo, we don't need
+ // a handler for that register; we only handle intStatusHi.
+
+ // Even though this is a 16-bit register as defined by the Palm headers,
+ // it's a 32-bit register according to DragonballEZ docs, and is in fact
+ // accessed that way in the kernal files (cf. HwrIRQ4Handler). In those
+ // cases, we're still only interested in access to the IRQ# bits, so we
+ // can turn 4-byte accesses into 2-byte accesses.
+
+ if (size == 4)
+ value >>= 16;
+
+ // Take into account the possibility of 1-byte accesses, too. If we're
+ // accessing the upper byte, just return. If we're accessing the lower
+ // byte, we can treat it as a 2-byte access.
+
+ else if (size == 1 && address == addressof (intStatusHi))
+ return;
+
+ // Now we can treat the rest of this function as a word-write to intStatusHi.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ // For each interrupt:
+ // If we're writing to that interrupt's status bit and its edge bit is set:
+ // - clear the interrupt's pending bit
+ // - respond to the new interrupt state.
+
+ #undef CLEAR_PENDING_INTERRUPT
+ #define CLEAR_PENDING_INTERRUPT(edge, irq) \
+ if ((READ_REGISTER (intControl) & edge) && (value & (irq))) \
+ { \
+ intPendingHi &= ~(irq); \
+ }
+
+ CLEAR_PENDING_INTERRUPT (hwrEZ328IntCtlEdge1, hwrEZ328IntHiIRQ1);
+ CLEAR_PENDING_INTERRUPT (hwrEZ328IntCtlEdge2, hwrEZ328IntHiIRQ2);
+ CLEAR_PENDING_INTERRUPT (hwrEZ328IntCtlEdge3, hwrEZ328IntHiIRQ3);
+ CLEAR_PENDING_INTERRUPT (hwrEZ328IntCtlEdge6, hwrEZ328IntHiIRQ6);
+
+ // IRQ7 is not edge-programmable, so clear it if we're merely writing to it.
+ // !!! Double check this for EZ!
+
+ if (value & hwrEZ328IntHiEMU)
+ {
+ intPendingHi &= ~(hwrEZ328IntHiEMU);
+ }
+
+ // If we're emulating the user pressing the hotsync button, make sure the
+ // interrupt stays asserted. (!!! Should we use the same technique for
+ // other buttons, too? It doesn't seem to be needed right now, but doing
+ // that may more closely mirror the hardware.)
+
+ if (fHotSyncButtonDown)
+ {
+ intPendingHi |= hwrEZ328IntHiIRQ1;
+ }
+ else
+ {
+ intPendingHi &= ~hwrEZ328IntHiIRQ1;
+ }
+
+ // This makes the power on key work. If the signal is asserted, the
+ // unit will not transition between asleep and awake (cf. HwrSleep, HwrWake).
+
+ intPendingHi &= ~hwrEZ328IntHiIRQ6;
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::portXDataWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::portXDataWrite (emuptr address, int size, uint32 value)
+{
+ // Get the old value before updating it.
+
+ uint8 oldValue = StdRead (address, size);
+
+ // Take a snapshot of the line driver states.
+
+ Bool driverStates[kUARTEnd];
+ EmHAL::GetLineDriverStates (driverStates);
+
+ // Now update the value with a standard write.
+
+ StdWrite (address, size, value);
+
+ // Let anyone know that it's changed.
+
+ int port = GetPort (address);
+ PRINTF ("EmRegsEZ::port%cDataWrite: oldValue = 0x%02lX", (char) port, (uint32) (uint8) oldValue);
+ PRINTF ("EmRegsEZ::port%cDataWrite: newValue = 0x%02lX", (char) port, (uint32) (uint8) value);
+
+ EmHAL::PortDataChanged (port, oldValue, value);
+
+ // Respond to any changes in the line driver states.
+
+ EmHAL::CompareLineDriverStates (driverStates);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::portDIntReqEnWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::portDIntReqEnWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Set the new interrupt state.
+
+ EmRegsEZ::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::tmr1StatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::tmr1StatusWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ EmAssert (size == 2); // This function's a hell of a lot easier to write if
+ // we assume only full-register access.
+
+ // Get the current value.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status);
+
+ // If the user had previously read the status bits while they
+ // were set, then it's OK for them to be clear now. Otherwise,
+ // we have to merge any set status bits back in.
+
+ tmr1Status &= value | ~fLastTmr1Status; // fLastTmr1Status was set in EmRegsEZ::tmr1StatusRead()
+
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ fLastTmr1Status = 0;
+ if ((tmr1Status & hwrEZ328TmrStatusCompare) == 0)
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwrEZ328IntLoTimer;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::spiMasterControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::spiMasterControlWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Get the current value.
+
+ uint16 spiMasterData = READ_REGISTER (spiMasterData);
+ uint16 spiMasterControl = READ_REGISTER (spiMasterControl);
+
+ // Check to see if data exchange and interrupts are enabled.
+
+ #define BIT_MASK (hwrEZ328SPIMControlExchange | hwrEZ328SPIMControlEnable)
+ if ((spiMasterControl & BIT_MASK) == BIT_MASK)
+ {
+ // If the SPI is hooked up to something, talk with it.
+
+ EmSPISlave* spiSlave = this->GetSPISlave ();
+ if (spiSlave)
+ {
+ // Write out the old data, read in the new data.
+
+ uint16 newData = spiSlave->DoExchange (spiMasterControl, spiMasterData);
+
+ // Shift in the new data.
+
+ uint16 numBits = (spiMasterControl & hwrEZ328SPIMControlBitsMask) + 1;
+
+ uint16 oldBitsMask = ~0 << numBits;
+ uint16 newBitsMask = ~oldBitsMask;
+
+ spiMasterData = /*((spiMasterData << numBits) & oldBitsMask) | */
+ (newData & newBitsMask);
+
+ WRITE_REGISTER (spiMasterData, spiMasterData);
+ }
+
+ // Assert the interrupt and clear the exchange bit.
+
+ spiMasterControl |= hwrEZ328SPIMControlIntStatus;
+ spiMasterControl &= ~hwrEZ328SPIMControlExchange;
+
+ WRITE_REGISTER (spiMasterControl, spiMasterControl);
+
+ // If hwrEZ328SPIMControlIntEnable is set, trigger an interrupt.
+
+ if ((spiMasterControl & hwrEZ328SPIMControlIntEnable) != 0)
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo);
+ intPendingLo |= hwrEZ328IntLoSPIM;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+ this->UpdateInterrupts ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::uartWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::uartWrite(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // If this write included the TX_DATA field, signal that it needs to
+ // be transmitted.
+
+ Bool sendTxData =
+ ((address == addressof (uTransmit)) && (size == 2)) ||
+ ((address == addressof (uTransmit) + 1) && (size == 1));
+
+ // React to any changes.
+
+ EmRegsEZ::UARTStateChanged (sendTxData);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::lcdRegisterWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::lcdRegisterWrite (emuptr address, int size, uint32 value)
+{
+ // First, get the old value in case we need to see what changed.
+
+ uint32 oldValue = EmRegsEZ::StdRead (address, size);
+
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Note what changed.
+
+ if (address == addressof (lcdScreenWidth))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdScreenHeight))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPanelControl))
+ {
+ // hwrEZ328LcdPanelControlGrayScale is incorrectly defined as 0x01,
+ // so use the hard-coded value of 0x03 here.
+
+// if (((value ^ oldValue) & hwrEZ328LcdPanelControlGrayScale) != 0)
+ if (((value ^ oldValue) & 0x03) != 0)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+ else if (address == addressof (lcdStartAddr))
+ {
+ // Make sure the low-bit is always zero.
+ // Make sure bits 31-29 are always zero.
+
+ uint32 lcdStartAddr = READ_REGISTER (lcdStartAddr) & 0x1FFFFFFE;
+ WRITE_REGISTER (lcdStartAddr, lcdStartAddr);
+
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPageWidth))
+ {
+ if (value != oldValue)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::rtcControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::rtcControlWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::rtcIntStatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::rtcIntStatusWrite (emuptr address, int size, uint32 value)
+{
+ // Status bits are cleared by writing ones to them.
+
+ // If we're doing a byte-write to the upper byte, shift the byte
+ // so that we can treat the operation as a word write. If we're
+ // doing a byte-write to the lower byte, this extension will happen
+ // automatically.
+
+ if (address == addressof (rtcIntStatus) && size == 1)
+ value <<= 8;
+
+ // Get the current value.
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+
+ // Clear the requested bits.
+
+ rtcIntStatus &= ~value;
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcIntStatus, rtcIntStatus);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::rtcIntEnableWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::rtcIntEnableWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsEZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::ButtonEvent
+// ---------------------------------------------------------------------------
+// Handles a Palm device button event by updating the appropriate registers.
+
+void EmRegsEZ::ButtonEvent (SkinElementType button, Bool buttonIsDown)
+{
+ uint16 bitNumber = this->ButtonToBits (button);
+
+ // Get the bits that should have been set with the previous set
+ // of pressed keys. We use this old value to update the port D interrupts.
+
+ uint8 oldBits = this->GetKeyBits ();
+
+ // Update the set of keys that are currently pressed.
+
+ if (buttonIsDown)
+ {
+ fKeyBits |= bitNumber; // Remember the key bit
+ }
+ else
+ {
+ fKeyBits &= ~bitNumber; // Forget the key bit
+ }
+
+ // Now get the new set of bits that should be set.
+
+ uint8 newBits = this->GetKeyBits ();
+
+ PRINTF ("EmRegsEZ::ButtonEvent: fKeyBits = 0x%04lX", (uint32) fKeyBits);
+ PRINTF ("EmRegsEZ::ButtonEvent: oldBits = 0x%02lX", (uint32) oldBits);
+ PRINTF ("EmRegsEZ::ButtonEvent: newBits = 0x%02lX", (uint32) newBits);
+
+ // Set the interrupt bits for the bits that went from off to on.
+ // These get cleared when portDData is written to.
+
+ fPortDEdge |= newBits & ~oldBits;
+
+ PRINTF ("EmRegsEZ::ButtonEvent: fPortDEdge = 0x%02lX", (uint32) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegsEZ::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::HotSyncEvent
+// ---------------------------------------------------------------------------
+// Handles a HotSync button event by updating the appropriate registers.
+
+void EmRegsEZ::HotSyncEvent (Bool buttonIsDown)
+{
+ // If the button changes state, set or clear the HotSync interrupt.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ if (buttonIsDown)
+ {
+ intPendingHi |= hwrEZ328IntHiIRQ1;
+ fHotSyncButtonDown = true;
+ }
+ else
+ {
+ intPendingHi &= ~hwrEZ328IntHiIRQ1;
+ fHotSyncButtonDown = false;
+ }
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetKeyBits
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsEZ::GetKeyBits (void)
+{
+ // "Keys" (that is, buttons) are read from the Port D Data register.
+ // There are 7 or 8 keys that can be pressed, but only 4 bits are
+ // available in the Port D Data register for reporting pressed keys.
+ // Therefore, the keys are organized into a matrix, one row or which
+ // can be requested and reported at a time. This function determines
+ // what row is being requested, and sets the appropriate Port D Data
+ // bits for the keys are are currently pressed.
+
+ int numRows;
+ int numCols;
+ uint16 keyMap[16];
+ Bool rows[4];
+
+ this->GetKeyInfo (&numRows, &numCols, keyMap, rows);
+
+ uint8 keyData = 0;
+
+ // Walk the rows, looking for one that is requested.
+
+ for (int row = 0; row < numRows; ++row)
+ {
+ if (rows[row])
+ {
+ // Walk the columns, looking for ones that have a pressed key.
+
+ for (int col = 0; col < numCols; ++col)
+ {
+ // Get the key corresponding to this row and column.
+ // If we've recorded (in fKeyBits) that this key is
+ // pressed, then set its column bit.
+
+ uint16 key = keyMap[row * numCols + col];
+ if ((key & fKeyBits) != 0)
+ {
+ keyData |= (1 << col);
+ }
+ }
+ }
+ }
+
+ UInt8 portFDir = READ_REGISTER (portFDir);
+ UInt8 portFData = READ_REGISTER (portFData);
+
+ PRINTF ("EmRegsEZ::GetKeyBits: numRows = %d, numCols = %d", numRows, numCols);
+ PRINTF ("EmRegsEZ::GetKeyBits: portFDir = 0x%02lX, portFData = 0x%02lX", (uint32) portFDir, (uint32) portFData);
+ PRINTF ("EmRegsEZ::GetKeyBits: rows[0] = %d, [1] = %d, [2] = %d, [3] = %d", rows[0], rows[1], rows[2], rows[3]);
+// PRINTF ("EmRegsEZ::GetKeyBits: keyMap[0] = %2d, [1] = %2d, [2] = %2d, [3] = %2d", keyMap[0], keyMap[1], keyMap[2], keyMap[3]);
+// PRINTF ("EmRegsEZ::GetKeyBits: keyMap[4] = %2d, [5] = %2d, [6] = %2d, [7] = %2d", keyMap[4], keyMap[5], keyMap[6], keyMap[7]);
+// PRINTF ("EmRegsEZ::GetKeyBits: keyMap[8] = %2d, [9] = %2d, [A] = %2d, [B] = %2d", keyMap[8], keyMap[9], keyMap[10], keyMap[11]);
+// PRINTF ("EmRegsEZ::GetKeyBits: keyMap[C] = %2d, [D] = %2d, [E] = %2d, [F] = %2d", keyMap[12], keyMap[13], keyMap[14], keyMap[15]);
+ PRINTF ("EmRegsEZ::GetKeyBits: fKeyBits = 0x%04lX", (uint32) fKeyBits);
+ PRINTF ("EmRegsEZ::GetKeyBits: keyData = 0x%02lX", (uint32) keyData);
+
+ return keyData;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::ButtonToBits
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsEZ::ButtonToBits (SkinElementType button)
+{
+ uint16 bitNumber = 0;
+ switch (button)
+ {
+ case kElement_None: break;
+
+ case kElement_PowerButton: bitNumber = keyBitPower; break;
+ case kElement_UpButton: bitNumber = keyBitPageUp; break;
+ case kElement_DownButton: bitNumber = keyBitPageDown; break;
+ case kElement_App1Button: bitNumber = keyBitHard1; break;
+ case kElement_App2Button: bitNumber = keyBitHard2; break;
+ case kElement_App3Button: bitNumber = keyBitHard3; break;
+ case kElement_App4Button: bitNumber = keyBitHard4; break;
+ case kElement_CradleButton: bitNumber = keyBitCradle; break;
+ case kElement_Antenna: bitNumber = keyBitAntenna; break;
+ case kElement_ContrastButton: bitNumber = keyBitContrast; break;
+
+ default: EmAssert (false);
+ }
+
+ return bitNumber;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZ::GetSPISlave (void)
+{
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UpdateInterrupts
+// ---------------------------------------------------------------------------
+// Determines whether an interrupt has occurred by copying the Interrupt
+// Pending Register to the Interrupt Status Register.
+
+void EmRegsEZ::UpdateInterrupts (void)
+{
+ // Copy the Interrupt Pending Register to the Interrupt Status
+ // Register, but ignore interrupts that are being masked.
+
+ // Note: this function is not sensitive to the byte ordering of the registers,
+ // so their contents don't need to be accessed via READ_REGISTER or WRITE_REGISTER.
+
+ f68EZ328Regs.intStatusHi = f68EZ328Regs.intPendingHi & ~f68EZ328Regs.intMaskHi;
+ f68EZ328Regs.intStatusLo = f68EZ328Regs.intPendingLo & ~f68EZ328Regs.intMaskLo;
+
+ PRINTF ("EmRegsEZ::UpdateInterrupts: intMask = 0x%04lX %04lX",
+ (uint32) f68EZ328Regs.intMaskHi, (uint32) f68EZ328Regs.intMaskLo);
+
+ PRINTF ("EmRegsEZ::UpdateInterrupts: intPending = 0x%04lX %04lX",
+ (uint32) f68EZ328Regs.intPendingHi, (uint32) f68EZ328Regs.intPendingLo);
+
+ // If the Interrupt Status Register isn't clear, flag an interrupt.
+
+ if (f68EZ328Regs.intStatusHi || f68EZ328Regs.intStatusLo)
+ {
+ regs.spcflags |= SPCFLAG_INT;
+
+ PRINTF ("EmRegsEZ::UpdateInterrupts: intStatus = 0x%04lX %04lX",
+ (uint32) f68EZ328Regs.intStatusHi, (uint32) f68EZ328Regs.intStatusLo);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UpdatePortDInterrupts
+// ---------------------------------------------------------------------------
+// Determine what interrupts need to be generated based on the current
+// settings in portDData and fPortDEdge.
+
+void EmRegsEZ::UpdatePortDInterrupts (void)
+{
+ // Update INT0-INT3 of the Interrupt-Pending register (bits 8-11 of the low word).
+
+ PRINTF ("EmRegsEZ::UpdatePortDInterrupts:");
+
+ // First, get those bits and clear them out.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwrEZ328IntLoAllKeys;
+
+
+ // Initialize the variable to hold the new interrupt settings.
+
+ uint8 newBits = 0;
+
+
+ // Get some other values we're going to need:
+
+ uint8 portDDir = READ_REGISTER (portDDir); // Interrupt on inputs only (when pin is low)
+ uint8 portDData = EmHAL::GetPortInputValue ('D');
+ uint8 portDPolarity = READ_REGISTER (portDPolarity);
+ uint8 portDIntReqEn = READ_REGISTER (portDIntReqEn);
+ uint8 portDKbdIntEn = READ_REGISTER (portDKbdIntEn);
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+ // We have a line-level interrupt if:
+ //
+ // - line-level interrupts are requested
+ // - the GPIO bit matches the polarity bit
+
+ newBits |= ~portDIntEdge & portDData & portDPolarity;
+ newBits |= ~portDIntEdge & ~portDData & ~portDPolarity;
+
+
+ // We have an edge interrupt if:
+ //
+ // - edge interrupts are requested
+ // - an edge has been recorded
+ //
+ // Note that we should distinguish between rising and falling edges.
+ // For historical reasons, that's not done, and the Palm OS doesn't
+ // look for them, so it's OK for now.
+ //
+ // Edge interrupts on INT[3:0] should not wake up a sleeping device.
+
+ uint16 pllControl = READ_REGISTER (pllControl);
+
+ if (pllControl & hwrEZ328PLLControlDisable)
+ {
+ newBits |= portDIntEdge & fPortDEdge & portDPolarity & 0xF0;
+ newBits |= portDIntEdge & 0 & ~portDPolarity & 0xF0;
+ }
+ else
+ {
+ newBits |= portDIntEdge & fPortDEdge & portDPolarity;
+ newBits |= portDIntEdge & 0 & ~portDPolarity;
+ }
+
+
+ // Only have interrupts if they're enabled and the pin is configured for input.
+
+ newBits &= portDIntReqEn & ~portDDir;
+
+ PRINTF ("EmRegsEZ::UpdatePortDInterrupts: Dir Data Pol Req Edg PDE bits");
+ PRINTF ("EmRegsEZ::UpdatePortDInterrupts: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (uint32) portDDir, (uint32) portDData, (uint32) portDPolarity, (uint32) portDIntReqEn, (uint32) portDIntEdge,
+ (uint32) fPortDEdge, (uint32) newBits);
+
+
+ // Determine if the KB interrupt needs to be asserted. It is if:
+ //
+ // A Port D Data bit is on.
+ // The bit is configured for input (?)
+ // The bit is configured to be OR'd into the interrupt.
+
+ uint8 KB = portDData & ~portDDir & portDKbdIntEn;
+
+ if (KB)
+ intPendingLo |= hwrEZ328IntLoKbd;
+ else
+ intPendingLo &= ~hwrEZ328IntLoKbd;
+
+
+ // Merge in the new values and write out the result.
+
+ intPendingLo |= (((uint16) newBits) << hwrEZ328IntLoInt0Bit) & hwrEZ328IntLoAllKeys;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UpdateRTCInterrupts
+// ---------------------------------------------------------------------------
+// Determine whether to set or clear the RTC bit in the interrupt pending
+// register based on the current RTC register values.
+
+void EmRegsEZ::UpdateRTCInterrupts (void)
+{
+ // See if the RTC is enabled.
+
+ Bool rtcEnabled = (READ_REGISTER (rtcControl) & hwrEZ328RTCControlRTCEnable) != 0;
+
+ // See if there are any RTC events that need to trigger an interrupt.
+
+#define BITS_TO_CHECK ( \
+ hwrEZ328RTCIntEnableSec | \
+ hwrEZ328RTCIntEnable24Hr | \
+ hwrEZ328RTCIntEnableAlarm | \
+ hwrEZ328RTCIntEnableMinute | \
+ hwrEZ328RTCIntEnableStopWatch )
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+ uint16 rtcIntEnable = READ_REGISTER (rtcIntEnable);
+ uint16 rtcIntPending = rtcIntStatus & rtcIntEnable & BITS_TO_CHECK;
+
+ Bool havePendingEvents = rtcIntPending != 0;
+
+ // If the RTC is enabled and there are pending events, set the interrupt.
+ // Otherwise, clear the interrupt.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo);
+
+ if (rtcEnabled && havePendingEvents)
+ {
+ intPendingLo |= hwrEZ328IntLoRTC; // have events, so set interrupt
+ }
+ else
+ {
+ intPendingLo &= ~hwrEZ328IntLoRTC; // no events, so clear interrupt
+ }
+
+ // Update the interrupt pending register.
+
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::IDDetectAsserted
+// ---------------------------------------------------------------------------
+// cf. HwrIdentifyFeatures and HwrPreRAMInit.
+
+Bool EmRegsEZ::IDDetectAsserted (void)
+{
+ uint8 portGDir = READ_REGISTER(portGDir);
+ uint8 portGData = READ_REGISTER(portGData);
+ uint8 portGPullupEn = READ_REGISTER(portGPullupEn);
+ uint8 portGSelect = READ_REGISTER(portGSelect);
+ const uint8 kMask = hwrEZPortGIDDetect;
+
+ return (portGDir & kMask) == kMask &&
+ (portGData & kMask) == 0 &&
+ (portGPullupEn & kMask) == 0 &&
+ (portGSelect & kMask) == kMask;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetHardwareID
+// ---------------------------------------------------------------------------
+
+UInt8 EmRegsEZ::GetHardwareID (void)
+{
+ // Determine the hardware ID.
+
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ long miscFlags = device.HardwareID ();
+
+ // Reverse map the following:
+
+// GHwrMiscFlags = 0;
+// if ((keyState & hwrEZPortDKbdCol0) == 0) GHwrMiscFlags |= hwrMiscFlagID1;
+// if ((keyState & hwrEZPortDKbdCol1) == 0) GHwrMiscFlags |= hwrMiscFlagID2;
+// if ((keyState & hwrEZPortDKbdCol2) == 0) GHwrMiscFlags |= hwrMiscFlagID3;
+// if ((keyState & hwrEZPortDKbdCol3) == 0) GHwrMiscFlags |= hwrMiscFlagID4;
+
+ UInt8 keyState = ~0;
+
+ if ((miscFlags & hwrMiscFlagID1) != 0) keyState &= ~hwrEZPortDKbdCol0;
+ if ((miscFlags & hwrMiscFlagID2) != 0) keyState &= ~hwrEZPortDKbdCol1;
+ if ((miscFlags & hwrMiscFlagID3) != 0) keyState &= ~hwrEZPortDKbdCol2;
+ if ((miscFlags & hwrMiscFlagID4) != 0) keyState &= ~hwrEZPortDKbdCol3;
+
+ return keyState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UARTStateChanged
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::UARTStateChanged (Bool sendTxData)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_DragonballEZ);
+
+ EmRegsEZ::MarshalUARTState (state);
+ fUART->StateChanged (state, sendTxData);
+ EmRegsEZ::UnmarshalUARTState (state);
+
+ EmRegsEZ::UpdateUARTInterrupts (state);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UpdateUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::UpdateUARTState (Bool refreshRxData)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_DragonballEZ);
+
+ EmRegsEZ::MarshalUARTState (state);
+ fUART->UpdateState (state, refreshRxData);
+ EmRegsEZ::UnmarshalUARTState (state);
+
+ EmRegsEZ::UpdateUARTInterrupts (state);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UpdateUARTInterrupts
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::UpdateUARTInterrupts (const EmUARTDragonball::State& state)
+{
+ // Generate the appropriate interrupts.
+
+ if (state.RX_FULL_ENABLE && state.RX_FIFO_FULL ||
+ state.RX_HALF_ENABLE && state.RX_FIFO_HALF ||
+ state.RX_RDY_ENABLE && state.DATA_READY ||
+ state.TX_EMPTY_ENABLE && state.TX_FIFO_EMPTY ||
+ state.TX_HALF_ENABLE && state.TX_FIFO_HALF ||
+ state.TX_AVAIL_ENABLE && state.TX_AVAIL)
+ {
+ // Set the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwrEZ328IntLoUART);
+ }
+ else
+ {
+ // Clear the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) & ~hwrEZ328IntLoUART);
+ }
+
+ // Respond to the new interrupt state.
+
+ EmRegsEZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::MarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::MarshalUARTState (EmUARTDragonball::State& state)
+{
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uBaud = READ_REGISTER (uBaud);
+ uint16 uReceive = READ_REGISTER (uReceive);
+ uint16 uTransmit = READ_REGISTER (uTransmit);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ state.UART_ENABLE = (uControl & hwrEZ328UControlUARTEnable) != 0;
+ state.RX_ENABLE = (uControl & hwrEZ328UControlRxEnable) != 0;
+ state.TX_ENABLE = (uControl & hwrEZ328UControlTxEnable) != 0;
+ state.RX_CLK_CONT = (uControl & hwrEZ328UControlRxClock1xSync) != 0;
+ state.PARITY_EN = (uControl & hwrEZ328UControlParityEn) != 0;
+ state.ODD_EVEN = (uControl & hwrEZ328UControlParityOdd) != 0;
+ state.STOP_BITS = (uControl & hwrEZ328UControlStopBits2) != 0;
+ state.CHAR8_7 = (uControl & hwrEZ328UControlDataBits8) != 0;
+// state.GPIO_DELTA_ENABLE = (uControl & hwr328UControlGPIODeltaEn) != 0; // 68328 only
+ state.OLD_ENABLE = (uControl & hwrEZ328UControlOldDataEn) != 0; // 68EZ328 only
+ state.CTS_DELTA_ENABLE = (uControl & hwrEZ328UControlCTSDeltaEn) != 0;
+ state.RX_FULL_ENABLE = (uControl & hwrEZ328UControlRxFullEn) != 0;
+ state.RX_HALF_ENABLE = (uControl & hwrEZ328UControlRxHalfEn) != 0;
+ state.RX_RDY_ENABLE = (uControl & hwrEZ328UControlRxRdyEn) != 0;
+ state.TX_EMPTY_ENABLE = (uControl & hwrEZ328UControlTxEmptyEn) != 0;
+ state.TX_HALF_ENABLE = (uControl & hwrEZ328UControlTxHalfEn) != 0;
+ state.TX_AVAIL_ENABLE = (uControl & hwrEZ328UControlTxAvailEn) != 0;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+// state.GPIO_DELTA = (uBaud & hwr328UBaudGPIODelta) != 0; // 68328 only
+// state.GPIO = (uBaud & hwr328UBaudGPIOData) != 0; // 68328 only
+// state.GPIO_DIR = (uBaud & hwr328UBaudGPIODirOut) != 0; // 68328 only
+// state.GPIO_SRC = (uBaud & hwrEZ328UBaudGPIOSrcBaudGen) != 0; // 68328 only
+ state.UCLK_DIR = (uBaud & hwrEZ328UBaudUCLKDirOut) != 0; // 68EZ328 only
+ state.BAUD_SRC = (uBaud & hwrEZ328UBaudBaudSrcUCLK) != 0;
+ state.DIVIDE = (uBaud & hwrEZ328UBaudDivider) >> hwrEZ328UBaudDivideBitOffset;
+ state.PRESCALER = (uBaud & hwrEZ328UBaudPrescaler);
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ state.RX_FIFO_FULL = (uReceive & hwrEZ328UReceiveFIFOFull) != 0;
+ state.RX_FIFO_HALF = (uReceive & hwrEZ328UReceiveFIFOHalf) != 0;
+ state.DATA_READY = (uReceive & hwrEZ328UReceiveDataRdy) != 0;
+ state.OLD_DATA = (uReceive & hwrEZ328UReceiveOldData) != 0; // 68EZ328 only
+ state.OVRUN = (uReceive & hwrEZ328UReceiveOverrunErr) != 0;
+ state.FRAME_ERROR = (uReceive & hwrEZ328UReceiveFrameErr) != 0;
+ state.BREAK = (uReceive & hwrEZ328UReceiveBreakErr) != 0;
+ state.PARITY_ERROR = (uReceive & hwrEZ328UReceiveParityErr) != 0;
+ state.RX_DATA = (uReceive & hwrEZ328UReceiveData);
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ state.TX_FIFO_EMPTY = (uTransmit & hwrEZ328UTransmitFIFOEmpty) != 0;
+ state.TX_FIFO_HALF = (uTransmit & hwrEZ328UTransmitFIFOHalf) != 0;
+ state.TX_AVAIL = (uTransmit & hwrEZ328UTransmitTxAvail) != 0;
+ state.SEND_BREAK = (uTransmit & hwrEZ328UTransmitSendBreak) != 0;
+ state.IGNORE_CTS = (uTransmit & hwrEZ328UTransmitIgnoreCTS) != 0;
+ state.BUSY = (uTransmit & hwrEZ328UTransmitBusy) != 0; // 68EZ328 only
+ state.CTS_STATUS = (uTransmit & hwrEZ328UTransmitCTSStatus) != 0;
+ state.CTS_DELTA = (uTransmit & hwrEZ328UTransmitCTSDelta) != 0;
+ state.TX_DATA = (uTransmit & hwrEZ328UTransmitData);
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+ state.BAUD_TEST = (uMisc & hwrEZ328UMiscBaudTest) != 0; // 68EZ328 only
+ state.CLK_SRC = (uMisc & hwrEZ328UMiscClkSrcUCLK) != 0;
+ state.FORCE_PERR = (uMisc & hwrEZ328UMiscForceParityErr) != 0;
+ state.LOOP = (uMisc & hwrEZ328UMiscLoopback) != 0;
+ state.BAUD_RESET = (uMisc & hwrEZ328UMiscBaudReset) != 0; // 68EZ328 only
+ state.IR_TEST = (uMisc & hwrEZ328UMiscIRTestEn) != 0; // 68EZ328 only
+ state.RTS_CONT = (uMisc & hwrEZ328UMiscRTSThruFIFO) != 0;
+ state.RTS = (uMisc & hwrEZ328UMiscRTSOut) != 0;
+ state.IRDA_ENABLE = (uMisc & hwrEZ328UMiscIRDAEn) != 0;
+ state.IRDA_LOOP = (uMisc & hwrEZ328UMiscLoopIRDA) != 0;
+ state.RX_POL = (uMisc & hwrEZ328UMiscRXPolarityInv) != 0; // 68EZ328 only
+ state.TX_POL = (uMisc & hwrEZ328UMiscTXPolarityInv) != 0; // 68EZ328 only
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::UnmarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::UnmarshalUARTState (const EmUARTDragonball::State& state)
+{
+ uint16 uControl = 0;
+ uint16 uBaud = 0;
+ uint16 uReceive = 0;
+ uint16 uTransmit = 0;
+ uint16 uMisc = 0;
+
+ if (state.UART_ENABLE) uControl |= hwrEZ328UControlUARTEnable;
+ if (state.RX_ENABLE) uControl |= hwrEZ328UControlRxEnable;
+ if (state.TX_ENABLE) uControl |= hwrEZ328UControlTxEnable;
+ if (state.RX_CLK_CONT) uControl |= hwrEZ328UControlRxClock1xSync;
+ if (state.PARITY_EN) uControl |= hwrEZ328UControlParityEn;
+ if (state.ODD_EVEN) uControl |= hwrEZ328UControlParityOdd;
+ if (state.STOP_BITS) uControl |= hwrEZ328UControlStopBits2;
+ if (state.CHAR8_7) uControl |= hwrEZ328UControlDataBits8;
+// if (state.GPIO_DELTA_ENABLE)uControl |= hwr328UControlGPIODeltaEn; // 68328 only
+ if (state.OLD_ENABLE) uControl |= hwrEZ328UControlOldDataEn; // 68EZ328 only
+ if (state.CTS_DELTA_ENABLE) uControl |= hwrEZ328UControlCTSDeltaEn;
+ if (state.RX_FULL_ENABLE) uControl |= hwrEZ328UControlRxFullEn;
+ if (state.RX_HALF_ENABLE) uControl |= hwrEZ328UControlRxHalfEn;
+ if (state.RX_RDY_ENABLE) uControl |= hwrEZ328UControlRxRdyEn;
+ if (state.TX_EMPTY_ENABLE) uControl |= hwrEZ328UControlTxEmptyEn;
+ if (state.TX_HALF_ENABLE) uControl |= hwrEZ328UControlTxHalfEn;
+ if (state.TX_AVAIL_ENABLE) uControl |= hwrEZ328UControlTxAvailEn;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+// if (state.GPIO_DELTA) uBaud |= hwr328UBaudGPIODelta; // 68328 only
+// if (state.GPIO) uBaud |= hwr328UBaudGPIOData; // 68328 only
+// if (state.GPIO_DIR) uBaud |= hwr328UBaudGPIODirOut; // 68328 only
+// if (state.GPIO_SRC) uBaud |= hwr328UBaudGPIOSrcBaudGen; // 68328 only
+ if (state.UCLK_DIR) uBaud |= hwrEZ328UBaudUCLKDirOut; // 68EZ328 only
+ if (state.BAUD_SRC) uBaud |= hwrEZ328UBaudBaudSrcUCLK;
+
+ uBaud |= (state.DIVIDE << hwrEZ328UBaudDivideBitOffset) & hwrEZ328UBaudDivider;
+ uBaud |= (state.PRESCALER) & hwrEZ328UBaudPrescaler;
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ if (state.RX_FIFO_FULL) uReceive |= hwrEZ328UReceiveFIFOFull;
+ if (state.RX_FIFO_HALF) uReceive |= hwrEZ328UReceiveFIFOHalf;
+ if (state.DATA_READY) uReceive |= hwrEZ328UReceiveDataRdy;
+ if (state.OLD_DATA) uReceive |= hwrEZ328UReceiveOldData; // 68EZ328 only
+ if (state.OVRUN) uReceive |= hwrEZ328UReceiveOverrunErr;
+ if (state.FRAME_ERROR) uReceive |= hwrEZ328UReceiveFrameErr;
+ if (state.BREAK) uReceive |= hwrEZ328UReceiveBreakErr;
+ if (state.PARITY_ERROR) uReceive |= hwrEZ328UReceiveParityErr;
+
+ uReceive |= (state.RX_DATA) & hwrEZ328UReceiveData;
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ if (state.TX_FIFO_EMPTY) uTransmit |= hwrEZ328UTransmitFIFOEmpty;
+ if (state.TX_FIFO_HALF) uTransmit |= hwrEZ328UTransmitFIFOHalf;
+ if (state.TX_AVAIL) uTransmit |= hwrEZ328UTransmitTxAvail;
+ if (state.SEND_BREAK) uTransmit |= hwrEZ328UTransmitSendBreak;
+ if (state.IGNORE_CTS) uTransmit |= hwrEZ328UTransmitIgnoreCTS;
+ if (state.BUSY) uTransmit |= hwrEZ328UTransmitBusy; // 68EZ328 only
+ if (state.CTS_STATUS) uTransmit |= hwrEZ328UTransmitCTSStatus;
+ if (state.CTS_DELTA) uTransmit |= hwrEZ328UTransmitCTSDelta;
+
+ uTransmit |= (state.TX_DATA) & hwrEZ328UTransmitData;
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+ if (state.BAUD_TEST) uMisc |= hwrEZ328UMiscBaudTest; // 68EZ328 only
+ if (state.CLK_SRC) uMisc |= hwrEZ328UMiscClkSrcUCLK;
+ if (state.FORCE_PERR) uMisc |= hwrEZ328UMiscForceParityErr;
+ if (state.LOOP) uMisc |= hwrEZ328UMiscLoopback;
+ if (state.BAUD_RESET) uMisc |= hwrEZ328UMiscBaudReset; // 68EZ328 only
+ if (state.IR_TEST) uMisc |= hwrEZ328UMiscIRTestEn; // 68EZ328 only
+ if (state.RTS_CONT) uMisc |= hwrEZ328UMiscRTSThruFIFO;
+ if (state.RTS) uMisc |= hwrEZ328UMiscRTSOut;
+ if (state.IRDA_ENABLE) uMisc |= hwrEZ328UMiscIRDAEn;
+ if (state.IRDA_LOOP) uMisc |= hwrEZ328UMiscLoopIRDA;
+ if (state.RX_POL) uMisc |= hwrEZ328UMiscRXPolarityInv; // 68EZ328 only
+ if (state.TX_POL) uMisc |= hwrEZ328UMiscTXPolarityInv; // 68EZ328 only
+
+ WRITE_REGISTER (uControl, uControl);
+ WRITE_REGISTER (uBaud, uBaud);
+ WRITE_REGISTER (uReceive, uReceive);
+ WRITE_REGISTER (uTransmit, uTransmit);
+ WRITE_REGISTER (uMisc, uMisc);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::GetPort
+// ---------------------------------------------------------------------------
+// Given an address, return a value indicating what port it is associated with.
+
+int EmRegsEZ::GetPort (emuptr address)
+{
+ const long MASK = 0x00000FF8;
+
+ switch (address & MASK)
+ {
+ case 0x0400: return 'A';
+ case 0x0408: return 'B';
+ case 0x0410: return 'C';
+ case 0x0418: return 'D';
+ case 0x0420: return 'E';
+ case 0x0428: return 'F';
+ case 0x0430: return 'G';
+ }
+
+ EmAssert (false);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZ::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegsEZ::PrvGetPalette (RGBList& thePalette)
+{
+ // !!! TBD
+ Preference<RGBType> pref1 (kPrefKeyBackgroundColor);
+ Preference<RGBType> pref2 (kPrefKeyHighlightColor);
+
+ RGBType foreground (0, 0, 0);
+ RGBType background;
+
+ if (this->GetLCDBacklightOn ())
+ {
+ if (pref2.Loaded ())
+ background = *pref2;
+ else
+ background = ::SkinGetHighlightColor ();
+ }
+ else
+ {
+ if (pref1.Loaded ())
+ background = *pref1;
+ else
+ background = ::SkinGetBackgroundColor ();
+ }
+
+ long br = ((long) background.fRed);
+ long bg = ((long) background.fGreen);
+ long bb = ((long) background.fBlue);
+
+ long dr = ((long) foreground.fRed) - ((long) background.fRed);
+ long dg = ((long) foreground.fGreen) - ((long) background.fGreen);
+ long db = ((long) foreground.fBlue) - ((long) background.fBlue);
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x03);
+ int32 numColors = 1 << bpp;
+ thePalette.resize (numColors);
+
+ for (int color = 0; color < numColors; ++color)
+ {
+ thePalette[color].fRed = (UInt8) (br + dr * color / (numColors - 1));
+ thePalette[color].fGreen = (UInt8) (bg + dg * color / (numColors - 1));
+ thePalette[color].fBlue = (UInt8) (bb + db * color / (numColors - 1));
+ }
+}
diff --git a/SrcShared/Hardware/EmRegsEZ.h b/SrcShared/Hardware/EmRegsEZ.h
new file mode 100644
index 0000000..d9c69b2
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZ.h
@@ -0,0 +1,143 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZ_h
+#define EmRegsEZ_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmRegs.h" // EmRegs
+#include "EmStructs.h" // RGBList
+#include "EmUARTDragonball.h" // EmUARTDragonball::State
+
+class EmScreenUpdateInfo;
+class EmSPISlave;
+
+
+class EmRegsEZ : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsEZ (void);
+ virtual ~EmRegsEZ (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHALHandler overrides
+ virtual void Cycle (Bool sleeping);
+ virtual void CycleSlowly (Bool sleeping);
+
+ virtual void ButtonEvent (SkinElementType, Bool buttonIsDown);
+ virtual void TurnSoundOff (void);
+ virtual void ResetTimer (void);
+ virtual void ResetRTC (void);
+
+ virtual int32 GetInterruptLevel (void);
+ virtual int32 GetInterruptBase (void);
+
+ virtual Bool GetLCDScreenOn (void) = 0;
+ virtual Bool GetLCDBacklightOn (void) = 0;
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr&, emuptr&);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+ virtual int32 GetDynamicHeapSize (void);
+ virtual int32 GetROMSize (void);
+ virtual emuptr GetROMBaseAddress (void);
+ virtual Bool ChipSelectsConfigured (void);
+ virtual int32 GetSystemClockFrequency (void);
+ virtual Bool GetCanStop (void);
+ virtual Bool GetAsleep (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void PortDataChanged (int, uint8, uint8);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows) = 0;
+
+ protected:
+ uint32 pllFreqSelRead (emuptr address, int size);
+ uint32 portXDataRead (emuptr address, int size);
+ uint32 tmr1StatusRead (emuptr address, int size);
+ uint32 uartRead (emuptr address, int size);
+ uint32 rtcHourMinSecRead (emuptr address, int size);
+
+ void csASelectWrite (emuptr address, int size, uint32 value);
+ void csDSelectWrite (emuptr address, int size, uint32 value);
+ void intMaskHiWrite (emuptr address, int size, uint32 value);
+ void intMaskLoWrite (emuptr address, int size, uint32 value);
+ void intStatusHiWrite (emuptr address, int size, uint32 value);
+ void portXDataWrite (emuptr address, int size, uint32 value);
+ void portDIntReqEnWrite (emuptr address, int size, uint32 value);
+ void tmr1StatusWrite (emuptr address, int size, uint32 value);
+ void spiMasterControlWrite (emuptr address, int size, uint32 value);
+ void uartWrite (emuptr address, int size, uint32 value);
+ void lcdRegisterWrite (emuptr address, int size, uint32 value);
+ void rtcControlWrite (emuptr address, int size, uint32 value);
+ void rtcIntStatusWrite (emuptr address, int size, uint32 value);
+ void rtcIntEnableWrite (emuptr address, int size, uint32 value);
+
+ protected:
+ void HotSyncEvent (Bool buttonIsDown);
+
+ virtual uint8 GetKeyBits (void);
+ virtual uint16 ButtonToBits (SkinElementType);
+ virtual EmSPISlave* GetSPISlave (void);
+
+ protected:
+ void UpdateInterrupts (void);
+ void UpdatePortDInterrupts (void);
+ void UpdateRTCInterrupts (void);
+
+ protected:
+ Bool IDDetectAsserted (void);
+ UInt8 GetHardwareID (void);
+
+ protected:
+ void UARTStateChanged (Bool sendTxData);
+ void UpdateUARTState (Bool refreshRxData);
+ void UpdateUARTInterrupts (const EmUARTDragonball::State& state);
+ void MarshalUARTState (EmUARTDragonball::State& state);
+ void UnmarshalUARTState (const EmUARTDragonball::State& state);
+
+ protected:
+ int GetPort (emuptr address);
+ void PrvGetPalette (RGBList& thePalette);
+
+ protected:
+ HwrM68EZ328Type f68EZ328Regs;
+ bool fHotSyncButtonDown;
+ uint16 fKeyBits;
+ uint16 fLastTmr1Status;
+ uint8 fPortDEdge;
+ uint32 fPortDDataCount;
+
+ uint32 fHour;
+ uint32 fMin;
+ uint32 fSec;
+ uint32 fTick;
+ uint32 fCycle;
+
+ EmUARTDragonball* fUART;
+};
+
+#endif /* EmRegsEZ_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmIIIc.cpp b/SrcShared/Hardware/EmRegsEZPalmIIIc.cpp
new file mode 100644
index 0000000..bc4744e
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmIIIc.cpp
@@ -0,0 +1,222 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZPalmIIIc.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "EZAustin/IncsPrv/HardwareAustin.h" // hwrEZPortCKbdRow0, hwrEZPortBRS232Enable, etc.
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::EmRegsEZPalmIIIc
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmIIIc::EmRegsEZPalmIIIc (void) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::~EmRegsEZPalmIIIc
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmIIIc::~EmRegsEZPalmIIIc (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmIIIc::GetLCDScreenOn (void)
+{
+ // Override the Dragonball version and let the SED 1375 handle it.
+
+ return EmHALHandler::GetLCDScreenOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmIIIc::GetLCDBacklightOn (void)
+{
+ // Override the Dragonball version and let the SED 1375 handle it.
+
+ return EmHALHandler::GetLCDBacklightOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmIIIc::GetLCDHasFrame (void)
+{
+ // Override the Dragonball version and let the SED 1375 handle it.
+
+ return EmHALHandler::GetLCDHasFrame ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmIIIc::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Override the Dragonball version and let the SED 1375 handle it.
+
+ EmHALHandler::GetLCDBeginEnd (begin, end);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmIIIc::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Override the Dragonball version and let the SED 1375 handle it.
+
+ EmHALHandler::GetLCDScanlines (info);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZPalmIIIc::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portBData) & hwrEZPortBRS232Enable) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & hwrEZPortGIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZPalmIIIc::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ if (port == 'F')
+ {
+ // Ensure that bit hwrEZPortFIXTRNL2 is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ // Make sure hwrEZPortFLCDPowered is always set, or HwrDisplayWake will hang
+
+ result |= hwrEZPortFIXTRNL2 | hwrEZPortFLCDPowered;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZPalmIIIc::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrEZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrEZPortDPowerFail;
+
+ // Make sure hwrEZPortDAdapterInstalled is set, or the dock-status routines
+ // will report that we're powered (even if we aren't docked!).
+
+ result |= hwrEZPortDAdapterInstalled;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmIIIc::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portCDir = READ_REGISTER (portCDir);
+ UInt8 portCData = READ_REGISTER (portCData);
+
+ rows[0] = (portCDir & hwrEZPortCKbdRow0) != 0 && (portCData & hwrEZPortCKbdRow0) == 0;
+ rows[1] = (portCDir & hwrEZPortCKbdRow1) != 0 && (portCData & hwrEZPortCKbdRow1) == 0;
+ rows[2] = (portCDir & hwrEZPortCKbdRow2) != 0 && (portCData & hwrEZPortCKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmIIIc::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZPalmIIIc::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portBData) & hwrEZPortBCS_ADC) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZPalmIIIc.h b/SrcShared/Hardware/EmRegsEZPalmIIIc.h
new file mode 100644
index 0000000..704f8a0
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmIIIc.h
@@ -0,0 +1,48 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmIIIc_h
+#define EmRegsEZPalmIIIc_h
+
+#include "EmRegsEZ.h"
+
+class EmScreenUpdateInfo;
+
+
+class EmRegsEZPalmIIIc : public EmRegsEZ
+{
+ public:
+ EmRegsEZPalmIIIc (void);
+ virtual ~EmRegsEZPalmIIIc (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr&, emuptr&);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsEZPalmIIIc_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmIIIe.h b/SrcShared/Hardware/EmRegsEZPalmIIIe.h
new file mode 100644
index 0000000..a0f356d
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmIIIe.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmIIIe_h
+#define EmRegsEZPalmIIIe_h
+
+#include "EmRegsEZPalmV.h"
+
+typedef EmRegsEZPalmV EmRegsEZPalmIIIe;
+
+#endif /* EmRegsEZPalmIIIe_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmIIIx.h b/SrcShared/Hardware/EmRegsEZPalmIIIx.h
new file mode 100644
index 0000000..7ab02de
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmIIIx.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmIIIx_h
+#define EmRegsEZPalmIIIx_h
+
+#include "EmRegsEZPalmV.h"
+
+typedef EmRegsEZPalmV EmRegsEZPalmIIIx;
+
+#endif /* EmRegsEZPalmIIIx_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmM100.cpp b/SrcShared/Hardware/EmRegsEZPalmM100.cpp
new file mode 100644
index 0000000..684d0ee
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmM100.cpp
@@ -0,0 +1,247 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZPalmM100.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmSession.h" // GetDevice
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+
+// The following are taken from the m100 version of HardwareEZ.h.
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrEZPortBKbdRow0 0x01
+#define hwrEZPortBLCDVccOff 0x02 // (L) LCD Vcc On
+#define hwrEZPortBKbdRow1 0x08
+#define hwrEZPortBKbdRow2 0x40
+#define hwrEZPortBKbdRows 0x49
+
+#define hwrEZPortBLCDAdjOn 0x40 // (L) LCD Contrast Adjust On (Brad Rev 0)
+
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+#define hwrEZPortCLCDEnableOn 0x80 // (H) LCD Enable
+
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+#define hwrEZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+#define hwrEZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+#define hwrEZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+#define hwrEZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+#define hwrEZPortDKeyBits 0x0F // (H) All Keyboard Columns
+#define hwrEZPortDDockButton 0x10 // (L) Dock Button (aka IRQ1) (edge, negative)
+#define hwrEZPortD232Enable 0x20 // (L) Serial Shutdown on Sumo Rev 1 (aka IRQ2)
+#define hwrEZPortDLCDBiasOn 0x40 // (H) LCD Bias on
+#define hwrEZPortDPowerFail 0x80 // (L) Power Fail Interrupt (aka IRQ6) (level, low)
+
+#define hwrEZPortDDataMaskBeforeWrite (~(hwrEZPortDKeyBits)) // Don't write ones to these bits!
+#define hwrEZPortDKeyOffset 0x0 // bits to shift to put Col 0 in msb
+
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrEZPortESpiTxD 0x01 // (L) SPI TXD (Internal)
+#define hwrEZPortESpiRxD 0x02 // (L) SPI RXD (Internal)
+#define hwrEZPortESpiClk 0x04 // SPI Clock
+#define hwrEZPortESpiBits 0x07 // all the SPI bits
+#define hwrEZPortERXD 0x10 // external RXD
+#define hwrEZPortETXD 0x20 // external TXD
+#define hwrEZPortECTS 0x80 // external CTS
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+#define hwrEZPortFLCDBiasData 0x01 // LCD Bias data
+#define hwrEZPortFPenIO 0x02 // (L) Pen Interrupt,Pen I/O
+#define hwrEZPortFLCDBiasStrb 0x04 // LCD Bias strobe
+#define hwrEZPortFBacklightOn 0x20 // (H) Backlight on
+#define hwrEZPortFLCDDispOn 0x40 // (H) LCD display on
+#define hwrEZPortFLCDBiasClk 0x80 // LCD Bias clock
+
+#define hwrEZPortFLCDAdjOn 0x01 // (L) LCD Contrast Adjust On (Brad Rev 1)
+#define hwrEZPortF232Enable 0x04 // (L) Shutdown Serial
+#define hwrEZPortFContrastPWM 0x01 // (L) PWM output for LCD contrast
+
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+#define hwrEZPortGDTACK 0x01 // (L) DTACK
+#define hwrEZPortGFree1 0x02 // (-) FREE5
+#define hwrEZPortGIDDetect 0x04 // (L) ID select (drives kbd)
+#define hwrEZPortGLiIonVoltReadDis 0x08 // (L) Enable A/D Voltage Divider
+#define hwrEZPortGIRShutdown 0x10 // (H) Shutdown IRDA
+#define hwrEZPortGADCOff 0x20 // (L) A/D Select
+
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { 0, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitPageUp, keyBitHard2, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::EmRegsEZPalmM100
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmM100::EmRegsEZPalmM100 (void) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::~EmRegsEZPalmM100
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmM100::~EmRegsEZPalmM100 (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmM100::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portFData) & hwrEZPortFLCDDispOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmM100::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portFData) & hwrEZPortFBacklightOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZPalmM100::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portDData) & hwrEZPortD232Enable) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & hwrEZPortGIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZPalmM100::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ // Return the hardware sub-ID.
+
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ result |= ~device.HardwareSubID ();
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZPalmM100::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrEZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrEZPortDPowerFail;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmM100::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portBDir = READ_REGISTER (portBDir);
+ UInt8 portBData = READ_REGISTER (portBData);
+
+ rows[0] = (portBDir & hwrEZPortBKbdRow0) != 0 && (portBData & hwrEZPortBKbdRow0) == 0;
+ rows[1] = (portBDir & hwrEZPortBKbdRow1) != 0 && (portBData & hwrEZPortBKbdRow1) == 0;
+ rows[2] = (portBDir & hwrEZPortBKbdRow2) != 0 && (portBData & hwrEZPortBKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmM100::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZPalmM100::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrEZPortGADCOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZPalmM100.h b/SrcShared/Hardware/EmRegsEZPalmM100.h
new file mode 100644
index 0000000..6b32d36
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmM100.h
@@ -0,0 +1,41 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZm100_h
+#define EmRegsEZm100_h
+
+#include "EmRegsEZ.h"
+
+class EmRegsEZPalmM100 : public EmRegsEZ
+{
+ public:
+ EmRegsEZPalmM100 (void);
+ virtual ~EmRegsEZPalmM100 (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsEZm100_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmV.cpp b/SrcShared/Hardware/EmRegsEZPalmV.cpp
new file mode 100644
index 0000000..ad59040
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmV.cpp
@@ -0,0 +1,179 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZPalmV.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmDevice.h" // HardwareSubID
+#include "EmSession.h" // GetDevice
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "EZSumo/IncsPrv/HardwareEZ.h" // hwrEZPortCLCDEnableOn, etc.
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::EmRegsEZPalmV
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmV::EmRegsEZPalmV (void) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::~EmRegsEZPalmV
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmV::~EmRegsEZPalmV (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmV::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portCData) & hwrEZPortCLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmV::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portFData) & hwrEZPortFBacklightOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZPalmV::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portDData) & hwrEZPortD232Enable) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & hwrEZPortGIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZPalmV::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ // Return the hardware sub-ID.
+
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ result |= ~device.HardwareSubID ();
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZPalmV::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrEZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrEZPortDPowerFail;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmV::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portFDir = READ_REGISTER (portFDir);
+ UInt8 portFData = READ_REGISTER (portFData);
+
+ rows[0] = (portFDir & hwrEZPortFKbdRow0) != 0 && (portFData & hwrEZPortFKbdRow0) == 0;
+ rows[1] = (portFDir & hwrEZPortFKbdRow1) != 0 && (portFData & hwrEZPortFKbdRow1) == 0;
+ rows[2] = (portFDir & hwrEZPortFKbdRow2) != 0 && (portFData & hwrEZPortFKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmV::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZPalmV::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrEZPortGADCOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZPalmV.h b/SrcShared/Hardware/EmRegsEZPalmV.h
new file mode 100644
index 0000000..16dc0e0
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmV.h
@@ -0,0 +1,42 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmV_h
+#define EmRegsEZPalmV_h
+
+#include "EmRegsEZ.h"
+
+
+class EmRegsEZPalmV : public EmRegsEZ
+{
+ public:
+ EmRegsEZPalmV (void);
+ virtual ~EmRegsEZPalmV (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsEZPalmV_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmVII.cpp b/SrcShared/Hardware/EmRegsEZPalmVII.cpp
new file mode 100644
index 0000000..edc6da7
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmVII.cpp
@@ -0,0 +1,41 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZPalmVII.h"
+#include "EmRegsEZPrv.h"
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "EZSumo/IncsPrv/HardwareEZ.h" // hwrEZPortGIRShutdown
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVII::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZPalmVII::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ // Pass this on to the PLD handler.
+ return EmHALHandler::GetLineDriverState (type);
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & hwrEZPortGIRShutdown) == 0;
+
+ return false;
+}
diff --git a/SrcShared/Hardware/EmRegsEZPalmVII.h b/SrcShared/Hardware/EmRegsEZPalmVII.h
new file mode 100644
index 0000000..d5a4386
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmVII.h
@@ -0,0 +1,26 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmVII_h
+#define EmRegsEZPalmVII_h
+
+#include "EmRegsEZPalmV.h"
+
+
+class EmRegsEZPalmVII : public EmRegsEZPalmV
+{
+ public:
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+};
+
+#endif /* EmRegsEZPalmVII_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmVIIx.cpp b/SrcShared/Hardware/EmRegsEZPalmVIIx.cpp
new file mode 100644
index 0000000..1659dcc
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmVIIx.cpp
@@ -0,0 +1,192 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZPalmVIIx.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmDevice.h" // HardwareSubID
+#include "EmSession.h" // GetDevice
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "EZSumo/IncsPrv/HardwareEZ.h" // hwrEZPortCLCDEnableOn, etc.
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+// As near as I can tell, PalmVIIx uses the same hardware defs as
+// a Sumo, but with this one bit difference. Actually, there are
+// other Port F and G differences, but they aren't (currently)
+// relevent to Poser.
+
+#undef hwrEZPortFKbdRow0
+#define hwrEZPortFKbdRow0 0x01 // (L) Keyboard Row 0
+
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+
+// ============================== PalmVIIx ==============================
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::EmRegsEZPalmVIIx
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmVIIx::EmRegsEZPalmVIIx (void) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::~EmRegsEZPalmVIIx
+// ---------------------------------------------------------------------------
+
+EmRegsEZPalmVIIx::~EmRegsEZPalmVIIx (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmVIIx::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portCData) & hwrEZPortCLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZPalmVIIx::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portFData) & hwrEZPortFBacklightOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZPalmVIIx::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ // Pass this on to the PLD handler.
+ return EmHALHandler::GetLineDriverState (type);
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & hwrEZPortGIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZPalmVIIx::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ // Return the hardware sub-ID.
+
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ result |= ~device.HardwareSubID ();
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZPalmVIIx::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrEZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrEZPortDPowerFail;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZPalmVIIx::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portFDir = READ_REGISTER (portFDir);
+ UInt8 portFData = READ_REGISTER (portFData);
+
+ rows[0] = (portFDir & hwrEZPortFKbdRow0) != 0 && (portFData & hwrEZPortFKbdRow0) == 0;
+ rows[1] = (portFDir & hwrEZPortFKbdRow1) != 0 && (portFData & hwrEZPortFKbdRow1) == 0;
+ rows[2] = (portFDir & hwrEZPortFKbdRow2) != 0 && (portFData & hwrEZPortFKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZPalmVIIx::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZPalmVIIx::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrEZPortGADCOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZPalmVIIx.h b/SrcShared/Hardware/EmRegsEZPalmVIIx.h
new file mode 100644
index 0000000..57f8faa
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmVIIx.h
@@ -0,0 +1,41 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmVIIx_h
+#define EmRegsEZPalmVIIx_h
+
+#include "EmRegsEZ.h"
+
+class EmRegsEZPalmVIIx : public EmRegsEZ
+{
+ public:
+ EmRegsEZPalmVIIx (void);
+ virtual ~EmRegsEZPalmVIIx (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsEZPalmVIIx_h */
diff --git a/SrcShared/Hardware/EmRegsEZPalmVx.h b/SrcShared/Hardware/EmRegsEZPalmVx.h
new file mode 100644
index 0000000..b348bb3
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPalmVx.h
@@ -0,0 +1,21 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPalmVx_h
+#define EmRegsEZPalmVx_h
+
+#include "EmRegsEZPalmV.h"
+
+typedef EmRegsEZPalmV EmRegsEZPalmVx;
+
+#endif /* EmRegsEZPalmVx_h */
diff --git a/SrcShared/Hardware/EmRegsEZPrv.h b/SrcShared/Hardware/EmRegsEZPrv.h
new file mode 100644
index 0000000..660ea30
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZPrv.h
@@ -0,0 +1,45 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZPrv_h
+#define EmRegsEZPrv_h
+
+#include "EmRegsPrv.h"
+
+// Location and range of registers
+
+const uint32 kMemoryStart = 0xFFFFF000;
+const uint32 kMemorySize = sizeof (HwrM68EZ328Type);
+
+
+// Macro to return the DragonballEZ address of the specified register
+
+#define addressof(x) (kMemoryStart + offsetof(HwrM68EZ328Type, x))
+
+
+// Macros for reading/writing DragonballEZ registers.
+
+#define READ_REGISTER(reg) \
+ _get_reg (&f68EZ328Regs.reg)
+
+#define WRITE_REGISTER(reg, value) \
+ _put_reg (&f68EZ328Regs.reg, value)
+
+
+// Macro for installing DragonballEZ register handlers
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ((ReadFunction) &EmRegsEZ::read, (WriteFunction) &EmRegsEZ::write, addressof (reg), sizeof (f68EZ328Regs.reg))
+
+
+#endif /* EmRegsEZPrv_h */
diff --git a/SrcShared/Hardware/EmRegsEZTRGpro.cpp b/SrcShared/Hardware/EmRegsEZTRGpro.cpp
new file mode 100644
index 0000000..cd7926f
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZTRGpro.cpp
@@ -0,0 +1,251 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// This file provides emulation at the register level for TRG's
+// TRGpro handheld computer, which uses the EZ processor
+
+
+#include "EmCommon.h"
+#include "EmRegsEZTRGpro.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "EZSumo/IncsPrv/HardwareEZ.h" // hwrEZPortCLCDEnableOn, etc.
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+// TRGpro Defines
+#define hwrEZPortDCFInit 0x40
+#define hwrEZPortGDO_LATCH 0x08 // SPI DO_LATCH enable
+#define hwrEZPortBLCDVccOff 0x02 // LCD VCC off
+#define hwrEZPortD232EnableTRGpro 0x20 // RS 232 enable
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::EmRegsEZTRGpro
+// ---------------------------------------------------------------------------
+
+EmRegsEZTRGpro::EmRegsEZTRGpro (CFBusManager ** fBusMgr) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+ *fBusMgr = &CFBus;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::~EmRegsEZTRGpro
+// ---------------------------------------------------------------------------
+
+EmRegsEZTRGpro::~EmRegsEZTRGpro (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsEZTRGpro::Initialize(void)
+{
+ bBacklightOn = false;
+ CFBus.bEnabled = false;
+ CFBus.Width = kCFBusWidth16;
+ CFBus.bSwapped = false;
+ EmRegsEZ::Initialize();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZTRGpro::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portCData) & hwrEZPortCLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZTRGpro::GetLCDBacklightOn (void)
+{
+ return (bBacklightOn);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZTRGpro::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portDData) & hwrEZPortD232EnableTRGpro) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portGData) & 0x10) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZTRGpro::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZTRGpro::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrEZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= (hwrEZPortDCFInit | hwrEZPortDPowerFail);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZTRGpro::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+// KeyRowsType keyRows;
+
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+ rows[0] = Keys.Row[0];
+ rows[1] = Keys.Row[1];
+ rows[2] = Keys.Row[2];
+}
+
+void EmRegsEZTRGpro::LatchSpi(void)
+{
+ uint16 latched = spiUnlatchedVal;
+
+ bBacklightOn = ((latched & SPIBacklightOn) != 0);
+ CFBus.bEnabled = ((latched & (SPICardBufferOff |
+ SPICardSlotPwrOff)) == 0);
+ CFBus.bSwapped = ((latched & SPIBusSwapOff) == 0);
+ if (latched & SPIBusWidth8)
+ CFBus.Width = kCFBusWidth8;
+ else
+ CFBus.Width = kCFBusWidth16;
+ Keys.Row[0] = !(latched & SPIKeyRow0);
+ Keys.Row[1] = !(latched & SPIKeyRow1);
+ Keys.Row[2] = !(latched & SPIKeyRow2);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZTRGpro::PortDataChanged (int port, uint8 oldValue, uint8 newValue)
+{
+ if (port == 'G')
+ {
+ // If the the DO_LATCH bit is set, then the recent value
+ // written to the SPI controller is for us, and not
+ // the touchscreen
+
+ if (newValue & hwrEZPortGDO_LATCH)
+ LatchSpi();
+ }
+
+ EmRegsEZ::PortDataChanged(port, oldValue, newValue);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::spiWrite
+//
+// We need to share SPI writes with the touchscreen ...
+// ---------------------------------------------------------------------------
+
+void EmRegsEZTRGpro::spiWrite(emuptr address, int size, uint32 value)
+{
+ spiUnlatchedVal = value;
+ EmRegsEZ::spiMasterControlWrite (address, size, value);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsEZTRGpro::SetSubBankHandlers(void)
+{
+ EmRegsEZ::SetSubBankHandlers();
+ this->SetHandler((ReadFunction)&EmRegs::StdRead,
+ (WriteFunction)&EmRegsEZTRGpro::spiWrite,
+ addressof(spiMasterData),
+ sizeof(f68EZ328Regs.spiMasterData));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZTRGpro::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZTRGpro::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrEZPortGADCOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZTRGpro.h b/SrcShared/Hardware/EmRegsEZTRGpro.h
new file mode 100644
index 0000000..25f5c7e
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZTRGpro.h
@@ -0,0 +1,76 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZTRGpro_h
+#define EmRegsEZTRGpro_h
+
+#include "EmRegsEZ.h"
+#include "EmHandEraCFBus.h"
+
+// --------------------------------------------------------------------------
+// This file is used to emulate the SPI controller ... the SPI performs
+// double duty for the TRGpro ... normally, it controls the touch screen ...
+// however, if a latch bit is set on Port D, it will use the SPI to
+// control the keypad and bus-state
+// --------------------------------------------------------------------------
+
+#define SPIKeyRow0 0x01
+#define SPIKeyRow1 0x02
+#define SPIKeyRow2 0x04
+#define SPIBusSwapOff 0x08
+#define SPIBacklightOn 0x10
+#define SPICardBufferOff 0x20
+#define SPICardSlotPwrOff 0x40
+#define SPIBusWidth8 0x80
+
+#define TRGPRO_NUM_KEY_ROWS 3
+
+typedef struct {
+ uint16 Row[TRGPRO_NUM_KEY_ROWS];
+} TrgProKeys;
+
+
+class EmRegsEZTRGpro : public EmRegsEZ
+{
+ public:
+ EmRegsEZTRGpro (CFBusManager ** fBusManager);
+ virtual ~EmRegsEZTRGpro (void);
+
+ virtual void Initialize (void);
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+ virtual void PortDataChanged (int, uint8, uint8);
+ void SetSubBankHandlers(void);
+ private:
+ void spiWrite(emuptr address, int size, uint32 value);
+ uint16 spiLatchedVal, spiUnlatchedVal;
+ void LatchSpi(void);
+
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+ CFBusManager CFBus;
+ TrgProKeys Keys;
+ int bBacklightOn;
+};
+
+#endif /* EmRegsEZTRGpro_h */
diff --git a/SrcShared/Hardware/EmRegsEZTemp.cpp b/SrcShared/Hardware/EmRegsEZTemp.cpp
new file mode 100644
index 0000000..a0725f5
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZTemp.cpp
@@ -0,0 +1,18 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZTemp.h"
+#include "EmRegsEZPrv.h"
+
+
diff --git a/SrcShared/Hardware/EmRegsEZTemp.h b/SrcShared/Hardware/EmRegsEZTemp.h
new file mode 100644
index 0000000..7818645
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZTemp.h
@@ -0,0 +1,18 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZTemp_h
+#define EmRegsEZTemp_h
+
+
+#endif /* EmRegsEZTemp_h */
diff --git a/SrcShared/Hardware/EmRegsEZVisor.cpp b/SrcShared/Hardware/EmRegsEZVisor.cpp
new file mode 100644
index 0000000..166158c
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZVisor.cpp
@@ -0,0 +1,243 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZVisor.h"
+#include "EmRegsEZPrv.h"
+
+#include "EmDevice.h" // HardwareID
+#include "EmSession.h" // GetDevice
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+
+const uint16 kVisorButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3 },
+ { keyBitPageUp, keyBitPageDown, 0 },
+ { keyBitPower, keyBitHard4, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::EmRegsEZVisor
+// ---------------------------------------------------------------------------
+
+EmRegsEZVisor::EmRegsEZVisor (void) :
+ EmRegsEZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::~EmRegsEZVisor
+// ---------------------------------------------------------------------------
+
+EmRegsEZVisor::~EmRegsEZVisor (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZVisor::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portCData) & hwrLegoPortCLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsEZVisor::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrLegoPortGBacklightOff) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsEZVisor::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) == 0;
+ }
+
+ if (type == kUARTIR)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) != 0;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsEZVisor::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ /*
+ Support the Visor model ID. From Bob Petersen at Handspring:
+
+ The Visor ROM only works with 1 device so far. But, the Visor does have
+ model detect pins so that future ROMs can work on multiple platforms. The
+ model input pins are connected to port E, bits 0-2 (E[0-2]). To read them,
+ you have to drive port G bit 2 low and enable the pullups on port E.
+ */
+
+#define modelOutPin 0x04 // EMUIRQ (IRQ7)
+#define modelInPins 0x07 // SPI pins on Visor
+
+ UInt8 portGData = READ_REGISTER (portGData);
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGSelect = READ_REGISTER (portGSelect);
+
+ if (((portGData & modelOutPin) == 0) &&
+ ((portGDir & modelOutPin) == modelOutPin) &&
+ ((portGSelect & modelOutPin) == modelOutPin))
+ {
+ EmAssert (gSession);
+
+ EmDevice device = gSession->GetDevice ();
+ result |= (~device.HardwareID ()) & modelInPins; // <chg 24-Apr-2000 BP> expects inverse output
+ }
+ else
+ {
+ // The pin for detecting "in cradle" is hwrLegoPortEDock2Off. It should be low
+ // if in the serial cradle. If it is high, we assume USB.
+ // -- Bob Petersen
+
+ result &= ~hwrLegoPortEDock2Off;
+ }
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrLegoPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrLegoPortGPowerFailIrqOff;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsEZVisor::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsEZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Always set the high bit, indicating that there's no memory module
+ // installed. From Bob Petersen at Handspring:
+ //
+ // This is a probe into the module memory, to check for a replacement ROM on a
+ // card that is plugged in. The card is mapped to 0x20000000 and the card's
+ // ROM is at 0x28000000. If it finds the card header (FEEDBEEF) and the card
+ // is plugged in that has a non-zero reset vector, the chip selects are changed
+ // so B0 addresses 10c00000, and then we jump to the reset vector and boot off
+ // the card.
+ //
+ // This part of the boot code should only be called if it is detected that a
+ // card is currently plugged in (bit 7 of port D) and we aren't currently
+ // booting from the card.
+
+ result |= hwrLegoPortDCardInstIrqOff;
+
+ // Ensure that bit hwrLegoPortDDock1IrqOff is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ result |= hwrLegoPortDDock1IrqOff;
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrLegoPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrLegoPortGPowerFailIrqOff;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsEZVisor::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kVisorButtonMap, sizeof (kVisorButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portDDir = READ_REGISTER (portDDir);
+ UInt8 portDData = READ_REGISTER (portDData);
+
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGData = READ_REGISTER (portGData);
+
+ rows[0] = (portGDir & hwrLegoPortGKbdRow0) != 0 && (portGData & hwrLegoPortGKbdRow0) == 0;
+ rows[1] = (portGDir & hwrLegoPortGKbdRow1) != 0 && (portGData & hwrLegoPortGKbdRow1) == 0;
+ rows[2] = (portDDir & hwrLegoPortDKbdRow2) != 0 && (portDData & hwrLegoPortDKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsEZVisor::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrLegoPortGAdcCsOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
diff --git a/SrcShared/Hardware/EmRegsEZVisor.h b/SrcShared/Hardware/EmRegsEZVisor.h
new file mode 100644
index 0000000..d71c711
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsEZVisor.h
@@ -0,0 +1,131 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsEZVisor_h
+#define EmRegsEZVisor_h
+
+#include "EmRegsEZ.h"
+
+// Handspring modelID defines
+// DOLATER BP: move the general Handspring-specific stuff to another include file
+#define halModelChipIDEZ 0x00 // 0000 0
+#define halModelChipIDVZ 0x08 // 0000 1
+//#define halModelChipIDXZ 0x10 // 0001 0 placeholder
+
+#define halModelEZIndexLego 0x00 // 000
+
+#define halModelVZIndexVisorPlatinum 0x00 // 000
+#define halModelVZIndexVisorPrism 0x02 // 010
+#define halModelVZIndexVisorEdge 0x01 // 001
+
+
+// Model IDs (combinations of the above)...
+// ----------------------------------------
+#define halModelIDLego (halModelChipIDEZ | halModelEZIndexLego) // Lego (Visor)
+#define halModelIDVisorPlatinum (halModelChipIDVZ | halModelVZIndexVisorPlatinum)
+#define halModelIDVisorPrism (halModelChipIDVZ | halModelVZIndexVisorPrism)
+#define halModelIDVisorEdge (halModelChipIDVZ | halModelVZIndexVisorEdge)
+
+
+// Visor pin definitions from Handspring. Mostly the same as a Palm V,
+// but with some pins changed and moved around.
+
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrLegoPortBLCDVccOff 0x08 // (L) LCD Vcc
+#define hwrLegoPortBLCDAdjOn 0x40 // (H) LCD Contrast Voltage
+
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+#define hwrLegoPortCLCDEnableOn 0x80 // (H) LCD Enable
+
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+#define hwrLegoPortDKbdCol0On 0x01 // (H) Keyboard Column 0
+#define hwrLegoPortDKbdCol1On 0x02 // (H) Keyboard Column 1
+#define hwrLegoPortDKbdCol2On 0x04 // (H) Keyboard Column 2
+
+#define hwrLegoPortDKbdRow2 0x08 // (H) Keyboard Row 2
+
+#define hwrLegoPortDDock1IrqOff 0x10 // (L) Dock1 interrupt
+#define hwrLegoPortDSlotIrqOff 0x20 // (L) Slot Interrupt
+#define hwrLegoPortDUsbIrqOff 0x40 // (L) USB Interrupt
+#define hwrLegoPortDCardInstIrqOff 0x80 // (L) Card Installed Interrupt
+
+#define hwrLegoPortDKeyBits 0x07 // (H) All Keyboard Columns
+
+
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrLegoPortESerialTxD 0x20 // ( ) Serial transmit line
+#define hwrLegoPortESlotResetOff 0x40 // (L) Slot reset
+#define hwrLegoPortEDock2Off 0x80 // (L) Dock2 input
+
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+#define hwrLegoPortFContrast 0x01 // ( ) LCD Contrast PWM output
+#define hwrLegoPortFIREnableOff 0x04 // (L) Shutdown IR
+#define hwrLegoPortFUsbCsOff 0x80 // (L) USB chip select
+
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+#define hwrLegoPortGBacklightOff 0x01 // (L) Backlight on/off
+#define hwrLegoPortGUSBSuspend 0x02 // (X) USB Suspend bit - Output low for active
+ // - Input for suspend
+#define hwrLegoPortGPowerFailIrqOff 0x04 // (L) Power Fail IRQ
+#define hwrLegoPortGKbdRow0 0x08 // (H) Keyboard Row 0
+#define hwrLegoPortGKbdRow1 0x10 // (H) Keyboard Row 1
+#define hwrLegoPortGAdcCsOff 0x20 // (L) A/D Select
+
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 3;
+
+extern const uint16 kVisorButtonMap[kNumButtonRows][kNumButtonCols];
+
+
+class EmRegsEZVisor : public EmRegsEZ
+{
+ public:
+ EmRegsEZVisor (void);
+ virtual ~EmRegsEZVisor (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsEZVisor_h */
diff --git a/SrcShared/Hardware/EmRegsFrameBuffer.cpp b/SrcShared/Hardware/EmRegsFrameBuffer.cpp
new file mode 100644
index 0000000..cb436fd
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsFrameBuffer.cpp
@@ -0,0 +1,241 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsFrameBuffer.h"
+
+#include "Byteswapping.h" // ByteswapWords
+#include "EmMemory.h" // EmMemDoGet32
+#include "EmScreen.h" // EmScreen::MarkDirty
+#include "Miscellaneous.h" // StWordSwapper
+#include "Platform.h" // Platform::AllocateMemoryClear
+#include "SessionFile.h" // SessionFile
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::EmRegsFrameBuffer
+// ---------------------------------------------------------------------------
+
+EmRegsFrameBuffer::EmRegsFrameBuffer (emuptr baseAddr, int32 size) :
+ fBaseAddr (baseAddr),
+ fSize (size),
+ fVideoMem (NULL)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::~EmRegsFrameBuffer
+// ---------------------------------------------------------------------------
+
+EmRegsFrameBuffer::~EmRegsFrameBuffer (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::Initialize (void)
+{
+ EmRegs::Initialize ();
+
+ // Allocate a chunk of memory for the VRAM space.
+
+ if (!fVideoMem)
+ {
+ fVideoMem = Platform::AllocateMemoryClear (fSize);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ StWordSwapper swapper (fVideoMem, fSize);
+ f.WriteSED1375Image (fVideoMem, fSize);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ // Read in the LCD image, and then byteswap it.
+
+ if (f.ReadSED1375Image (fVideoMem))
+ {
+ ByteswapWords (fVideoMem, fSize);
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::Dispose (void)
+{
+ EmRegs::Dispose ();
+
+ Platform::DisposeMemory (fVideoMem);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetLong
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsFrameBuffer::GetLong (emuptr address)
+{
+ uint32 offset = address - fBaseAddr;
+ return EmMemDoGet32 (((uint8*) fVideoMem) + offset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetWord
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsFrameBuffer::GetWord (emuptr address)
+{
+ uint32 offset = address - fBaseAddr;
+ return EmMemDoGet16 (((uint8*) fVideoMem) + offset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetByte
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsFrameBuffer::GetByte (emuptr address)
+{
+ uint32 offset = address - fBaseAddr;
+ return EmMemDoGet8 (((uint8*) fVideoMem) + offset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::SetLong
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::SetLong (emuptr address, uint32 value)
+{
+ uint32 offset = address - fBaseAddr;
+ EmMemDoPut32 (((uint8*) fVideoMem) + offset, value);
+ EmScreen::MarkDirty (address, 4);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::SetWord
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::SetWord (emuptr address, uint32 value)
+{
+ uint32 offset = address - fBaseAddr;
+ EmMemDoPut16 (((uint8*) fVideoMem) + offset, value);
+ EmScreen::MarkDirty (address, 2);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::SetByte
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::SetByte (emuptr address, uint32 value)
+{
+ uint32 offset = address - fBaseAddr;
+ EmMemDoPut8 (((uint8*) fVideoMem) + offset, value);
+ EmScreen::MarkDirty (address, 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::ValidAddress
+// ---------------------------------------------------------------------------
+
+int EmRegsFrameBuffer::ValidAddress (emuptr address, uint32 size)
+{
+ UNUSED_PARAM (address);
+ UNUSED_PARAM (size);
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsFrameBuffer::SetSubBankHandlers (void)
+{
+ // We don't have handlers for each byte of memory, so there's nothing
+ // to install here.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsFrameBuffer::GetRealAddress (emuptr address)
+{
+ uint32 offset = address - fBaseAddr;
+ return (uint8*) fVideoMem + offset;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsFrameBuffer::GetAddressStart (void)
+{
+ return fBaseAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsFrameBuffer::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsFrameBuffer::GetAddressRange (void)
+{
+ return fSize;
+}
diff --git a/SrcShared/Hardware/EmRegsFrameBuffer.h b/SrcShared/Hardware/EmRegsFrameBuffer.h
new file mode 100644
index 0000000..e2d4741
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsFrameBuffer.h
@@ -0,0 +1,52 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsFrameBuffer_h
+#define EmRegsFrameBuffer_h
+
+#include "EmRegs.h"
+
+class SessionFile;
+
+
+class EmRegsFrameBuffer : public EmRegs
+{
+ public:
+ EmRegsFrameBuffer (emuptr baseAddr, int32 size);
+ virtual ~EmRegsFrameBuffer (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual uint32 GetLong (emuptr address);
+ virtual uint32 GetWord (emuptr address);
+ virtual uint32 GetByte (emuptr address);
+ virtual void SetLong (emuptr address, uint32 value);
+ virtual void SetWord (emuptr address, uint32 value);
+ virtual void SetByte (emuptr address, uint32 value);
+ virtual int ValidAddress (emuptr address, uint32 size);
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ private:
+ emuptr fBaseAddr;
+ int32 fSize;
+ void* fVideoMem;
+};
+
+#endif /* EmRegsFrameBuffer_h */
diff --git a/SrcShared/Hardware/EmRegsMediaQ11xx.cpp b/SrcShared/Hardware/EmRegsMediaQ11xx.cpp
new file mode 100644
index 0000000..19506b0
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsMediaQ11xx.cpp
@@ -0,0 +1,4791 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsMediaQ11xx.h"
+
+#include "EmCPU68K.h" // gCPU68K
+#include "EmPixMap.h" // EmPixMap::GetLCDScanlines
+#include "EmScreen.h" // EmScreen::InvalidateAll
+#include "SessionFile.h" //
+
+#include "Logging.h" // LogAppendMsg
+
+#include <algorithm> // swap
+
+
+#define LOG_LINE 0
+#define PRINTF_LINE if (!LOG_LINE) ; else LogAppendMsg
+
+#define LOG_BLIT 0
+#define PRINTF_BLIT if (!LOG_BLIT) ; else LogAppendMsg
+
+
+/* --------------------------------------------------------------------------- *\
+ MediaQ Graphics Engine overview and description
+ -----------------------------------------------
+
+ The MediaQ 1100/1132 chip contains a graphics engine used for accelerating
+ graphics drawing operations. It has the following features:
+
+ * Line drawing
+ * Rectangle operations (fill, scroll, and BLT)
+ * Arbitrary transfer operations (using Windows ROP definitions)
+ * Monochrome and color source data
+ * Monochrome pattern data
+ * Colorization of monochrome source and pattern data
+ * Transparency support
+ * Clipping support
+ * Automatic screen flipping
+
+ There are 20 registers reserved for the graphics accelerator. The MediaQ
+ client generally works by storing necessary values in a subset of those
+ registers, and then kicks off the drawing process by updating the register
+ that receives the drawing command. This register (GE00R) is the master
+ control register. It contains all of the top-level information about what
+ is to be drawn and how. As needed, other registers are queried for
+ additional values needed for the operation. Registers not required for
+ the drawing operation need not be updated before the drawing command is
+ issued. The drawing operation takes place asynchronously, freeing up the
+ MediaQ client for other tasks.
+
+ The graphics chip makes use of two FIFOs: a command FIFO and a source data
+ FIFO. The command FIFO is used to make sure that registers are not
+ updated and changed out from under a drawing operation currently in
+ progress. That is, any write access to a register really results in an
+ entry being added to the command FIFO. Entries are then popped off and
+ used to update the registers. If the command register is written to, the
+ drawing operation commences. Any subsequent writes to registers will
+ still be added to the FIFO, but will stay there until the drawing
+ operation has completed. If the FIFO is full (it has room only for 16
+ commands), the main CPU will stall if it tries to add any more commands.
+
+ Sometimes the drawing operation requires "source data", that is, data from
+ main memory. The MediaQ chip doesn't have direct access to main RAM, and
+ so data from there needs to be fed in through a source FIFO. After a
+ drawing command has been started that requires source data, the MediaQ
+ client must go into a loop and ensure that this source data FIFO is filled
+ with the necessary data. Note that this source FIFO contains 16 64-bit
+ slots. Therefore, the client needs to make sure that information written
+ to the FIFO occurs in multiples of 64-bits (or 8 bytes).
+
+ GEState
+ -------
+
+ This Poser-defined structure is a mirror of the registers used by the
+ MediaQ graphics acceleration engine. It breaks out all of the pieces of
+ information packed into those registers, and stores each piece into its
+ own field for easy access. This unpacking takes place as needed,
+ generally when a graphics drawing command is issued.
+
+ Following is a description of all the registers and the fields within
+ those registers. After that are included some notes on how those
+ registers fit into the bigger picture.
+
+ **************************************************************************
+ ==========================================================================
+ GE00R
+ ==========================================================================
+
+ GE00R[7:0] rasterOperation
+ -----------------------------------------------
+ Specifies the transfer mode. That is, it defines the way in which the
+ source data, destination data, and pattern data are combined to
+ produce the final destination or output data. The values that can be
+ used here are the same that Microsoft has defined for GDI.
+
+ This register can contain either the ternary ROP codes or the binary
+ ROP2 codes, depending on the setting of rop2Select (GE00R[25]).
+
+ GE00R[10:8] commandType
+ -----------------------------------------------
+ Specifies the drawing command. Can be one of three values:
+
+ 0 = NOP
+ 2 = BitBLT
+ 4 = Line
+
+ All other values are either reserved or undefined.
+
+ Note that BitBLT is used for drawing filled rectangles, scrolling
+ images in the screen memory, or copy images from main memory to the
+ screen memory. Monochrome and color source data and patterns are
+ supported.
+
+ GE00R[11] xDirection
+ GE00R[12] yDirection
+ -----------------------------------------------
+ Defines the direction in which a BitBLT or line drawing operation
+ occurs. Values of zero indicate the positive (right or down)
+ direction; values of one indicate the negative (left or up) direction.
+ When drawing a line, note that these fields are used only if the
+ useXY field is set.
+
+ GE00R[13] systemMemory
+ -----------------------------------------------
+ If true, specifies that any source data comes from the source FIFO.
+ Otherwise, the data comes from display memory, and xSrc (GE03R[11:0])
+ and ySrc (GE03R[27:16]) need to be programmed.
+
+ GE00R[14] monoSource
+ -----------------------------------------------
+ Specifies whether the source data is a monochrome (aka, bitonal)
+ bitmap where each pixel is represented by a single bit, or that the
+ source data is in color format, where each pixel is defined by an 8 or
+ 16 bit value, depending on the setting of colorDepth (GE0AR[31:30]).
+
+ GE00R[15] monoPattern
+ -----------------------------------------------
+ Specifies whether the pattern data is a monochrome (aka, bitonal)
+ bitmap where each pixel is represented by a single bit, or that the
+ pattern data is in color format, where each pixel is defined by an 8
+ or 16 bit value. Note that in the current chip, this bit *MUST* be
+ set to 1, indicating a monochrome pattern. There doesn't appear to be
+ any support or any way to specify a color pattern.
+
+ GE00R[16] colorTransEnable
+ -----------------------------------------------
+ Setting this bit enables transparent BitBLT operations when the source
+ data is in color format. It works in conjunction with
+ destTransPolarity, colorTransCmpSrc, and destTransColor to determine
+ if the destination pixel is updated or stays the same.
+
+ GE00R[17] destTransPolarity
+ -----------------------------------------------
+ If color transparency is enabled (that is, colorTransEnable is set),
+ determines how transparency is achieved. Depending on the setting of
+ colorTransCmpSrc, either the source data or the dest data is compared
+ to destTransColor. If destTransPolarity is zero, then the destination
+ pixel is updated if the result of the comparison is not equal. If
+ destTransPolarity is one, then the destination pixel is update if the
+ result is equal.
+
+ GE00R[18] monoTransEnable
+ -----------------------------------------------
+ Setting this bit enables transparent BitBLT operations when the source
+ data is in monochrome format. It works in conjunction with
+ monoTransPolarity to determine if the destination pixel is updated or
+ stays the same.
+
+ GE00R[19] monoTransPolarity
+ -----------------------------------------------
+ If monochrome transparency is enabled (that is, monoTransEnable is
+ set), determines how transparency is achieved. If this value is zero,
+ then background (that is, zero) bits in the source are treated as
+ transparent and don't update the destination. If this value is one,
+ then foreground (that is, one) bits in the source data are treated as
+ transparent.
+
+ GE00R[20] memToScreen
+ -----------------------------------------------
+ Specifies LINED (memToScreen == 0) or PACKED (memToScreen == 1) blit
+ transfer mode. PACKED Mode allows bitmaps that are compact to be
+ transferred more efficiently. LINE Mode requires each line of bitmap
+ to be aligned at 64-bit and thus could require padding and realignment
+ if each line of bitmap to be transfer is non-64-bit aligned.
+
+ GE00R[23] solidSourceColor
+ -----------------------------------------------
+ If set, the actual color source data is effectively ignored, and
+ instead treated as if it were all fgColorMonoSrc.
+
+ GE00R[24] srcEqualDestStride
+ -----------------------------------------------
+ Specifies whether or not the dest and source have the same "strides"
+ (that is, "rowBytes" in other terminologies). If the source is the
+ display, then the source will always be the same as the dest. But if
+ the source is main memory, then the data comes in through the source
+ FIFO, and I'm not sure how stride comes in to play there.
+
+ GE00R[25] rop2Select
+ -----------------------------------------------
+ Causes the value in rasterOperation (GE00R[7:0]) to be treated as a
+ binary ROP2 value instead of a ternary ROP value. The documentation
+ says that "[3:0] is duplicated to [7:4]". However, it's not clear to
+ me is the programmer is required to write the register in this
+ duplicated fashion, or if the hardware aliases the low values into the
+ high values in some way. In either case, I'm not sure why the
+ hardware cares. Why wouldn't it just look at the low 4 bits and
+ ignore the upper 4 bits. My guess is that the hardware performs this
+ aliasing on its own, and that the result when looking at all 8 bits
+ has the result of acting like a binary ROP2 code (that is, the any
+ source data will be ignored -- see comments in PrvUsesSource on how
+ the ROP value can be examined to see if the pattern, source or
+ destination have any role in determining the final output value).
+
+ GE00R[26] clipEnable
+ -----------------------------------------------
+ Enable clipping according to the clipLeft, clipTop, clipRight, and
+ clipBottom fields (registers GE05R and GE06R).
+
+ GE00R[27] autoExecute
+ -----------------------------------------------
+ Setting this bit enables auto-execution of the command after the
+ destination XY register (GE02R) is written. If it's clear, the
+ graphics engine command execution starts the command register (GE00R)
+ is written.
+
+ GE00R[30] solidPattern
+ -----------------------------------------------
+ If set, then all pattern data is forced to the value of the pattern
+ foreground color register (GE12R).
+
+ GE00R[31] colorTransCmpSrc
+ -----------------------------------------------
+ Used in conjunction with the transparency-enable bits, determines if
+ the color to be compared comes from the source or destination.
+ Compare to the source data if it's zero, destination if it's one.
+
+ ==========================================================================
+ GE01R
+ ==========================================================================
+
+ GE01R[11:0] (BitBLT) width
+ GE01R[27:16] (BitBLT) height
+ -----------------------------------------------
+ When a BitBLT operation has been specified, these fields contain the
+ dimensions (in pixels) of the operation. It is used for both the
+ source and destination.
+
+ GE01R[31] (BitBLT) xyConversion
+ -----------------------------------------------
+ When a BitBLT operation has been specified, this field controls how
+ the starting x/y values are interpreted. If this bit is clear, then
+ the specified x/y values are the first pixel updated. If this bit is
+ set, then the specified x/y values are the top/left corner of the
+ rectangle that's updated.
+
+ GE01R[16:0] (Line) gamma
+ -----------------------------------------------
+ When a line drawing operation has been specified, contains a value
+ identified as "gamma". This is defined in the documentation as
+ "either -(dm >> 1) - 1 or -(dm >> 1), depending on the quadrant",
+ where "dm" is the major axis delta. However, there's no mention of
+ which value is used in what situations. As well, our source code
+ writes to this field a value that has the same magnitude of dm. That
+ is dm gets written to its designated field, and -dm gets written to
+ gamma.
+
+ GE01R[28:17] (Line) majorLength
+ -----------------------------------------------
+ When a line drawing operation has been specified, contains the length
+ along the major axis.
+
+ GE01R[29] (Line) yIsMajor
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies which axis
+ is the major axis (that is, the "long" axis -- a "mostly horizontal"
+ line has X as the major axis, while a "mostly vertical" line has Y as
+ the major axis, and a diagonal line can have either defines as its
+ major axis). If set, Y is the major axis. Otherwise, X is the major
+ axis. Note that this field is used only if the useXY field is set.
+
+ GE01R[30] (Line) drawLastPixel
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies whether or
+ not the last pixel in the rasterization process is drawn.
+
+ GE01R[31] (Line) useXY
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies the method
+ used to determine in which direction the line should be drawn. If
+ this field is set, then the information about direction and slope is
+ taken from the xDirection, yDirection, and yIsMajor fields. If this
+ field is clear, then the information is taken from the quadrant field.
+
+ ==========================================================================
+ GE02R
+ ==========================================================================
+
+ GE02R[11:0] (BitBLT) xDest
+ GE02R[27:16] (BitBLT) yDest
+ -----------------------------------------------
+ When a BitBLT operation has been specified, these fields contain the
+ initial x,y location to receive the blitted data. Note that these
+ values are always the topLeft of the destination area, regardless of
+ xDirection and yDirection.
+
+ GE02R[15:13] (BitBLT) monoPatternXOffset
+ GE02R[31:29] (BitBLT) monoPatternYOffset
+ -----------------------------------------------
+ When a BitBLT operation has been specified, these fields contain the
+ initial x,y offsets into the monochrome pattern being used.
+
+ GE02R[11:0] (Line) xStart
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies starting X
+ position of the line.
+
+ GE02R[28:12] (Line) deltaMajor
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies the length
+ of the line along the major axis. See yIsMajor for a definition of
+ "major axis".
+
+ GE02R[31:29] (Line) quadrant
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies the
+ direction and angle in which the line is drawn. This is used only
+ when the useXY field is clear, and replaces the same information
+ provided by xDirection, yDirection, and yIsMajor. The field contains
+ a value from 0 to 7, indicating one of the following 8 quadrants:
+
+ Quadrant 0 (x-major, positive x and y directions)
+ Quadrant 1 (y-major, positive x and y directions)
+ Quadrant 2 (y-major, negative x and positive y directions)
+ Quadrant 3 (x-major, negative x and positive y directions)
+ Quadrant 4 (x-major, negative x and y directions)
+ Quadrant 5 (y-major, negative x and y directions)
+ Quadrant 6 (y-major, positive x and negative y directions)
+ Quadrant 7 (x-major, positive x and negative y directions)
+
+ ==========================================================================
+ GE03R
+ ==========================================================================
+
+ GE03R[11:0] (BitBLT) xSrc
+ GE03R[27:16] (BitBLT) ySrc
+ -----------------------------------------------
+ When a BitBLT operation has been specified, these fields contain the
+ initial x,y location from which to read the source data. Only used
+ when the source data is coming from display memory and not the source
+ FIFO. That is, used in scrolling operations. Note that these values
+ are always the topLeft of the source area, regardless of xDirection
+ and yDirection.
+
+ GE03R[11:0] (Line) yStart
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies starting Y
+ position of the line.
+
+ GE03R[28:12] (Line) deltaMinor
+ -----------------------------------------------
+ When a line drawing operation has been specified, specifies the length
+ of the line along the minor axis. The "minor axis" is the X or Y axis
+ that is not designated as the major axis. See yIsMajor for a
+ definition of "major axis".
+
+ ==========================================================================
+ GE04R
+ ==========================================================================
+
+ GE04R[15:0] destTransColor
+ -----------------------------------------------
+ When color transparency has been enabled by setting the
+ colorTransEnable field, specifies the color that should be compared
+ against.
+
+ ==========================================================================
+ GE05R/GE06R
+ ==========================================================================
+
+ GE05R[10:0] clipLeft
+ GE05R[25:16] clipTop
+ GE06R[10:0] clipRight
+ GE06R[25:16] clipBottom
+ -----------------------------------------------
+ When the clippingEnable bit is set, these four fields specify the
+ clipping boundary. Pixels outside this rectangle are not written.
+
+ ==========================================================================
+ GE07R/GE08R
+ ==========================================================================
+
+ GE07R[15:0] fgColorMonoSrc
+ GE08R[15:0] bgColorMonoSrc
+ -----------------------------------------------
+ When a monochrome source is being used, these two fields contain the
+ fore- and background colors that should be applied to the bits
+ representing the pixels. Any 1 bit is replace with fgColorMonoSrc,
+ and any 0 bit is replaces with bgColorMonoSrc.
+
+ ==========================================================================
+ GE09R
+ ==========================================================================
+
+ GE09R[9:0] (Lined) srcLineStride
+ -----------------------------------------------
+ When Lined mode is being used (see memToScreen (GE00R[20])) and
+ srcEqualDestStride is false, contains the number of bytes in a line
+ of source data.
+
+ GE09R[27:25] (Lined) srcBitOffset
+ -----------------------------------------------
+ When Lined mode is being used (see memToScreen (GE00R[20])), contains
+ the bit offset into the byte containing the leftmost pixel. Makes
+ sense only with a monochrome source.
+
+ GE09R[30:28] (Lined) srcByteOffset
+ -----------------------------------------------
+ When Lined mode is being used (see memToScreen (GE00R[20])), contains
+ the byte offset of the byte containing the leftmost pixel.
+
+ GE09R[2:0] (Packed) srcLeadingBits
+ -----------------------------------------------
+ When Packed mode is being used (see memToScreen (GE00R[20])), contains
+ the bit offset into the byte containing the leftmost pixel. Makes
+ sense only with a monochrome source.
+
+ GE09R[5:3] (Packed) srcLeadingBytes
+ -----------------------------------------------
+ When Packed mode is being used (see memToScreen (GE00R[20])), contains
+ the byte offset of the byte containing the leftmost pixel.
+
+ GE09R[15:6] (Packed) srcNumBytes
+ -----------------------------------------------
+ When Packed mode is being used (see memToScreen (GE00R[20])), described
+ in the manual as: Number of 8 bytes amount that MIU needs to fetch from
+ frame buffer. For off-screen to on-screen packed mode, these 10 bits
+ represent the number of 8 bytes needed to be fetched by the MIU; the
+ maximum amount it can address is 16 Kbyte, which is the off screen
+ monochrome font or monochrome image graphics engine can support for
+ packed mode.
+
+ GE09R[27:25] (Packed) srcTrailingBits
+ -----------------------------------------------
+ When Packed mode is being used (see memToScreen (GE00R[20])), contains
+ the number of unused trailing bits in the last byte containing pixel
+ data. Makes sense only in monochrome mode.
+
+ GE09R[31:28] (Packed) srcTrailingBytes
+ -----------------------------------------------
+ When Packed mode is being used (see memToScreen (GE00R[20])), contains
+ the number of unused trailing bytes.
+
+ ==========================================================================
+ GE0AR
+ ==========================================================================
+
+ GE0AR[9:0] destLineStride
+ -----------------------------------------------
+ Specifies the stride (or rowBytes) of the destination bitmap. The
+ stride is the number of bytes between the first pixel of one line and
+ the first pixel of the following lines. This information duplicates
+ that stored in the graphic controller, but presumably is stored here
+ as well because the controller and accelerator are separate modules.
+
+ GE0AR[28] monoSrcBitSwap
+ -----------------------------------------------
+ Determines the interpretation of the bits in a monochrome pattern or
+ source bitmap. If this bit is clear, then bit 7 of a byte is the
+ leftmost pixel and bit 0 is the rightmost pixel. If this bit is set,
+ then bit 0 is the leftmost pixel and bit 7 is the rightmost. Having
+ this bit clear is consistent with Windows CE and Palm, and having it
+ set is consistent with EPOC.
+
+ GE0AR[29] rotate90
+ -----------------------------------------------
+ If set, rotates all drawing operation 90 degrees clockwise.
+
+ GE0AR[31:30] colorDepth
+ -----------------------------------------------
+ Determines the number of bits per pixel. If zero, BPP == 8. If one,
+ BPP == 16. All other settings are undefined. This information
+ duplicates that stored in the graphic controller, but presumably is
+ stored here as well because the controller and accelerator are
+ separate modules.
+
+ ==========================================================================
+ GE0BR
+ ==========================================================================
+
+ GE0BR[19:0] baseAddr
+ -----------------------------------------------
+ Determines the base address of the frame buffer, relative to the start
+ of the buffer. That is, a value of 0x00000 indicates the beginning of
+ the buffer, not the beginning of RAM. This information duplicates
+ that stored in the graphic controller, but presumably is stored here
+ as well because the controller and accelerator are separate modules.
+
+ GE0BR[29] testModeEnable
+ GE0BR[31:30] testModeControl
+ -----------------------------------------------
+ Test enable and control bits. Unsupported in Poser.
+
+ ==========================================================================
+ GE0CR
+ ==========================================================================
+
+ GE0CR[9:0] cmdLineStart
+ GE0CR[21:12] cmdLineEnd
+ -----------------------------------------------
+ Specifies the beginning and end of the "command start window".
+ However, there is no explanation of what this window is.
+
+ GE0CR[24] cmdLineControl
+ -----------------------------------------------
+ Controls whether or not the graphics engine needs to check with
+ graphics controller before starting a command. However, there's no
+ explanation of how the graphics controller decides whether or not a
+ command should be started.
+
+ GE0CR[27:26] gc1SwitchControl
+ -----------------------------------------------
+ Controls automatics switching between the main and alternate windows
+ in the graphic controller. A value of 0 or 2 means that no switching
+ is performed. A value of 1 means to switch to the main window after
+ the current drawing command is done. A value of 3 means to switch to
+ the alternate window when the command is done.
+
+ ==========================================================================
+ GE0FR
+ ==========================================================================
+
+ GE0FR[31:0]
+ -----------------------------------------------
+ If testModeEnable is on, this field receives various values, as
+ defined by testModeControl.
+
+ ==========================================================================
+ GE10R/GE11R
+ ==========================================================================
+
+ GE10R[31:0] monoPattern1
+ GE11R[31:0] monoPattern2
+ -----------------------------------------------
+ Together, these fields specify 64 bits of an 8x8 monochrome pattern.
+ The low-order byte of monoPattern1 contains the 8 bits for the first
+ line, the next-order byte of monoPattern1 contains the 8 bits for the
+ next line, etc., all the way up to the high-order byte of monoPattern2
+ containing the 8 bits for the last line.
+
+ ==========================================================================
+ GE12R/GE13R
+ ==========================================================================
+
+ GE12R[15:0] fgColorMonoPat
+ GE13R[15:0] bgColorMonoPat
+ -----------------------------------------------
+ When a monochrome pattern is being used, these two fields contain the
+ fore- and background colors that should be applied to the bits
+ representing the pixels. Any 1 bit is replace with fgColorMonoPat,
+ and any 0 bit is replaces with bgColorMonoPat.
+
+ **************************************************************************
+
+ Notes:
+ -----------------------------------------------
+ Transparency
+ -----------------------------------------------
+ Use destTransPolarity, colorTransCmpSrc, and destTransColor to
+ determine if the destination needs to be updated. All told, it should
+ lay out like this:
+
+ destTransPolarity == 0
+ colorTransCmpSrc == 0
+ Compare destTransColor to the source pixel.
+ If ==, do not update the destination.
+
+ That is, treat all destTransColor colored pixels
+ in the source as transparent.
+
+ colorTransCmpSrc == 1
+ Compare destTransColor to the destination pixel.
+ If ==, do not update the destination.
+
+ That is, leave all destTransColor colored pixels
+ in the destination alone.
+
+ destTransPolarity == 1
+ colorTransCmpSrc == 0
+ Compare destTransColor to the source pixel.
+ If !=, do not update the destination.
+
+ That is, transfer all destTransColor colored pixels
+ from the source to the destination.
+
+ colorTransCmpSrc == 1
+ Compare destTransColor to the destination pixel.
+ If !=, do not update the destination.
+
+ That is, update all destTransColor colored pixels
+ in the destination with source pixels.
+
+ ROPs
+ -----------------------------------------------
+ Take the pattern, source, and destination, and consider each value one
+ bit at a time. The three bits from the three values can form eight
+ combinations. The raster opcode is a bitfield containing the desired
+ output from each of the combinations. Thus:
+
+ P S D O (output)
+ --- --- --- ---
+ 0 0 0 b0
+ 0 0 1 b1
+ 0 1 0 b2
+ 0 1 1 b3
+ 1 0 0 b4
+ 1 0 1 b5
+ 1 1 0 b6
+ 1 1 1 b7
+
+ The output is the byte <b7><b6><b5><b4><b3><b2><b1><b0>. And this
+ output value is what becomes the raster opcode. Thus, if the raster
+ opcode is, for example, 0xCC, the table would be:
+
+ P S D O (output)
+ --- --- --- ---
+ 0 0 0 0
+ 0 0 1 0
+ 0 1 0 1
+ 0 1 1 1
+ 1 0 0 0
+ 1 0 1 0
+ 1 1 0 1
+ 1 1 1 1
+
+ So, the we look at three bits from the source and they're all zero,
+ then the output is zero. If they're all one, then the output is one.
+ If the pattern is one and the source and destination are zero, then
+ the output is zero. Overall,
+
+ Output[x] = ROP[P[x],S[x],D[x]]
+
+ where "x" is 0..7, and "P[x],S[x],D[x]" is a bitfield composed of the
+ given bits.
+
+\* --------------------------------------------------------------------------- */
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(x) ( \
+ ((emuptr) fRegs.x.GetPtr ()) - \
+ ((emuptr) fRegs.GetPtr ()) + \
+ ((emuptr) this->GetAddressStart ()) \
+ )
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsMediaQ11xx::read, \
+ (WriteFunction) &EmRegsMediaQ11xx::write, \
+ addressof (reg), 4)
+
+// Private inline function for reading a LE register.
+
+static inline
+uint32 PrvReadRegister(uint8* p)
+{
+#if EM_HOST_BYTE_ORDER == EM_LITTLE_ENDIAN
+
+ return *(uint32*) p;
+
+#else
+
+ return
+ (((UInt32) p[0]) << 0) +
+ (((UInt32) p[1]) << 8) +
+ (((UInt32) p[2]) << 16) +
+ (((UInt32) p[3]) << 24);
+
+#endif
+}
+
+// Private inline function for writing a LE register
+
+static inline
+void PrvWriteRegister(uint8* p, uint32 value)
+{
+#if EM_HOST_BYTE_ORDER == EM_LITTLE_ENDIAN
+
+ *(uint32*) p = value;
+
+#else
+
+ p[0] = value >> 0;
+ p[1] = value >> 8;
+ p[2] = value >> 16;
+ p[3] = value >> 24;
+
+#endif
+}
+
+
+// Macros to make calling PrvReadRegister and PrvWriteRegister easier.
+
+#define READ_REGISTER(reg) ::PrvReadRegister ((uint8*) (fRegs.reg.GetPtr ()))
+#define WRITE_REGISTER(reg, value) ::PrvWriteRegister ((uint8*) (fRegs.reg.GetPtr ()), value)
+
+
+// ROP values
+
+#define ROP_SRCCOPY 0xcc
+#define ROP_SRCAND 0x88
+//#define ROP_SRCANDNOT 0x77
+#define ROP_SRCANDNOT 0x22
+#define ROP_SRCXOR 0x66
+#define ROP_SRCOR 0xee
+#define ROP_SRCCOPYNOT 0x33
+#define ROP_SRCORNOT 0xbb
+#define ROP_SRCXORNOT 0x99
+
+#define ROP_PATCOPY 0xf0
+#define ROP_PATAND 0xa0
+//#define ROP_PATANDNOT 0x5f
+#define ROP_PATANDNOT 0x0a
+#define ROP_PATXOR 0x5a
+#define ROP_PATOR 0xfa
+#define ROP_PATCOPYNOT 0x0f
+#define ROP_PATORNOT 0xaf
+#define ROP_PATXORNOT 0xa5
+
+#define ROP_BLACKNESS 0x00
+
+
+
+#define CMD_FIFO_MASK (0x0000001F)
+#define CMD_FIFO_EMPTY (0x00000010)
+#define CMD_SRC_MASK (0x00001F00)
+#define CMD_SRC_EMPTY (0x00001000)
+#define GE_BUSY_H (0x00010000)
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Graphics Controller Registers
+//
+#define GC_CONTROL (0x00) // Graphics Controll Control Reg
+#define GC_PWR_SEQ_CONTROL (0x01) // Power Sequencing Control register
+#define GC_HTOTAL_HEND (0x02) // Horizontal Display Total & End
+#define GC_VTOTAL_VEND (0x03) // Vertical Display Total and End
+#define GC_HSYNC (0x04) // Horizontal Sync Start and End
+#define GC_VSYNC (0x05) // Vertical Sync Start and End
+#define GC_HWINDOW (0x08) // Horizontal Window Start & End
+#define GC_VWINDOW (0x09) // Vertical Window Start & End
+#define GC_LINE_CLOCK (0x0B) // Line Clock Control
+#define GC_START_ADDR (0x0C) // Image Window Start Address
+#define GC_ALTWIN_START_ADDR (0x0D) // Alt Image Window Start Address
+#define GC_STRIDE (0x0E) // (Alt) Image Window Stride
+#define GC_FRAME_CLOCK (0x1A) // Frame Clock Control
+#define GC_SIGNALS (0x1B) // Miscellaneous signal register (read only)
+#define GC_HPARAM (0x1C) // Horizontal parameter register (read only)
+#define GC_VPARAM (0x1D) // Vertical parameter register (read only)
+
+
+// GC_CONTROL register bit definition
+
+#define GC_ENABLE (1UL << 0) // Controll enabled
+#define GC_H_PIX_DBLNG (1UL << 14) // Enable Horizontal Pixel Doubling
+#define GC_V_PIX_DBLNG (1UL << 15) // Enable Vertical Scan Line Doubling
+#define GC_PIX_DBLNG_MASK (GC_H_PIX_DBLNG | GC_V_PIX_DBLNG)
+
+
+// Palette masks
+
+#define RED_MASK 0x0000000FC
+#define GREEN_MASK 0x00000FC00
+#define BLUE_MASK 0x000FC0000
+
+
+#define kColorDepth8 0
+#define kColorDepth16 1
+
+#define kCommandNOP 0
+#define kCommandBitBLT 2
+#define kCommandLine 4
+
+#define kAllRegisters -1
+
+static const char* kCommands[] =
+{
+ "NOP",
+ "Undefined",
+ "BitBLT",
+ "Reserved",
+ "Line Draw",
+ "Reserved",
+ "Undefined",
+ "Reserved",
+};
+
+static const char* kDirections[] =
+{
+ "Positive",
+ "Negative"
+};
+
+const struct
+{
+ uint16 yIsMajor; // 0 = x is major, 1 = y is major
+ uint16 xDirection; // 0 = x is positive, 1 = x is negative
+ uint16 yDirection; // 0 = y is positive, 1 = y is negative
+ const char* text; // Description for debugging.
+} kQuadrantDecode[] =
+{
+ { 0, 0, 0, "x-major, positive x and y directions" },
+ { 1, 0, 0, "y-major, positive x and y directions" },
+ { 1, 1, 0, "y-major, negative x and positive y directions" },
+ { 0, 1, 0, "x-major, negative x and positive y directions" },
+ { 0, 1, 1, "x-major, negative x and y directions" },
+ { 1, 1, 1, "y-major, negative x and y directions" },
+ { 1, 0, 1, "y-major, positive x and negative y directions" },
+ { 0, 0, 1, "x-major, positive x and negative y directions" }
+};
+
+static char* kROPs[] =
+{
+ "0 BLACKNESS", "DPSoon", "DPSona", "PSon",
+ "SDPona", "DPon", "PDSxnon", "PDSaon",
+ "SDPnaa", "PDSxon", "DPna", "PSDnaon",
+ "SPna", "PDSnaon", "PDSonon", "Pn",
+ "PDSona", "DSon NOTSRCERASE", "SDPxnon", "SDPaon",
+ "DPSxnon", "DPSaon", "PSDPSanaxx", "SSPxDSxaxn",
+ "SPxPDxa", "SDPSanaxn", "PDSPaox", "SDPSxaxn",
+ "PSDPaox", "DSPDxaxn", "PDSox", "PDSoan",
+ "DPSnaa", "SDPxon", "DSna", "SPDnaon",
+ "SPxDSxa", "PDSPanaxn", "SDPSaox", "SDPSxnox",
+ "DPSxa", "PSDPSaoxxn", "DPSana", "SSPxPDxaxn",
+ "SPDSoax", "PSDnox", "PSDPxox", "PSDnoan",
+ "PSna", "SDPnaon", "SDPSoox", "Sn NOTSRCCOPY",
+ "SPDSaox", "SPDSxnox", "SDPox", "SDPoan",
+ "PSDPoax", "SPDnox", "SPDSxox", "SPDnoan",
+ "PSx", "SPDSonox", "SPDSnaox", "PSan",
+ "PSDnaa", "DPSxon", "SDxPDxa", "SPDSanaxn",
+ "SDna SRCERASE", "DPSnaon", "DSPDaox", "PSDPxaxn",
+ "SDPxa", "PDSPDaoxxn", "DPSDoax", "PDSnox",
+ "SDPana", "SSPxDSxoxn", "PDSPxox", "PDSnoan",
+ "PDna", "DSPnaon", "DPSDaox", "SPDSxaxn",
+ "DPSonon", "Dn DSTINVERT", "DPSox", "DPSoan",
+ "PDSPoax", "DPSnox", "DPx PATINVERT", "DPSDonox",
+ "DPSDxox", "DPSnoan", "DPSDnaox", "DPan",
+ "PDSxa", "DSPDSaoxxn", "DSPDoax", "SDPnox",
+ "SDPSoax", "DSPnox", "DSx SRCINVERT", "SDPSonox",
+ "DSPDSonoxxn", "PDSxxn", "DPSax", "PSDPSoaxxn",
+ "SDPax", "PDSPDoaxxn", "SDPSnoax", "PDSxnan",
+ "PDSana", "SSDxPDxaxn", "SDPSxox", "SDPnoan",
+ "DSPDxox", "DSPnoan", "SDPSnaox", "DSan",
+ "PDSax", "DSPDSoaxxn", "DPSDnoax", "SDPxnan",
+ "SPDSnoax", "DPSxnan", "SPxDSxo", "DPSaan",
+ "DPSaa", "SPxDSxon", "DPSxna", "SPDSnoaxn",
+ "SDPxna", "PDSPnoaxn", "DSPDSoaxx", "PDSaxn",
+ "DSa SRCAND", "SDPSnaoxn", "DSPnoa", "DSPDxoxn",
+ "SDPnoa", "SDPSxoxn", "SSDxPDxax", "PDSanan",
+ "PDSxna", "SDPSnoaxn", "DPSDPoaxx", "SPDaxn",
+ "PSDPSoaxx", "DPSaxn", "DPSxx", "PSDPSonoxx",
+ "SDPSonoxn", "DSxn", "DPSnax", "SDPSoaxn",
+ "SPDnax", "DSPDoaxn", "DSPDSaoxx", "PDSxan",
+ "DPa", "PDSPnaoxn", "DPSnoa", "DPSDxoxn",
+ "PDSPonoxn", "PDxn", "DSPnax", "PDSPoaxn",
+ "DPSoa", "DPSoxn", "D", "DPSono",
+ "SPDSxax", "DPSDaoxn", "DSPnao", "DPno",
+ "PDSnoa", "PDSPxoxn", "SSPxDSxox", "SDPanan",
+ "PSDnax", "DPSDoaxn", "DPSDPaoxx", "SDPxan",
+ "PSDPxax", "DSPDaoxn", "DPSnao", "DSno MERGEPAINT",
+ "SPDSanax", "SDxPDxan", "DPSxo", "DPSano",
+ "PSa MERGECOPY", "SPDSnaoxn", "SPDSonoxn", "PSxn",
+ "SPDnoa", "SPDSxoxn", "SDPnax", "PSDPoaxn",
+ "SDPoa", "SPDoxn", "DPSDxax", "SPDSaoxn",
+ "S SRCCOPY", "SDPono", "SDPnao", "SPno",
+ "PSDnoa", "PSDPxoxn", "PDSnax", "SPDSoaxn",
+ "SSPxPDxax", "DPSanan", "PSDPSaoxx", "DPSxan",
+ "PDSPxax", "SDPSaoxn", "DPSDanax", "SPxDSxan",
+ "SPDnao", "SDno", "SDPxo", "SDPano",
+ "PDSoa", "PDSoxn", "DSPDxax", "PSDPaoxn",
+ "SDPSxax", "PDSPaoxn", "SDPSanax", "SPxPDxan",
+ "SSPxDSxax", "DSPDSanaxxn", "DPSao", "DPSxno",
+ "SDPao", "SDPxno", "DSo SRCPAINT", "SDPnoo",
+ "P PATCOPY", "PDSono", "PDSnao", "PSno",
+ "PSDnao", "PDno", "PDSxo", "PDSano",
+ "PDSao", "PDSxno", "DPo", "DPSnoo PATPAINT",
+ "PSo", "PSDnoo", "DPSoo", "1 WHITENESS"
+};
+
+
+// Inline functions.
+
+inline uint32 EmRegsMediaQ11xx::PrvGetBPP (void)
+{
+ return 1 << ((READ_REGISTER (gcREG[GC_CONTROL]) & 0x00000070) >> 4);
+}
+
+inline uint32 EmRegsMediaQ11xx::PrvGetWidth (void)
+{
+ return (READ_REGISTER (gcREG[GC_HWINDOW]) >> 16) + 1;
+}
+
+inline uint32 EmRegsMediaQ11xx::PrvGetHeight (void)
+{
+ return (READ_REGISTER (gcREG[GC_VWINDOW]) >> 16) + 1;
+}
+
+inline uint32 EmRegsMediaQ11xx::PrvGetRowBytes (void)
+{
+ return READ_REGISTER (gcREG[GC_STRIDE]) & 0x0000FFFF;
+}
+
+inline uint32 EmRegsMediaQ11xx::PrvGetVideoOffset (void)
+{
+ return READ_REGISTER (gcREG[GC_START_ADDR]) & 0x0003FFFF;
+}
+
+inline emuptr EmRegsMediaQ11xx::PrvGetVideoBase (void)
+{
+ return fBaseVideoAddr;
+}
+
+inline emuptr EmRegsMediaQ11xx::PrvGetFrameBuffer (void)
+{
+ return this->PrvGetVideoBase () + this->PrvGetVideoOffset ();
+}
+
+inline Bool EmRegsMediaQ11xx::PrvGetXDoubling (void)
+{
+ return (READ_REGISTER (gcREG[GC_CONTROL]) & GC_H_PIX_DBLNG) != 0;
+}
+
+inline Bool EmRegsMediaQ11xx::PrvGetYDoubling (void)
+{
+ return (READ_REGISTER (gcREG[GC_CONTROL]) & GC_V_PIX_DBLNG) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::EmRegsMediaQ11xx
+// ---------------------------------------------------------------------------
+
+EmRegsMediaQ11xx::EmRegsMediaQ11xx (emuptr baseRegsAddr, emuptr baseVideoAddr) :
+ fBaseRegsAddr (baseRegsAddr),
+ fBaseVideoAddr (baseVideoAddr),
+ fRegs (),
+/* fState (), */
+/* fByteLanes (), */
+ fLastAddress (EmMemNULL),
+ fLastSize (0),
+ fSourceFifo (),
+ fBlitInProgress (false),
+ fCurXOffset (0),
+ fCurYOffset (0),
+ fUsesPattern (false),
+ fUsesSource (false),
+ fLeadingSourcePixels (0),
+ fTrailingSourcePixels (0),
+/* fPatternPipe (), */
+ fXPattern (0),
+ fYPattern (0),
+/* fSourcePipe (), */
+ fSourcePipeIndex (0),
+ fSourcePipeMax (0),
+ fSourcePipeSkip (0),
+ fXSrc (0),
+ fYSrc (0),
+ fXDest (0),
+ fYDest (0)
+{
+#if LOG_LINE || LOG_BLIT
+ LogGetStdLog ()->SetLogSize (32 * 1024L * 1024L);
+#endif
+
+ COMPILE_TIME_ASSERT(countof (kCommands) == 8);
+ COMPILE_TIME_ASSERT(countof (kDirections) == 2);
+ COMPILE_TIME_ASSERT(countof (kQuadrantDecode) == 8);
+ COMPILE_TIME_ASSERT(countof (kROPs) == 256);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::~EmRegsMediaQ11xx
+// ---------------------------------------------------------------------------
+
+EmRegsMediaQ11xx::~EmRegsMediaQ11xx (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ WRITE_REGISTER (ccREG[0x00], 0x00000000);
+ WRITE_REGISTER (ccREG[0x01], 0x00000000);
+ WRITE_REGISTER (ccREG[0x02], 0x00000000);
+ WRITE_REGISTER (ccREG[0x03], 0x00000000);
+ WRITE_REGISTER (ccREG[0x04], 0x00000000);
+
+ WRITE_REGISTER (mmREG[0x00], 0x00000000); // (Low nybble only)
+ WRITE_REGISTER (mmREG[0x01], 0x00000000); // (Low nybble only)
+ WRITE_REGISTER (mmREG[0x02], 0x00000000); // (Low nybble only)
+
+ WRITE_REGISTER (inREG[0x00], 0x00000000);
+ WRITE_REGISTER (inREG[0x01], 0x00000000);
+ WRITE_REGISTER (inREG[0x02], 0x00000000);
+ WRITE_REGISTER (inREG[0x03], 0x00000000);
+
+ WRITE_REGISTER (gcREG[0x00], 0x00000000);
+ WRITE_REGISTER (gcREG[0x01], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (gcREG[0x06], 0x00000000); // (Low word only)
+ WRITE_REGISTER (gcREG[0x07], 0x00000000); // (Low word only)
+
+ // GC_CONTROL (0x00) // Graphics Controll Control Reg
+ // GC_PWR_SEQ_CONTROL (0x01) // Power Sequencing Control register
+ // GC_HTOTAL_HEND (0x02) // Horizontal Display Total & End
+ // GC_VTOTAL_VEND (0x03) // Vertical Display Total and End
+ // GC_HSYNC (0x04) // Horizontal Sync Start and End
+ // GC_VSYNC (0x05) // Vertical Sync Start and End
+ // GC_HWINDOW (0x08) // Horizontal Window Start & End
+ // GC_VWINDOW (0x09) // Vertical Window Start & End
+ // GC_LINE_CLOCK (0x0B) // Line Clock Control
+ // GC_START_ADDR (0x0C) // Image Window Start Address
+ // GC_ALTWIN_START_ADDR (0x0D) // Alt Image Window Start Address
+ // GC_STRIDE (0x0E) // (Alt) Image Window Stride
+ // GC_FRAME_CLOCK (0x1A) // Frame Clock Control
+
+ // For now, let's initialize all the graphics controller registers to 0.
+ for (int i = 0x00; i < 0x20; i++)
+ {
+ WRITE_REGISTER (gcREG[i], 0x00000000);
+ }
+
+ WRITE_REGISTER (geREG[0x00], 0x00000000);
+ WRITE_REGISTER (geREG[0x0C], 0x00000000);
+
+ WRITE_REGISTER (ssREG[0x00], 0x00000000);
+ WRITE_REGISTER (ssREG[0x01], 0x00000000);
+ WRITE_REGISTER (ssREG[0x04], 0x00000000); // (Low nybble only)
+ WRITE_REGISTER (ssREG[0x08], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (ssREG[0x09], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (ssREG[0x0A], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (ssREG[0x0B], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (ssREG[0x10], 0x00000000);
+ WRITE_REGISTER (ssREG[0x11], 0x00000000);
+ WRITE_REGISTER (ssREG[0x13], 0x00000000);
+
+ WRITE_REGISTER (spREG[0x00], 0x00000000);
+ WRITE_REGISTER (spREG[0x01], 0xF0000000);
+ WRITE_REGISTER (spREG[0x02], 0x00000000);
+ WRITE_REGISTER (spREG[0x03], 0x00000000);
+ WRITE_REGISTER (spREG[0x04], 0x00000000);
+ WRITE_REGISTER (spREG[0x05], 0x00000000);
+ WRITE_REGISTER (spREG[0x06], 0x00000000);
+ WRITE_REGISTER (spREG[0x07], 0x00000000);
+ WRITE_REGISTER (spREG[0x08], 0x00000000);
+
+ WRITE_REGISTER (dcREG[0x00], 0x00000000);
+ WRITE_REGISTER (dcREG[0x01], 0xF0000000);
+ WRITE_REGISTER (dcREG[0x02], 0x00000000);
+ WRITE_REGISTER (dcREG[0x03], 0x00000000);
+ WRITE_REGISTER (dcREG[0x04], 0x00000000);
+ WRITE_REGISTER (dcREG[0x05], 0x00000000);
+ WRITE_REGISTER (dcREG[0x06], 0x00000000);
+ WRITE_REGISTER (dcREG[0x07], 0x00000000);
+
+ WRITE_REGISTER (pcREG[0x00], 0x01204D51);
+ WRITE_REGISTER (pcREG[0x01], 0x02800000);
+ WRITE_REGISTER (pcREG[0x02], 0x03800000);
+ WRITE_REGISTER (pcREG[0x03], 0x00000000);
+ WRITE_REGISTER (pcREG[0x0B], 0x00000100);
+ WRITE_REGISTER (pcREG[0x0F], 0x00000100);
+
+ WRITE_REGISTER (uhREG[0x00], 0x00000010); // (Low byte only)
+ WRITE_REGISTER (uhREG[0x01], 0x00000000);
+ WRITE_REGISTER (uhREG[0x02], 0x00000000);
+ WRITE_REGISTER (uhREG[0x03], 0x00000000);
+ WRITE_REGISTER (uhREG[0x04], 0x00000000);
+ WRITE_REGISTER (uhREG[0x05], 0x00000000);
+ WRITE_REGISTER (uhREG[0x06], 0x00000000);
+ WRITE_REGISTER (uhREG[0x07], 0x00000000);
+ WRITE_REGISTER (uhREG[0x08], 0x00000000);
+ WRITE_REGISTER (uhREG[0x09], 0x00000000);
+ WRITE_REGISTER (uhREG[0x0A], 0x00000000);
+ WRITE_REGISTER (uhREG[0x0B], 0x00000000);
+ WRITE_REGISTER (uhREG[0x0C], 0x00000000);
+ WRITE_REGISTER (uhREG[0x0D], 0x00002EDF);
+ WRITE_REGISTER (uhREG[0x0E], 0x00000000);
+ WRITE_REGISTER (uhREG[0x0F], 0x00000000);
+ WRITE_REGISTER (uhREG[0x10], 0x00000000); // (Low word only)
+ WRITE_REGISTER (uhREG[0x11], 0x00000628);
+ WRITE_REGISTER (uhREG[0x12], 0x00001102);
+ WRITE_REGISTER (uhREG[0x13], 0x00000000);
+ WRITE_REGISTER (uhREG[0x14], 0x00000000);
+ WRITE_REGISTER (uhREG[0x15], 0x00000000);
+ WRITE_REGISTER (uhREG[0x16], 0x00000000);
+
+ WRITE_REGISTER (fpREG[0x00], 0x00000000);
+ WRITE_REGISTER (fpREG[0x01], 0x00000000);
+ WRITE_REGISTER (fpREG[0x02], 0x0FFCFCFF);
+ WRITE_REGISTER (fpREG[0x03], 0x00000000);
+ WRITE_REGISTER (fpREG[0x04], 0x00000000);
+ WRITE_REGISTER (fpREG[0x05], 0x00000000);
+ WRITE_REGISTER (fpREG[0x06], 0x00000000);
+ WRITE_REGISTER (fpREG[0x07], 0x00000000);
+ WRITE_REGISTER (fpREG[0x0A], 0xF0030000);
+ WRITE_REGISTER (fpREG[0x0B], 0x00000000); // (Low 12-bits only)
+ WRITE_REGISTER (fpREG[0x0E], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (fpREG[0x0F], 0x00000000);
+
+ // (No reset values for color palette and source FIFO)
+
+ WRITE_REGISTER (udREG[0x00], 0x00000000);
+ WRITE_REGISTER (udREG[0x01], 0x00000000);
+ WRITE_REGISTER (udREG[0x02], 0x00000000);
+ WRITE_REGISTER (udREG[0x03], 0x00000000);
+ WRITE_REGISTER (udREG[0x04], 0x00000000);
+ WRITE_REGISTER (udREG[0x05], 0x00000000);
+ WRITE_REGISTER (udREG[0x06], 0x00000000);
+ WRITE_REGISTER (udREG[0x07], 0x00000000);
+ WRITE_REGISTER (udREG[0x08], 0x00000000);
+ WRITE_REGISTER (udREG[0x09], 0x00000000);
+ WRITE_REGISTER (udREG[0x0A], 0x00000000);
+ WRITE_REGISTER (udREG[0x0B], 0x00000000); // (Low byte only)
+ WRITE_REGISTER (udREG[0x0C], 0x00000000);
+ WRITE_REGISTER (udREG[0x0D], 0x00000000);
+ WRITE_REGISTER (udREG[0x0E], 0x00000000);
+ WRITE_REGISTER (udREG[0x0F], 0x00000000);
+ WRITE_REGISTER (udREG[0x00], 0x00000000);
+ WRITE_REGISTER (udREG[0x01], 0x00000000);
+ WRITE_REGISTER (udREG[0x02], 0x00000000);
+
+ // Because DC00R is reset to zero, establish the
+ // byteswapping lanes corresponding to that.
+
+ this->PrvUpdateByteLanes ();
+
+ fLastAddress = EmMemNULL;
+ fLastSize = 0;
+
+ fBlitInProgress = false;
+
+ this->PrvGetGEState (kAllRegisters);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::Save (SessionFile& f)
+{
+ const long kCurrentMediaQVersion = 1;
+
+ EmRegs::Save (f);
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentMediaQVersion;
+
+ s.PutBytes (fRegs.GetPtr (), fRegs.GetSize ());
+
+ f.WriteMediaQRegsType (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ Chunk chunk;
+
+ if (!f.ReadMediaQRegsType (chunk))
+ {
+ f.SetCanReload (false);
+ }
+ else
+ {
+ long version;
+
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s.GetBytes (fRegs.GetPtr (), fRegs.GetSize ());
+ }
+ }
+
+ this->PrvUpdateByteLanes ();
+
+ // !!! Save and restore these?
+
+ fLastAddress = EmMemNULL;
+ fLastSize = 0;
+
+ fBlitInProgress = false;
+
+ this->PrvGetGEState (kAllRegisters);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (MQRead, MQWrite, ccREG[0x00]);
+ INSTALL_HANDLER (CC01Read, MQWrite, ccREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, ccREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, ccREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, ccREG[0x04]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, mmREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, mmREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, mmREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, mmREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, mmREG[0x04]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, inREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, inREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, inREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, inREG[0x03]);
+
+ INSTALL_HANDLER (MQRead, invalidateWrite, gcREG[0x00]); // BPP (et al)
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x07]);
+ INSTALL_HANDLER (MQRead, invalidateWrite, gcREG[0x08]); // Width
+ INSTALL_HANDLER (MQRead, invalidateWrite, gcREG[0x09]); // Height
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x0B]);
+ INSTALL_HANDLER (MQRead, invalidateWrite, gcREG[0x0C]); // Base Address
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x0D]);
+ INSTALL_HANDLER (MQRead, invalidateWrite, gcREG[0x0E]); // Stride
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x0F]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x10]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x12]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x13]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x14]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x15]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x16]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x17]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x18]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x19]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1A]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1B]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1C]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1D]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1E]);
+ INSTALL_HANDLER (MQRead, MQWrite, gcREG[0x1F]);
+
+ INSTALL_HANDLER (MQRead, GE00Write, geREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x01]);
+ INSTALL_HANDLER (MQRead, GE02Write, geREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x07]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x08]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x09]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0B]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0C]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0D]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0E]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x0F]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x10]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x12]);
+ INSTALL_HANDLER (MQRead, MQWrite, geREG[0x13]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x04]); // Skip some here
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x08]); // Skip some here
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x09]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x0B]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x0C]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x0D]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x10]); // Skip some here
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x12]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x13]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x14]);
+ INSTALL_HANDLER (MQRead, MQWrite, ssREG[0x15]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x07]);
+ INSTALL_HANDLER (MQRead, MQWrite, spREG[0x08]);
+
+ INSTALL_HANDLER (MQRead, DC00Write, dcREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, dcREG[0x07]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x0B]); // Skip some here
+ INSTALL_HANDLER (MQRead, MQWrite, pcREG[0x0F]); // Skip some here
+
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x07]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x08]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x09]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0B]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0C]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0D]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0E]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x0F]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x10]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x12]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x13]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x14]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x15]);
+ INSTALL_HANDLER (MQRead, MQWrite, uhREG[0x16]);
+
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x07]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x08]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x09]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x0B]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x0E]); // Skip some here
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x0F]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x10]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x12]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x13]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x14]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x15]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x16]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x17]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x18]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x19]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1A]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1B]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1C]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1D]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1E]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x1F]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x20]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x21]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x22]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x23]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x24]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x25]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x26]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x27]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x28]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x29]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2A]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2B]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2C]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2D]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2E]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x2F]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x30]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x31]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x32]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x33]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x34]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x35]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x36]);
+ INSTALL_HANDLER (MQRead, MQWrite, fpREG[0x37]);
+
+ this->SetHandler ( (ReadFunction) &EmRegsMediaQ11xx::MQRead,
+ (WriteFunction) &EmRegsMediaQ11xx::invalidateWrite,
+ addressof (cpREG), 0x0400);
+
+ this->SetHandler ( (ReadFunction) &EmRegsMediaQ11xx::MQRead,
+ (WriteFunction) &EmRegsMediaQ11xx::SourceFifoWrite,
+ addressof (sfREG), 0x0400);
+
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x00]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x01]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x02]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x03]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x04]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x05]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x06]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x07]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x08]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x09]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0A]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0B]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0C]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0D]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0E]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x0F]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x10]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x11]);
+ INSTALL_HANDLER (MQRead, MQWrite, udREG[0x12]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsMediaQ11xx::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + (address - this->GetAddressStart ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsMediaQ11xx::GetAddressStart (void)
+{
+ return fBaseRegsAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsMediaQ11xx::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsMediaQ11xx::GetLCDScreenOn (void)
+{
+ return ((READ_REGISTER (gcREG[GC_CONTROL]) & GC_ENABLE) != 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsMediaQ11xx::GetLCDBacklightOn (void)
+{
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsMediaQ11xx::GetLCDHasFrame (void)
+{
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ int32 height = this->PrvGetHeight ();
+ int32 rowBytes = this->PrvGetRowBytes ();
+ emuptr baseAddr = this->PrvGetFrameBuffer ();
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+ int32 bpp = this->PrvGetBPP ();
+ int32 width = this->PrvGetWidth ();
+ int32 height = this->PrvGetHeight ();
+ int32 rowBytes = this->PrvGetRowBytes ();
+ emuptr baseAddr = this->PrvGetFrameBuffer ();
+
+#ifdef _DEBUG
+ Bool xDoubling = this->PrvGetXDoubling ();
+ Bool yDoubling = this->PrvGetYDoubling ();
+
+ EmAssert (xDoubling == 0 && yDoubling == 0);
+#endif
+
+ info.fLeftMargin = 0;
+
+ if (bpp <= 8)
+ {
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+ }
+ else
+ {
+ // Set depth, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (kPixMapFormat24RGB);
+
+ // Determine first and last scanlines to fetch.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ // Get location and rowBytes of source bytes.
+
+ uint8* srcStart = EmMemGetRealAddress (baseAddr);
+ int32 srcRowBytes = rowBytes;
+ uint8* srcPtr = srcStart + srcRowBytes * info.fFirstLine;
+ uint8* srcPtr0 = srcPtr;
+
+ // Get location and rowBytes of destination bytes.
+
+ uint8* destStart = (uint8*) info.fImage.GetBits ();
+ int32 destRowBytes = info.fImage.GetRowBytes ();
+ uint8* destPtr = destStart + destRowBytes * info.fFirstLine;
+ uint8* destPtr0 = destPtr;
+
+ // Get height of range to copy.
+
+ int32 height = info.fLastLine - info.fFirstLine;
+
+ // Copy the pixels from source to dest.
+
+ for (int yy = 0; yy < height; ++yy)
+ {
+ for (int xx = 0; xx < width; ++xx)
+ {
+ uint8 p1 = EmMemDoGet8 (srcPtr++); // GGGBBBBB
+ uint8 p2 = EmMemDoGet8 (srcPtr++); // RRRRRGGG
+
+ // Merge the two together so that we get RRRRRGGG GGGBBBBB
+
+ uint16 p;
+
+ p = (p1 << 8) | p2;
+
+ // Shift the bits around, forming RRRRRrrr, GGGGGGgg, and
+ // BBBBBbbb values, where the lower-case bits are copies of
+ // the least significant bits in the upper-case bits.
+ //
+ // Note that all of this could also be done with three 64K
+ // lookup tables. If speed is an issue, we might want to
+ // investigate that.
+
+ if (bpp == 1)
+ {
+ uint8 green = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = green;
+ *destPtr++ = green;
+ *destPtr++ = green;
+ }
+ else
+ {
+ *destPtr++ = ((p >> 8) & 0xF8) | ((p >> 11) & 0x07);
+ *destPtr++ = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = ((p << 3) & 0xF8) | ((p >> 0) & 0x07);
+ }
+ }
+
+ srcPtr = srcPtr0 += srcRowBytes;
+ destPtr = destPtr0 += destRowBytes;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::MQRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsMediaQ11xx::MQRead (emuptr address, int size)
+{
+ // Determine the offset from the beginning of the register memory range
+ // to the location we want to read.
+
+ uint32 offset = address - this->GetAddressStart ();
+
+ EmAssert (offset < this->GetAddressRange ());
+
+ // Determine the index for the register being read (treating the entire
+ // memory range as an array of 32-bit values), and determine the delta
+ // into the register.
+
+ int index = offset / 4;
+ int delta = offset - (index * 4);
+
+ EmAssert (delta >= 0);
+ EmAssert (delta < 4);
+
+ // Get the pointer to the register to read from.
+
+ UInt32 value;
+ UInt8* p = (UInt8*) fRegs.ccREG[index].GetPtr ();
+
+ if (size == 4)
+ {
+ // Make sure we're reading the whole register.
+
+ if ((delta & 3) != 0)
+ this->AddressError (address, size, true);
+
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Read the value a byte at a time, reconstructing it according
+ // to the byteswapping rules.
+
+ value =
+ (((UInt32) p[bytelanes[0]]) << 24) |
+ (((UInt32) p[bytelanes[1]]) << 16) |
+ (((UInt32) p[bytelanes[2]]) << 8) |
+ (((UInt32) p[bytelanes[3]]) << 0);
+ }
+ else if (size == 2)
+ {
+ // Make sure we're reading from an even address.
+ // !!! This is really a characteristic of the host
+ // CPU and bus, not the MediaQ chip.
+
+ if ((delta & 1) != 0)
+ this->AddressError (address, size, true);
+
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Read the value a byte at a time, reconstructing it according
+ // to the byteswapping rules.
+
+ value =
+ (((UInt32) p[bytelanes[0]]) << 8) |
+ (((UInt32) p[bytelanes[1]]) << 0);
+ }
+ else if (size == 1)
+ {
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Read the value a byte at a time, reconstructing it according
+ // to the byteswapping rules.
+
+ value =
+ (((UInt32) p[bytelanes[0]]) << 0);
+ }
+ else
+ {
+ EmAssert (false);
+ value = 0;
+ }
+
+ return value;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::MQWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::MQWrite (emuptr address, int size, uint32 value)
+{
+ // Determine the offset from the beginning of the register memory range
+ // to the location we want to update.
+
+ uint32 offset = address - this->GetAddressStart ();
+
+ EmAssert (offset < this->GetAddressRange ());
+
+ // Determine the index for the register being updated (treating the entire
+ // memory range as an array of 32-bit values), and determine the delta
+ // into the register.
+
+ int index = offset / 4;
+ int delta = offset - (index * 4);
+
+ EmAssert (delta >= 0);
+ EmAssert (delta < 4);
+
+ // Get the pointer to the register to update.
+
+ UInt8* p = (UInt8*) fRegs.ccREG[index].GetPtr ();
+
+ if (size == 4)
+ {
+ // Make sure we're updating the whole register.
+
+ if ((delta & 3) != 0)
+ this->AddressError (address, size, false);
+
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Write the value a byte at a time, using the bytelanes array
+ // to sort out the byteswapping for us.
+
+ p[bytelanes[0]] = value >> 24;
+ p[bytelanes[1]] = value >> 16;
+ p[bytelanes[2]] = value >> 8;
+ p[bytelanes[3]] = value >> 0;
+ }
+ else if (size == 2)
+ {
+ // Make sure we're updating to an even address.
+ // !!! This is really a characteristic of the host
+ // CPU and bus, not the MediaQ chip.
+
+ if ((delta & 1) != 0)
+ this->AddressError (address, size, false);
+
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Write the value a byte at a time, using the bytelanes array
+ // to sort out the byteswapping for us.
+
+ p[bytelanes[0]] = value >> 8;
+ p[bytelanes[1]] = value >> 0;
+ }
+ else if (size == 1)
+ {
+ // Get a pointer to the "bytelanes" array that will sort out
+ // any 32-bit or 16-bit byteswapping for us.
+
+ int* bytelanes = &this->fBytelanes[delta];
+
+ // Write the value a byte at a time, using the bytelanes array
+ // to sort out the byteswapping for us.
+
+ p[bytelanes[0]] = value >> 0;
+ }
+ else
+ {
+ EmAssert (false);
+ }
+
+ fLastAddress = address;
+ fLastSize = size;
+
+ if (index >= 0x080 && index <= 0x093)
+ {
+ this->PrvGetGEState (index - 0x080);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::CC01Read
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsMediaQ11xx::CC01Read (emuptr address, int size)
+{
+ // Update the Command FIFO size.
+ // Update the Source FIFO size.
+ // Also make sure the busy bit is clear.
+
+ uint32 CC01 = READ_REGISTER (ccREG[0x01]);
+
+ CC01 = (CC01 & ~CMD_FIFO_MASK) | (CMD_FIFO_EMPTY & CMD_FIFO_MASK);
+ CC01 = (CC01 & ~CMD_SRC_MASK) | (CMD_SRC_EMPTY & CMD_SRC_MASK);
+ CC01 = CC01 & ~GE_BUSY_H;
+
+ WRITE_REGISTER (ccREG[0x01], CC01);
+
+ // Perform a standard read.
+
+ uint32 result = MQRead (address, size);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::DC00Write
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::DC00Write (emuptr address, int size, uint32 value)
+{
+ // Perform a standard update.
+
+ this->MQWrite (address, size, value);
+
+ this->PrvUpdateByteLanes ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GE00Write
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::GE00Write (emuptr address, int size, uint32 value)
+{
+ emuptr lastAddress = this->fLastAddress;
+ int lastSize = this->fLastSize;
+
+ // Perform a standard update.
+
+ this->MQWrite (address, size, value);
+
+ // If a command was issued, execute it (if autoExecute is false).
+
+ uint32 reg = READ_REGISTER (geREG[0]);
+
+ if ((reg & (1 << 27)) == 0)
+ {
+ if (size == 4)
+ {
+ this->PrvDoCommand ();
+ }
+ else if (size == 2 && lastSize == 2 && address == (lastAddress + 2))
+ {
+ this->PrvDoCommand ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::GE02Write
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::GE02Write (emuptr address, int size, uint32 value)
+{
+ emuptr lastAddress = this->fLastAddress;
+ int lastSize = this->fLastSize;
+
+ // Perform a standard update.
+
+ this->MQWrite (address, size, value);
+
+ // If a command was issued, execute it (if autoExecute is true).
+
+ uint32 reg = READ_REGISTER (geREG[0]);
+
+ if ((reg & (1 << 27)) != 0)
+ {
+ if (size == 4)
+ {
+ this->PrvDoCommand ();
+ }
+ else if (size == 2 && lastSize == 2 && address == (lastAddress + 2))
+ {
+ this->PrvDoCommand ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::SourceFifoWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::SourceFifoWrite (emuptr address, int size, uint32 value)
+{
+ emuptr lastAddress = this->fLastAddress;
+ int lastSize = this->fLastSize;
+
+ // Perform a standard update.
+
+ this->MQWrite (address, size, value);
+
+ // If a complete entry was added, push it onto the FIFO, and give the
+ // blitter a chance to run.
+
+ if (size == 4)
+ {
+ value = READ_REGISTER (sfREG[(address >> 2) & 0x0FF]);
+ fSourceFifo.push_back (value);
+ this->PrvIncBlitterRun ();
+ }
+ else if (size == 2 && lastSize == 2 && address == (lastAddress + 2))
+ {
+ value = READ_REGISTER (sfREG[(address >> 2) & 0x0FF]);
+ fSourceFifo.push_back (value);
+ this->PrvIncBlitterRun ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::invalidateWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::invalidateWrite (emuptr address, int size, uint32 value)
+{
+ // Perform a standard update.
+
+ this->MQWrite (address, size, value);
+
+ // Invalidate the entire LCD area so that it can get redrawn with
+ // the new palette information.
+
+ EmScreen::InvalidateAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::AddressError
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::AddressError (emuptr address, long size, Bool forRead)
+{
+ EmAssert (false);
+ EmAssert (gCPU68K);
+ gCPU68K->AddressError (address, size, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvGetPalette (RGBList& thePalette)
+{
+ int32 bpp = this->PrvGetBPP ();
+ int32 numColors = 1 << bpp;
+
+ thePalette.resize (numColors);
+
+ for (int ii = 0; ii < numColors; ++ii)
+ {
+ uint32 reg = READ_REGISTER (cpREG[ii]);
+
+ thePalette[ii].fRed = (reg & RED_MASK) >> 0;
+ thePalette[ii].fGreen = (reg & GREEN_MASK) >> 8;
+ thePalette[ii].fBlue = (reg & BLUE_MASK) >> 16;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvUpdateByteLanes
+// ---------------------------------------------------------------------------
+/*
+ Figuring out byteswapping:
+
+ Our source code has the following function for writing data to registers:
+
+ void sREGW (volatile UCHAR* addr, ULONG data)
+ {
+ UInt16 _data16;
+ UInt16* dc00R = (UInt16*) (MMIO_BASE + DC_BASE);
+
+ if (*dc00R & 1) // no need to swap data (16BPP mode) within word16
+ {
+ *((UInt16*) addr) = (UInt16) data; // write without swap
+ *((UInt16*) (addr + 2)) = (UInt16) __rol (data, 16); // get next word16
+ }
+ else
+ {
+ _data16 = (UInt16) (data);
+ _data16 = __rol (_data16, 8); // bswap for Big Endian
+ *((UInt16*) addr) = _data16;
+
+ _data16 = (UInt16) __rol (data, 16); // get next word16
+ _data16 = __rol (_data16, 8); // bswap for Big Endian
+ *((UInt16 *)(addr + 2)) = _data16;
+ }
+ }
+
+ My assumption here is that we want to take a data pattern like 0x01234567
+ and end up with it stored in the register as 67 45 23 01. Working from
+ the code above, if byteswapping is off, we execute the following:
+
+ *((UInt16*) addr) = (UInt16) data; // write without swap
+ *((UInt16*) (addr + 2)) = (UInt16) __rol (data, 16); // get next word16
+
+ or:
+
+ *((UInt16*) addr) = 0x4567; // write without swap
+ *((UInt16*) (addr + 2)) = 0x0123; // get next word16
+
+ In order for this to result in the right bytes getting written to the
+ right places in memory, 16-bit byteswapping must be on at the hardware
+ level. Confirming with the code in the "else" statement:
+
+ _data16 = (UInt16) (data);
+ _data16 = __rol (_data16, 8); // bswap for Big Endian
+ *((UInt16*) addr) = _data16;
+
+ _data16 = (UInt16) __rol (data, 16); // get next word16
+ _data16 = __rol (_data16, 8); // bswap for Big Endian
+ *((UInt16 *)(addr + 2)) = _data16;
+
+ or:
+
+ _data16 = 0x4567;
+ _data16 = 0x6745; // bswap for Big Endian
+ *((UInt16*) addr) = 0x6745;
+
+ _data16 = 0x0123; // get next word16
+ _data16 = 0x2301; // bswap for Big Endian
+ *((UInt16 *)(addr + 2)) = 0x2301;
+
+ In this case, if 16-bit byteswapping is turned on in the device
+ configuration register, then that will counteract the byteswapping
+ performed by the hardware. If, however, 32-bit byteswapping is
+ enabled in the device configuration register, I'm not sure what
+ will happen.
+
+ Let's take a look at another example. Registers are often written
+ using the geREG16 macro. This macro is called twice in order to
+ update the whole 32-bit register:
+
+ geREG16( GE_WIDTH_L, width );
+ geREG16( GE_HEIGHT_H, height );
+
+ Where:
+
+ #define GE_WIDTH_L (GE_WIDTH_HEIGHT) // 40204h
+ #define GE_HEIGHT_H (GE_WIDTH_HEIGHT + 2) // 40206h
+
+ There is also a geREG macro used to update the whole 32-bit register
+ at once:
+
+ geREG( GE_DEST_XY, dstAddr );
+
+ I find a number of definitions of these macros. The two sets that
+ appear most likely to be the ones used in our ROM are as follows:
+
+ # mqgeHAL.h
+
+ #define geREG16(id, data) *(pGE16 + (id)) = (UInt16)(data)
+ #define geREG(id, data) *(pGE + (id)) = (UInt32)(data)
+
+ # mqge.h
+
+ #define geREG16(id, data) *((UInt16 *)(pGE + id)) = __rol( data, 8 )
+ #define geREG(id, data) \
+ { \
+ register UInt32 _data32; \
+ _data32 = (data); \
+ geREG16(id, (UInt16)_data32); \
+ geREG16((id + 2), (UInt16)(_data32 >> 16) ); \
+ }
+
+ The second set appears to be more consistant with our first
+ study case, so let's assume that it represents what's going
+ on in our ROM.
+
+ What's left unclear is what really happens when writing a 32-bit
+ value to a 32-bit register, and how the 64-bit source data FIFO
+ is handled.
+*/
+
+void EmRegsMediaQ11xx::PrvUpdateByteLanes (void)
+{
+ // Read the register.
+
+ uint32 reg = READ_REGISTER (dcREG[0x00]);
+
+ // Adjust the bytelanes array to reflect the byteswapping options.
+ // Without any other adjustments, it appears that the CPU bytelanes
+ // are set up to swap 16-bit values with the MediaQ chip.
+
+ this->fBytelanes[0] = 1;
+ this->fBytelanes[1] = 0;
+ this->fBytelanes[2] = 3;
+ this->fBytelanes[3] = 2;
+
+ if ((reg & 1) == 1)
+ {
+ // Enable little endian mode. Byte swapping is not performed on data.
+
+ }
+ else if ((reg & 2) == 2)
+ {
+ // Enable 32-bit byte swapping for big endian to little endian conversion.
+ // byte0 <-> byte3, byte1 <-> byte2
+
+ std::swap (this->fBytelanes[0], this->fBytelanes[3]);
+ std::swap (this->fBytelanes[1], this->fBytelanes[2]);
+ }
+ else
+ {
+ // Enable 16-bit Byte swapping for big endian to little endian conversion.
+ // byte0 <-> byte1, byte2 <-> byte3
+
+ std::swap (this->fBytelanes[0], this->fBytelanes[1]);
+ std::swap (this->fBytelanes[2], this->fBytelanes[3]);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvGetGEState
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvGetGEState (int regNum)
+{
+ uint32 reg;
+
+ // ==================== GE00R ====================
+
+ if (regNum == kAllRegisters || regNum == 0)
+ {
+ reg = READ_REGISTER (geREG[0x00]);
+
+ fState.rasterOperation = (reg >> 0) & 0x000000FF;
+ fState.commandType = (reg >> 8) & 0x00000007;
+ fState.xDirection = (reg >> 11) & 0x00000001;
+ fState.yDirection = (reg >> 12) & 0x00000001;
+ fState.systemMemory = (reg >> 13) & 0x00000001;
+ fState.monoSource = (reg >> 14) & 0x00000001;
+ fState.monoPattern = (reg >> 15) & 0x00000001;
+ fState.colorTransEnable = (reg >> 16) & 0x00000001;
+ fState.destTransPolarity = (reg >> 17) & 0x00000001;
+ fState.monoTransEnable = (reg >> 18) & 0x00000001;
+ fState.monoTransPolarity = (reg >> 19) & 0x00000001;
+ fState.memToScreen = (reg >> 20) & 0x00000001;
+ fState.solidSourceColor = (reg >> 23) & 0x00000001;
+ fState.srcEqualDestStride = (reg >> 24) & 0x00000001;
+ fState.rop2Select = (reg >> 25) & 0x00000001;
+ fState.clipEnable = (reg >> 26) & 0x00000001;
+ fState.autoExecute = (reg >> 27) & 0x00000001;
+ fState.solidPattern = (reg >> 30) & 0x00000001;
+ fState.colorTransCmpSrc = (reg >> 31) & 0x00000001;
+ }
+
+ // ==================== GE01R ====================
+
+ if (regNum == kAllRegisters || regNum == 1)
+ {
+ reg = READ_REGISTER (geREG[0x01]);
+
+ // BitBLT
+
+ fState.width = (reg >> 0) & 0x00000FFF;
+ fState.height = (reg >> 16) & 0x00000FFF;
+ fState.xyConversion = (reg >> 31) & 0x00000001;
+
+ // Line
+
+ fState.gamma = (reg >> 0) & 0x0001FFFF; fState.gamma |= 0xFFFE0000;
+ fState.majorLength = (reg >> 17) & 0x00000FFF;
+ fState.yIsMajor = (reg >> 29) & 0x00000001;
+ fState.drawLastPixel = (reg >> 30) & 0x00000001;
+ fState.useXY = (reg >> 31) & 0x00000001;
+ }
+
+ // ==================== GE02R ====================
+
+ if (regNum == kAllRegisters || regNum == 2)
+ {
+ reg = READ_REGISTER (geREG[0x02]);
+
+ // BitBLT
+
+ fState.xDest = (reg >> 0) & 0x00000FFF;
+ fState.monoPatternXOffset = (reg >> 13) & 0x00000007;
+ fState.yDest = (reg >> 16) & 0x00000FFF;
+ fState.monoPatternYOffset = (reg >> 29) & 0x00000007;
+
+ // Line
+
+ fState.xStart = (reg >> 0) & 0x00000FFF;
+ fState.deltaMajor = (reg >> 12) & 0x0001FFFF;
+ fState.quadrant = (reg >> 29) & 0x00000007;
+ }
+
+ // ==================== GE03R ====================
+
+ if (regNum == kAllRegisters || regNum == 3)
+ {
+ reg = READ_REGISTER (geREG[0x03]);
+
+ // BitBLT
+
+ fState.xSrc = (reg >> 0) & 0x00000FFF;
+ fState.ySrc = (reg >> 16) & 0x00000FFF;
+
+ // Line
+
+ fState.yStart = (reg >> 0) & 0x00000FFF;
+ fState.deltaMinor = (reg >> 12) & 0x0001FFFF;
+ }
+
+ // ==================== GE04R ====================
+
+ if (regNum == kAllRegisters || regNum == 4)
+ {
+ reg = READ_REGISTER (geREG[0x04]);
+
+ fState.destTransColor = (reg >> 0) & 0x0000FFFF;
+ }
+
+ // ==================== GE05R ====================
+
+ if (regNum == kAllRegisters || regNum == 5)
+ {
+ reg = READ_REGISTER (geREG[0x05]);
+
+ fState.clipLeft = (reg >> 0) & 0x000007FF;
+ fState.clipTop = (reg >> 16) & 0x000003FF;
+ }
+
+ // ==================== GE06R ====================
+
+ if (regNum == kAllRegisters || regNum == 6)
+ {
+ reg = READ_REGISTER (geREG[0x06]);
+
+ fState.clipRight = (reg >> 0) & 0x000007FF;
+ fState.clipBottom = (reg >> 16) & 0x000003FF;
+ }
+
+ // ==================== GE07R ====================
+
+ if (regNum == kAllRegisters || regNum == 7)
+ {
+ reg = READ_REGISTER (geREG[0x07]);
+
+ fState.fgColorMonoSrc = (reg >> 0) & 0x0000FFFF;
+ }
+
+ // ==================== GE08R ====================
+
+ if (regNum == kAllRegisters || regNum == 8)
+ {
+ reg = READ_REGISTER (geREG[0x08]);
+
+ fState.bgColorMonoSrc = (reg >> 0) & 0x0000FFFF;
+ }
+
+ // ==================== GE09R ====================
+
+ if (regNum == kAllRegisters || regNum == 9)
+ {
+ reg = READ_REGISTER (geREG[0x09]);
+
+ // Lined Mode
+
+ fState.srcLineStride = (reg >> 0) & 0x000003FF;
+ fState.srcBitOffset = (reg >> 25) & 0x00000007;
+ fState.srcByteOffset = (reg >> 28) & 0x00000007;
+
+ // Packed Mode
+
+ fState.srcLeadingBits = (reg >> 0) & 0x00000007;
+ fState.srcLeadingBytes = (reg >> 3) & 0x00000007;
+ fState.srcNumBytes = (reg >> 6) & 0x000003FF;
+ fState.srcTrailingBits = (reg >> 25) & 0x00000007;
+ fState.srcTrailingBytes = (reg >> 28) & 0x0000000F;
+ }
+
+ // ==================== GE0AR ====================
+
+ if (regNum == kAllRegisters || regNum == 10)
+ {
+ reg = READ_REGISTER (geREG[0x0A]);
+
+ fState.destLineStride = (reg >> 0) & 0x000003FF;
+ fState.monoSrcBitSwap = (reg >> 28) & 0x00000001;
+ fState.rotate90 = (reg >> 29) & 0x00000001;
+ fState.colorDepth = (reg >> 30) & 0x00000003;
+ }
+
+ // ==================== GE0BR ====================
+
+ if (regNum == kAllRegisters || regNum == 11)
+ {
+ reg = READ_REGISTER (geREG[0x0B]);
+
+ fState.baseAddr = (reg >> 0) & 0x000FFFFF;
+ }
+
+ // ==================== GE0CR ====================
+
+ if (regNum == kAllRegisters || regNum == 12)
+ {
+ reg = READ_REGISTER (geREG[0x0C]);
+
+ fState.cmdLineStart = (reg >> 0) & 0x000003FF;
+ fState.cmdLineEnd = (reg >> 12) & 0x000003FF;
+ fState.cmdLineControl = (reg >> 24) & 0x00000001;
+ fState.gc1SwitchControl = (reg >> 26) & 0x00000003;
+ }
+
+ // ==================== GE0FR ====================
+
+ // ==================== GE10R ====================
+
+ if (regNum == kAllRegisters || regNum == 16)
+ {
+ reg = READ_REGISTER (geREG[0x10]);
+
+ fState.monoPattern1 = (reg >> 0) & 0xFFFFFFFF;
+ }
+
+ // ==================== GE11R ====================
+
+ if (regNum == kAllRegisters || regNum == 17)
+ {
+ reg = READ_REGISTER (geREG[0x11]);
+
+ fState.monoPattern2 = (reg >> 0) & 0xFFFFFFFF;
+ }
+
+ // ==================== GE12R ====================
+
+ if (regNum == kAllRegisters || regNum == 18)
+ {
+ reg = READ_REGISTER (geREG[0x12]);
+
+ fState.fgColorMonoPat = (reg >> 0) & 0x0000FFFF;
+ }
+
+ // ==================== GE13R ====================
+
+ if (regNum == kAllRegisters || regNum == 19)
+ {
+ reg = READ_REGISTER (geREG[0x13]);
+
+ fState.bgColorMonoPat = (reg >> 0) & 0x0000FFFF;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvLogGEState
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvLogGEState (void)
+{
+ LogAppendMsg ("========================================");
+
+ // ==================== GE00R ====================
+
+ LogAppendMsg ("GC00R:");
+ LogAppendMsg (" xDoubling %s", this->PrvGetXDoubling () ? "TRUE" : "FALSE");
+ LogAppendMsg (" yDoubling %s", this->PrvGetYDoubling () ? "TRUE" : "FALSE");
+ LogAppendMsg ("");
+
+ // ==================== GE00R ====================
+
+ LogAppendMsg ("GE00R:");
+ LogAppendMsg (" rasterOperation 0x%02X (%s)", fState.rasterOperation, kROPs[fState.rasterOperation]);
+ LogAppendMsg (" commandType %u (%s)", fState.commandType, kCommands[fState.commandType]);
+ LogAppendMsg (" xDirection %u (%s)", fState.xDirection, kDirections[fState.xDirection]);
+ LogAppendMsg (" yDirection %u (%s)", fState.yDirection, kDirections[fState.yDirection]);
+ LogAppendMsg (" systemMemory %u", fState.systemMemory);
+ LogAppendMsg (" monoSource %u", fState.monoSource);
+ LogAppendMsg (" monoPattern %u", fState.monoPattern);
+ LogAppendMsg (" colorTransEnable %u", fState.colorTransEnable);
+ LogAppendMsg (" destTransPolarity %u (Transparent if pixel is %s to test color)", fState.destTransPolarity, fState.destTransPolarity ? "NOT equal" : "equal");
+ LogAppendMsg (" monoTransEnable %u", fState.monoTransEnable);
+ LogAppendMsg (" monoTransPolarity %u", fState.monoTransPolarity);
+ LogAppendMsg (" memToScreen %u (%s)", fState.memToScreen, fState.memToScreen ? "PACKED" : "LINED");
+ LogAppendMsg (" solidSourceColor %u", fState.solidSourceColor);
+ LogAppendMsg (" srcEqualDestStride %u", fState.srcEqualDestStride);
+ LogAppendMsg (" rop2Select %u", fState.rop2Select);
+ LogAppendMsg (" clipEnable %u", fState.clipEnable);
+ LogAppendMsg (" autoExecute %u", fState.autoExecute);
+ LogAppendMsg (" solidPattern %u", fState.solidPattern);
+ LogAppendMsg (" colorTransCmpSrc %u (Compare to %s)", fState.colorTransCmpSrc, fState.colorTransCmpSrc ? "Destination" : "Source");
+ LogAppendMsg ("");
+
+ // ==================== GE01R ====================
+
+ // BitBLT
+
+ if (fState.commandType == kCommandBitBLT)
+ {
+ LogAppendMsg ("GE01R (BitBLT):");
+ LogAppendMsg (" width %u", fState.width);
+ LogAppendMsg (" height %u", fState.height);
+ LogAppendMsg (" xyConversion %u", fState.xyConversion);
+ LogAppendMsg ("");
+ }
+
+ // Line
+
+ if (fState.commandType == kCommandLine)
+ {
+ LogAppendMsg ("GE01R (Line):");
+ LogAppendMsg (" gamma %d", fState.gamma);
+ LogAppendMsg (" majorLength %u", fState.majorLength);
+ LogAppendMsg (" yIsMajor %u", fState.yIsMajor);
+ LogAppendMsg (" drawLastPixel %u", fState.drawLastPixel);
+ LogAppendMsg (" useXY %u", fState.useXY);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE02R ====================
+
+ // BitBLT
+
+ if (fState.commandType == kCommandBitBLT)
+ {
+ LogAppendMsg ("GE02R (BitBLT):");
+ LogAppendMsg (" xDest %u", fState.xDest);
+ LogAppendMsg (" yDest %u", fState.yDest);
+ LogAppendMsg (" monoPatternXOffset %u", fState.monoPatternXOffset);
+ LogAppendMsg (" monoPatternYOffset %u", fState.monoPatternYOffset);
+ LogAppendMsg ("");
+ }
+
+ // Line
+
+ if (fState.commandType == kCommandLine)
+ {
+ LogAppendMsg ("GE02R (Line):");
+ LogAppendMsg (" xStart %u", fState.xStart);
+ LogAppendMsg (" deltaMajor %u", fState.deltaMajor);
+ LogAppendMsg (" quadrant %u (%s)", fState.quadrant, kQuadrantDecode[fState.quadrant].text);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE03R ====================
+
+ // BitBLT
+
+ if (fState.commandType == kCommandBitBLT)
+ {
+ LogAppendMsg ("GE03R (BitBLT):");
+ LogAppendMsg (" xSrc %u", fState.xSrc);
+ LogAppendMsg (" ySrc %u", fState.ySrc);
+ LogAppendMsg ("");
+ }
+
+ // Line
+
+ if (fState.commandType == kCommandLine)
+ {
+ LogAppendMsg ("GE03R (Line):");
+ LogAppendMsg (" yStart %u", fState.yStart);
+ LogAppendMsg (" deltaMinor %u", fState.deltaMinor);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE04R ====================
+
+ if (fState.colorTransEnable)
+ {
+ LogAppendMsg ("GE04R:");
+ LogAppendMsg (" destTransColor 0x%04X", fState.destTransColor);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE05R/GE06R ====================
+
+ if (fState.clipEnable)
+ {
+ LogAppendMsg ("GE05R/GE06R:");
+ LogAppendMsg (" clipLeft %u", fState.clipLeft);
+ LogAppendMsg (" clipTop %u", fState.clipTop);
+ LogAppendMsg (" clipRight %u", fState.clipRight);
+ LogAppendMsg (" clipBottom %u", fState.clipBottom);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE07R/GE08R ====================
+
+ if (fState.monoSource)
+ {
+ LogAppendMsg ("GE07R/GE08R:");
+ LogAppendMsg (" fgColorMonoSrc 0x%04X", fState.fgColorMonoSrc);
+ LogAppendMsg (" bgColorMonoSrc 0x%04X", fState.bgColorMonoSrc);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE09R ====================
+
+ // Lined Mode
+
+ if (fState.memToScreen == 0)
+ {
+ LogAppendMsg ("GE09R (Lined):");
+ LogAppendMsg (" srcLineStride %u", fState.srcLineStride);
+ LogAppendMsg (" srcBitOffset %u", fState.srcBitOffset);
+ LogAppendMsg (" srcByteOffset %u", fState.srcByteOffset);
+ LogAppendMsg ("");
+ }
+
+ // Packed Mode
+
+ if (fState.memToScreen == 1)
+ {
+ LogAppendMsg ("GE09R (Packed):");
+ LogAppendMsg (" srcLeadingBits %u", fState.srcLeadingBits);
+ LogAppendMsg (" srcLeadingBytes %u", fState.srcLeadingBytes);
+ LogAppendMsg (" srcNumBytes %u", fState.srcNumBytes);
+ LogAppendMsg (" srcTrailingBits %u", fState.srcTrailingBits);
+ LogAppendMsg (" srcTrailingBytes %u", fState.srcTrailingBytes);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE0AR ====================
+
+ LogAppendMsg ("GE0AR:");
+ LogAppendMsg (" destLineStride %u", fState.destLineStride);
+ LogAppendMsg (" monoSrcBitSwap %u", fState.monoSrcBitSwap);
+ LogAppendMsg (" rotate90 %u", fState.rotate90);
+ LogAppendMsg (" colorDepth %u", fState.colorDepth);
+ LogAppendMsg ("");
+
+ // ==================== GE0BR ====================
+
+ LogAppendMsg ("GE0AR:");
+ LogAppendMsg (" baseAddr 0x%08X", fState.baseAddr);
+ LogAppendMsg ("");
+
+ // ==================== GE0CR ====================
+
+ LogAppendMsg ("GE0CR:");
+ LogAppendMsg (" cmdLineStart %u", fState.cmdLineStart);
+ LogAppendMsg (" cmdLineEnd %u", fState.cmdLineEnd);
+ LogAppendMsg (" cmdLineControl %u", fState.cmdLineControl);
+ LogAppendMsg (" gc1SwitchControl %u", fState.gc1SwitchControl);
+ LogAppendMsg ("");
+
+ // ==================== GE0FR ====================
+
+ // ==================== GE10R/GE11R ====================
+
+ if (fState.monoPattern)
+ {
+ LogAppendMsg ("GE10R/GE11R:");
+ LogAppendMsg (" monoPattern1 0x%08X", fState.monoPattern1);
+ LogAppendMsg (" monoPattern2 0x%08X", fState.monoPattern2);
+ LogAppendMsg ("");
+ }
+
+ // ==================== GE12R/GE13R ====================
+
+ if (fState.monoPattern)
+ {
+ LogAppendMsg ("GE12R/GE13R:");
+ LogAppendMsg (" fgColorMonoPat 0x%04X", fState.fgColorMonoPat);
+ LogAppendMsg (" bgColorMonoPat 0x%04X", fState.bgColorMonoPat);
+ }
+
+ LogAppendMsg ("========================================");
+
+ if (fState.commandType == kCommandBitBLT)
+ {
+ EmAssert (!(
+ (fState.width == 25) &&
+ (fState.height == 19) &&
+ (fState.xDest == 0) &&
+ (fState.yDest == 320) &&
+ (fState.xSrc == 0) &&
+ (fState.ySrc == 320) &&
+ 1));
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDoCommand
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDoCommand (void)
+{
+ switch (fState.commandType)
+ {
+ case kCommandNOP:
+ // NOP command -- do nothing
+ break;
+
+ case kCommandBitBLT:
+ this->PrvDoBitBLT ();
+ break;
+
+ case kCommandLine:
+ this->PrvDoLine ();
+ break;
+
+ default:
+ this->PrvIllegalCommand ();
+ break;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDoBitBLT
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDoBitBLT (void)
+{
+ this->PrvIncBlitterInit ();
+ this->PrvIncBlitterRun ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDoLine
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDoLine (void)
+{
+ PRINTF_LINE (" PrvDoLine: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+
+#if LOG_LINE
+ this->PrvLogGEState ();
+#endif
+
+ // Draw a line using the information in the GE registers,
+ // using a Bresenham line drawing algorithm. For a good
+ // tutorial on this algorithm, see:
+ //
+ // <http://www.gamedev.net/reference/articles/article1275.asp>
+
+ // Figure out our starting and ending points. The starting
+ // point is in the registers. The ending point needs to
+ // be determined by looking at deltaMajor, deltaMinor, the
+ // flag that says if the major is the X or Y access, and the
+ // X and Y directions.
+
+ uint16 yIsMajor; // 0 = x is major, 1 = y is major
+ uint16 xDirection; // 0 = x is positive, 1 = x is negative
+ uint16 yDirection; // 0 = y is positive, 1 = y is negative
+
+ if (fState.useXY)
+ {
+ yIsMajor = fState.yIsMajor;
+ xDirection = fState.xDirection;
+ yDirection = fState.yDirection;
+ }
+ else
+ {
+ yIsMajor = kQuadrantDecode[fState.quadrant].yIsMajor;
+ xDirection = kQuadrantDecode[fState.quadrant].xDirection;
+ yDirection = kQuadrantDecode[fState.quadrant].yDirection;
+ }
+
+ PRINTF_LINE (" yIsMajor: %d", yIsMajor);
+ PRINTF_LINE (" xDirection: %d", xDirection);
+ PRINTF_LINE (" yDirection: %d", yDirection);
+
+ // Get the starting x,y position. We'll be updating these
+ // variables as we draw the line.
+
+ uint16 x = fState.xStart;
+ uint16 y = fState.yStart;
+
+ PRINTF_LINE (" x: %d", x);
+ PRINTF_LINE (" y: %d", y);
+
+ // Get the direction in which the x,y coordinates needs to
+ // be updated.
+
+ int xAdjust = xDirection ? -1 : 1;
+ int yAdjust = yDirection ? -1 : 1;
+
+ PRINTF_LINE (" xAdjust: %d", xAdjust);
+ PRINTF_LINE (" yAdjust: %d", yAdjust);
+
+ // Based on which axis is the major axis, get pointers to
+ // the major and minor coordinates and the values that will
+ // be used to update them.
+
+ uint16* major;
+ uint16* minor;
+
+ int majorAdjust;
+ int minorAdjust;
+
+ if (yIsMajor)
+ {
+ major = &y;
+ minor = &x;
+
+ majorAdjust = yAdjust;
+ minorAdjust = xAdjust;
+ }
+ else
+ {
+ major = &x;
+ minor = &y;
+
+ majorAdjust = xAdjust;
+ minorAdjust = yAdjust;
+ }
+
+ PRINTF_LINE (" major: %d", *major);
+ PRINTF_LINE (" minor: %d", *minor);
+
+ PRINTF_LINE (" majorAdjust: %d", majorAdjust);
+ PRINTF_LINE (" minorAdjust: %d", minorAdjust);
+
+ PRINTF_LINE (" gamma: %d", fState.gamma);
+ PRINTF_LINE (" majorLength: %d", fState.majorLength);
+ PRINTF_LINE (" deltaMajor: %d", fState.deltaMajor);
+
+ PRINTF_LINE (" ...................");
+
+ // Initialize "error" (which is used to determine when we
+ // need to increment the minor axis coordinate) and "count"
+ // (which is used to iterate over the major axis).
+
+ int error = 0;
+ uint16 count = 0;
+
+ // Iterate over all the points along the major axis.
+
+ while (count < fState.majorLength)
+ {
+ PRINTF_LINE (" count: %d", count);
+ PRINTF_LINE (" major: %d", *major);
+ PRINTF_LINE (" minor: %d", *minor);
+
+ // Plot a point.
+
+ uint16 src = 0; // Dummy value. The ROP had better not be one that makes use of a source pixel!
+ uint16 pen = fState.fgColorMonoPat;
+ uint16 dest = this->PrvGetPixel (x, y);
+
+ uint16 output = this->PrvAdjustPixel (pen, src, dest, fState.rasterOperation);
+
+ this->PrvSetPixel (output, x, y);
+
+ // Update the major axis coordinate and adjust the error factor.
+
+ *major += majorAdjust;
+ error += 2 * fState.deltaMinor;
+
+ // See if it's time to update the minor access coordinate.
+
+ if (error > fState.deltaMajor)
+ {
+ // Update the minor axis coordinate and adjust the error factor.
+
+ *minor += minorAdjust;
+ error -= 2 * fState.deltaMajor;
+ }
+
+ // Keep track of how many points we've plotted.
+
+ count += 1;
+ }
+
+ PRINTF_LINE (" ...................");
+
+ // If we need to draw the last pixel, then do it.
+
+ if (fState.drawLastPixel)
+ {
+ PRINTF_LINE (" count: %d", count);
+ PRINTF_LINE (" major: %d", *major);
+ PRINTF_LINE (" minor: %d", *minor);
+
+ PRINTF_LINE (" ...................");
+
+ uint16 src = 0; // Dummy value. The ROP had better not be one that makes use of a source pixel!
+ uint16 pen = fState.fgColorMonoPat;
+ uint16 dest = this->PrvGetPixel (x, y);
+
+ uint16 output = this->PrvAdjustPixel (pen, src, dest, fState.rasterOperation);
+
+ this->PrvSetPixel (output, x, y);
+ }
+
+ PRINTF_LINE (" PrvDoLine: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvIllegalCommand
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvIllegalCommand (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcFifoFilledSlots
+// ---------------------------------------------------------------------------
+
+int EmRegsMediaQ11xx::PrvSrcFifoFilledSlots (void)
+{
+ return fSourceFifo.size () / 2;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvGetSrcFifoSlot
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvGetSrcFifoSlot (uint32& a, uint32& b)
+{
+ a = fSourceFifo[0];
+ fSourceFifo.erase (fSourceFifo.begin ());
+
+ b = fSourceFifo[0];
+ fSourceFifo.erase (fSourceFifo.begin ());
+}
+
+
+// ---------------------------------------------------------------------------
+// Drawing Functions
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvAdjustPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvAdjustPixel (uint16 pen, uint16 dest, uint8 rOpCode)
+{
+ uint16 result;
+
+ /*
+ (From MSDN)
+
+ Each raster-operation code represents a Boolean operation in which the
+ values of the pixels in the selected pen and the destination bitmap are
+ combined. The following are the two operands used in these operations.
+
+ Operand Meaning
+ ------- -------
+ P Selected pen
+ D Destination bitmap
+
+ The Boolean operators used in these operations follow.
+
+ Operator Meaning
+ -------- -------
+ a Bitwise AND
+ n Bitwise NOT (inverse)
+ o Bitwise OR
+ x Bitwise exclusive OR (XOR)
+
+ All Boolean operations are presented in reverse Polish notation. For
+ example, the following operation replaces the values of the pixels in
+ the destination bitmap with a combination of the pixel values of the
+ pen and the selected brush:
+
+ DPo
+
+ Each raster-operation code is a 32-bit integer whose high-order word
+ is a Boolean operation index and whose low-order word is the operation
+ code. The 16-bit operation index is a zero-extended 8-bit value that
+ represents all possible outcomes resulting from the Boolean operation
+ on two parameters (in this case, the pen and destination values). For
+ example, the operation indexes for the DPo and DPan operations are shown
+ in the following list.
+
+ P D DPo Dpan
+ 0 0 0 1
+ 0 1 1 1
+ 1 0 1 1
+ 1 1 1 0
+
+ The following list outlines the drawing modes and the Boolean operations
+ that they represent.
+
+ Raster operation Boolean operation
+ ---------------- -----------------
+ R2_BLACK 0
+ R2_COPYPEN P
+ R2_MASKNOTPEN DPna
+ R2_MASKPEN DPa
+ R2_MASKPENNOT PDna
+ R2_MERGENOTPEN DPno
+ R2_MERGEPEN DPo
+ R2_MERGEPENNOT PDno
+ R2_NOP D
+ R2_NOT Dn
+ R2_NOTCOPYPEN Pn
+ R2_NOTMASKPEN DPan
+ R2_NOTMERGEPEN DPon
+ R2_NOTXORPEN DPxn
+ R2_WHITE 1
+ R2_XORPEN DPx
+ */
+
+ switch (rOpCode)
+ {
+ case 0: /* 0 */
+ result = 0;
+ break;
+
+ case 1: /* DPon */
+ result = ~(dest | pen);
+ break;
+
+ case 2: /* DPna */
+ result = dest & ~pen;
+ break;
+
+ case 3: /* PN */
+ result = ~pen;
+ break;
+
+ case 4: /* PDna */
+ result = pen & ~dest;
+ break;
+
+ case 5: /* Dn */
+ result = ~dest;
+ break;
+
+ case 6: /* DPx */
+ result = dest ^ pen;
+ break;
+
+ case 7: /* DPan */
+ result = ~(dest & pen);
+ break;
+
+ case 8: /* DPa */
+ result = dest & pen;
+ break;
+
+ case 9: /* DPxn */
+ result = ~(dest ^ pen);
+ break;
+
+ case 10: /* D */
+ result = dest;
+ break;
+
+ case 11: /* DPno */
+ result = dest | ~pen;
+ break;
+
+ case 12: /* P */
+ result = pen;
+ break;
+
+ case 13: /* PDno */
+ result = pen & ~dest;
+ break;
+
+ case 14: /* DPo */
+ result = dest | pen;
+ break;
+
+ case 15: /* 1 */
+ result = ~0;
+ break;
+
+ default:
+ EmAssert (false);
+ result = 0;
+ break;
+ }
+
+#ifdef _DEBUG
+ // Double-check the special cases with the generalized code.
+
+ {
+ const int kNumBits = 8 * sizeof (result);
+
+ uint16 result2 = 0;
+
+ for (int bitNumber = 0; bitNumber < kNumBits; ++bitNumber)
+ {
+ uint8 index = (((pen >> bitNumber) & 1) << 1) |
+ (((dest >> bitNumber) & 1) << 0);
+
+ result2 |= (((rOpCode >> index) & 1) << bitNumber);
+ }
+
+ EmAssert (result == result2);
+ }
+#endif
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvAdjustPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvAdjustPixel (uint16 pattern, uint16 src, uint16 dest, uint8 rOpCode)
+{
+ uint16 result;
+
+ /*
+ (From MSDN)
+
+ Each raster-operation code represents a Boolean operation in which
+ the values of the pixels in the source, the selected brush, and the
+ destination are combined. The following are the three operands used
+ in these operations.
+
+ Operand Meaning
+ ------- -------
+ D Destination bitmap
+ P Selected brush (also called pattern)
+ S Source bitmap
+
+ Boolean operators used in these operations follow.
+
+ Operator Meaning
+ -------- -------
+ a Bitwise AND
+ n Bitwise NOT (inverse)
+ o Bitwise OR
+ x Bitwise exclusive OR (XOR)
+
+ ---------------------------------------------------------------------
+
+ (From Keith)
+
+ Here's another way to think about it: take the pattern, source, and
+ destination, and consider each value one bit at a time. The three
+ bits from the three values can form eight combinations. The raster
+ opcode is a bitfield containing the desired output from each of the
+ combinations. Thus:
+
+ P S D O (output)
+ --- --- --- ---
+ 0 0 0 b0
+ 0 0 1 b1
+ 0 1 0 b2
+ 0 1 1 b3
+ 1 0 0 b4
+ 1 0 1 b5
+ 1 1 0 b6
+ 1 1 1 b7
+
+ The output is the byte <b7><b6><b5><b4><b3><b2><b1><b0>. And this
+ output value is what becomes the raster opcode. Thus, if the raster
+ opcode is, for example, 0xCC, the table would be:
+
+ P S D O (output)
+ --- --- --- ---
+ 0 0 0 0
+ 0 0 1 0
+ 0 1 0 1
+ 0 1 1 1
+ 1 0 0 0
+ 1 0 1 0
+ 1 1 0 1
+ 1 1 1 1
+
+ So, the we look at three bits from the source and they're all zero,
+ then the output is zero. If they're all one, then the output is
+ one. If the pattern is one and the source and destination are zero,
+ then the output is zero. Overall,
+
+ Output[x] = ROP[P[x],S[x],D[x]]
+
+ where "x" is 0..7, and "P[x],S[x],D[x]" is a bitfield composed of
+ the given bits.
+
+ We will use this generalization for the default case. However, for
+ the most common raster ops, we can manipulate all bits of all the
+ incumbant values simultaneously. We special-case those opcodes.
+ */
+
+ switch (rOpCode)
+ {
+ case 0x00: // 00000042 0 BLACKNESS
+ result = 0;
+ break;
+
+ // case 0x01: // 00010289 DPSoon –
+ // case 0x02: // 00020C89 DPSona –
+ // case 0x03: // 000300AA PSon –
+ // case 0x04: // 00040C88 SDPona –
+ // case 0x05: // 000500A9 DPon –
+ // case 0x06: // 00060865 PDSxnon –
+ // case 0x07: // 000702C5 PDSaon –
+ // case 0x08: // 00080F08 SDPnaa –
+ // case 0x09: // 00090245 PDSxon –
+ case 0x0A: // 000A0329 DPna –
+ result = dest & ~pattern;
+ break;
+
+ // case 0x0B: // 000B0B2A PSDnaon –
+ // case 0x0C: // 000C0324 SPna –
+ // case 0x0D: // 000D0B25 PDSnaon –
+ // case 0x0E: // 000E08A5 PDSonon –
+ case 0x0F: // 000F0001 Pn –
+ result = ~pattern;
+ break;
+
+ // case 0x10: // 00100C85 PDSona –
+ case 0x11: // 001100A6 DSon NOTSRCERASE
+ result = ~(dest | src);
+ break;
+
+ // case 0x12: // 00120868 SDPxnon –
+ // case 0x13: // 001302C8 SDPaon –
+ // case 0x14: // 00140869 DPSxnon –
+ // case 0x15: // 001502C9 DPSaon –
+ // case 0x16: // 00165CCA PSDPSanaxx –
+ // case 0x17: // 00171D54 SSPxDSxaxn –
+ // case 0x18: // 00180D59 SPxPDxa –
+ // case 0x19: // 00191CC8 SDPSanaxn –
+ // case 0x1A: // 001A06C5 PDSPaox –
+ // case 0x1B: // 001B0768 SDPSxaxn –
+ // case 0x1C: // 001C06CA PSDPaox –
+ // case 0x1D: // 001D0766 DSPDxaxn –
+ // case 0x1E: // 001E01A5 PDSox –
+ // case 0x1F: // 001F0385 PDSoan –
+ // case 0x20: // 00200F09 DPSnaa –
+ // case 0x21: // 00210248 SDPxon –
+ case 0x22: // 00220326 DSna –
+ result = dest & ~src;
+ break;
+
+ // case 0x23: // 00230B24 SPDnaon –
+ // case 0x24: // 00240D55 SPxDSxa –
+ // case 0x25: // 00251CC5 PDSPanaxn –
+ // case 0x26: // 002606C8 SDPSaox –
+ // case 0x27: // 00271868 SDPSxnox –
+ // case 0x28: // 00280369 DPSxa –
+ // case 0x29: // 002916CA PSDPSaoxxn –
+ // case 0x2A: // 002A0CC9 DPSana –
+ // case 0x2B: // 002B1D58 SSPxPDxaxn –
+ // case 0x2C: // 002C0784 SPDSoax –
+ // case 0x2D: // 002D060A PSDnox –
+ // case 0x2E: // 002E064A PSDPxox –
+ // case 0x2F: // 002F0E2A PSDnoan –
+ // case 0x30: // 0030032A PSna –
+ // case 0x31: // 00310B28 SDPnaon –
+ // case 0x32: // 00320688 SDPSoox –
+ case 0x33: // 00330008 Sn NOTSRCCOPY
+ result = ~src;
+ break;
+
+ // case 0x34: // 003406C4 SPDSaox –
+ // case 0x35: // 00351864 SPDSxnox –
+ // case 0x36: // 003601A8 SDPox –
+ // case 0x37: // 00370388 SDPoan –
+ // case 0x38: // 0038078A PSDPoax –
+ // case 0x39: // 00390604 SPDnox –
+ // case 0x3A: // 003A0644 SPDSxox –
+ // case 0x3B: // 003B0E24 SPDnoan –
+ // case 0x3C: // 003C004A PSx –
+ // case 0x3D: // 003D18A4 SPDSonox –
+ // case 0x3E: // 003E1B24 SPDSnaox –
+ // case 0x3F: // 003F00EA PSan –
+ // case 0x40: // 00400F0A PSDnaa –
+ // case 0x41: // 00410249 DPSxon –
+ // case 0x42: // 00420D5D SDxPDxa –
+ // case 0x43: // 00431CC4 SPDSanaxn –
+ case 0x44: // 00440328 SDna SRCERASE
+ result = src & ~dest;
+ break;
+
+ // case 0x45: // 00450B29 DPSnaon –
+ // case 0x46: // 004606C6 DSPDaox –
+ // case 0x47: // 0047076A PSDPxaxn –
+ // case 0x48: // 00480368 SDPxa –
+ // case 0x49: // 004916C5 PDSPDaoxxn –
+ // case 0x4A: // 004A0789 DPSDoax –
+ // case 0x4B: // 004B0605 PDSnox –
+ // case 0x4C: // 004C0CC8 SDPana –
+ // case 0x4D: // 004D1954 SSPxDSxoxn –
+ // case 0x4E: // 004E0645 PDSPxox –
+ // case 0x4F: // 004F0E25 PDSnoan –
+ // case 0x50: // 00500325 PDna –
+ // case 0x51: // 00510B26 DSPnaon –
+ // case 0x52: // 005206C9 DPSDaox –
+ // case 0x53: // 00530764 SPDSxaxn –
+ // case 0x54: // 005408A9 DPSonon –
+ case 0x55: // 00550009 Dn DSTINVERT
+ result = ~dest;
+ break;
+
+ // case 0x56: // 005601A9 DPSox –
+ // case 0x57: // 00570389 DPSoan –
+ // case 0x58: // 00580785 PDSPoax –
+ // case 0x59: // 00590609 DPSnox –
+ case 0x5A: // 005A0049 DPx PATINVERT
+ result = dest ^ pattern;
+ break;
+
+ // case 0x5B: // 005B18A9 DPSDonox –
+ // case 0x5C: // 005C0649 DPSDxox –
+ // case 0x5D: // 005D0E29 DPSnoan –
+ // case 0x5E: // 005E1B29 DPSDnaox –
+ case 0x5F: // 005F00E9 DPan –
+ result = ~(dest & pattern);
+ break;
+
+ // case 0x60: // 00600365 PDSxa –
+ // case 0x61: // 006116C6 DSPDSaoxxn –
+ // case 0x62: // 00620786 DSPDoax –
+ // case 0x63: // 00630608 SDPnox –
+ // case 0x64: // 00640788 SDPSoax –
+ // case 0x65: // 00650606 DSPnox –
+ case 0x66: // 00660046 DSx SRCINVERT
+ result = dest ^ src;
+ break;
+
+ // case 0x67: // 006718A8 SDPSonox –
+ // case 0x68: // 006858A6 DSPDSonoxxn –
+ // case 0x69: // 00690145 PDSxxn –
+ // case 0x6A: // 006A01E9 DPSax –
+ // case 0x6B: // 006B178A PSDPSoaxxn –
+ // case 0x6C: // 006C01E8 SDPax –
+ // case 0x6D: // 006D1785 PDSPDoaxxn –
+ // case 0x6E: // 006E1E28 SDPSnoax –
+ // case 0x6F: // 006F0C65 PDSxnan –
+ // case 0x70: // 00700CC5 PDSana –
+ // case 0x71: // 00711D5C SSDxPDxaxn –
+ // case 0x72: // 00720648 SDPSxox –
+ // case 0x73: // 00730E28 SDPnoan –
+ // case 0x74: // 00740646 DSPDxox –
+ // case 0x75: // 00750E26 DSPnoan –
+ // case 0x76: // 00761B28 SDPSnaox –
+ case 0x77: // 007700E6 DSan –
+ result = ~(dest & src);
+ break;
+
+ // case 0x78: // 007801E5 PDSax –
+ // case 0x79: // 00791786 DSPDSoaxxn –
+ // case 0x7A: // 007A1E29 DPSDnoax –
+ // case 0x7B: // 007B0C68 SDPxnan –
+ // case 0x7C: // 007C1E24 SPDSnoax –
+ // case 0x7D: // 007D0C69 DPSxnan –
+ // case 0x7E: // 007E0955 SPxDSxo –
+ // case 0x7F: // 007F03C9 DPSaan –
+ // case 0x80: // 008003E9 DPSaa –
+ // case 0x81: // 00810975 SPxDSxon –
+ // case 0x82: // 00820C49 DPSxna –
+ // case 0x83: // 00831E04 SPDSnoaxn –
+ // case 0x84: // 00840C48 SDPxna –
+ // case 0x85: // 00851E05 PDSPnoaxn –
+ // case 0x86: // 008617A6 DSPDSoaxx –
+ // case 0x87: // 008701C5 PDSaxn –
+ case 0x88: // 008800C6 DSa SRCAND
+ result = dest & src;
+ break;
+
+ // case 0x89: // 00891B08 SDPSnaoxn –
+ // case 0x8A: // 008A0E06 DSPnoa –
+ // case 0x8B: // 008B0666 DSPDxoxn –
+ // case 0x8C: // 008C0E08 SDPnoa –
+ // case 0x8D: // 008D0668 SDPSxoxn –
+ // case 0x8E: // 008E1D7C SSDxPDxax –
+ // case 0x8F: // 008F0CE5 PDSanan –
+ // case 0x90: // 00900C45 PDSxna –
+ // case 0x91: // 00911E08 SDPSnoaxn –
+ // case 0x92: // 009217A9 DPSDPoaxx –
+ // case 0x93: // 009301C4 SPDaxn –
+ // case 0x94: // 009417AA PSDPSoaxx –
+ // case 0x95: // 009501C9 DPSaxn –
+ // case 0x96: // 00960169 DPSxx –
+ // case 0x97: // 0097588A PSDPSonoxx –
+ // case 0x98: // 00981888 SDPSonoxn –
+ case 0x99: // 00990066 DSxn –
+ result = ~(dest ^ src);
+ break;
+
+ // case 0x9A: // 009A0709 DPSnax –
+ // case 0x9B: // 009B07A8 SDPSoaxn –
+ // case 0x9C: // 009C0704 SPDnax –
+ // case 0x9D: // 009D07A6 DSPDoaxn –
+ // case 0x9E: // 009E16E6 DSPDSaoxx –
+ // case 0x9F: // 009F0345 PDSxan –
+ case 0xA0: // 00A000C9 DPa –
+ result = dest & pattern;
+ break;
+
+ // case 0xA1: // 00A11B05 PDSPnaoxn –
+ // case 0xA2: // 00A20E09 DPSnoa –
+ // case 0xA3: // 00A30669 DPSDxoxn –
+ // case 0xA4: // 00A41885 PDSPonoxn –
+ case 0xA5: // 00A50065 PDxn –
+ result = ~(pattern ^ dest);
+ break;
+
+ // case 0xA6: // 00A60706 DSPnax –
+ // case 0xA7: // 00A707A5 PDSPoaxn –
+ // case 0xA8: // 00A803A9 DPSoa –
+ // case 0xA9: // 00A90189 DPSoxn –
+ // case 0xAA: // 00AA0029 D –
+ // case 0xAB: // 00AB0889 DPSono –
+ // case 0xAC: // 00AC0744 SPDSxax –
+ // case 0xAD: // 00AD06E9 DPSDaoxn –
+ // case 0xAE: // 00AE0B06 DSPnao –
+ case 0xAF: // 00AF0229 DPno –
+ result = dest | ~pattern;
+ break;
+
+ // case 0xB0: // 00B00E05 PDSnoa –
+ // case 0xB1: // 00B10665 PDSPxoxn –
+ // case 0xB2: // 00B21974 SSPxDSxox –
+ // case 0xB3: // 00B30CE8 SDPanan –
+ // case 0xB4: // 00B4070A PSDnax –
+ // case 0xB5: // 00B507A9 DPSDoaxn –
+ // case 0xB6: // 00B616E9 DPSDPaoxx –
+ // case 0xB7: // 00B70348 SDPxan –
+ // case 0xB8: // 00B8074A PSDPxax –
+ // case 0xB9: // 00B906E6 DSPDaoxn –
+ // case 0xBA: // 00BA0B09 DPSnao –
+ case 0xBB: // 00BB0226 DSno MERGEPAINT
+ result = dest | ~src;
+ break;
+
+ // case 0xBC: // 00BC1CE4 SPDSanax –
+ // case 0xBD: // 00BD0D7D SDxPDxan –
+ // case 0xBE: // 00BE0269 DPSxo –
+ // case 0xBF: // 00BF08C9 DPSano –
+ case 0xC0: // 00C000CA PSa MERGECOPY
+ result = pattern & src;
+ break;
+
+ // case 0xC1: // 00C11B04 SPDSnaoxn –
+ // case 0xC2: // 00C21884 SPDSonoxn –
+ // case 0xC3: // 00C3006A PSxn –
+ // case 0xC4: // 00C40E04 SPDnoa –
+ // case 0xC5: // 00C50664 SPDSxoxn –
+ // case 0xC6: // 00C60708 SDPnax –
+ // case 0xC7: // 00C707AA PSDPoaxn –
+ // case 0xC8: // 00C803A8 SDPoa –
+ // case 0xC9: // 00C90184 SPDoxn –
+ // case 0xCA: // 00CA0749 DPSDxax –
+ // case 0xCB: // 00CB06E4 SPDSaoxn –
+ case 0xCC: // 00CC0020 S SRCCOPY
+ result = src;
+ break;
+
+ // case 0xCD: // 00CD0888 SDPono –
+ // case 0xCE: // 00CE0B08 SDPnao –
+ // case 0xCF: // 00CF0224 SPno –
+ // case 0xD0: // 00D00E0A PSDnoa –
+ // case 0xD1: // 00D1066A PSDPxoxn –
+ // case 0xD2: // 00D20705 PDSnax –
+ // case 0xD3: // 00D307A4 SPDSoaxn –
+ // case 0xD4: // 00D41D78 SSPxPDxax –
+ // case 0xD5: // 00D50CE9 DPSanan –
+ // case 0xD6: // 00D616EA PSDPSaoxx –
+ // case 0xD7: // 00D70349 DPSxan –
+ // case 0xD8: // 00D80745 PDSPxax –
+ // case 0xD9: // 00D906E8 SDPSaoxn –
+ // case 0xDA: // 00DA1CE9 DPSDanax –
+ // case 0xDB: // 00DB0D75 SPxDSxan –
+ // case 0xDC: // 00DC0B04 SPDnao –
+ // case 0xDD: // 00DD0228 SDno –
+ // case 0xDE: // 00DE0268 SDPxo –
+ // case 0xDF: // 00DF08C8 SDPano –
+ // case 0xE0: // 00E003A5 PDSoa –
+ // case 0xE1: // 00E10185 PDSoxn –
+ // case 0xE2: // 00E20746 DSPDxax –
+ // case 0xE3: // 00E306EA PSDPaoxn –
+ // case 0xE4: // 00E40748 SDPSxax –
+ // case 0xE5: // 00E506E5 PDSPaoxn –
+ // case 0xE6: // 00E61CE8 SDPSanax –
+ // case 0xE7: // 00E70D79 SPxPDxan –
+ // case 0xE8: // 00E81D74 SSPxDSxax –
+ // case 0xE9: // 00E95CE6 DSPDSanaxxn –
+ // case 0xEA: // 00EA02E9 DPSao –
+ // case 0xEB: // 00EB0849 DPSxno –
+ // case 0xEC: // 00EC02E8 SDPao –
+ // case 0xED: // 00ED0848 SDPxno –
+ case 0xEE: // 00EE0086 DSo SRCPAINT
+ result = dest | src;
+ break;
+
+ // case 0xEF: // 00EF0A08 SDPnoo –
+ case 0xF0: // 00F00021 P PATCOPY
+ result = pattern;
+ break;
+
+ // case 0xF1: // 00F10885 PDSono –
+ // case 0xF2: // 00F20B05 PDSnao –
+ // case 0xF3: // 00F3022A PSno –
+ // case 0xF4: // 00F40B0A PSDnao –
+ // case 0xF5: // 00F50225 PDno –
+ // case 0xF6: // 00F60265 PDSxo –
+ // case 0xF7: // 00F708C5 PDSano –
+ // case 0xF8: // 00F802E5 PDSao –
+ // case 0xF9: // 00F90845 PDSxno –
+ case 0xFA: // 00FA0089 DPo –
+ result = dest | pattern;
+ break;
+
+ case 0xFB: // 00FB0A09 DPSnoo PATPAINT
+ result = dest | (pattern | ~src);
+ break;
+
+ // case 0xFC: // 00FC008A PSo –
+ // case 0xFD: // 00FD0A0A PSDnoo –
+ // case 0xFE: // 00FE02A9 DPSoo –
+ case 0xFF: // 00FF0062 1 WHITENESS
+ result = ~0;
+ break;
+
+ default:
+ {
+ const int kNumBits = 8 * sizeof (result);
+
+ result = 0;
+
+ for (int bitNumber = 0; bitNumber < kNumBits; ++bitNumber)
+ {
+ uint8 index = (((pattern >> bitNumber) & 1) << 2) |
+ (((src >> bitNumber) & 1) << 1) |
+ (((dest >> bitNumber) & 1) << 0);
+
+ result |= (((rOpCode >> index) & 1) << bitNumber);
+ }
+ }
+ break;
+ }
+
+#ifdef _DEBUG
+ // Double-check the special cases with the generalized code.
+
+ {
+ const int kNumBits = 8 * sizeof (result);
+
+ uint16 result2 = 0;
+
+ for (int bitNumber = 0; bitNumber < kNumBits; ++bitNumber)
+ {
+ uint8 index = (((pattern >> bitNumber) & 1) << 2) |
+ (((src >> bitNumber) & 1) << 1) |
+ (((dest >> bitNumber) & 1) << 0);
+
+ result2 |= (((rOpCode >> index) & 1) << bitNumber);
+ }
+
+ EmAssert (result == result2);
+ }
+#endif
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSetPixel
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvSetPixel (uint16 pixel, uint16 x, uint16 y)
+{
+ emuptr pixelLocation = this->PrvGetPixelLocation (x, y);
+
+ switch (fState.colorDepth)
+ {
+ case kColorDepth8:
+ EmMemPut8 (pixelLocation, pixel);
+ break;
+
+ case kColorDepth16:
+ EmAssert (::IsEven (pixelLocation));
+ EmMemPut16 (pixelLocation, pixel);
+ break;
+
+ default:
+ EmAssert (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvGetPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvGetPixel (uint16 x, uint16 y)
+{
+ uint16 result;
+ emuptr pixelLocation = this->PrvGetPixelLocation (x, y);
+
+ switch (fState.colorDepth)
+ {
+ case kColorDepth8:
+ result = EmMemGet8 (pixelLocation);
+ break;
+
+ case kColorDepth16:
+ EmAssert (::IsEven (pixelLocation));
+ result = EmMemGet16 (pixelLocation);
+ break;
+
+ default:
+ EmAssert (false);
+ result = 0;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvGetPixelLocation
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsMediaQ11xx::PrvGetPixelLocation (uint16 x, uint16 y)
+{
+ int bytesPerPixel;
+
+ switch (fState.colorDepth)
+ {
+ case kColorDepth8:
+ bytesPerPixel = 1;
+ break;
+
+ case kColorDepth16:
+ bytesPerPixel = 2;
+ break;
+
+ default:
+ EmAssert (false);
+ return 0;
+ }
+
+ if (fState.rotate90)
+ {
+ // Rotate 90 deg clockwise.
+
+ /*
+ -----x y--
+ |+--------------------+|
+ || ||
+ y| 1 ||
+ | 2 |x
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +--------------------+
+
+ Point 1 is the original point.
+ Point 2 is the rotated point.
+ */
+
+ int16 newX = fState.destLineStride * bytesPerPixel - y;
+ int16 newY = x;
+
+ x = newX;
+ y = newY;
+ }
+
+ emuptr frameBuffer = this->PrvGetVideoBase () + fState.baseAddr;
+ emuptr scanLine = frameBuffer + (y * fState.destLineStride);
+ emuptr scanByte = scanLine + (x * bytesPerPixel);
+
+ EmAssert (scanByte >= fBaseVideoAddr);
+ EmAssert (scanByte + bytesPerPixel <= fBaseVideoAddr + MMIO_OFFSET);
+
+ return scanByte;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvIncBlitterInit
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvIncBlitterInit (void)
+{
+ PRINTF_BLIT (" PrvIncBlitterInit: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+
+#if LOG_BLIT
+ this->PrvLogGEState ();
+#endif
+
+ fBlitInProgress = true;
+
+ fCurXOffset = 0;
+ fCurYOffset = 0;
+
+ fUsesPattern = this->PrvUsesPattern ();
+ fUsesSource = this->PrvUsesSource ();
+
+ if (!fUsesPattern)
+ PRINTF_BLIT (" PrvIncBlitterInit: pattern not used...");
+
+ if (!fUsesSource)
+ PRINTF_BLIT (" PrvIncBlitterInit: source data not used...");
+
+ if (fState.monoSource)
+ {
+ if (fState.monoTransEnable)
+ {
+ if (fState.monoTransPolarity)
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Foreground is transparent...");
+ }
+ else
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Background is transparent...");
+ }
+ }
+ }
+ else if (fState.colorTransEnable)
+ {
+ if (fState.destTransPolarity == 0)
+ {
+ if (fState.colorTransCmpSrc == 0)
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Treat all destTransColor pixels in the source as transparent...");
+ }
+ else
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Leave all destTransColor pixels in the destination alone...");
+ }
+ }
+ else
+ {
+ if (fState.colorTransCmpSrc == 0)
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Transfer only destTransColor pixels from the source to the destination...");
+ }
+ else
+ {
+ PRINTF_BLIT (" PrvIncBlitterInit: Update only destTransColor pixels in the destination with source pixels...");
+ }
+ }
+ }
+
+ this->PrvPatternPipeInit ();
+ this->PrvSrcPipeInit ();
+ this->PrvDestPipeInit ();
+
+ PRINTF_BLIT (" PrvIncBlitterInit: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvIncBlitterRun
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvIncBlitterRun (void)
+{
+ if (!fBlitInProgress)
+ return;
+
+ static long counter = 0;
+
+ PRINTF_BLIT (" PrvIncBlitterRun: **************************************************");
+ PRINTF_BLIT (" PrvIncBlitterRun: counter: %u", ++counter);
+ PRINTF_BLIT (" PrvIncBlitterRun: **************************************************");
+
+ while (fBlitInProgress)
+ {
+ Bool stalled;
+
+ // Get the relevent pixel values.
+
+ uint16 source = this->PrvSrcPipeNextPixel (stalled);
+
+ // If the source FIFO stalled (no more input data for now),
+ // return false, indicating that the BLT operation is still
+ // in progress.
+
+ if (stalled)
+ {
+ PRINTF_BLIT (" PrvIncBlitterRun: stalled...");
+ break;
+ }
+
+ // Continue getting more pixel values.
+
+ uint16 pattern = this->PrvPatternPipeNextPixel ();
+ uint16 dest = this->PrvDestPipeNextPixel ();
+ uint16 output = this->PrvAdjustPixel (pattern, source, dest,
+ fState.rasterOperation);
+
+ PRINTF_BLIT (" PrvIncBlitterRun: pattern: 0x%04X", pattern);
+ PRINTF_BLIT (" PrvIncBlitterRun: source: 0x%04X", source);
+ PRINTF_BLIT (" PrvIncBlitterRun: dest: 0x%04X", dest);
+ PRINTF_BLIT (" PrvIncBlitterRun: output: 0x%04X", output);
+
+ // Write this pixel as long as it's not transparent or clipped out.
+
+ if (!this->PrvTransparent (source, dest, pattern) && !this->PrvClipped ())
+ {
+ PRINTF_BLIT (" PrvIncBlitterRun: setting...");
+
+ this->PrvSetPixel (output, fXDest, fYDest);
+ }
+ else
+ {
+ PRINTF_BLIT (" PrvIncBlitterRun: skipping...");
+ }
+
+ // Move to the next X/Y position.
+
+ fBlitInProgress = this->PrvNextXY ();
+
+ if (!fBlitInProgress)
+ {
+ EmAssert (this->PrvSrcFifoFilledSlots () == 0);
+ PRINTF_BLIT (" PrvIncBlitterRun: Completed!");
+ }
+ }
+
+ PRINTF_BLIT (" PrvIncBlitterRun: **************************************************");
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvPatternPipeInit
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvPatternPipeInit (void)
+{
+ fXPattern = fState.monoPatternXOffset;
+ fYPattern = fState.monoPatternYOffset;
+
+ PRINTF_BLIT (" PrvPatternPipeInit: fXPattern: %u", fXPattern);
+ PRINTF_BLIT (" PrvPatternPipeInit: fYPattern: %u", fYPattern);
+
+ // Expand the specified pattern into a pixel array.
+
+ if (fUsesPattern)
+ {
+ // Force the pattern data to be a solid color, if specified.
+
+ if (fState.solidPattern)
+ {
+ PRINTF_BLIT (" PrvPatternPipeInit: filling with: 0x%04X",
+ fState.fgColorMonoPat);
+
+ for (int ii = 0; ii < 64; ++ii)
+ {
+ fPatternPipe [ii] = fState.fgColorMonoPat;
+ }
+ }
+
+ // If the pattern is specified as a 64-bit array, expand it
+ // into a 64-byte array with the fore- and background colors set.
+
+ else if (fState.monoPattern)
+ {
+ /*
+ A pattern is an 8x8 structure, for a total of 64 bits.
+ This is represented on the Palm as an 8 element array
+ of 8-bit bytes. When translated into MediaQ terms, they
+ are transferred to the registers with:
+
+ gePAT16( GE_MONO_PAT0_L, *patPtr++ );
+ gePAT16( GE_MONO_PAT0_H, *patPtr++ );
+ gePAT16( GE_MONO_PAT1_L, *patPtr++ );
+ gePAT16( GE_MONO_PAT1_H, *patPtr );
+
+ where "patPtr" is a UInt16*. Thus, when read back out
+ as two DWORDs, the LSB of monoPattern1 contains the first
+ byte of the pattern, the next LSB contains the second
+ byte, all the way up to where the MSB of monoPattern2
+ contains the last byte.
+ */
+
+ PRINTF_BLIT (" PrvPatternPipeInit: expanding: 0x%08X 0x%08X",
+ fState.monoPattern1, fState.monoPattern2);
+
+ this->PrvExpandMono32 (fState.monoPattern1, &fPatternPipe [0],
+ fState.fgColorMonoPat, fState.bgColorMonoPat);
+
+ this->PrvExpandMono32 (fState.monoPattern2, &fPatternPipe [32],
+ fState.fgColorMonoPat, fState.bgColorMonoPat);
+
+ uint16* p = fPatternPipe;
+ UNUSED_PARAM(p);
+
+ PRINTF_BLIT (" PrvPatternPipeInit: 0: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 1: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[8+0], p[8+1], p[8+2], p[8+3], p[8+4], p[8+5], p[8+6], p[8+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 2: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[16+0], p[16+1], p[16+2], p[16+3], p[16+4], p[16+5], p[16+6], p[16+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 3: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[24+0], p[24+1], p[24+2], p[24+3], p[24+4], p[24+5], p[24+6], p[24+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 4: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[32+0], p[32+1], p[32+2], p[32+3], p[32+4], p[32+5], p[32+6], p[32+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 5: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[40+0], p[40+1], p[40+2], p[40+3], p[40+4], p[40+5], p[40+6], p[40+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 6: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[48+0], p[48+1], p[48+2], p[48+3], p[48+4], p[48+5], p[48+6], p[48+7]);
+ PRINTF_BLIT (" PrvPatternPipeInit: 7: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[56+0], p[56+1], p[56+2], p[56+3], p[56+4], p[56+5], p[56+6], p[56+7]);
+ }
+ else
+ {
+ // The monoPattern bit MUST be programmed to 1, according to
+ // the docs. Color patterns don't appear to be supported.
+
+ EmAssert (false);
+ }
+ }
+
+ // We're not making use of any pattern data.
+
+ else
+ {
+ // Do nothing. The pattern array will be garbage, but the theory
+ // here is that it's not going to be used.
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvPatternPipeNextPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvPatternPipeNextPixel (void)
+{
+ uint16 result = fPatternPipe [fXPattern + fYPattern * 8];
+
+ PRINTF_BLIT (" PrvPatternPipeNextPixel: fXPattern: %u", fXPattern);
+ PRINTF_BLIT (" PrvPatternPipeNextPixel: fYPattern: %u", fYPattern);
+ PRINTF_BLIT (" PrvPatternPipeNextPixel: result: 0x%04X", result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvPatternPipeNextX
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvPatternPipeNextX (void)
+{
+ ++fXPattern;
+
+ if (fXPattern == 8)
+ {
+ fXPattern = 0;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvPatternPipeNextY
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvPatternPipeNextY (void)
+{
+ ++fYPattern;
+ fXPattern = fState.monoPatternXOffset;
+
+ if (fYPattern == 8)
+ {
+ fYPattern = 0;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcPipeInit
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvSrcPipeInit (void)
+{
+ fXSrc = fState.xSrc;
+ fYSrc = fState.ySrc;
+
+ if (fState.xyConversion)
+ {
+ if (fState.xDirection)
+ fXSrc += fState.width - 1;
+
+ if (fState.yDirection)
+ fYSrc += fState.height - 1;
+ }
+
+ if (fUsesSource && !fState.solidSourceColor && fState.systemMemory)
+ {
+ fLeadingSourcePixels = this->PrvLeadingPixels ();
+ fTrailingSourcePixels = this->PrvTrailingPixels ();
+
+ PRINTF_BLIT (" PrvSrcPipeInit: fLeadingSourcePixels: %u", fLeadingSourcePixels);
+ PRINTF_BLIT (" PrvSrcPipeInit: fTrailingSourcePixels: %u", fTrailingSourcePixels);
+ }
+
+ // Setting both of these variables to the same value will force the
+ // source pipe to fill itself from the source data FIFO the first
+ // time we access it (assuming that that's where the source data is
+ // coming from).
+
+ fSourcePipeIndex = 0;
+ fSourcePipeMax = 0;
+
+ fSourcePipeSkip = fLeadingSourcePixels;
+
+ PRINTF_BLIT (" PrvSrcPipeInit: fXSrc: %u", fXSrc);
+ PRINTF_BLIT (" PrvSrcPipeInit: fYSrc: %u", fYSrc);
+ PRINTF_BLIT (" PrvSrcPipeInit: fSourcePipeSkip: %u", fSourcePipeSkip);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcPipeNextPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvSrcPipeNextPixel (Bool& stalled)
+{
+ stalled = false;
+
+ if (!fUsesSource)
+ {
+ // Return a dummy value. The theory here is that it's not
+ // going to be used.
+
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: result: <dummy>");
+
+ return 0;
+ }
+
+ // Force the source data to be a solid color, if specified.
+
+ if (fState.solidSourceColor)
+ {
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: result: 0x%04X (solid)", fState.fgColorMonoSrc);
+
+ return fState.fgColorMonoSrc;
+ }
+
+ // If we're getting source data from system memory, then read
+ // the data from the source FIFO.
+
+ if (fState.systemMemory)
+ {
+ uint16 result;
+
+ // Loop getting source pixels. Normally, we'll just return
+ // the first pixel, but we may need to skip some in case we're
+ // in the part of the scanline before the first valid pixel
+ // or after the last one.
+
+ while (1)
+ {
+ if (fSourcePipeIndex == fSourcePipeMax)
+ {
+ this->PrvSrcPipeFill (stalled);
+
+ if (stalled)
+ return 0; // Return a dummy value
+
+ fSourcePipeIndex = 0;
+ }
+
+ result = fSourcePipe [fSourcePipeIndex++];
+
+ if (fSourcePipeSkip == 0)
+ {
+ break;
+ }
+
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: skipping... %u", fSourcePipeSkip);
+
+ --fSourcePipeSkip;
+ }
+
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: result: 0x%04X", result);
+
+ return result;
+ }
+
+ // We're getting the source pixel value from the display memory.
+
+ uint16 result = this->PrvGetPixel (fXSrc, fYSrc);
+
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: fXSrc: %u", fXSrc);
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: fYSrc: %u", fYSrc);
+ PRINTF_BLIT (" PrvSrcPipeNextPixel: result: 0x%04X", result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcPipeNextX
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvSrcPipeNextX (void)
+{
+ fXSrc += (fState.xDirection == 0) ? 1 : -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcPipeNextY
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvSrcPipeNextY (void)
+{
+ fYSrc += (fState.yDirection == 0) ? 1 : -1;
+ fXSrc = fState.xSrc;
+
+ if (fState.xyConversion)
+ {
+ if (fState.xDirection)
+ fXSrc += fState.width - 1;
+ }
+
+ fSourcePipeSkip = fTrailingSourcePixels/* + fLeadingSourcePixels*/;
+
+ PRINTF_BLIT (" PrvSrcPipeNextY: fXSrc: %u", fXSrc);
+ PRINTF_BLIT (" PrvSrcPipeNextY: fYSrc: %u", fYSrc);
+ PRINTF_BLIT (" PrvSrcPipeNextY: fSourcePipeSkip: %u", fSourcePipeSkip);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvSrcPipeFill
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvSrcPipeFill (Bool& stalled)
+{
+ // If there's no data in the FIFO, bail out.
+
+ if (this->PrvSrcFifoFilledSlots () == 0)
+ {
+ PRINTF_BLIT (" PrvSrcPipeFill: stalled...");
+
+ stalled = true;
+ return;
+ }
+
+ uint16* p = fSourcePipe;
+ UNUSED_PARAM(p);
+
+ uint32 source1;
+ uint32 source2;
+
+ this->PrvGetSrcFifoSlot (source1, source2);
+
+ // If the source is monochrome, then expand it.
+
+ if (fState.monoSource)
+ {
+ fSourcePipeMax = 64;
+
+ PRINTF_BLIT (" PrvSrcPipeFill: expanding: 0x%08X 0x%08X",
+ source1, source2);
+
+ this->PrvExpandMono32 (source1, &fSourcePipe[0],
+ fState.fgColorMonoSrc, fState.bgColorMonoSrc);
+
+ this->PrvExpandMono32 (source2, &fSourcePipe[32],
+ fState.fgColorMonoSrc, fState.bgColorMonoSrc);
+
+ PRINTF_BLIT (" PrvSrcPipeFill: 0: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 1: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[8+0], p[8+1], p[8+2], p[8+3], p[8+4], p[8+5], p[8+6], p[8+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 2: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[16+0], p[16+1], p[16+2], p[16+3], p[16+4], p[16+5], p[16+6], p[16+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 3: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[24+0], p[24+1], p[24+2], p[24+3], p[24+4], p[24+5], p[24+6], p[24+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 4: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[32+0], p[32+1], p[32+2], p[32+3], p[32+4], p[32+5], p[32+6], p[32+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 5: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[40+0], p[40+1], p[40+2], p[40+3], p[40+4], p[40+5], p[40+6], p[40+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 6: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[48+0], p[48+1], p[48+2], p[48+3], p[48+4], p[48+5], p[48+6], p[48+7]);
+ PRINTF_BLIT (" PrvSrcPipeFill: 7: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[54+0], p[54+1], p[54+2], p[54+3], p[54+4], p[54+5], p[54+6], p[54+7]);
+ }
+
+ // If the source is in color, then break apart the 64-bit
+ // value we read into individual pixels. We'll get either
+ // 4 or 8 pixels, depending on the source depth.
+
+ else if (fState.colorDepth == kColorDepth8)
+ {
+ fSourcePipeMax = 8;
+
+ fSourcePipe[0] = (source1 >> 0) & 0x000000FF;
+ fSourcePipe[1] = (source1 >> 8) & 0x000000FF;
+ fSourcePipe[2] = (source1 >> 16) & 0x000000FF;
+ fSourcePipe[3] = (source1 >> 24) & 0x000000FF;
+
+ fSourcePipe[4] = (source2 >> 0) & 0x000000FF;
+ fSourcePipe[5] = (source2 >> 8) & 0x000000FF;
+ fSourcePipe[6] = (source2 >> 16) & 0x000000FF;
+ fSourcePipe[7] = (source2 >> 24) & 0x000000FF;
+
+ PRINTF_BLIT (" PrvSrcPipeFill: 0: 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ }
+ else if (fState.colorDepth == kColorDepth16)
+ {
+ fSourcePipeMax = 4;
+
+ fSourcePipe[0] = (source1 >> 0) & 0x0000FFFF;
+ fSourcePipe[1] = (source1 >> 16) & 0x0000FFFF;
+
+ fSourcePipe[2] = (source2 >> 0) & 0x0000FFFF;
+ fSourcePipe[3] = (source2 >> 16) & 0x0000FFFF;
+
+ PRINTF_BLIT (" PrvSrcPipeFill: 0: 0x%04X 0x%04X 0x%04X 0x%04X",
+ p[0], p[1], p[2], p[3]);
+ }
+ else
+ {
+ EmAssert (false);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDestPipeInit
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDestPipeInit (void)
+{
+ fXDest = fState.xDest;
+ fYDest = fState.yDest;
+
+ if (fState.xyConversion)
+ {
+ if (fState.xDirection)
+ fXDest += fState.width - 1;
+
+ if (fState.yDirection)
+ fYDest += fState.height - 1;
+ }
+
+ PRINTF_BLIT (" PrvDestPipeInit: fXDest: %u", fXDest);
+ PRINTF_BLIT (" PrvDestPipeInit: fYDest: %u", fYDest);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDestPipeNextPixel
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvDestPipeNextPixel (void)
+{
+ uint16 result = this->PrvGetPixel (fXDest, fYDest);
+
+ PRINTF_BLIT (" PrvDestPipeNextPixel: fXDest: %u", fXDest);
+ PRINTF_BLIT (" PrvDestPipeNextPixel: fYDest: %u", fYDest);
+ PRINTF_BLIT (" PrvDestPipeNextPixel: result: 0x%04X", result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDestPipeNextX
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDestPipeNextX (void)
+{
+ fXDest += (fState.xDirection == 0) ? 1 : -1;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvDestPipeNextY
+// ---------------------------------------------------------------------------
+
+void EmRegsMediaQ11xx::PrvDestPipeNextY (void)
+{
+ fYDest += (fState.yDirection == 0) ? 1 : -1;
+ fXDest = fState.xDest;
+
+ if (fState.xyConversion)
+ {
+ if (fState.xDirection)
+ fXDest += fState.width - 1;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvNextXY
+// ---------------------------------------------------------------------------
+// Increment our X and Y counters. If we we're done, return false. If we've
+// moved to the next line, inform the various pipes that we've done that. If
+// we've merely moved to the next pixel on the same line, inform the pipes
+// that we've done that.
+
+Bool EmRegsMediaQ11xx::PrvNextXY (void)
+{
+ fCurXOffset += 1;
+
+ if (fCurXOffset == fState.width)
+ {
+ fCurXOffset = 0;
+ fCurYOffset += 1;
+
+ if (fCurYOffset == fState.height)
+ {
+ return false;
+ }
+
+ this->PrvPatternPipeNextY ();
+ this->PrvSrcPipeNextY ();
+ this->PrvDestPipeNextY ();
+ }
+ else
+ {
+ this->PrvPatternPipeNextX ();
+ this->PrvSrcPipeNextX ();
+ this->PrvDestPipeNextX ();
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvTransparent
+// ---------------------------------------------------------------------------
+
+Bool EmRegsMediaQ11xx::PrvTransparent (uint16 source, uint16 dest, uint16 pattern)
+{
+ if (fState.monoTransEnable)
+ {
+ if (fState.monoSource)
+ {
+ if (fState.monoTransPolarity == 0)
+ {
+ // Source background is transparent.
+
+ if (source == fState.bgColorMonoSrc)
+ {
+ PRINTF_BLIT (" PrvTransparent: source == fState.bgColorMonoSrc...");
+ return true;
+ }
+ }
+ else
+ {
+ // Source foreground is transparent.
+
+ if (source == fState.fgColorMonoSrc)
+ {
+ PRINTF_BLIT (" PrvTransparent: source == fState.fgColorMonoSrc...");
+ return true;
+ }
+ }
+ }
+
+ if (fState.monoPattern)
+ {
+ if (fState.monoTransPolarity == 0)
+ {
+ // Source background is transparent.
+
+ if (pattern == fState.bgColorMonoPat)
+ {
+ PRINTF_BLIT (" PrvTransparent: pattern == fState.bgColorMonoPat...");
+ return true;
+ }
+ }
+ else
+ {
+ // Source foreground is transparent.
+
+ if (pattern == fState.fgColorMonoPat)
+ {
+ PRINTF_BLIT (" PrvTransparent: pattern == fState.fgColorMonoPat...");
+ return true;
+ }
+ }
+ }
+ }
+
+ if (fState.colorTransEnable)
+ {
+ // Compare to source data.
+
+ if (fState.colorTransCmpSrc == 0)
+ {
+ if (!fState.monoSource)
+ {
+ // Transparent if source is the same as the test color.
+
+ if (fState.destTransPolarity == 0)
+ {
+ if (source == fState.destTransColor)
+ {
+ PRINTF_BLIT (" PrvTransparent: source == fState.destTransColor...");
+ return true;
+ }
+ }
+
+ // Transparent if source is different from the test color.
+
+ else
+ {
+ if (source != fState.destTransColor)
+ {
+ PRINTF_BLIT (" PrvTransparent: source != fState.destTransColor...");
+ return true;
+ }
+ }
+ }
+ }
+
+ // Compare to destination data.
+
+ else
+ {
+ // Transparent if dest is the same as the test color.
+
+ if (fState.destTransPolarity == 0)
+ {
+ if (dest == fState.destTransColor)
+ {
+ PRINTF_BLIT (" PrvTransparent: dest == fState.destTransColor...");
+ return true;
+ }
+ }
+
+ // Transparent if dest is different from the test color.
+
+ else
+ {
+ if (dest != fState.destTransColor)
+ {
+ PRINTF_BLIT (" PrvTransparent: dest != fState.destTransColor...");
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvClipped
+// ---------------------------------------------------------------------------
+
+Bool EmRegsMediaQ11xx::PrvClipped (void)
+{
+ if (fState.clipEnable)
+ {
+ if (fXDest < fState.clipLeft || fXDest >= fState.clipRight ||
+ fYDest < fState.clipTop || fYDest >= fState.clipBottom)
+ {
+ PRINTF_BLIT (" PrvWriteIt: clipped out...");
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvLeadingPixels
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvLeadingPixels (void)
+{
+ uint16 result;
+
+ if (fState.memToScreen)
+ {
+ // Packed Mode
+
+ if (fState.monoSource)
+ {
+ result = fState.srcLeadingBits + 8 * fState.srcLeadingBytes;
+ }
+ else if (fState.colorDepth == kColorDepth8)
+ {
+ result = fState.srcLeadingBytes;
+ }
+ else if (fState.colorDepth == kColorDepth16)
+ {
+ EmAssert (::IsEven (fState.srcLeadingBytes));
+ result = fState.srcLeadingBytes / 2;
+ }
+ else
+ {
+ EmAssert (false);
+ result = 0;
+ }
+ }
+ else
+ {
+ // Lined Mode
+
+ if (fState.monoSource)
+ {
+ result = fState.srcBitOffset + 8 * fState.srcByteOffset;
+ }
+ else if (fState.colorDepth == kColorDepth8)
+ {
+ result = fState.srcByteOffset;
+ }
+ else if (fState.colorDepth == kColorDepth16)
+ {
+ EmAssert (::IsEven (fState.srcByteOffset));
+ result = fState.srcByteOffset / 2;
+ }
+ else
+ {
+ EmAssert (false);
+ result = 0;
+ }
+ }
+
+ EmAssert (result < 64);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvTrailingPixels
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsMediaQ11xx::PrvTrailingPixels (void)
+{
+ uint16 result;
+
+ if (fState.memToScreen)
+ {
+ // Packed Mode
+
+ if (fState.monoSource)
+ {
+ result = fState.srcTrailingBits + 8 * fState.srcTrailingBytes;
+ }
+ else if (fState.colorDepth == kColorDepth8)
+ {
+ result = fState.srcTrailingBytes;
+ }
+ else if (fState.colorDepth == kColorDepth16)
+ {
+ EmAssert (::IsEven (fState.srcTrailingBytes));
+ result = fState.srcTrailingBytes / 2;
+ }
+ else
+ {
+ EmAssert (false);
+ result = 0;
+ }
+ }
+ else
+ {
+ // Lined Mode
+
+ uint16 bytesPerLine;
+
+ if (!fState.systemMemory || fState.srcEqualDestStride)
+ {
+ bytesPerLine = fState.destLineStride;
+ }
+ else
+ {
+ bytesPerLine = fState.srcLineStride;
+ }
+
+ uint16 pixelsPerLine;
+
+ if (fState.monoSource)
+ {
+ pixelsPerLine = bytesPerLine * 8;
+ }
+ else if (fState.colorDepth == kColorDepth8)
+ {
+ pixelsPerLine = bytesPerLine;
+ }
+ else if (fState.colorDepth == kColorDepth16)
+ {
+ EmAssert (::IsEven (bytesPerLine));
+ pixelsPerLine = bytesPerLine / 2;
+ }
+ else
+ {
+ EmAssert (false);
+ pixelsPerLine = 0;
+ }
+
+ result = pixelsPerLine - (fState.width + fLeadingSourcePixels);
+ }
+
+ EmAssert (result < 64);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvUsesPattern
+// ---------------------------------------------------------------------------
+// Return whether or not the specified rasterOperation will require the use
+// of a "pattern" value (that is, a pixel value from the pattern registers).
+//
+// To see if P is used in the output, consider the P, S, D combination
+// table again:
+//
+// P S D O (output)
+// --- --- --- ---
+// 0 0 0 b0
+// 0 0 1 b1
+// 0 1 0 b2
+// 0 1 1 b3
+// 1 0 0 b4
+// 1 0 1 b5
+// 1 1 0 b6
+// 1 1 1 b7
+//
+// If b0 == b4, b1 == b5, b2 == b6, and b3 == b7, then P has not figured into
+// the result at all. That is, for any S & D combination, we got the same
+// output regardless of what P was. Therefore, we can compare those bits to
+// see if P is relevent to the outcome or not.
+//
+// We can quickly compare the bits by taking the ROP:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+//
+// Making a copy of it:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+// b7 b6 b5 b4 b3 b2 b1 b0
+//
+// Shifting the copy:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+// 0 0 0 0 b7 b6 b5 b4
+//
+// XORing the two:
+//
+// (b7^0) (b6^0) (b5^0) (b4^0) (b3^b7) (b2^b6) (b1^b5) (b0^b4)
+//
+// And then masking out bits 4, 5, 6, and 7, as they don't include
+// results that we want:
+//
+// 0 0 0 0 (b3^b7) (b2^b6) (b1^b5) (b0^b4)
+//
+// Here, we have a bitfield containing the results of comparing the bits
+// that we're interested in. We can test the whole result to see if it's
+// zero or non-zero.
+
+Bool EmRegsMediaQ11xx::PrvUsesPattern (void)
+{
+ uint8 rop = fState.rasterOperation;
+ uint8 shifted = rop >> 4;
+ uint8 xored = rop ^ shifted;
+ uint8 masked = xored & 0x0F;
+
+ return masked != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvUsesSource
+// ---------------------------------------------------------------------------
+// Return whether or not the specified rasterOperation will require the use
+// of a "source" value (that is, a pixel value from a source buffer).
+//
+// To see if S is used in the output, consider the P, S, D combination
+// table again:
+//
+// P S D O (output)
+// --- --- --- ---
+// 0 0 0 b0
+// 0 0 1 b1
+// 0 1 0 b2
+// 0 1 1 b3
+// 1 0 0 b4
+// 1 0 1 b5
+// 1 1 0 b6
+// 1 1 1 b7
+//
+// If b0 == b2, b1 == b3, b4 == b6, and b5 == b7, then S has not figured into
+// the result at all. That is, for any P & D combination, we got the same
+// output regardless of what S was. Therefore, we can compare those bits to
+// see if S is relevent to the outcome or not.
+//
+// We can quickly compare the bits by taking the ROP:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+//
+// Making a copy of it:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+// b7 b6 b5 b4 b3 b2 b1 b0
+//
+// Shifting the copy:
+//
+// b7 b6 b5 b4 b3 b2 b1 b0
+// 0 0 b7 b6 b5 b4 b3 b2
+//
+// XORing the two:
+//
+// (b7^0) (b6^0) (b5^b7) (b4^b6) (b3^b5) (b2^b4) (b1^b3) (b0^b2)
+//
+// And then masking out bits 2, 3, 6, and 7, as they don't include
+// results that we want:
+//
+// 0 0 (b5^b7) (b4^b6) 0 0 (b1^b3) (b0^b2)
+//
+// Here, we have a bitfield containing the results of comparing the bits
+// that we're interested in. We can test the whole result to see if it's
+// zero or non-zero.
+
+Bool EmRegsMediaQ11xx::PrvUsesSource (void)
+{
+ uint8 rop = fState.rasterOperation;
+ uint8 shifted = rop >> 2;
+ uint8 xored = rop ^ shifted;
+ uint8 masked = xored & 0x33;
+
+ return masked != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvExpandMono8
+// ---------------------------------------------------------------------------
+// Take a bit pattern, and expand it into an array of color values, where
+// elements of the array are set to the foreground color if the bit in the
+// pattern is one, and the background color if the bit is zero.
+
+void EmRegsMediaQ11xx::PrvExpandMono8 (uint8 bits, uint16* results,
+ uint16 fgColor, uint16 bgColor)
+{
+ if (fState.monoSrcBitSwap)
+ {
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ if ((bits & (1 << ii)) != 0)
+ {
+ results[ii] = fgColor;
+ }
+ else
+ {
+ results[ii] = bgColor;
+ }
+ }
+ }
+ else
+ {
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ if ((bits & (0x080 >> ii)) != 0)
+ {
+ results[ii] = fgColor;
+ }
+ else
+ {
+ results[ii] = bgColor;
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsMediaQ11xx::PrvExpandMono32
+// ---------------------------------------------------------------------------
+// Wrapper to perform the expansion of 4 8-bit bitfields in a DWORD.
+
+void EmRegsMediaQ11xx::PrvExpandMono32 (uint32 bits, uint16* results,
+ uint16 fgColor, uint16 bgColor)
+{
+ this->PrvExpandMono8 (bits >> 0, &results[ 0], fgColor, bgColor);
+ this->PrvExpandMono8 (bits >> 8, &results[ 8], fgColor, bgColor);
+ this->PrvExpandMono8 (bits >> 16, &results[16], fgColor, bgColor);
+ this->PrvExpandMono8 (bits >> 24, &results[24], fgColor, bgColor);
+}
diff --git a/SrcShared/Hardware/EmRegsMediaQ11xx.h b/SrcShared/Hardware/EmRegsMediaQ11xx.h
new file mode 100644
index 0000000..2a6a69a
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsMediaQ11xx.h
@@ -0,0 +1,351 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsMediaQ11xx_h
+#define EmRegsMediaQ11xx_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmRegs.h" // EmRegs
+#include "EmPalmStructs.h" // EmProxyHwrMediaQ11xType
+
+#include <vector> // vector
+
+
+#define T_BASE 0x1F000000L //68KVZ for Palm platform
+#define MMIO_OFFSET 0x40000 // starts at 256K address
+#define MMIO_BASE (T_BASE + MMIO_OFFSET)
+
+// This struct is a mirror of the MediaQ graphics enginer registers. As
+// the registers are updated, this struct is updated so that we have
+// easy access to the values in the registers without having to unpack
+// them all the time.
+
+struct GEState
+{
+ // * means that I've completely accounted for that field
+ // and don't have to think about it any more.
+ //
+ // - means that I'm not going to support that field and
+ // so don't ever have to think about it.
+ //
+ // ? means that I don't know what this field is for.
+
+ // ==================== GE00R ====================
+
+ uint8 rasterOperation; // [7:0]*
+ uint8 commandType; // [10:8]*
+ uint8 xDirection; // [11]*
+ uint8 yDirection; // [12]*
+ uint8 systemMemory; // [13]*
+ uint8 monoSource; // [14]*
+ uint8 monoPattern; // [15]*
+ uint8 colorTransEnable; // [16]*
+ uint8 destTransPolarity; // [17]*
+ uint8 monoTransEnable; // [18]*
+ uint8 monoTransPolarity; // [19]*
+ uint8 memToScreen; // [20]*
+ uint8 solidSourceColor; // [23]*
+ uint8 srcEqualDestStride; // [24]*
+ uint8 rop2Select; // [25]?
+ uint8 clipEnable; // [26]*
+ uint8 autoExecute; // [27]*
+ uint8 solidPattern; // [30]*
+ uint8 colorTransCmpSrc; // [31]*
+
+ // ==================== GE01R ====================
+
+ // BitBLT
+
+ uint16 width; // [11:0]*
+ uint16 height; // [27:16]*
+ uint8 xyConversion; // [31]*
+
+ // Line
+
+ int32 gamma; // [16:0]?
+ uint16 majorLength; // [28:17]*
+ uint8 yIsMajor; // [29]*
+ uint8 drawLastPixel; // [30]*
+ uint8 useXY; // [31]*
+
+ // ==================== GE02R ====================
+
+ // BitBLT
+
+ uint16 xDest; // [11:0]*
+ uint8 monoPatternXOffset; // [15:13]*
+ uint16 yDest; // [27:16]*
+ uint8 monoPatternYOffset; // [31:29]*
+
+ // Line
+
+ uint16 xStart; // [11:0]*
+ uint16 deltaMajor; // [28:12]*
+ uint16 quadrant; // [31:29]*
+
+ // ==================== GE03R ====================
+
+ // BitBLT
+
+ uint16 xSrc; // [11:0]*
+ uint16 ySrc; // [27:16]*
+
+ // Line
+
+ uint16 yStart; // [11:0]*
+ uint16 deltaMinor; // [28:12]*
+
+ // ==================== GE04R ====================
+
+ uint16 destTransColor; // [15:0]*
+
+ // ==================== GE05R ====================
+
+ uint16 clipLeft; // [10:0]*
+ uint16 clipTop; // [25:16]*
+
+ // ==================== GE06R ====================
+
+ uint16 clipRight; // [10:0]*
+ uint16 clipBottom; // [25:16]*
+
+ // ==================== GE07R ====================
+
+ uint16 fgColorMonoSrc; // [15:0]*
+
+ // ==================== GE08R ====================
+
+ uint16 bgColorMonoSrc; // [15:0]*
+
+ // ==================== GE09R ====================
+
+ // Lined Mode
+
+ uint16 srcLineStride; // [9:0]*
+ uint8 srcBitOffset; // [27:25]*
+ uint8 srcByteOffset; // [30:28]*
+
+ // Packed Mode
+
+ uint8 srcLeadingBits; // [2:0]*
+ uint8 srcLeadingBytes; // [5:3]*
+ uint16 srcNumBytes; // [15:6]*
+ uint8 srcTrailingBits; // [27:25]*
+ uint8 srcTrailingBytes; // [31:28]*
+
+ // ==================== GE0AR ====================
+
+ uint16 destLineStride; // [9:0]*
+ uint8 monoSrcBitSwap; // [28]*
+ uint8 rotate90; // [29]*
+ uint8 colorDepth; // [31:30]*
+
+ // ==================== GE0BR ====================
+
+ uint32 baseAddr; // [19:0]*
+ uint8 testModeEnable; // [29]-
+ uint8 testModeControl; // [31:30]-
+
+ // ==================== GE0CR ====================
+
+ uint16 cmdLineStart; // [9:0]-
+ uint16 cmdLineEnd; // [21:12]-
+ uint8 cmdLineControl; // [24]-
+ uint8 gc1SwitchControl; // [27:26]-
+
+ // ==================== GE0FR ====================
+
+ // Test register
+
+ // ==================== GE10R ====================
+
+ uint32 monoPattern1; // [31:0]*
+
+ // ==================== GE11R ====================
+
+ uint32 monoPattern2; // [31:0]*
+
+ // ==================== GE12R ====================
+
+ uint16 fgColorMonoPat; // [15:0]*
+
+ // ==================== GE13R ====================
+
+ uint16 bgColorMonoPat; // [15:0]*
+};
+
+
+class EmRegsMediaQ11xx : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsMediaQ11xx (emuptr baseRegsAddr,
+ emuptr baseVideoAddr);
+ virtual ~EmRegsMediaQ11xx (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHAL overrides
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ protected:
+ uint32 MQRead (emuptr address, int size);
+ void MQWrite (emuptr address, int size, uint32 value);
+
+ private:
+ uint32 CC01Read (emuptr address, int size);
+
+ void DC00Write (emuptr address, int size, uint32 value);
+ void GE00Write (emuptr address, int size, uint32 value);
+ void GE02Write (emuptr address, int size, uint32 value);
+ void SourceFifoWrite (emuptr address, int size, uint32 value);
+ void invalidateWrite (emuptr address, int size, uint32 value);
+
+ private:
+ void AddressError (emuptr address, long size, Bool forRead);
+ void PrvGetPalette (RGBList& thePalette);
+ void PrvUpdateByteLanes (void);
+
+ uint32 PrvGetBPP (void);
+ uint32 PrvGetWidth (void);
+ uint32 PrvGetHeight (void);
+ uint32 PrvGetRowBytes (void);
+ uint32 PrvGetVideoOffset (void);
+ uint32 PrvGetVideoBase (void);
+ uint32 PrvGetFrameBuffer (void);
+ Bool PrvGetXDoubling (void);
+ Bool PrvGetYDoubling (void);
+
+ void PrvGetGEState (int regNum);
+ void PrvLogGEState ();
+
+ void PrvDoCommand (void);
+ void PrvDoBitBLT (void);
+ void PrvDoLine (void);
+ void PrvIllegalCommand (void);
+
+ int PrvSrcFifoFilledSlots (void);
+ void PrvGetSrcFifoSlot (uint32&, uint32&);
+
+ // Drawing related functions
+ uint16 PrvAdjustPixel (uint16 pen,
+ uint16 dest,
+ uint8 rOpCode);
+ uint16 PrvAdjustPixel (uint16 pattern,
+ uint16 src,
+ uint16 dest,
+ uint8 rOpCode);
+
+ void PrvSetPixel (uint16 pixel,
+ uint16 x, uint16 y);
+ uint16 PrvGetPixel (uint16 x, uint16 y);
+ emuptr PrvGetPixelLocation (uint16 x, uint16 y);
+
+ void PrvIncBlitterInit (void);
+ void PrvIncBlitterRun (void);
+
+ void PrvPatternPipeInit (void);
+ uint16 PrvPatternPipeNextPixel (void);
+ void PrvPatternPipeNextX (void);
+ void PrvPatternPipeNextY (void);
+
+ void PrvSrcPipeInit (void);
+ uint16 PrvSrcPipeNextPixel (Bool& stalled);
+ void PrvSrcPipeNextX (void);
+ void PrvSrcPipeNextY (void);
+ void PrvSrcPipeFill (Bool& stalled);
+
+ void PrvDestPipeInit (void);
+ uint16 PrvDestPipeNextPixel (void);
+ void PrvDestPipeNextX (void);
+ void PrvDestPipeNextY (void);
+
+ Bool PrvNextXY (void);
+ Bool PrvTransparent (uint16 source, uint16 dest, uint16 pattern);
+ Bool PrvClipped (void);
+ uint16 PrvLeadingPixels (void);
+ uint16 PrvTrailingPixels (void);
+
+ Bool PrvUsesPattern (void);
+ Bool PrvUsesSource (void);
+ void PrvExpandMono8 (uint8 bits, uint16* results,
+ uint16 fgColor, uint16 bgColor);
+ void PrvExpandMono32 (uint32 bits, uint16* results,
+ uint16 fgColor, uint16 bgColor);
+
+ private:
+ emuptr fBaseRegsAddr;
+ emuptr fBaseVideoAddr;
+ EmProxyHwrMediaQ11xxType fRegs;
+ GEState fState;
+
+ int fBytelanes[4];
+ emuptr fLastAddress;
+ int fLastSize;
+
+ vector<uint32> fSourceFifo;
+
+ // Values used while incrementally blitting.
+
+ Bool fBlitInProgress;
+
+ uint16 fCurXOffset;
+ uint16 fCurYOffset;
+
+ // Some values cached for speed. These are calculated once
+ // for each blit operation and saved, as they don't vary once
+ // the blit has started. However, there's no evidence that
+ // any such caching is needed -- no timing experiments have
+ // bee performed.
+
+ Bool fUsesPattern;
+ Bool fUsesSource;
+
+ uint16 fLeadingSourcePixels;
+ uint16 fTrailingSourcePixels;
+
+ // Pattern pipe data
+
+ uint16 fPatternPipe[64];
+ uint16 fXPattern;
+ uint16 fYPattern;
+
+ // Source pipe data
+
+ uint16 fSourcePipe[64];
+ uint16 fSourcePipeIndex;
+ uint16 fSourcePipeMax;
+ uint16 fSourcePipeSkip;
+ uint16 fXSrc;
+ uint16 fYSrc;
+
+ // Dest pipe data
+
+ uint16 fXDest;
+ uint16 fYDest;
+};
+
+#endif // EmRegsMediaQ11xx_h
diff --git a/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.cpp b/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.cpp
new file mode 100644
index 0000000..6f0bc8b
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.cpp
@@ -0,0 +1,210 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsPLDPalmVIIEZ.h"
+
+#include "EmHAL.h" // EmHAL::GetSerialPortOn
+
+#define NON_PORTABLE
+#include "EZSumo/IncsPrv/HardwareEZ.h" // hwrJerryPldBase, hwrJerryPld232Enable
+#undef NON_PORTABLE
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsPLDPalmVIIEZ::read, \
+ (WriteFunction) &EmRegsPLDPalmVIIEZ::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::EmRegsPLDPalmVIIEZ
+// ---------------------------------------------------------------------------
+
+EmRegsPLDPalmVIIEZ::EmRegsPLDPalmVIIEZ (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::~EmRegsPLDPalmVIIEZ
+// ---------------------------------------------------------------------------
+
+EmRegsPLDPalmVIIEZ::~EmRegsPLDPalmVIIEZ (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::GetSerialPortOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsPLDPalmVIIEZ::GetSerialPortOn (int /*uartNum*/)
+{
+ return (fRegs.rs232Shdn & hwrJerryPld232Enable) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dspOn);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, chargeOn);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, refOn);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, pipaBiasEnable);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dspReset);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, ezToDsl);
+ INSTALL_HANDLER (StdReadBE, rs232ShdnWrite, rs232Shdn);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, spareOut);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dTo3Sln);
+ INSTALL_HANDLER (iXtrnl2Read, StdWriteBE, iXtrnl2);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsPLDPalmVIIEZ::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsPLDPalmVIIEZ::GetAddressStart (void)
+{
+ return hwrJerryPldBase;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmVIIEZ::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::rs232ShdnWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmVIIEZ::rs232ShdnWrite (emuptr address, int size, uint32 value)
+{
+ // Take a snapshot of the line driver states.
+
+ Bool driverStates[kUARTEnd];
+ EmHAL::GetLineDriverStates (driverStates);
+
+ StdWriteBE (address, size, value);
+
+ // Respond to any changes in the line driver states.
+
+ EmHAL::CompareLineDriverStates (driverStates);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmVIIEZ::iXtrnl2Read
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmVIIEZ::iXtrnl2Read (emuptr address, int size)
+{
+ uint32 result = StdReadBE (address, size);
+
+ // Ensure that bit 0x0080 is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ result |= 0x0080;
+
+ return result;
+}
diff --git a/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.h b/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.h
new file mode 100644
index 0000000..92085f8
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsPLDPalmVIIEZ.h
@@ -0,0 +1,51 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsPLDPalmVIIEZ_h
+#define EmRegsPLDPalmVIIEZ_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmPalmStructs.h" // EmProxyHwrJerryPLDType
+#include "EmRegs.h" // EmRegs
+
+class SessionFile;
+
+
+class EmRegsPLDPalmVIIEZ : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsPLDPalmVIIEZ (void);
+ virtual ~EmRegsPLDPalmVIIEZ (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual Bool GetSerialPortOn (int uartNum);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ protected:
+ void rs232ShdnWrite (emuptr address, int size, uint32 value);
+ uint32 iXtrnl2Read (emuptr address, int size);
+
+ private:
+ EmProxyHwrJerryPLDType fRegs;
+};
+
+#endif /* EmRegsPLDPalmVIIEZ_h */
diff --git a/SrcShared/Hardware/EmRegsPrv.h b/SrcShared/Hardware/EmRegsPrv.h
new file mode 100644
index 0000000..d436c47
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsPrv.h
@@ -0,0 +1,37 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsPrv_h
+#define EmRegsPrv_h
+
+#include "EmMemory.h" // EmMemDoGet8, EmMemDoPut8, etc.
+
+// Inline functions for reading/writing registers.
+
+inline int8 _get_reg (int8* a) { return EmMemDoGet8 (a); }
+inline int16 _get_reg (int16* a) { return EmMemDoGet16 (a); }
+inline int32 _get_reg (int32* a) { return EmMemDoGet32 (a); }
+
+inline uint8 _get_reg (uint8* a) { return EmMemDoGet8 (a); }
+inline uint16 _get_reg (uint16* a) { return EmMemDoGet16 (a); }
+inline uint32 _get_reg (uint32* a) { return EmMemDoGet32 (a); }
+
+inline void _put_reg (int8* a, int8 v) { EmMemDoPut8 (a, v); }
+inline void _put_reg (int16* a, int16 v) { EmMemDoPut16 (a, v); }
+inline void _put_reg (int32* a, int32 v) { EmMemDoPut32 (a, v); }
+
+inline void _put_reg (uint8* a, uint8 v) { EmMemDoPut8 (a, v); }
+inline void _put_reg (uint16* a, uint16 v) { EmMemDoPut16 (a, v); }
+inline void _put_reg (uint32* a, uint32 v) { EmMemDoPut32 (a, v); }
+
+#endif // EmRegsPrv_h
diff --git a/SrcShared/Hardware/EmRegsSED1375.cpp b/SrcShared/Hardware/EmRegsSED1375.cpp
new file mode 100644
index 0000000..ea9831b
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSED1375.cpp
@@ -0,0 +1,506 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsSED1375.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmMemory.h" // EmMem_memcpy
+#include "EmPixMap.h" // SetSize, SetRowBytes, etc.
+#include "EmScreen.h" // EmScreen::InvalidateAll
+#include "Miscellaneous.h" // StWordSwapper
+#include "SessionFile.h" // WriteSED1375RegsType
+
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsSED1375::read, \
+ (WriteFunction) &EmRegsSED1375::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+#define kCLUTColorIndexMask 0xf000
+#define kCLUTColorsMask 0x0fff
+
+#define kCLUTRedMask 0x0f00
+#define kCLUTGreenMask 0x00f0
+#define kCLUTBlueMask 0x000f
+
+#define kCLUTIndexRed 0x4000
+#define kCLUTIndexGreen 0x2000
+#define kCLUTIndexBlue 0x1000
+
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::EmRegsSED1375
+// ---------------------------------------------------------------------------
+
+EmRegsSED1375::EmRegsSED1375 (emuptr baseRegsAddr, emuptr baseVideoAddr) :
+ fBaseRegsAddr (baseRegsAddr),
+ fBaseVideoAddr (baseVideoAddr),
+ fRegs ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::~EmRegsSED1375
+// ---------------------------------------------------------------------------
+
+EmRegsSED1375::~EmRegsSED1375 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+
+// EmAssert ((sed1375ProductCodeExpected | sed1375RevisionCodeExpected) == 0x24);
+ fRegs.productRevisionCode = 0x24;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ f.WriteSED1375RegsType (*(SED1375RegsType*) fRegs.GetPtr ());
+ f.FixBug (SessionFile::kBugByteswappedStructs);
+
+ StWordSwapper swapper1 (fClutData, sizeof (fClutData));
+ f.WriteSED1375Palette (fClutData);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ // Read in the SED registers.
+
+ if (f.ReadSED1375RegsType (*(SED1375RegsType*) fRegs.GetPtr ()))
+ {
+ // The Windows version of Poser 2.1d29 and earlier did not write
+ // out structs in the correct format. The fields of the struct
+ // were written out in Little-Endian format, not Big-Endian. To
+ // address this problem, the bug has been fixed, and a new field
+ // is added to the file format indicating that the bug has been
+ // fixed. With the new field (the "bug bit"), Poser can identify
+ // old files from new files and read them in accordingly.
+ //
+ // With the bug fixed, the .psf files should now be interchangeable
+ // across platforms (modulo other bugs...).
+
+ if (!f.IncludesBugFix (SessionFile::kBugByteswappedStructs))
+ {
+ Canonical (*(SED1375RegsType*) fRegs.GetPtr ());
+ }
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+ // Read in the LCD palette, and then byteswap it.
+
+ if (f.ReadSED1375Palette (fClutData))
+ {
+ ::ByteswapWords (fClutData, sizeof (fClutData));
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, NullWrite, productRevisionCode);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, mode0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mode1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, mode2);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, horizontalPanelSize);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPanelSizeLSB);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPanelSizeMSB);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLineStartPosition);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalNonDisplayPeriod);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEStartPosition);
+ INSTALL_HANDLER (vertNonDisplayRead, StdWriteBE, verticalNonDisplayPeriod);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, MODRate);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, screen1StartAddressLSB);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, screen1StartAddressMSB);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, screen2StartAddressLSB);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, screen2StartAddressMSB);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, screen1StartAddressMSBit);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, memoryAddressOffset);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, screen1VerticalSizeLSB);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, screen1VerticalSizeMSB);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, unused1);
+ INSTALL_HANDLER (StdReadBE, lookUpTableAddressWrite, lookUpTableAddress);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, unused2);
+ INSTALL_HANDLER (lookUpTableDataRead, lookUpTableDataWrite, lookUpTableData);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOConfigurationControl);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOStatusControl);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, scratchPad);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, portraitMode);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, lineByteCountRegister);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, unused3);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, unused4);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, unused5);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsSED1375::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsSED1375::GetAddressStart (void)
+{
+ return fBaseRegsAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsSED1375::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1375::GetLCDScreenOn (void)
+{
+ return ((fRegs.mode1) & sed1375DisplayBlank) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1375::GetLCDBacklightOn (void)
+{
+ return true; // The Backlight is always on for these units.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1375::GetLCDHasFrame (void)
+{
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Get the screen metrics.
+
+ int32 bpp = 1 << ((fRegs.mode1 & sed1375BPPMask) >> sed1375BPPShift);
+ int32 height = ((fRegs.verticalPanelSizeMSB << 8) | fRegs.verticalPanelSizeLSB) + 1;
+ int32 rowBytes = (fRegs.horizontalPanelSize + 1) * bpp;
+ uint32 offset = (fRegs.screen1StartAddressMSBit << 17) |
+ (fRegs.screen1StartAddressMSB << 9) |
+ (fRegs.screen1StartAddressLSB << 1);
+ emuptr baseAddr = fBaseVideoAddr + offset;
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+ int32 bpp = 1 << ((fRegs.mode1 & sed1375BPPMask) >> sed1375BPPShift);
+ int32 width = (fRegs.horizontalPanelSize + 1) * 8;
+ int32 height = ((fRegs.verticalPanelSizeMSB << 8) | fRegs.verticalPanelSizeLSB) + 1;
+ int32 rowBytes = (fRegs.horizontalPanelSize + 1) * bpp;
+ uint32 offset = (fRegs.screen1StartAddressMSBit << 17) |
+ (fRegs.screen1StartAddressMSB << 9) |
+ (fRegs.screen1StartAddressLSB << 1);
+ emuptr baseAddr = fBaseVideoAddr + offset;
+
+ info.fLeftMargin = 0;
+
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::invalidateWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::invalidateWrite (emuptr address, int size, uint32 value)
+{
+ this->StdWriteBE (address, size, value);
+ EmScreen::InvalidateAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::vertNonDisplayRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsSED1375::vertNonDisplayRead (emuptr address, int size)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ // Always set the vertical non-display status high since in the real
+ // hardware, the ROM will check this flag in order to write the CLUT
+ // registers.
+
+ return (fRegs.verticalNonDisplayPeriod) | sed1375VerticalNonDisplayStatus;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::lookUpTableAddressWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::lookUpTableAddressWrite (emuptr address, int size, uint32 value)
+{
+ this->StdWriteBE (address, size, value);
+
+ value &= 0x0FF;
+
+ fClutData[value] &= kCLUTColorsMask; // Update the rgb index
+ fClutData[value] |= kCLUTIndexRed;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::lookUpTableDataRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsSED1375::lookUpTableDataRead (emuptr address, int size)
+{
+ EmAssert (size == 1);
+
+ if (size != 1)
+ return 0; // Error case.
+
+ uint8 clutIndex = (fRegs.lookUpTableAddress); // Get the LUT Addr.
+ uint16 clutEntry = fClutData[clutIndex]; // Get the entry.
+ uint8 colorData;
+
+ if ((clutEntry & kCLUTIndexRed) != 0)
+ {
+ colorData = (uint8) ((clutEntry & kCLUTRedMask) >> 4); // Get the 4 bits of red.
+
+ fClutData[clutIndex] = // Update the next rgb index
+ (fClutData[clutIndex] & kCLUTColorsMask) | kCLUTIndexGreen;
+ }
+ else if ((clutEntry & kCLUTIndexGreen) != 0)
+ {
+ colorData = (uint8) (clutEntry & kCLUTGreenMask); // Get the 4 bits of green
+
+ fClutData[clutIndex] = // Update the next rgb index
+ (fClutData[clutIndex] & kCLUTColorsMask) | kCLUTIndexBlue;
+ }
+ else
+ {
+ colorData = (uint8) ((clutEntry & kCLUTBlueMask) << 4); // Get the 4 bits of blue.
+
+ address = (emuptr) (addressof (lookUpTableAddress));
+ EmRegsSED1375::lookUpTableAddressWrite (address, 1, (clutIndex + 1) & 0xFF);
+ }
+
+ return colorData;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::lookUpTableDataWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::lookUpTableDataWrite (emuptr address, int size, uint32 value)
+{
+ EmAssert (size == 1);
+
+ if (size != 1)
+ return; // Error case.
+
+ uint8 clutIndex = (fRegs.lookUpTableAddress); // Get the LUT Addr.
+ uint16 clutEntry = fClutData[clutIndex]; // Get the entry.
+
+ uint8 newColor = (uint8) (value & 0x00F0);
+
+ if (clutEntry & kCLUTIndexRed)
+ {
+ fClutData[clutIndex] &= ~kCLUTRedMask; // Clear out old red bits.
+ fClutData[clutIndex] |= newColor << 4; // Save in new red bits.
+
+ fClutData[clutIndex] = // Update the rgb index
+ (fClutData[clutIndex] & kCLUTColorsMask) | kCLUTIndexGreen;
+ }
+ else if (clutEntry & kCLUTIndexGreen)
+ {
+ fClutData[clutIndex] &= ~kCLUTGreenMask; // Clear out old red bits.
+ fClutData[clutIndex] |= newColor; // Save in new green bits.
+
+ fClutData[clutIndex] = // Update the rgb index
+ (fClutData[clutIndex] & kCLUTColorsMask) | kCLUTIndexBlue;
+ }
+ else
+ {
+ fClutData[clutIndex] &= ~kCLUTBlueMask; // Clear out old red bits.
+ fClutData[clutIndex] |= newColor >> 4; // Save in new blue bits.
+
+ address = (emuptr) (addressof (lookUpTableAddress));
+ EmRegsSED1375::lookUpTableAddressWrite (address, 1, (clutIndex + 1) & 0xFF);
+ }
+
+ EmScreen::InvalidateAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1375::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1375::PrvGetPalette (RGBList& thePalette)
+{
+ int32 bpp = 1 << ((fRegs.mode1 & sed1375BPPMask) >> sed1375BPPShift);
+ int32 numColors = 1 << bpp;
+
+ thePalette.resize (numColors);
+
+ for (int ii = 0; ii < numColors; ++ii)
+ {
+ uint16 curEntry = fClutData[ii];
+ uint8 color;
+
+ color = (uint8) ((curEntry & kCLUTRedMask) >> 4);
+ thePalette[ii].fRed = color + (color >> 4);
+
+ color = (uint8) ((curEntry & kCLUTGreenMask) >> 0);
+ thePalette[ii].fGreen = color + (color >> 4);
+
+ color = (uint8) ((curEntry & kCLUTBlueMask) << 4);
+ thePalette[ii].fBlue = color + (color >> 4);
+ }
+}
diff --git a/SrcShared/Hardware/EmRegsSED1375.h b/SrcShared/Hardware/EmRegsSED1375.h
new file mode 100644
index 0000000..7a0e5b5
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSED1375.h
@@ -0,0 +1,70 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsSED1375_h
+#define EmRegsSED1375_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmPalmStructs.h"
+#include "EmRegs.h"
+#include "EmStructs.h" // RGBList
+
+class SessionFile;
+class EmScreenUpdateInfo;
+
+
+class EmRegsSED1375 : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsSED1375 (emuptr baseRegsAddr,
+ emuptr baseVideoAddr);
+ virtual ~EmRegsSED1375 (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHAL overrides
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ private:
+ uint32 vertNonDisplayRead (emuptr address, int size);
+ uint32 lookUpTableDataRead (emuptr address, int size);
+
+ void invalidateWrite (emuptr address, int size, uint32 value);
+ void lookUpTableAddressWrite (emuptr address, int size, uint32 value);
+ void lookUpTableDataWrite (emuptr address, int size, uint32 value);
+
+ private:
+ void PrvGetPalette (RGBList& thePalette);
+
+ private:
+ emuptr fBaseRegsAddr;
+ emuptr fBaseVideoAddr;
+ EmProxySED1375RegsType fRegs;
+ uint16 fClutData[256];
+};
+
+#endif /* EmRegsSED1375_h */
diff --git a/SrcShared/Hardware/EmRegsSED1376.cpp b/SrcShared/Hardware/EmRegsSED1376.cpp
new file mode 100644
index 0000000..223c24a
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSED1376.cpp
@@ -0,0 +1,860 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsSED1376.h"
+
+#include "EmMemory.h" // EmMem_memcpy
+#include "EmScreen.h" // EmScreen::InvalidateAll
+#include "EmPixMap.h" // EmPixMap::GetLCDScanlines
+#include "SessionFile.h" // WriteSED1376RegsType
+
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsSED1376::read, \
+ (WriteFunction) &EmRegsSED1376::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+// Panel type register [10h]
+#define sed1376MonoMask 0x40
+
+// Display mode register [70h]
+#define sed1376DisplayBlankMask 0x80
+#define sed1376BPPMask 0x07
+#define sed1376BPPShift 0x00
+
+// REG[0x70] displayMode register
+// (Same as previous set, but with Handspring names for their contributed code)
+#define sed1376DisplayModeBlank 0x80
+#define sed1376DisplayModeDitherOff 0x40
+#define sed1376DisplayModeHwInvert 0x20
+#define sed1376DisplayModeSwInvert 0x10
+#define sed1376DisplayModeDepthMask 0x07
+#define sed1376DisplayModeDepth16 0x04
+#define sed1376DisplayModeDepth8 0x03
+#define sed1376DisplayModeDepth4 0x02
+#define sed1376DisplayModeDepth2 0x01
+#define sed1376DisplayModeDepth1 0x00
+
+// Special effects register [71h]
+#define sed1376WordSwapMask 0x80
+#define sed1376ByteSwapMask 0x40
+#define sed1376SubWindowEnableMask 0x10
+
+#define hwrDisplayGPIOPCI 0x08 // in GPIOStatusControl0
+#define hwrDisplayGPIOEL_ON 0x10 // in GPIOStatusControl0
+#define hwrDisplayGPIOLCD_ON 0x20 // in GPIOStatusControl0
+#define hwrDisplayGPIOMOD 0x40 // in GPIOStatusControl0
+
+// The current SED1376 driver code is completely whacked. It's initialized to use
+// the main display for drawing (see HwrDisplayInit in HwrDisplayBootSED1376.c), but
+// if you change the base address, it (a) always returns the base of the embedded
+// SRAM buffer as the old base address, and (b) stores the new base address in
+// ovlyStartAddress (see PrvDisplayBaseAddr in HwrDisplaySED1376.c). Also, the
+// splash screen appears to be drawn relative to ovlyStartAddress. Finally,
+// there appears to be code to draw a border in the main screen around the
+// overlay screen (see PrvDisplayBorder in HwrDisplayBootSED1376.c), however,
+// the mainStartAddress registers are never changed to point to this border.
+// On top of that, the border is only programmed on the left and right of the
+// of the overlay screen, not on the top and bottom.
+
+#define OVERLAY_IS_MAIN 1
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::EmRegsSED1376
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376::EmRegsSED1376 (emuptr baseRegsAddr, emuptr baseVideoAddr) :
+ fBaseRegsAddr (baseRegsAddr),
+ fBaseVideoAddr (baseVideoAddr),
+ fRegs ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::~EmRegsSED1376
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376::~EmRegsSED1376 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+
+// EmAssert ((sed1376ProductCodeExpected | sed1376RevisionCodeExpected) == 0x28);
+ fRegs.productRevisionCode = 0x28;
+ fRegs.displayBufferSize = 20; // 80K / 4K
+ fRegs.configurationReadback = 0;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ f.WriteSED1376RegsType (*(SED1376RegsType*) fRegs.GetPtr ());
+ f.WriteSED1376Palette (fClutData);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ // Read in the SED registers.
+
+ if (!f.ReadSED1376RegsType (*(SED1376RegsType*) fRegs.GetPtr ()))
+ {
+ f.SetCanReload (false);
+ }
+
+ // Read in the LCD palette.
+
+ if (!f.ReadSED1376Palette (fClutData))
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, NullWrite, productRevisionCode);
+ INSTALL_HANDLER (StdReadBE, NullWrite, displayBufferSize);
+ INSTALL_HANDLER (StdReadBE, NullWrite, configurationReadback);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, memoryClockConfiguration);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, pixelClockConfiguration);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteBlue);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteGreen);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteRed);
+ INSTALL_HANDLER (ZeroRead, lutWriteAddressWrite, lutWriteAddress);
+ INSTALL_HANDLER (StdReadBE, NullWrite, lutReadBlue);
+ INSTALL_HANDLER (StdReadBE, NullWrite, lutReadGreen);
+ INSTALL_HANDLER (StdReadBE, NullWrite, lutReadRed);
+ INSTALL_HANDLER (ZeroRead, lutReadAddressWrite, lutReadAddress);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, panelType);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, MODRate);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalTotal);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, horizontalPeriod);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalPeriodStart0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalPeriodStart1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalTotal0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalTotal1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPeriod0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPeriod1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalPeriodStart0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalPeriodStart1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseWidth);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseStart0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseStart1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseWidth);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseStart0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseStart1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, DTFD_GCPIndex);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, DTFD_GCPData);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, displayMode);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, specialEffects);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress2);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mainLineAddressOffset0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, mainLineAddressOffset1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress2);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyLineAddressOffset0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyLineAddressOffset1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartXPosition0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartXPosition1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartYPosition0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartYPosition1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndXPosition0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndXPosition1);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndYPosition0);
+ INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndYPosition1);
+ INSTALL_HANDLER (powerSaveConfigurationRead, StdWriteBE, powerSaveConfiguration);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, SoftwareReset);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, scratchPad0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, scratchPad1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOConfiguration0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOConfiguration1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOStatusControl0);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOStatusControl1);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMClockCVPulseControl);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMClockCVPulseConfig);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, CVPulseBurstLength);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMOutDutyCycle);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsSED1376::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsSED1376::GetAddressStart (void)
+{
+ return fBaseRegsAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsSED1376::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1376::GetLCDScreenOn (void)
+{
+// return ((fRegs.displayMode) & sed1376DisplayBlankMask) == 0;
+ return ((fRegs.GPIOStatusControl0) & hwrDisplayGPIOLCD_ON) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1376::GetLCDBacklightOn (void)
+{
+ return ((fRegs.GPIOStatusControl0) & hwrDisplayGPIOEL_ON) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsSED1376::GetLCDHasFrame (void)
+{
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::invalidateWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::invalidateWrite (emuptr address, int size, uint32 value)
+{
+ this->StdWriteBE (address, size, value);
+ EmScreen::InvalidateAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::powerSaveConfigurationRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsSED1376::powerSaveConfigurationRead (emuptr address, int size)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ // Always set the vertical non-display status high since in the real
+ // hardware, the ROM will check this flag in order to write the CLUT
+ // registers.
+
+ return (fRegs.powerSaveConfiguration) | 0x80;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::lutWriteAddressWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::lutWriteAddressWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ value &= 0x0FF;
+
+ uint8 red = fRegs.lutWriteRed;
+ uint8 green = fRegs.lutWriteGreen;
+ uint8 blue = fRegs.lutWriteBlue;
+
+ fClutData[value] = RGBType ((red & 0xFC) | (red >> 6),
+ (green & 0xFC) | (green >> 6),
+ (blue & 0xFC) | (blue >> 6));
+
+ EmScreen::InvalidateAll ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::lutReadAddressWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::lutReadAddressWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ value &= 0x0FF;
+
+ RGBType rgb = fClutData[value];
+
+ fRegs.lutReadRed = rgb.fRed & 0xFC;
+ fRegs.lutReadGreen = rgb.fGreen & 0xFC;
+ fRegs.lutReadBlue = rgb.fBlue & 0xFC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376::PrvGetPalette (RGBList& thePalette)
+{
+ Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0;
+ int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift);
+ int32 numColors = 1 << bpp;
+
+ thePalette.resize (numColors);
+
+ for (int ii = 0; ii < numColors; ++ii)
+ {
+ if (mono)
+ {
+ uint8 green = fClutData[ii].fGreen;
+ thePalette[ii].fRed = green;
+ thePalette[ii].fGreen = green;
+ thePalette[ii].fBlue = green;
+ }
+ else
+ {
+ thePalette[ii] = fClutData[ii];
+ }
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::EmRegsSED1376VisorPrism
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376VisorPrism::EmRegsSED1376VisorPrism (emuptr baseRegsAddr,
+ emuptr baseVideoAddr) :
+ EmRegsSED1376 (baseRegsAddr, baseVideoAddr)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::~EmRegsSED1376VisorPrism
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376VisorPrism::~EmRegsSED1376VisorPrism (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376VisorPrism::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegsSED1376::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+#undef INSTALL_HANDLER
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsSED1376VisorPrism::read, \
+ (WriteFunction) &EmRegsSED1376VisorPrism::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+ INSTALL_HANDLER (StdReadBE, reservedWrite, reserved);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376VisorPrism::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Get the screen metrics.
+
+ // The hardware is written to in reverse, so the mainStartOffsetX registers
+ // report the END of the frame buffer, not the beginning.
+ emuptr baseAddr = fBaseVideoAddr;
+
+ int32 width = ((fRegs.horizontalPeriod + 1) * 8);
+ int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1;
+ int32 rowBytes = ((width * this->PrvGetLCDDepth ()) / 8);
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376VisorPrism::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+ Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0;
+ Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0;
+ int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift);
+
+ // The hardware is written to in reverse, so the mainStartOffsetX registers
+ // report the END of the frame buffer, not the beginning.
+ emuptr baseAddr = fBaseVideoAddr;
+
+ int32 width = ((fRegs.horizontalPeriod + 1) * 8);
+ int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1;
+ int32 rowBytes = ((width * this->PrvGetLCDDepth ()) / 8);
+
+ info.fLeftMargin = 0;
+
+ if (bpp <= 8)
+ {
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+ }
+ else
+ {
+ // Set depth, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (kPixMapFormat24RGB);
+
+ // Determine first and last scanlines to fetch.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ // Get location and rowBytes of source bytes.
+
+ uint8* srcStart = EmMemGetRealAddress (baseAddr);
+ int32 srcRowBytes = rowBytes;
+ uint8* srcPtr = srcStart + srcRowBytes * info.fFirstLine;
+ uint8* srcPtr0 = srcPtr;
+
+ // Get location and rowBytes of destination bytes.
+
+ uint8* destStart = (uint8*) info.fImage.GetBits ();
+ int32 destRowBytes = info.fImage.GetRowBytes ();
+ uint8* destPtr = destStart + destRowBytes * info.fFirstLine;
+ uint8* destPtr0 = destPtr;
+
+ // Get height of range to copy.
+
+ int32 height = info.fLastLine - info.fFirstLine;
+
+ // Copy the pixels from source to dest.
+
+ for (int yy = 0; yy < height; ++yy)
+ {
+ for (int xx = 0; xx < width; ++xx)
+ {
+ uint8 p1 = EmMemDoGet8 (srcPtr++); // GGGBBBBB
+ uint8 p2 = EmMemDoGet8 (srcPtr++); // RRRRRGGG
+
+ // Merge the two together so that we get RRRRRGGG GGGBBBBB
+
+ uint16 p;
+
+ if (!byteSwapped)
+ p = (p2 << 8) | p1;
+ else
+ p = (p1 << 8) | p2;
+
+ // Shift the bits around, forming RRRRRrrr, GGGGGGgg, and
+ // BBBBBbbb values, where the lower-case bits are copies of
+ // the least significant bits in the upper-case bits.
+ //
+ // Note that all of this could also be done with three 64K
+ // lookup tables. If speed is an issue, we might want to
+ // investigate that.
+
+ if (mono)
+ {
+ uint8 green = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = green;
+ *destPtr++ = green;
+ *destPtr++ = green;
+ }
+ else
+ {
+ *destPtr++ = ((p >> 8) & 0xF8) | ((p >> 11) & 0x07);
+ *destPtr++ = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = ((p << 3) & 0xF8) | ((p >> 0) & 0x07);
+ }
+ }
+
+ srcPtr = srcPtr0 += srcRowBytes;
+ destPtr = destPtr0 += destRowBytes;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::PrvGetLCDDepth
+// ---------------------------------------------------------------------------
+
+int32 EmRegsSED1376VisorPrism::PrvGetLCDDepth (void)
+{
+ UInt8 depth = fRegs.displayMode;
+
+ depth &= sed1376DisplayModeDepthMask;
+
+ switch (depth)
+ {
+ case sed1376DisplayModeDepth16: return 16;
+ case sed1376DisplayModeDepth8: return 8;
+ case sed1376DisplayModeDepth4: return 4;
+ case sed1376DisplayModeDepth2: return 2;
+ case sed1376DisplayModeDepth1: return 1;
+ default: EmAssert (false);
+ }
+
+ return 8;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376VisorPrism::reservedWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376VisorPrism::reservedWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM (address);
+ UNUSED_PARAM (size);
+ UNUSED_PARAM (value);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376PalmGeneric::EmRegsSED1376PalmGeneric
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376PalmGeneric::EmRegsSED1376PalmGeneric (emuptr baseRegsAddr,
+ emuptr baseVideoAddr) :
+ EmRegsSED1376 (baseRegsAddr, baseVideoAddr)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376PalmGeneric::~EmRegsSED1376PalmGeneric
+// ---------------------------------------------------------------------------
+
+EmRegsSED1376PalmGeneric::~EmRegsSED1376PalmGeneric (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376PalmGeneric::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376PalmGeneric::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Get the screen metrics.
+
+// Bool wordSwapped = (fRegs.specialEffects & sed1376WordSwapMask) != 0;
+// Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0;
+// int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift);
+#if !OVERLAY_IS_MAIN
+// int32 width = ((fRegs.horizontalPeriod + 1) * 8);
+ int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1;
+ int32 rowBytes = ((fRegs.mainLineAddressOffset1 << 8) | fRegs.mainLineAddressOffset0) * 4;
+ uint32 offset = (fRegs.mainStartAddress2 << 18) |
+ (fRegs.mainStartAddress1 << 10) |
+ (fRegs.mainStartAddress0 << 2);
+#else
+// int32 left = ((fRegs.ovlyStartXPosition1 << 8) | fRegs.ovlyStartXPosition0) * 32 / bpp;
+// int32 right = ((fRegs.ovlyEndXPosition1 << 8) | fRegs.ovlyEndXPosition0) * 32 / bpp;
+ int32 top = ((fRegs.ovlyStartYPosition1 << 8) | fRegs.ovlyStartYPosition0);
+ int32 bottom = ((fRegs.ovlyEndYPosition1 << 8) | fRegs.ovlyEndYPosition0);
+
+// int32 width = right - left + (32 / bpp);
+ int32 height = bottom - top + 1;
+ int32 rowBytes = ((fRegs.ovlyLineAddressOffset1 << 8) | fRegs.ovlyLineAddressOffset0) * 4;
+ uint32 offset = (fRegs.ovlyStartAddress2 << 18) |
+ (fRegs.ovlyStartAddress1 << 10) |
+ (fRegs.ovlyStartAddress0 << 2);
+#endif
+ emuptr baseAddr = fBaseVideoAddr + offset;
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsSED1376PalmGeneric::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsSED1376PalmGeneric::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+// Bool wordSwapped = (fRegs.specialEffects & sed1376WordSwapMask) != 0;
+ Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0;
+ Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0;
+ int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift);
+#if !OVERLAY_IS_MAIN
+ int32 width = ((fRegs.horizontalPeriod + 1) * 8);
+ int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1;
+ int32 rowBytes = ((fRegs.mainLineAddressOffset1 << 8) | fRegs.mainLineAddressOffset0) * 4;
+ uint32 offset = (fRegs.mainStartAddress2 << 18) |
+ (fRegs.mainStartAddress1 << 10) |
+ (fRegs.mainStartAddress0 << 2);
+#else
+ int32 left = ((fRegs.ovlyStartXPosition1 << 8) | fRegs.ovlyStartXPosition0) * 32 / bpp;
+ int32 right = ((fRegs.ovlyEndXPosition1 << 8) | fRegs.ovlyEndXPosition0) * 32 / bpp;
+ int32 top = ((fRegs.ovlyStartYPosition1 << 8) | fRegs.ovlyStartYPosition0);
+ int32 bottom = ((fRegs.ovlyEndYPosition1 << 8) | fRegs.ovlyEndYPosition0);
+
+ int32 width = right - left + (32 / bpp);
+ int32 height = bottom - top + 1;
+ int32 rowBytes = ((fRegs.ovlyLineAddressOffset1 << 8) | fRegs.ovlyLineAddressOffset0) * 4;
+ uint32 offset = (fRegs.ovlyStartAddress2 << 18) |
+ (fRegs.ovlyStartAddress1 << 10) |
+ (fRegs.ovlyStartAddress0 << 2);
+#endif
+ emuptr baseAddr = fBaseVideoAddr + offset;
+
+ info.fLeftMargin = 0;
+
+ if (bpp <= 8)
+ {
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+ }
+ else
+ {
+ // Set depth, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (kPixMapFormat24RGB);
+
+ // Determine first and last scanlines to fetch.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ // Get location and rowBytes of source bytes.
+
+ uint8* srcStart = EmMemGetRealAddress (baseAddr);
+ int32 srcRowBytes = rowBytes;
+ uint8* srcPtr = srcStart + srcRowBytes * info.fFirstLine;
+ uint8* srcPtr0 = srcPtr;
+
+ // Get location and rowBytes of destination bytes.
+
+ uint8* destStart = (uint8*) info.fImage.GetBits ();
+ int32 destRowBytes = info.fImage.GetRowBytes ();
+ uint8* destPtr = destStart + destRowBytes * info.fFirstLine;
+ uint8* destPtr0 = destPtr;
+
+ // Get height of range to copy.
+
+ int32 height = info.fLastLine - info.fFirstLine;
+
+ // Copy the pixels from source to dest.
+
+ for (int yy = 0; yy < height; ++yy)
+ {
+ for (int xx = 0; xx < width; ++xx)
+ {
+ uint8 p1 = EmMemDoGet8 (srcPtr++); // GGGBBBBB
+ uint8 p2 = EmMemDoGet8 (srcPtr++); // RRRRRGGG
+
+ // Merge the two together so that we get RRRRRGGG GGGBBBBB
+
+ uint16 p;
+
+ if (!byteSwapped)
+ p = (p2 << 8) | p1;
+ else
+ p = (p1 << 8) | p2;
+
+ // Shift the bits around, forming RRRRRrrr, GGGGGGgg, and
+ // BBBBBbbb values, where the lower-case bits are copies of
+ // the least significant bits in the upper-case bits.
+ //
+ // Note that all of this could also be done with three 64K
+ // lookup tables. If speed is an issue, we might want to
+ // investigate that.
+
+ if (mono)
+ {
+ uint8 green = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = green;
+ *destPtr++ = green;
+ *destPtr++ = green;
+ }
+ else
+ {
+ *destPtr++ = ((p >> 8) & 0xF8) | ((p >> 11) & 0x07);
+ *destPtr++ = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03);
+ *destPtr++ = ((p << 3) & 0xF8) | ((p >> 0) & 0x07);
+ }
+ }
+
+ srcPtr = srcPtr0 += srcRowBytes;
+ destPtr = destPtr0 += destRowBytes;
+ }
+ }
+
+ if (!this->GetLCDBacklightOn ())
+ {
+ info.fImage.ChangeTone (-10, info.fFirstLine, info.fLastLine);
+ }
+}
diff --git a/SrcShared/Hardware/EmRegsSED1376.h b/SrcShared/Hardware/EmRegsSED1376.h
new file mode 100644
index 0000000..62a1c56
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSED1376.h
@@ -0,0 +1,106 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsSED1376_h
+#define EmRegsSED1376_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmPalmStructs.h"
+#include "EmRegs.h"
+#include "EmStructs.h" // RGBList
+
+class SessionFile;
+class EmScreenUpdateInfo;
+
+
+#define sed1376RegsAddr (0x1FF80000)
+#define sed1376VideoMemStart (0x1FFA0000)
+#define sed1376VideoMemSize (80 * 1024L)
+
+
+class EmRegsSED1376 : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsSED1376 (emuptr baseRegsAddr,
+ emuptr baseVideoAddr);
+ virtual ~EmRegsSED1376 (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHAL overrides
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end) = 0;
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info) = 0;
+
+ private:
+ uint32 powerSaveConfigurationRead (emuptr address, int size);
+
+ void invalidateWrite (emuptr address, int size, uint32 value);
+ void lutWriteAddressWrite (emuptr address, int size, uint32 value);
+ void lutReadAddressWrite (emuptr address, int size, uint32 value);
+
+ protected:
+ void PrvGetPalette (RGBList& thePalette);
+
+ protected:
+ emuptr fBaseRegsAddr;
+ emuptr fBaseVideoAddr;
+ EmProxySED1376RegsType fRegs;
+ RGBType fClutData[256];
+};
+
+
+class EmRegsSED1376VisorPrism : public EmRegsSED1376
+{
+ public:
+ EmRegsSED1376VisorPrism (emuptr baseRegsAddr,
+ emuptr baseVideoAddr);
+ virtual ~EmRegsSED1376VisorPrism (void);
+
+ virtual void SetSubBankHandlers (void);
+
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ private:
+ void reservedWrite (emuptr address, int size, uint32 value);
+
+ private:
+ int32 PrvGetLCDDepth (void);
+};
+
+
+class EmRegsSED1376PalmGeneric : public EmRegsSED1376
+{
+ public:
+ EmRegsSED1376PalmGeneric (emuptr baseRegsAddr,
+ emuptr baseVideoAddr);
+ virtual ~EmRegsSED1376PalmGeneric (void);
+
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+};
+
+#endif /* EmRegsSED1376_h */
diff --git a/SrcShared/Hardware/EmRegsSZ.cpp b/SrcShared/Hardware/EmRegsSZ.cpp
new file mode 100644
index 0000000..b6b0a96
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSZ.cpp
@@ -0,0 +1,17 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsSZ.h"
+#include "EmRegsSZPrv.h"
+
diff --git a/SrcShared/Hardware/EmRegsSZ.h b/SrcShared/Hardware/EmRegsSZ.h
new file mode 100644
index 0000000..bc4f3b3
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSZ.h
@@ -0,0 +1,18 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsSZ_h
+#define EmRegsSZ_h
+
+
+#endif /* EmRegsSZ_h */
diff --git a/SrcShared/Hardware/EmRegsSZPrv.h b/SrcShared/Hardware/EmRegsSZPrv.h
new file mode 100644
index 0000000..4c9aaa7
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSZPrv.h
@@ -0,0 +1,19 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsSZPrv_h
+#define EmRegsSZPrv_h
+
+
+
+#endif /* EmRegsSZPrv_h */
diff --git a/SrcShared/Hardware/EmRegsSZTemp.cpp b/SrcShared/Hardware/EmRegsSZTemp.cpp
new file mode 100644
index 0000000..7a621bf
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSZTemp.cpp
@@ -0,0 +1,17 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsSZTemp.h"
+#include "EmRegsSZPrv.h"
+
diff --git a/SrcShared/Hardware/EmRegsSZTemp.h b/SrcShared/Hardware/EmRegsSZTemp.h
new file mode 100644
index 0000000..7905540
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsSZTemp.h
@@ -0,0 +1,20 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsSZTemp_h
+#define EmRegsSZTemp_h
+
+#include "EmRegsSZ.h"
+
+
+#endif /* EmRegsSZTemp_h */
diff --git a/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.cpp b/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.cpp
new file mode 100644
index 0000000..20df6e1
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.cpp
@@ -0,0 +1,154 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsUSBPhilipsPDIUSBD12.h"
+
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#undef addressof
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#undef INSTALL_HANDLER
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsUSBPhilipsPDIUSBD12::read, \
+ (WriteFunction) &EmRegsUSBPhilipsPDIUSBD12::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::EmRegsUSBPhilipsPDIUSBD12
+// ---------------------------------------------------------------------------
+
+EmRegsUSBPhilipsPDIUSBD12::EmRegsUSBPhilipsPDIUSBD12 (emuptr baseAddr) :
+ fBaseAddr (baseAddr)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::~EmRegsUSBPhilipsPDIUSBD12
+// ---------------------------------------------------------------------------
+
+EmRegsUSBPhilipsPDIUSBD12::~EmRegsUSBPhilipsPDIUSBD12 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBPhilipsPDIUSBD12::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, data);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, command);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsUSBPhilipsPDIUSBD12::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsUSBPhilipsPDIUSBD12::GetAddressStart (void)
+{
+ return fBaseAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBPhilipsPDIUSBD12::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsUSBPhilipsPDIUSBD12::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
diff --git a/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.h b/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.h
new file mode 100644
index 0000000..71e0b34
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsUSBPhilipsPDIUSBD12.h
@@ -0,0 +1,42 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsUSBPhilipsPDIUSBD12_h
+#define EmRegsUSBPhilipsPDIUSBD12_h
+
+#include "EmRegs.h"
+#include "EmPalmStructs.h" // EmProxyUsbHwrType
+
+class EmRegsUSBPhilipsPDIUSBD12 : public EmRegs
+{
+ public:
+ EmRegsUSBPhilipsPDIUSBD12 (emuptr);
+ virtual ~EmRegsUSBPhilipsPDIUSBD12 (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ private:
+ emuptr fBaseAddr;
+ EmProxyUsbHwrType fRegs;
+};
+
+#endif /* EmRegsUSBPhilipsPDIUSBD12_h */
diff --git a/SrcShared/Hardware/EmRegsUSBVisor.cpp b/SrcShared/Hardware/EmRegsUSBVisor.cpp
new file mode 100644
index 0000000..ccd4c6e
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsUSBVisor.cpp
@@ -0,0 +1,164 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsUSBVisor.h"
+
+#include "EmSession.h" // GetDevice
+#include "EmHAL.h" // EmHAL::GetROMSize
+#include "EmBankROM.h" // EmBankROM::GetMemoryStart
+
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsUSBVisor::read, \
+ (WriteFunction) &EmRegsUSBVisor::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::EmRegsUSBVisor
+// ---------------------------------------------------------------------------
+
+EmRegsUSBVisor::EmRegsUSBVisor (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::~EmRegsUSBVisor
+// ---------------------------------------------------------------------------
+
+EmRegsUSBVisor::~EmRegsUSBVisor (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsUSBVisor::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, data);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, command);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsUSBVisor::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsUSBVisor::GetAddressStart (void)
+{
+ /*
+ Auto-detect USB hardware base address. In the Visor, the USB hardware
+ is at CSA1, which resides just after the ROM (CSA0) in memory.
+ */
+
+ EmDevice device = gSession->GetDevice ();
+ if (device.HardwareID () == 0x0a /*halModelIDVisorPrism*/) // in Prism it is not at CSA1
+ return (emuptr) 0x10800000L;
+
+ return EmBankROM::GetMemoryStart() + EmHAL::GetROMSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsUSBVisor::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsUSBVisor::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
diff --git a/SrcShared/Hardware/EmRegsUSBVisor.h b/SrcShared/Hardware/EmRegsUSBVisor.h
new file mode 100644
index 0000000..0468f39
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsUSBVisor.h
@@ -0,0 +1,44 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsUSBVisor_h
+#define EmRegsUSBVisor_h
+
+#include "EmPalmStructs.h"
+#include "EmRegs.h"
+
+class SessionFile;
+
+
+class EmRegsUSBVisor : public EmRegs
+{
+ public:
+ EmRegsUSBVisor (void);
+ virtual ~EmRegsUSBVisor (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ private:
+ EmProxyUsbHwrType fRegs;
+};
+
+#endif /* EmRegsUSBVisor_h */
diff --git a/SrcShared/Hardware/EmRegsVZ.cpp b/SrcShared/Hardware/EmRegsVZ.cpp
new file mode 100644
index 0000000..f646b5b
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZ.cpp
@@ -0,0 +1,3116 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZ.h"
+#include "EmRegsVZPrv.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmDevice.h"
+#include "EmHAL.h" // EmHAL
+#include "EmMemory.h" // gMemAccessFlags, EmMem_memcpy
+#include "EmPixMap.h" // SetSize, SetRowBytes, etc.
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmSession.h" // gSession
+#include "EmSPISlave.h" // DoExchange
+#include "Hordes.h" // Hordes::IsOn
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // GetHostTime
+#include "PreferenceMgr.h" // Preference
+#include "SessionFile.h" // WriteHwrDBallVZType, etc.
+#include "UAE.h" // regs, SPCFLAG_INT
+
+#include "PalmPack.h"
+#define NON_PORTABLE
+ #include "HwrMiscFlags.h" // hwrMiscFlagID1
+
+ // Some platform-specific -- yet fairly portable -- defines.
+ #define hwrVZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+ #define hwrVZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+ #define hwrVZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+ #define hwrVZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+ #define hwrVZPortDKeyBits 0x0F // All Keyboard Columns
+
+#undef NON_PORTABLE
+#include "PalmPackPop.h"
+
+
+static const uint16 UPSIZMask = 0x1800; // Mask to get the unprotected memory size from csDSelect.
+static const uint16 DRAMMask = 0x0200;
+static const uint16 SIZMask = 0x000E; // Mask to get the memory size from csASelect.
+static const uint16 ENMask = 0x0001; // Mask to get the enable bit from csASelect.
+
+static const int UPSIZShift = 11;
+static const int SIZShift = 1;
+static const int ENShift = 0;
+
+static const uint16 BUPS2Mask = 0x0001;
+static const uint16 CUPS2Mask = 0x0004;
+static const uint16 DUPS2Mask = 0x0010;
+static const uint16 DSIZ3Mask = 0x0040;
+static const uint16 EUPENMask = 0x4000;
+
+static const int BUPS2Shift = 0;
+static const int CUPS2Shift = 2;
+static const int DUPS2Shift = 4;
+
+static const int kBaseAddressShift = 13; // Shift to get base address from CSGBx register value
+
+#define PRINTF if (1) ; else LogAppendMsg
+
+// Values used to initialize the DragonBallVZ registers.
+
+static const HwrM68VZ328Type kInitial68VZ328RegisterValues =
+{
+ 0x1C, // UInt8 scr; // $000: System Control Register
+
+ { 0 }, // UInt8 ___filler0[0x003-0x001];
+
+ 0x00, // UInt8 pcr; // $003: Peripheral Control Register
+ 0x56, // UInt8 chipID; // $004: Chip ID Register
+ 0x01, // UInt8 maskID; // $005: Mask ID Register
+ 0x0000, // UInt16 swID; // $006: Software ID Register
+ 0x1FFF, // UInt16 ioDriveControl; // $008: I/O Drive Control Register
+
+ { 0 }, // UInt8 ___filler1[0x100-0x00A];
+
+ 0x0000, // UInt16 csAGroupBase; // $100: Chip Select Group A Base Register
+ 0x0000, // UInt16 csBGroupBase; // $102: Chip Select Group B Base Register
+ 0x0000, // UInt16 csCGroupBase; // $104: Chip Select Group C Base Register
+ 0x0000, // UInt16 csDGroupBase; // $106: Chip Select Group D Base Register
+
+ 0x0000, // UInt16 csUGroupBase; // $108: Chip Select Upper Group Base Register
+
+ 0x0000, // UInt16 csControl1; // $10A: Chip Select Control Register
+ 0x0000, // UInt16 csControl2; // $10C: Chip Select Control Register
+
+ { 0 }, // UInt8 ___filler2[0x110-0x10c];
+
+ 0x00B0, // UInt16 csASelect; // $110: Group A Chip Select Register
+ 0x0000, // UInt16 csBSelect; // $112: Group B Chip Select Register
+ 0x0000, // UInt16 csCSelect; // $114: Group C Chip Select Register
+ 0x0200, // UInt16 csDSelect; // $116: Group D Chip Select Register
+
+ 0x0060, // UInt16 emuCS; // $118: EMU Chip Select Register
+
+ { 0 }, // UInt8 ___filler3[0x200-0x11A];
+
+ 0x0000, // UInt16 csControl3; // $150: Chip Select Control Register
+
+ { 0 }, // UInt8 ___filler3[0x200-0x11A];
+
+ 0x24B3, // UInt16 pllControl; // $200: PLL Control Register
+ 0x0123, // UInt16 pllFreqSel; // $202: CGM Frequency Select Register
+
+ { 0 }, // UInt8 ___filler4[0x207-0x204];
+
+ 0x1F, // UInt8 pwrControl; // $207: Power Control Register
+
+ { 0 }, // UInt8 ___filler5[0x300-0x208];
+
+ 0x00, // UInt8 intVector; // $300: Interrupt Vector Register
+ 0x00, // UInt8 ___filler6;
+ 0x0000, // UInt16 intControl; // $302: Interrupt Control Register
+ 0x00FF, // UInt16 intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ 0xFFFF, // UInt16 intMaskLo; // $306: Interrupt Mask Register/LOW word
+ { 0 }, // UInt8 ___filler7[0x30c-0x308];
+ 0x0000, // UInt16 intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ 0x0000, // UInt16 intStatusLo; // $30E: Interrupt Status Register/LOW word
+ 0x0000, // UInt16 intPendingHi; // $310: Interrupt Pending Register/HIGH word
+ 0x0000, // UInt16 intPendingLo; // $312: Interrupt Pending Register/LOW word
+ 0x6533, // UInt16 intLevelControl; // $314: Interrupt Level Control Register
+
+ { 0 }, // UInt8 ___filler4a[0x400-0x316];
+
+ 0x00, // UInt8 portADir; // $400: Port A Direction Register
+ 0x00, // UInt8 portAData; // $401: Port A Data Register
+ 0xFF, // UInt8 portAPullupEn; // $402: Port A Pullup Enable
+
+ { 0 }, // UInt8 ___filler8[5];
+
+ 0x00, // UInt8 portBDir; // $408: Port B Direction Register
+ 0x00, // UInt8 portBData; // $409: Port B Data Register
+ 0xFF, // UInt8 portBPullupEn; // $40A: Port B Pullup Enable
+ 0xFF, // UInt8 portBSelect; // $40B: Port B Select Register
+
+ { 0 }, // UInt8 ___filler9[4];
+
+ 0x00, // UInt8 portCDir; // $410: Port C Direction Register
+ 0x00, // UInt8 portCData; // $411: Port C Data Register
+ 0xFF, // UInt8 portCPulldnEn; // $412: Port C Pulldown Enable
+ 0xFF, // UInt8 portCSelect; // $413: Port C Select Register
+
+ { 0 }, // UInt8 ___filler10[4];
+
+ 0x00, // UInt8 portDDir; // $418: Port D Direction Register
+ 0x00, // UInt8 portDData; // $419: Port D Data Register
+ 0xFF, // UInt8 portDPullupEn; // $41A: Port D Pull-up Enable
+ 0xFF, // UInt8 portDSelect; // $41B: Port D Select Register
+ 0x00, // UInt8 portDPolarity; // $41C: Port D Polarity Register
+ 0x00, // UInt8 portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ 0x00, // UInt8 portDKbdIntEn; // $41E: Port D Keyboard Interrupt Enable
+ 0x00, // UInt8 portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ 0x00, // UInt8 portEDir; // $420: Port E Direction Register
+ 0x00, // UInt8 portEData; // $421: Port E Data Register
+ 0xFF, // UInt8 portEPullupEn; // $422: Port E Pull-up Enable
+ 0xFF, // UInt8 portESelect; // $423: Port E Select Register
+
+ { 0 }, // UInt8 ___filler14[4];
+
+ 0x00, // UInt8 portFDir; // $428: Port F Direction Register
+ 0x00, // UInt8 portFData; // $429: Port F Data Register
+ 0xFF, // UInt8 portFPullupdnEn; // $42A: Port F Pull-up/down Enable
+ 0x8F, // UInt8 portFSelect; // $42B: Port F Select Register
+
+ { 0 }, // UInt8 ___filler16[4];
+
+ 0x00, // UInt8 portGDir; // $430: Port G Direction Register
+ 0x00, // UInt8 portGData; // $431: Port G Data Register
+ 0x3D, // UInt8 portGPullupEn; // $432: Port G Pull-up Enable
+ 0x08, // UInt8 portGSelect; // $433: Port G Select Register
+
+ { 0 }, // UInt8 ___filler17[0x438-0x434];
+
+ 0x00, // UInt8 portJDir; // $438: Port J Direction Register
+ 0x00, // UInt8 portJData; // $439: Port J Data Register
+ 0xFF, // UInt8 portJPullupEn; // $43A: Port J Pull-up Enable
+ 0xEF, // UInt8 portJSelect; // $43B: Port J Select Register
+
+ { 0 }, // UInt8 ___filler18[0x440-0x43C];
+
+ 0x00, // UInt8 portKDir; // $440: Port K Direction Register
+ 0x00, // UInt8 portKData; // $441: Port K Data Register
+ 0xFF, // UInt8 portKPullupdnEn; // $442: Port K Pull-up/down Enable
+ 0xFF, // UInt8 portKSelect; // $443: Port K Select Register
+
+ { 0 }, // UInt8 ___filler19[0x448-0x444];
+
+ 0x00, // UInt8 portMDir; // $448: Port M Direction Register
+ 0x00, // UInt8 portMData; // $449: Port M Data Register
+ 0x3F, // UInt8 portMPullupdnEn; // $44A: Port M Pull-up/down Enable
+ 0x3F, // UInt8 portMSelect; // $44B: Port M Select Register
+
+ { 0 }, // UInt8 ___filler20[0x500-0x44C];
+
+ 0x0020, // UInt16 pwmControl; // $500: PWM 1 Control Register (PWM 1 is the same as the single PWM in EZ)
+ 0x00, // UInt8 pwmSampleHi; // $502: PWM 1 Sample - high byte
+ 0x00, // UInt8 pwmSampleLo; // $503: PWM 1 Sample - low byte
+ 0xFE, // UInt8 pwmPeriod; // $504: PWM 1 Period
+ 0x00, // UInt8 pwmCounter; // $505: PWM 1 Counter
+
+ { 0 }, // UInt8 ___filler22[0x510-0x506];
+
+ 0x0000, // UInt16 pwm2Control; // $510: PWM 2 Control Register
+ 0x0000, // UInt16 pwm2Period; // $512: PWM 2 Period
+ 0x0000, // UInt16 pwm2Width; // $514: PWM 2 Width
+ 0x0000, // UInt16 pwm2Counter; // $516: PWM 2 Counter
+
+ { 0 }, // UInt8 ___filler23[0x600-0x518];
+
+ 0x0000, // UInt16 tmr1Control; // $600: Timer 1 Control Register
+ 0x0000, // UInt16 tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ 0xFFFF, // UInt16 tmr1Compare; // $604: Timer 1 Compare Register
+ 0x0000, // UInt16 tmr1Capture; // $606: Timer 1 Capture Register
+ 0x0000, // UInt16 tmr1Counter; // $608: Timer 1 Counter Register
+ 0x0000, // UInt16 tmr1Status; // $60A: Timer 1 Status Register
+
+ { 0 }, // UInt8 ___filler24[0x610-0x60C];
+
+ 0x0000, // UInt16 tmr2Control; // $610: Timer 2 Control Register
+ 0x0000, // UInt16 tmr2Prescaler; // $612: Timer 2 Prescaler Register
+ 0xFFFF, // UInt16 tmr2Compare; // $614: Timer 2 Compare Register
+ 0x0000, // UInt16 tmr2Capture; // $616: Timer 2 Capture Register
+ 0x0000, // UInt16 tmr2Counter; // $618: Timer 2 Counter Register
+ 0x0000, // UInt16 tmr2Status; // $61A: Timer 2 Status Register
+
+ { 0 }, // UInt8 ___filler25[0x700-0x61C];
+
+ 0x0000, // UInt16 spiRxD; // $700: SPI Unit 1 Receive Data Register
+ 0x0000, // UInt16 spiTxD; // $702: SPI Unit 1 Transmit Data Register
+ 0x0000, // UInt16 spiCont1; // $704: SPI Unit 1 Control/Status Register
+ 0x0000, // UInt16 spiIntCS; // $706: SPI Unit 1 Interrupt control/Status Register
+ 0x0000, // UInt16 spiTest; // $708: SPI Unit 1 Test Register
+ 0x0000, // UInt16 spiSpc; // $70A: SPI Unit 1 Sample period counter register
+
+ { 0 }, // UInt8 ___filler26[0x800-0x706];
+
+ 0x0000, // UInt16 spiMasterData; // $800: SPI Unit 2 Data Register (SPI 2 is the same as the single SPI Master in EZ)
+ 0x0000, // UInt16 spiMasterControl; // $802: SPI Unit 2 Control/Status Register
+
+ { 0 }, // UInt8 ___filler27[0x900-0x804];
+
+ 0x0000, // UInt16 uControl; // $900: Uart 1 Status/Control Register (Uart 1 is the same as the single Uart in EZ)
+ 0x003F, // UInt16 uBaud; // $902: Uart 1 Baud Control Register
+ 0x0000, // UInt16 uReceive; // $904: Uart 1 Receive Register
+ 0x0000, // UInt16 uTransmit; // $906: Uart 1 Transmit Register
+ 0x0000, // UInt16 uMisc; // $908: Uart 1 Miscellaneous Register
+ 0x0000, // UInt16 uNonIntPresc; // $90A: Uart 1 Non-Integer Prescaler
+
+ { 0 }, // UInt8 ___filler28[0x910-0x90C];
+
+ 0x0000, // UInt16 u2Control; // $910: Uart 2 Status/Control Register
+ 0x003F, // UInt16 u2Baud; // $912: Uart 2 Baud Control Register
+ 0x0000, // UInt16 u2Receive; // $914: Uart 2 Receiver Register
+ 0x0000, // UInt16 u2Transmit; // $916: Uart 2 Transmitter Register
+ 0x0000, // UInt16 u2Misc; // $918: Uart 2 Miscellaneous Register
+ 0x0000, // UInt16 u2NonIntPresc; // $91A: Uart 2 Non-Integer Prescaler
+ 0x0000, // UInt16 u2FIFOHMark; // $91C: Uart 2 Half Mark FIFO Register
+
+ { 0 }, // UInt8 ___filler28a[0xA00-0x91E];
+
+ 0x00000000, // UInt32 lcdStartAddr; // $A00: Screen Starting Address Register
+ { 0 }, // UInt8 ___filler29;
+ 0xFF, // UInt8 lcdPageWidth; // $A05: Virtual Page Width Register
+ { 0 }, // UInt8 ___filler30[2];
+ 0x03F0, // UInt16 lcdScreenWidth; // $A08: Screen Width Register
+ 0x01FF, // UInt16 lcdScreenHeight; // $A0A: Screen Height Register
+ { 0 }, // UInt8 ___filler31[0xA18-0xA0C];
+ 0x0000, // UInt16 lcdCursorXPos; // $A18: Cursor X Position
+ 0x0000, // UInt16 lcdCursorYPos; // $A1A: Cursor Y Position
+ 0x0101, // UInt16 lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ { 0 }, // UInt8 ___filler32;
+ 0x7F, // UInt8 lcdBlinkControl; // $A1F: Blink Control Register
+ 0x00, // UInt8 lcdPanelControl; // $A20: Panel Interface Configuration Register
+ 0x00, // UInt8 lcdPolarity; // $A21: Polarity Config Register
+ { 0 }, // UInt8 ___filler33;
+ 0x00, // UInt8 lcdACDRate; // $A23: ACD (M) Rate Control Register
+ { 0 }, // UInt8 ___filler34;
+ 0x00, // UInt8 lcdPixelClock; // $A25: Pixel Clock Divider Register
+ { 0 }, // UInt8 ___filler35;
+ 0x00, // UInt8 lcdClockControl; // $A27: Clocking Control Register
+ 0x00FF, // UInt16 lcdRefreshRateAdj; // $A28: Refresh Rate Adjustment Register
+ { 0 }, // UInt8 ___filler37;
+ 0x00, // UInt8 lcdReserved1; // $A2B: Reserved
+ { 0 }, // UInt8 ___filler38;
+ 0x00, // UInt8 lcdPanningOffset; // $A2D: Panning Offset Register
+
+ { 0 }, // UInt8 ___filler39[0xA31-0xA2E];
+
+ 0x00, // UInt8 lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ { 0 }, // UInt8 ___filler2004;
+ 0x84, // UInt8 lcdGrayPalette; // $A33: Gray Palette Mapping Register
+ 0x00, // UInt8 lcdReserved2; // $A34: Reserved
+ { 0 }, // UInt8 ___filler2005;
+ 0x0000, // UInt16 lcdContrastControlPWM; // $A36: Contrast Control
+ 0x00, // UInt8 lcdRefreshModeControl; // $A38: Refresh Mode Control Register
+ 0x62, // UInt8 lcdDMAControl; // $A39: DMA Control Register
+
+ { 0 }, // UInt8 ___filler40[0xB00-0xA3a];
+
+ 0x00000000, // UInt32 rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ 0x00000000, // UInt32 rtcAlarm; // $B04: RTC Alarm Register
+ { 0 }, // UInt8 ___filler2001[0xB0A-0xB08];
+ 0x0001, // UInt16 rtcWatchDog; // $B0A: RTC Watchdog Timer
+ 0x0080, // UInt16 rtcControl; // $B0C: RTC Control Register
+ 0x0000, // UInt16 rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ 0x0000, // UInt16 rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ 0x003F, // UInt16 stopWatch; // $B12: Stopwatch Minutes
+ { 0 }, // UInt8 ___filler2002[0xB1A-0xB14];
+ 0x0000, // UInt16 rtcDay; // $B1A: RTC Day
+ 0x0000, // UInt16 rtcDayAlarm; // $B1C: RTC Day Alarm
+
+ { 0 }, // UInt8 ___filler41[0xC00-0xB1E];
+
+ 0x0000, // UInt16 dramConfig; // $C00: DRAM Memory Config Register
+ 0x003C, // UInt16 dramControl; // $C02: DRAM Control Register
+ 0x0000, // UInt16 sdramControl; // $C04: SDRAM Control Register
+ 0x0000, // UInt16 sdramPwDn; // $C06: SDRAM Power Down Register
+
+ { 0 }, // UInt8 ___filler42[0xD00-0xC08];
+
+ 0x00000000, // UInt32 emuAddrCompare; // $D00: Emulation Address Compare Register
+ 0x00000000, // UInt32 emuAddrMask; // $D04: Emulation Address Mask Register
+ 0x0000, // UInt16 emuControlCompare; // $D08: Emulation Control Compare Register
+ 0x0000, // UInt16 emuControlMask; // $D0A: Emulation Control Mask Register
+ 0x0000, // UInt16 emuControl; // $DOC: Emulation Control Register
+ 0x0000 // UInt16 emuStatus; // $D0E: Emulation Status Register
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::EmRegsVZ
+// ---------------------------------------------------------------------------
+
+EmRegsVZ::EmRegsVZ (void) :
+ EmRegs (),
+ f68VZ328Regs (),
+ fHotSyncButtonDown (0),
+ fKeyBits (0),
+ fLastTmr1Status (0),
+ fLastTmr2Status (0),
+ fPortDEdge (0),
+ fPortDDataCount (0),
+ fHour (0),
+ fMin (0),
+ fSec (0),
+ fTick (0),
+ fCycle (0)
+{
+ fUART[0] = NULL;
+ fUART[1] = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::~EmRegsVZ
+// ---------------------------------------------------------------------------
+
+EmRegsVZ::~EmRegsVZ (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::Initialize (void)
+{
+ EmRegs::Initialize ();
+
+ fUART[0] = new EmUARTDragonball (EmUARTDragonball::kUART_DragonballVZ, 0);
+ fUART[1] = new EmUARTDragonball (EmUARTDragonball::kUART_DragonballVZ, 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+ if (hardwareReset)
+ {
+
+ f68VZ328Regs = kInitial68VZ328RegisterValues;
+
+ // Byteswap all the words in the DragonballVZ registers (if necessary).
+
+ Canonical (f68VZ328Regs);
+ ByteswapWords (&f68VZ328Regs, sizeof(f68VZ328Regs));
+
+ fKeyBits = 0;
+ fLastTmr1Status = 0;
+ fLastTmr2Status = 0;
+ fPortDEdge = 0;
+ fPortDDataCount = 0;
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegsVZ::UARTStateChanged (sendTxData, 0);
+ EmRegsVZ::UARTStateChanged (sendTxData, 1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+
+ StWordSwapper swapper (&f68VZ328Regs, sizeof(f68VZ328Regs));
+ f.WriteHwrDBallVZType (f68VZ328Regs);
+ f.FixBug (SessionFile::kBugByteswappedStructs);
+
+ const long kCurrentVersion = 3;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ s << fHotSyncButtonDown;
+ s << fKeyBits;
+ s << fLastTmr1Status;
+ s << fLastTmr2Status;
+ s << fPortDEdge;
+
+
+ // Added in version 2.
+
+ s << fHour;
+ s << fMin;
+ s << fSec;
+ s << fTick;
+ s << fCycle;
+
+ // Added in version 3.
+
+ s << fPortDDataCount;
+
+ f.WriteDBallVZState (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+
+ if (f.ReadHwrDBallVZType (f68VZ328Regs))
+ {
+ // The Windows version of Poser 2.1d29 and earlier did not write
+ // out structs in the correct format. The fields of the struct
+ // were written out in Little-Endian format, not Big-Endian. To
+ // address this problem, the bug has been fixed, and a new field
+ // is added to the file format indicating that the bug has been
+ // fixed. With the new field (the "bug bit"), Poser can identify
+ // old files from new files and read them in accordingly.
+ //
+ // With the bug fixed, the .psf files should now be interchangeable
+ // across platforms (modulo other bugs...).
+
+ if (!f.IncludesBugFix (SessionFile::kBugByteswappedStructs))
+ {
+ Canonical (f68VZ328Regs);
+ }
+ ByteswapWords (&f68VZ328Regs, sizeof(f68VZ328Regs));
+
+ // React to the new data in the UART registers.
+
+ Bool sendTxData = false;
+ EmRegsVZ::UARTStateChanged (sendTxData, 0);
+ EmRegsVZ::UARTStateChanged (sendTxData, 1);
+
+ // Reset gMemAccessFlags.fProtect_SRAMSet
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csDSelect) & 0x2000) != 0;
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+
+ Chunk chunk;
+ if (f.ReadDBallVZState (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> fHotSyncButtonDown;
+ s >> fKeyBits;
+ s >> fLastTmr1Status;
+ s >> fLastTmr2Status;
+ s >> fPortDEdge;
+ }
+
+ if (version >= 2)
+ {
+ s >> fHour;
+ s >> fMin;
+ s >> fSec;
+ s >> fTick;
+ s >> fCycle;
+ }
+
+ if (version >= 3)
+ {
+ s >> fPortDDataCount;
+ }
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::Dispose (void)
+{
+ delete fUART[0]; fUART[0] = NULL;
+ delete fUART[1]; fUART[1] = NULL;
+
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdRead, StdWrite, scr);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pcr);
+ INSTALL_HANDLER (StdRead, NullWrite, chipID);
+ INSTALL_HANDLER (StdRead, NullWrite, maskID);
+ INSTALL_HANDLER (StdRead, NullWrite, swID);
+ INSTALL_HANDLER (StdRead, StdWrite, ioDriveControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csAGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csBGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csCGroupBase);
+ INSTALL_HANDLER (StdRead, StdWrite, csDGroupBase);
+
+ INSTALL_HANDLER (StdRead, StdWrite, csUGroupBase);
+
+ INSTALL_HANDLER (StdRead, csControl1Write, csControl1);
+ INSTALL_HANDLER (StdRead, StdWrite, csControl2);
+ INSTALL_HANDLER (StdRead, StdWrite, csControl3);
+
+ INSTALL_HANDLER (StdRead, csASelectWrite, csASelect);
+ INSTALL_HANDLER (StdRead, StdWrite, csBSelect);
+ INSTALL_HANDLER (StdRead, StdWrite, csCSelect);
+ INSTALL_HANDLER (StdRead, csDSelectWrite, csDSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, emuCS);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pllControl);
+ INSTALL_HANDLER (pllFreqSelRead, StdWrite, pllFreqSel);
+ INSTALL_HANDLER (StdRead, StdWrite, pwrControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, intVector);
+ INSTALL_HANDLER (StdRead, StdWrite, intControl);
+ INSTALL_HANDLER (StdRead, intMaskHiWrite, intMaskHi);
+ INSTALL_HANDLER (StdRead, intMaskLoWrite, intMaskLo);
+ INSTALL_HANDLER (StdRead, intStatusHiWrite, intStatusHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intStatusLo);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingHi);
+ INSTALL_HANDLER (StdRead, NullWrite, intPendingLo);
+ INSTALL_HANDLER (StdRead, StdWrite, intLevelControl);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portADir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portAData);
+ INSTALL_HANDLER (StdRead, StdWrite, portAPullupEn);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portBDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portBData);
+ INSTALL_HANDLER (StdRead, StdWrite, portBPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portBSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portCDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portCData);
+ INSTALL_HANDLER (StdRead, StdWrite, portCPulldnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portCSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portDDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portDData);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDSelect);
+ INSTALL_HANDLER (StdRead, StdWrite, portDPolarity);
+ INSTALL_HANDLER (StdRead, portDIntReqEnWrite, portDIntReqEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDKbdIntEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portDIntEdge);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portEDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portEData);
+ INSTALL_HANDLER (StdRead, StdWrite, portEPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portESelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portFDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portFData);
+ INSTALL_HANDLER (StdRead, StdWrite, portFPullupdnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portFSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portGDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portGData);
+ INSTALL_HANDLER (StdRead, StdWrite, portGPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portGSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portJDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portJData);
+ INSTALL_HANDLER (StdRead, StdWrite, portJPullupEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portJSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portKDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portKData);
+ INSTALL_HANDLER (StdRead, StdWrite, portKPullupdnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portKSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, portMDir);
+ INSTALL_HANDLER (portXDataRead, portXDataWrite, portMData);
+ INSTALL_HANDLER (StdRead, StdWrite, portMPullupdnEn);
+ INSTALL_HANDLER (StdRead, StdWrite, portMSelect);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pwmControl);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmSampleHi);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmSampleLo);
+ INSTALL_HANDLER (StdRead, StdWrite, pwmPeriod);
+ INSTALL_HANDLER (StdRead, NullWrite, pwmCounter);
+
+ INSTALL_HANDLER (StdRead, StdWrite, pwm2Control);
+ INSTALL_HANDLER (StdRead, StdWrite, pwm2Period);
+ INSTALL_HANDLER (StdRead, StdWrite, pwm2Width);
+ INSTALL_HANDLER (StdRead, NullWrite, pwm2Counter);
+
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Control);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Prescaler);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Compare);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr1Capture);
+ INSTALL_HANDLER (StdRead, NullWrite, tmr1Counter);
+ INSTALL_HANDLER (tmr1StatusRead, tmr1StatusWrite, tmr1Status);
+
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Control);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Prescaler);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Compare);
+ INSTALL_HANDLER (StdRead, StdWrite, tmr2Capture);
+ INSTALL_HANDLER (StdRead, NullWrite, tmr2Counter);
+ INSTALL_HANDLER (tmr2StatusRead, tmr2StatusWrite, tmr2Status);
+
+ INSTALL_HANDLER (StdRead, StdWrite, spiRxD);
+ INSTALL_HANDLER (StdRead, StdWrite, spiTxD);
+ INSTALL_HANDLER (StdRead, spiCont1Write, spiCont1);
+ INSTALL_HANDLER (StdRead, StdWrite, spiIntCS);
+ INSTALL_HANDLER (StdRead, StdWrite, spiTest);
+ INSTALL_HANDLER (StdRead, StdWrite, spiSpc);
+
+ INSTALL_HANDLER (StdRead, StdWrite, spiMasterData);
+ INSTALL_HANDLER (StdRead, spiMasterControlWrite, spiMasterControl);
+
+ INSTALL_HANDLER (uart1Read, uart1Write, uControl);
+ INSTALL_HANDLER (uart1Read, uart1Write, uBaud);
+ INSTALL_HANDLER (uart1Read, uart1Write, uReceive);
+ INSTALL_HANDLER (uart1Read, uart1Write, uTransmit);
+ INSTALL_HANDLER (uart1Read, uart1Write, uMisc);
+ INSTALL_HANDLER (uart1Read, uart1Write, uNonIntPresc);
+
+ INSTALL_HANDLER (uart2Read, uart2Write, u2Control);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2Baud);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2Receive);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2Transmit);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2Misc);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2NonIntPresc);
+ INSTALL_HANDLER (uart2Read, uart2Write, u2FIFOHMark);
+
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdStartAddr);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPageWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenWidth);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdScreenHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorXPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorYPos);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdCursorWidthHeight);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdBlinkControl);
+ INSTALL_HANDLER (StdRead, lcdRegisterWrite, lcdPanelControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPolarity);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdACDRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPixelClock);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdClockControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdRefreshRateAdj);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdPanningOffset);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdFrameRate);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdGrayPalette);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdContrastControlPWM);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdRefreshModeControl);
+ INSTALL_HANDLER (StdRead, StdWrite, lcdDMAControl);
+
+ INSTALL_HANDLER (rtcHourMinSecRead, StdWrite, rtcHourMinSec);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcAlarm);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcWatchDog);
+ INSTALL_HANDLER (StdRead, rtcControlWrite, rtcControl);
+ INSTALL_HANDLER (StdRead, rtcIntStatusWrite, rtcIntStatus);
+ INSTALL_HANDLER (StdRead, rtcIntEnableWrite, rtcIntEnable);
+ INSTALL_HANDLER (StdRead, StdWrite, stopWatch);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcDay);
+ INSTALL_HANDLER (StdRead, StdWrite, rtcDayAlarm);
+
+ INSTALL_HANDLER (StdRead, StdWrite, dramConfig);
+ INSTALL_HANDLER (StdRead, StdWrite, dramControl);
+ INSTALL_HANDLER (StdRead, StdWrite, sdramControl);
+ INSTALL_HANDLER (StdRead, StdWrite, sdramPwDn);
+
+ INSTALL_HANDLER (StdRead, StdWrite, emuAddrCompare);
+ INSTALL_HANDLER (StdRead, StdWrite, emuAddrMask);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControlCompare);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControlMask);
+ INSTALL_HANDLER (StdRead, StdWrite, emuControl);
+ INSTALL_HANDLER (StdRead, StdWrite, emuStatus);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsVZ::GetRealAddress (emuptr address)
+{
+ uint8* loc = ((uint8*) &f68VZ328Regs) + (address - kMemoryStart);
+
+ return loc;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsVZ::GetAddressStart (void)
+{
+ return kMemoryStart;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::GetAddressRange (void)
+{
+ return kMemorySize;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::Cycle
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+void EmRegsVZ::Cycle (Bool sleeping)
+{
+#if _DEBUG
+ #define increment 20
+#else
+ #define increment 4
+#endif
+
+ // ===== Handle Timer 1 =====
+
+ // Determine whether timer is enabled.
+
+ if ((READ_REGISTER (tmr1Control) & hwrVZ328TmrControlEnable) != 0)
+ {
+ // If so, increment the timer.
+
+ WRITE_REGISTER (tmr1Counter, READ_REGISTER (tmr1Counter) + (sleeping ? 1 : increment));
+
+ // Determine whether the timer has reached the specified count.
+
+ if (sleeping || READ_REGISTER (tmr1Counter) > READ_REGISTER (tmr1Compare))
+ {
+ // Flag the occurrence of the successful comparison.
+
+ WRITE_REGISTER (tmr1Status, READ_REGISTER (tmr1Status) | hwrVZ328TmrStatusCompare);
+
+ // If the Free Run/Restart flag is not set, clear the counter.
+
+ if ((READ_REGISTER (tmr1Control) & hwrVZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr1Counter, 0);
+ }
+
+ // If the timer interrupt is enabled, post an interrupt.
+
+ if ((READ_REGISTER (tmr1Control) & hwrVZ328TmrControlEnInterrupt) != 0)
+ {
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwrVZ328IntLoTimer);
+ EmRegsVZ::UpdateInterrupts ();
+ }
+ }
+ }
+
+ // ===== Handle Timer 2 =====
+ // ===== (Same code, just the name have been changed) =====
+
+ // Determine whether timer is enabled.
+
+#if 1
+ if ((READ_REGISTER (tmr2Control) & hwrVZ328TmrControlEnable) != 0)
+ {
+ // Divide by the prescale amount. We do this by decrementing
+ // a prescaler counter. Only when this counter reaches zero
+ // do we increment the timer counter.
+
+ static int prescaleCounter;
+
+ if ((prescaleCounter -= (sleeping ? (increment * 1024) : increment)) <= 0)
+ {
+ prescaleCounter = READ_REGISTER (tmr2Prescaler) * 1024;
+
+ // If so, increment the timer.
+
+ WRITE_REGISTER (tmr2Counter, READ_REGISTER (tmr2Counter) + (sleeping ? 1 : increment));
+
+ // Determine whether the timer has reached the specified count.
+
+ if (sleeping || READ_REGISTER (tmr2Counter) > READ_REGISTER (tmr2Compare))
+ {
+ // Flag the occurrence of the successful comparison.
+
+ WRITE_REGISTER (tmr2Status, READ_REGISTER (tmr2Status) | hwrVZ328TmrStatusCompare);
+
+ // If the Free Run/Restart flag is not set, clear the counter.
+
+ if ((READ_REGISTER (tmr2Control) & hwrVZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr2Counter, 0);
+ }
+
+ // If the timer interrupt is enabled, post an interrupt.
+
+ if ((READ_REGISTER (tmr2Control) & hwrVZ328TmrControlEnInterrupt) != 0)
+ {
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | hwrVZ328IntLoTimer2);
+ EmRegsVZ::UpdateInterrupts ();
+ }
+ }
+ }
+ }
+#endif
+
+ // ===== Handle time increment (used when running Gremlins) =====
+
+ if ((fCycle += increment) > READ_REGISTER (tmr1Compare))
+ {
+ fCycle = 0;
+
+ if (++fTick >= 100)
+ {
+ fTick = 0;
+
+ if (++fSec >= 60)
+ {
+ fSec = 0;
+
+ if (++fMin >= 60)
+ {
+ fMin = 0;
+
+ if (++fHour >= 24)
+ {
+ fHour = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::CycleSlowly
+// ---------------------------------------------------------------------------
+// Handles periodic events that need to occur when the processor cycles (like
+// updating timer registers). This function is called in two places from
+// Emulator::Execute. Interestingly, the loop runs 3% FASTER if this function
+// is in its own separate function instead of being inline.
+
+void EmRegsVZ::CycleSlowly (Bool sleeping)
+{
+ UNUSED_PARAM(sleeping)
+
+ // See if a hard button is pressed.
+
+ EmAssert (gSession);
+ if (gSession->HasButtonEvent ())
+ {
+ EmButtonEvent event = gSession->GetButtonEvent ();
+ if (event.fButton == kElement_CradleButton)
+ {
+ EmRegsVZ::HotSyncEvent (event.fButtonIsDown);
+ }
+ else
+ {
+ EmRegsVZ::ButtonEvent (event.fButton, event.fButtonIsDown);
+ }
+ }
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegsVZ::UpdateUARTState (false, 0);
+ EmRegsVZ::UpdateUARTState (false, 1);
+
+ // Check to see if the RTC alarm is ready to go off. First see
+ // if the RTC is enabled, and that the alarm event isn't already
+ // registered (the latter check is just an optimization).
+
+ if ((READ_REGISTER (rtcIntEnable) & hwrVZ328RTCIntEnableAlarm) != 0 &&
+ (READ_REGISTER (rtcIntStatus) & hwrVZ328RTCIntStatusAlarm) == 0)
+ {
+ uint32 rtcAlarm = READ_REGISTER (rtcAlarm);
+
+ long almHour = (rtcAlarm & hwrVZ328RTCAlarmHoursMask) >> hwrVZ328RTCAlarmHoursOffset;
+ long almMin = (rtcAlarm & hwrVZ328RTCAlarmMinutesMask) >> hwrVZ328RTCAlarmMinutesOffset;
+ long almSec = (rtcAlarm & hwrVZ328RTCAlarmSecondsMask) >> hwrVZ328RTCAlarmSecondsOffset;
+ long almInSeconds = (almHour * 60 * 60) + (almMin * 60) + almSec;
+
+ long nowHour;
+ long nowMin;
+ long nowSec;
+ ::GetHostTime (&nowHour, &nowMin, &nowSec);
+ long nowInSeconds = (nowHour * 60 * 60) + (nowMin * 60) + nowSec;
+
+ if (almInSeconds <= nowInSeconds)
+ {
+ WRITE_REGISTER (rtcIntStatus, READ_REGISTER (rtcIntStatus) | hwrVZ328RTCIntStatusAlarm);
+ EmRegsVZ::UpdateRTCInterrupts ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::TurnSoundOff
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::TurnSoundOff (void)
+{
+ uint16 pwmControl = READ_REGISTER (pwmControl);
+ WRITE_REGISTER (pwmControl, pwmControl & ~hwrVZ328PWMControlEnable);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::ResetTimer
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::ResetTimer (void)
+{
+ WRITE_REGISTER (tmr1Counter, 0);
+ WRITE_REGISTER (tmr2Counter, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::ResetRTC
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::ResetRTC (void)
+{
+ fHour = 15;
+ fMin = 0;
+ fSec = 0;
+ fTick = 0;
+ fCycle = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZ::GetInterruptLevel (void)
+{
+ /*
+ From the DragonBall VZ manual, Chapter 9:
+
+ * EMUIRQ or hardware breakpoint interrupt (level 7)
+
+ * IRQ6 external interrupt (level 6)
+ * Timer unit 1 (level 6)
+ * Timer unit 2 (configurable from level 1 to 6)
+ * Pulse-width modulator unit 1 (level 6)
+ * Pulse-width modulator unit 2 (configurable from level 1 to 6)
+
+ * IRQ5 external interrupt-pen (level 5)
+
+ * Serial peripheral interface unit 1 (configurable from level 1 to 6)
+ * Serial peripheral interface unit 2 (level 4)
+ * UART unit 1 (level 4)
+ * UART unit 2 (configurable from level 1 to 6)
+ * Software watchdog timer interrupt (level 4)
+ * Real-time clock (level 4)
+ * Real-time interrupt (level 4)
+ * Keyboard interrupt (level 4)
+ * General-purpose interrupt INT[3:0] (level 4)-these pins can be
+ used as keyboard interrupts
+
+ * IRQ3 external interrupt (level 3)
+ * IRQ2 external interrupt (level 2)
+ * IRQ1 external interrupt (level 1)
+ */
+
+ static int8 intLevel[32] =
+ {
+ 4, // 0x00 - hwrVZ328IntLoSPIM
+ 6, // 0x01 - hwrVZ328IntLoTimer
+ 4, // 0x02 - hwrVZ328IntLoUART
+ 4, // 0x03 - hwrVZ328IntLoWDT
+ 4, // 0x04 - hwrVZ328IntLoRTC
+ 0, // 0x05 - hwrVZ328IntLoTimer2 (configurable - 3 by default, reprogrammed to level 6)
+ 4, // 0x06 - hwrVZ328IntLoKbd
+ 6, // 0x07 - hwrVZ328IntLoPWM
+
+ 4, // 0x08 - hwrVZ328IntLoInt0
+ 4, // 0x09 - hwrVZ328IntLoInt1
+ 4, // 0x0A - hwrVZ328IntLoInt2
+ 4, // 0x0B - hwrVZ328IntLoInt3
+ 0, // 0x0C - hwrVZ328IntLoUART2 (configurable - 5 by default, reprogrammed to level 4)
+ 0, // 0x0D - PWM2 (configurable - 3 by default)
+ -2, // 0x0E - <Unused>
+ -2, // 0x0F - <Unused>
+
+ 1, // 0x10 - hwrVZ328IntHiIRQ1
+ 2, // 0x11 - hwrVZ328IntHiIRQ2
+ 3, // 0x12 - hwrVZ328IntHiIRQ3
+ 6, // 0x13 - hwrVZ328IntHiIRQ6
+ 5, // 0x14 - hwrVZ328IntHiPen
+ 0, // 0x15 - SPI1 (configurable - 6 by default)
+ 4, // 0x16 - hwrVZ328IntHiSampleTimer
+ 7, // 0x17 - hwrVZ328IntHiEMU
+
+ -2, // 0x18 - <Unused>
+ -2, // 0x19 - <Unused>
+ -2, // 0x1A - <Unused>
+ -2, // 0x1B - <Unused>
+ -2, // 0x1C - <Unused>
+ -2, // 0x1D - <Unused>
+ -2, // 0x1E - <Unused>
+ -2 // 0x1F - <Unused>
+ };
+
+ // Load in the configurable interrupt levels.
+
+ uint16 intLevelControl = READ_REGISTER (intLevelControl);
+
+ intLevel[0x15] = (intLevelControl >> 12) & 0x000F;
+ intLevel[0x0C] = (intLevelControl >> 8) & 0x000F;
+ intLevel[0x0D] = (intLevelControl >> 4) & 0x000F;
+ intLevel[0x05] = (intLevelControl >> 0) & 0x000F;
+
+ // !!! HACK: Skywalker sets the interrupt level to zero in order
+ // to clear it out before setting it to six. Zero is not allowed,
+ // so mask the problem by replacing it with six.
+
+ if (intLevel[0x05] == 0)
+ intLevel[0x05] = 6;
+
+#ifndef NDEBUG
+ for (int ii = 0; ii < 32; ++ii)
+ {
+ EmAssert (intLevel[ii] != 0);
+ EmAssert (intLevel[ii] != 7 || ii == 0x17);
+ }
+#endif
+
+ // Find the highest interrupt level.
+
+ int8 result = -1;
+ int index = 0;
+
+ uint16 intStatusHi = READ_REGISTER (intStatusHi);
+ uint16 intStatusLo = READ_REGISTER (intStatusLo);
+ uint32 intStatus = (((uint32) intStatusHi) << 16) | intStatusLo;
+
+ while (intStatus)
+ {
+ if (intStatus & 1)
+ {
+ // Make sure no undefined bits are set.
+ EmAssert (intLevel[index] >= 0);
+
+ if (result < intLevel[index])
+ {
+ result = intLevel[index];
+ }
+ }
+
+ intStatus >>= 1;
+ index++;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetInterruptBase
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZ::GetInterruptBase (void)
+{
+ return READ_REGISTER (intVector) & 0xF8;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZ::GetLCDHasFrame (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+ int rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ int height = READ_REGISTER (lcdScreenHeight) + 1;
+
+ begin = baseAddr;
+ end = baseAddr + rowBytes * height;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Get the screen metrics.
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x03);
+ int32 width = READ_REGISTER (lcdScreenWidth);
+ int32 height = READ_REGISTER (lcdScreenHeight) + 1;
+ int32 rowBytes = READ_REGISTER (lcdPageWidth) * 2;
+ emuptr baseAddr = READ_REGISTER (lcdStartAddr);
+
+ info.fLeftMargin = READ_REGISTER (lcdPanningOffset) & 0x0F;
+
+ EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 :
+ bpp == 2 ? kPixMapFormat2 :
+ bpp == 4 ? kPixMapFormat4 :
+ kPixMapFormat8;
+
+ RGBList colorTable;
+ this->PrvGetPalette (colorTable);
+
+ // Set format, size, and color table of EmPixMap.
+
+ info.fImage.SetSize (EmPoint (width, height));
+ info.fImage.SetFormat (format);
+ info.fImage.SetRowBytes (rowBytes);
+ info.fImage.SetColorTable (colorTable);
+
+ // Determine first and last scanlines to fetch, and fetch them.
+
+ info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes;
+ info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1;
+
+ long firstLineOffset = info.fFirstLine * rowBytes;
+ long lastLineOffset = info.fLastLine * rowBytes;
+
+ EmMem_memcpy (
+ (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset),
+ baseAddr + firstLineOffset,
+ lastLineOffset - firstLineOffset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetDynamicHeapSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZ::GetDynamicHeapSize (void)
+{
+ int32 result = 0;
+
+ uint16 csControl = READ_REGISTER (csControl1);
+ uint16 csDSelect = READ_REGISTER (csDSelect);
+
+ uint16 csDUPSIZ = (csDSelect & UPSIZMask) >> UPSIZShift;
+ uint16 csDSIZ = (csDSelect & SIZMask) >> SIZShift;
+
+ if ((csControl & EUPENMask) != 0)
+ {
+ // Unprotected size = Chip-select Size/2^(7-upsize)
+
+ // Determine upsize.
+
+ // Merge in the extended bit. UPSIZ contains [1:0]. The bit
+ // in DUPS2 extends this to [2:0].
+
+ csDUPSIZ |= ((csControl & DUPS2Mask) >> DUPS2Shift) << 2;
+
+ // Determine Chip-select Size.
+
+ long chip_select_size = (32 * 1024L) << csDSIZ;
+
+ if ((csControl & DSIZ3Mask) != 0 &&
+ (csDSelect & DRAMMask) != 0 &&
+ csDSIZ <= 0x01)
+ {
+ chip_select_size = (8 * 1024L * 1024L) << csDSIZ;
+ }
+
+ result = chip_select_size / (1 << (7 - csDUPSIZ));
+ }
+ else
+ {
+ result = (32 * 1024L) << csDUPSIZ;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZ::GetROMSize (void)
+{
+ /*
+ SIZ Chip-Select Size
+
+ This field determines the memory range of the chip-select. For CSA
+ and CSB, chip-select size is between 128K and 16M. For CSC and CSD,
+ chip-select size is between 32K and 4M.
+
+ 000 = 128K (32K for CSC and CSD).
+ 001 = 256K (64K for CSC and CSD).
+ 010 = 512K (128K for CSC and CSD).
+ 011 = 1M (256K for CSC and CSD).
+ 100 = 2M (512K for CSC and CSD).
+ 101 = 4M (1M for CSC and CSD).
+ 110 = 8M (2M for CSC and CSD).
+ 111 = 16M (4M for CSC and CSD).
+ */
+
+ uint16 csASelect = READ_REGISTER (csASelect);
+ uint32 result = (128 * 1024L) << ((csASelect & SIZMask) >> SIZShift);
+
+ if ((csASelect & ENMask) == 0)
+ {
+ result = 16 * 1024L * 1024L;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetROMBaseAddress
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::GetROMBaseAddress (void)
+{
+ /*
+ csAGroupBase: Chip-select Group Base Address register
+
+ The csAGroupBase register stores the base address (bits 14-28 of
+ the address) in the top 15 bits. The low bit is always zero.
+ Shifting this value by 13 gives the ROM base address.
+
+ E.g: If the base address is 0x10C00000, then csAGroupBase will
+ contain 0x10C00000 >> 13 (base 10) = 0x8600.
+
+ If the enable bit of the CSA register is low, the chip selects
+ have not yet been set up. In this case, return an invalid value.
+ */
+
+ if (!this->ChipSelectsConfigured())
+ {
+ return 0xFFFFFFFF;
+ }
+
+ uint16 csAGroupBase = READ_REGISTER (csAGroupBase);
+ uint32 result = csAGroupBase << kBaseAddressShift;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::ChipSelectsConfigured
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZ::ChipSelectsConfigured (void)
+{
+ return READ_REGISTER (csASelect) & ENMask;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetSystemClockFrequency
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZ::GetSystemClockFrequency (void)
+{
+ uint16 pllControl = READ_REGISTER (pllControl);
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel);
+
+ // Convert the 32.768KHz clock (CLK32) into the PLLCLK frequency.
+
+ uint16 PC = (pllFreqSel & 0x00FF);
+ uint16 QC = (pllFreqSel & 0x0F00) >> 8;
+
+ uint32 result = 32768L * 2 * (14 * (PC + 1) + QC + 1);
+
+ // Divide by the first prescaler, if needed.
+
+ if ((pllControl & hwrVZ328PLLControlPreSc1Div2) != 0)
+ {
+ result /= 2;
+ }
+
+ // Divide by the second prescaler, if needed.
+
+ if ((pllControl & hwrVZ328PLLControlPreSc2Div2) != 0)
+ {
+ result /= 2;
+ }
+
+ // Divide by the system clock scaler, if needed.
+
+ switch (pllControl & 0x0F00)
+ {
+ case hwrVZ328PLLControlSysDMADiv2:
+ result /= 2;
+ break;
+
+ case hwrVZ328PLLControlSysDMADiv4:
+ result /= 4;
+ break;
+
+ case hwrVZ328PLLControlSysDMADiv8:
+ result /= 8;
+ break;
+
+ case hwrVZ328PLLControlSysDMADiv16:
+ result /= 16;
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetCanStop
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZ::GetCanStop (void)
+{
+ // Make sure Timer is enabled or the RTC interrupt is enabled.
+
+ if ((READ_REGISTER (tmr1Control) & hwrVZ328TmrControlEnable) != 0)
+ return true;
+
+ if ((READ_REGISTER (tmr2Control) & hwrVZ328TmrControlEnable) != 0)
+ return true;
+
+ if ((READ_REGISTER (rtcIntEnable) & hwrVZ328RTCIntEnableAlarm) != 0)
+ return true;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetAsleep
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZ::GetAsleep (void)
+{
+ return ((READ_REGISTER (pllControl) & hwrVZ328PLLControlDisable) != 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZ::GetPortInputValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'D')
+ {
+ result = this->GetPortInternalValue (port);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZ::GetPortInternalValue (int port)
+{
+ uint8 result = 0;
+
+ if (port == 'D')
+ {
+ // Get the INT bits that need to be set.
+
+ result = this->GetKeyBits ();
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::PortDataChanged
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::PortDataChanged (int port, uint8, uint8 newValue)
+{
+ if (port == 'D')
+ {
+ // Clear the interrupt bits that are having a 1 written to them.
+ // Only clear them if they're configured as edge-senstive.
+
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+ PRINTF ("EmRegsVZ::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+ PRINTF ("EmRegsVZ::PortDataChanged (D): portDIntEdge = 0x%02lX", (uint32) (uint8) portDIntEdge);
+ PRINTF ("EmRegsVZ::PortDataChanged (D): newValue = 0x%02lX", (uint32) (uint8) newValue);
+
+ fPortDEdge &= ~(newValue & portDIntEdge);
+
+ PRINTF ("EmRegsVZ::PortDataChanged (D): fPortDEdge = 0x%02lX", (uint32) (uint8) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegsVZ::UpdatePortDInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::pllFreqSelRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::pllFreqSelRead (emuptr address, int size)
+{
+ // Simulate the rising and falling of the CLK32 signal so that functions
+ // like HwrPreRAMInit, HwrShutDownPLL, PrvSetPLL, and PrvShutDownPLL
+ // won't hang.
+
+ uint16 pllFreqSel = READ_REGISTER (pllFreqSel) ^ 0x8000;
+ WRITE_REGISTER (pllFreqSel, pllFreqSel);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::portXDataRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::portXDataRead (emuptr address, int)
+{
+ // The value read can come from three different places:
+ //
+ // - the value what was written to the data register
+ // - any dedicated inputs
+ // - any GPIO inputs
+ //
+ // The value returned depends on the settings of the SEL and DIR
+ // registers. So let's get those settings, the values from the three
+ // input sources, and build up a return value based on those.
+
+ int port = GetPort (address);
+
+ uint8 sel = StdRead (address + 2, 1);
+ uint8 dir = StdRead (address - 1, 1);
+ uint8 output = StdRead (address + 0, 1);
+ uint8 input = EmHAL::GetPortInputValue (port);
+ uint8 intFn = EmHAL::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ sel |= 0x0F; // No "select" bit in low nybble, so set for IO values.
+
+ // The system will poll portD 18 times in KeyBootKeys to see
+ // if any keys are down. Wait at least that long before
+ // letting up any boot keys maintained by the session. When we
+ // do call ReleaseBootKeys, set our counter to -1 as a flag not
+ // to call it any more.
+
+ if (fPortDDataCount != 0xFFFFFFFF && ++fPortDDataCount >= 18 * 2)
+ {
+ fPortDDataCount = 0xFFFFFFFF;
+ gSession->ReleaseBootKeys ();
+ }
+ }
+
+ // Use the internal chip function bits if the "sel" bits are zero.
+
+ intFn &= ~sel;
+
+ // Otherwise, use the I/O bits.
+
+ output &= sel & dir; // Use the output bits if the "dir" is one.
+ input &= sel & ~dir; // Use the input bits if the "dir" is zero.
+
+ // Assert that there are no overlaps.
+
+ EmAssert ((output & input) == 0);
+ EmAssert ((output & intFn) == 0);
+ EmAssert ((input & intFn) == 0);
+
+ // Mush everything together.
+
+ uint8 result = output | input | intFn;
+
+ // If this is port D, flip the bits if the POLARITY register says to.
+ // (!!! Does this inversion apply only to input bits? That is, the
+ // bits where the "dir" register has 0 bits?)
+
+ if (0 && port == 'D')
+ {
+ uint8 polarity = READ_REGISTER (portDPolarity);
+ PRINTF ("EmRegsVZ::portXDataRead: polarity = 0x%02lX", (uint32) polarity);
+ result ^= polarity;
+ }
+
+ PRINTF ("EmRegsVZ::port%cDataRead: sel dir output input intFn result", (char) port);
+ PRINTF ("EmRegsVZ::port%cDataRead: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (char) port, (uint32) sel, (uint32) dir, (uint32) output, (uint32) input, (uint32) intFn, (uint32) result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::tmr1StatusRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::tmr1StatusRead (emuptr address, int size)
+{
+ uint16 tmr1Counter = READ_REGISTER (tmr1Counter) + 16;
+ uint16 tmr1Compare = READ_REGISTER (tmr1Compare);
+ uint16 tmr1Control = READ_REGISTER (tmr1Control);
+
+ // Increment the timer.
+
+ WRITE_REGISTER (tmr1Counter, tmr1Counter);
+
+ // If the timer has passed the specified value...
+
+ if ((tmr1Counter - tmr1Compare) < 16)
+ {
+ // Set the flag saying the timer timed out.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status) | hwrVZ328TmrStatusCompare;
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ // If it's not a free-running timer, reset it to zero.
+
+ if ((tmr1Control & hwrVZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr1Counter, 0);
+ }
+ }
+
+ // Remember this guy for later (see EmRegsVZ::tmr1StatusWrite())
+
+ fLastTmr1Status |= READ_REGISTER (tmr1Status);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::tmr2StatusRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::tmr2StatusRead (emuptr address, int size)
+{
+ uint16 tmr2Counter = READ_REGISTER (tmr2Counter) + 16;
+ uint16 tmr2Compare = READ_REGISTER (tmr2Compare);
+ uint16 tmr2Control = READ_REGISTER (tmr2Control);
+
+ // Increment the timer.
+
+ WRITE_REGISTER (tmr2Counter, tmr2Counter);
+
+ // If the timer has passed the specified value...
+
+ if ((tmr2Counter - tmr2Compare) < 16)
+ {
+ // Set the flag saying the timer timed out.
+
+ uint16 tmr2Status = READ_REGISTER (tmr2Status) | hwrVZ328TmrStatusCompare;
+ WRITE_REGISTER (tmr2Status, tmr2Status);
+
+ // If it's not a free-running timer, reset it to zero.
+
+ if ((tmr2Control & hwrVZ328TmrControlFreeRun) == 0)
+ {
+ WRITE_REGISTER (tmr2Counter, 0);
+ }
+ }
+
+ // Remember this guy for later (see EmRegsVZ::tmr2StatusWrite())
+
+ fLastTmr2Status |= READ_REGISTER (tmr2Status);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::uart1Read
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::uart1Read (emuptr address, int size)
+{
+ // If this is a full read, get the next byte from the FIFO.
+
+ Bool refreshRxData = (address == addressof (uReceive)) && (size == 2);
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegsVZ::UpdateUARTState (refreshRxData, 0);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::uart2Read
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::uart2Read (emuptr address, int size)
+{
+ // If this is a full read, get the next byte from the FIFO.
+
+ Bool refreshRxData = (address == addressof (u2Receive)) && (size == 2);
+
+ // See if there's anything new ("Put the data on the bus")
+
+ EmRegsVZ::UpdateUARTState (refreshRxData, 1);
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::rtcHourMinSecRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsVZ::rtcHourMinSecRead (emuptr address, int size)
+{
+ // Get the desktop machine's time.
+
+ long hour, min, sec;
+
+ if (Hordes::IsOn ())
+ {
+ hour = fHour;
+ min = fMin;
+ sec = fSec;
+ }
+ else
+ {
+ ::GetHostTime (&hour, &min, &sec);
+ }
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcHourMinSec, (hour << hwrVZ328RTCHourMinSecHoursOffset)
+ | (min << hwrVZ328RTCHourMinSecMinutesOffset)
+ | (sec << hwrVZ328RTCHourMinSecSecondsOffset));
+
+ // Finish up by doing a standard read.
+
+ return EmRegsVZ::StdRead (address, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::csControl1Write
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::csControl1Write (emuptr address, int size, uint32 value)
+{
+ // Get the current value.
+
+ uint16 csControl = READ_REGISTER (csControl1);
+
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Check to see if the unprotected memory range changed.
+
+ const uint16 bits = EUPENMask | DSIZ3Mask | DUPS2Mask;
+
+ if ((csControl & bits) != (READ_REGISTER (csControl1) & bits))
+ {
+ EmAssert (gSession);
+
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::csASelectWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::csASelectWrite (emuptr address, int size, uint32 value)
+{
+ // Get the current value.
+
+ uint16 csASelect = READ_REGISTER (csASelect);
+
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csASelect & SIZMask) != (READ_REGISTER (csASelect) & SIZMask))
+ {
+ EmAssert (gSession);
+
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::csDSelectWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::csDSelectWrite (emuptr address, int size, uint32 value)
+{
+ // Get the current value.
+
+ uint16 csDSelect = READ_REGISTER (csDSelect);
+
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Check its new state and update our ram-protect flag.
+
+ gMemAccessFlags.fProtect_SRAMSet = (READ_REGISTER (csDSelect) & 0x2000) != 0;
+
+ // Check to see if the unprotected memory range changed.
+
+ if ((csDSelect & UPSIZMask) != (READ_REGISTER (csDSelect) & UPSIZMask))
+ {
+ EmAssert (gSession);
+
+ gSession->ScheduleResetBanks ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::intMaskHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::intMaskHiWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::intMaskLoWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::intMaskLoWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::intStatusHiWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::intStatusHiWrite (emuptr address, int size, uint32 value)
+{
+ // IRQ1, IRQ2, IRQ3, IRQ6 and IRQ7 are cleared by writing to their
+ // respective status bits. We handle those there. Since there are
+ // no interrupt status bits like this in intStatusLo, we don't need
+ // a handler for that register; we only handle intStatusHi.
+
+ // Even though this is a 16-bit register as defined by the Palm headers,
+ // it's a 32-bit register according to DragonballVZ docs, and is in fact
+ // accessed that way in the kernal files (cf. HwrIRQ4Handler). In those
+ // cases, we're still only interested in access to the IRQ# bits, so we
+ // can turn 4-byte accesses into 2-byte accesses.
+
+ if (size == 4)
+ value >>= 16;
+
+ // Take into account the possibility of 1-byte accesses, too. If we're
+ // accessing the upper byte, just return. If we're accessing the lower
+ // byte, we can treat it as a 2-byte access.
+
+ else if (size == 1 && address == addressof (intStatusHi))
+ return;
+
+ // Now we can treat the rest of this function as a word-write to intStatusHi.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ // For each interrupt:
+ // If we're writing to that interrupt's status bit and its edge bit is set:
+ // - clear the interrupt's pending bit
+ // - respond to the new interrupt state.
+
+ #undef CLEAR_PENDING_INTERRUPT
+ #define CLEAR_PENDING_INTERRUPT(edge, irq) \
+ if ((READ_REGISTER (intControl) & edge) && (value & (irq))) \
+ { \
+ intPendingHi &= ~(irq); \
+ }
+
+ CLEAR_PENDING_INTERRUPT (hwrVZ328IntCtlEdge1, hwrVZ328IntHiIRQ1);
+ CLEAR_PENDING_INTERRUPT (hwrVZ328IntCtlEdge2, hwrVZ328IntHiIRQ2);
+ CLEAR_PENDING_INTERRUPT (hwrVZ328IntCtlEdge3, hwrVZ328IntHiIRQ3);
+ CLEAR_PENDING_INTERRUPT (hwrVZ328IntCtlEdge6, hwrVZ328IntHiIRQ6);
+
+ // IRQ7 is not edge-programmable, so clear it if we're merely writing to it.
+ // !!! Double check this for VZ!
+
+ if (value & hwrVZ328IntHiEMU)
+ {
+ intPendingHi &= ~(hwrVZ328IntHiEMU);
+ }
+
+ // If we're emulating the user pressing the hotsync button, make sure the
+ // interrupt stays asserted. (!!! Should we use the same technique for
+ // other buttons, too? It doesn't seem to be needed right now, but doing
+ // that may more closely mirror the hardware.)
+
+ if (fHotSyncButtonDown)
+ {
+ intPendingHi |= hwrVZ328IntHiIRQ1;
+ }
+ else
+ {
+ intPendingHi &= ~hwrVZ328IntHiIRQ1;
+ }
+
+ // This makes the power on key work. If the signal is asserted, the
+ // unit will not transition between asleep and awake (cf. HwrSleep, HwrWake).
+
+ intPendingHi &= ~hwrVZ328IntHiIRQ6;
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::portXDataWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::portXDataWrite (emuptr address, int size, uint32 value)
+{
+ // Get the old value before updating it.
+
+ uint8 oldValue = StdRead (address, size);
+
+ // Take a snapshot of the line driver states.
+
+ Bool driverStates[kUARTEnd];
+ EmHAL::GetLineDriverStates (driverStates);
+
+ // Take a snapshot of the DTR pin.
+
+ Bool dtrOn = EmHAL::GetDTR (1);
+
+ // Now update the value with a standard write.
+
+ StdWrite (address, size, value);
+
+ // Let anyone know that it's changed.
+
+ int port = GetPort (address);
+ PRINTF ("EmRegsVZ::port%cDataWrite: oldValue = 0x%02lX", (char) port, (uint32) (uint8) oldValue);
+ PRINTF ("EmRegsVZ::port%cDataWrite: newValue = 0x%02lX", (char) port, (uint32) (uint8) value);
+
+ EmHAL::PortDataChanged (port, oldValue, value);
+
+ // Respond to any changes in the line driver states.
+
+ EmHAL::CompareLineDriverStates (driverStates);
+
+ // Respond to any change in the DTR pin.
+
+ if (EmHAL::GetDTR (1) != dtrOn)
+ {
+ EmHAL::DTRChanged (1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::portDIntReqEnWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::portDIntReqEnWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Set the new interrupt state.
+
+ EmRegsVZ::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::tmr1StatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::tmr1StatusWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ EmAssert (size == 2); // This function's a hell of a lot easier to write if
+ // we assume only full-register access.
+
+ // Get the current value.
+
+ uint16 tmr1Status = READ_REGISTER (tmr1Status);
+
+ // If the user had previously read the status bits while they
+ // were set, then it's OK for them to be clear now. Otherwise,
+ // we have to merge any set status bits back in.
+
+ tmr1Status &= value | ~fLastTmr1Status; // fLastTmr1Status was set in EmRegsVZ::tmr1StatusRead()
+
+ WRITE_REGISTER (tmr1Status, tmr1Status);
+
+ fLastTmr1Status = 0;
+ if ((tmr1Status & hwrVZ328TmrStatusCompare) == 0)
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwrVZ328IntLoTimer;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::tmr2StatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::tmr2StatusWrite (emuptr address, int size, uint32 value)
+{
+ UNUSED_PARAM(address)
+ UNUSED_PARAM(size)
+
+ EmAssert (size == 2); // This function's a hell of a lot easier to write if
+ // we assume only full-register access.
+
+ // Get the current value.
+
+ uint16 tmr2Status = READ_REGISTER (tmr2Status);
+
+ // If the user had previously read the status bits while they
+ // were set, then it's OK for them to be clear now. Otherwise,
+ // we have to merge any set status bits back in.
+
+ tmr2Status &= value | ~fLastTmr2Status; // fLastTmr2Status was set in EmRegsVZ::tmr2StatusRead()
+
+ WRITE_REGISTER (tmr2Status, tmr2Status);
+
+ fLastTmr2Status = 0;
+ if ((tmr2Status & hwrVZ328TmrStatusCompare) == 0)
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwrVZ328IntLoTimer2;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::spiCont1Write
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::spiCont1Write (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Get the current value.
+
+ uint16 spiCont1 = READ_REGISTER (spiCont1);
+
+ // Check to see if data exchange and enable are enabled.
+
+ #define BIT_MASK (hwrVZ328SPIMControlExchange | hwrVZ328SPIMControlEnable)
+ if ((spiCont1 & BIT_MASK) == BIT_MASK)
+ {
+ // Clear the exchange bit.
+
+ spiCont1 &= ~hwrVZ328SPIMControlExchange;
+
+ WRITE_REGISTER (spiCont1, spiCont1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::spiMasterControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::spiMasterControlWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Get the current value.
+
+ uint16 spiMasterData = READ_REGISTER (spiMasterData);
+ uint16 spiMasterControl = READ_REGISTER (spiMasterControl);
+
+ // Check to see if data exchange and enable are enabled.
+
+ #define BIT_MASK (hwrVZ328SPIMControlExchange | hwrVZ328SPIMControlEnable)
+ if ((spiMasterControl & BIT_MASK) == BIT_MASK)
+ {
+ // If the SPI is hooked up to something, talk with it.
+
+ EmSPISlave* spiSlave = this->GetSPISlave ();
+ if (spiSlave)
+ {
+ // Write out the old data, read in the new data.
+
+ uint16 newData = spiSlave->DoExchange (spiMasterControl, spiMasterData);
+
+ // Shift in the new data.
+
+ uint16 numBits = (spiMasterControl & hwrVZ328SPIMControlBitsMask) + 1;
+
+ uint16 oldBitsMask = ~0 << numBits;
+ uint16 newBitsMask = ~oldBitsMask;
+
+ spiMasterData = /*((spiMasterData << numBits) & oldBitsMask) | */
+ (newData & newBitsMask);
+
+ WRITE_REGISTER (spiMasterData, spiMasterData);
+ }
+
+ // Assert the interrupt and clear the exchange bit.
+
+ spiMasterControl |= hwrVZ328SPIMControlIntStatus;
+ spiMasterControl &= ~hwrVZ328SPIMControlExchange;
+
+ WRITE_REGISTER (spiMasterControl, spiMasterControl);
+
+ // If hwrVZ328SPIMControlIntEnable is set, trigger an interrupt.
+
+ if ((spiMasterControl & hwrVZ328SPIMControlIntEnable) != 0)
+ {
+ uint16 intPendingLo = READ_REGISTER (intPendingLo);
+ intPendingLo |= hwrVZ328IntLoSPIM;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+ this->UpdateInterrupts ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::uart1Write
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::uart1Write(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // If this write included the TX_DATA field, signal that it needs to
+ // be transmitted.
+
+ Bool sendTxData =
+ ((address == addressof (uTransmit)) && (size == 2)) ||
+ ((address == addressof (uTransmit) + 1) && (size == 1));
+
+ // React to any changes.
+
+ EmRegsVZ::UARTStateChanged (sendTxData, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::uart2Write
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::uart2Write(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // If this write included the TX_DATA field, signal that it needs to
+ // be transmitted.
+
+ Bool sendTxData =
+ ((address == addressof (u2Transmit)) && (size == 2)) ||
+ ((address == addressof (u2Transmit) + 1) && (size == 1));
+
+ // React to any changes.
+
+ EmRegsVZ::UARTStateChanged (sendTxData, 1);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::lcdRegisterWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::lcdRegisterWrite (emuptr address, int size, uint32 value)
+{
+ // First, get the old value in case we need to see what changed.
+
+ uint32 oldValue = EmRegsVZ::StdRead (address, size);
+
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Note what changed.
+
+ if (address == addressof (lcdScreenWidth))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdScreenHeight))
+ {
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPanelControl))
+ {
+ // hwrVZ328LcdPanelControlGrayScale is incorrectly defined as 0x01,
+ // so use the hard-coded value of 0x03 here.
+
+// if (((value ^ oldValue) & hwrVZ328LcdPanelControlGrayScale) != 0)
+ if (((value ^ oldValue) & 0x03) != 0)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+ else if (address == addressof (lcdStartAddr))
+ {
+ // Make sure the low-bit is always zero.
+ // Make sure bits 31-29 are always zero.
+
+ uint32 lcdStartAddr = READ_REGISTER (lcdStartAddr) & 0x1FFFFFFE;
+ WRITE_REGISTER (lcdStartAddr, lcdStartAddr);
+
+ EmScreen::InvalidateAll ();
+ }
+ else if (address == addressof (lcdPageWidth))
+ {
+ if (value != oldValue)
+ {
+ EmScreen::InvalidateAll ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::rtcControlWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::rtcControlWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::rtcIntStatusWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::rtcIntStatusWrite (emuptr address, int size, uint32 value)
+{
+ // Status bits are cleared by writing ones to them.
+
+ // If we're doing a byte-write to the upper byte, shift the byte
+ // so that we can treat the operation as a word write. If we're
+ // doing a byte-write to the lower byte, this extension will happen
+ // automatically.
+
+ if (address == addressof (rtcIntStatus) && size == 1)
+ value <<= 8;
+
+ // Get the current value.
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+
+ // Clear the requested bits.
+
+ rtcIntStatus &= ~value;
+
+ // Update the register.
+
+ WRITE_REGISTER (rtcIntStatus, rtcIntStatus);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::rtcIntEnableWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::rtcIntEnableWrite (emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateRTCInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::ButtonEvent
+// ---------------------------------------------------------------------------
+// Handles a Palm device button event by updating the appropriate registers.
+
+void EmRegsVZ::ButtonEvent (SkinElementType button, Bool buttonIsDown)
+{
+ uint16 bitNumber = this->ButtonToBits (button);
+
+ // Get the bits that should have been set with the previous set
+ // of pressed keys. We use this old value to update the port D interrupts.
+
+ uint8 oldBits = this->GetKeyBits ();
+
+ // Update the set of keys that are currently pressed.
+
+ if (buttonIsDown)
+ {
+ fKeyBits |= bitNumber; // Remember the key bit
+ }
+ else
+ {
+ fKeyBits &= ~bitNumber; // Forget the key bit
+ }
+
+ // Now get the new set of bits that should be set.
+
+ uint8 newBits = this->GetKeyBits ();
+
+ PRINTF ("EmRegsVZ::ButtonEvent: fKeyBits = 0x%04lX", (uint32) fKeyBits);
+ PRINTF ("EmRegsVZ::ButtonEvent: oldBits = 0x%02lX", (uint32) oldBits);
+ PRINTF ("EmRegsVZ::ButtonEvent: newBits = 0x%02lX", (uint32) newBits);
+
+ // Set the interrupt bits for the bits that went from off to on.
+ // These get cleared when portDData is written to.
+
+ fPortDEdge |= newBits & ~oldBits;
+
+ PRINTF ("EmRegsVZ::ButtonEvent: fPortDEdge = 0x%02lX", (uint32) fPortDEdge);
+
+ // Set the new interrupt state.
+
+ EmRegsVZ::UpdatePortDInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::HotSyncEvent
+// ---------------------------------------------------------------------------
+// Handles a HotSync button event by updating the appropriate registers.
+
+void EmRegsVZ::HotSyncEvent (Bool buttonIsDown)
+{
+ // If the button changes state, set or clear the HotSync interrupt.
+
+ uint16 intPendingHi = READ_REGISTER (intPendingHi);
+
+ if (buttonIsDown)
+ {
+ intPendingHi |= hwrVZ328IntHiIRQ1;
+ fHotSyncButtonDown = true;
+ }
+ else
+ {
+ intPendingHi &= ~hwrVZ328IntHiIRQ1;
+ fHotSyncButtonDown = false;
+ }
+
+ WRITE_REGISTER (intPendingHi, intPendingHi);
+
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetKeyBits
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZ::GetKeyBits (void)
+{
+ // "Keys" (that is, buttons) are read from the Port D Data register.
+ // There are 7 or 8 keys that can be pressed, but only 4 bits are
+ // available in the Port D Data register for reporting pressed keys.
+ // Therefore, the keys are organized into a matrix, one row or which
+ // can be requested and reported at a time. This function determines
+ // what row is being requested, and sets the appropriate Port D Data
+ // bits for the keys are are currently pressed.
+
+ int numRows;
+ int numCols;
+ uint16 keyMap[16];
+ Bool rows[4];
+
+ this->GetKeyInfo (&numRows, &numCols, keyMap, rows);
+
+ uint8 keyData = 0;
+
+ // Walk the rows, looking for one that is requested.
+
+ for (int row = 0; row < numRows; ++row)
+ {
+ if (rows[row])
+ {
+ // Walk the columns, looking for ones that have a pressed key.
+
+ for (int col = 0; col < numCols; ++col)
+ {
+ // Get the key corresponding to this row and column.
+ // If we've recorded (in fKeyBits) that this key is
+ // pressed, then set its column bit.
+
+ uint16 key = keyMap[row * numCols + col];
+ if ((key & fKeyBits) != 0)
+ {
+ keyData |= (1 << col);
+ }
+ }
+ }
+ }
+
+ return keyData;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::ButtonToBits
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsVZ::ButtonToBits (SkinElementType button)
+{
+ uint16 bitNumber = 0;
+ switch (button)
+ {
+ case kElement_None: break;
+
+ case kElement_PowerButton: bitNumber = keyBitPower; break;
+ case kElement_UpButton: bitNumber = keyBitPageUp; break;
+ case kElement_DownButton: bitNumber = keyBitPageDown; break;
+ case kElement_App1Button: bitNumber = keyBitHard1; break;
+ case kElement_App2Button: bitNumber = keyBitHard2; break;
+ case kElement_App3Button: bitNumber = keyBitHard3; break;
+ case kElement_App4Button: bitNumber = keyBitHard4; break;
+ case kElement_CradleButton: bitNumber = keyBitCradle; break;
+ case kElement_Antenna: bitNumber = keyBitAntenna; break;
+ case kElement_ContrastButton: bitNumber = keyBitContrast; break;
+
+ default: EmAssert (false);
+ }
+
+ return bitNumber;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZ::GetSPISlave (void)
+{
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UpdateInterrupts
+// ---------------------------------------------------------------------------
+// Determines whether an interrupt has occurred by copying the Interrupt
+// Pending Register to the Interrupt Status Register.
+
+void EmRegsVZ::UpdateInterrupts (void)
+{
+ // Copy the Interrupt Pending Register to the Interrupt Status
+ // Register, but ignore interrupts that are being masked.
+
+ // Note: this function is not sensitive to the byte ordering of the registers,
+ // so their contents don't need to be accessed via READ_REGISTER or WRITE_REGISTER.
+
+ f68VZ328Regs.intStatusHi = f68VZ328Regs.intPendingHi & ~f68VZ328Regs.intMaskHi;
+ f68VZ328Regs.intStatusLo = f68VZ328Regs.intPendingLo & ~f68VZ328Regs.intMaskLo;
+
+ PRINTF ("EmRegsVZ::UpdateInterrupts: intMask = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intMaskHi, (uint32) f68VZ328Regs.intMaskLo);
+
+ PRINTF ("EmRegsVZ::UpdateInterrupts: intPending = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intPendingHi, (uint32) f68VZ328Regs.intPendingLo);
+
+ // If the Interrupt Status Register isn't clear, flag an interrupt.
+
+ if (f68VZ328Regs.intStatusHi || f68VZ328Regs.intStatusLo)
+ {
+ regs.spcflags |= SPCFLAG_INT;
+
+ PRINTF ("EmRegsVZ::UpdateInterrupts: intStatus = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intStatusHi, (uint32) f68VZ328Regs.intStatusLo);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UpdatePortDInterrupts
+// ---------------------------------------------------------------------------
+// Determine what interrupts need to be generated based on the current
+// settings in portDData and fPortDEdge.
+
+void EmRegsVZ::UpdatePortDInterrupts (void)
+{
+ // Update INT0-INT3 of the Interrupt-Pending register (bits 8-11 of the low word).
+
+ // First, get those bits and clear them out.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo) & ~hwrVZ328IntLoAllKeys;
+
+
+ // Initialize the variable to hold the new interrupt settings.
+
+ uint8 newBits = 0;
+
+
+ // Get some other values we're going to need:
+
+ uint8 portDDir = READ_REGISTER (portDDir); // Interrupt on inputs only (when pin is low)
+ uint8 portDData = EmHAL::GetPortInputValue ('D');
+ uint8 portDPolarity = READ_REGISTER (portDPolarity);
+ uint8 portDIntReqEn = READ_REGISTER (portDIntReqEn);
+ uint8 portDKbdIntEn = READ_REGISTER (portDKbdIntEn);
+ uint8 portDIntEdge = READ_REGISTER (portDIntEdge);
+
+ // We have a line-level interrupt if:
+ //
+ // - line-level interrupts are requested
+ // - the GPIO bit matches the polarity bit
+
+ newBits |= ~portDIntEdge & portDData & portDPolarity;
+ newBits |= ~portDIntEdge & ~portDData & ~portDPolarity;
+
+
+ // We have an edge interrupt if:
+ //
+ // - edge interrupts are requested
+ // - an edge has been recorded
+ //
+ // Note that we should distinguish between rising and falling edges.
+ // For historical reasons, that's not done, and the Palm OS doesn't
+ // look for them, so it's OK for now.
+ //
+ // Edge interrupts on INT[3:0] should not wake up a sleeping device.
+
+ uint16 pllControl = READ_REGISTER (pllControl);
+
+#if 0
+ if ((pllControl & hwrVZ328PLLControlDisable) && !(gSession->GetDevice ().EdgeHack ()))
+ {
+ newBits |= portDIntEdge & fPortDEdge & portDPolarity & 0xF0;
+ newBits |= portDIntEdge & 0 & ~portDPolarity & 0xF0;
+ }
+ else
+#endif
+ {
+ newBits |= portDIntEdge & fPortDEdge & portDPolarity;
+ newBits |= portDIntEdge & 0 & ~portDPolarity;
+ }
+
+
+ // Only have interrupts if they're enabled and the pin is configured for input.
+
+ newBits &= portDIntReqEn & ~portDDir;
+
+ PRINTF ("EmRegsVZ::UpdatePortDInterrupts: Dir Data Pol Req Edg PDE bits");
+ PRINTF ("EmRegsVZ::UpdatePortDInterrupts: 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX 0x%02lX",
+ (uint32) portDDir, (uint32) portDData, (uint32) portDPolarity, (uint32) portDIntReqEn, (uint32) portDIntEdge,
+ (uint32) fPortDEdge, (uint32) newBits);
+
+
+ // Determine if the KB interrupt needs to be asserted. It is if:
+ //
+ // A Port D Data bit is on.
+ // The bit is configured for input (?)
+ // The bit is configured to be OR'd into the interrupt.
+
+ if (!gSession->GetDevice ().EdgeHack ())
+ {
+ uint8 KB = portDData & ~portDDir & portDKbdIntEn;
+
+ if (KB)
+ intPendingLo |= hwrVZ328IntLoKbd;
+ else
+ intPendingLo &= ~hwrVZ328IntLoKbd;
+ }
+
+
+ // Merge in the new values and write out the result.
+
+ intPendingLo |= (((uint16) newBits) << hwrVZ328IntLoInt0Bit) & hwrVZ328IntLoAllKeys;
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UpdateRTCInterrupts
+// ---------------------------------------------------------------------------
+// Determine whether to set or clear the RTC bit in the interrupt pending
+// register based on the current RTC register values.
+
+void EmRegsVZ::UpdateRTCInterrupts (void)
+{
+ // See if the RTC is enabled.
+
+ Bool rtcEnabled = (READ_REGISTER (rtcControl) & hwrVZ328RTCControlRTCEnable) != 0;
+
+ // See if there are any RTC events that need to trigger an interrupt.
+
+#define BITS_TO_CHECK ( \
+ hwrVZ328RTCIntEnableSec | \
+ hwrVZ328RTCIntEnable24Hr | \
+ hwrVZ328RTCIntEnableAlarm | \
+ hwrVZ328RTCIntEnableMinute | \
+ hwrVZ328RTCIntEnableStopWatch )
+
+ uint16 rtcIntStatus = READ_REGISTER (rtcIntStatus);
+ uint16 rtcIntEnable = READ_REGISTER (rtcIntEnable);
+ uint16 rtcIntPending = rtcIntStatus & rtcIntEnable & BITS_TO_CHECK;
+
+ Bool havePendingEvents = rtcIntPending != 0;
+
+ // If the RTC is enabled and there are pending events, set the interrupt.
+ // Otherwise, clear the interrupt.
+
+ uint16 intPendingLo = READ_REGISTER (intPendingLo);
+
+ if (rtcEnabled && havePendingEvents)
+ {
+ intPendingLo |= hwrVZ328IntLoRTC; // have events, so set interrupt
+ }
+ else
+ {
+ intPendingLo &= ~hwrVZ328IntLoRTC; // no events, so clear interrupt
+ }
+
+ // Update the interrupt pending register.
+
+ WRITE_REGISTER (intPendingLo, intPendingLo);
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UARTStateChanged
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::UARTStateChanged (Bool sendTxData, int uartNum)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_DragonballVZ);
+
+ EmRegsVZ::MarshalUARTState (state, uartNum);
+
+ fUART[uartNum]->StateChanged (state, sendTxData);
+
+ EmRegsVZ::UnmarshalUARTState (state, uartNum);
+
+ EmRegsVZ::UpdateUARTInterrupts (state, uartNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UpdateUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::UpdateUARTState (Bool refreshRxData, int uartNum)
+{
+ EmUARTDragonball::State state (EmUARTDragonball::kUART_DragonballVZ);
+
+ EmRegsVZ::MarshalUARTState (state, uartNum);
+
+ fUART[uartNum]->UpdateState (state, refreshRxData);
+
+ EmRegsVZ::UnmarshalUARTState (state, uartNum);
+
+ EmRegsVZ::UpdateUARTInterrupts (state, uartNum);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UpdateUARTInterrupts
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::UpdateUARTInterrupts (const EmUARTDragonball::State& state, int uartNum)
+{
+ // Generate the appropriate interrupts.
+
+ uint16 whichBit = uartNum == 0 ? hwrVZ328IntLoUART : hwrVZ328IntLoUART2;
+
+#if 0
+ LogAppendMsg ("UpdateUARTInterrupts for UART %d.", uartNum + 1);
+
+ if (uartNum == 1)
+ {
+ LogAppendMsg ("RX_FIFO_FULL: %s RX_FIFO_HALF: %s DATA_READY: %s",
+ state.RX_FIFO_FULL ? "ON " : "off",
+ state.RX_FIFO_HALF ? "ON " : "off",
+ state.DATA_READY ? "ON " : "off");
+
+ LogAppendMsg ("RX_FULL_ENABLE: %s RX_HALF_ENABLE: %s RX_RDY_ENABLE: %s",
+ state.RX_FULL_ENABLE ? "ON " : "off",
+ state.RX_HALF_ENABLE ? "ON " : "off",
+ state.RX_RDY_ENABLE ? "ON " : "off");
+
+ LogAppendMsg ("TX_FIFO_EMPTY: %s TX_FIFO_HALF: %s TX_AVAIL: %s",
+ state.TX_FIFO_EMPTY ? "ON " : "off",
+ state.TX_FIFO_HALF ? "ON " : "off",
+ state.TX_AVAIL ? "ON " : "off");
+
+ LogAppendMsg ("TX_EMPTY_ENABLE: %s TX_HALF_ENABLE: %s TX_AVAIL_ENABLE: %s",
+ state.TX_EMPTY_ENABLE ? "ON " : "off",
+ state.TX_HALF_ENABLE ? "ON " : "off",
+ state.TX_AVAIL_ENABLE ? "ON " : "off");
+ }
+#endif
+
+ if (state.RX_FULL_ENABLE && state.RX_FIFO_FULL ||
+ state.RX_HALF_ENABLE && state.RX_FIFO_HALF ||
+ state.RX_RDY_ENABLE && state.DATA_READY ||
+ state.TX_EMPTY_ENABLE && state.TX_FIFO_EMPTY ||
+ state.TX_HALF_ENABLE && state.TX_FIFO_HALF ||
+ state.TX_AVAIL_ENABLE && state.TX_AVAIL)
+ {
+ // Set the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) | whichBit);
+#if 0
+ if (uartNum == 1)
+ {
+ LogAppendMsg ("Setting UART %d interrupt.", uartNum + 1);
+ }
+#endif
+ }
+ else
+ {
+ // Clear the UART interrupt.
+
+ WRITE_REGISTER (intPendingLo, READ_REGISTER (intPendingLo) & ~whichBit);
+#if 0
+ if (uartNum == 1)
+ {
+ LogAppendMsg ("Clearing UART %d interrupt.", uartNum + 1);
+ }
+#endif
+ }
+
+ // Respond to the new interrupt state.
+
+ EmRegsVZ::UpdateInterrupts ();
+
+#if 0
+ if (uartNum == 1)
+ {
+ LogAppendMsg ("intPending = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intPendingHi,
+ (uint32) f68VZ328Regs.intPendingLo);
+
+ LogAppendMsg ("intMask = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intMaskHi,
+ (uint32) f68VZ328Regs.intMaskLo);
+
+ LogAppendMsg ("intStatus = 0x%04lX %04lX",
+ (uint32) f68VZ328Regs.intStatusHi,
+ (uint32) f68VZ328Regs.intStatusLo);
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::MarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::MarshalUARTState (EmUARTDragonball::State& state, int uartNum)
+{
+ uint16 uControl;
+ uint16 uBaud;
+ uint16 uReceive;
+ uint16 uTransmit;
+ uint16 uMisc;
+ uint16 uLevel;
+
+ if (uartNum == 0)
+ {
+ uControl = READ_REGISTER (uControl);
+ uBaud = READ_REGISTER (uBaud);
+ uReceive = READ_REGISTER (uReceive);
+ uTransmit = READ_REGISTER (uTransmit);
+ uMisc = READ_REGISTER (uMisc);
+ uLevel = 0;
+ }
+ else
+ {
+ uControl = READ_REGISTER (u2Control);
+ uBaud = READ_REGISTER (u2Baud);
+ uReceive = READ_REGISTER (u2Receive);
+ uTransmit = READ_REGISTER (u2Transmit);
+ uMisc = READ_REGISTER (u2Misc);
+ uLevel = READ_REGISTER (u2FIFOHMark);
+ }
+
+ state.UART_ENABLE = (uControl & hwrVZ328UControlUARTEnable) != 0;
+ state.RX_ENABLE = (uControl & hwrVZ328UControlRxEnable) != 0;
+ state.TX_ENABLE = (uControl & hwrVZ328UControlTxEnable) != 0;
+ state.RX_CLK_CONT = (uControl & hwrVZ328UControlRxClock1xSync) != 0;
+ state.PARITY_EN = (uControl & hwrVZ328UControlParityEn) != 0;
+ state.ODD_EVEN = (uControl & hwrVZ328UControlParityOdd) != 0;
+ state.STOP_BITS = (uControl & hwrVZ328UControlStopBits2) != 0;
+ state.CHAR8_7 = (uControl & hwrVZ328UControlDataBits8) != 0;
+// state.GPIO_DELTA_ENABLE = (uControl & hwr328UControlGPIODeltaEn) != 0; // 68328 only
+ state.OLD_ENABLE = (uControl & hwrVZ328UControlOldDataEn) != 0; // 68VZ328 only
+ state.CTS_DELTA_ENABLE = (uControl & hwrVZ328UControlCTSDeltaEn) != 0;
+ state.RX_FULL_ENABLE = (uControl & hwrVZ328UControlRxFullEn) != 0;
+ state.RX_HALF_ENABLE = (uControl & hwrVZ328UControlRxHalfEn) != 0;
+ state.RX_RDY_ENABLE = (uControl & hwrVZ328UControlRxRdyEn) != 0;
+ state.TX_EMPTY_ENABLE = (uControl & hwrVZ328UControlTxEmptyEn) != 0;
+ state.TX_HALF_ENABLE = (uControl & hwrVZ328UControlTxHalfEn) != 0;
+ state.TX_AVAIL_ENABLE = (uControl & hwrVZ328UControlTxAvailEn) != 0;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+// state.GPIO_DELTA = (uBaud & hwr328UBaudGPIODelta) != 0; // 68328 only
+// state.GPIO = (uBaud & hwr328UBaudGPIOData) != 0; // 68328 only
+// state.GPIO_DIR = (uBaud & hwr328UBaudGPIODirOut) != 0; // 68328 only
+// state.GPIO_SRC = (uBaud & hwrVZ328UBaudGPIOSrcBaudGen) != 0; // 68328 only
+ state.UCLK_DIR = (uBaud & hwrVZ328UBaudUCLKDirOut) != 0; // 68VZ328 only
+ state.BAUD_SRC = (uBaud & hwrVZ328UBaudBaudSrcUCLK) != 0;
+ state.DIVIDE = (uBaud & hwrVZ328UBaudDivider) >> hwrVZ328UBaudDivideBitOffset;
+ state.PRESCALER = (uBaud & hwrVZ328UBaudPrescaler);
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ state.RX_FIFO_FULL = (uReceive & hwrVZ328UReceiveFIFOFull) != 0;
+ state.RX_FIFO_HALF = (uReceive & hwrVZ328UReceiveFIFOHalf) != 0;
+ state.DATA_READY = (uReceive & hwrVZ328UReceiveDataRdy) != 0;
+ state.OLD_DATA = (uReceive & hwrVZ328UReceiveOldData) != 0; // 68VZ328 only
+ state.OVRUN = (uReceive & hwrVZ328UReceiveOverrunErr) != 0;
+ state.FRAME_ERROR = (uReceive & hwrVZ328UReceiveFrameErr) != 0;
+ state.BREAK = (uReceive & hwrVZ328UReceiveBreakErr) != 0;
+ state.PARITY_ERROR = (uReceive & hwrVZ328UReceiveParityErr) != 0;
+ state.RX_DATA = (uReceive & hwrVZ328UReceiveData);
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ state.TX_FIFO_EMPTY = (uTransmit & hwrVZ328UTransmitFIFOEmpty) != 0;
+ state.TX_FIFO_HALF = (uTransmit & hwrVZ328UTransmitFIFOHalf) != 0;
+ state.TX_AVAIL = (uTransmit & hwrVZ328UTransmitTxAvail) != 0;
+ state.SEND_BREAK = (uTransmit & hwrVZ328UTransmitSendBreak) != 0;
+ state.IGNORE_CTS = (uTransmit & hwrVZ328UTransmitIgnoreCTS) != 0;
+ state.BUSY = (uTransmit & hwrVZ328UTransmitBusy) != 0; // 68VZ328 only
+ state.CTS_STATUS = (uTransmit & hwrVZ328UTransmitCTSStatus) != 0;
+ state.CTS_DELTA = (uTransmit & hwrVZ328UTransmitCTSDelta) != 0;
+ state.TX_DATA = (uTransmit & hwrVZ328UTransmitData);
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+ state.BAUD_TEST = (uMisc & hwrVZ328UMiscBaudTest) != 0; // 68VZ328 only
+ state.CLK_SRC = (uMisc & hwrVZ328UMiscClkSrcUCLK) != 0;
+ state.FORCE_PERR = (uMisc & hwrVZ328UMiscForceParityErr) != 0;
+ state.LOOP = (uMisc & hwrVZ328UMiscLoopback) != 0;
+ state.BAUD_RESET = (uMisc & hwrVZ328UMiscBaudReset) != 0; // 68VZ328 only
+ state.IR_TEST = (uMisc & hwrVZ328UMiscIRTestEn) != 0; // 68VZ328 only
+ state.RTS_CONT = (uMisc & hwrVZ328UMiscRTSThruFIFO) != 0;
+ state.RTS = (uMisc & hwrVZ328UMiscRTSOut) != 0;
+ state.IRDA_ENABLE = (uMisc & hwrVZ328UMiscIRDAEn) != 0;
+ state.IRDA_LOOP = (uMisc & hwrVZ328UMiscLoopIRDA) != 0;
+ state.RX_POL = (uMisc & hwrVZ328UMiscRXPolarityInv) != 0; // 68VZ328 only
+ state.TX_POL = (uMisc & hwrVZ328UMiscTXPolarityInv) != 0; // 68VZ328 only
+
+ // Level Marker Interrupt
+
+ state.TXFIFO_LEVEL_MARKER = ((uLevel >> 8) & 0x0F); // 68VZ328 only
+ state.RXFIFO_LEVEL_MARKER = ((uLevel >> 0) & 0x0F); // 68VZ328 only
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::UnmarshalUARTState
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::UnmarshalUARTState (const EmUARTDragonball::State& state, int uartNum)
+{
+ uint16 uControl = 0;
+ uint16 uBaud = 0;
+ uint16 uReceive = 0;
+ uint16 uTransmit = 0;
+ uint16 uMisc = 0;
+ uint16 uLevel = 0;
+
+ if (state.UART_ENABLE) uControl |= hwrVZ328UControlUARTEnable;
+ if (state.RX_ENABLE) uControl |= hwrVZ328UControlRxEnable;
+ if (state.TX_ENABLE) uControl |= hwrVZ328UControlTxEnable;
+ if (state.RX_CLK_CONT) uControl |= hwrVZ328UControlRxClock1xSync;
+ if (state.PARITY_EN) uControl |= hwrVZ328UControlParityEn;
+ if (state.ODD_EVEN) uControl |= hwrVZ328UControlParityOdd;
+ if (state.STOP_BITS) uControl |= hwrVZ328UControlStopBits2;
+ if (state.CHAR8_7) uControl |= hwrVZ328UControlDataBits8;
+// if (state.GPIO_DELTA_ENABLE)uControl |= hwr328UControlGPIODeltaEn; // 68328 only
+ if (state.OLD_ENABLE) uControl |= hwrVZ328UControlOldDataEn; // 68VZ328 only
+ if (state.CTS_DELTA_ENABLE) uControl |= hwrVZ328UControlCTSDeltaEn;
+ if (state.RX_FULL_ENABLE) uControl |= hwrVZ328UControlRxFullEn;
+ if (state.RX_HALF_ENABLE) uControl |= hwrVZ328UControlRxHalfEn;
+ if (state.RX_RDY_ENABLE) uControl |= hwrVZ328UControlRxRdyEn;
+ if (state.TX_EMPTY_ENABLE) uControl |= hwrVZ328UControlTxEmptyEn;
+ if (state.TX_HALF_ENABLE) uControl |= hwrVZ328UControlTxHalfEn;
+ if (state.TX_AVAIL_ENABLE) uControl |= hwrVZ328UControlTxAvailEn;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+// if (state.GPIO_DELTA) uBaud |= hwr328UBaudGPIODelta; // 68328 only
+// if (state.GPIO) uBaud |= hwr328UBaudGPIOData; // 68328 only
+// if (state.GPIO_DIR) uBaud |= hwr328UBaudGPIODirOut; // 68328 only
+// if (state.GPIO_SRC) uBaud |= hwr328UBaudGPIOSrcBaudGen; // 68328 only
+ if (state.UCLK_DIR) uBaud |= hwrVZ328UBaudUCLKDirOut; // 68VZ328 only
+ if (state.BAUD_SRC) uBaud |= hwrVZ328UBaudBaudSrcUCLK;
+
+ uBaud |= (state.DIVIDE << hwrVZ328UBaudDivideBitOffset) & hwrVZ328UBaudDivider;
+ uBaud |= (state.PRESCALER) & hwrVZ328UBaudPrescaler;
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ if (state.RX_FIFO_FULL) uReceive |= hwrVZ328UReceiveFIFOFull;
+ if (state.RX_FIFO_HALF) uReceive |= hwrVZ328UReceiveFIFOHalf;
+ if (state.DATA_READY) uReceive |= hwrVZ328UReceiveDataRdy;
+ if (state.OLD_DATA) uReceive |= hwrVZ328UReceiveOldData; // 68VZ328 only
+ if (state.OVRUN) uReceive |= hwrVZ328UReceiveOverrunErr;
+ if (state.FRAME_ERROR) uReceive |= hwrVZ328UReceiveFrameErr;
+ if (state.BREAK) uReceive |= hwrVZ328UReceiveBreakErr;
+ if (state.PARITY_ERROR) uReceive |= hwrVZ328UReceiveParityErr;
+
+ uReceive |= (state.RX_DATA) & hwrVZ328UReceiveData;
+
+ // Transmitter register bits
+ // We set everything except TX_DATA; the user sets that
+ // value and ONLY that value.
+
+ if (state.TX_FIFO_EMPTY) uTransmit |= hwrVZ328UTransmitFIFOEmpty;
+ if (state.TX_FIFO_HALF) uTransmit |= hwrVZ328UTransmitFIFOHalf;
+ if (state.TX_AVAIL) uTransmit |= hwrVZ328UTransmitTxAvail;
+ if (state.SEND_BREAK) uTransmit |= hwrVZ328UTransmitSendBreak;
+ if (state.IGNORE_CTS) uTransmit |= hwrVZ328UTransmitIgnoreCTS;
+ if (state.BUSY) uTransmit |= hwrVZ328UTransmitBusy; // 68VZ328 only
+ if (state.CTS_STATUS) uTransmit |= hwrVZ328UTransmitCTSStatus;
+ if (state.CTS_DELTA) uTransmit |= hwrVZ328UTransmitCTSDelta;
+
+ uTransmit |= (state.TX_DATA) & hwrVZ328UTransmitData;
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+ if (state.BAUD_TEST) uMisc |= hwrVZ328UMiscBaudTest; // 68VZ328 only
+ if (state.CLK_SRC) uMisc |= hwrVZ328UMiscClkSrcUCLK;
+ if (state.FORCE_PERR) uMisc |= hwrVZ328UMiscForceParityErr;
+ if (state.LOOP) uMisc |= hwrVZ328UMiscLoopback;
+ if (state.BAUD_RESET) uMisc |= hwrVZ328UMiscBaudReset; // 68VZ328 only
+ if (state.IR_TEST) uMisc |= hwrVZ328UMiscIRTestEn; // 68VZ328 only
+ if (state.RTS_CONT) uMisc |= hwrVZ328UMiscRTSThruFIFO;
+ if (state.RTS) uMisc |= hwrVZ328UMiscRTSOut;
+ if (state.IRDA_ENABLE) uMisc |= hwrVZ328UMiscIRDAEn;
+ if (state.IRDA_LOOP) uMisc |= hwrVZ328UMiscLoopIRDA;
+ if (state.RX_POL) uMisc |= hwrVZ328UMiscRXPolarityInv; // 68VZ328 only
+ if (state.TX_POL) uMisc |= hwrVZ328UMiscTXPolarityInv; // 68VZ328 only
+
+ // Level Marker Interrupt
+
+ uLevel |= (state.TXFIFO_LEVEL_MARKER) << 8;
+ uLevel |= (state.RXFIFO_LEVEL_MARKER) << 0;
+
+ if (uartNum == 0)
+ {
+ WRITE_REGISTER (uControl, uControl);
+ WRITE_REGISTER (uBaud, uBaud);
+ WRITE_REGISTER (uReceive, uReceive);
+ WRITE_REGISTER (uTransmit, uTransmit);
+ WRITE_REGISTER (uMisc, uMisc);
+ }
+ else
+ {
+ WRITE_REGISTER (u2Control, uControl);
+ WRITE_REGISTER (u2Baud, uBaud);
+ WRITE_REGISTER (u2Receive, uReceive);
+ WRITE_REGISTER (u2Transmit, uTransmit);
+ WRITE_REGISTER (u2Misc, uMisc);
+ WRITE_REGISTER (u2FIFOHMark, uLevel);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::GetPort
+// ---------------------------------------------------------------------------
+// Given an address, return a value indicating what port it is associated with.
+
+int EmRegsVZ::GetPort (emuptr address)
+{
+ const long MASK = 0x00000FF8;
+
+ switch (address & MASK)
+ {
+ case 0x0400: return 'A';
+ case 0x0408: return 'B';
+ case 0x0410: return 'C';
+ case 0x0418: return 'D';
+ case 0x0420: return 'E';
+ case 0x0428: return 'F';
+ case 0x0430: return 'G';
+ case 0x0438: return 'J';
+ case 0x0440: return 'K';
+ case 0x0448: return 'M';
+ }
+
+ EmAssert (false);
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::PrvGetPalette
+// ---------------------------------------------------------------------------
+
+void EmRegsVZ::PrvGetPalette (RGBList& thePalette)
+{
+ // !!! TBD
+ Preference<RGBType> pref1 (kPrefKeyBackgroundColor);
+ Preference<RGBType> pref2 (kPrefKeyHighlightColor);
+
+ RGBType foreground (0, 0, 0);
+ RGBType background;
+
+ if (this->GetLCDBacklightOn ())
+ {
+ if (pref2.Loaded ())
+ background = *pref2;
+ else
+ background = ::SkinGetHighlightColor ();
+ }
+ else
+ {
+ if (pref1.Loaded ())
+ background = *pref1;
+ else
+ background = ::SkinGetBackgroundColor ();
+ }
+
+ long br = ((long) background.fRed);
+ long bg = ((long) background.fGreen);
+ long bb = ((long) background.fBlue);
+
+ long dr = ((long) foreground.fRed) - ((long) background.fRed);
+ long dg = ((long) foreground.fGreen) - ((long) background.fGreen);
+ long db = ((long) foreground.fBlue) - ((long) background.fBlue);
+
+ int32 bpp = 1 << (READ_REGISTER (lcdPanelControl) & 0x03);
+ int32 numColors = 1 << bpp;
+ thePalette.resize (numColors);
+
+ for (int color = 0; color < numColors; ++color)
+ {
+ thePalette[color].fRed = (UInt8) (br + dr * color / (numColors - 1));
+ thePalette[color].fGreen = (UInt8) (bg + dg * color / (numColors - 1));
+ thePalette[color].fBlue = (UInt8) (bb + db * color / (numColors - 1));
+ }
+}
diff --git a/SrcShared/Hardware/EmRegsVZ.h b/SrcShared/Hardware/EmRegsVZ.h
new file mode 100644
index 0000000..42ad360
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZ.h
@@ -0,0 +1,145 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZ_h
+#define EmRegsVZ_h
+
+#include "EmHAL.h" // EmHALHandler
+#include "EmRegs.h" // EmRegs
+#include "EmStructs.h" // RGBList
+#include "EmUARTDragonball.h" // EmUARTDragonball::State
+
+class EmScreenUpdateInfo;
+class EmSPISlave;
+
+
+class EmRegsVZ : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsVZ (void);
+ virtual ~EmRegsVZ (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ // EmHALHandler overrides
+ virtual void Cycle (Bool sleeping);
+ virtual void CycleSlowly (Bool sleeping);
+
+ virtual void ButtonEvent (SkinElementType, Bool buttonIsDown);
+ virtual void TurnSoundOff (void);
+ virtual void ResetTimer (void);
+ virtual void ResetRTC (void);
+
+ virtual int32 GetInterruptLevel (void);
+ virtual int32 GetInterruptBase (void);
+
+ virtual Bool GetLCDScreenOn (void) = 0;
+ virtual Bool GetLCDBacklightOn (void) = 0;
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr&, emuptr&);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ virtual int32 GetDynamicHeapSize (void);
+ virtual int32 GetROMSize (void);
+ virtual emuptr GetROMBaseAddress (void);
+ virtual Bool ChipSelectsConfigured (void);
+ virtual int32 GetSystemClockFrequency (void);
+ virtual Bool GetCanStop (void);
+ virtual Bool GetAsleep (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void PortDataChanged (int, uint8, uint8);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows) = 0;
+
+ private:
+ uint32 pllFreqSelRead (emuptr address, int size);
+ uint32 portXDataRead (emuptr address, int size);
+ uint32 tmr1StatusRead (emuptr address, int size);
+ uint32 tmr2StatusRead (emuptr address, int size);
+ uint32 uart1Read (emuptr address, int size);
+ uint32 uart2Read (emuptr address, int size);
+ uint32 rtcHourMinSecRead (emuptr address, int size);
+
+ void csControl1Write (emuptr address, int size, uint32 value);
+ void csASelectWrite (emuptr address, int size, uint32 value);
+ void csDSelectWrite (emuptr address, int size, uint32 value);
+ void intMaskHiWrite (emuptr address, int size, uint32 value);
+ void intMaskLoWrite (emuptr address, int size, uint32 value);
+ void intStatusHiWrite (emuptr address, int size, uint32 value);
+ void portXDataWrite (emuptr address, int size, uint32 value);
+ void portDIntReqEnWrite (emuptr address, int size, uint32 value);
+ void tmr1StatusWrite (emuptr address, int size, uint32 value);
+ void tmr2StatusWrite (emuptr address, int size, uint32 value);
+ void spiCont1Write (emuptr address, int size, uint32 value);
+ void spiMasterControlWrite (emuptr address, int size, uint32 value);
+ void uart1Write (emuptr address, int size, uint32 value);
+ void uart2Write (emuptr address, int size, uint32 value);
+ void lcdRegisterWrite (emuptr address, int size, uint32 value);
+ void rtcControlWrite (emuptr address, int size, uint32 value);
+ void rtcIntStatusWrite (emuptr address, int size, uint32 value);
+ void rtcIntEnableWrite (emuptr address, int size, uint32 value);
+
+ protected:
+ void HotSyncEvent (Bool buttonIsDown);
+
+ virtual uint8 GetKeyBits (void);
+ virtual uint16 ButtonToBits (SkinElementType);
+ virtual EmSPISlave* GetSPISlave (void);
+
+ protected:
+ void UpdateInterrupts (void);
+ void UpdatePortDInterrupts (void);
+ void UpdateRTCInterrupts (void);
+
+ protected:
+ void UARTStateChanged (Bool sendTxData, int uartNum);
+ void UpdateUARTState (Bool refreshRxData, int uartNum);
+ void UpdateUARTInterrupts (const EmUARTDragonball::State& state, int uartNum);
+ void MarshalUARTState (EmUARTDragonball::State& state, int uartNum);
+ void UnmarshalUARTState (const EmUARTDragonball::State& state, int uartNum);
+
+ protected:
+ int GetPort (emuptr address);
+ void PrvGetPalette (RGBList& thePalette);
+
+ protected:
+ HwrM68VZ328Type f68VZ328Regs;
+ bool fHotSyncButtonDown;
+ uint16 fKeyBits;
+ uint16 fLastTmr1Status;
+ uint16 fLastTmr2Status;
+ uint8 fPortDEdge;
+ uint32 fPortDDataCount;
+
+ uint32 fHour;
+ uint32 fMin;
+ uint32 fSec;
+ uint32 fTick;
+ uint32 fCycle;
+
+ EmUARTDragonball* fUART[2];
+};
+
+#endif /* EmRegsVZ_h */
diff --git a/SrcShared/Hardware/EmRegsVZHandEra330.cpp b/SrcShared/Hardware/EmRegsVZHandEra330.cpp
new file mode 100644
index 0000000..598320e
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZHandEra330.cpp
@@ -0,0 +1,608 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZTemp.h"
+#include "EmRegsVZPrv.h"
+#include "EmTRGSD.h"
+#include "EmRegsVZHandEra330.h"
+#include "EmRegs330CPLD.h"
+#include "EmBankRegs.h" // EmBankRegs::DisableSubBank
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+#include "EmSPISlave330Current.h"
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmDlg.h" // EmDlg::DoCommonDialog
+
+
+#pragma mark -
+
+const int kNumButtonRows = 4;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, keyBitThumbDown},
+ { keyBitPower, 0, keyBitContrast, keyBitThumbPush},
+ { 0, 0, 0, keyBitThumbUp},
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::EmRegsVZHandEra330
+// ---------------------------------------------------------------------------
+
+EmRegsVZHandEra330::EmRegsVZHandEra330 (HandEra330PortManager ** fPortManager) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2)),
+ fSPISlaveCurrent (new EmSPISlave330Current ())
+{
+ PortD = PortD_DOCK_BTN |
+ PortD_CD_IRQ |
+ PortD_CF_IRQ |
+ PortD_POWER_FAIL;
+ PortF = PortF_PEN_IO |
+ PortF_CPLD_CS_F;
+ PortG = PortG_DTACK |
+ PortG_A0 |
+ PortG_Unused |
+ // PortG_LION |
+ PortG_Unused2;
+ PortJ = PortJ_AD_CS;
+ PortK = PortK_LED_GREEN |
+ PortK_LED_RED |
+ PortK_CPLD_TDO |
+ PortK_CPLD_TCK;
+ PortM = PortM_CPLD_TDI;
+ *fPortManager = &PortMgr;
+ PortMgr.Keys.Row[0] = 1;
+ PortMgr.Keys.Row[1] = 1;
+ PortMgr.Keys.Row[2] = 1;
+ PortMgr.Keys.Row[3] = 1;
+ PortMgr.LCDOn = false;
+ PortMgr.BacklightOn = false;
+ PortMgr.IRPortOn = false;
+ PortMgr.CFBus.bEnabled = false;
+ PortMgr.CFBus.Width = kCFBusWidth16;
+ PortMgr.CFBus.bSwapped = false;
+ PortMgr.CFInserted = true;
+ PortMgr.SDInserted = true;
+ PortMgr.pendingIRQ2 = false;
+ PortMgr.SDChipSelect = false;
+ PortMgr.PowerConnected = false;
+
+ // make sure SPI1 fifos are empty
+ rxHead = rxTail = txHead = txTail = 0;
+ txFifoEmpty = true;
+ rxFifoEmpty = true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::~EmRegsVZHandEra330
+// ---------------------------------------------------------------------------
+
+EmRegsVZHandEra330::~EmRegsVZHandEra330 (void)
+{
+ delete fSPISlaveADC;
+}
+
+void EmRegsVZHandEra330::Initialize(void)
+{
+ EmRegsVZ::Initialize();
+
+ SD.Initialize();
+}
+
+void EmRegsVZHandEra330::Dispose (void)
+{
+ EmRegsVZ::Dispose();
+
+ SD.Dispose();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZHandEra330::GetLCDScreenOn (void)
+{
+ // TRG LCD on is determined by LCD contrast on in the CPLD
+ return PortMgr.LCDOn;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZHandEra330::GetLCDBacklightOn (void)
+{
+ // TRG CPLD controls the backlight
+ return PortMgr.BacklightOn;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZHandEra330::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portBData) & PortB_RS232_ON) != 0;
+
+ if (type == kUARTIR)
+ return PortMgr.IRPortOn;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZHandEra330::GetUARTDevice (int /*uartNum*/)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ // !!! Which UART are they using?
+
+// if (uartNum == ???)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetVibrateOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZHandEra330::GetVibrateOn (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetInterruptLevel
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZHandEra330::GetInterruptLevel (void)
+{
+ int32 retval;
+
+ retval = EmRegsVZ::GetInterruptLevel ();
+
+ if (PortMgr.pendingIRQ2 && (retval < 2))
+ retval = 2;
+
+ return retval;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetLEDState
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsVZHandEra330::GetLEDState (void)
+{
+ uint16 result = kLEDOff;
+ uint8 portKData = READ_REGISTER (portKData);
+
+ if ((portKData & PortK_LED_GREEN) == 0)
+ result |= kLEDGreen;
+
+ if ((portKData & PortK_LED_RED) == 0)
+ result |= kLEDRed;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetPortD
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZHandEra330::GetPortD (uint8 result)
+{
+ return result |
+ PortD_DOCK_BTN |
+ PortD_CD_IRQ |
+ PortD_CF_IRQ |
+ PortD_POWER_FAIL;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZHandEra330::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ switch (port)
+ {
+ case 'D' :
+ result = GetPortD (result);
+ break;
+ case 'F' :
+ result = PortF;
+ break;
+ case 'G' :
+ result = PortG;
+ break;
+ case 'J' :
+ result = PortJ;
+ break;
+ case 'K' :
+ result = PortK;
+ break;
+ case 'M' :
+ result = PortM;
+ break;
+
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZHandEra330::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ switch (port)
+ {
+ case 'D' :
+ result = GetPortD(result);
+ break;
+ case 'F' :
+ result = PortF;
+ break;
+ case 'G' :
+ result = PortG;
+ break;
+ case 'J' :
+ result = PortJ;
+ break;
+ case 'K' :
+ result = PortK;
+ break;
+ case 'M' :
+ result = PortM;
+ break;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZHandEra330::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+ rows[0] = PortMgr.Keys.Row[0];
+ rows[1] = PortMgr.Keys.Row[1];
+ rows[2] = PortMgr.Keys.Row[2];
+ rows[3] = PortMgr.Keys.Row[3];
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZHandEra330::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portJData) & PortJ_AD_CS) == 0)
+ {
+ if (PortMgr.SenseCurrent)
+ return fSPISlaveCurrent;
+ else
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::GetROMSize
+// ---------------------------------------------------------------------------
+
+int32 EmRegsVZHandEra330::GetROMSize (void)
+{
+ return (2 * 1024 * 1024);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::ButtonToBits
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsVZHandEra330::ButtonToBits (SkinElementType button)
+{
+ uint16 bitNumber = 0;
+ static Bool CF_button_pushed = false;
+ static Bool SD_button_pushed = false;
+ static Bool power_button_pushed = false;
+
+ switch (button)
+ {
+ default:
+ bitNumber = EmRegsVZ::ButtonToBits (button);
+ break;
+
+ // Borrow some skin elements from Symbol for our Thumb wheel
+ // NOTE: Borrowed Palm's contrast for our aux, so above case already handles it.
+ case kElement_TriggerLeft :
+ bitNumber = keyBitThumbUp; break;
+ case kElement_TriggerCenter :
+ bitNumber = keyBitThumbPush; break;
+ case kElement_TriggerRight :
+ bitNumber = keyBitThumbDown; break;
+
+ // Borrow some additional skin elements to trigger a CF removal or insert.
+ case kElement_DownButtonLeft :
+ bitNumber = 0;
+ // we get called twice here, don't handle the event on the button release
+ if(!CF_button_pushed)
+ {
+ PortMgr.CFInserted = !PortMgr.CFInserted;
+
+ if (PortMgr.CFInserted)
+ EmDlg::DoCommonDialog("The CF card has been installed.", kDlgFlags_OK);
+ else
+ EmDlg::DoCommonDialog("The CF card has been removed.", kDlgFlags_OK);
+
+ PortMgr.pendingIRQ2 = true;
+ CF_button_pushed = true;
+ }
+ else
+ CF_button_pushed = false;
+ break;
+
+ // SD
+ case kElement_DownButtonRight :
+ bitNumber = 0;
+ if (!SD_button_pushed)
+ {
+ PortMgr.SDInserted = !PortMgr.SDInserted;
+
+ if (PortMgr.SDInserted)
+ EmDlg::DoCommonDialog("The SD card has been installed.\n\nIt will take a second for the OS to mount it.",
+ kDlgFlags_OK);
+ else
+ EmDlg::DoCommonDialog("The SD card has been removed.", kDlgFlags_OK);
+
+ PortMgr.pendingIRQ2 = true;
+ SD_button_pushed = true;
+ }
+ else
+ SD_button_pushed = false;
+ break;
+
+ // power
+ case kElement_UpButtonLeft :
+ bitNumber = 0;
+ if (!power_button_pushed)
+ {
+ if (!PortMgr.PowerConnected)
+ {
+ if (PortG & PortG_LION)
+ PortG &= ~PortG_LION;
+ else
+ PortG |= PortG_LION;
+ }
+ PortMgr.PowerConnected = !PortMgr.PowerConnected;
+ PortMgr.pendingIRQ2 = true;
+ ((EmSPISlave330Current *)fSPISlaveCurrent)->SetMode(PortMgr.PowerConnected);
+
+ power_button_pushed = true;
+ }
+ else
+ power_button_pushed = false;
+ break;
+ }
+
+ return bitNumber;
+}
+
+
+/**********************************************************************************
+ * SD support:
+ * HandEra 330 SD is attached to the DragonballVZ SPI1 which is otherwise unused.
+ **********************************************************************************/
+uint32 EmRegsVZHandEra330::spiRxDRead(emuptr /* address */, int /* size */)
+{
+ uint32 retval;
+
+ // there is an 8 word fifo here, read back the first in.
+
+ if ((rxHead == rxTail) && rxFifoEmpty)
+ {
+ // invalid read, fifo empty
+ return 0;
+ }
+
+ retval = rxFifo[rxTail++];
+ if (rxTail == 8)
+ rxTail = 0;
+ if (rxTail == rxHead)
+ txFifoEmpty = true;
+ return retval;
+}
+
+void EmRegsVZHandEra330::spiTxDWrite(emuptr address, int size, uint32 value)
+{
+ // Do a standard update of the register. (so reading the last value back works)
+ EmRegsVZ::StdWrite (address, size, value);
+
+ if (!txFifoEmpty && (txHead == txTail))
+ {
+ // fifo full, do nothing
+ return;
+ }
+
+ txFifoEmpty = false;
+
+ // there is an 8 word fifo here.
+ txFifo[txHead++] = value;
+ if (txHead == 8)
+ txHead = 0;
+}
+
+void EmRegsVZHandEra330::spiCont1Write(emuptr address, int size, uint32 value)
+{
+ // if we were not enabled before, flush fifos
+ if ((value & hwrVZ328SPIMControlEnable)==0)
+ {
+ txTail = txHead;
+ rxTail = rxHead;
+ txFifoEmpty = rxFifoEmpty = true;
+ }
+
+ // Do a standard update of the register.
+ EmRegsVZ::StdWrite (address, size, value);
+
+ // Get the current value.
+ uint16 spiCont1 = READ_REGISTER (spiCont1);
+
+ // Check to see if data exchange and enable are enabled.
+ #define BIT_MASK (hwrVZ328SPIMControlExchange | hwrVZ328SPIMControlEnable)
+ if ((spiCont1 & BIT_MASK) == BIT_MASK)
+ {
+ // do the exchange
+ if (!txFifoEmpty)
+ {
+ // is SD chip selected?
+ if (PortMgr.SDChipSelect)
+ {
+ uint16 rxData, txData;
+
+ do
+ {
+ txData = txFifo[txTail++];
+ if (txTail == 8)
+ txTail = 0;
+ SD.ExchangeBits(txData, &rxData, (spiCont1 & 0x000f)+1);
+ rxFifo[rxHead++] = rxData;
+ if (rxHead == 8)
+ rxHead = 0;
+ } while (txTail != txHead);
+ txFifoEmpty = true;
+ rxFifoEmpty = false;
+ }
+ else
+ {
+ // nothing else is connected here, just stuff the rx fifo and flush the tx fifo
+ do
+ {
+ txTail++;
+ if (txTail == 8)
+ txTail = 0;
+ rxFifo[rxHead++] = 0xff;
+ if (rxHead == 8)
+ rxHead = 0;
+ } while (txTail != txHead);
+ rxFifoEmpty = false;
+ txFifoEmpty = true;
+ }
+ }
+
+ // Clear the exchange bit.
+ spiCont1 &= ~hwrVZ328SPIMControlExchange;
+ WRITE_REGISTER (spiCont1, spiCont1);
+ }
+}
+
+uint32 EmRegsVZHandEra330::spiCont1Read(emuptr /* address */, int /* size */)
+{
+ return 0;
+}
+
+void EmRegsVZHandEra330::spiIntCSWrite(emuptr /* address */, int /* size */, uint32 /* value */)
+{
+}
+
+uint32 EmRegsVZHandEra330::spiIntCSRead(emuptr /* address */, int /* size */)
+{
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZHandEra330::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsVZHandEra330::SetSubBankHandlers(void)
+{
+ //HwrM68VZ328Type regs;
+
+ EmRegsVZ::SetSubBankHandlers();
+
+ // SD support
+ this->SetHandler((ReadFunction)&EmRegsVZHandEra330::spiRxDRead,
+ (WriteFunction)&EmRegsVZ::StdWrite,
+ addressof(spiRxD),
+ sizeof(UInt16));
+ this->SetHandler((ReadFunction)&EmRegsVZ::StdRead,
+ (WriteFunction)&EmRegsVZHandEra330::spiTxDWrite,
+ addressof(spiTxD),
+ sizeof(UInt16));
+ this->SetHandler((ReadFunction)&EmRegsVZ::StdRead,
+ (WriteFunction)&EmRegsVZHandEra330::spiCont1Write,
+ addressof(spiCont1),
+ sizeof(UInt16));
+/*
+ this->SetHandler((ReadFunction)&EmRegsVZHandEra330::spiIntCSRead,
+ (WriteFunction)&EmRegsVZHandEra330::spiIntCSWrite,
+ addressof(spiIntCS),
+ sizeof(regs.spiIntCS));
+*/
+}
diff --git a/SrcShared/Hardware/EmRegsVZHandEra330.h b/SrcShared/Hardware/EmRegsVZHandEra330.h
new file mode 100644
index 0000000..154ad23
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZHandEra330.h
@@ -0,0 +1,142 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZHandEra330_h
+#define EmRegsVZHandEra330_h
+
+#include "EmRegsVZ.h"
+#include "EmHandEra330Defs.h"
+#include "EmPalmStructs.h"
+#include "EmTRGSD.h"
+
+#define keyBitThumbDown 0x1000
+#define keyBitThumbUp 0x2000
+#define keyBitThumbPush 0x4000
+
+#define PortB_CF_CS 0x0001
+#define PortB_RS232_ON 0x0040
+
+#define PortD_KBD_COL0 0x0001
+#define PortD_KBD_COL1 0x0002
+#define PortD_KBD_COL2 0x0004
+#define PortD_KBD_COL3 0x0008
+#define PortD_DOCK_BTN 0x0010
+#define PortD_CD_IRQ 0x0020
+#define PortD_CF_IRQ 0x0040
+#define PortD_POWER_FAIL 0x0080
+
+#define PortF_LCD_PWM 0x0001
+#define PortF_PEN_IO 0x0002
+#define PortF_CLK_OUT 0x0004
+#define PortF_A20 0x0008
+#define PortF_A21 0x0010
+#define PortF_A22 0x0020
+#define PortF_A23 0x0040
+#define PortF_CPLD_CS_F 0x0080
+
+#define PortG_DTACK 0x0001
+#define PortG_A0 0x0002
+#define PortG_Unused 0x0004
+#define PortG_CPLD_TMS 0x0008
+#define PortG_LION 0x0010
+#define PortG_Unused2 0x0020
+
+#define PortJ_SPI_TX 0x0001
+#define PortJ_SPI_RX 0x0002
+#define PortJ_SPI_CLK 0x0004
+#define PortJ_AD_CS 0x0008
+#define PortJ_232_RX2 0x0010
+#define PortJ_232_TX2 0x0020
+#define PortJ_232_RTS2 0x0040
+#define PortJ_232_CTS2 0x0080
+
+#define PortK_VOL_PWM 0x0001
+#define PortK_GP_IN_F 0x0002
+#define PortK_LED_GREEN 0x0004
+#define PortK_LED_RED 0x0008
+#define PortK_CPLD_TDO 0x0010
+#define PortK_Unused 0x0020
+#define PortK_CPLD_TCK 0x0040
+#define PortK_Unused2 0x0020
+
+#define PortM_SD_CLK 0x0001
+#define PortM_SD_CE 0x0002
+#define PortM_SD_DQMH 0x0004
+#define PortM_SD_DQML 0x0008
+#define PortM_SD_A10 0x0010
+#define PortM_CPLD_TDI 0x0020
+
+class EmRegsVZHandEra330 : public EmRegsVZ
+{
+ public:
+ EmRegsVZHandEra330 (HandEra330PortManager ** fPortManager);
+ virtual ~EmRegsVZHandEra330 (void);
+
+ virtual void Initialize (void);
+ virtual void Dispose (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+ virtual Bool GetVibrateOn (void);
+ virtual uint16 GetLEDState (void);
+ int32 GetROMSize (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+ virtual int32 GetInterruptLevel (void);
+ void SetSubBankHandlers (void);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+ virtual uint16 ButtonToBits (SkinElementType button);
+
+ private:
+ uint8 GetPortD(uint8 result);
+ UInt16 PortD;
+ UInt16 PortF;
+ UInt16 PortG;
+ UInt16 PortJ;
+ UInt16 PortK;
+ UInt16 PortM;
+ EmSPISlave* fSPISlaveADC;
+ EmSPISlave* fSPISlaveCurrent;
+ HandEra330PortManager PortMgr;
+ EmTRGSD SD;
+
+ uint16 rxFifo[8];
+ bool rxFifoEmpty;
+ int rxHead;
+ int rxTail;
+ uint16 txFifo[8];
+ bool txFifoEmpty;
+ int txHead;
+ int txTail;
+
+ void spiRxDWrite (emuptr address, int size, uint32 value);
+ uint32 spiRxDRead (emuptr address, int size);
+ void spiTxDWrite (emuptr address, int size, uint32 value);
+ uint32 spiTxDRead (emuptr address, int size);
+ void spiCont1Write (emuptr address, int size, uint32 value);
+ uint32 spiCont1Read (emuptr address, int size);
+ void spiIntCSWrite (emuptr address, int size, uint32 value);
+ uint32 spiIntCSRead (emuptr address, int size);
+};
+
+
+
+#endif /* EmRegsVZTemp_h */
+
diff --git a/SrcShared/Hardware/EmRegsVZPalmM500.cpp b/SrcShared/Hardware/EmRegsVZPalmM500.cpp
new file mode 100644
index 0000000..420de8b
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZPalmM500.cpp
@@ -0,0 +1,259 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZPalmM500.h"
+#include "EmRegsVZPrv.h"
+
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+#define hwrVZPortBALARM_LED 0x40 // (L) Alarm LED
+
+#define hwrVZPortDSpi1Card 0x20 // (-) SPI #1, slot 0, SD/MMC Card Detect EOR Wake EOR Ready (aka IRQ2)
+#define hwrVZPortDPowerFail 0x80 // (L) Power Fail interrupt (aka IRQ6)
+
+#define hwrVZPortGEL_ON 0x02 // (L) EL_ON
+#define hwrVZPortGADC_CS_N 0x04 // (H) ADC_CS#
+#define hwrVZPortG232_SHDN_N 0x08 // (L) 232_SHDN#
+
+#define hwrVZPortKLCDOn 0x02 // (-) LCD_DISP_ON (RW#)
+#define hwrVZPortKAC_PWR_N 0x04 // (-) AC_PWR# (LDS#)
+#define hwrVZPortKVibeEn 0x10 // (-) VIBE_EN
+#define hwrVZPortKKbdRow0 0x20 // (H) Keyboard Row 0
+#define hwrVZPortKKbdRow1 0x40 // (H) Keyboard Row 1
+#define hwrVZPortKKbdRow2 0x80 // (H) Keyboard Row 2
+
+#define hwrVZPortMIR_SD 0x20 // (L) Infrared Shut-down
+
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kGenericMonoMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::EmRegsVZPalmM500
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM500::EmRegsVZPalmM500 (void) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet1))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::~EmRegsVZPalmM500
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM500::~EmRegsVZPalmM500 (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM500::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portKData) & hwrVZPortKLCDOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM500::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrVZPortGEL_ON) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZPalmM500::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portGData) & hwrVZPortG232_SHDN_N) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portMData) & hwrVZPortMIR_SD) == 0;
+
+ if (type == kUARTMystery)
+ return true;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZPalmM500::GetUARTDevice (int uartNum)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ /*
+ From Michael Cortopassi:
+
+ UART 1 for IRda
+ UART 2 for hotsync
+ */
+
+ if (uartNum == 0)
+ {
+ if (irEnabled)
+ return kUARTIR;
+ }
+ else if (uartNum == 1)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetVibrateOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM500::GetVibrateOn (void)
+{
+ return (READ_REGISTER (portKData) & hwrVZPortKVibeEn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetLEDState
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsVZPalmM500::GetLEDState (void)
+{
+ uint16 result = kLEDOff;
+ UInt8 portBData = READ_REGISTER (portBData);
+
+ if (portBData & hwrVZPortBALARM_LED)
+ result |= kLEDGreen;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZPalmM500::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ if (port == 'K')
+ {
+ // Make sure hwrVZPortKAC_PWR_N is set, or the dock-status routines
+ // will report that we're powered (even if we aren't docked!).
+
+ result |= hwrVZPortKAC_PWR_N;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZPalmM500::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrVZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+ //
+ // Also make sure that hwrVZPortDSpi1Card is set. If it's clear,
+ // the slot driver will think there's a card installed and will try querying it.
+
+ result |= hwrVZPortDPowerFail | hwrVZPortDSpi1Card;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM500::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kGenericMonoMap, sizeof (kGenericMonoMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDir = READ_REGISTER (portKDir);
+ UInt8 portKData = READ_REGISTER (portKData);
+
+ rows[0] = (portKDir & hwrVZPortKKbdRow0) != 0 && (portKData & hwrVZPortKKbdRow0) == 0;
+ rows[1] = (portKDir & hwrVZPortKKbdRow1) != 0 && (portKData & hwrVZPortKKbdRow1) == 0;
+ rows[2] = (portKDir & hwrVZPortKKbdRow2) != 0 && (portKData & hwrVZPortKKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM500::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZPalmM500::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrVZPortGADC_CS_N) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
diff --git a/SrcShared/Hardware/EmRegsVZPalmM500.h b/SrcShared/Hardware/EmRegsVZPalmM500.h
new file mode 100644
index 0000000..81fe5b4
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZPalmM500.h
@@ -0,0 +1,44 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZPalmM500_h
+#define EmRegsVZPalmM500_h
+
+#include "EmRegsVZ.h"
+
+class EmRegsVZPalmM500 : public EmRegsVZ
+{
+ public:
+ EmRegsVZPalmM500 (void);
+ virtual ~EmRegsVZPalmM500 (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+ virtual Bool GetVibrateOn (void);
+ virtual uint16 GetLEDState (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsVZPalmM500_h */
diff --git a/SrcShared/Hardware/EmRegsVZPalmM505.cpp b/SrcShared/Hardware/EmRegsVZPalmM505.cpp
new file mode 100644
index 0000000..938a4e6
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZPalmM505.cpp
@@ -0,0 +1,151 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZPalmM505.h"
+#include "EmRegsVZPrv.h"
+
+#include "EmBankRegs.h" // EmBankRegs::DisableSubBank
+#include "EmRegsSED1376.h" // sed1376RegsAddr
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::EmRegsVZPalmM505
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM505::EmRegsVZPalmM505 (void) :
+ EmRegsVZPalmM500 ()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::~EmRegsVZPalmM505
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM505::~EmRegsVZPalmM505 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM505::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegsVZ::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ this->SetHandler ((ReadFunction) &EmRegsVZ::StdRead,
+ (WriteFunction) &EmRegsVZPalmM505::portFSelectWrite,
+ addressof (portFSelect), sizeof (f68VZ328Regs.portFSelect));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZ::portFSelectWrite
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM505::portFSelectWrite (emuptr address, int size, uint32 value)
+{
+ uint8 oldPortFSelect = READ_REGISTER (portFSelect);
+
+ // Do a standard update of the register.
+
+ EmRegsVZ::StdWrite (address, size, value);
+
+ uint8 portFSelect = READ_REGISTER (portFSelect);
+
+#define hwrVZPortFBusClock 0x04 // (P) Bus Clock
+
+ if (((portFSelect ^ oldPortFSelect) & hwrVZPortFBusClock) != 0)
+ {
+ if ((portFSelect & hwrVZPortFBusClock) != 0)
+ {
+ EmBankRegs::DisableSubBank (sed1376RegsAddr);
+ EmBankRegs::DisableSubBank (sed1376VideoMemStart);
+ }
+ else
+ {
+ EmBankRegs::EnableSubBank (sed1376RegsAddr);
+ EmBankRegs::EnableSubBank (sed1376VideoMemStart);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM505::GetLCDScreenOn (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDScreenOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM505::GetLCDBacklightOn (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDBacklightOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM505::GetLCDHasFrame (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDHasFrame ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM505::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ EmHALHandler::GetLCDBeginEnd (begin, end);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM505::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM505::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ EmHALHandler::GetLCDScanlines (info);
+}
+
+
+
diff --git a/SrcShared/Hardware/EmRegsVZPalmM505.h b/SrcShared/Hardware/EmRegsVZPalmM505.h
new file mode 100644
index 0000000..7488855
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZPalmM505.h
@@ -0,0 +1,36 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZPalmM505_h
+#define EmRegsVZPalmM505_h
+
+#include "EmRegsVZPalmM500.h"
+
+class EmRegsVZPalmM505 : public EmRegsVZPalmM500
+{
+ public:
+ EmRegsVZPalmM505 (void);
+ virtual ~EmRegsVZPalmM505 (void);
+
+ virtual void SetSubBankHandlers (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+
+ void portFSelectWrite (emuptr address, int size, uint32 value);
+};
+
+#endif /* EmRegsVZPalmM505_h */
diff --git a/SrcShared/Hardware/EmRegsVZPrv.h b/SrcShared/Hardware/EmRegsVZPrv.h
new file mode 100644
index 0000000..02e9779
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZPrv.h
@@ -0,0 +1,45 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZPrv_h
+#define EmRegsVZPrv_h
+
+#include "EmRegsPrv.h"
+
+// Location and range of registers
+
+const uint32 kMemoryStart = 0xFFFFF000;
+const uint32 kMemorySize = sizeof (HwrM68VZ328Type);
+
+
+// Macro to return the DragonballVZ address of the specified register
+
+#define addressof(x) (kMemoryStart + offsetof(HwrM68VZ328Type, x))
+
+
+// Macros for reading/writing DragonballVZ registers.
+
+#define READ_REGISTER(reg) \
+ _get_reg (&f68VZ328Regs.reg)
+
+#define WRITE_REGISTER(reg, value) \
+ _put_reg (&f68VZ328Regs.reg, value)
+
+
+// Macro for installing DragonballVZ register handlers
+
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ((ReadFunction) &EmRegsVZ::read, (WriteFunction) &EmRegsVZ::write, addressof (reg), sizeof (f68VZ328Regs.reg))
+
+
+#endif /* EmRegsVZPrv_h */
diff --git a/SrcShared/Hardware/EmRegsVZTemp.cpp b/SrcShared/Hardware/EmRegsVZTemp.cpp
new file mode 100644
index 0000000..36a8521
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZTemp.cpp
@@ -0,0 +1,848 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZTemp.h"
+#include "EmRegsVZPrv.h"
+
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+#include "EmTransportSerial.h" // EmTransportSerial
+
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 4;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { keyBitPageUp, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitContrast, keyBitHard2, 0 }
+};
+
+
+
+#pragma mark -
+#define hwrVZPortBRADIO_DTR 0x40 // (L) Radio DTR
+#define hwrVZPortKRADIO_DSR 0x02 // Radio DTR
+
+#define hwrVZPalmI705PortDTWISTIRQ 0x20 // Twister IRQ (IRQ2)
+#define hwrVZPalmI705PortDPowerFail 0x80 // (L) Power Fail interrupt (aka IRQ6)
+
+#define hwrVZPalmI705PortGEL_ON 0x02 // (L) EL_ON
+#define hwrVZPalmI705PortGLCD_DISP_ON 0x04 // (H) LCD_DISP_ON
+#define hwrVZPalmI705PortG232_SHDN_N 0x08 // (L) 232_SHDN#
+#define hwrVZPalmI705PortGADC_CS_N 0x20 // (H) ADC_CS#
+
+#define hwrVZPalmI705PortKVIB_EN 0x10 // vibarator enable/disable
+#define hwrVZPalmI705PortKKbdRow0 0x20 // (H) Keyboard Row 0
+#define hwrVZPalmI705PortKKbdRow1 0x40 // (H) Keyboard Row 1
+#define hwrVZPalmI705PortKKbdRow2 0x80 // (H) Keyboard Row 2
+
+#define hwrVZPalmI705PortMIR_SD 0x20 // (L) Infrared Shut-down (UART 2)
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::EmRegsVZPalmI705
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmI705::EmRegsVZPalmI705 (void) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet1))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::~EmRegsVZPalmI705
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmI705::~EmRegsVZPalmI705 (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmI705::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrVZPalmI705PortGLCD_DISP_ON) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmI705::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrVZPalmI705PortGEL_ON) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZPalmI705::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portGData) & hwrVZPalmI705PortG232_SHDN_N) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portMData) & hwrVZPalmI705PortMIR_SD) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZPalmI705::GetUARTDevice (int uartNum)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ /*
+ From Van Oler:
+
+ UART #2 is used for serial (rs-232) and IR. The rs-232 receiver
+ and the IR receiver are tristate outouts with individual enables
+ to control which one drives the RXD2 input.
+
+ UART1 is not used; only the pins are used for GPIO.
+
+ The Master SPI (on PE0,1,2) is used for data to and from the
+ touchscreen A/D and the radio DSP. Each has individual selects.
+
+ The Master/Slave SPI (on PJ0,1,2) is used for the MMC/SD card slot.
+
+ There is a separate USB chip, the same as tornado.
+ */
+
+ if (uartNum == 1)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetVibrateOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmI705::GetVibrateOn (void)
+{
+ return (READ_REGISTER (portKData) & hwrVZPalmI705PortKVIB_EN) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZPalmI705::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZPalmI705::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrVZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+ //
+ // Also make sure that hwrVZPalmI705PortDTWISTIRQ is set. If it's clear,
+ // the slot driver will think there's a card installed and will try querying it.
+
+ result |= hwrVZPalmI705PortDPowerFail | hwrVZPalmI705PortDTWISTIRQ;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmI705::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDir = READ_REGISTER (portKDir);
+ UInt8 portKData = READ_REGISTER (portKData);
+
+ rows[0] = (portKDir & hwrVZPalmI705PortKKbdRow0) != 0 && (portKData & hwrVZPalmI705PortKKbdRow0) == 0;
+ rows[1] = (portKDir & hwrVZPalmI705PortKKbdRow1) != 0 && (portKData & hwrVZPalmI705PortKKbdRow1) == 0;
+ rows[2] = (portKDir & hwrVZPalmI705PortKKbdRow2) != 0 && (portKData & hwrVZPalmI705PortKKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmI705::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZPalmI705::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrVZPalmI705PortGADC_CS_N) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
+
+
+#pragma mark -
+
+#define hwrVZPalmM125PortDTWISTIRQ 0x20 // Twister IRQ (IRQ2)
+#define hwrVZPalmM125PortDPowerFail 0x80 // (L) Power Fail interrupt (aka IRQ6)
+
+#define hwrVZPalmM125PortGEL_ON 0x02 // (L) EL_ON
+#define hwrVZPalmM125PortGLCD_DISP_ON 0x04 // (H) LCD_DISP_ON
+#define hwrVZPalmM125PortG232_SHDN_N 0x08 // (L) 232_SHDN#
+#define hwrVZPalmM125PortGADC_CS_N 0x20 // (H) ADC_CS#
+
+#define hwrVZPalmM125PortKIRShutdown 0x04 // (-) IR_SHDN
+#define hwrVZPalmM125PortKVIB_EN 0x10 // vibarator enable/disable
+#define hwrVZPalmM125PortKKbdRow0 0x20 // (H) Keyboard Row 0
+#define hwrVZPalmM125PortKKbdRow1 0x40 // (H) Keyboard Row 1
+#define hwrVZPalmM125PortKKbdRow2 0x80 // (H) Keyboard Row 2
+
+const uint16 kButtonMapPalmM125[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { 0, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitPageUp, 0, 0 }
+};
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::EmRegsVZPalmM125
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM125::EmRegsVZPalmM125 (void) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet3))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::~EmRegsVZPalmM125
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM125::~EmRegsVZPalmM125 (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM125::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portKData) & 0x02) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM125::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portFData) & 0x10) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZPalmM125::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portEData) & 0x40) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portKData) & hwrVZPalmM125PortKIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZPalmM125::GetUARTDevice (int uartNum)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ if (uartNum == 0)
+ {
+ if (irEnabled)
+ return kUARTIR;
+ }
+ else if (uartNum == 1)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZPalmM125::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZPalmM125::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrVZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+ //
+ // Also make sure that hwrVZPalmM125PortDTWISTIRQ is set. If it's clear,
+ // the slot driver will think there's a card installed and will try querying it.
+
+ result |= hwrVZPalmM125PortDPowerFail | hwrVZPalmM125PortDTWISTIRQ;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM125::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMapPalmM125, sizeof (kButtonMapPalmM125));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDir = READ_REGISTER (portKDir);
+ UInt8 portKData = READ_REGISTER (portKData);
+
+ rows[0] = (portKDir & hwrVZPalmM125PortKKbdRow0) != 0 && (portKData & hwrVZPalmM125PortKKbdRow0) == 0;
+ rows[1] = (portKDir & hwrVZPalmM125PortKKbdRow1) != 0 && (portKData & hwrVZPalmM125PortKKbdRow1) == 0;
+ rows[2] = (portKDir & hwrVZPalmM125PortKKbdRow2) != 0 && (portKData & hwrVZPalmM125PortKKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM125::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZPalmM125::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrVZPalmM125PortGADC_CS_N) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
+#pragma mark -
+
+#define hwrVZPalmM130PortDTWISTIRQ 0x20 // Twister IRQ (IRQ2)
+#define hwrVZPalmM130PortDPowerFail 0x80 // (L) Power Fail interrupt (aka IRQ6)
+
+#define hwrVZPalmM130PortGEL_ON 0x02 // (L) EL_ON
+#define hwrVZPalmM130PortGLCD_DISP_ON 0x04 // (H) LCD_DISP_ON
+#define hwrVZPalmM130PortG232_SHDN_N 0x08 // (L) 232_SHDN#
+#define hwrVZPalmM130PortGADC_CS_N 0x20 // (H) ADC_CS#
+
+#define hwrVZPalmM130PortKIRShutdown 0x04 // (-) IR_SHDN
+#define hwrVZPalmM130PortKVIB_EN 0x10 // vibarator enable/disable
+#define hwrVZPalmM130PortKKbdRow0 0x20 // (H) Keyboard Row 0
+#define hwrVZPalmM130PortKKbdRow1 0x40 // (H) Keyboard Row 1
+#define hwrVZPalmM130PortKKbdRow2 0x80 // (H) Keyboard Row 2
+
+const uint16 kButtonMapPalmM130[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3, keyBitHard4 },
+ { 0, keyBitPageDown, 0, 0 },
+ { keyBitPower, keyBitPageUp, 0, 0 }
+};
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::EmRegsVZPalmM130
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM130::EmRegsVZPalmM130 (void) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet1))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::~EmRegsVZPalmM130
+// ---------------------------------------------------------------------------
+
+EmRegsVZPalmM130::~EmRegsVZPalmM130 (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM130::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portKData) & 0x02) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZPalmM130::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portFData) & 0x10) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZPalmM130::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ return (READ_REGISTER (portEData) & 0x40) != 0;
+
+ if (type == kUARTIR)
+ return (READ_REGISTER (portKData) & hwrVZPalmM130PortKIRShutdown) == 0;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZPalmM130::GetUARTDevice (int uartNum)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ if (uartNum == 0)
+ {
+ if (irEnabled)
+ return kUARTIR;
+ }
+ else if (uartNum == 1)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetPortInputValue
+// ---------------------------------------------------------------------------
+// Return the GPIO values for the pins on the port. These values are used
+// if the select pins are high.
+
+uint8 EmRegsVZPalmM130::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetPortInternalValue
+// ---------------------------------------------------------------------------
+// Return the dedicated values for the pins on the port. These values are
+// used if the select pins are low.
+
+uint8 EmRegsVZPalmM130::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Make sure that hwrVZPortDPowerFail is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+ //
+ // Also make sure that hwrVZPalmM130PortDTWISTIRQ is set. If it's clear,
+ // the slot driver will think there's a card installed and will try querying it.
+
+ result |= hwrVZPalmM130PortDPowerFail | hwrVZPalmM130PortDTWISTIRQ;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZPalmM130::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMapPalmM130, sizeof (kButtonMapPalmM130));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDir = READ_REGISTER (portKDir);
+ UInt8 portKData = READ_REGISTER (portKData);
+
+ rows[0] = (portKDir & hwrVZPalmM130PortKKbdRow0) != 0 && (portKData & hwrVZPalmM130PortKKbdRow0) == 0;
+ rows[1] = (portKDir & hwrVZPalmM130PortKKbdRow1) != 0 && (portKData & hwrVZPalmM130PortKKbdRow1) == 0;
+ rows[2] = (portKDir & hwrVZPalmM130PortKKbdRow2) != 0 && (portKData & hwrVZPalmM130PortKKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZPalmM130::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZPalmM130::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrVZPalmM130PortGADC_CS_N) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
+#pragma mark -
+
+// Given a register (specified by its field name), return its address
+// in emulated space.
+
+#undef addressof
+#define addressof(reg) \
+ (this->GetAddressStart () + fRegs.offsetof_##reg ())
+
+
+// Macro to help the installation of handlers for a register.
+
+#undef INSTALL_HANDLER
+#define INSTALL_HANDLER(read, write, reg) \
+ this->SetHandler ( (ReadFunction) &EmRegsPLDPalmI705::read, \
+ (WriteFunction) &EmRegsPLDPalmI705::write, \
+ addressof (reg), \
+ fRegs.reg.GetSize ())
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::EmRegsPLDPalmI705
+// ---------------------------------------------------------------------------
+
+EmRegsPLDPalmI705::EmRegsPLDPalmI705 (emuptr baseAddr) :
+ fBaseAddr (baseAddr)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::~EmRegsPLDPalmI705
+// ---------------------------------------------------------------------------
+
+EmRegsPLDPalmI705::~EmRegsPLDPalmI705 (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::Initialize (void)
+{
+ EmRegs::Initialize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::Reset
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::Reset (Bool hardwareReset)
+{
+ EmRegs::Reset (hardwareReset);
+
+ if (hardwareReset)
+ {
+ memset (fRegs.GetPtr (), 0, fRegs.GetSize ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::Save
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::Save (SessionFile& f)
+{
+ EmRegs::Save (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::Load
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::Load (SessionFile& f)
+{
+ EmRegs::Load (f);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::Dispose
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::Dispose (void)
+{
+ EmRegs::Dispose ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::GetLEDState
+// ---------------------------------------------------------------------------
+
+uint16 EmRegsPLDPalmI705::GetLEDState (void)
+{
+ uint16 result = kLEDOff;
+
+ if (fRegs.green_led)
+ result |= kLEDGreen;
+
+ if (fRegs.red_led)
+ result |= kLEDRed;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+
+void EmRegsPLDPalmI705::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers ();
+
+ // Now add standard/specialized handers for the defined registers.
+
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, todsln3);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, green_led);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, pin_notify_enable);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, red_led);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, acpr);
+ INSTALL_HANDLER (low_battRead, StdWriteBE, low_batt);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dto3svc_irq);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dsp_irq_enable);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, dsp_irq_polarity);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, charging_in_progress);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, charging_in_prog2);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, charging_in_prog_OE);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, twister_irq_wake);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, low_batt_mask);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, acpr_mask);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, acpr_polarity);
+ INSTALL_HANDLER (usb_intRead, StdWriteBE, usb_int);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, usb_int_mask);
+ INSTALL_HANDLER (bullet_detRead, StdWriteBE, bullet_det);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, bullet_det_mask);
+ INSTALL_HANDLER (StdReadBE, StdWriteBE, bullet_det_pol);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::GetRealAddress
+// ---------------------------------------------------------------------------
+
+uint8* EmRegsPLDPalmI705::GetRealAddress (emuptr address)
+{
+ return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::GetAddressStart
+// ---------------------------------------------------------------------------
+
+emuptr EmRegsPLDPalmI705::GetAddressStart (void)
+{
+ return fBaseAddr;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::GetAddressRange
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmI705::GetAddressRange (void)
+{
+ return fRegs.GetSize ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::low_battRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmI705::low_battRead (emuptr address, int size)
+{
+ uint32 reg = StdReadBE (address, size);
+
+#define hwrPLDlow_battOn 0 //this is inverted!
+#define hwrPLDlow_battOff 0x80
+
+ // If we're reading the whole register, or if we're reading the second
+ // byte, then set the bit that says that the low-battery condition is off.
+
+ if ((size == 2) || ((size == 1) && ((address & 1) == 1)))
+ {
+ reg |= hwrPLDlow_battOff;
+ }
+
+ return reg;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::usb_intRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmI705::usb_intRead (emuptr /*address*/, int /*size*/)
+{
+ // this bit is low-asserted
+
+ return ~0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsPLDPalmI705::bullet_detRead
+// ---------------------------------------------------------------------------
+
+uint32 EmRegsPLDPalmI705::bullet_detRead (emuptr /*address*/, int /*size*/)
+{
+ // 1 = undocked, 0 = docked
+
+ return ~0;
+}
+
+
diff --git a/SrcShared/Hardware/EmRegsVZTemp.h b/SrcShared/Hardware/EmRegsVZTemp.h
new file mode 100644
index 0000000..3864ca7
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZTemp.h
@@ -0,0 +1,130 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZTemp_h
+#define EmRegsVZTemp_h
+
+#include "EmRegsVZ.h"
+
+#include "EmPalmStructs.h" // EmProxyHwrPalmI705PLDType
+
+
+
+class EmRegsVZPalmI705 : public EmRegsVZ
+{
+ public:
+ EmRegsVZPalmI705 (void);
+ virtual ~EmRegsVZPalmI705 (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+ virtual Bool GetVibrateOn (void);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+
+
+
+class EmRegsVZPalmM125 : public EmRegsVZ
+{
+ public:
+ EmRegsVZPalmM125 (void);
+ virtual ~EmRegsVZPalmM125 (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+
+class EmRegsVZPalmM130 : public EmRegsVZ
+{
+ public:
+ EmRegsVZPalmM130 (void);
+ virtual ~EmRegsVZPalmM130 (void);
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+
+class EmRegsPLDPalmI705 : public EmRegs, public EmHALHandler
+{
+ public:
+ EmRegsPLDPalmI705 (emuptr);
+ virtual ~EmRegsPLDPalmI705 (void);
+
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ virtual uint16 GetLEDState (void);
+
+ virtual void SetSubBankHandlers (void);
+ virtual uint8* GetRealAddress (emuptr address);
+ virtual emuptr GetAddressStart (void);
+ virtual uint32 GetAddressRange (void);
+
+ private:
+ uint32 low_battRead (emuptr address, int size);
+ uint32 usb_intRead (emuptr address, int size);
+ uint32 bullet_detRead (emuptr address, int size);
+
+ emuptr fBaseAddr;
+ EmProxyHwrPalmI705PLDType fRegs;
+};
+
+typedef EmRegsPLDPalmI705 EmRegsPLDJabba;
+
+
+
+#endif /* EmRegsVZTemp_h */
diff --git a/SrcShared/Hardware/EmRegsVZVisorEdge.cpp b/SrcShared/Hardware/EmRegsVZVisorEdge.cpp
new file mode 100644
index 0000000..2717990
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorEdge.cpp
@@ -0,0 +1,166 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsEZVisor.h"
+#include "EmRegsVZVisorEdge.h"
+#include "EmRegsVZPrv.h"
+
+
+// Implementation of register-handling for Visor Edge. Visor Edge is derived
+// from Visor Platinum with the following differences:
+// - key setup is identical to Visor Prism
+// - "LCD Enable On" pin is in a different location
+// - backlight pin is active high and in different place
+
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortBLCDVccOff 0x08 // (L) LCD Vcc
+#define hwrVisorEdgePortBLCDAdjOn 0x40 // (H) LCD Contrast Voltage
+
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortDKbdCol0On 0x01 // (H) Keyboard Column 0
+#define hwrVisorEdgePortDKbdCol1On 0x02 // (H) Keyboard Column 1
+#define hwrVisorEdgePortDKbdCol2On 0x04 // (H) Keyboard Column 2
+
+#define hwrVisorEdgePortDExtPowerOn 0x08 // (H) External power indicator
+
+#define hwrVisorEdgePortDDock1IrqOff 0x10 // (L) Dock1 interrupt
+#define hwrVisorEdgePortDSlotIrqOff 0x20 // (L) Slot Interrupt
+#define hwrVisorEdgePortDUsbIrqOff 0x40 // (L) USB Interrupt
+#define hwrVisorEdgePortDCardInstIrqOff 0x80 // (L) Card Installed Interrupt
+
+#define hwrVisorEdgePortDKeyBits 0x07 // (H) All Keyboard Columns
+
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortESerialTxD 0x20 // ( ) Serial transmit line
+#define hwrVisorEdgePortESlotResetOff 0x40 // (L) Slot reset
+#define hwrVisorEdgePortEDock2Off 0x80 // (L) Dock2 input
+
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortFContrast 0x01 // ( ) LCD Contrast PWM output
+#define hwrVisorEdgePortFIREnableOff 0x04 // (L) Shutdown IR
+#define hwrVisorEdgePortFUsbCsOff 0x80 // (L) USB chip select
+
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortGUnused0 0x01 // ( ) unused GPIO (after reset)
+#define hwrVisorEdgePortGUsbSuspend 0x02 // (X) USB Suspend bit - Output low for active
+ // - Input for suspend
+#define hwrVisorEdgePortGPowerFailIrqOff 0x04 // (L) Power Fail IRQ
+#define hwrVisorEdgePortGKbdRow0 0x08 // (H) Keyboard Row 0
+#define hwrVisorEdgePortGKbdRow1 0x10 // (H) Keyboard Row 1
+#define hwrVisorEdgePortGAdcCsOff 0x20 // (L) A/D Select
+
+
+/************************************************************************
+ * Port J Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortJUnused0 0x01 // (X) unused GPIO
+#define hwrVisorEdgePortJUnused1 0x02 // (X) unused GPIO
+#define hwrVisorEdgePortJUnused2 0x04 // (X) unused GPIO
+#define hwrVisorEdgePortJUnused3 0x08 // (X) unused GPIO
+#define hwrVisorEdgePortJSerial2RxD 0x10 // ( ) Serial (UART2) recieve line
+#define hwrVisorEdgePortJSerial2TxD 0x20 // ( ) Serial (UART2) transmit line
+#define hwrVisorEdgePortJSerial2Rts 0x40 // ( ) Serial (UART2) RTS
+#define hwrVisorEdgePortJSerial2Cts 0x80 // ( ) Serial (UART2) CTS
+
+
+/************************************************************************
+ * Port K Bit settings
+ ************************************************************************/
+#define hwrVisorEdgePortKUnused0 0x01 // (X) unused GPIO
+#define hwrVisorEdgePortKKbdRow2 0x02 // (H) Keyboard Row 2
+#define hwrVisorEdgePortKUnused2 0x04 // (X) unused GPIO
+#define hwrVisorEdgePortKUnused3 0x08 // (X) unused GPIO
+
+#define hwrVisorEdgePortKLedOn 0x10 // (L) Turn on LED
+#define hwrVisorEdgePortKLCDEnableOn 0x20 // (L) Shutdown IR
+#define hwrVisorEdgePortKBacklightOn 0x40 // (H) Backlight on/off
+#define hwrVisorEdgePortKUsbResetOff 0x80 // (L) USB reset
+
+
+/************************************************************************
+ * Port M Bit settings
+ ************************************************************************/
+
+#define hwrVisorEdgePortMChargerOff 0x01 // (L) Assert (drive low) to enable
+ // charger. Deassert for 1ms
+ // to restart charger
+#define hwrVisorEdgePortMChargerOn 0x04 // (H) Assert (drive high) to enable
+ // charger. Deassert for 1ms
+ // to restart charger
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorEdge::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorEdge::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portKData) & hwrVisorEdgePortKLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorEdge::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorEdge::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portKData) & hwrVisorEdgePortKBacklightOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorEdge::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZVisorEdge::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kVisorButtonMap, sizeof (kVisorButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDir = READ_REGISTER (portKDir);
+ UInt8 portKData = READ_REGISTER (portKData);
+
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGData = READ_REGISTER (portGData);
+
+ rows[0] = (portGDir & hwrVisorEdgePortGKbdRow0) != 0 && (portGData & hwrVisorEdgePortGKbdRow0) == 0;
+ rows[1] = (portGDir & hwrVisorEdgePortGKbdRow1) != 0 && (portGData & hwrVisorEdgePortGKbdRow1) == 0;
+ rows[2] = (portKDir & hwrVisorEdgePortKKbdRow2) != 0 && (portKData & hwrVisorEdgePortKKbdRow2) == 0;
+}
diff --git a/SrcShared/Hardware/EmRegsVZVisorEdge.h b/SrcShared/Hardware/EmRegsVZVisorEdge.h
new file mode 100644
index 0000000..49cb53e
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorEdge.h
@@ -0,0 +1,30 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZVisorVisorEdge_h
+#define EmRegsVZVisorVisorEdge_h
+
+#include "EmRegsVZ.h"
+#include "EmRegsVZVisorPlatinum.h"
+
+class EmRegsVZVisorEdge: public EmRegsVZVisorPlatinum
+{
+ public:
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+};
+
+#endif /* EmRegsVZVisorVisorEdge_h */
diff --git a/SrcShared/Hardware/EmRegsVZVisorPlatinum.cpp b/SrcShared/Hardware/EmRegsVZVisorPlatinum.cpp
new file mode 100644
index 0000000..c6ebb5a
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorPlatinum.cpp
@@ -0,0 +1,262 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZVisorPlatinum.h"
+#include "EmRegsEZVisor.h"
+#include "EmRegsVZPrv.h"
+
+#include "EmSession.h" // GetDevice
+#include "EmDevice.h" // HardwareID
+#include "EmSPISlaveADS784x.h" // EmSPISlaveADS784x
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::EmRegsEZVisor
+// ---------------------------------------------------------------------------
+
+EmRegsVZVisorPlatinum::EmRegsVZVisorPlatinum (void) :
+ EmRegsVZ (),
+ fSPISlaveADC (new EmSPISlaveADS784x (kChannelSet2))
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsEZVisor::~EmRegsEZVisor
+// ---------------------------------------------------------------------------
+
+EmRegsVZVisorPlatinum::~EmRegsVZVisorPlatinum (void)
+{
+ delete fSPISlaveADC;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorPlatinum::GetLCDScreenOn (void)
+{
+ return (READ_REGISTER (portCData) & hwrLegoPortCLCDEnableOn) != 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorPlatinum::GetLCDBacklightOn (void)
+{
+ return (READ_REGISTER (portGData) & hwrLegoPortGBacklightOff) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+
+Bool EmRegsVZVisorPlatinum::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) == 0;
+ }
+
+ if (type == kUARTIR)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) != 0;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZVisorPlatinum::GetUARTDevice (int /*uartNum*/)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ // !!! Which UART are they using?
+
+// if (uartNum == ???)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetPortInputValue
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZVisorPlatinum::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ /*
+ Support the Visor model ID. From Bob Petersen at Handspring:
+
+ The Visor ROM only works with 1 device so far. But, the Visor does have
+ model detect pins so that future ROMs can work on multiple platforms. The
+ model input pins are connected to port E, bits 0-2 (E[0-2]). To read them,
+ you have to drive port G bit 2 low and enable the pullups on port E.
+ */
+
+#define modelOutPin 0x04 // EMUIRQ (IRQ7)
+#define modelInPins 0x07 // SPI pins on Visor
+
+ UInt8 portGData = READ_REGISTER (portGData);
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGSelect = READ_REGISTER (portGSelect);
+
+ if (((portGData & modelOutPin) == 0) &&
+ ((portGDir & modelOutPin) == modelOutPin) &&
+ ((portGSelect & modelOutPin) == modelOutPin))
+ {
+ EmDevice device = gSession->GetDevice ();
+ result |= (~device.HardwareID ()) & modelInPins; // <chg 24-Apr-2000 BP> expects inverse output
+ }
+ else
+ {
+ // The pin for detecting "in cradle" is hwrLegoPortEDock2Off. It should be low
+ // if in the serial cradle. If it is high, we assume USB.
+ // -- Bob Petersen
+
+ result &= ~hwrLegoPortEDock2Off;
+ }
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrLegoPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrLegoPortGPowerFailIrqOff;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetPortInternalValue
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZVisorPlatinum::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Always set the high bit, indicating that there's no memory module
+ // installed. From Bob Petersen at Handspring:
+ //
+ // This is a probe into the module memory, to check for a replacement ROM on a
+ // card that is plugged in. The card is mapped to 0x20000000 and the card's
+ // ROM is at 0x28000000. If it finds the card header (FEEDBEEF) and the card
+ // is plugged in that has a non-zero reset vector, the chip selects are changed
+ // so B0 addresses 10c00000, and then we jump to the reset vector and boot off
+ // the card.
+ //
+ // This part of the boot code should only be called if it is detected that a
+ // card is currently plugged in (bit 7 of port D) and we aren't currently
+ // booting from the card.
+
+ result |= hwrLegoPortDCardInstIrqOff;
+
+ // Ensure that bit hwrLegoPortDDock1IrqOff is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ result |= hwrLegoPortDDock1IrqOff;
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrLegoPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrLegoPortGPowerFailIrqOff;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZVisorPlatinum::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kVisorButtonMap, sizeof (kVisorButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portDDir = READ_REGISTER (portDDir);
+ UInt8 portDData = READ_REGISTER (portDData);
+
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGData = READ_REGISTER (portGData);
+
+ rows[0] = (portGDir & hwrLegoPortGKbdRow0) != 0 && (portGData & hwrLegoPortGKbdRow0) == 0;
+ rows[1] = (portGDir & hwrLegoPortGKbdRow1) != 0 && (portGData & hwrLegoPortGKbdRow1) == 0;
+ rows[2] = (portDDir & hwrLegoPortDKbdRow2) != 0 && (portDData & hwrLegoPortDKbdRow2) == 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPlatinum::GetSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave* EmRegsVZVisorPlatinum::GetSPISlave (void)
+{
+ if ((READ_REGISTER (portGData) & hwrLegoPortGAdcCsOff) == 0)
+ {
+ return fSPISlaveADC;
+ }
+
+ return NULL;
+}
+
+
diff --git a/SrcShared/Hardware/EmRegsVZVisorPlatinum.h b/SrcShared/Hardware/EmRegsVZVisorPlatinum.h
new file mode 100644
index 0000000..b2aafa9
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorPlatinum.h
@@ -0,0 +1,43 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZVisorPlatinum_h
+#define EmRegsVZVisorPlatinum_h
+
+#include "EmRegsVZ.h"
+
+
+class EmRegsVZVisorPlatinum : public EmRegsVZ
+{
+ public:
+ EmRegsVZVisorPlatinum ();
+ ~EmRegsVZVisorPlatinum ();
+
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+
+ protected:
+ virtual EmSPISlave* GetSPISlave (void);
+
+ private:
+ EmSPISlave* fSPISlaveADC;
+};
+
+#endif /* EmRegsVZVisorPlatinum_h */
diff --git a/SrcShared/Hardware/EmRegsVZVisorPrism.cpp b/SrcShared/Hardware/EmRegsVZVisorPrism.cpp
new file mode 100644
index 0000000..6c73779
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorPrism.cpp
@@ -0,0 +1,393 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmRegsVZVisorPrism.h"
+#include "EmRegsVZPrv.h"
+
+#include "EmRegsSED1376.h" // SED1376 video controller register access
+
+#include "EmSession.h" // GetDevice
+#include "EmDevice.h" // HardwareID
+
+
+// Prism pin definitions from Handspring. Mostly the same as a Palm V,
+// but with some pins changed and moved around.
+
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortBLCDVccOff 0x08 // (L) LCD Vcc
+#define hwrVisorPrismPortBLCDAdjOn 0x40 // (H) LCD Contrast Voltage
+
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortCLCDEnableOn 0x80 // (H) LCD Enable
+
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortDKbdCol0On 0x01 // (H) Keyboard Column 0
+#define hwrVisorPrismPortDKbdCol1On 0x02 // (H) Keyboard Column 1
+#define hwrVisorPrismPortDKbdCol2On 0x04 // (H) Keyboard Column 2
+
+// Not here! See hwrVisorPrismPortKKbdRow2
+// #define hwrVisorPrismPortDKbdRow2 0x08 // (H) Keyboard Row 2
+
+#define hwrVisorPrismPortDDock1IrqOff 0x10 // (L) Dock1 interrupt
+#define hwrVisorPrismPortDSlotIrqOff 0x20 // (L) Slot Interrupt
+#define hwrVisorPrismPortDUsbIrqOff 0x40 // (L) USB Interrupt
+#define hwrVisorPrismPortDCardInstIrqOff 0x80 // (L) Card Installed Interrupt
+
+#define hwrVisorPrismPortDKeyBits 0x07 // (H) All Keyboard Columns
+
+
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortESerialTxD 0x20 // ( ) Serial transmit line
+#define hwrVisorPrismPortESlotResetOff 0x40 // (L) Slot reset
+#define hwrVisorPrismPortEDock2Off 0x80 // (L) Dock2 input
+
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortFContrast 0x01 // ( ) LCD Contrast PWM output
+#define hwrVisorPrismPortFIREnableOff 0x04 // (L) Shutdown IR
+#define hwrVisorPrismPortFUsbCsOff 0x80 // (L) USB chip select
+
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortGBacklightOff 0x01 // (L) Backlight on/off
+#define hwrVisorPrismPortGUSBSuspend 0x02 // (X) USB Suspend bit - Output low for active
+ // - Input for suspend
+#define hwrVisorPrismPortGPowerFailIrqOff 0x04 // (L) Power Fail IRQ
+#define hwrVisorPrismPortGKbdRow0 0x08 // (H) Keyboard Row 0
+#define hwrVisorPrismPortGKbdRow1 0x10 // (H) Keyboard Row 1
+#define hwrVisorPrismPortGAdcCsOff 0x20 // (L) A/D Select
+
+
+/************************************************************************
+ * Port J Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortJEepromDi 0x01 // (H) EEPROM Data in
+#define hwrVisorPrismPortJEepromDo 0x02 // ( ) EEPROM Data out
+#define hwrVisorPrismPortJEepromSkOn 0x04 // (H) EEPROM Clock
+#define hwrVisorPrismPortJEepromCsOn 0x08 // (H) EEPROM Chip Select
+#define hwrVisorPrismPortJUnused4 0x10 // (H) unused GPIO
+#define hwrVisorPrismPortJUnused5 0x20 // (H) unused GPIO
+#define hwrVisorPrismPortJUnused6 0x40 // (H) unused GPIO
+#define hwrVisorPrismPortJUnused7 0x80 // (H) unused GPIO
+
+
+/************************************************************************
+ * Port K Bit settings
+ ************************************************************************/
+#define hwrVisorPrismPortKBrightnessPWMOff 0x01 // (L) Brightness PWM output
+#define hwrVisorPrismPortKKbdRow2 0x02 // (H) Keyboard Row 2
+#define hwrVisorPrismPortKUnused2 0x04 // (X) unused GPIO
+#define hwrVisorPrismPortKIREnableBOff 0x08 // (L) Shutdown IR on DVT and later
+
+#define hwrVisorPrismPortKLcdResetOff 0x10 // (L) LCD reset
+#define hwrVisorPrismPortKIREnableAOff 0x20 // (L) Shutdown IR on pre-DVT
+#define hwrVisorPrismPortKUnused6 0x40 // (H) unused GPIO
+#define hwrVisorPrismPortKUsbResetOff 0x80 // (L) USB reset
+
+
+/************************************************************************
+ * Port M Bit settings
+ ************************************************************************/
+
+
+
+/************************************************************************
+ * Hard key settings
+ ************************************************************************/
+
+const int kNumButtonRows = 3;
+const int kNumButtonCols = 3;
+
+const uint16 kButtonMap[kNumButtonRows][kNumButtonCols] =
+{
+ { keyBitHard1, keyBitHard2, keyBitHard3 },
+ { keyBitPageUp, keyBitPageDown, 0 },
+ { keyBitPower, keyBitHard4, 0 }
+};
+
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLCDScreenOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorPrism::GetLCDScreenOn (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDScreenOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLCDBacklightOn
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorPrism::GetLCDBacklightOn (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDBacklightOn ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLCDHasFrame
+// ---------------------------------------------------------------------------
+
+Bool EmRegsVZVisorPrism::GetLCDHasFrame (void)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ return EmHALHandler::GetLCDHasFrame ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLCDBeginEnd
+// ---------------------------------------------------------------------------
+
+void EmRegsVZVisorPrism::GetLCDBeginEnd (emuptr& begin, emuptr& end)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ EmHALHandler::GetLCDBeginEnd (begin, end);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLCDScanlines
+// ---------------------------------------------------------------------------
+
+void EmRegsVZVisorPrism::GetLCDScanlines (EmScreenUpdateInfo& info)
+{
+ // Override the Dragonball version and let the SED 1376 handle it.
+
+ EmHALHandler::GetLCDScanlines (info);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetLineDriverState
+// ---------------------------------------------------------------------------
+// Return whether or not the line drivers for the given object are open or
+// closed.
+//
+// DOLATER BP: this way of detecting SerialPortOn may be wrong.
+// See PalmIIIc or PalmV. It may impact Visor emulation as well
+
+Bool EmRegsVZVisorPrism::GetLineDriverState (EmUARTDeviceType type)
+{
+ if (type == kUARTSerial)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) == 0;
+ }
+
+ if (type == kUARTIR)
+ {
+ uint16 uControl = READ_REGISTER (uControl);
+ uint16 uMisc = READ_REGISTER (uMisc);
+
+ return (uControl & hwrEZ328UControlUARTEnable) != 0 &&
+ (uMisc & hwrEZ328UMiscIRDAEn) != 0;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetUARTDevice
+// ---------------------------------------------------------------------------
+// Return what sort of device is hooked up to the given UART.
+
+EmUARTDeviceType EmRegsVZVisorPrism::GetUARTDevice (int /*uartNum*/)
+{
+ Bool serEnabled = this->GetLineDriverState (kUARTSerial);
+ Bool irEnabled = this->GetLineDriverState (kUARTIR);
+
+ // It's probably an error to have them both enabled at the same
+ // time. !!! TBD: make this an error message.
+
+ EmAssert (!(serEnabled && irEnabled));
+
+ // !!! Which UART are they using?
+
+// if (uartNum == ???)
+ {
+ if (serEnabled)
+ return kUARTSerial;
+
+ if (irEnabled)
+ return kUARTIR;
+ }
+
+ return kUARTNone;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetPortInputValue
+//
+// Returns the GPIO value of the given port.
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZVisorPrism::GetPortInputValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInputValue (port);
+
+ if (port == 'E')
+ {
+ /*
+ Support the Visor model ID. From Bob Petersen at Handspring:
+
+ The Visor ROM only works with 1 device so far. But, the Visor does have
+ model detect pins so that future ROMs can work on multiple platforms. The
+ model input pins are connected to port E, bits 0-2 (E[0-2]). To read them,
+ you have to drive port G bit 2 low and enable the pullups on port E.
+ */
+
+#define modelOutPin 0x04 // EMUIRQ (IRQ7)
+#define modelInPins 0x07 // SPI pins on Visor
+
+ UInt8 portGData = READ_REGISTER (portGData);
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGSelect = READ_REGISTER (portGSelect);
+
+ if (((portGData & modelOutPin) == 0) &&
+ ((portGDir & modelOutPin) == modelOutPin) &&
+ ((portGSelect & modelOutPin) == modelOutPin))
+ {
+ EmDevice device = gSession->GetDevice ();
+ result |= (~device.HardwareID ()) & modelInPins; // <chg 24-Apr-2000 BP> expects inverse output
+ }
+ else
+ {
+ // The pin for detecting "in cradle" is hwrVisorPrismPortEDock2Off. It should be low
+ // if in the serial cradle. If it is high, we assume USB.
+ // -- Bob Petersen
+
+ result &= ~hwrVisorPrismPortEDock2Off;
+ }
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrVisorPrismPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrVisorPrismPortGPowerFailIrqOff;
+ }
+
+ else if (port == 'J')
+ {
+ // Make sure this bit is set, which means the EEPROM has finished being read.
+ // Otherwise we will loop indefinitely as the OS polls this port.
+
+ result |= hwrVisorPrismPortJEepromDo;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetPortInternalValue
+//
+// Returns the "dedicated" pin value of the given port.
+// ---------------------------------------------------------------------------
+
+uint8 EmRegsVZVisorPrism::GetPortInternalValue (int port)
+{
+ uint8 result = EmRegsVZ::GetPortInternalValue (port);
+
+ if (port == 'D')
+ {
+ // Always set the high bit, indicating that there's no memory module
+ // installed. From Bob Petersen at Handspring:
+ //
+ // This is a probe into the module memory, to check for a replacement ROM on a
+ // card that is plugged in. The card is mapped to 0x20000000 and the card's
+ // ROM is at 0x28000000. If it finds the card header (FEEDBEEF) and the card
+ // is plugged in that has a non-zero reset vector, the chip selects are changed
+ // so B0 addresses 10c00000, and then we jump to the reset vector and boot off
+ // the card.
+ //
+ // This part of the boot code should only be called if it is detected that a
+ // card is currently plugged in (bit 7 of port D) and we aren't currently
+ // booting from the card.
+
+ result |= hwrVisorPrismPortDCardInstIrqOff;
+
+ // Ensure that bit hwrVisorPrismPortDDock1IrqOff is set. If it's clear, HotSync
+ // will sync via the modem instead of the serial port.
+
+ result |= hwrVisorPrismPortDDock1IrqOff;
+ }
+ else if (port == 'G')
+ {
+ // Make sure that hwrVisorPrismPortGPowerFailIrqOff is set. If it's clear,
+ // the battery code will make the device go to sleep immediately.
+
+ result |= hwrVisorPrismPortGPowerFailIrqOff;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsVZVisorPrism::GetKeyInfo
+// ---------------------------------------------------------------------------
+
+void EmRegsVZVisorPrism::GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows)
+{
+ *numRows = kNumButtonRows;
+ *numCols = kNumButtonCols;
+
+ memcpy (keyMap, kButtonMap, sizeof (kButtonMap));
+
+ // Determine what row is being asked for.
+
+ UInt8 portKDirVZ = READ_REGISTER (portKDir);
+ UInt8 portKDataVZ = READ_REGISTER (portKData);
+
+ UInt8 portGDir = READ_REGISTER (portGDir);
+ UInt8 portGData = READ_REGISTER (portGData);
+
+ rows[0] = (portGDir & hwrVisorPrismPortGKbdRow0) != 0 && (portGData & hwrVisorPrismPortGKbdRow0) == 0;
+ rows[1] = (portGDir & hwrVisorPrismPortGKbdRow1) != 0 && (portGData & hwrVisorPrismPortGKbdRow1) == 0;
+ rows[2] = (portKDirVZ & hwrVisorPrismPortKKbdRow2) != 0 && (portKDataVZ & hwrVisorPrismPortKKbdRow2) == 0;
+}
+
diff --git a/SrcShared/Hardware/EmRegsVZVisorPrism.h b/SrcShared/Hardware/EmRegsVZVisorPrism.h
new file mode 100644
index 0000000..4d9eaf0
--- /dev/null
+++ b/SrcShared/Hardware/EmRegsVZVisorPrism.h
@@ -0,0 +1,37 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmRegsVZVisorPrism_h
+#define EmRegsVZVisorPrism_h
+
+#include "EmRegsVZ.h"
+
+
+class EmRegsVZVisorPrism : public EmRegsVZ
+{
+ public:
+ virtual Bool GetLCDScreenOn (void);
+ virtual Bool GetLCDBacklightOn (void);
+ virtual Bool GetLCDHasFrame (void);
+ virtual void GetLCDBeginEnd (emuptr& begin, emuptr& end);
+ virtual void GetLCDScanlines (EmScreenUpdateInfo& info);
+ virtual Bool GetLineDriverState (EmUARTDeviceType type);
+ virtual EmUARTDeviceType GetUARTDevice (int uartNum);
+
+ virtual uint8 GetPortInputValue (int);
+ virtual uint8 GetPortInternalValue (int);
+ virtual void GetKeyInfo (int* numRows, int* numCols,
+ uint16* keyMap, Bool* rows);
+};
+
+#endif /* EmRegsVZVisorPrism_h */
diff --git a/SrcShared/Hardware/EmSPISlave.cpp b/SrcShared/Hardware/EmSPISlave.cpp
new file mode 100644
index 0000000..9dc7ff6
--- /dev/null
+++ b/SrcShared/Hardware/EmSPISlave.cpp
@@ -0,0 +1,51 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmSPISlave.h"
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave::EmSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave::EmSPISlave (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave::~EmSPISlave
+// ---------------------------------------------------------------------------
+
+EmSPISlave::~EmSPISlave (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave::Enable
+// ---------------------------------------------------------------------------
+
+void EmSPISlave::Enable (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave::Disable
+// ---------------------------------------------------------------------------
+
+void EmSPISlave::Disable (void)
+{
+}
diff --git a/SrcShared/Hardware/EmSPISlave.h b/SrcShared/Hardware/EmSPISlave.h
new file mode 100644
index 0000000..1fcb2dd
--- /dev/null
+++ b/SrcShared/Hardware/EmSPISlave.h
@@ -0,0 +1,28 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmSPISlave_h
+#define EmSPISlave_h
+
+class EmSPISlave
+{
+ public:
+ EmSPISlave (void);
+ virtual ~EmSPISlave (void);
+
+ virtual uint16 DoExchange (uint16 control, uint16 data) = 0;
+ virtual void Enable (void);
+ virtual void Disable (void);
+};
+
+#endif // EmSPISlave_h
diff --git a/SrcShared/Hardware/EmSPISlaveADS784x.cpp b/SrcShared/Hardware/EmSPISlaveADS784x.cpp
new file mode 100644
index 0000000..51960e0
--- /dev/null
+++ b/SrcShared/Hardware/EmSPISlaveADS784x.cpp
@@ -0,0 +1,428 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmSPISlaveADS784x.h"
+
+#include "EmLowMem.h" // EmLowMem_GetGlobal
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmPalmStructs.h" // EmAliasSysBatteryDataStruct
+
+#include "Logging.h"
+#define PRINTF if (1) ; else LogAppendMsg
+
+/********************************************************************
+ * Single-Ended Mode Channel Constants (adcSERDFR = 1)
+ ********************************************************************/
+#define adcSERTemp0 0x04 // Temperature 0
+#define adcSERYPos 0x14 // Y-Position
+#define adcSERBat 0x24 // Battery
+#define adcSERZ1Pos 0x34 // Z1-Position
+#define adcSERZ2Pos 0x44 // Z2-Position
+#define adcSERXPos 0x54 // X-Position
+#define adcSERAux 0x64 // Auxilliary
+#define adcSERTemp1 0x74 // Temperature 1
+
+/********************************************************************
+ * Differential Mode Channel Constants (adcSERDFR = 0)
+ ********************************************************************/
+#define adcDFRYPos 0x10 // Y-Position
+#define adcDFRZ1Pos 0x30 // Z1-Position
+#define adcDFRZ2Pos 0x40 // Z2-Position
+#define adcDFRXPos 0x50 // X-Position
+
+/********************************************************************
+ * Conversion Mode Resolution
+ ********************************************************************/
+#define adcMode12Bit 0x00 // 12-bit conversion
+#define adcMode8Bit 0x08 // 8-bit conversion
+
+/********************************************************************
+ * Power Down Bit Use (for Burr-Brown ADS7846)
+ ********************************************************************/
+#define adcPDADCOn 0x01 // If set, turn on the ADC converter
+#define adcPDReferenceOn 0x02 // If set, the internal Vref reference is turned on
+
+#define kChannelBits 0x70
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlaveADS784x::EmSPISlaveADS784x
+// ---------------------------------------------------------------------------
+
+EmSPISlaveADS784x::EmSPISlaveADS784x ( EmADSChannelType ch0,
+ EmADSChannelType ch1,
+ EmADSChannelType ch2,
+ EmADSChannelType ch3,
+ EmADSChannelType ch4,
+ EmADSChannelType ch5,
+ EmADSChannelType ch6,
+ EmADSChannelType ch7) :
+ EmSPISlave (),
+ fBitBufferIn (0),
+ fBitBufferOut (0),
+ fNumBitsIn (0),
+ fPendingResult (0),
+ fHavePending (false),
+ fCommandBitsSeen (0)
+{
+ fChannelUse[0] = ch0;
+ fChannelUse[1] = ch1;
+ fChannelUse[2] = ch2;
+ fChannelUse[3] = ch3;
+ fChannelUse[4] = ch4;
+ fChannelUse[5] = ch5;
+ fChannelUse[6] = ch6;
+ fChannelUse[7] = ch7;
+
+ // If there's a 7846-style battery, it *must* be on channel 2.
+
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ if (fChannelUse[ii] == kChannelBattery7846)
+ {
+ EmAssert (ii == 2);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlaveADS784x::~EmSPISlaveADS784x
+// ---------------------------------------------------------------------------
+
+EmSPISlaveADS784x::~EmSPISlaveADS784x (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlaveADS784x::DoExchange
+// ---------------------------------------------------------------------------
+
+uint16 EmSPISlaveADS784x::DoExchange (uint16 control, uint16 data)
+{
+ PRINTF ("");
+ PRINTF ("EmSPISlaveADS784x::DoExchange");
+ PRINTF ("control = 0x%04X, data = 0x%04X", control, data);
+
+ // -----------------------------------------------------------------------
+ // Merge the incoming bits with our current buffer.
+ // -----------------------------------------------------------------------
+
+ uint16 numBits = (control & hwrVZ328SPIMControlBitsMask) + 1;
+ uint32 oldBitsMask = ~0 << numBits;
+ uint32 newBitsMask = ~oldBitsMask;
+
+ PRINTF ("Before merging input: fBitBufferIn = 0x%04X, fNumBitsIn = 0x%04X", fBitBufferIn, fNumBitsIn);
+
+ fBitBufferIn = ((fBitBufferIn << numBits) & oldBitsMask) | (data & newBitsMask);
+ fNumBitsIn += numBits;
+
+ PRINTF ("After merging input: fBitBufferIn = 0x%04X, fNumBitsIn = 0x%04X", fBitBufferIn, fNumBitsIn);
+
+ // -----------------------------------------------------------------------
+ // Start processing the command bits.
+ // -----------------------------------------------------------------------
+
+ EmAssert (fNumBitsIn - fCommandBitsSeen - 1 >= 0);
+
+ uint16 result = 0;
+ uint32 mask = 1 << (fNumBitsIn - fCommandBitsSeen - 1);
+
+ while (mask)
+ {
+ // Shift out a bit.
+
+ {
+ result = (result << 1) | (fBitBufferOut >> 15);
+ fBitBufferOut <<= 1;
+ }
+
+ // If we haven't seen the Start bit yet, look for it.
+
+ if (fCommandBitsSeen == 0)
+ {
+ // If we found the Start bit, start counting the
+ // number of command bits as we stream through them.
+
+ if ((mask & fBitBufferIn) != 0)
+ {
+ fCommandBitsSeen++;
+ }
+
+ // Otherwise, adjust fNumBitsIn so that when we *do*
+ // find the Start bit, we know where it is.
+
+ else
+ {
+ fNumBitsIn--;
+ }
+
+ // If there's a pending conversion, load it into the
+ // output shift register after receiving the first
+ // bit after the last bit of the previous command.
+
+ this->LoadPendingConversion ();
+ }
+ else
+ {
+ fCommandBitsSeen++;
+
+ // If we've seen 8 bits, process the command, and then
+ // prepare for the next one.
+
+ if (fCommandBitsSeen == 8)
+ {
+ fNumBitsIn -= 8;
+ fCommandBitsSeen = 0;
+
+ uint8 command = fBitBufferIn >> fNumBitsIn;
+ this->ProcessCommand (command);
+
+ PRINTF ("After ProcessCommand: fPendingResult = 0x%04X", fPendingResult);
+ }
+ }
+
+ mask >>= 1;
+ }
+
+
+ // ----------------------------------------------------------------------
+ // Return the result.
+ // ----------------------------------------------------------------------
+
+ PRINTF ("result = 0x%04X", result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlaveADS784x::ProcessCommand
+// ---------------------------------------------------------------------------
+
+void EmSPISlaveADS784x::ProcessCommand (uint8 command)
+{
+ uint16 result = 0;
+
+ /*
+ Command format is:
+
+ +-----+-----+-----+-----+-----+-----+-----+-----+
+ | S | A2 | A1 | A0 | M | Ref | PD1 | PD0 |
+ +-----+-----+-----+-----+-----+-----+-----+-----+
+
+ S = Start Bit. Must be 1.
+ A2:0 = Channel select bits
+ M = 12/8 bit mode (1 = 8-bit)
+ Ref = Single-ended/Differential reference select bit
+ PD1:0 = Power down mode select bits.
+
+ We care about the A2:0 bits, since they tell us what data
+ is being asked for. We also care about the M bit, as that
+ determines how many bits we load into fBitBufferOut.
+ */
+
+ int channel = (command & kChannelBits) >> 4;
+
+ EmAssert (channel >= 0 && channel <= 7);
+
+ switch (fChannelUse [channel])
+ {
+ case kChannelPenX:
+ case kChannelPenY:
+ {
+ result = 0;
+ break;
+ }
+
+ case kChannelBattery7843:
+ case kChannelBattery7846:
+ {
+ /*
+ The current batterly level is read with the following:
+
+ currentLevel = PrvAverageBattery ( );
+
+ PrvAverageBattery() reads the ADC battery value and then
+ uses a 7/8 averaging method to merge the new value into
+ previously averaged values.
+
+ "currentLevel" is then used to determine "batteryLevel"
+ as follows:
+
+ batteryLevel = (((UInt16)currentLevel + (battDataP->sysBattVoltageStepOffset))
+ * 100 + (battDataP->sysBattStepsPerVolt)/2)
+ / (battDataP->sysBattStepsPerVolt);
+
+ "batteryLevel" is then used to search through the sysBattVoltageCurve
+ array to determine the percent charge.
+
+ Thus, in order to determine the "currentLevel" for a desired
+ "batteryLevel", we solve for it, getting:
+
+ currentLevel = (batteryLevel * battDataP->sysBattStepsPerVolt + 50) / 100 -
+ battDataP->sysBattVoltageStepOffset;
+
+ We can then get the "batteryLevel" from the voltage curve
+ array in the battery table. For example, for a 100% charge,
+ read sysBattVoltageCurve[10].
+ */
+
+ CEnableFullAccess munge;
+
+ // Get a pointer to the system battery globals and determine
+ // what version table we're using.
+
+ emuptr sysBatteryDataP = EmLowMem_GetGlobal (sysBatteryDataP);
+
+ if (sysBatteryDataP)
+ {
+ EmAliasSysBatteryDataStructV1<PAS> sysBatteryData (sysBatteryDataP);
+
+ UInt16 sysBattDataStructVersion = sysBatteryData.sysBattDataStructVersion;
+
+ if (sysBattDataStructVersion <= 3)
+ {
+ UInt16 voltageCurve = 0;
+ UInt16 sysBattStepsPerVolt = 0;
+ Int16 sysBattVoltageStepOffset = 0;
+
+ // Fill out the above variables from the system battery globals,
+ // sorting out table version differences.
+
+ if (sysBattDataStructVersion == 1)
+ {
+ EmAliasSysBatteryDataStructV1<PAS> sysBatteryDataV1 (sysBatteryDataP);
+
+ voltageCurve = sysBatteryDataV1.sysBattVoltageCurve[10];
+ sysBattStepsPerVolt = sysBatteryDataV1.sysBattStepsPerVolt;
+ sysBattVoltageStepOffset = sysBatteryDataV1.sysBattVoltageStepOffset;
+ }
+ else if (sysBattDataStructVersion == 2)
+ {
+ EmAliasSysBatteryDataStructV2<PAS> sysBatteryDataV2 (sysBatteryDataP);
+
+ voltageCurve = sysBatteryDataV2.sysBattVoltageCurve[10];
+ sysBattStepsPerVolt = sysBatteryDataV2.sysBattStepsPerVolt;
+ sysBattVoltageStepOffset = sysBatteryDataV2.sysBattVoltageStepOffset;
+ }
+ else if (sysBattDataStructVersion == 3)
+ {
+ EmAliasSysBatteryDataStructV3<PAS> sysBatteryDataV3 (sysBatteryDataP);
+
+ voltageCurve = sysBatteryDataV3.sysBattVoltageCurve[10];
+ sysBattStepsPerVolt = sysBatteryDataV3.sysBattStepsPerVolt;
+ sysBattVoltageStepOffset = sysBatteryDataV3.sysBattVoltageStepOffset;
+ }
+ else
+ {
+ EmAssert (false);
+ }
+
+ PRINTF ("voltageCurve = %d", voltageCurve);
+ PRINTF ("sysBattStepsPerVolt = %d", sysBattStepsPerVolt);
+ PRINTF ("sysBattVoltageStepOffset = %d", sysBattVoltageStepOffset);
+
+ // Determine the result based on the formula in the comments above.
+
+ result = (voltageCurve *
+ sysBattStepsPerVolt + 50) / 100 -
+ sysBattVoltageStepOffset;
+
+ // Turn this into a 12 bit result.
+
+ result <<= 4;
+
+ if (fChannelUse [channel] == kChannelBattery7846)
+ {
+ result *= 2; // Account for the fact that the Palm OS battery
+ // tables assume a 5.0V reference voltage, while
+ // the 7846 uses 2.5V. (?)
+ result /= 4; // Account for 1:4 voltage divider
+ }
+ }
+ else
+ {
+ result = 0x0FFF;
+ }
+ }
+ else
+ {
+ result = 0x0FFF;
+ }
+
+ PRINTF ("result = 0x%04X", result);
+ break;
+ }
+
+ case kChannelDockSerial:
+ {
+ // Say that we're undocked.
+
+ result = 0x0000;
+ break;
+ }
+
+ case kChannelDockTwister:
+ {
+ // Say that we're undocked.
+
+ result = 0x0FFF;
+ break;
+ }
+
+ case kChannelTemp0:
+ {
+ result = 0x0FFF; // !!! Dummy value; need to determine real value
+ break;
+ }
+
+ case kChannelTemp1:
+ {
+ result = 0x0FFF; // !!! Dummy value; need to determine real value
+ break;
+ }
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ fPendingResult = result << 4;
+ fHavePending = true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlaveADS784x::LoadPendingConversion
+// ---------------------------------------------------------------------------
+
+void EmSPISlaveADS784x::LoadPendingConversion (void)
+{
+ // -----------------------------------------------------------------------
+ // If there's a pending conversion, move it into the output shift register.
+ // -----------------------------------------------------------------------
+
+ if (fHavePending)
+ {
+ PRINTF ("Before merging pending: fBitBufferOut = 0x%04X", fBitBufferOut);
+
+ fHavePending = false;
+ fBitBufferOut = fPendingResult;
+
+ PRINTF ("After merging pending: fBitBufferOut = 0x%04X", fBitBufferOut);
+ }
+}
+
diff --git a/SrcShared/Hardware/EmSPISlaveADS784x.h b/SrcShared/Hardware/EmSPISlaveADS784x.h
new file mode 100644
index 0000000..318e44c
--- /dev/null
+++ b/SrcShared/Hardware/EmSPISlaveADS784x.h
@@ -0,0 +1,97 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmSPISlaveADS784x_h
+#define EmSPISlaveADS784x_h
+
+#include "EmSPISlave.h" // EmSPISlave
+
+enum EmADSChannelType
+{
+ kChannelUnused,
+ kChannelPenX,
+ kChannelPenY,
+ kChannelBattery7843,
+ kChannelBattery7846,
+ kChannelDockSerial,
+ kChannelDockTwister,
+ kChannelTemp0,
+ kChannelTemp1
+};
+
+
+#define kChannelSet1 \
+ kChannelTemp0, \
+ kChannelPenY, \
+ kChannelBattery7846, \
+ kChannelUnused, \
+ kChannelUnused, \
+ kChannelPenX, \
+ kChannelDockTwister, \
+ kChannelTemp1
+
+
+#define kChannelSet2 \
+ kChannelUnused, \
+ kChannelPenY, \
+ kChannelBattery7843, \
+ kChannelUnused, \
+ kChannelUnused, \
+ kChannelPenX, \
+ kChannelDockSerial, \
+ kChannelUnused
+
+
+#define kChannelSet3 \
+ kChannelUnused, \
+ kChannelPenY, \
+ kChannelBattery7843, \
+ kChannelUnused, \
+ kChannelUnused, \
+ kChannelPenX, \
+ kChannelDockTwister, \
+ kChannelUnused
+
+
+class EmSPISlaveADS784x : public EmSPISlave
+{
+ public:
+ EmSPISlaveADS784x (EmADSChannelType ch0,
+ EmADSChannelType ch1,
+ EmADSChannelType ch2,
+ EmADSChannelType ch3,
+ EmADSChannelType ch4,
+ EmADSChannelType ch5,
+ EmADSChannelType ch6,
+ EmADSChannelType ch7);
+ virtual ~EmSPISlaveADS784x (void);
+
+ virtual uint16 DoExchange (uint16 control, uint16 data);
+
+ protected:
+ void ProcessCommand (uint8);
+ void LoadPendingConversion (void);
+
+ private:
+ EmADSChannelType fChannelUse[8];
+
+ uint32 fBitBufferIn;
+ uint16 fBitBufferOut;
+ int fNumBitsIn;
+ uint16 fPendingResult;
+ Bool fHavePending;
+
+ int fCommandBitsSeen;
+};
+
+#endif // EmSPISlaveADS784x_h
diff --git a/SrcShared/Hardware/EmUAEGlue.cpp b/SrcShared/Hardware/EmUAEGlue.cpp
new file mode 100644
index 0000000..351fa43
--- /dev/null
+++ b/SrcShared/Hardware/EmUAEGlue.cpp
@@ -0,0 +1,166 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmUAEGlue.h"
+
+#include "EmCPU68K.h" // ProcessException, etc.
+#include "EmSession.h" // gSession->Reset
+#include "Platform.h" // AllocateMemory
+#include "UAE.h" // MakeSR, uae_s32, etc.
+
+
+// ---------------------------------------------------------------------------
+// Glue functions to bridge from UAE-generated code to the implemenations
+// we define.
+// ---------------------------------------------------------------------------
+
+void customreset (void)
+{
+ EmAssert (gSession);
+
+ gSession->ScheduleReset (kResetSoft);
+}
+
+
+void Exception (int nr, emuptr /*oldpc*/)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->ProcessException ((ExceptionNumber) nr);
+}
+
+
+unsigned long op_illg (uint32 iOpcode)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->ProcessIllegalInstruction (iOpcode);
+ return 0;
+}
+
+
+void Software_ProcessLINK (int32 linkSize)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->ProcessLINK (linkSize);
+}
+
+
+int Software_ProcessRTS (emuptr dest)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewPC (dest);
+ return gCPU68K->ProcessRTS (dest);
+}
+
+
+int Software_ProcessRTE (emuptr dest)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewPC (dest);
+ return gCPU68K->ProcessRTE (dest);
+}
+
+
+int Software_ProcessJSR (emuptr oldpc, emuptr dest)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewPC (dest);
+ return gCPU68K->ProcessJSR (oldpc, dest);
+}
+
+
+int Software_ProcessJSR_Ind (emuptr oldpc, emuptr dest)
+{
+ EmAssert (gCPU68K);
+
+ return gCPU68K->ProcessJSR_Ind (oldpc, dest);
+}
+
+
+void Software_CheckNewPC (emuptr dest)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewPC (dest);
+}
+
+
+void Software_CheckStackPointerAssignment ()
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewSP (kStackPointerChanged);
+}
+
+
+void Software_CheckStackPointerDecrement ()
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewSP (kStackPointerDecremented);
+}
+
+
+void Software_CheckStackPointerIncrement ()
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewSP (kStackPointerIncremented);
+}
+
+
+void Software_CheckKernelStack ()
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->CheckNewSP (kStackPointerKernelStackHack);
+}
+
+
+void MakeSR (void)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->UpdateSRFromRegisters ();
+}
+
+
+void MakeFromSR (void)
+{
+ EmAssert (gCPU68K);
+
+ gCPU68K->UpdateRegistersFromSR ();
+}
+
+
+void* xmalloc (size_t size)
+{
+ return Platform::AllocateMemory (size);
+}
+
+uint32 get_disp_ea_000 (uint32 base, uint32 dp)
+{
+ int reg = (dp >> 12) & 15;
+ uae_s32 regd = regs.regs[reg];
+
+ if ((dp & 0x800) == 0)
+ regd = (uae_s32)(uae_s16)regd;
+
+ return base + (uae_s8)dp + regd;
+}
diff --git a/SrcShared/Hardware/EmUAEGlue.h b/SrcShared/Hardware/EmUAEGlue.h
new file mode 100644
index 0000000..cef39b8
--- /dev/null
+++ b/SrcShared/Hardware/EmUAEGlue.h
@@ -0,0 +1,17 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmUAEGlue_h
+#define EmUAEGlue_h
+
+#endif /* EmUAEGlue_h */
diff --git a/SrcShared/Hardware/EmUARTDragonball.cpp b/SrcShared/Hardware/EmUARTDragonball.cpp
new file mode 100644
index 0000000..40d6ac3
--- /dev/null
+++ b/SrcShared/Hardware/EmUARTDragonball.cpp
@@ -0,0 +1,936 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmUARTDragonball.h"
+
+#include "EmHAL.h" // EmHAL, EmUARTDeviceType
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "Logging.h" // LogAppendMsg
+#include "Preferences.h" // gEmuPrefs
+#include "ErrorHandling.h" // ReportErrCommPort
+
+
+/*
+ This module contains the routines for handling serial I/O. It
+ is responsible for responding to changes in state enacted by
+ software (from either the OS or user), and for dealing with
+ the actual transmission and reception of serial data.
+
+ There are four ways in which serial activity could occur: something
+ could write to a UART register, something could read from a UART
+ register, a byte could be received from the host serial port, or
+ a byte could be sent out the host serial port. Here is what
+ happens on each of those events.
+
+ Something reads a UART register:
+ - If the register is the RX_DATA register, clear the DATA_READY bit
+ - Make sure the state is up-to-date (including interrupts)
+ - Return the register contents
+
+ Something writes to a UART register:
+ - Update the writable parts of the register
+ - React to any changes
+ - Make sure the state is up-to-date (including interrupts)
+
+ Data appears at the host serial port:
+ - Post the byte to the RX FIFO (if there is room)
+ - Make sure the state is up-to-date (including interrupts)
+
+ Data needs to be sent to the host serial port:
+ - Send the first byte in the TX FIFO
+ - Make sure the state is up-to-date (including interrupts)
+*/
+
+
+// ======================================================================
+// Private functions
+// ======================================================================
+
+static const int kMaxFifoSize = 64;
+
+static Bool PrvPinBaud (EmTransportSerial::Baud& newBaud);
+static Bool PrvPinBaud (EmTransportSerial::Baud& newBaud,
+ EmTransportSerial::Baud testBaud);
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::EmUARTDragonball
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: type - the type of UART to emulate. The Dragonball
+ * and DragonballEZ UARTs are similar enough that we
+ * can handle them both here with just a few tests in
+ * the places where they differ.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmUARTDragonball::EmUARTDragonball (UART_Type type, int uartNum) :
+ fUARTNum (uartNum),
+ fState (type),
+ fRxFIFO (this->PrvFIFOSize (true)),
+ fTxFIFO (this->PrvFIFOSize (false))
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::~EmUARTDragonball
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmUARTDragonball::~EmUARTDragonball (void)
+{
+ // All line drivers are effectively disabled, so close the transports.
+
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ EmTransport* transport = gEmuPrefs->GetTransportForDevice (ii);
+
+ if (transport)
+ {
+ transport->Close ();
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::StateChanged
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmUARTDragonball::StateChanged (State& newState, Bool sendTxData)
+{
+ EmAssert (fState.UART_TYPE == newState.UART_TYPE);
+
+ // (Changing the configuration is the only place where we assume that
+ // the transport we're using is a serial transport.)
+
+ EmTransportSerial::ConfigSerial config;
+ EmTransport* transport = this->GetTransport ();
+ EmTransportSerial* serTransport = dynamic_cast<EmTransportSerial*> (transport);
+
+ if (serTransport)
+ {
+ serTransport->GetConfig (config);
+ }
+
+
+ // ========== RX_ENABLE ==========
+ //
+ // This bit enables the receiver block. While this bit is low, the receiver is disabled and the
+ // receive FIFO is flushed. This bit resets to 0.
+
+ if (fState.RX_ENABLE != newState.RX_ENABLE)
+ {
+ if (newState.RX_ENABLE == 0)
+ {
+ fRxFIFO.Clear ();
+ }
+ }
+
+
+ // ========== TX_ENABLE ==========
+ //
+ // This bit enables the transmitter block. While this bit is low, the transmitter is disabled and
+ // the transmit FIFO is flushed. This bit resets to 0.
+
+ if (fState.TX_ENABLE != newState.TX_ENABLE)
+ {
+ if (newState.TX_ENABLE == 0)
+ {
+ fTxFIFO.Clear ();
+ }
+ }
+
+
+ // ========== PARITY_EN ==========
+ //
+ // This bit controls the parity generator in the transmitter and parity checker in the receiver.
+ // When this bit is high, they are enabled. When it is low, they are disabled.
+ //
+ // ========== ODD_EVEN ==========
+ //
+ // This bit controls the sense of the parity generator and checker. When this bit is high, odd
+ // parity is generated and expected. When this bit is low, even parity is generated and
+ // expected. This bit has no function if PARITY EN is low.
+
+ if (newState.PARITY_EN == 0)
+ {
+ config.fParity = EmTransportSerial::kNoParity;
+ }
+ else if (newState.ODD_EVEN)
+ {
+ config.fParity = EmTransportSerial::kOddParity;
+ }
+ else
+ {
+ config.fParity = EmTransportSerial::kEvenParity;
+ }
+
+
+ // ========== STOP_BITS =========
+ //
+ // This bit controls the number of stop bits transmitted after a character. When this bit is high,
+ // two stop bits are sent. When this bit is low, one stop bit is sent. This bit has no effect on the
+ // receiver, which expects one or more stop bits.
+
+ config.fStopBits = newState.STOP_BITS ? 2 : 1;
+
+
+ // ========== CHAR8_7 ==========
+ //
+ // This bit controls the character length. While high, the transmitter and receiver are in 8-bit
+ // mode. While low, they are in 7-bit mode. The transmitter then ignores B7 and the receiver
+ // sets B7 to 0.
+
+ config.fDataBits = newState.CHAR8_7 ? 8 : 7;
+
+
+ // ========== DIVIDE ==========
+ //
+ // These bits control the clock frequency produced by the baud rate generator.
+ //
+ // 000 = Divide by 1.
+ // 001 = Divide by 2.
+ // 010 = Divide by 4.
+ // 011 = Divide by 8.
+ // 100 = Divide by 16.
+ // 101 = Divide by 32.
+ // 110 = Divide by 64.
+ // 111 = Divide by 128.
+ //
+ // ========== PRESCALER ==========
+ //
+ // These bits control the division value of the baud generator prescaler. The division value is
+ // determined by the following formula:
+ //
+ // Prescaler division value = 65 (decimal) - PRESCALER
+
+ // Baud rate is sysClockFreq / preScaler / divider / 16
+ //
+ // (Using sysClockFreq / (preScaler * divider * 16) might get closer to the
+ // intended baud (as would using floating point), but does it mirror what
+ // the hardware actually does?)
+
+ int32 sysClockFreq = EmHAL::GetSystemClockFrequency ();
+ config.fBaud = sysClockFreq / (65 - newState.PRESCALER) / (1 << newState.DIVIDE) / 16;
+
+ // "newRate" is only approximate to within 0.1%. Pin the value to an
+ // exact value.
+ //
+ // !!! What to do if we can't pin to a valid value?
+
+ (void) PrvPinBaud (config.fBaud);
+
+
+ // ========== IGNORE_CTS ==========
+ //
+ // When this bit is high, it forces the CTS signal that is presented to the transmitter to always
+ // be asserted, which effectively ignores the external pin.
+
+ config.fHwrHandshake = newState.IGNORE_CTS == 0;
+
+
+ // ========== RTS_CONT ==========
+ //
+ // This bit selects the function of the RTS pin.
+ //
+ // 0 = RTS pin is controlled by the RTS bit.
+ // 1 = RTS pin is controlled by the receiver FIFO. When the FIFO is full (one slot is
+ // remaining), RTS is negated.
+ //
+ // ========== RTS ==========
+ //
+ // This bit controls the RTS pin while the RTS CONT bit is 0.
+ //
+ // 0 = RTS pin is 1.
+ // 1 = RTS pin is 0.
+
+ if (fState.RTS_CONT != newState.RTS_CONT ||
+ fState.RTS != newState.RTS)
+ {
+ if (serTransport)
+ {
+ if (newState.RTS_CONT)
+ {
+ serTransport->SetRTS (EmTransportSerial::kRTSAuto);
+ }
+ else
+ {
+ if (newState.RTS)
+ {
+ serTransport->SetRTS (EmTransportSerial::kRTSOn);
+ }
+ else
+ {
+ serTransport->SetRTS (EmTransportSerial::kRTSOff);
+ }
+ }
+ }
+ }
+
+
+ // ========== UART_ENABLE ==========
+ //
+ // This bit enables the UART module. When this bit is low, the UART module is disabled and
+ // in low-power mode. While this bit is high, the UART module is active. This bit resets to 0.
+
+ // ========== IRDA_ENABLE ==========
+ //
+ // This bit enables the IrDA interface.
+ //
+ // 0 = Normal NRZ operation.
+ // 1 = IRDA operation.
+
+ if (fState.UART_ENABLE != newState.UART_ENABLE ||
+ fState.IRDA_ENABLE != newState.IRDA_ENABLE)
+ {
+ // Nothing to do here.
+ }
+
+ // Establish the new settings. Do this only when the UART is
+ // enabled, to help reduce the thrashing on the host serial port,
+ // and to help prevent the installation of invalid settings (which
+ // could appear in the UART registers as it's being configured).
+
+ if (newState.UART_ENABLE)
+ {
+ if (serTransport)
+ {
+ serTransport->SetConfig (config);
+ }
+ }
+
+ // ========== SEND_BREAK ==========
+ //
+ // This bit forces the transmitter to immediately send continuous zeros creating a break
+ // character.
+
+ if (fState.SEND_BREAK != newState.SEND_BREAK)
+ {
+ if (serTransport)
+ {
+ serTransport->SetBreak (newState.SEND_BREAK);
+ }
+ }
+
+
+ // ========== TX_DATA ==========
+ //
+ // These bits are the parallel transmit-data inputs. In 7-bit mode, D7 is ignored and in 8-bit
+ // mode, all of the bits are used. Data is transmitted LSB first. A new character is transmitted
+ // when these bits are written and have passed through the FIFO.
+
+ // ========== LOOP ==========
+ //
+ // This bit controls loopback for system testing purposes. When this bit is high, the receiver
+ // input is internally connected to the transmitter and ignores the RXD pin. The TXD pin is
+ // unaffected by this bit.
+
+ if (sendTxData && newState.UART_ENABLE && newState.TX_ENABLE)
+ {
+ if (newState.LOOP == 0)
+ {
+ if (transport && transport->CanWrite ()) // The host serial port is open
+ {
+ // With or without hardware handshaking, we'll put data
+ // in the FIFO, and let the host's handshaking take care
+ // of when the data is removed from the FIFO.
+
+ if (fTxFIFO.GetFree () > 0) // There's room in the FIFO
+ {
+ fTxFIFO.Put (newState.TX_DATA); // so add the data
+
+ // Call TransmitTxFIFO here to send the data we
+ // just queued up. Doing this is important on the Mac in
+ // order to send out the data quickly instead of later at
+ // idle time.
+
+ this->TransmitTxFIFO (transport);
+ }
+ }
+ else // The host serial port is NOT open
+ {
+ if (config.fHwrHandshake) // Reflects the state of the IGNORE_CTS bit.
+ {
+ // With hardware handshaking, data is sent only when CTS
+ // is asserted. With no host serial port, we define that
+ // CTS is never asserted, so the data clogs up the FIFO.
+
+ if (fTxFIFO.GetFree () > 0) // There's room in the FIFO
+ {
+ fTxFIFO.Put (newState.TX_DATA); // so add the data
+
+ // Serial port is closed, so don't call Platform::TransmitTxFIFO.
+ }
+ }
+ else
+ {
+ // With no hardware handshaking, data is sent whenever it's
+ // ready. With nowhere to go, we can drop it on the floor.
+ }
+ }
+ }
+ else // We're in loopback mode.
+ {
+ if (fRxFIFO.GetFree () > 0)
+ {
+ fRxFIFO.Put (newState.TX_DATA);
+ }
+ }
+ }
+
+
+ // Update the state in case any of the above operations have side-effects.
+
+ UpdateState (newState, false);
+
+
+ // Remember this for next time.
+
+ fState = newState;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::UpdateState
+ *
+ * DESCRIPTION: Receive any data, and update the FIFO state registers.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmUARTDragonball::UpdateState (State& state, Bool refreshRxData)
+{
+ EmAssert (fState.UART_TYPE == state.UART_TYPE);
+
+ // Update the RxFIFO if there's been any buffered data.
+
+ EmTransport* transport = this->GetTransport ();
+ if (transport)
+ {
+ this->ReceiveRxFIFO (transport);
+ }
+
+ // === RX_FIFO_FULL ===
+ //
+ // This read-only bit indicates that the receiver FIFO is full and may generate an overrun. This
+ // bit generates a maskable interrupt.
+ //
+ // Further, from the overview section of the manual:
+ //
+ // If your software has a short interrupt
+ // latency time, the FIFO FULL interrupt in the Receiver register can be enabled. The FIFO has
+ // one remaining space available when this interrupt is generated.
+
+ state.RX_FIFO_FULL = fRxFIFO.GetFree () == 0;
+
+
+ // === RX_FIFO_HALF ===
+ //
+ // This read-only bit indicates that the receiver FIFO has four or fewer slots remaining in the
+ // FIFO. This bit generates a maskable interrupt.
+
+ state.RX_FIFO_HALF = fRxFIFO.GetFree () <= this->PrvLevelMarker (true);
+
+
+ // === DATA_READY ===
+ //
+ // This read-only bit indicates that at least one byte is present in the receive FIFO. The
+ // character bits are valid only while this bit is set. This bit generates a maskable interrupt.
+
+ state.DATA_READY = fRxFIFO.GetUsed () > 0;
+
+
+ // === OLD_DATA === // non-68328 only
+ //
+ // This read-only bit indicates that data in the FIFO is older than 30 bit times. It is useful in
+ // situations where the FIFO FULL or FIFO HALF interrupts are used. If there is data in the
+ // FIFO, but below the interrupt threshold, a maskable interrupt can be generated to alert the
+ // software that unread data is present. This bit clears when the character bits are read.
+
+ // Not supported right now.
+
+
+ // === OVRUN ===
+ //
+ // When this read-only bit is high, it indicates that the receiver overwrote data in the FIFO. The
+ // character with this bit set is valid, but at least one previous character was lost. In normal
+ // circumstances, this bit should never be set. It indicates that your software is not keeping up
+ // with the incoming data rate. This bit is updated and valid for each received character.
+
+ // !!! TBD
+
+
+ // === FRAME_ERROR ===
+ //
+ // While high, this read-only bit indicates that the current character had a framing error
+ // (missing stop bit), indicating the possibility of corrupted data. This bit is updated for each
+ // character read from the FIFO.
+
+ // !!! TBD
+
+
+ // === BREAK ===
+ //
+ // When this read-only bit is high, it indicates that the current character was detected as a
+ // BREAK. The data bits are all 0 and the stop bit was also 0. The FRAME ERROR bit will
+ // always be set when this bit is set. If odd parity is selected, PARITY ERROR will also be set
+ // along with this bit. This bit is updated and valid with each character read from the FIFO.
+
+ // !!! TBD
+
+ // === PARITY_ERROR ===
+ //
+ // When this read-only bit is high, it indicates that the current character was detected with a
+ // parity error, indicating the possibility of corrupted data. This bit is updated and valid with
+ // each character read from the FIFO. While parity is disabled, this bit always reads zero.
+
+ // !!! TBD
+
+ // === RX_DATA ===
+ //
+ // These read-only bits are the top receive character in the FIFO. They have no meaning if the
+ // DATA READY bit is 0. In 7-bit mode, the MSB is forced to 0 and in 8-bit mode, all bits are
+ // active.
+
+ if (state.DATA_READY && state.UART_ENABLE && state.RX_ENABLE && refreshRxData)
+ {
+ state.RX_DATA = fRxFIFO.Get ();
+
+ if (state.CHAR8_7 == 0)
+ {
+ state.RX_DATA &= 0x07F;
+ }
+
+ PRINTF ("UART: Put 0x%02X into RX_DATA.", (uint32) (uint8) state.RX_DATA);
+ }
+
+
+ // === TX_FIFO_EMPTY ===
+ //
+ // This read-only bit indicates that the transmit FIFO is empty. This bit generates a maskable
+ // interrupt.
+
+ state.TX_FIFO_EMPTY = fTxFIFO.GetUsed () == 0;
+
+
+ // === TX_FIFO_HALF ===
+ //
+ // This read-only bit indicates that the transmit FIFO is less than half full. This bit generates a
+ // maskable interrupt.
+
+ state.TX_FIFO_HALF = fTxFIFO.GetUsed () < this->PrvLevelMarker (false);
+
+
+ // === TX_AVAIL ===
+ //
+ // This read-only bit indicates that the transmit FIFO has at least one slot available for data.
+ // This bit generates a maskable interrupt.
+
+ state.TX_AVAIL = fTxFIFO.GetFree () > 0;
+
+
+ // === BUSY === // non-68328 only
+ //
+ // When this bit is high, it indicates that the transmitter is busy sending a character. This signal
+ // is asserted while the transmitter state machine is not idle or the FIFO has data in it.
+
+ state.BUSY = !state.TX_FIFO_EMPTY;
+
+
+ // === CTS_STATUS ===
+ //
+ // This bit indicates the current status of the CTS pin. A "snapshot" of the pin is taken
+ // immediately before this bit is presented to the data bus. While the IGNORE CTS bit is high,
+ // this bit can serve as a general-purpose input.
+ //
+ // Note that this pin is ACTIVE LOW! That's why the Boolean expression is negated below.
+ //
+ // For now, say that it's clear to send if the FIFO is empty
+ //
+ // !!! TBD - could be better?
+
+ state.CTS_STATUS = !(fTxFIFO.GetUsed () == 0);
+
+
+ // === CTS_DELTA ===
+ //
+ // When this bit is high, it indicates that the CTS pin changed state and generates a maskable
+ // interrupt. The current state of the CTS pin is available on the CTS STATUS bit. You can
+ // generate an immediate interrupt by setting this bit high. The CTS interrupt is cleared by
+ // writing 0 to this bit.
+
+ // Not supported right now.
+
+
+ // Remember this for next time.
+
+ fState = state;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::TransmitTxFIFO
+ *
+ * DESCRIPTION: Transmit any bytes in the TX FIFO out the serial port.
+ * Assumes that the serial port is open.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmUARTDragonball::TransmitTxFIFO (EmTransport* transport)
+{
+ EmAssert (transport);
+
+ if (transport->CanWrite ())
+ {
+ // Write out any outgoing bytes.
+
+ ErrCode err = errNone;
+ char buffer[kMaxFifoSize];
+ long spaceInTxFIFO = fTxFIFO.GetUsed ();
+
+ if (spaceInTxFIFO > 0)
+ {
+ for (long ii = 0; ii < spaceInTxFIFO; ++ii)
+ {
+ buffer[ii] = fTxFIFO.Get ();
+ }
+
+ if (LogSerialData ())
+ LogAppendData (buffer, spaceInTxFIFO, "UART: Transmitted data:");
+ else
+ PRINTF ("UART: Transmitted %ld serial bytes.", spaceInTxFIFO);
+
+ err = transport->Write (spaceInTxFIFO, buffer);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::ReceiveRxFIFO
+ *
+ * DESCRIPTION: Fills up the RX FIFO with as many bytes as it can from
+ * the host serial port. Assumes that the serial port is
+ * open.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmUARTDragonball::ReceiveRxFIFO (EmTransport* transport)
+{
+ EmAssert (transport);
+
+ if (transport->CanRead ())
+ {
+ // Buffer up any incoming bytes.
+
+ ErrCode err = errNone;
+ char buffer[kMaxFifoSize];
+ long spaceInRxFIFO = fRxFIFO.GetFree ();
+
+ // See how many bytes are waiting.
+
+ long bytesToBuffer = transport->BytesInBuffer (fRxFIFO.GetMaxSize ());
+
+ // See if we have that much room in the FIFO. If not, limit our read
+ // to that many bytes.
+
+ if (bytesToBuffer > spaceInRxFIFO)
+ {
+ bytesToBuffer = spaceInRxFIFO;
+ }
+
+ // If there is data waiting in the wings, and the hardware says it's
+ // OK to receive data, and there's room in the RxFIFO, then receive it.
+ //
+ // It's OK to receive data if RTS_CONT is 1. That means that the FIFO
+ // controls whether or not it's OK to receive data, and that check
+ // is taken care of with "bytesToBuffer > 0".
+ //
+ // If RTS_CONT is zero, then it's OK to receive data if RTS is 1. That
+ // mean that the /RTS pin is zero, which means OK to receive.
+
+ if (bytesToBuffer > 0 && (fState.RTS_CONT == 1 || fState.RTS == 1))
+ {
+ // If there are still bytes to be read, read them in and insert them
+ // into the RX FIFO. If the buffer was previously empty, Hardware::Cycle
+ // will notice that there are now bytes in there and update the
+ // UART registers.
+ //
+ // !!! TBD: Hardware::Cycle is called after every opcode execution.
+ // Since it is very rare that serial bytes are coming in, the overhead
+ // incurred for checking to see if there are serial bytes does not pay
+ // off. We may want to figure out a way to update the UART registers
+ // here, and take the check out of Hardware::Cycle. I'd do that here,
+ // but (a) Hardware::Cycle takes a "sleeping" parameter that I'd have
+ // to determine here, and (b) the similar solution on Windows is more
+ // difficult, as I'd have to stop the CPU thread, update the registers,
+ // and restart the thread.
+
+ err = transport->Read (bytesToBuffer, buffer);
+
+ if (err == errNone)
+ {
+ // not quite the correct phrase for IR over serial (over TCP)
+ if (LogSerialData ())
+ LogAppendData (buffer, bytesToBuffer, "UART: Received data:");
+ else
+ PRINTF ("UART: Received %ld serial bytes.", bytesToBuffer);
+
+ for (long ii = 0; ii < bytesToBuffer; ++ii)
+ {
+ fRxFIFO.Put (buffer[ii]);
+ } // end loop that puts bytes into FIFO
+ } // end no-error-from-EmTransport::Read
+ } // end BytesInBuffer-returned-non-zero
+ } // end is-serial-port-open
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::GetTransport
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+EmTransport* EmUARTDragonball::GetTransport (void)
+{
+ EmUARTDeviceType type = EmHAL::GetUARTDevice (fUARTNum);
+ EmTransport* transport = gEmuPrefs->GetTransportForDevice (type);
+
+ return transport;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::PrvFIFOSize
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+int EmUARTDragonball::PrvFIFOSize (Bool forRX)
+{
+ int size;
+
+ switch (fState.UART_TYPE)
+ {
+ case kUART_Dragonball:
+ size = 8;
+ break;
+
+ case kUART_DragonballEZ:
+ if (forRX)
+ {
+ size = 12;
+ }
+ else
+ {
+ size = 8;
+ }
+ break;
+
+ case kUART_DragonballVZ:
+ if (this->fUARTNum == 0)
+ {
+ if (forRX)
+ {
+ size = 12;
+ }
+ else
+ {
+ size = 8;
+ }
+ }
+ else
+ {
+ size = 64;
+ }
+ break;
+
+ default:
+ EmAssert (false);
+ size = 8;
+ break;
+ }
+
+ return size;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmUARTDragonball::PrvLevelMarker
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+int EmUARTDragonball::PrvLevelMarker (Bool forRX)
+{
+ int level = (forRX ? fRxFIFO.GetMaxSize () : fTxFIFO.GetMaxSize ()) / 2;
+
+ switch (fState.UART_TYPE)
+ {
+ case kUART_Dragonball:
+ break;
+
+ case kUART_DragonballEZ:
+ break;
+
+ case kUART_DragonballVZ:
+ if (this->fUARTNum == 1)
+ {
+ int marker = forRX ? fState.TXFIFO_LEVEL_MARKER : fState.RXFIFO_LEVEL_MARKER;
+
+ if (marker != 0)
+ {
+ level = marker * 4;
+ }
+ }
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+
+ return level;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPinBaud
+ *
+ * DESCRIPTION: Pins the given baud value to the test baud value if the
+ * former is sufficiently close to the latter.
+ *
+ * PARAMETERS: newBaud - the value to possibly alter.
+ *
+ * testBaud - the value to pin to.
+ *
+ * RETURNED: newBaud is changed in place. If it is changed, the
+ * function returns true. Otherwise, it returns false.
+ *
+ ***********************************************************************/
+
+Bool PrvPinBaud (EmTransportSerial::Baud& newBaud)
+{
+ Bool pinned = false;
+
+ if (!pinned) pinned = PrvPinBaud (newBaud, 150);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 300);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 600);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 1200);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 1800);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 2400);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 3600);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 4800);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 7200);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 9600);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 14400);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 19200);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 28800);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 38400);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 57600);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 115200);
+ if (!pinned) pinned = PrvPinBaud (newBaud, 230400);
+
+ return pinned;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPinBaud
+ *
+ * DESCRIPTION: Pins the given baud value to the test baud value if the
+ * former is sufficiently close to the latter.
+ *
+ * PARAMETERS: newBaud - the value to possibly alter.
+ *
+ * testBaud - the value to pin to.
+ *
+ * RETURNED: newBaud is changed in place. If it is changed, the
+ * function returns true. Otherwise, it returns false.
+ *
+ ***********************************************************************/
+
+Bool PrvPinBaud (EmTransportSerial::Baud& newBaud, EmTransportSerial::Baud testBaud)
+{
+ // Pin to within 2%. The Dragonball reference says that the uBaud
+ // register should be accurate to within 0.1%, but let's give it
+ // some slop.
+
+ if (newBaud > (testBaud - (testBaud / 50)) &&
+ newBaud < (testBaud + (testBaud / 50)))
+ {
+ newBaud = testBaud;
+ return true;
+ }
+
+ return false;
+}
diff --git a/SrcShared/Hardware/EmUARTDragonball.h b/SrcShared/Hardware/EmUARTDragonball.h
new file mode 100644
index 0000000..8c777be
--- /dev/null
+++ b/SrcShared/Hardware/EmUARTDragonball.h
@@ -0,0 +1,149 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmUARTDragonball_h
+#define EmUARTDragonball_h
+
+#include "EmThreadSafeQueue.h" // EmByteQueue
+
+class EmTransport;
+class SessionFile;
+
+
+class EmUARTDragonball
+{
+ public:
+ enum UART_Type
+ {
+ kUART_Dragonball,
+ kUART_DragonballEZ,
+ kUART_DragonballVZ,
+ kUART_DragonballSZ
+ };
+
+ struct State
+ {
+ State (UART_Type type) { UART_TYPE = type; }
+
+ UART_Type UART_TYPE;
+
+ // + = Supported
+ // = Unsupported
+ // -> = Input value
+ // <- = Output value
+
+ // UART control register bits
+ // These are all values the user sets; we just look at them.
+
+ /* + -> */ unsigned int UART_ENABLE:1;
+ /* + -> */ unsigned int RX_ENABLE:1;
+ /* + -> */ unsigned int TX_ENABLE:1;
+ /* -> */ unsigned int RX_CLK_CONT:1;
+ /* + -> */ unsigned int PARITY_EN:1;
+ /* + -> */ unsigned int ODD_EVEN:1;
+ /* + -> */ unsigned int STOP_BITS:1;
+ /* + -> */ unsigned int CHAR8_7:1;
+ /* -> */ unsigned int GPIO_DELTA_ENABLE:1; // 68328 only
+ /* -> */ unsigned int OLD_ENABLE:1; // 68EZ328 only
+ /* -> */ unsigned int CTS_DELTA_ENABLE:1;
+ /* + -> */ unsigned int RX_FULL_ENABLE:1;
+ /* + -> */ unsigned int RX_HALF_ENABLE:1;
+ /* + -> */ unsigned int RX_RDY_ENABLE:1;
+ /* + -> */ unsigned int TX_EMPTY_ENABLE:1;
+ /* + -> */ unsigned int TX_HALF_ENABLE:1;
+ /* + -> */ unsigned int TX_AVAIL_ENABLE:1;
+
+ // Baud control register bits
+ // These are all values the user sets; we just look at them.
+
+ /* -> */ unsigned int GPIO_DELTA:1; // 68328 only
+ /* -> */ unsigned int GPIO:1; // 68328 only
+ /* -> */ unsigned int GPIO_DIR:1; // 68328 only
+ /* -> */ unsigned int GPIO_SRC:1; // 68328 only
+ /* -> */ unsigned int UCLK_DIR:1; // 68EZ328 only
+ /* -> */ unsigned int BAUD_SRC:1;
+ /* + -> */ unsigned int DIVIDE;
+ /* + -> */ unsigned int PRESCALER;
+
+ // Receive register bits
+ // These are all input bits; we set them, not the user.
+
+ /* + <- */ unsigned int RX_FIFO_FULL:1;
+ /* + <- */ unsigned int RX_FIFO_HALF:1;
+ /* + <- */ unsigned int DATA_READY:1;
+ /* <- */ unsigned int OLD_DATA:1; // 68EZ328 only
+ /* <- */ unsigned int OVRUN:1;
+ /* <- */ unsigned int FRAME_ERROR:1;
+ /* <- */ unsigned int BREAK:1;
+ /* <- */ unsigned int PARITY_ERROR:1;
+ /* + <- */ unsigned int RX_DATA;
+
+ // Transmitter register bits
+ // The user sets TX_DATA, IGNORE_CTS, and SEND_BREAK.
+ // We set the rest.
+
+ /* + <- */ unsigned int TX_FIFO_EMPTY:1;
+ /* + <- */ unsigned int TX_FIFO_HALF:1;
+ /* + <- */ unsigned int TX_AVAIL:1;
+ /* -> */ unsigned int SEND_BREAK:1;
+ /* + -> */ unsigned int IGNORE_CTS:1;
+ /* + <- */ unsigned int BUSY:1; // 68EZ328 only
+ /* + <- */ unsigned int CTS_STATUS:1;
+ /* <- */ unsigned int CTS_DELTA:1;
+ /* + -> */ unsigned int TX_DATA;
+
+ // Misc register bits
+ // These are all values the user sets; we just look at them.
+
+ /* -> */ unsigned int BAUD_TEST:1; // 68EZ328 only
+ /* -> */ unsigned int CLK_SRC:1;
+ /* -> */ unsigned int FORCE_PERR:1;
+ /* + -> */ unsigned int LOOP:1;
+ /* -> */ unsigned int BAUD_RESET:1; // 68EZ328 only
+ /* -> */ unsigned int IR_TEST:1; // 68EZ328 only
+ /* + -> */ unsigned int RTS_CONT:1;
+ /* + -> */ unsigned int RTS:1;
+ /* + -> */ unsigned int IRDA_ENABLE:1;
+ /* -> */ unsigned int IRDA_LOOP:1;
+ /* -> */ unsigned int RX_POL:1; // 68EZ328 only
+ /* -> */ unsigned int TX_POL:1; // 68EZ328 only
+
+ // Level Marker Interrupt
+
+ /* + -> */ unsigned int TXFIFO_LEVEL_MARKER:4; // 68SZ328 only
+ /* + -> */ unsigned int RXFIFO_LEVEL_MARKER:4; // 68SZ328 only
+ };
+
+ EmUARTDragonball (UART_Type, int uartNum);
+ ~EmUARTDragonball (void);
+
+ void StateChanged (State&, Bool sendRxData);
+ void UpdateState (State&, Bool refreshRxData);
+
+ void TransmitTxFIFO (EmTransport*);
+ void ReceiveRxFIFO (EmTransport*);
+
+ EmTransport* GetTransport (void);
+
+ private:
+ int PrvFIFOSize (Bool forRX);
+ int PrvLevelMarker (Bool forRX);
+
+ private:
+ int fUARTNum;
+ State fState;
+ EmByteQueue fRxFIFO;
+ EmByteQueue fTxFIFO;
+};
+
+#endif /* EmUARTDragonball_h */
diff --git a/SrcShared/Hardware/TRG/EmHandEra330Defs.h b/SrcShared/Hardware/TRG/EmHandEra330Defs.h
new file mode 100644
index 0000000..4b2e3a5
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmHandEra330Defs.h
@@ -0,0 +1,40 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+#ifndef EmHandEra330Defs_h
+#define EmHandEra330Defs_h
+
+#include "EmHandEraCFBus.h"
+#include "EmHandEraSDBus.h"
+
+#define HE330_NUM_KEY_ROWS 4
+
+typedef struct {
+ uint16 Row[HE330_NUM_KEY_ROWS];
+} HandEra330Keys;
+
+typedef struct {
+ HandEra330Keys Keys;
+ CFBusManager CFBus;
+ SDBusManager SDBus;
+ Bool LCDOn;
+ Bool BacklightOn;
+ Bool IRPortOn;
+ Bool SenseCurrent;
+ Bool pendingIRQ2;
+ Bool CFInserted;
+ Bool SDInserted;
+ Bool PowerConnected;
+ Bool SDChipSelect;
+} HandEra330PortManager;
+
+#endif // EmHandEra330Defs_h
diff --git a/SrcShared/Hardware/TRG/EmHandEraCFBus.h b/SrcShared/Hardware/TRG/EmHandEraCFBus.h
new file mode 100644
index 0000000..8a1fadd
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmHandEraCFBus.h
@@ -0,0 +1,28 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmHandEraCFBus_h
+#define EmHandEraCFBus_h
+
+enum CFBusWidth {
+ kCFBusWidth8,
+ kCFBusWidth16
+};
+
+typedef struct {
+ int bEnabled;
+ enum CFBusWidth Width;
+ int bSwapped;
+} CFBusManager;
+
+#endif // EmHandEraBusDefs_h
diff --git a/SrcShared/Hardware/TRG/EmHandEraSDBus.h b/SrcShared/Hardware/TRG/EmHandEraSDBus.h
new file mode 100644
index 0000000..6853244
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmHandEraSDBus.h
@@ -0,0 +1,22 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmHandEraSDBus_h
+#define EmHandEraSDBus_h
+
+typedef struct {
+ int bEnabled;
+ int bSwapped;
+} SDBusManager;
+
+#endif // EmHandEraBusDefs_h
diff --git a/SrcShared/Hardware/TRG/EmRegs330CPLD.cpp b/SrcShared/Hardware/TRG/EmRegs330CPLD.cpp
new file mode 100644
index 0000000..bc1ed57
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmRegs330CPLD.cpp
@@ -0,0 +1,263 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+#include "EmCommon.h"
+#include "EmRegs330CPLD.h"
+
+#include "EmHAL.h" // EmHAL::LineDriverChanged
+#include "EmHandEra330Defs.h"
+#include "EmMemory.h"
+#include "EmScreen.h" // EmScreenUpdateInfo
+
+/*****************************************************************************
+ * The HandEra 330 uses a CPLD for additional GPIO
+ * This includes:
+ * CF & SD bus control, keyboard row drivers, LCD control, Backlight, IRDA,
+ * RS232 DTR signal, current vs voltage sense, and audio control.
+ *
+ * POSE needs to know about LCD, backlight, keyboard, and current sense so these
+ * are stored in an external HandEra330PortManager class that the EmRegsVZHandEra330
+ * class can get the values from.
+ ****************************************************************************/
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::EmRegs330CPLD
+// ---------------------------------------------------------------------------
+EmRegs330CPLD::EmRegs330CPLD (HandEra330PortManager * fPortManager)
+{
+ Reg0 = Cpld0Edo;
+ Reg2 = Cpld2CfDetect |
+ Cpld2NoSdDetect |
+ Cpld2NoExPwrDetect |
+ Cpld2SdUnwriteProt |
+ Cpld2SdPowerOff |
+ Cpld2Kbd3Inactive |
+ Cpld2Kbd2Inactive |
+ Cpld2Kbd1Inactive |
+ Cpld2Kbd0Inactive |
+ Cpld2NoReset |
+ Cpld2CfBufsOff |
+ Cpld2SwapOff |
+ Cpld2CfPowerOff |
+ Cpld2BusWidth16;
+ Reg4 = Cpld4LcdBiasOff |
+ Cpld4LcdVccOn |
+ Cpld4LcdOff |
+ Cpld4BlPdOff |
+ Cpld4DtrOff |
+ Cpld4MmcCsOn |
+ Cpld4FiltSdOff |
+ Cpld4Rs232Off |
+ Cpld4IrdaOff |
+ Cpld4MicOff |
+ Cpld4SenseVoltage;
+ fPortMgr = fPortManager;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::~EmRegs330CPLD
+// ---------------------------------------------------------------------------
+
+EmRegs330CPLD::~EmRegs330CPLD (void)
+{
+}
+
+void EmRegs330CPLD::Reset(Bool /*hardwareReset*/)
+{
+ fPortMgr->Keys.Row[0] = 1;
+ fPortMgr->Keys.Row[1] = 1;
+ fPortMgr->Keys.Row[2] = 1;
+ fPortMgr->Keys.Row[3] = 1;
+ fPortMgr->LCDOn = false;
+ fPortMgr->BacklightOn = false;
+ fPortMgr->IRPortOn = false;
+ fPortMgr->CFBus.bEnabled = false;
+ fPortMgr->CFBus.Width = kCFBusWidth16;
+ fPortMgr->CFBus.bSwapped = false;
+ fPortMgr->pendingIRQ2 = false;
+ fPortMgr->SDChipSelect = false;
+ fPortMgr->PowerConnected = false;
+}
+
+// -------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+void EmRegs330CPLD::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers();
+ // Now add standard/specialized handers for the defined registers.
+ this->SetHandler((ReadFunction)&EmRegs330CPLD::Read,
+ (WriteFunction)&EmRegs330CPLD::Write,
+ kMemoryStartCPLD,
+ kMemorySizeCPLD);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::GetRealAddress
+// ---------------------------------------------------------------------------
+uint8 * EmRegs330CPLD::GetRealAddress (emuptr address)
+{
+ return (address-kMemoryStartCPLD) + Buffer;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::GetWord
+// ---------------------------------------------------------------------------
+uint32 EmRegs330CPLD::GetWord (emuptr address)
+{
+ uint32 offset = address - kMemoryStartCPLD;
+
+ switch (offset)
+ {
+ case CpldReg00 :
+ return Cpld0Edo;
+
+ case CpldReg02 :
+ if (fPortMgr->CFInserted)
+ Reg2 &= ~Cpld2NoCfDetect;
+ else
+ Reg2 |= Cpld2NoCfDetect;
+ if (fPortMgr->SDInserted)
+ Reg2 &= ~Cpld2NoSdDetect;
+ else
+ Reg2 |= Cpld2NoSdDetect;
+ if (fPortMgr->PowerConnected)
+ Reg2 &= ~Cpld2NoExPwrDetect;
+ else
+ Reg2 |= Cpld2NoExPwrDetect;
+ return (Reg2);
+
+ case CpldReg04 :
+ return (Reg4);
+
+ default :
+ return 0;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::SetWord
+// ---------------------------------------------------------------------------
+void EmRegs330CPLD::SetWord (emuptr address, uint32 val)
+{
+ uint32 offset = address - kMemoryStartCPLD;
+
+ switch (offset)
+ {
+ case CpldReg00 :
+ fPortMgr->pendingIRQ2 = false;
+ break;
+
+ case CpldReg02 :
+ Reg2 = (val & 0x0fff) | (Reg2 & 0xf000); // top 4 bits are read only.
+
+ // keys:
+ fPortMgr->Keys.Row[3] = (Reg2 & Cpld2Kbd3Inactive) ? 0 : 1;
+ fPortMgr->Keys.Row[2] = (Reg2 & Cpld2Kbd2Inactive) ? 0 : 1;
+ fPortMgr->Keys.Row[1] = (Reg2 & Cpld2Kbd1Inactive) ? 0 : 1;
+ fPortMgr->Keys.Row[0] = (Reg2 & Cpld2Kbd0Inactive) ? 0 : 1;
+
+ // CF:
+ fPortMgr->CFBus.bEnabled = (Reg2 & Cpld2CfBufsOn);
+ if (Reg2 & Cpld2BusWidth8)
+ {
+ fPortMgr->CFBus.Width = kCFBusWidth8;
+
+ // HandEra330 byte swapping is not the same as the TRGpro when
+ // in byte mode. On the TRGpro it must be enabled to access bytes
+ // correctly, on the 330 it will work either way...
+ // Fudge it here to be the same as TRGpro so code can be shared.
+ fPortMgr->CFBus.bSwapped = true;
+ }
+ else
+ {
+ fPortMgr->CFBus.Width = kCFBusWidth16;
+ fPortMgr->CFBus.bSwapped = (Reg2 & Cpld2SwapOn);
+ }
+
+ break;
+
+ case CpldReg04 :
+ Bool backlightWasOn = fPortMgr->BacklightOn;
+ Bool lcdWasOn = fPortMgr->LCDOn;
+ Bool irWasOn = fPortMgr->IRPortOn;
+
+ Reg4 = val;
+
+ fPortMgr->LCDOn = (Reg4 & Cpld4LcdBiasOn);
+ fPortMgr->BacklightOn = (Reg4 & Cpld4BlPdOn);
+ fPortMgr->IRPortOn = (Reg4 & Cpld4IrdaOff) == 0;
+ fPortMgr->SenseCurrent = (Reg4 & Cpld4SenseCurrent);
+ fPortMgr->SDChipSelect = ((Reg4 & Cpld4MmcCsOn) == 0);
+
+ if ((fPortMgr->LCDOn != lcdWasOn) || (fPortMgr->BacklightOn != backlightWasOn))
+ EmScreen::InvalidateAll ();
+
+ if (irWasOn != fPortMgr->IRPortOn)
+ EmHAL::LineDriverChanged (kUARTIR);
+
+ break;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::GetAddressStart
+// ---------------------------------------------------------------------------
+emuptr EmRegs330CPLD::GetAddressStart (void)
+{
+ return (kMemoryStartCPLD);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::GetAddressRange
+// ---------------------------------------------------------------------------
+uint32 EmRegs330CPLD::GetAddressRange (void)
+{
+ return kMemorySizeCPLD;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::Read
+// ---------------------------------------------------------------------------
+uint32 EmRegs330CPLD::Read(emuptr address, int size)
+{
+ switch(size)
+ {
+// case sizeof(uint8) :
+// return(GetByte(address));
+ case sizeof(uint16) :
+ return(GetWord(address));
+ }
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegs330CPLD::Write
+// ---------------------------------------------------------------------------
+void EmRegs330CPLD::Write(emuptr address, int size, uint32 val)
+{
+ switch(size)
+ {
+// case sizeof(uint8) :
+// SetByte(address, val);
+// break;
+ case sizeof(uint16) :
+ SetWord(address, val);
+ break;
+ }
+}
+
diff --git a/SrcShared/Hardware/TRG/EmRegs330CPLD.h b/SrcShared/Hardware/TRG/EmRegs330CPLD.h
new file mode 100644
index 0000000..08487aa
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmRegs330CPLD.h
@@ -0,0 +1,144 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+#ifndef EmRegs330CPLD_h
+#define EmRegs330CPLD_h
+
+#include "EmRegs.h"
+#include "EmHandEra330Defs.h"
+
+#define CpldReg00 0x0000
+// CPLD Register 0x0000 Bit Definitions
+// -------------------------------------
+ #define Cpld0Edo 0x0002
+ #define Cpld0Sdram 0x0000
+
+#define CpldReg02 0x0002
+// CPLD Register 0x0002 Bit Definitions
+// -------------------------------------
+ #define Cpld2NoCfDetect 0x8000
+ #define Cpld2CfDetect 0x0000
+
+ #define Cpld2NoSdDetect 0x4000
+ #define Cpld2SdDetect 0x0000
+
+ #define Cpld2NoExPwrDetect 0x2000
+ #define Cpld2ExPwrDetect 0x0000
+
+ #define Cpld2SdUnwriteProt 0x0000
+ #define Cpld2SdWriteProt 0x1000
+
+ #define Cpld2SdPowerOn 0x0000
+ #define Cpld2SdPowerOff 0x0200
+
+ #define Cpld2Kbd3Active 0x0000
+ #define Cpld2Kbd3Inactive 0x0100
+
+ #define Cpld2Kbd2Active 0x0000
+ #define Cpld2Kbd2Inactive 0x0080
+
+ #define Cpld2Kbd1Active 0x0000
+ #define Cpld2Kbd1Inactive 0x0040
+
+ #define Cpld2Kbd0Active 0x0000
+ #define Cpld2Kbd0Inactive 0x0020
+
+ #define Cpld2NoReset 0x0000
+ #define Cpld2Reset 0x0010
+
+ #define Cpld2CfBufsOff 0x0000
+ #define Cpld2CfBufsOn 0x0008
+
+ #define Cpld2SwapOff 0x0000
+ #define Cpld2SwapOn 0x0004
+
+ #define Cpld2CfPowerOn 0x0000
+ #define Cpld2CfPowerOff 0x0002
+
+ #define Cpld2BusWidth16 0x0000
+ #define Cpld2BusWidth8 0x0001
+
+#define CpldReg04 0x0004
+// CPLD Register 0x0004 Bit Definitions
+// -------------------------------------
+ #define Cpld4LcdBiasOff 0x0000
+ #define Cpld4LcdBiasOn 0x0400
+
+ #define Cpld4LcdVccOn 0x0000
+ #define Cpld4LcdVccOff 0x0200
+
+ #define Cpld4LcdOff 0x0000
+ #define Cpld4LcdON 0x0100
+
+ #define Cpld4BlPdOff 0x0000
+ #define Cpld4BlPdOn 0x0080
+
+ #define Cpld4DtrOn 0x0000
+ #define Cpld4DtrOff 0x0040
+
+ #define Cpld4MmcCsOff 0x0000
+ #define Cpld4MmcCsOn 0x0020
+
+ #define Cpld4FiltSdOff 0x0000
+ #define Cpld4FiltSdOn 0x0010
+
+ #define Cpld4Rs232Off 0x0000
+ #define Cpld4Rs232On 0x0008
+
+ #define Cpld4IrdaOn 0x0000
+ #define Cpld4IrdaOff 0x0004
+
+ #define Cpld4MicOn 0x0000
+ #define Cpld4MicOff 0x0002
+
+ #define Cpld4SenseVoltage 0x0000
+ #define Cpld4SenseCurrent 0x0001
+
+
+const uint32 kMemoryStartCPLD = 0x10E00000;
+const uint32 kMemorySizeCPLD = 0x100;
+
+class EmRegs330CPLD : public EmRegs
+{
+ public:
+ EmRegs330CPLD (HandEra330PortManager * fPortManager);
+ virtual ~EmRegs330CPLD (void);
+
+ virtual void Reset (Bool hardwareReset);
+
+ uint8* GetRealAddress (emuptr address);
+ void SetSubBankHandlers (void);
+ emuptr GetAddressStart (void);
+ uint32 GetAddressRange (void);
+
+ uint32 GetWord (emuptr iAddress);
+ void SetWord (emuptr iAddress, uint32 iWordValue);
+
+ // only word access is allowed to the CPLD
+// uint32 GetLong (emuptr iAddress) { return 0;}
+// uint32 GetByte (emuptr iAddress) { return 0;}
+// void SetLong (emuptr iAddress, uint32 iLongValue) {}
+// void SetByte (emuptr iAddress, uint32 iByteValue) {}
+private:
+ uint16 Reg0;
+ uint16 Reg2;
+ uint16 Reg4;
+ uint8 Buffer[kMemorySizeCPLD];
+ uint32 Read (emuptr address, int size);
+ void Write (emuptr address, int size, uint32 value);
+// void SetReg02(uint16 val);
+// void SetReg04(uint16 val);
+ HandEra330PortManager * fPortMgr;
+};
+
+#endif // EmTRGCFDefs_h
+
diff --git a/SrcShared/Hardware/TRG/EmSPISlave330Current.cpp b/SrcShared/Hardware/TRG/EmSPISlave330Current.cpp
new file mode 100644
index 0000000..43fd47b
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmSPISlave330Current.cpp
@@ -0,0 +1,189 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmSPISlave330Current.h"
+
+#include "Logging.h"
+#define PRINTF if (1) ; else LogAppendMsg
+
+
+/*****************************************************************************
+ * The HandEra 330 includes a battery current sense. It is switched in and
+ * out of channel 2 of the ADC.
+ ****************************************************************************/
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave330Current::EmSPISlave330Current
+// ---------------------------------------------------------------------------
+
+EmSPISlave330Current::EmSPISlave330Current () :
+ EmSPISlave (),
+ fBitBufferIn (0),
+ fBitBufferOut (0),
+ fNumBitsIn (0),
+ fPendingResult (0),
+ fHavePending (false),
+ fCommandBitsSeen (0),
+ fPowerConnected(false)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave330Current::~EmSPISlave330Current
+// ---------------------------------------------------------------------------
+
+EmSPISlave330Current::~EmSPISlave330Current (void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave330Current::DoExchange
+// ---------------------------------------------------------------------------
+
+uint16 EmSPISlave330Current::DoExchange (uint16 control, uint16 data)
+{
+ PRINTF ("");
+ PRINTF ("EmSPISlave330Current::DoExchange");
+ PRINTF ("control = 0x%04X, data = 0x%04X", control, data);
+
+ // -----------------------------------------------------------------------
+ // Merge the incoming bits with our current buffer.
+ // -----------------------------------------------------------------------
+
+ uint16 numBits = (control & hwrVZ328SPIMControlBitsMask) + 1;
+ uint32 oldBitsMask = ~0 << numBits;
+ uint32 newBitsMask = ~oldBitsMask;
+
+ PRINTF ("Before merging input: fBitBufferIn = 0x%04X, fNumBitsIn = 0x%04X", fBitBufferIn, fNumBitsIn);
+
+ fBitBufferIn = ((fBitBufferIn << numBits) & oldBitsMask) | (data & newBitsMask);
+ fNumBitsIn += numBits;
+
+ PRINTF ("After merging input: fBitBufferIn = 0x%04X, fNumBitsIn = 0x%04X", fBitBufferIn, fNumBitsIn);
+
+ // -----------------------------------------------------------------------
+ // Start processing the command bits.
+ // -----------------------------------------------------------------------
+
+ EmAssert (fNumBitsIn - fCommandBitsSeen - 1 >= 0);
+
+ uint16 result = 0;
+ uint32 mask = 1 << (fNumBitsIn - fCommandBitsSeen - 1);
+
+ while (mask)
+ {
+ // Shift out a bit.
+
+ {
+ result = (result << 1) | (fBitBufferOut >> 15);
+ fBitBufferOut <<= 1;
+ }
+
+ // If we haven't seen the Start bit yet, look for it.
+
+ if (fCommandBitsSeen == 0)
+ {
+ // If we found the Start bit, start counting the
+ // number of command bits as we stream through them.
+
+ if ((mask & fBitBufferIn) != 0)
+ {
+ fCommandBitsSeen++;
+ }
+
+ // Otherwise, adjust fNumBitsIn so that when we *do*
+ // find the Start bit, we know where it is.
+
+ else
+ {
+ fNumBitsIn--;
+ }
+
+ // If there's a pending conversion, load it into the
+ // output shift register after receiving the first
+ // bit after the last bit of the previous command.
+
+ this->LoadPendingConversion ();
+ }
+ else
+ {
+ fCommandBitsSeen++;
+
+ // If we've seen 8 bits, process the command, and then
+ // prepare for the next one.
+
+ if (fCommandBitsSeen == 8)
+ {
+ fNumBitsIn -= 8;
+ fCommandBitsSeen = 0;
+
+ uint8 command = fBitBufferIn >> fNumBitsIn;
+ this->ProcessCommand (command);
+
+ PRINTF ("After ProcessCommand: fPendingResult = 0x%04X", fPendingResult);
+ }
+ }
+
+ mask >>= 1;
+ }
+
+
+ // ----------------------------------------------------------------------
+ // Return the result.
+ // ----------------------------------------------------------------------
+
+ PRINTF ("result = 0x%04X", result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave330Current::ProcessCommand
+// ---------------------------------------------------------------------------
+
+void EmSPISlave330Current::ProcessCommand (uint8 command)
+{
+ uint16 result = 0;
+
+ // we should only get here for channel 2
+ EmAssert (((command & kChannelBits) >> 4) == 2);
+
+ if (fPowerConnected)
+ result = 0; // no battery current with ext power connected.
+ else
+ result = 0x60; // just hard code some current for now.
+
+ fPendingResult = result << 4;
+ fHavePending = true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmSPISlave330Current::LoadPendingConversion
+// ---------------------------------------------------------------------------
+
+void EmSPISlave330Current::LoadPendingConversion (void)
+{
+ // -----------------------------------------------------------------------
+ // If there's a pending conversion, move it into the output shift register.
+ // -----------------------------------------------------------------------
+ if (fHavePending)
+ {
+ fHavePending = false;
+ fBitBufferOut = fPendingResult;
+ }
+}
+
diff --git a/SrcShared/Hardware/TRG/EmSPISlave330Current.h b/SrcShared/Hardware/TRG/EmSPISlave330Current.h
new file mode 100644
index 0000000..c514250
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmSPISlave330Current.h
@@ -0,0 +1,51 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmSPISlave330Current_h
+#define EmSPISlave330Current_h
+
+#include "EmSPISlave.h" // EmSPISlave
+
+#define kChannelBits 0x70
+
+/*--------------------------------------------------------------------
+ * HandEra 330 has an analog switch which switches between voltage and
+ * current sense on channel 2. Need to cobble together something so
+ * it can sense some battery current and not think we are always on
+ * external power.
+ *-------------------------------------------------------------------*/
+class EmSPISlave330Current : public EmSPISlave
+{
+ public:
+ EmSPISlave330Current ();
+ virtual ~EmSPISlave330Current (void);
+
+ virtual uint16 DoExchange (uint16 control, uint16 data);
+ void SetMode (Bool powerConnected) { fPowerConnected = powerConnected; }
+
+ protected:
+ void ProcessCommand (uint8);
+ void LoadPendingConversion (void);
+
+ private:
+ uint32 fBitBufferIn;
+ uint16 fBitBufferOut;
+ int fNumBitsIn;
+ uint16 fPendingResult;
+ Bool fHavePending;
+ int fCommandBitsSeen;
+
+ Bool fPowerConnected;
+};
+
+#endif \ No newline at end of file
diff --git a/SrcShared/Hardware/TRG/EmTRG.cpp b/SrcShared/Hardware/TRG/EmTRG.cpp
new file mode 100644
index 0000000..f079538
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRG.cpp
@@ -0,0 +1,57 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRG.h"
+
+#include "EmBankRegs.h"
+#include "EmRegsEZTRGpro.h"
+#include "EmRegs330CPLD.h"
+#include "EmRegsVZHandEra330.h"
+#include "EmHandEraCFBus.h"
+#include "EmHandEraSDBus.h"
+#include "EmTRGCF.h"
+#include "EmTRGSD.h"
+
+
+/***********************************************************************
+ *
+ * FUNCTION: OEMCreateTRGRegObjs
+ *
+ * DESCRIPTION: This function is called by EmDevice::CreateRegs for TRG
+ * devices
+ *
+ * PARAMETERS: 'fHardwareSubID' specifies the device
+ *
+ * RETURNED: None
+ *
+ ***********************************************************************/
+void OEMCreateTRGRegObjs(long hardwareSubID)
+{
+ CFBusManager * fCFBus;
+ HandEra330PortManager * fPortMgr;
+
+ switch (hardwareSubID)
+ {
+ case hwrTRGproID :
+ default :
+ EmBankRegs::AddSubBank (new EmRegsEZTRGpro(&fCFBus));
+ EmBankRegs::AddSubBank (new EmRegsCFMemCard(fCFBus));
+ break;
+ case hwrTRGproID + 1 :
+ EmBankRegs::AddSubBank (new EmRegsVZHandEra330(&fPortMgr));
+ EmBankRegs::AddSubBank (new EmRegs330CPLD(fPortMgr));
+ EmBankRegs::AddSubBank (new EmRegsCFMemCard(&fPortMgr->CFBus));
+ break;
+ }
+}
diff --git a/SrcShared/Hardware/TRG/EmTRG.h b/SrcShared/Hardware/TRG/EmTRG.h
new file mode 100644
index 0000000..21d14d5
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRG.h
@@ -0,0 +1,23 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRG_h
+#define EmTRG_h
+
+#define TRGPRO_MANUF "TRG Products"
+#define hwrOEMDeviceIDTRGpro 1
+#define hwrTRGproID 0
+
+void OEMCreateTRGRegObjs(long hardwareSubID);
+
+#endif // EmTRG_h
diff --git a/SrcShared/Hardware/TRG/EmTRGATA.cpp b/SrcShared/Hardware/TRG/EmTRGATA.cpp
new file mode 100644
index 0000000..fcff3e6
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGATA.cpp
@@ -0,0 +1,471 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGATA.h"
+
+// ------------------------------------------------------------------------
+// This file emulates the ATA Registers on the CF Memory Card.
+//
+// Address Description
+// --------------------- --------------------
+// 0x18001000-0x1800100F ATA Registers
+// 0x18001010-0x180013FF Mirror of the ATA Registers
+// 0x18001400-0x18001FFF Equivalent to the Data-Even/Data-Odd Registers
+// ------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::EmRegsCFAta
+// ---------------------------------------------------------------------------
+EmRegsCFAta::EmRegsCFAta(void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::~EmRegsCFATA
+// ---------------------------------------------------------------------------
+EmRegsCFAta::~EmRegsCFAta(void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Initialize
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Initialize(EmDiskTypeID DiskTypeID)
+{
+ int i;
+
+ AtaMode = MODE_DISK_IO;
+ DiskIO.Initialize(DiskTypeID);
+ for (i=0; i<NUM_IDE_REGS; i++)
+ RegMem[i] = i;
+ RegMem[6] = 0xA0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reset
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Reset(void)
+{
+ DiskIO.Reset();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Dispose
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Dispose(void)
+{
+ DiskIO.Dispose();
+}
+
+//----------------------------------------------------------------------------
+// Status and Alternate Status Registers Offsets 7h and Eh
+//
+// These registers return the CompactFlash Storage Card status when read by
+// the host. Reading the Status register does clear a pending interrupt while
+// reading the Auxiliary Status register does not. The status bits are
+// described as follows:
+//
+// D7 D6 D5 D4 D3 D2 D1 D0
+// --- --- --- --- --- --- --- ---
+// BSY RDY DWF DSC DRQ CRR 0 ERR
+//
+// Bit 7 (BUSY): the busy bit is set when the CompactFlash Storage Card has
+// access to the command buffer and registers and the host is locked out
+// from accessing the command register and buffer. No other bits in this
+// register are valid when this bit is set to a 1.
+// Bit 6 (RDY): RDY indicates whether the device is capable of performing
+// CompactFlash Storage Card operations. This bit is cleared at power up
+// and remains cleared until the CompactFlash Storage Card is ready to
+// accept a command.
+// Bit 5 (DWF): This bit, if set, indicates a write fault has occurred.
+// Bit 4 (DSC): This bit is set when the CompactFlash Storage Card is ready.
+// Bit 3 (DRQ): The Data Request is set when the CompactFlash Storage Card
+// requires that information be transferred either to or from the host
+// through the Data register.
+// Bit 2 (CORR): This bit is set when a Correctable data error has been
+// encountered and the data has been corrected. This condition does not
+// terminate a multi-sector read operation.
+// Bit 1 (IDX): This bit is always set to 0.
+// Bit 0 (ERR): This bit is set when the previous command has ended in
+// some type of error. The bits in the Error register contain additional
+// information describing the error. It is recommended that media access
+// commands (such as Read Sectors and Write Sectors) that end with an
+// error condition should have the address of the first sector in error
+// in the command block registers.
+//----------------------------------------------------------------------------
+uint8 EmRegsCFAta::RegReadStatus(Boolean /*is_alt_reg*/)
+{
+ uint8 retVal;
+ DiskIOStatus status;
+ DiskDataStatus dataStatus;
+
+ DiskIO.GetStatus(&status, &dataStatus);
+ if (status == DIO_SUCCESS)
+ {
+ retVal = (IDE_STS_RDY|IDE_STS_DSC);
+ if (dataStatus == DIO_MORE_DATA)
+ {
+ retVal |= IDE_STS_DRQ;
+ }
+ else
+ {
+ DiskParams.Lba += DiskParams.SectorCnt;
+ RegMem[IDE_REG_5_LBA_23_16] = (uint8)(DiskParams.Lba >> 16);
+ RegMem[IDE_REG_4_LBA_15_8] = (uint8)(DiskParams.Lba >> 8);
+ RegMem[IDE_REG_3_LBA_7_0] = (uint8)DiskParams.Lba;
+ }
+ }
+ else
+ {
+ retVal = (IDE_STS_RDY|IDE_STS_DSC|IDE_STS_ERR);
+ }
+ return(retVal);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::GetDiskIOParams
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::GetDiskIOParams(DiskIOParams * Params)
+{
+ Params->DriveNum = 0;
+ Params->Lba =
+ (((uint32)RegMem[IDE_REG_6_DRV_HEAD] & 0x0F) << 24) +
+ ((uint32)RegMem[IDE_REG_5_LBA_23_16] << 16) +
+ ((uint32)RegMem[IDE_REG_4_LBA_15_8] << 8) +
+ (uint32)RegMem[IDE_REG_3_LBA_7_0];
+ Params->SectorCnt = (uint32)RegMem[IDE_REG_2_SECTOR_CNT];
+ if (Params->SectorCnt == 0)
+ Params->SectorCnt = 256;
+
+ DiskParams = *Params;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::CmdIdentifyDrive
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::CmdIdentifyDrive(void)
+{
+ DiskIO.StartDriveID();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::CmdReadSectors
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::CmdReadSectors(void)
+{
+ DiskIOParams params;
+
+ GetDiskIOParams(&params);
+ DiskIO.StartRead(&params);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::CmdWriteSectors
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::CmdWriteSectors(void)
+{
+ DiskIOParams params;
+
+ GetDiskIOParams(&params);
+ DiskIO.StartWrite(&params);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::CmdDriveDiagnostic
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::CmdDriveDiagnostic(void)
+{
+ AtaMode = MODE_DRIVE_DIAGNOSTICS;
+}
+
+//----------------------------------------------------------------------------
+// Data Register Offset 0 (8-bit) and 8-9 (16-bit)
+//
+// The Data Register is a 16-bit register, and it is used to transfer data
+// blocks between the CompactFlash Storage Card data buffer and the Host.
+// This register overlaps the Error Register. The table below describes the
+// combinations of data register access and is provided to assist in
+// understanding the overlapped Data Register and Error/Feature Register
+// rather than to attempt to define general PCMCIA word and byte access
+// modes and operations. See the PCMCIA PC Card Standard Release 2.0 for
+// definitions of the Card Accessing Modes for I/O and Memory cycles.
+// Note: Because of the overlapped registers, access to the 1F1h, 171h or
+// offset 1 are not defined for word (-CE2 = 0 and -CE1 = 0) operations.
+// These accesses are treated as accesses to the Word Data Register.
+// The duplicated registers at offsets 8, 9 and Dh have no restrictions on
+// the operations that can be performed by the socket.
+//----------------------------------------------------------------------------
+uint8 EmRegsCFAta::Reg0ReadData(void)
+{
+ DiskIO.ReadNextDataByte(&RegMem[IDE_REG_0_DATA]);
+ return(RegMem[IDE_REG_0_DATA]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg0WriteData
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Reg0WriteData(void)
+{
+ DiskIO.WriteNextDataByte(RegMem[IDE_REG_0_DATA]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg8ReadDataEven
+// ---------------------------------------------------------------------------
+uint8 EmRegsCFAta::Reg8ReadDataEven(void)
+{
+ DiskIO.ReadNextDataByte(&RegMem[IDE_REG_8_DATA_EVEN]);
+ return(RegMem[IDE_REG_8_DATA_EVEN]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg8WriteDataEven
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Reg8WriteDataEven(void)
+{
+ DiskIO.WriteNextDataByte(RegMem[IDE_REG_8_DATA_EVEN]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg9ReadDataOdd
+// ---------------------------------------------------------------------------
+uint8 EmRegsCFAta::Reg9ReadDataOdd(void)
+{
+ DiskIO.ReadNextDataByte(&RegMem[IDE_REG_9_DATA_ODD]);
+ return(RegMem[IDE_REG_9_DATA_ODD]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg9WriteDataOdd
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Reg9WriteDataOdd(void)
+{
+ DiskIO.WriteNextDataByte(RegMem[IDE_REG_9_DATA_ODD]);
+}
+
+//----------------------------------------------------------------------------
+// Error Register -- Offset 1h and Dh (read-only)
+//
+// This register contains additional information about the source of
+// an error when an error is indicated in bit 0 of the Status register.
+// The bits are defined as follows:
+//
+// Error Register
+// This register is also accessed on data bits D15-D8 during a write
+// operation to offset 0 with -CE2 low and -CE1 high.
+//
+// Bit 7 (BBK): this bit is set when a Bad Block is detected.
+// Bit 6 (UNC): this bit is set when an Uncorrectable Error is encountered.
+// Bit 5: this bit is 0.
+// Bit 4 (IDNF): the requested sector ID is in error or cannot be found.
+// Bit 3: this bit is 0.
+// Bit 2 (Abort) This bit is set if the command has been aborted because of
+// a CompactFlash Storage Card status condition: (Not Ready, Write Fault,
+// etc.) or when an invalid command has been issued.
+// Bit 1 This bit is 0.
+// Bit 0 (AMNF) This bit is set in case of a general error.
+//----------------------------------------------------------------------------
+uint8 EmRegsCFAta::RegReadError(Boolean /*is_alt_reg*/)
+{
+ if (AtaMode == MODE_DRIVE_DIAGNOSTICS)
+ return(IDE_DIA_01_NO_ERROR);
+ else
+ return DiskIO.GetError();
+}
+
+
+//----------------------------------------------------------------------------
+// Sector Count Register (Offset 2h)
+//
+// This register contains the numbers of sectors of data requested to be
+// transferred on a read or write operation between the host and the
+// CompactFlash Storage Card. If the value in this register is zero,
+// a count of 256 sectors is specified. If the command was successful,
+// this register is zero at command completion. If not successfully completed,
+// the register contains the number of sectors that need to be transferred
+// in order to complete the request.
+//----------------------------------------------------------------------------
+uint8 EmRegsCFAta::Reg2ReadSectorCount(void)
+{
+ uint32 cnt;
+
+ cnt = DiskIO.GetSectorCount();
+ if (cnt > 0xFF)
+ cnt = 0x0;
+ return(cnt);
+}
+
+//----------------------------------------------------------------------------
+// Device Control Register -- Offset Eh
+// This register is used to control the CompactFlash Storage Card interrupt
+// request and to issue an ATA soft reset to the card. This register can
+// be written even if the device is BUSY. The bits are defined as follows:
+//
+// D7 D6 D5 D4 D3 D2 D1 D0
+// --- --- --- --- --- ------ ---- ---
+// X X X X 1 SW Rst -IEn 0
+//
+// Bit 7: this bit is an X (don't care).
+// Bit 6: this bit is an X (don't care).
+// Bit 5: this bit is an X (don't care).
+// Bit 4: this bit is an X (don't care).
+// Bit 3: this bit is ignored by the CompactFlash Storage Card.
+// Bit 2 (SW Rst): this bit is set to 1 in order to force the CompactFlash
+// Storage Card to perform an AT Disk controller Soft Reset operation.
+// This does not change the PCMCIA Card Configuration Registers (4.3.2
+// to 4.3.5) as a hardware Reset does. The Card remains in Reset until this
+// bit is reset to 0.
+// Bit 1 (-IEn): the Interrupt Enable bit enables interrupts when the bit is
+// 0. When the bit is 1, interrupts from the CompactFlash Storage Card are
+// disabled. This bit also controls the Int bit in the Configuration and
+// Status Register. This bit is set to 0 at power on and Reset.
+// Bit 0: this bit is ignored by the CompactFlash Storage Card.
+//----------------------------------------------------------------------------
+void EmRegsCFAta::RegEWriteDeviceControl(void)
+{
+ DiskIO.Reset();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::Reg7WriteCmd
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::Reg7WriteCmd(void)
+{
+ AtaMode = MODE_DISK_IO;
+ DiskIO.ClearError();
+ switch(RegMem[IDE_REG_7_COMMAND])
+ {
+ case IDE_CMD_EC_IDENTIFY_DRIVE :
+ CmdIdentifyDrive();
+ break;
+
+ case IDE_CMD_20_READ_SECTORS :
+ case IDE_CMD_21_READ_SECTORS :
+ CmdReadSectors();
+ break;
+
+ case IDE_CMD_30_WRITE_SECTORS :
+ case IDE_CMD_31_WRITE_SECTORS :
+ CmdWriteSectors();
+ break;
+
+ case IDE_CMD_90_EXEC_DRIVE_DIAGNOSTIC :
+ CmdDriveDiagnostic();
+ break;
+
+ case IDE_CMD_C6_SET_MULTIPLE_MODE :
+ DiskIO.SetError(IDE_ERR_04_ABORT);
+ break;
+
+ default :
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::ReadByte
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::ReadByte(uint32 offset,
+ uint8 * val)
+{
+ *val = 0;
+ switch(offset)
+ {
+ case IDE_REG_0_DATA :
+ *val = Reg0ReadData();
+ break;
+ case IDE_REG_1_ERROR :
+ *val = RegReadError(IS_BASE_REG);
+ break;
+ case IDE_REG_D_ERROR :
+ *val = RegReadError(IS_ALT_REG);
+ break;
+ case IDE_REG_2_SECTOR_CNT :
+ *val = Reg2ReadSectorCount();
+ break;
+ case IDE_REG_7_STATUS :
+ *val = RegReadStatus(IS_BASE_REG);
+ break;
+ case IDE_REG_E_ALT_STATUS :
+ *val = RegReadStatus(IS_ALT_REG);
+ break;
+ case IDE_REG_8_DATA_EVEN :
+ *val = Reg8ReadDataEven();
+ break;
+ case IDE_REG_9_DATA_ODD :
+ *val = Reg9ReadDataOdd();
+ break;
+ default :
+ if (offset < NUM_IDE_REGS)
+ *val = RegMem[offset];
+ else
+ *val = 0;
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::WriteByte
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::WriteByte(uint32 offset, uint8 val)
+{
+ RegMem[offset] = val;
+ switch(offset)
+ {
+ case IDE_REG_0_DATA :
+ Reg0WriteData();
+ break;
+ case IDE_REG_7_COMMAND :
+ Reg7WriteCmd();
+ break;
+ case IDE_REG_8_DATA_EVEN :
+ Reg8WriteDataEven();
+ break;
+ case IDE_REG_9_DATA_ODD :
+ Reg9WriteDataOdd();
+ break;
+ case IDE_REG_E_DEVICE_CONTROL :
+ RegEWriteDeviceControl();
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::ReadWord
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::ReadWord(uint32 offset,
+ _Word * val)
+{
+ // 16-bit reads of Register 0 are NOT equivalent to 2 8-bit reads
+ // of Register 0 and 1 ... instead it reads the Even & Odd Data
+ // bytes, so we change the register to be 8
+ if (offset == IDE_REG_0_DATA)
+ offset = IDE_REG_8_DATA_EVEN;
+ ReadByte(offset, &val->Bytes[0]);
+ ReadByte(offset+1, &val->Bytes[1]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFAta::WriteWord
+// ---------------------------------------------------------------------------
+void EmRegsCFAta::WriteWord(uint32 offset, _Word val)
+{
+ // 16-bit writes of Register 0 are NOT equivalent to 2 8-bit writes
+ // of Register 0 and 1 ... instead it writes the Even & Odd Data
+ // bytes, so we change the register to be 8
+ if (offset == IDE_REG_0_DATA)
+ offset = IDE_REG_8_DATA_EVEN;
+ WriteByte(offset, val.Bytes[0]);
+ WriteByte(offset+1, val.Bytes[1]);
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGATA.h b/SrcShared/Hardware/TRG/EmTRGATA.h
new file mode 100644
index 0000000..4b743cb
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGATA.h
@@ -0,0 +1,63 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGATA_h
+#define EmTRGATA_h
+
+#include "EmRegs.h"
+#include "EmTRGCFDefs.h"
+#include "EmTRGCFIO.h"
+
+#define IS_ALT_REG true
+#define IS_BASE_REG false
+
+typedef enum {MODE_DISK_IO=0, MODE_DRIVE_DIAGNOSTICS=1} AtaModeType;
+
+class EmRegsCFAta
+{
+ public:
+ EmRegsCFAta(void);
+ virtual ~EmRegsCFAta(void);
+
+ void Initialize(EmDiskTypeID DiskTypeID);
+ void Reset (void);
+ void Dispose (void);
+ void ReadByte(uint32 offset, uint8 * val);
+ void WriteByte(uint32 offset, uint8 val);
+ void ReadWord(uint32 offset, _Word * val);
+ void WriteWord(uint32 offset, _Word val);
+ private:
+ uint8 RegMem[NUM_IDE_REGS];
+ AtaModeType AtaMode;
+ DiskIOParams DiskParams;
+ void GetDiskIOParams(DiskIOParams * params);
+ uint8 Reg0ReadData(void);
+ uint8 RegReadError(Boolean is_alt_reg);
+ uint8 Reg2ReadSectorCount(void);
+ void Reg0WriteData(void);
+ void Reg7WriteCmd(void);
+ uint8 RegReadStatus(Boolean is_alt_reg);
+ uint8 Reg8ReadDataEven(void);
+ void Reg8WriteDataEven(void);
+ uint8 Reg9ReadDataOdd(void);
+ void Reg9WriteDataOdd(void);
+ void RegEWriteDeviceControl(void);
+ EmCFIO DiskIO;
+ uint8 ConvertStatus(void);
+ void CmdIdentifyDrive(void);
+ void CmdWriteSectors(void);
+ void CmdReadSectors(void);
+ void CmdDriveDiagnostic(void);
+};
+
+#endif // EmTRGATA_h
diff --git a/SrcShared/Hardware/TRG/EmTRGCF.cpp b/SrcShared/Hardware/TRG/EmTRGCF.cpp
new file mode 100644
index 0000000..3a62a17
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCF.cpp
@@ -0,0 +1,305 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGCF.h"
+
+#include "EmMemory.h"
+
+
+
+//-------------------------------------------------------------------------
+// This file contains the class EmRegsCFMemCard, which emulates a
+// CompactFlash memory card. The bulk of this class is a series of
+// routines to dispatch calls to the appropriate section of a memory
+// card ... either its Tuple memory, its Configuration Registers, or its
+// ATA registers. This class also handles all decisions about how to
+// emulate the effect of the current bus state (8-bit vs. 16-bit, swap vs.
+// no swap) on the data.
+//-------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::EmRegsCFMemCard
+// ---------------------------------------------------------------------------
+
+EmRegsCFMemCard::EmRegsCFMemCard (CFBusManager * fBusManager)
+{
+ fBusMgr = fBusManager;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::~EmRegsCFMemCard
+// ---------------------------------------------------------------------------
+
+EmRegsCFMemCard::~EmRegsCFMemCard (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Initialize
+// ---------------------------------------------------------------------------
+
+void EmRegsCFMemCard::Initialize (void)
+{
+ DiskTypeID = EM_DISK_GENERIC_8MB;
+
+ Ata.Initialize(DiskTypeID);
+ Config.Initialize(DiskTypeID);
+ Tuple.Initialize(DiskTypeID);
+ CFReset.Initialize(DiskTypeID);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Reset
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::Reset (Bool /*hardwareReset*/)
+{
+ Ata.Reset();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Save
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::Save (SessionFile& /*f*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Load
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::Load (SessionFile& /*f*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Dispose
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::Dispose (void)
+{
+ Ata.Dispose();
+}
+
+// -------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::SetSubBankHandlers
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::SetSubBankHandlers (void)
+{
+ // Install base handlers.
+
+ EmRegs::SetSubBankHandlers();
+ // Now add standard/specialized handers for the defined registers.
+ this->SetHandler((ReadFunction)&EmRegsCFMemCard::Read,
+ (WriteFunction)&EmRegsCFMemCard::Write,
+ kMemoryStartCF,
+ kMemorySizeCF);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetRealAddress
+// ---------------------------------------------------------------------------
+uint8 * EmRegsCFMemCard::GetRealAddress (emuptr address)
+{
+ return (address-kMemoryStartCF) + Buffer;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetLong
+// ---------------------------------------------------------------------------
+uint32 EmRegsCFMemCard::GetLong (emuptr /*address*/)
+{
+ return (0);
+}
+
+#define INVALID_READ 0x3F
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetByte
+// ---------------------------------------------------------------------------
+uint32 EmRegsCFMemCard::GetByte(emuptr address)
+{
+ uint8 retVal = 0;
+ uint32 offset;
+
+ if (!fBusMgr->bEnabled)
+ return(INVALID_READ);
+
+ if ((fBusMgr->Width == kCFBusWidth8) && (!fBusMgr->bSwapped))
+ return(INVALID_READ);
+
+ offset = address-kMemoryStartCF;
+ if (offset < kMemoryOffsetCFConfig)
+ Tuple.ReadByte(offset-kMemoryOffsetCFTuple, &retVal);
+ else if (offset < kMemoryOffsetCFAta)
+ Config.ReadByte(offset-kMemoryOffsetCFConfig, &retVal);
+ else if (offset < kMemoryOffsetCFReset)
+ Ata.ReadByte(offset-kMemoryOffsetCFAta, &retVal);
+ else
+ CFReset.ReadByte(offset-kMemoryOffsetCFReset, &retVal);
+
+ return((uint32)retVal);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetWord
+// ---------------------------------------------------------------------------
+uint32 EmRegsCFMemCard::GetWord (emuptr address)
+{
+ _Word val;
+ uint32 retval;
+ int msb, lsb;
+ uint32 offset;
+
+ if (!fBusMgr->bEnabled)
+ return(INVALID_READ);
+ if ((fBusMgr->Width == kCFBusWidth8) && (!fBusMgr->bSwapped))
+ return(INVALID_READ);
+ offset = address-kMemoryStartCF;
+
+ if (offset < kMemoryOffsetCFConfig)
+ Tuple.ReadWord(offset-kMemoryOffsetCFTuple, &val);
+ else if (offset < kMemoryOffsetCFAta)
+ Config.ReadWord(offset-kMemoryOffsetCFConfig, &val);
+ else if (offset < kMemoryOffsetCFReset)
+ Ata.ReadWord(offset-kMemoryOffsetCFAta, &val);
+ else
+ CFReset.ReadWord(offset-kMemoryOffsetCFReset, &val);
+
+ if (fBusMgr->bSwapped)
+ {
+ msb = 0;
+ lsb = 1;
+ }
+ else
+ {
+ msb = 1;
+ lsb = 0;
+ }
+ retval = ((uint32)(val.Bytes[msb]) << 8) | (uint32)val.Bytes[lsb];
+ return (retval);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::SetLong
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::SetLong (emuptr /*address*/, uint32 /*value*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::SetWord
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::SetWord (emuptr address, uint32 val)
+{
+ _Word setVal;
+ int msb, lsb;
+
+ if (!fBusMgr->bEnabled)
+ return;
+
+ if (fBusMgr->bSwapped)
+ {
+ msb = 0;
+ lsb = 1;
+ }
+ else
+ {
+ msb = 1;
+ lsb = 0;
+ }
+ setVal.Bytes[msb] = (uint8)((val & 0xFF00) >> 8);
+ setVal.Bytes[lsb] = (uint8)(val & 0x00FF);
+
+ if (address < kMemoryStartCFConfig)
+ Tuple.WriteWord(address-kMemoryStartCFTuple, setVal);
+ else if (address < kMemoryStartCFAta)
+ Config.WriteWord(address-kMemoryStartCFConfig, setVal);
+ else if (address < kMemoryStartCFReset)
+ Ata.WriteWord(address-kMemoryStartCFAta, setVal);
+ else
+ CFReset.WriteWord(address-kMemoryStartCFReset, setVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::SetByte
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::SetByte (emuptr address, uint32 value)
+{
+ uint8 setVal = 0;
+
+ if (!fBusMgr->bEnabled)
+ return;
+
+ setVal = (uint8)value;
+ if (address < kMemoryStartCFConfig)
+ Tuple.WriteByte(address-kMemoryStartCFTuple, setVal);
+ else if (address < kMemoryStartCFAta)
+ Config.WriteByte(address-kMemoryStartCFConfig, setVal);
+ else if (address < kMemoryStartCFReset)
+ Ata.WriteByte(address-kMemoryStartCFAta, setVal);
+ else
+ CFReset.WriteByte(address-kMemoryStartCFReset, setVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetAddressStart
+// ---------------------------------------------------------------------------
+emuptr EmRegsCFMemCard::GetAddressStart (void)
+{
+ return (kMemoryStartCF);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::GetAddressRange
+// ---------------------------------------------------------------------------
+uint32 EmRegsCFMemCard::GetAddressRange (void)
+{
+ return kMemorySizeCF;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Read
+// ---------------------------------------------------------------------------
+uint32 EmRegsCFMemCard::Read(emuptr address, int size)
+{
+ switch(size)
+ {
+ case sizeof(uint8) :
+ return(GetByte(address));
+ case sizeof(uint16) :
+ return(GetWord(address));
+ }
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFMemCard::Write
+// ---------------------------------------------------------------------------
+void EmRegsCFMemCard::Write(emuptr address, int size, uint32 val)
+{
+ switch(size)
+ {
+ case sizeof(uint8) :
+ SetByte(address, val);
+ break;
+ case sizeof(uint16) :
+ SetWord(address, val);
+ break;
+ }
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGCF.h b/SrcShared/Hardware/TRG/EmTRGCF.h
new file mode 100644
index 0000000..a3eb969
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCF.h
@@ -0,0 +1,58 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGCF_h
+#define EmTRGCF_h
+
+#include "EmRegs.h"
+#include "EmTRGCFDefs.h"
+#include "EmTRGATA.h"
+#include "EmTRGCFMem.h"
+
+class EmRegsCFMemCard : public EmRegs
+{
+ public:
+ EmRegsCFMemCard (CFBusManager * fCFBusManager);
+ virtual ~EmRegsCFMemCard (void);
+
+ // EmRegs overrides
+ virtual void Initialize (void);
+ virtual void Reset (Bool hardwareReset);
+ virtual void Save (SessionFile&);
+ virtual void Load (SessionFile&);
+ virtual void Dispose (void);
+
+ uint8* GetRealAddress (emuptr address);
+ void SetSubBankHandlers (void);
+ emuptr GetAddressStart (void);
+ uint32 GetAddressRange (void);
+
+ uint32 GetLong (emuptr iAddress);
+ uint32 GetWord (emuptr iAddress);
+ uint32 GetByte (emuptr iAddress);
+ void SetLong (emuptr iAddress, uint32 iLongValue);
+ void SetWord (emuptr iAddress, uint32 iWordValue);
+ void SetByte (emuptr iAddress, uint32 iByteValue);
+private:
+ uint8 Buffer[kMemorySizeCF];
+ uint32 Read (emuptr address, int size);
+ void Write (emuptr address, int size, uint32 value);
+ EmDiskTypeID DiskTypeID;
+ EmRegsCFAta Ata;
+ EmRegsCFTuple Tuple;
+ EmRegsCFConfig Config;
+ EmRegsCFReset CFReset;
+ CFBusManager * fBusMgr;
+};
+
+#endif /* EmTRGCF_h */
diff --git a/SrcShared/Hardware/TRG/EmTRGCFDefs.h b/SrcShared/Hardware/TRG/EmTRGCFDefs.h
new file mode 100644
index 0000000..aa5274b
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCFDefs.h
@@ -0,0 +1,187 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGCFDefs_h
+#define EmTRGCFDefs_h
+
+#define IDE_REG_0_DATA 0x0
+#define IDE_REG_1_ERROR 0x1
+#define IDE_REG_1_FEATURES 0x1
+#define IDE_REG_2_SECTOR_CNT 0x2
+#define IDE_REG_3_LBA_7_0 0x3
+#define IDE_REG_4_LBA_15_8 0x4
+#define IDE_REG_5_LBA_23_16 0x5
+#define IDE_REG_6_DRV_HEAD 0x6
+#define IDE_REG_7_STATUS 0x7
+#define IDE_REG_7_COMMAND 0x7
+#define IDE_REG_8_DATA_EVEN 0x8
+#define IDE_REG_9_DATA_ODD 0x9
+#define IDE_REG_A_UNUSED 0xA
+#define IDE_REG_B_UNUSED 0xB
+#define IDE_REG_C_UNUSED 0xC
+#define IDE_REG_D_ERROR 0xD
+#define IDE_REG_E_ALT_STATUS 0xE
+#define IDE_REG_E_DEVICE_CONTROL 0xE
+#define IDE_REG_F_DRIVE_ADDR 0xF
+
+#define NUM_IDE_REGS (IDE_REG_F_DRIVE_ADDR + 1)
+
+#define SECTOR_SIZE 512
+
+#define IDE_CMD_03_REQUEST_SENSE 0x03
+#define IDE_CMD_10_RECALIBRATE 0x10
+#define IDE_CMD_11_RECALIBRATE 0x11
+#define IDE_CMD_12_RECALIBRATE 0x12
+#define IDE_CMD_13_RECALIBRATE 0x13
+#define IDE_CMD_14_RECALIBRATE 0x14
+#define IDE_CMD_15_RECALIBRATE 0x15
+#define IDE_CMD_16_RECALIBRATE 0x16
+#define IDE_CMD_17_RECALIBRATE 0x17
+#define IDE_CMD_18_RECALIBRATE 0x18
+#define IDE_CMD_19_RECALIBRATE 0x19
+#define IDE_CMD_1A_RECALIBRATE 0x1A
+#define IDE_CMD_1B_RECALIBRATE 0x1B
+#define IDE_CMD_1C_RECALIBRATE 0x1C
+#define IDE_CMD_1D_RECALIBRATE 0x1D
+#define IDE_CMD_1E_RECALIBRATE 0x1E
+#define IDE_CMD_1F_RECALIBRATE 0x1F
+#define IDE_CMD_20_READ_SECTORS 0x20
+#define IDE_CMD_21_READ_SECTORS 0x21
+#define IDE_CMD_22_READ_LONG_SECTOR 0x22
+#define IDE_CMD_23_READ_LONG_SECTOR 0x23
+#define IDE_CMD_30_WRITE_SECTORS 0x30
+#define IDE_CMD_31_WRITE_SECTORS 0x31
+#define IDE_CMD_32_WRITE_LONG_SECTOR 0x32
+#define IDE_CMD_33_WRITE_LONG_SECTOR 0x33
+#define IDE_CMD_38_WRITE_SECTORS_WO_ERASE 0x38
+#define IDE_CMD_3C_WRITE_VERIFY 0x3C
+#define IDE_CMD_40_READ_VERIFY_SECTORS 0x40
+#define IDE_CMD_41_READ_VERIFY_SECTORS 0x41
+#define IDE_CMD_50_FORMAT_TRACK 0x50
+#define IDE_CMD_70_SEEK 0x70
+#define IDE_CMD_71_SEEK 0x71
+#define IDE_CMD_72_SEEK 0x72
+#define IDE_CMD_73_SEEK 0x73
+#define IDE_CMD_74_SEEK 0x74
+#define IDE_CMD_75_SEEK 0x75
+#define IDE_CMD_76_SEEK 0x76
+#define IDE_CMD_77_SEEK 0x77
+#define IDE_CMD_78_SEEK 0x78
+#define IDE_CMD_79_SEEK 0x79
+#define IDE_CMD_7A_SEEK 0x7A
+#define IDE_CMD_7B_SEEK 0x7B
+#define IDE_CMD_7C_SEEK 0x7C
+#define IDE_CMD_7D_SEEK 0x7D
+#define IDE_CMD_7E_SEEK 0x7E
+#define IDE_CMD_7F_SEEK 0x7F
+#define IDE_CMD_87_TRANSLATE_SECTOR 0x87
+#define IDE_CMD_90_EXEC_DRIVE_DIAGNOSTIC 0x90
+#define IDE_CMD_91_INIT_DRIVE_PARAMS 0x91
+#define IDE_CMD_94_STANDBY_IMMEDIATE 0x94
+#define IDE_CMD_95_IDLE_IMMEDIATE 0x95
+#define IDE_CMD_96_STANDBY 0x96
+#define IDE_CMD_97_IDLE 0x97
+#define IDE_CMD_98_CHECK_POWER_MODE 0x98
+#define IDE_CMD_99_SET_SLEEP_MODE 0x99
+#define IDE_CMD_C0_ERASE_SECTOR 0xC0
+#define IDE_CMD_C4_READ_MULTIPLE 0xC4
+#define IDE_CMD_C6_SET_MULTIPLE_MODE 0xC6
+#define IDE_CMD_CD_WRITE_MULT_WO_ERASE 0xCD
+#define IDE_CMD_E0_STANDBY_IMMEDIATE 0xE0
+#define IDE_CMD_E1_IDLE_IMMEDIATE 0xE1
+#define IDE_CMD_E2_STANDBY 0xE2
+#define IDE_CMD_E3_IDLE 0xE3
+#define IDE_CMD_E4_READ_BUFFER 0xE4
+#define IDE_CMD_E5_CHECK_POWER_MODE 0xE5
+#define IDE_CMD_E6_SET_SLEEP_MODE 0xE6
+#define IDE_CMD_E8_WRITE_BUFFER 0xE8
+#define IDE_CMD_EC_IDENTIFY_DRIVE 0xEC
+#define IDE_CMD_EF_SET_FEATURES 0xEF
+#define IDE_CMD_F1_SECUR_SET_PASSWORD 0xF1
+#define IDE_CMD_F2_SECUR_UNLOCK 0xF2
+#define IDE_CMD_F3_SECUR_ERASE_PREPARE 0xF3
+#define IDE_CMD_F4_SECUR_ERASE_UNIT 0xF4
+#define IDE_CMD_F5_SECUR_FREEZE_LOCK 0xF5
+#define IDE_CMD_F6_SECUR_DISABLE_PASSWORD 0xF6
+
+#define IDE_STS_BUSY 0x80
+#define IDE_STS_RDY 0x40
+#define IDE_STS_DWF 0x20
+#define IDE_STS_DSC 0x10
+#define IDE_STS_DRQ 0x08
+#define IDE_STS_CORR 0x04
+#define IDE_STS_IDX 0x02
+#define IDE_STS_ERR 0x01
+
+#define IDE_ERR_10_SECTOR_NOT_FOUND 0x10
+#define IDE_ERR_04_ABORT 0x04
+#define IDE_ERR_01_GENERAL_ERROR 0x01
+#define IDE_ERR_00_NONE 0x00
+
+#define IDE_DIA_80_SLAVE_ERR 0x80
+#define IDE_DIA_05_CPU_ERR 0x05
+#define IDE_DIA_04_ECC_CIRCUITRY_ERR 0x04
+#define IDE_DIA_03_SECTOR_BUFFER_ERR 0x03
+#define IDE_DIA_02_FORMAT_ERR 0x02
+#define IDE_DIA_01_NO_ERROR 0x01
+
+typedef struct {
+ uint8 Bytes[SECTOR_SIZE];
+} EmSector;
+
+typedef uint8 DiskStatus;
+typedef uint32 LogicalBlockAddr;
+
+typedef enum {
+ EM_DISK_GENERIC_8MB
+} EmDiskTypeID;
+
+class SessionFile;
+
+typedef struct {
+ uint8 Bytes[2];
+} _Word;
+
+typedef enum {
+ CF_MEM_TUPLE,
+ CF_MEM_CONFIG,
+ CF_MEM_ATA,
+ CF_MEM_RESET
+} CFMemSection;
+
+
+const uint32 kMemoryStartCF = 0x18000000;
+
+const uint32 kMemoryOffsetCFTuple = 0;
+const uint32 kMemoryStartCFTuple = kMemoryStartCF + kMemoryOffsetCFTuple;
+const uint32 kMemorySizeCFTuple = 0x200;
+
+const uint32 kMemoryOffsetCFConfig = kMemoryOffsetCFTuple + kMemorySizeCFTuple;
+const uint32 kMemoryStartCFConfig = kMemoryStartCF + kMemoryOffsetCFConfig;
+const uint32 kMemorySizeCFConfig = 0xE00;
+
+const uint32 kMemoryOffsetCFAta = kMemoryOffsetCFConfig + kMemorySizeCFConfig;
+const uint32 kMemoryStartCFAta = kMemoryStartCF + kMemoryOffsetCFAta;
+const uint32 kMemorySizeCFAta = 0x1000;
+
+const uint32 kMemoryOffsetCFReset = kMemoryOffsetCFAta + kMemorySizeCFAta;
+const uint32 kMemoryStartCFReset = kMemoryStartCF + kMemoryOffsetCFReset;
+const uint32 kMemorySizeCFReset = 0x200;
+
+const uint32 kMemorySizeCF = kMemoryOffsetCFReset + kMemorySizeCFReset;
+
+#include "EmRegs.h"
+#include "EmHandEraCFBus.h"
+
+
+#endif // EmTRGCFDefs_h
diff --git a/SrcShared/Hardware/TRG/EmTRGCFIO.cpp b/SrcShared/Hardware/TRG/EmTRGCFIO.cpp
new file mode 100644
index 0000000..d1ec47e
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCFIO.cpp
@@ -0,0 +1,236 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGCFIO.h"
+
+
+//-------------------------------------------------------------------------
+// This file implements card I/O emulation by performing read and write
+// operations on a file on the PC. Note that this file doesn't know
+// anything about ATA registers ... it's more of a state machine for
+// a continuous series of reads and writes
+//
+// These functions will create a disk file on the PC ... if one doesn't
+// exist, it will create it in a formatted state.
+//
+// The code should work even if the disk file is replaced by an image
+// from a real card ... there is no additional info stored with the card
+// however, the tuple info won't agree with the card
+//---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::EmCFIO
+// ---------------------------------------------------------------------------
+EmCFIO::EmCFIO (void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::~EmCFIO
+// ---------------------------------------------------------------------------
+EmCFIO::~EmCFIO (void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::~EmCFIO
+// ---------------------------------------------------------------------------
+void EmCFIO::Reset(void)
+{
+ State.NumSectorsRequested = 0;
+ State.NumSectorsCompleted = 0;
+ State.SectorIndex = 0;
+ State.Status = DIO_SUCCESS;
+ State.Error = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::Initialize
+// ---------------------------------------------------------------------------
+void EmCFIO::Initialize (EmDiskTypeID ID)
+{
+ DiskTypeID = ID;
+ DiskIO.Initialize(ID, CF_DRIVE);
+ Reset();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::Dispose
+// ---------------------------------------------------------------------------
+void EmCFIO::Dispose (void)
+{
+ DiskIO.Dispose();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::ReadSector
+// ---------------------------------------------------------------------------
+DiskIOStatus EmCFIO::ReadSector(void)
+{
+ if ((DiskIO.ReadSector(State.Lba, (char *)State.Sector.Bytes)) != 0)
+ return DIO_ERROR;
+
+ return DIO_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::WriteSector
+// ---------------------------------------------------------------------------
+DiskIOStatus EmCFIO::WriteSector(void)
+{
+ if ((DiskIO.WriteSector(State.Lba, (char *)State.Sector.Bytes)) != 0)
+ return DIO_ERROR;
+
+ return DIO_SUCCESS;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::ReadNextDataByte
+// ---------------------------------------------------------------------------
+void EmCFIO::ReadNextDataByte(uint8 * val)
+{
+ // this first statement will likely not be called except when someone's
+ // dumping memory at our address range
+ if (State.NumSectorsCompleted >= State.NumSectorsRequested)
+ *val = 0;
+ else
+ {
+ *val = State.Sector.Bytes[State.SectorIndex++];
+ if (State.SectorIndex >= SECTOR_SIZE)
+ {
+ if (++State.NumSectorsCompleted < State.NumSectorsRequested)
+ {
+ State.Lba++;
+ State.SectorIndex = 0;
+ State.Status = ReadSector();
+ }
+ }
+ }
+ if (State.Status != DIO_SUCCESS)
+ State.Error = IDE_ERR_01_GENERAL_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::WriteNextDataByte
+// ---------------------------------------------------------------------------
+void EmCFIO::WriteNextDataByte(uint8 val)
+{
+ State.Status = DIO_SUCCESS;
+ if (State.NumSectorsCompleted < State.NumSectorsRequested)
+ {
+ State.Sector.Bytes[State.SectorIndex++] = val;
+ if (State.SectorIndex >= SECTOR_SIZE)
+ {
+ if (WriteSector() == DIO_ERROR)
+ State.Status = DIO_ERROR;
+ else if (++State.NumSectorsCompleted < State.NumSectorsRequested)
+ {
+ State.Status = DIO_SUCCESS;
+ State.Lba++;
+ State.SectorIndex = 0;
+ }
+ }
+ }
+ if (State.Status != DIO_SUCCESS)
+ State.Error = IDE_ERR_01_GENERAL_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::GetSectorCount
+// ---------------------------------------------------------------------------
+uint32 EmCFIO::GetSectorCount(void)
+{
+ return State.NumSectorsCompleted;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::StartDriveID
+// ---------------------------------------------------------------------------
+void EmCFIO::StartDriveID(void)
+{
+ CurrDisk.GetDriveID(DiskTypeID,
+ &State.Sector);
+ State.NumSectorsRequested = 1;
+ State.NumSectorsCompleted = 0;
+ State.SectorIndex = 0;
+ State.Status = DIO_SUCCESS;
+ State.Error = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::StartRead
+// ---------------------------------------------------------------------------
+void EmCFIO::StartRead(DiskIOParams * params)
+{
+ State.Lba = params->Lba;
+ State.NumSectorsRequested = params->SectorCnt;
+ State.NumSectorsCompleted = 0;
+ State.SectorIndex = 0;
+ State.Error = 0;
+ State.Status = ReadSector();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::StartWrite
+// ---------------------------------------------------------------------------
+void EmCFIO::StartWrite(DiskIOParams * params)
+{
+ State.Lba = params->Lba;
+ State.NumSectorsRequested = params->SectorCnt;
+ State.NumSectorsCompleted = 0;
+ State.SectorIndex = 0;
+ State.Status = DIO_SUCCESS;
+ State.Error = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::GetStatus
+// ---------------------------------------------------------------------------
+void EmCFIO::GetStatus(DiskIOStatus * status,
+ DiskDataStatus * dataStatus)
+{
+ *status = State.Status;
+ if (State.NumSectorsCompleted == State.NumSectorsRequested)
+ *dataStatus = DIO_DATA_COMPLETE;
+ else
+ *dataStatus = DIO_MORE_DATA;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCFIO::GetError
+// ---------------------------------------------------------------------------
+DiskIOError EmCFIO::GetError(void)
+{
+ if (State.Status == DIO_SUCCESS)
+ return(0);
+ else
+ // at this point, all errors are pretty much the same ... we can't
+ // create our emulation file ... we probably will need to include
+ // some more refined error codes at some point
+ return(State.Error);
+}
+
+
+void EmCFIO::SetError(DiskIOError error)
+{
+ State.Status = DIO_ERROR;
+ State.Error = error;
+}
+
+void EmCFIO::ClearError(void)
+{
+ State.Status = DIO_SUCCESS;
+ State.Error = 0;
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGCFIO.h b/SrcShared/Hardware/TRG/EmTRGCFIO.h
new file mode 100644
index 0000000..5ce0974
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCFIO.h
@@ -0,0 +1,90 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGCFIO_h
+#define EmTRGCFIO_h
+
+#include "EmTRGCFDefs.h"
+#include "EmTRGDiskType.h"
+#include "EmTRGDiskIO.h"
+
+#include <stdio.h> // FILE
+
+#define DISKFILE_NAME "trgdrv.dat"
+
+typedef struct {
+ uint32 DriveNum;
+ LogicalBlockAddr Lba;
+ uint32 SectorCnt;
+} DiskIOParams;
+
+typedef enum {
+ DIO_SUCCESS = 0,
+ DIO_ERROR = 1
+} DiskIOStatus;
+
+typedef enum {
+ DIO_DATA_COMPLETE = 0,
+ DIO_MORE_DATA = 1
+} DiskDataStatus;
+
+//typedef enum {
+// DIO_ERR_NONE = 0,
+// DIO_ERR_GENERIC = 1
+//} DiskIOError;
+typedef uint8 DiskIOError;
+
+typedef struct {
+ LogicalBlockAddr Lba;
+ uint32 NumSectorsRequested;
+ uint32 NumSectorsCompleted;
+ EmSector Sector;
+ int SectorIndex;
+ DiskIOStatus Status;
+ DiskIOError Error;
+} DiskIOState;
+
+class EmCFIO
+{
+public:
+ EmCFIO (void);
+ virtual ~EmCFIO (void);
+
+ // EmRegs overrides
+ void Initialize(EmDiskTypeID DiskTypeID);
+ void Dispose(void);
+ void Reset(void);
+ void StartDriveID(void);
+ void ReadNextDataByte(uint8 * val);
+ void WriteNextDataByte(uint8 val);
+ uint32 GetSectorCount(void);
+ void StartRead(DiskIOParams * params);
+ void StartWrite(DiskIOParams * params);
+ void GetStatus(DiskIOStatus * status,
+ DiskDataStatus * dataStatus);
+ DiskIOError GetError(void);
+ void SetError(DiskIOError error);
+ void ClearError(void);
+
+private:
+ EmDiskTypeID DiskTypeID;
+ EmCurrDiskType CurrDisk;
+ DiskIOStatus WriteSector(void);
+ DiskIOStatus ReadSector(void);
+ void CloseFile(void);
+ DiskIOState State;
+
+ EmTRGDiskIO DiskIO;
+};
+
+#endif /* EmTRGCFIO_h */
diff --git a/SrcShared/Hardware/TRG/EmTRGCFMem.cpp b/SrcShared/Hardware/TRG/EmTRGCFMem.cpp
new file mode 100644
index 0000000..3d9a169
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCFMem.cpp
@@ -0,0 +1,349 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGCFMem.h"
+
+// ------------------------------------------------------------------------
+// This file emulates the Registers on the CF Memory Card aside from the
+// ATA registers (they are handled in a different source file).
+//
+// Address Description Class
+// --------------------- -------------------- ---------------------
+// 0x18000000-0x180001FF Card Tuple EmRegsCFTuple
+// 0x18000200-0x18000FFF Configuration Regs EmRegsCFConfig
+// 0x18001000-0x18001FFF ATA Registers
+// 0x18002000 CF Reset EmRegsCFReset
+// ------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Configuration Option Register (Base + 00h in Attribute Memory)
+//
+// The Configuration Option Register is used to configure the cards interface,
+// address decoding and interrupt and to issue a soft reset to the CompactFlash
+// Storage Card or CF+ Card.
+//
+// D7 D6 D5 D4 D3 D2 D1 D0
+// R/W SRESET LevlREQ Conf5 Conf4 Conf3 Conf2 Conf1 Conf0
+//
+// SRESET - Soft Reset: setting this bit to one (1), waiting the minimum reset
+// width time and returning to zero (0) places the CompactFlash Storage Card
+// or CF+ Card in the Reset state. Setting this bit to one (1) is equivalent
+// to assertion of the +RESET signal except that the SRESET bit is not cleared.
+// Returning this bit to zero (0) leaves the CompactFlash Storage
+// Card or CF+ Card in the same un-configured, Reset state as following
+// power-up and hardware reset. This bit is set to zero (0) by power-up and
+// hardware reset. For CompactFlash Storage Cards, using the PCMCIA Soft
+// Reset is considered a hard Reset by the ATA Commands. Contrast with Soft
+// Reset in the Device Control Register.
+//
+// LevlREQ: this bit is set to one (1) when Level Mode Interrupt is selected,
+// and zero (0) when Pulse Mode is selected. Set to zero (0) by Reset.
+//
+// Conf5 - Conf0 - Configuration Index: set to zero (0) by reset. It is used
+// to select operation mode of the CompactFlash Storage Card or CF+ Card
+// as shown below.
+/// Note: Conf5 and Conf4 are reserved for CompactFlash Storage cards and
+// must be written as zero (0) These bits are vendor defined for CF+ Cards.
+//
+// CompactFlash Storage Card Configurations
+// Conf5 Conf4 Conf3 Conf2 Conf1 Conf0 Disk Card Mode
+// 0 0 0 0 0 0 Memory Mapped
+// 0 0 0 0 0 1 I/O Mapped, Any 16 byte system
+// decoded boundary
+// 0 0 0 0 1 0 I/O Mapped, 1F0h-1F7h/3F6h-3F7h
+// 0 0 0 0 1 1 I/O Mapped, 170h-177h/376h-377h
+//
+// CF+ Card Configurations
+// Conf5 Conf4 Conf3 Conf2 Conf1 Conf0 CF+ Card Mode
+// 0 0 0 0 0 0 Memory Mapped, I/O cycles are ignored
+// X X X X X X Any non-zero value, vendor defined
+//
+// On Multiple Function CF+ Cards, bits in this field enable the following
+// functionality:
+//
+// Bit 0 Enable Function - If this bit is reset to zero (0), the function is
+// disabled. If this bit is set to one (1), the function is enabled.
+//
+// Bit 1 Enable Base and Limit Registers - If this bit is reset to zero (0)
+// and Bit 0 is set to one (1), all I/O addresses on the host system are
+// passed to the function. If this is set to one (1) and Bit 0 is set to one
+// (1), only I/O addresses that are qualified by the Base and Limit registers
+// are passed to the function. If Bit 0 is reset to zero (0), this bit is
+// undefined.
+//
+// Bit 2 Enable IREQ# Routing - If this bit is reset to zero (0) and Bit 0
+// is set to one (1), this function shall not generate interrupt requests
+// on the CF+ Card's IREQ# line. If this is set to one (1) and
+// Bit 0 is set to one (1), this function shall generate interrupt requests
+// on the CF+ Card's IREQ# line. If Bit 0 is reset to zero (0), this bit is
+// undefined.
+//
+// Bit 3..5 Reserved for vendor implementation.
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Card Configuration and Status Register (Base + 02h in Attribute Memory)
+// The Card Configuration and Status Register contains information about the
+// Card's condition.
+//
+// Operation D7 D6 D5 D4 D3 D2 D1 D0
+// ---------- ------- ------ ------- ------- ------- ------ ------ ------
+// Read Changed SigChg IOis8 -XE Audio PwrDwn Int 0
+// Write 0 SigChg IOis8 -XE Audio PwrDwn 0 0
+//
+// Changed: indicates that one or both of the Pin Replacement register CRdy,
+// or CWProt bits are set to one (1). When the Changed bit is set,
+// -STSCHG Pin 46 is held low if the SigChg bit is a One (1) and the
+// CompactFlash Storage Card or CF+ Card is configured for the I/O interface.
+//
+// SigChg: this bit is set and reset by the host to enable and disable a
+// state-change signal from the Status Register, the Changed bit control
+// pin 46 the Changed Status signal. If no state change signal is desired,
+// this bit should be set to zero (0) and pin 46 (-STSCHG) signal will
+// be held high while the CompactFlash Storage Card or CF+ Card is configured
+// for I/O.
+//
+// IOis8: the host sets this bit to a one (1) if the CompactFlash Storage
+// Card or CF+ Card is to be configured in an 8 bit I/O Mode. The
+// CompactFlash Storage Card is always configured for both 8- and 16-bit I/O,
+// so this bit is ignored. Some CF+ cards can be configured for either 8-
+// bit I/O mode or 16-bit I/O mode, so CF+ cards may respond to this bit.
+//
+// -XE: this bit is set and reset by the host to disable and enable Power
+// Level 1 commands in CF+ cards. If the value is 0, Power Level 1 commands
+// are enabled; if it is 1, Power Level 1 commands are disabled. Default
+// value at power on or after reset is 0. The host may read the value of
+// this bit to determine whether Power Level 1 commands are currently enabled.
+// For CompactFlash Storage cards (which must not support Power Level 1),
+// this bit has value 0 and is not writeable.
+//
+// Audio: this bit is set and reset by the host to enable and disable
+// audio information on SPKR# when the CF+ card is configured. This bit
+// should always be zero for CompactFlash Storage cards.
+//
+// PwrDwn: this bit indicates whether the host requests the CompactFlash
+// Storage Card or CF+ Card to be in the power saving or active mode. When
+// the bit is one (1), the CompactFlash Storage Card or CF+ Card enters a
+// power down mode. When zero (0), the host is requesting the CompactFlash
+// Storage Card or CF+ Card to enter the active mode. The PCMCIA Rdy/-Bsy
+// value becomes BUSY when this bit is changed. Rdy/-Bsy will not become
+// Ready until the power state requested has been entered. The CompactFlash
+// Storage Card automatically powers down when it is idle and powers back up
+// when it receives a command.
+//
+// Int: this bit represents the internal state of the interrupt request.
+// This value is available whether or not I/O interface has been configured.
+// This signal remains true until the condition which caused the interrupt
+// request has been serviced. If interrupts are disabled by the -IEN bit in
+// the Device Control Register, this bit is a zero (0).
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Pin Replacement Register (Base + 04h in Attribute Memory)
+//
+// Operation D7 D6 D5 D4 D3 D2 D1 D0
+// --------- ------ ------ --------- ------ ------ ------ -------- ------
+// Read 0 0 CRdy/-Bsy CWProt 1 1 Rdy/-Bsy WProt
+// Write 0 0 CRdy/-Bsy CWProt 0 0 MRdy/-Bsy MWProt
+//
+// CRdy/-Bsy: this bit is set to one (1) when the bit RRdy/-Bsy changes state.
+// This bit can also be written by the host.
+//
+// CWProt: this bit is set to one (1) when the RWprot changes state.
+// This bit may also be written by the host.
+//
+// Rdy/-Bsy: this bit is used to determine the internal state of the Rdy/-Bsy
+// signal. This bit may be used to determine the state of the Ready/-Busy as
+// this pin has been reallocated for use as Interrupt Request on an I/O card.
+// When written, this bit acts as a mask for writing the corresponding bit
+// CRdy/-Bsy.
+//
+// Wprot: this bit is always zero (0) since the CompactFlash Storage Card or
+// CF+ Card does not have a Write Protect switch. When written, this bit acts
+// as a mask for writing the corresponding bit CWProt.
+//
+// MRdy/-Bsy: this bit acts as a mask for writing the corresponding bit
+// CRdy/-Bsy.
+//
+// MWProt: this bit when written acts as a mask for writing the corresponding
+// bit CWProt.
+//
+// Pin Replacement Changed Bit/Mask Bit Values
+//
+// Initial Value | Written by Host | Final | Comments
+// of (C) Status | C-Bit M-Bit | C-Bit |
+// ------------- | --------------- | ----- | ----------
+// 0 | X 0 | 0 | Unchanged
+// 1 | X 0 | 1 | Unchanged
+// X | 0 1 | 0 | Cleared by Host
+// X | 1 1 | 1 | Set by Host
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Socket and Copy Register (Base + 06h in Attribute Memory)
+//
+// This register contains additional configuration information. This register
+// is always written by the system before writing the card's Configuration
+// Index Register. This register is not required for CF+ Cards.
+//
+// Operation D7 D6 D5 D4 D3 D2 D1 D0
+// --------- ------ ------ ------ ------ ------ ------ ------ ------
+// Read Resrvd 0 0 Drive# 0 0 0 0
+// Write 0 0 0 Drive# X X X X
+//
+// Reserved: this bit is reserved for future standardization. This bit must
+// be set to zero (0) by the software when the register is written.
+//
+// Drive #: this bit indicates the drive number of the card for twin card
+// configuration.
+//
+// X: the socket number is ignored by the CompactFlash Storage Card.
+//----------------------------------------------------------------------------
+static uint8 CFRegMem[] = {
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x2E, 0x00, 0x00,
+};
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::InRange
+// ---------------------------------------------------------------------------
+Boolean EmRegsCFConfig::InRange(uint32 offset)
+{
+ if (offset < sizeof(CFRegMem))
+ return(true);
+ else
+ return(false);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::Initialize
+// ---------------------------------------------------------------------------
+void EmRegsCFConfig::Initialize(EmDiskTypeID /*ID*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::ReadByte
+// ---------------------------------------------------------------------------
+void EmRegsCFConfig::ReadByte(uint32 offset, uint8 * val)
+{
+ if (InRange(offset))
+ *val = CFRegMem[offset];
+ else
+ *val = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::WriteByte
+// ---------------------------------------------------------------------------
+void EmRegsCFConfig::WriteByte(uint32 /*offset*/, uint8 /*val*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::ReadWord
+// ---------------------------------------------------------------------------
+void EmRegsCFConfig::ReadWord(uint32 offset, _Word * val)
+{
+ ReadByte(offset, &val->Bytes[0]);
+ ReadByte(offset+1, &val->Bytes[1]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFConfig::WriteWord
+// ---------------------------------------------------------------------------
+void EmRegsCFConfig::WriteWord(uint32 /*offset*/, _Word /*val*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFReset::Initialize
+// ---------------------------------------------------------------------------
+void EmRegsCFReset::Initialize(EmDiskTypeID /*ID*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFReset::ReadByte
+// ---------------------------------------------------------------------------
+void EmRegsCFReset::ReadByte(uint32 /*offset*/, uint8 * val)
+{
+ *val = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFReset::WriteByte
+// ---------------------------------------------------------------------------
+void EmRegsCFReset::WriteByte(uint32 /*offset*/, uint8 /*val*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFReset::ReadWord
+// ---------------------------------------------------------------------------
+void EmRegsCFReset::ReadWord(uint32 /*offset*/, _Word * val)
+{
+ val->Bytes[0] = val->Bytes[1] = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFReset::WriteWord
+// ---------------------------------------------------------------------------
+void EmRegsCFReset::WriteWord(uint32 /*offset*/, _Word /*val*/)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFTuple::Initialize
+// ---------------------------------------------------------------------------
+void EmRegsCFTuple::Initialize(EmDiskTypeID DiskTypeID)
+{
+ CurrDisk.GetTuple(DiskTypeID,
+ &tuple);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFTuple::ReadByte
+// ---------------------------------------------------------------------------
+void EmRegsCFTuple::ReadByte(uint32 offset, uint8 * val)
+{
+ if (offset < sizeof(EmSector))
+ *val = tuple.Bytes[offset];
+ else
+ *val = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFTuple::WriteByte
+// ---------------------------------------------------------------------------
+void EmRegsCFTuple::WriteByte(uint32 /*offset*/, uint8 /*val*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFTuple::ReadWord
+// ---------------------------------------------------------------------------
+void EmRegsCFTuple::ReadWord(uint32 offset, _Word * val)
+{
+ ReadByte(offset, &val->Bytes[0]);
+ ReadByte(offset+1, &val->Bytes[1]);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmRegsCFTuple::WriteWord
+// ---------------------------------------------------------------------------
+void EmRegsCFTuple::WriteWord(uint32 /*offset*/, _Word /*val*/)
+{
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGCFMem.h b/SrcShared/Hardware/TRG/EmTRGCFMem.h
new file mode 100644
index 0000000..699daf1
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGCFMem.h
@@ -0,0 +1,66 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+/****************************************************************************************
+** File: Bank_CF_Config.h
+** Date: 6/14/00
+** Project: POSE
+** Author: Dan Kolz
+** Notes: This class is an emulation of the config area on a CF card.
+** It takes its information from a hardcoded array in the source code.
+****************************************************************************************/
+
+#ifndef EmTRGCFMem_h
+#define EmTRGCFMem_h
+
+#include "EmRegs.h"
+#include "EmTRGCFDefs.h"
+#include "EmTRGDiskType.h"
+
+class EmRegsCFConfig
+{
+ public:
+ void Initialize(EmDiskTypeID ID);
+ void ReadByte(uint32 offset, uint8 * val);
+ void WriteByte(uint32 offset, uint8 val);
+ void ReadWord(uint32 offset, _Word * val);
+ void WriteWord(uint32 offset, _Word val);
+ private:
+ Boolean InRange(uint32 offset);
+};
+
+class EmRegsCFReset
+{
+ public:
+ void Initialize(EmDiskTypeID ID);
+ void ReadByte(uint32 offset, uint8 * val);
+ void WriteByte(uint32 offset, uint8 val);
+ void ReadWord(uint32 offset, _Word * val);
+ void WriteWord(uint32 offset, _Word val);
+ private:
+};
+
+class EmRegsCFTuple
+{
+ public:
+ void Initialize(EmDiskTypeID DiskTypeID);
+ void ReadByte(uint32 offset, uint8 * val);
+ void WriteByte(uint32 offset, uint8 val);
+ void ReadWord(uint32 offset, _Word * val);
+ void WriteWord(uint32 offset, _Word val);
+ private:
+ EmCurrDiskType CurrDisk;
+ EmSector tuple;
+};
+
+#endif // EmTRGCFMem_h
diff --git a/SrcShared/Hardware/TRG/EmTRGDiskIO.cpp b/SrcShared/Hardware/TRG/EmTRGDiskIO.cpp
new file mode 100644
index 0000000..9b43582
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGDiskIO.cpp
@@ -0,0 +1,174 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGDiskIO.h"
+
+/************************************************************************
+ * This class handles the generic low level disk access.
+ ************************************************************************/
+#include <stdio.h>
+
+#include "EmCommon.h"
+#include "EmTRGDiskIO.h"
+
+#define CFFILE_NAME "trgdrv.dat"
+#define SDFILE_NAME "trgdrvsd.dat"
+
+#define SECTOR_SIZE 512
+
+
+EmTRGDiskIO::EmTRGDiskIO()
+{
+ m_driveNo = UNKNOWN_DRIVE;
+}
+
+
+EmTRGDiskIO::~EmTRGDiskIO()
+{
+}
+
+
+char * EmTRGDiskIO::GetFilePath(int driveNo)
+{
+#if PLATFORM_WINDOWS
+ static char tmp[MAX_PATH];
+
+ if (driveNo == CF_DRIVE)
+ _snprintf(tmp, sizeof(tmp), "%s\\%s", getenv("WINDIR"), CFFILE_NAME);
+ else
+ _snprintf(tmp, sizeof(tmp), "%s\\%s", getenv("WINDIR"), SDFILE_NAME);
+ return(tmp);
+#else
+ if (driveNo == CF_DRIVE)
+ return CFFILE_NAME;
+ else
+ return SDFILE_NAME;
+#endif
+}
+
+int EmTRGDiskIO::Format(void)
+{
+ EmSector *buffer;
+ uint32 num, lba;
+ FILE *fp;
+
+ fp = fopen(GetFilePath(m_driveNo), "wb");
+ if (fp == NULL)
+ return -1;
+
+ buffer = new EmSector;
+ num = m_currDisk.GetNumSectors(m_diskTypeID);
+ for (lba=0; lba<num; lba++)
+ {
+ m_currDisk.GetSector(m_diskTypeID, lba, buffer);
+
+ // The most probable error condition is
+ // attempting to write to a full drive ... it could also
+ // be write-protected, or on a disconnected network drive.
+ if (fwrite(buffer, SECTOR_SIZE, 1, fp) == 0)
+ {
+ delete buffer;
+ fclose(fp);
+ return -1;
+ }
+ }
+ delete buffer;
+
+ return 0;
+}
+
+int EmTRGDiskIO::Read(uint32 sectorNum, void *buffer)
+{
+ FILE *fp;
+
+ if ((fp = fopen(GetFilePath(m_driveNo), "rb")) == NULL)
+ return -1;
+
+ if (fseek(fp, sectorNum * SECTOR_SIZE, SEEK_SET) == -1)
+ {
+ fclose(fp);
+ return -1;
+ }
+
+ if (fread(buffer, SECTOR_SIZE, 1, fp) != 1)
+ {
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+int EmTRGDiskIO::Write(uint32 sectorNum, void *buffer)
+{
+ FILE *fp;
+
+ if ((fp = fopen(GetFilePath(m_driveNo), "r+b")) == NULL)
+ return -1;
+
+ if (fseek(fp, sectorNum * SECTOR_SIZE, SEEK_SET) == -1)
+ {
+ fclose(fp);
+ return -1;
+ }
+
+ if (fwrite(buffer, SECTOR_SIZE, 1, fp) != 1)
+ {
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+
+void EmTRGDiskIO::Initialize(EmDiskTypeID DiskTypeID, int driveNo)
+{
+ m_diskTypeID = DiskTypeID;
+ m_driveNo = driveNo;
+}
+
+void EmTRGDiskIO::Dispose(void)
+{
+}
+
+int EmTRGDiskIO::ReadSector(uint32 sectorNum, void *buffer)
+{
+ int retval;
+
+ if ((retval = Read(sectorNum, buffer)) != 0)
+ {
+ Format();
+ retval = Read(sectorNum, buffer);
+ }
+
+ return retval;
+}
+
+
+
+int EmTRGDiskIO::WriteSector(uint32 sectorNum, void *buffer)
+{
+ int retval;
+
+ if ((retval = Write(sectorNum, buffer)) != 0)
+ {
+ Format();
+ retval = Write(sectorNum, buffer);
+ }
+
+ return retval;
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGDiskIO.h b/SrcShared/Hardware/TRG/EmTRGDiskIO.h
new file mode 100644
index 0000000..74bca58
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGDiskIO.h
@@ -0,0 +1,53 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGDiskIO_h
+#define EmTRGDiskIO_h
+
+/************************************************************************
+ * This class handles the generic low level disk access.
+ ************************************************************************/
+#include "EmTRGCFDefs.h"
+#include "EmTRGDiskType.h"
+
+#define UNKNOWN_DRIVE 0
+#define CF_DRIVE 1
+#define SD_DRIVE 2
+
+#define SECTOR_SIZE 512
+
+class EmTRGDiskIO
+{
+private:
+ int m_driveNo;
+ EmDiskTypeID m_diskTypeID;
+ EmCurrDiskType m_currDisk;
+
+ int Format(void);
+ char *GetFilePath(int driveNo);
+
+ int Read(uint32 sectorNum, void *buffer);
+ int Write(uint32 sectorNum, void *buffer);
+
+public:
+ EmTRGDiskIO(void);
+ ~EmTRGDiskIO();
+
+ void Initialize(EmDiskTypeID DiskTypeID, int driveNo);
+ void Dispose(void);
+
+ int ReadSector(uint32 sectorNum, void *buffer);
+ int WriteSector(uint32 sectorNum, void *buffer);
+};
+
+#endif /* EmTRGDiskIO_h */
diff --git a/SrcShared/Hardware/TRG/EmTRGDiskType.cpp b/SrcShared/Hardware/TRG/EmTRGDiskType.cpp
new file mode 100644
index 0000000..571571f
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGDiskType.cpp
@@ -0,0 +1,511 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGDiskType.h"
+
+
+//---------------------------------------------------------------------------
+// This file is used to determine what sort of memory card is being
+// emulated ... so far, the only supported type is a generic 8MB card.
+// Card emulation requires having a copy of the Tuple, Drive ID, and
+// format sectors for a particular card
+//---------------------------------------------------------------------------
+
+#define B(x) x, 0
+
+static const EmSector _8MBTuple = {{
+ B(0x01), B(0x04), B(0xdf), B(0x4a), B(0x01), B(0xff), B(0x1c), B(0x04),
+ B(0x02), B(0xd9), B(0x01), B(0xff), B(0x18), B(0x02), B(0xdf), B(0x01),
+ B(0x20), B(0x04), B(0x07), B(0x00), B(0x00), B(0x00), B(0x15), B(0x15),
+ B(0x04), B(0x01), B(0x55), B(0x4e), B(0x49), B(0x54), B(0x59), B(0x20),
+ B(0x44), B(0x49), B(0x47), B(0x49), B(0x54), B(0x41), B(0x4c), B(0x00),
+ B(0x33), B(0x2e), B(0x30), B(0x00), B(0xff), B(0x21), B(0x02), B(0x04),
+ B(0x01), B(0x22), B(0x02), B(0x01), B(0x01), B(0x22), B(0x03), B(0x02),
+ B(0x0c), B(0x0f), B(0x1a), B(0x05), B(0x01), B(0x03), B(0x00), B(0x02),
+ B(0x0f), B(0x1b), B(0x08), B(0xc0), B(0xc0), B(0xa1), B(0x01), B(0x55),
+ B(0x08), B(0x00), B(0x20), B(0x1b), B(0x06), B(0x00), B(0x01), B(0x21),
+ B(0xb5), B(0x1e), B(0x4d), B(0x1b), B(0x0a), B(0xc1), B(0x41), B(0x99),
+ B(0x01), B(0x55), B(0x64), B(0xf0), B(0xff), B(0xff), B(0x20), B(0x1b),
+ B(0x06), B(0x01), B(0x01), B(0x21), B(0xb5), B(0x1e), B(0x4d), B(0x1b),
+ B(0x0f), B(0xc2), B(0x41), B(0x99), B(0x01), B(0x55), B(0xea), B(0x61),
+ B(0xf0), B(0x01), B(0x07), B(0xf6), B(0x03), B(0x01), B(0xee), B(0x20),
+ B(0x1b), B(0x06), B(0x02), B(0x01), B(0x21), B(0xb5), B(0x1e), B(0x4d),
+ B(0x1b), B(0x0f), B(0xc3), B(0x41), B(0x99), B(0x01), B(0x55), B(0xea),
+ B(0x61), B(0x70), B(0x01), B(0x07), B(0x76), B(0x03), B(0x01), B(0xee),
+ B(0x20), B(0x1b), B(0x06), B(0x03), B(0x01), B(0x21), B(0xb5), B(0x1e),
+ B(0x4d), B(0x14), B(0x00), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+ B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff), B(0xff),
+}};
+
+static const uint8 _8MBSD_CID[] = {
+ 0x00, 0x00, 0x02, 0x53, 0x44, 0x4D, 0x42, 0x2D,
+ 0x38, 0x00, 0x20, 0x06, 0x3A, 0x12, 0x32, 0x35
+};
+
+static const uint8 _8MBSD_CSD[] = {
+ 0x44, 0x26, 0x00, 0x2A, 0x1F, 0xF9, 0x81, 0xE9,
+ 0xE4, 0xB4, 0x83, 0xFF, 0x92, 0x40, 0x40, 0x81
+};
+
+#define W(x, y) x, y
+
+static const EmSector _8MBDriveID =
+{{
+ W(0x8A, 0x84), W(0xF6, 0x00), W(0x00, 0x00), W(0x02, 0x00), W(0x00, 0x00), W(0x00, 0x02), W(0x20, 0x00), W(0x00, 0x00),
+ W(0x80, 0x3D), W(0x00, 0x00), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20),
+ W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x02, 0x00), W(0x02, 0x00), W(0x04, 0x00), W(0x65, 0x52),
+ W(0x20, 0x76), W(0x2E, 0x31), W(0x32, 0x30), W(0x69, 0x48), W(0x61, 0x74), W(0x68, 0x63), W(0x20, 0x69), W(0x56, 0x43),
+ W(0x36, 0x20), W(0x31, 0x2E), W(0x32, 0x2E), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20),
+ W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x20, 0x20), W(0x01, 0x00),
+ W(0x00, 0x00), W(0x00, 0x02), W(0x00, 0x00), W(0x00, 0x01), W(0x00, 0x00), W(0x01, 0x00), W(0xF6, 0x00), W(0x02, 0x00),
+ W(0x20, 0x00), W(0x80, 0x3D), W(0x00, 0x00), W(0x00, 0x01), W(0x80, 0x3D), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x20, 0x00), W(0x80, 0x3D), W(0x00, 0x00), W(0x00, 0x01), W(0x80, 0x3D), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00),
+ W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00), W(0x00, 0x00)
+}};
+
+static const EmSector _8MBMasterBootRecord =
+{{
+0xFA, 0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0x8B, 0xF4, 0x50, 0x07, 0x50, 0x1F, 0xFB, 0xFC,
+0xBF, 0x00, 0x06, 0xB9, 0x00, 0x01, 0xF2, 0xA5, 0xEA, 0x1D, 0x06, 0x00, 0x00, 0xBE, 0xBE, 0x07,
+0xB3, 0x04, 0x80, 0x3C, 0x80, 0x74, 0x0E, 0x80, 0x3C, 0x00, 0x75, 0x1C, 0x83, 0xC6, 0x10, 0xFE,
+0xCB, 0x75, 0xEF, 0xCD, 0x18, 0x8B, 0x14, 0x8B, 0x4C, 0x02, 0x8B, 0xEE, 0x83, 0xC6, 0x10, 0xFE,
+0xCB, 0x74, 0x1A, 0x80, 0x3C, 0x00, 0x74, 0xF4, 0xBE, 0x8B, 0x06, 0xAC, 0x3C, 0x00, 0x74, 0x0B,
+0x56, 0xBB, 0x07, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0x5E, 0xEB, 0xF0, 0xEB, 0xFE, 0xBF, 0x05, 0x00,
+0x4F, 0x75, 0xED, 0xBE, 0xA3, 0x06, 0xEB, 0xD3, 0xBE, 0xC2, 0x06, 0xBF, 0xFE, 0x7D, 0x81, 0x3D,
+0x55, 0xAA, 0x75, 0xC7, 0x8B, 0xF5, 0xEA, 0x00, 0x7C, 0x00, 0x00, 0x49, 0x6E, 0x76, 0x61, 0x6C,
+0x69, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x74, 0x61, 0x62,
+0x6C, 0x65, 0x00, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x6C, 0x6F, 0x61, 0x64, 0x69, 0x6E, 0x67,
+0x20, 0x6F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+0x6D, 0x00, 0x4D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x6F, 0x70, 0x65, 0x72, 0x61, 0x74,
+0x69, 0x6E, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x89, 0x70, 0x61, 0x72, 0x74, 0x5F,
+0x62, 0x6F, 0x6F, 0x74, 0x00, 0x00, 0xEB, 0x3C, 0x90, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01,
+0x01, 0x00, 0x01, 0x01, 0x20, 0xF4, 0x20, 0x00, 0x00, 0x00, 0x20, 0x3D, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
+}};
+
+static const EmSector _8MBBootRecord =
+{{
+0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x08, 0x01, 0x00,
+0x02, 0x00, 0x02, 0x20, 0x3D, 0xF8, 0x06, 0x00, 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x0D, 0x0B, 0x00, 0x00, 0x53, 0x41, 0x4E, 0x56, 0x4F,
+0x4C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x8E,
+0xC0, 0x8E, 0xD8, 0xFB, 0xFC, 0xBE, 0x6A, 0x00, 0x81, 0xC6, 0x00, 0x7C, 0xAC, 0x0A, 0xC0, 0x74,
+0x0A, 0xB4, 0x0E, 0xB7, 0x00, 0xB3, 0x07, 0xCD, 0x10, 0xEB, 0xF1, 0x33, 0xC0, 0xCD, 0x16, 0xCD,
+0x19, 0xBE, 0xB3, 0x00, 0x81, 0xC6, 0x00, 0x7C, 0xEB, 0xE2, 0x0D, 0x0A, 0x4E, 0x6F, 0x6E, 0x2D,
+0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x20, 0x6F, 0x72, 0x20, 0x64,
+0x69, 0x73, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x52, 0x65, 0x70, 0x6C, 0x61,
+0x63, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6B, 0x65, 0x20, 0x61, 0x6E,
+0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x77, 0x68, 0x65, 0x6E, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79,
+0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x42, 0x6F, 0x6F, 0x74, 0x20, 0x66,
+0x61, 0x69, 0x6C, 0x75, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
+}};
+
+static const EmSector _8MBFat =
+{{
+0xF8, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}};
+
+static const EmSector _8MBRootDir =
+{{
+0xE5, 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, 'V', '?', 0x28, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x86, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ '8', 'M', 'B', '_', 'C', 'A', 'R', 'D', ' ', ' ', 0x20, 0x28, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x86, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+}};
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::EmGeneric8MB
+// ---------------------------------------------------------------------------
+EmGeneric8MB::EmGeneric8MB(void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::~EmGeneric8MB
+// ---------------------------------------------------------------------------
+EmGeneric8MB::~EmGeneric8MB(void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::GetTuple
+// ---------------------------------------------------------------------------
+EmSector * EmGeneric8MB::GetTuple(void)
+{
+ return((EmSector *)&_8MBTuple);
+}
+
+uint8 * EmGeneric8MB::GetSD_CSD(void)
+{
+ return ((uint8 *)&_8MBSD_CSD);
+}
+
+uint8 * EmGeneric8MB::GetSD_CID(void)
+{
+ return ((uint8 *)&_8MBSD_CID);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::GetDriveID
+// ---------------------------------------------------------------------------
+EmSector * EmGeneric8MB::GetDriveID(void)
+{
+ return((EmSector *)&_8MBDriveID);
+}
+
+#define _8MB_NUM_SECTORS 16384
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::GetNumSectors
+// ---------------------------------------------------------------------------
+uint32 EmGeneric8MB::GetNumSectors(void)
+{
+ return _8MB_NUM_SECTORS;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmGeneric8MB::GetSector
+// ---------------------------------------------------------------------------
+EmSector * EmGeneric8MB::GetSector(LogicalBlockAddr lba)
+{
+ switch(lba)
+ {
+ case 0 :
+ return((EmSector *)&_8MBMasterBootRecord);
+ case 32 :
+ return((EmSector *)&_8MBBootRecord);
+ case 33 :
+ case 39 :
+ return((EmSector *)&_8MBFat);
+ case 45 :
+ return((EmSector *)&_8MBRootDir);
+ default :
+ return(EmDiskType::GetEmptySector());
+ }
+}
+
+static const EmSector DummySector =
+{{
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}};
+
+// ---------------------------------------------------------------------------
+// ¥ EmDiskType::EmDiskType
+// ---------------------------------------------------------------------------
+EmDiskType::EmDiskType(void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmDiskType::~EmDiskType
+// ---------------------------------------------------------------------------
+EmDiskType::~EmDiskType(void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmDiskType::GetTuple
+// ---------------------------------------------------------------------------
+EmSector * EmDiskType::GetTuple(void)
+{
+ return (EmSector *)&DummySector;
+}
+
+uint8 * EmDiskType::GetSD_CSD(void)
+{
+ return ((uint8 *)&DummySector);
+}
+
+uint8 * EmDiskType::GetSD_CID(void)
+{
+ return ((uint8 *)&DummySector);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmDiskType::GetDriveID
+// ---------------------------------------------------------------------------
+EmSector * EmDiskType::GetDriveID(void)
+{
+ return (EmSector *)&DummySector;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmDiskType::GetEmptySector
+// ---------------------------------------------------------------------------
+EmSector * EmDiskType::GetEmptySector(void)
+{
+ return (EmSector *)&DummySector;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::EmCurrDiskType
+// ---------------------------------------------------------------------------
+EmCurrDiskType::EmCurrDiskType (void)
+{
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::~EmCurrDiskType
+// ---------------------------------------------------------------------------
+EmCurrDiskType::~EmCurrDiskType(void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::GetTuple
+// ---------------------------------------------------------------------------
+void EmCurrDiskType::GetTuple(EmDiskTypeID ID,
+ EmSector * s)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ *s = *Generic8MB.GetTuple();
+ break;
+ default :
+ *s = *UnknownDisk.GetTuple();
+ break;
+ }
+}
+
+uint8 *EmCurrDiskType::GetSD_CSD(EmDiskTypeID ID)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ return Generic8MB.GetSD_CSD();
+ break;
+ default :
+ return UnknownDisk.GetSD_CSD();
+ break;
+ }
+}
+
+uint8 *EmCurrDiskType::GetSD_CID(EmDiskTypeID ID)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ return Generic8MB.GetSD_CID();
+ break;
+ default :
+ return UnknownDisk.GetSD_CID();
+ break;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::GetDriveID
+// ---------------------------------------------------------------------------
+void EmCurrDiskType::GetDriveID(EmDiskTypeID ID,
+ EmSector * s)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ *s = *Generic8MB.GetDriveID();
+ break;
+ default :
+ *s = *UnknownDisk.GetDriveID();
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::GetNumSectors
+// ---------------------------------------------------------------------------
+uint32 EmCurrDiskType::GetNumSectors(EmDiskTypeID ID)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ return Generic8MB.GetNumSectors();
+ default :
+ return 0;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmCurrDiskType::GetSector
+// ---------------------------------------------------------------------------
+void EmCurrDiskType::GetSector(EmDiskTypeID ID,
+ LogicalBlockAddr lba,
+ EmSector * s)
+{
+ switch(ID)
+ {
+ case EM_DISK_GENERIC_8MB :
+ *s = *Generic8MB.GetSector(lba);
+ break;
+ default :
+ *s = *UnknownDisk.GetEmptySector();
+ break;
+ }
+}
diff --git a/SrcShared/Hardware/TRG/EmTRGDiskType.h b/SrcShared/Hardware/TRG/EmTRGDiskType.h
new file mode 100644
index 0000000..ac88a4d
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGDiskType.h
@@ -0,0 +1,65 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTRGDiskType_h
+#define EmTRGDiskType_h
+
+#include "EmTRGCFDefs.h"
+
+class EmDiskType
+{
+public:
+ EmDiskType (void);
+ virtual ~EmDiskType (void);
+
+ EmSector * GetTuple(void);
+ uint8 * GetSD_CSD(void);
+ uint8 * GetSD_CID(void);
+ EmSector * GetDriveID(void);
+ EmSector * GetEmptySector(void);
+
+};
+
+class EmGeneric8MB : public EmDiskType
+{
+public:
+ EmGeneric8MB(void);
+ virtual ~EmGeneric8MB(void);
+
+ EmSector * GetTuple(void);
+ uint8 * GetSD_CSD(void);
+ uint8 * GetSD_CID(void);
+ EmSector * GetDriveID(void);
+ uint32 GetNumSectors(void);
+ EmSector * GetSector(LogicalBlockAddr lba);
+};
+
+class EmCurrDiskType
+{
+private:
+ EmDiskType UnknownDisk;
+ EmGeneric8MB Generic8MB;
+
+public:
+ EmCurrDiskType (void);
+ virtual ~EmCurrDiskType (void);
+
+ void GetTuple(EmDiskTypeID ID, EmSector * s);
+ uint8 * GetSD_CSD(EmDiskTypeID ID);
+ uint8 * GetSD_CID(EmDiskTypeID ID);
+ void GetDriveID(EmDiskTypeID ID, EmSector * s);
+ uint32 GetNumSectors(EmDiskTypeID ID);
+ void GetSector(EmDiskTypeID ID, LogicalBlockAddr lba, EmSector * s);
+};
+
+#endif /* EmTRGDiskType_h */
diff --git a/SrcShared/Hardware/TRG/EmTRGSD.cpp b/SrcShared/Hardware/TRG/EmTRGSD.cpp
new file mode 100644
index 0000000..ad84526
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGSD.cpp
@@ -0,0 +1,321 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTRGSD.h"
+
+/************************************************************************
+ * This class handles the SPI SD controller interface used in the
+ * HandEra 330.
+ ************************************************************************/
+
+// SPI SD commands
+#define SD_CMD0_GO_IDLE 0
+#define SD_CMD1_GO_OPERATIONAL 1
+#define SD_CMD9_SEND_CSD 9
+#define SD_CMD10_SEND_CID 10
+#define SD_CMD12_STOP_TRANS 12 // not supported
+#define SD_CMD13_SEND_STATUS 13
+#define SD_CMD16_SET_BLOCKLEN 16 // not supported
+#define SD_CMD17_READ_SECTOR 17
+#define SD_CMD18_READ_MULTI 18 // not supported
+#define SD_CMD24_WRITE_SECTOR 24
+#define SD_CMD25_WRITE_MULTI 25 // not supported
+#define SD_CMD27_PROGRAM_CSD 27 // not supported
+#define SD_CMD28_SET_WRITE_PROT 28 // not supported
+#define SD_CMD29_CLR_WRITE_PROT 29 // not supported
+#define SD_CMD30_SEND_WRITE_PROT 30 // not supported
+#define SD_CMD32_ERASE_WR_BLK_START 32 // not supported
+#define SD_CMD33_ERASE_WR_BLK_END 33 // not supported
+#define SD_CMD38_ERASE 38 // not supported
+#define SD_CMD42_LOCK_UNLOCK 42 // not supported
+#define SD_CMD55_APP_CMD 55 // not supported
+#define SD_CMD56_GEN_CMD 56 // not supported
+#define SD_CMD58_READ_OCR 58 // not supported
+#define SD_CMD59_CRC_ON_OFF 59 // not supported
+
+#define SD_CMD_SIZE 6 // in bytes
+#define SD_CSD_SIZE 16
+#define SD_CID_SIZE 16
+
+#define SD_R1_OP_STATE 0x00
+#define SD_R1_IDLE_STATE 0x01
+#define SD_R1_ILLEGAL_CMD 0x04
+
+#define SD_STATUS_OK 0x00
+#define SD_DATA_START 0xFE
+
+#define SD_DATA_OK 0xE5
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::EmTRGSD
+// ---------------------------------------------------------------------------
+EmTRGSD::EmTRGSD()
+{
+ cmdIndex = 0;
+ sdBusState = sdBusGetCmdState;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::~EmTRGSD
+// ---------------------------------------------------------------------------
+EmTRGSD::~EmTRGSD()
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::Initialize
+// ---------------------------------------------------------------------------
+void EmTRGSD::Initialize(void)
+{
+ DiskIO.Initialize(EM_DISK_GENERIC_8MB, SD_DRIVE);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::Dispose
+// ---------------------------------------------------------------------------
+void EmTRGSD::Dispose(void)
+{
+ DiskIO.Dispose();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::CompleteCommand
+// complete command processing now that we have the data for it too
+// ---------------------------------------------------------------------------
+void EmTRGSD::CompleteCommand(void)
+{
+ cmdIndex = 0;
+ dataIndex = 0;
+ sdBusState = sdBusSendResponseState;
+ sdBusNextState = sdBusGetCmdState;
+ responseIndex = 0;
+
+ switch (cmdBuffer[0] & 0x3f)
+ {
+ case SD_CMD24_WRITE_SECTOR :
+ DiskIO.WriteSector(sectorNum, &dataBuffer[1]);
+
+ // send data OK response
+ responseBuffer[0] = SD_DATA_OK;
+ responseSize = 1;
+ break;
+
+ default :
+ // unimplemented, should never get here
+ EmAssert(false);
+ sdBusState = sdBusGetCmdState;
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::ProcessCommand
+// process the command we just received
+// ---------------------------------------------------------------------------
+void EmTRGSD::ProcessCommand(void)
+{
+ // clear command buffer
+ cmdIndex = 0;
+ sdBusState = sdBusSendResponseState;
+ sdBusNextState = sdBusGetCmdState;
+ responseIndex = 0;
+ dataIndex = 0;
+ dataSize = 0;
+
+ switch (cmdBuffer[0] & 0x3f)
+ {
+ case SD_CMD0_GO_IDLE :
+ responseBuffer[0] = SD_R1_IDLE_STATE;
+ responseSize = 1;
+ break;
+
+ case SD_CMD1_GO_OPERATIONAL :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseSize = 1;
+ break;
+
+ case SD_CMD9_SEND_CSD :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseSize = 1;
+
+ sdBusNextState = sdBusSendDataState;
+ dataBuffer[0] = SD_DATA_START;
+ memcpy(&dataBuffer[1], m_currDisk.GetSD_CSD(EM_DISK_GENERIC_8MB), SD_CSD_SIZE);
+ dataBuffer[SD_CSD_SIZE+2] = 0x00; // 16bit crc (unused)
+ dataBuffer[SD_CSD_SIZE+3] = 0x00;
+ dataSize = SD_CSD_SIZE+4;
+ break;
+
+ case SD_CMD10_SEND_CID :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseSize = 1;
+
+ sdBusNextState = sdBusSendDataState;
+ dataBuffer[0] = SD_DATA_START;
+ memcpy(&dataBuffer[1], m_currDisk.GetSD_CID(EM_DISK_GENERIC_8MB), SD_CID_SIZE);
+ dataBuffer[SD_CID_SIZE+1] = 0x00; // 16bit crc (unused)
+ dataBuffer[SD_CID_SIZE+2] = 0x00;
+ dataSize = SD_CID_SIZE+3;
+ break;
+
+ case SD_CMD13_SEND_STATUS :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseBuffer[1] = SD_STATUS_OK;
+ responseSize = 2;
+ break;
+
+ case SD_CMD17_READ_SECTOR :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseSize = 1;
+
+ sdBusNextState = sdBusSendDataState;
+ dataBuffer[0] = SD_DATA_START;
+ sectorNum = ((cmdBuffer[1] << 24) | (cmdBuffer[2] << 16) | (cmdBuffer[3] << 8) | cmdBuffer[4]);
+ // SD sector number is really a byte address...
+ sectorNum /= SECTOR_SIZE;
+ DiskIO.ReadSector(sectorNum, &dataBuffer[1]);
+ dataBuffer[SECTOR_SIZE+1] = 0x00; // 16 bit crc (unused)
+ dataBuffer[SECTOR_SIZE+2] = 0x00;
+ dataSize = SECTOR_SIZE+3;
+ break;
+
+ case SD_CMD24_WRITE_SECTOR :
+ responseBuffer[0] = SD_R1_OP_STATE;
+ responseSize = 1;
+ sectorNum = ((cmdBuffer[1] << 24) | (cmdBuffer[2] << 16) | (cmdBuffer[3] << 8) | cmdBuffer[4]);
+ // SD sector number is really a byte address...
+ sectorNum /= SECTOR_SIZE;
+
+ sdBusNextState = sdBusGetDataState;
+ dataSize = SECTOR_SIZE+3;
+ break;
+
+ default: // unimplemented
+ responseBuffer[0] = SD_R1_ILLEGAL_CMD;
+ responseSize = 1;
+ break;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmTRGSD::ExchangeBits
+// ---------------------------------------------------------------------------
+void EmTRGSD::ExchangeBits(uint16 txData, uint16 *rxData, uint16 bits)
+{
+ switch (bits)
+ {
+ case 8 :
+ switch (sdBusState)
+ {
+ case sdBusGetCmdState :
+ // all SPI commands start first two bits 0, 1
+ if ((cmdIndex != 0) || ((txData & 0xC0) == 0x40))
+ {
+ cmdBuffer[cmdIndex] = txData;
+ cmdIndex++;
+ if (cmdIndex == SD_CMD_SIZE)
+ ProcessCommand();
+ }
+ *rxData = 0xffff;
+ break;
+
+ case sdBusSendResponseState :
+ *rxData = responseBuffer[responseIndex++];
+ if (responseIndex == responseSize)
+ sdBusState = sdBusNextState;
+ break;
+
+ case sdBusGetDataState :
+ // all data blocks start with SD_DATA_START
+ if ((dataIndex != 0) || (txData == SD_DATA_START))
+ {
+ dataBuffer[dataIndex++] = txData;
+ if (dataIndex == dataSize)
+ {
+ // finish processing command waiting for this data...
+ CompleteCommand();
+ }
+ }
+ *rxData = 0xffff;
+ break;
+
+ case sdBusSendDataState :
+ *rxData = dataBuffer[dataIndex++];
+ if (dataIndex == dataSize)
+ sdBusState = sdBusGetCmdState;
+ break;
+
+ default :
+ break;
+ }
+ break;
+
+ case 16 :
+ switch (sdBusState)
+ {
+ case sdBusGetCmdState :
+ // all SPI commands start first two bits 0, 1
+ if ((cmdIndex != 0) || ((txData & 0xC000) == 0x4000))
+ {
+ cmdBuffer[cmdIndex++] = (txData & 0xff00) >> 8;
+ cmdBuffer[cmdIndex++] = (txData & 0x00ff);
+ if (cmdIndex >= SD_CMD_SIZE)
+ ProcessCommand();
+ }
+ *rxData = 0xffff;
+ break;
+
+ case sdBusSendResponseState :
+ *rxData = responseBuffer[responseIndex++] << 8;
+ *rxData |= responseBuffer[responseIndex++];
+ if (responseIndex >= responseSize)
+ sdBusState = sdBusNextState;
+ break;
+
+ case sdBusGetDataState :
+ dataBuffer[dataIndex++] = (txData & 0xff00) >> 8;
+ dataBuffer[dataIndex++] = (txData & 0x00ff);
+ if (dataIndex >= dataSize)
+ {
+ // finish processing command waiting for this data...
+ CompleteCommand();
+
+ sdBusState = sdBusGetCmdState;
+ }
+ *rxData = 0xffff;
+ break;
+
+ case sdBusSendDataState :
+ *rxData = dataBuffer[dataIndex++] << 8;
+ *rxData |= dataBuffer[dataIndex++];
+ if (dataIndex >= dataSize)
+ sdBusState = sdBusGetCmdState;
+ break;
+
+ default :
+ break;
+ }
+ break;
+
+ default :
+ // not supported...
+ EmAssert(false);
+ break;
+ }
+}
+
diff --git a/SrcShared/Hardware/TRG/EmTRGSD.h b/SrcShared/Hardware/TRG/EmTRGSD.h
new file mode 100644
index 0000000..bc5afd4
--- /dev/null
+++ b/SrcShared/Hardware/TRG/EmTRGSD.h
@@ -0,0 +1,64 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+#ifndef _EmTRGSD_h_
+#define _EmTRGSD_h_
+
+#include "EmTRGDiskIO.h"
+
+/************************************************************************
+ * This class handles the SPI SD controller interface used in the
+ * HandEra 330.
+ ************************************************************************/
+
+
+typedef enum
+{
+ sdBusGetCmdState,
+ sdBusSendResponseState,
+ sdBusGetDataState,
+ sdBusSendDataState
+} sdBusStateType;
+
+
+class EmTRGSD
+{
+ private:
+ uint8 cmdBuffer[6];
+ int cmdIndex;
+ uint8 responseBuffer[2];
+ int responseIndex;
+ int responseSize;
+ uint8 dataBuffer[520];
+ int dataIndex;
+ int dataSize;
+ uint32 sectorNum;
+ sdBusStateType sdBusState;
+ sdBusStateType sdBusNextState; // next state after sending response
+
+ EmTRGDiskIO DiskIO;
+ EmCurrDiskType m_currDisk;
+
+ void ProcessCommand(void);
+ void CompleteCommand(void);
+
+ public :
+ EmTRGSD();
+ ~EmTRGSD();
+
+ void Initialize(void);
+ void Dispose(void);
+
+ void ExchangeBits(uint16 txData, uint16 *rxData, uint16 Bits);
+};
+
+#endif \ No newline at end of file
diff --git a/SrcShared/Hordes.cpp b/SrcShared/Hordes.cpp
new file mode 100644
index 0000000..3e4178a
--- /dev/null
+++ b/SrcShared/Hordes.cpp
@@ -0,0 +1,2437 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Hordes.h" // class Hordes
+
+#include "CGremlins.h" // Gremlins
+#include "CGremlinsStubs.h" // StubAppGremlinsOff
+#include "EmApplication.h" // ScheduleQuit
+#include "EmEventPlayback.h" // SaveEvents, LoadEvents, Clear, RecordEvents
+#include "EmMapFile.h" // EmMapFile::Write, etc.
+#include "EmMinimize.h" // EmMinimize::IsDone
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmSession.h" // gSession, ScheduleResumeHordesFromFile
+#include "EmStreamFile.h" // kCreateOrOpenForWrite
+#include "ErrorHandling.h" // Errors::ThrowIfPalmError
+#include "Logging.h" // LogStartNew, etc.
+#include "Platform.h" // Platform::GetMilliseconds
+#include "PreferenceMgr.h" // Preference, gEmuPrefs
+#include "ROMStubs.h" // EvtWakeup
+#include "SessionFile.h" // Chunk, EmStreamChunk
+#include "Startup.h" // HordeQuitWhenDone
+#include "StringConversions.h" // ToString, FromString;
+#include "Strings.r.h" // kStr_CmdOpen, etc.
+#include "SystemMgr.h" // sysGetROMVerMajor
+
+#include <math.h> // sqrt
+#include <time.h> // time, localtime
+
+////////////////////////////////////////////////////////////////////////////////////////
+// HORDES CONSTANTS
+
+static const int MAXGREMLINS = 999;
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// HORDES STATIC DATA
+
+static Gremlins gTheGremlin;
+static int32 gGremlinStartNumber;
+static int32 gGremlinStopNumber;
+static int32 gSwitchDepth;
+static int32 gMaxDepth;
+ int32 gGremlinSaveFrequency;
+DatabaseInfoList gGremlinAppList;
+static int32 gCurrentGremlin;
+static int32 gCurrentDepth;
+static bool gIsOn;
+static uint32 gStartTime;
+static uint32 gStopTime;
+static EmGremlinThreadInfo gGremlinHaltedInError[MAXGREMLINS + 1];
+static EmDirRef gHomeForHordesFiles;
+
+static Bool gForceNewHordesDirectory;
+static EmDirRef gGremlinDir;
+
+Bool gWarningHappened;
+Bool gErrorHappened;
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// HORDES METHODS
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Hordes::Initialize (void)
+{
+ gTheGremlin.Reset ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Hordes::Reset (void)
+{
+ EmDlg::GremlinControlClose ();
+ Hordes::Stop ();
+ gTheGremlin.Reset ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Hordes::Save (SessionFile& f)
+{
+ gTheGremlin.Save (f);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Hordes::Load (SessionFile& f)
+{
+ Bool fHordesOn = gTheGremlin.Load (f);
+ Hordes::TurnOn (fHordesOn);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Hordes::Dispose (void)
+{
+ gTheGremlin.Reset ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::New
+ *
+ * DESCRIPTION: Starts a new Horde of Gremlins
+ *
+ * PARAMETERS: HordeInfo& info - Horde initialization info
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::New(const HordeInfo& info)
+{
+ gGremlinStartNumber = min(info.fStartNumber, info.fStopNumber);
+ gGremlinStopNumber = max(info.fStartNumber, info.fStopNumber);
+
+ if (info.fSwitchDepth == -1 || gGremlinStartNumber == gGremlinStopNumber)
+ gSwitchDepth = info.fMaxDepth;
+
+ else
+ gSwitchDepth = info.fSwitchDepth;
+
+ gMaxDepth = info.fMaxDepth;
+ gGremlinSaveFrequency = info.fSaveFrequency;
+ gGremlinAppList = info.fAppList;
+ gCurrentDepth = 0;
+ gCurrentGremlin = gGremlinStartNumber;
+
+ if (gSwitchDepth == 0)
+ gSwitchDepth = -1;
+
+ if (gMaxDepth == 0)
+ gMaxDepth = -1;
+
+ for (int counter = 0; counter <= MAXGREMLINS; counter++)
+ {
+ gGremlinHaltedInError[counter].fHalted = false;
+ gGremlinHaltedInError[counter].fErrorEvent = 0;
+ gGremlinHaltedInError[counter].fMessageID = -1;
+ }
+
+ GremlinInfo gremInfo;
+
+ gremInfo.fNumber = gCurrentGremlin;
+ gremInfo.fSaveFrequency = gGremlinSaveFrequency;
+ gremInfo.fSteps = (gMaxDepth == -1) ? gSwitchDepth : min (gSwitchDepth, gMaxDepth);
+ gremInfo.fAppList = gGremlinAppList;
+ gremInfo.fFinal = gMaxDepth;
+
+ gStartTime = Platform::GetMilliseconds ();
+
+ gTheGremlin.New (gremInfo);
+
+ EmDlg::GremlinControlOpen ();
+
+ Hordes::UseNewAutoSaveDirectory ();
+
+ EmEventPlayback::Clear ();
+
+ // When we save our root state, we want it to be saved with all
+ // the correct GremlinInfo (per the 2.0 file format) but with
+ // Gremlins turned OFF.
+
+ Hordes::TurnOn (false);
+
+ Hordes::SaveRootState ();
+
+ Hordes::TurnOn (true);
+
+ Hordes::StartLog ();
+
+ LogAppendMsg ("New Gremlin #%ld started anew to %ld events",
+ gremInfo.fNumber, gremInfo.fSteps);
+
+ LogDump ();
+
+ gWarningHappened = false;
+ gErrorHappened = false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::NewGremlin
+ *
+ * DESCRIPTION: Starts a new Horde of just one Gremlin --
+ * "classic Gremlins"
+ *
+ * PARAMETERS: GremlinInfo& info - Gremlin initialization info
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::NewGremlin (const GremlinInfo &info)
+{
+ HordeInfo newHorde;
+
+ newHorde.fStartNumber = info.fNumber;
+ newHorde.fStopNumber = info.fNumber;
+ newHorde.fSwitchDepth = info.fSteps;
+ newHorde.fMaxDepth = info.fSteps;
+ newHorde.fSaveFrequency = info.fSaveFrequency;
+ newHorde.fAppList = info.fAppList;
+
+ Hordes::New (newHorde);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Status
+ *
+ * DESCRIPTION: Returns several pieces of status information about the
+ * currently running Gremlin in the Horde.
+ *
+ * PARAMETERS: currentNumber - returns the current Gremlin number.
+ * currentStep - returns the current event number of the
+ * currently running Gremlin
+ * currentUntil - returns the current upper event bound of
+ * currently running Gremlin
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::Status (unsigned short *currentNumber, unsigned long *currentStep,
+ unsigned long *currentUntil)
+{
+ gTheGremlin.Status (currentNumber, currentStep, currentUntil);
+}
+
+
+string
+Hordes::GremlinsFlagsToString (void)
+{
+ string output;
+
+ for (int ii = 0; ii < MAXGREMLINS; ++ii)
+ {
+ gGremlinHaltedInError[ii].fHalted ? output += "1" : output += "0";
+ }
+
+ return output;
+}
+
+void
+Hordes::GremlinsFlagsFromString(string& inFlags)
+{
+ for (int ii = 0; ii < MAXGREMLINS; ++ii)
+ {
+ gGremlinHaltedInError[ii].fHalted = (inFlags.c_str()[ii] == '1');
+ }
+}
+
+void
+Hordes::SaveSearchProgress()
+{
+ StringStringMap searchProgress;
+
+ searchProgress["gGremlinStartNumber"] = ::ToString (gGremlinStartNumber);
+ searchProgress["gGremlinStopNumber"] = ::ToString (gGremlinStopNumber);
+ searchProgress["gSwitchDepth"] = ::ToString (gSwitchDepth);
+ searchProgress["gMaxDepth"] = ::ToString (gMaxDepth);
+ searchProgress["gGremlinSaveFrequency"] = ::ToString (gGremlinSaveFrequency);
+ searchProgress["gCurrentGremlin"] = ::ToString (gCurrentGremlin);
+ searchProgress["gCurrentDepth"] = ::ToString (gCurrentDepth);
+ searchProgress["gGremlinHaltedInError"] = Hordes::GremlinsFlagsToString ();
+ searchProgress["gStartTime"] = ::ToString (gStartTime);
+ searchProgress["gStopTime"] = ::ToString (gStopTime);
+
+ EmFileRef searchFile = Hordes::SuggestFileRef (kHordeProgressFile);
+
+ EmMapFile::Write (searchFile, searchProgress);
+}
+
+
+void
+Hordes::ResumeSearchProgress (const EmFileRef& f)
+{
+ StringStringMap searchProgress;
+
+ EmMapFile::Read (f, searchProgress);
+
+ ::FromString (searchProgress["gGremlinStartNumber"], gGremlinStartNumber);
+ ::FromString (searchProgress["gGremlinStopNumber"], gGremlinStopNumber);
+ ::FromString (searchProgress["gSwitchDepth"], gSwitchDepth);
+ ::FromString (searchProgress["gMaxDepth"], gMaxDepth);
+ ::FromString (searchProgress["gGremlinSaveFrequency"], gGremlinSaveFrequency);
+ ::FromString (searchProgress["gCurrentGremlin"], gCurrentGremlin);
+ ::FromString (searchProgress["gCurrentDepth"], gCurrentDepth);
+
+ Hordes::GremlinsFlagsFromString (searchProgress["gGremlinHaltedInError"]);
+
+ // Get, then patch up start and stop times.
+
+ ::FromString (searchProgress["gStartTime"], gStartTime);
+ ::FromString (searchProgress["gStopTime"], gStopTime);
+
+ uint32 delta = gStopTime - gStartTime;
+ gStopTime = Platform::GetMilliseconds ();
+ gStartTime = gStopTime - delta;
+
+// gSession->ScheduleResumeHordesFromFile ();
+}
+
+Bool
+Hordes::IsOn (void)
+{
+ return gIsOn;
+}
+
+Bool
+Hordes::InSingleGremlinMode (void)
+{
+ return gGremlinStartNumber == gGremlinStopNumber;
+}
+
+
+Bool
+Hordes::QuitWhenDone (void)
+{
+ if (Startup::HordeQuitWhenDone ())
+ return true;
+
+ return false;
+}
+
+
+Bool
+Hordes::CanNew (void)
+{
+ return !EmMinimize::IsOn () && EmPatchState::UIInitialized ();
+}
+
+
+Bool
+Hordes::CanSuspend (void)
+{
+ return !EmMinimize::IsOn ();
+}
+
+
+Bool
+Hordes::CanStep (void)
+{
+ return (gTheGremlin.IsInitialized () && !gIsOn && !EmMinimize::IsOn ());
+}
+
+
+Bool
+Hordes::CanResume (void)
+{
+ return (gTheGremlin.IsInitialized () && !gIsOn && !EmMinimize::IsOn ());
+}
+
+
+Bool
+Hordes::CanStop (void)
+{
+ return (gIsOn && !EmMinimize::IsOn ());
+}
+
+
+int32
+Hordes::GremlinNumber (void)
+{
+ return gCurrentGremlin;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::TurnOn
+ *
+ * DESCRIPTION: Turns Hordes on or off.
+ *
+ * PARAMETERS: fHordesOn - specifies if Hordes should be on or off.
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::TurnOn (Bool hordesOn)
+{
+ gIsOn = (hordesOn != false);
+ EmEventPlayback::RecordEvents (gIsOn);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::EventCounter
+ *
+ * DESCRIPTION: Returns the current event count of the currently running
+ * Gremlin
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: event count
+ *
+ ***********************************************************************/
+
+int32
+Hordes::EventCounter (void)
+{
+ unsigned short number;
+ unsigned long step;
+ unsigned long until;
+
+ Hordes::Status (&number, &step, &until);
+
+ return step;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::EventLimit
+ *
+ * DESCRIPTION: Returns the current event limit of the currently running
+ * Gremlin
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: event limit
+ *
+ ***********************************************************************/
+
+int32
+Hordes::EventLimit(void)
+{
+ unsigned short number;
+ unsigned long step;
+ unsigned long until;
+
+ Hordes::Status (&number, &step, &until);
+
+ return until;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::EndHordes
+ *
+ * DESCRIPTION: Ends Hordes, giving back control to user.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::EndHordes (void)
+{
+ // In an odd twist, logging doesn't work if Hordes is supposedly
+ // turned off. So let's spoof that it's on; it will be turned off --
+ // again -- below, when Hordes::Stop() is called.
+
+ Hordes::TurnOn (true);
+
+ if (!Hordes::InSingleGremlinMode ())
+ {
+ LogAppendMsg ("************* Gremlin Horde ended at Gremlin #%ld\n", gGremlinStopNumber);
+ }
+
+ // It's time to print out some basic info:
+ // ROM version
+ // ROM file name
+ // Device name
+ // RAM size
+
+ UInt32 romVersionData;
+ ::FtrGet (sysFileCSystem, sysFtrNumROMVersion, &romVersionData);
+
+ UInt32 romVersionMajor = sysGetROMVerMajor (romVersionData);
+ UInt32 romVersionMinor = sysGetROMVerMinor (romVersionData);
+
+ Preference<Configuration> pref (kPrefKeyLastConfiguration);
+ Preference<EmFileRef> pref2 (kPrefKeyLastPSF);
+
+ Configuration cfg = *pref;
+ EmDevice device = cfg.fDevice;
+ string deviceStr = device.GetIDString ();
+ RAMSizeType ramSize = cfg.fRAMSize;
+ EmFileRef romFile = cfg.fROMFile;
+ string romFileStr = romFile.GetFullPath ();
+ EmFileRef sessionFile = *pref2;
+ string sessionFileStr = sessionFile.GetFullPath ();
+
+ if (sessionFileStr.empty ())
+ {
+ sessionFileStr = "<Not selected>";
+ }
+
+ LogAppendMsg ("************* Device Info:");
+ LogAppendMsg ("ROM version: %d.%d", romVersionMajor, romVersionMinor);
+ LogAppendMsg ("ROM file name: %s", (char *) romFileStr.c_str ());
+ LogAppendMsg ("Session file: %s", (char *) sessionFileStr.c_str ());
+ LogAppendMsg ("Device name: %s", (char *) deviceStr.c_str ());
+ LogAppendMsg ("RAM size: %d KB\n", (long) ramSize);
+
+ // Let's come up with some statistics from our new field in
+ // gGremlinHaltedInError.
+
+ int32 min, max, avg, stdDev, smallErrorIndex;
+ Hordes::ComputeStatistics (min, max, avg, stdDev, smallErrorIndex);
+
+ LogAppendMsg ("************* Error Occurrence Statistics:");
+ LogAppendMsg ("");
+
+ Hordes::GremlinReport ();
+
+ // check for the sentinel value
+
+ if (smallErrorIndex != 0x7FFFFFFF)
+ {
+ LogAppendMsg ("");
+ LogAppendMsg ("Minimum Event: %d", min);
+ LogAppendMsg ("Maximum Event: %d", max);
+ LogAppendMsg ("Average Event: %d", avg);
+ LogAppendMsg ("Standard Deviation: %d", stdDev);
+ LogAppendMsg ("Overall Shortest Gremlin: #%d\n", smallErrorIndex);
+ }
+ else
+ {
+ LogAppendMsg ("No Gremlins found errors.\n");
+ }
+
+ LogDump ();
+
+ Hordes::TurnOn (false);
+
+ LogClear();
+ EmEventPlayback::Clear ();
+
+ if (!Hordes::InSingleGremlinMode ())
+ {
+ EmDlg::GremlinControlClose ();
+
+ EmAssert (gSession);
+ gSession->ScheduleLoadRootState ();
+ }
+
+ if (Hordes::QuitWhenDone ())
+ {
+ EmAssert (gApplication);
+ gApplication->ScheduleQuit ();
+ }
+ else
+ {
+ gWarningHappened = false;
+ gErrorHappened = false;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::ProposeNextGremlin
+ *
+ * DESCRIPTION: Proposes the NEXT Gremlin # and corresponding search
+ * depth, FROM the state of the Hordes run specified by the
+ * input paramaters
+ *
+ * PARAMETERS: outNextGremlin - passes back suggested next Gremlin
+ * outNextDepth - passes back next depth
+ * inFromGremlin - "current" Gremlin
+ * inFromGremlin - "current" depth
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::ProposeNextGremlin (long& outNextGremlin, long& outNextDepth,
+ long inFromGremlin, long inFromDepth)
+{
+ outNextGremlin = inFromGremlin + 1;
+ outNextDepth = inFromDepth;
+
+ if (outNextGremlin == gGremlinStopNumber + 1)
+ {
+ outNextGremlin = gGremlinStartNumber;
+
+ if (outNextDepth >= 0)
+ ++outNextDepth;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::StartGremlinFromLoadedRootState
+ *
+ * DESCRIPTION: After the CPU loads the root state during an off-cycle,
+ * it calls this to indicate that Hordes is meant to start
+ * the current Gremlin, and that the Emulator state is ready
+ * for this.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::StartGremlinFromLoadedRootState (void)
+{
+ GremlinInfo gremInfo;
+
+ gremInfo.fNumber = gCurrentGremlin;
+ gremInfo.fSaveFrequency = gGremlinSaveFrequency;
+ gremInfo.fSteps = ((gMaxDepth == -1) ? gSwitchDepth : min(gSwitchDepth, gMaxDepth));
+ gremInfo.fAppList = gGremlinAppList;
+ gremInfo.fFinal = gMaxDepth;
+
+ gTheGremlin.New (gremInfo);
+
+ LogAppendMsg ("New Gremlin #%ld started from root state to %ld events",
+ gCurrentGremlin, gremInfo.fSteps);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::StartGremlinFromLoadedSuspendedState
+ *
+ * DESCRIPTION: After the CPU loads the suspended state during an off-cycle,
+ * it calls this to indicate that Hordes is meant to resume
+ * the current Gremlin, and that the Emulator state is ready
+ * for this.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::StartGremlinFromLoadedSuspendedState (void)
+{
+ // We reset the Gremlin to go until the next occurence of the
+ // depth-bound, or until gMaxDepth, whichever occurs first.
+
+ long newUntil = gSwitchDepth * (gCurrentDepth + 1);
+
+ if (gMaxDepth != -1)
+ {
+ newUntil = min (newUntil, gMaxDepth);
+ }
+
+ gTheGremlin.SetUntil (newUntil);
+
+ LogAppendMsg("Resuming Gremlin #%ld to #%ld events",
+ gCurrentGremlin, newUntil);
+
+ Hordes::TurnOn(true);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SetGremlinStatePathFromControlFile
+ *
+ * DESCRIPTION: Given the file reference to a control file (actually *any*
+ * file in the Gremlins state path), set the Gremlins state
+ * path to the directory that contains this file.
+ *
+ * PARAMETERS: controlFile - reference to the rootStateFile.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void
+Hordes::SetGremlinStatePathFromControlFile (EmFileRef& controlFile)
+{
+ gGremlinDir = controlFile.GetParent ();
+ gForceNewHordesDirectory = false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::NextGremlin
+ *
+ * DESCRIPTION: Selects and runs the next Gremlin in the Horde, if there
+ * are unfinished Gremlins left. Otherwise, just loads
+ * the pre-Horde state and stops.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::NextGremlin (void)
+{
+ Hordes::Stop ();
+
+ Hordes::SaveSearchProgress ();
+
+ // Find the next Gremlin to run.
+
+ long nextGremlin, nextDepth;
+
+ // Keep looking until we find a Gremlin in the range which has
+ // not halted in error.
+
+ Hordes::ProposeNextGremlin (nextGremlin, nextDepth, gCurrentGremlin, gCurrentDepth);
+
+ while (gGremlinHaltedInError[nextGremlin].fHalted)
+ {
+ // All Gremlins halted in error when we are back at the current
+ // Gremlin at the next depth. (We looped around without finding
+ // the next Gremlin that didn't halt in error).
+
+ if (nextGremlin == gCurrentGremlin && nextDepth >= gCurrentDepth + 1)
+ {
+ Hordes::EndHordes ();
+ return;
+ }
+
+ Hordes::ProposeNextGremlin (nextGremlin, nextDepth, nextGremlin, nextDepth);
+ }
+
+ // Update our current location in the Gremlin search tree.
+
+ gCurrentGremlin = nextGremlin;
+ gCurrentDepth = nextDepth;
+
+ // All the Gremlins have reached gMaxDepth when the depth exceeds the
+ // depth necessary to reach gMaxDepth. Special case for
+ // gMaxDepth = forever.
+
+ if ( gMaxDepth != -1 &&
+ ( (gCurrentDepth > gMaxDepth / gSwitchDepth) ||
+ ( (gCurrentDepth == gMaxDepth / gSwitchDepth) && (gMaxDepth % gSwitchDepth == 0) ) ) )
+ {
+ Hordes::EndHordes();
+ return;
+ }
+
+ // If the current depth is 0, we start at the root state.
+
+ if (gCurrentDepth == 0)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleNextGremlinFromRootState ();
+ }
+
+ // Otherwise, we load the suspended state, which is where we begin to
+ // resume the Gremlin
+
+ else
+ {
+ EmAssert (gSession);
+ gSession->ScheduleNextGremlinFromSuspendedState ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::ErrorEncountered
+ *
+ * DESCRIPTION: Called when an error condition has been encountered.
+ * This function saves the current state and starts in
+ * motion the machinery to start the next Gremlin in the
+ * Horde.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::ErrorEncountered (void)
+{
+ int32 errorGremlin = Hordes::GremlinNumber ();
+ int32 errorEvent = Hordes::EventCounter () - 1;
+
+ Hordes::AutoSaveState ();
+
+ LogAppendMsg ("=== ERROR: Gremlin #%ld terminated in error at event #%ld\n",
+ errorGremlin, errorEvent);
+
+ LogDump ();
+
+ // This is a fatal error; stop the execution of this Gremlin.
+
+ gGremlinHaltedInError[errorGremlin].fHalted = true;
+
+ // Save the events, now that it's terminated with an error event.
+
+ Hordes::SaveEvents ();
+
+ // Move to the next Gremlin.
+
+// if (!Hordes::InSingleGremlinMode ())
+ {
+ Hordes::NextGremlin ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::RecordErrorStats
+ *
+ * DESCRIPTION: Called when an error message needs to be displayed,
+ * either as a result of a hardware exception, an error
+ * condition detected by Poser, or the Palm application
+ * calling SysFatalAlert. If appropriate, log the error
+ * message.
+ *
+ * PARAMETERS: messageID - ID indicating what error occurred. We pass
+ * that into here so that we can keep stats on the kinds
+ * of errors generated.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::RecordErrorStats (StrCode messageID)
+{
+ if (Hordes::IsOn ())
+ {
+ // Update our gGremlinHaltedInError info if it was passed, and if
+ // we haven't already assigned an error to this Gremlin. (This is
+ // so that the first error, of possibly many if we are continuing
+ // on errors, is the one that shows up in the statistics.)
+
+ int32 errorGremlin = Hordes::GremlinNumber();
+ int32 errorEvent = Hordes::EventCounter () - 1;
+
+ // Only update this if we haven't already logged an error event for the first
+ // error
+
+ Bool firstErrForGremlin = gGremlinHaltedInError[errorGremlin].fMessageID == -1;
+
+ if (firstErrForGremlin)
+ {
+ gGremlinHaltedInError[errorGremlin].fErrorEvent = errorEvent;
+
+ // Now update the message id if a valid one was passed
+
+ if (messageID != -1)
+ {
+ gGremlinHaltedInError[errorGremlin].fMessageID = (long) messageID;
+ }
+ }
+
+ // Tell Minimization that a warning or error occurred.
+ //
+ // Do we ever get here? RecordErrorStats is called from Errors::DoDialog.
+ // Errors::DoDialog is called from Errors::HandleDialog, which calls
+ // EmMinimize::ErrorOccurred and returns before calling Errors::DoDialog
+ // if minimization is turned on.
+
+ if (EmMinimize::IsOn ())
+ {
+ EmAssert (false); // See if we get here.
+
+ LogAppendMsg ("Calling EmMinimize::ErrorOccurred from Hordes::RecordErrorStats");
+ EmMinimize::ErrorOccurred ();
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::StopEventReached
+ *
+ * DESCRIPTION: Message to Hordes indicating that a Gremlin has
+ * completed its last event. Saves a suspended state if
+ * we intend to resume this Gremlin in the future.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::StopEventReached()
+{
+ int32 gremlinNumber = Hordes::GremlinNumber ();
+ int32 stopEventNumber = Hordes::EventLimit ();
+
+ LogAppendMsg ("Gremlin #%ld finished successfully to event #%ld",
+ gremlinNumber, stopEventNumber);
+
+ if (stopEventNumber == gMaxDepth)
+ {
+// LogAppendMsg ("********************************************************************************");
+ LogAppendMsg ("************* Gremlin #%ld successfully completed", gremlinNumber);
+// LogAppendMsg ("********************************************************************************");
+ }
+
+ LogDump ();
+
+ // Save the events of the successful run.
+
+ Hordes::SaveEvents ();
+
+ // Move to the next Gremlin.
+
+ Hordes::NextGremlin ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Suspend
+ *
+ * DESCRIPTION: Suspends the currently running Gremlin.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::Suspend()
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Step
+ *
+ * DESCRIPTION: "Steps" the currently running Gremlin.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::Step()
+{
+ if (!gIsOn)
+ {
+ Hordes::TurnOn (true);
+
+ // Spoof info to look as if this was a single Gremlin run. This way,
+ // stepping will work; if this is not done, then the next Gremlin is
+ // launched, just as if a switching barrier was reached.
+
+ gCurrentDepth = gMaxDepth;
+ gGremlinStartNumber = gGremlinStopNumber = gCurrentGremlin;
+
+ gTheGremlin.Step ();
+
+ // Make sure the app's awake. Normally, we post events on a patch to
+ // SysEvGroupWait. However, if the Palm device is already waiting,
+ // then that trap will never get called. By calling EvtWakeup now,
+ // we'll wake up the Palm device from its nap.
+
+ Errors::ThrowIfPalmError (EvtWakeup ());
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Resume
+ *
+ * DESCRIPTION: Resumes the currently suspended Gremlin.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::Resume()
+{
+ if (!Hordes::IsOn ())
+ {
+ Hordes::TurnOn (true);
+
+ gStartTime = Platform::GetMilliseconds () - (gStopTime - gStartTime);
+
+ gTheGremlin.RestoreFinalUntil ();
+
+ gTheGremlin.Resume ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::Stop
+ *
+ * DESCRIPTION: Suspends the currently running Gremlin.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::Stop (void)
+{
+ gStopTime = Platform::GetMilliseconds ();
+
+ StubAppGremlinsOff ();
+
+ gTheGremlin.Stop ();
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: Hordes::SuggestFileName
+ *
+ * DESCRIPTION: This function is responsible for deciding about the names of
+ * files that are created during a horde run. The file names
+ * are assigned based on the requested file category. Some
+ * file categories use gremlins data (event number, gremlin
+ * number) to construct a unique file name. The following
+ * categories are used by the "Horde" class:
+ *
+ * kHordeProgressFile
+ * kHordeRootFile
+ * kHordeSuspendFile
+ * kHordeAutoCurrentFile
+ *
+ * kHordeSuspendFile - last file in a gremlin thread
+ *
+ * PARAMETERS: file category
+ *
+ * RETURNED: file name or an empty string when the input category is
+ * incorrect
+ *
+ *****************************************************************************/
+
+string Hordes::SuggestFileName (HordeFileType category, uint32 num)
+{
+ static const char kStrSearchProgressFile[] = "Gremlin_Search_Progress.dat";
+ static const char kStrRootStateFile[] = "Gremlin_Root_State.psf";
+ static const char kStrSuspendedStateFile[] = "Gremlin_%03ld_Suspended.psf";
+ static const char kStrAutoSaveFile[] = "Gremlin_%03ld_Event_%08ld.psf";
+ static const char kStrEventFile[] = "Gremlin_%03ld_Events.pev";
+ static const char kStrMinimalEventFile [] = "Gremlin_%03ld_Interim_Event_File_%08ld.pev";
+
+ char fileName[64];
+
+ int32 gremlinNumber;
+ int32 eventCounter;
+ uint32 time;
+
+ switch (category)
+ {
+ case kHordeProgressFile:
+
+ strcpy (fileName, kStrSearchProgressFile);
+ break;
+
+ case kHordeRootFile:
+
+ strcpy (fileName, kStrRootStateFile);
+ break;
+
+ case kHordeSuspendFile:
+
+ gremlinNumber = Hordes::GremlinNumber ();
+ sprintf (fileName, kStrSuspendedStateFile, gremlinNumber);
+ break;
+
+ case kHordeAutoCurrentFile:
+
+ gremlinNumber = Hordes::GremlinNumber ();
+ eventCounter = Hordes::EventCounter ();
+
+ if (gGremlinSaveFrequency == 0)
+ {
+ sprintf (fileName, kStrAutoSaveFile, gremlinNumber, eventCounter);
+ }
+ else
+ {
+ eventCounter = (eventCounter / gGremlinSaveFrequency) * gGremlinSaveFrequency;
+ sprintf (fileName, kStrAutoSaveFile, gremlinNumber, eventCounter);
+ }
+ break;
+
+ case kHordeEventFile:
+
+ gremlinNumber = Hordes::GremlinNumber ();
+ sprintf (fileName, kStrEventFile, gremlinNumber);
+ break;
+
+ case kHordeMinimalEventFile:
+
+ gremlinNumber = num;
+ time = Platform::GetMilliseconds ();
+ sprintf (fileName, kStrMinimalEventFile, gremlinNumber, time);
+ break;
+
+ default:
+
+ *fileName = '\0';
+ break;
+ };
+
+ return string (fileName);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: Hordes::SuggestFileRef
+ *
+ * DESCRIPTION: This function is responsible for deciding about the names of
+ * files that are created during a horde run. The file names
+ * are assigned based on the requested file category. Some
+ * file categories use gremlins data (event number, gremlin
+ * number) to construct a unique file name. The following
+ * categories are used by the "Horde" class:
+ *
+ * kHordeProgressFile
+ * kHordeRootFile
+ * kHordeSuspendFile
+ * kHordeAutoCurrentFile
+ *
+ * kHordeSuspendFile - last file in a gremlin thread
+ *
+ * PARAMETERS: file category
+ *
+ * RETURNED: file ref
+ *
+ *****************************************************************************/
+
+EmFileRef Hordes::SuggestFileRef (HordeFileType category, uint32 num)
+{
+ EmFileRef fileRef (
+ Hordes::GetGremlinDirectory (),
+ Hordes::SuggestFileName (category, num));
+
+ return fileRef;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::PostLoad
+ *
+ * DESCRIPTION: Initializes a load that has taken place outside the
+ * control of the Hordes subsystem. For example, if the user
+ * has opened a session file manually. This is to set the
+ * Hordes state to play the Gremlin in the file as a "horde
+ * of one."
+ *
+ * PARAMETERS: f - SessionFile to load from
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::PostLoad (void)
+{
+ // We can't just call NewGremlin with the GremlinInfo because
+ // gTheGremlin.Load() has already restored the state of the Gremlin,
+ // so we should not call gTheGremlin.New() on it.
+
+ Preference<GremlinInfo> pref (kPrefKeyGremlinInfo);
+ GremlinInfo info = *pref;
+
+ gGremlinStartNumber = info.fNumber;
+ gGremlinStopNumber = info.fNumber;
+ gCurrentGremlin = info.fNumber;
+ gSwitchDepth = info.fSteps;
+ gMaxDepth = info.fSteps;
+ gGremlinSaveFrequency = info.fSaveFrequency;
+ gGremlinAppList = info.fAppList;
+ gCurrentDepth = 0;
+
+ gStartTime = gTheGremlin.GetStartTime ();
+ gStopTime = gTheGremlin.GetStopTime ();
+
+ if (Hordes::IsOn())
+ {
+ Hordes::UseNewAutoSaveDirectory ();
+
+ EmAssert (gSession);
+ gSession->ScheduleSaveRootState ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::PostFakeEvent
+ *
+ * DESCRIPTION: Posts a fake event through the currently running Gremlin.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: TRUE if a key or point was enqueued, FALSE otherwise.
+ *
+ ***********************************************************************/
+
+Bool
+Hordes::PostFakeEvent (void)
+{
+ // check to see if the Gremlin has produced its max # of "events."
+
+ if (Hordes::EventLimit() > 0 && Hordes::EventCounter () > Hordes::EventLimit ())
+ {
+ Hordes::StopEventReached ();
+ return false;
+ }
+
+ Bool result = gTheGremlin.GetFakeEvent ();
+
+ Hordes::BumpCounter ();
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::PostFakePenEvent
+ *
+ * DESCRIPTION: Posts a phony pen movement to through the currently
+ * running Gremlin
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::PostFakePenEvent (void)
+{
+ Hordes::BumpCounter ();
+ gTheGremlin.GetPenMovement ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SendCharsToType
+ *
+ * DESCRIPTION: Send a char to the Emulator if any are pending for the
+ * currently running Gremlin
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+Bool
+Hordes::SendCharsToType (void)
+{
+ return gTheGremlin.SendCharsToType ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::ElapsedMilliseconds
+ *
+ * DESCRIPTION: Returns the elapsed time of the Horde
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+uint32
+Hordes::ElapsedMilliseconds (void)
+{
+ if (gIsOn)
+ return Platform::GetMilliseconds () - gStartTime;
+
+ return gStopTime - gStartTime;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::BumpCounter
+ *
+ * DESCRIPTION: Bumps event counter of the currently running Gremlin
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::BumpCounter (void)
+{
+ gTheGremlin.BumpCounter ();
+
+ if (gGremlinSaveFrequency != 0 &&
+ (Hordes::EventCounter () % gGremlinSaveFrequency) == 0)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleAutoSaveState ();
+ }
+
+ if (Hordes::EventLimit () > 0 &&
+ Hordes::EventLimit () == Hordes::EventCounter ())
+ {
+ EmAssert (gSession);
+ gSession->ScheduleSaveSuspendedState ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::CanSwitchToApp
+ *
+ * DESCRIPTION: Returns whether the Horde can switch to the given Palm
+ * app
+ *
+ * PARAMETERS: cardNo \ Palm application info
+ * dbID /
+ *
+ * RETURNED: TRUE if the designated Palm app can be run by the Horde
+ * FALSE otherwise
+ *
+ ***********************************************************************/
+
+Bool
+Hordes::CanSwitchToApp (UInt16 cardNo, LocalID dbID)
+{
+ if (gGremlinAppList.size () == 0)
+ return true;
+
+ DatabaseInfoList appList = Hordes::GetAppList ();
+ DatabaseInfoList::iterator iter = appList.begin ();
+
+ while (iter != appList.end ())
+ {
+ DatabaseInfo& dbInfo = *iter++;
+
+ if (dbInfo.cardNo == cardNo && dbInfo.dbID == dbID)
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SetGremlinsHome
+ *
+ * DESCRIPTION: Indicates the directory in which the user would like
+ * his Horde files to collect.
+ *
+ * PARAMETERS: gremlinsHome - the name of the directory
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::SetGremlinsHome (const EmDirRef& gremlinsHome)
+{
+ gHomeForHordesFiles = gremlinsHome;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SetGremlinsHomeToDefault
+ *
+ * DESCRIPTION: Indicates that the user would like his Horde files to
+ * collect in the default location.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::SetGremlinsHomeToDefault (void)
+{
+ gHomeForHordesFiles = EmDirRef ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::GetGremlinsHome
+ *
+ * DESCRIPTION: Returns the directory that the user would like to house
+ * his Horde state files.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: TRUE if gHomeForHordesFiles is defined;
+ * FALSE otherwise (use default).
+ *
+ ***********************************************************************/
+
+Bool
+Hordes::GetGremlinsHome (EmDirRef& outPath)
+{
+ // If we don't have anything, default to Poser home.
+
+ outPath = gHomeForHordesFiles;
+
+ // Try to create the path if it doesn't exist.
+
+ if (!gHomeForHordesFiles.Exists ())
+ {
+ gHomeForHordesFiles.Create ();
+ }
+
+ // Return whether or not we succeeded.
+
+ return gHomeForHordesFiles.Exists ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::AutoSaveState
+ *
+ * DESCRIPTION: Creates a file reference to where the auto-saved state
+ * should be saved. Then calls a platform-specific
+ * routine to do the actual saving.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::AutoSaveState (void)
+{
+ EmFileRef fileRef = Hordes::SuggestFileRef (kHordeAutoCurrentFile);
+
+ EmAssert (gSession);
+ gSession->Save (fileRef, false);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SaveRootState
+ *
+ * DESCRIPTION: Creates a file reference to where the state
+ * should be saved. Then calls a platform-specific
+ * routine to do the actual saving.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::SaveRootState (void)
+{
+ EmFileRef fileRef = Hordes::SuggestFileRef (kHordeRootFile);
+
+ Bool hordesWasOn = Hordes::IsOn ();
+
+ if (hordesWasOn != false)
+ Hordes::TurnOn (false);
+
+ EmAssert (gSession);
+ gSession->Save (fileRef, false);
+
+ Hordes::TurnOn (hordesWasOn);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::LoadState
+ *
+ * DESCRIPTION: Does the work of loading a state while Hordes is running.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode
+Hordes::LoadState (const EmFileRef& ref)
+{
+ ErrCode returnedErrCode = errNone;
+
+ try
+ {
+ EmAssert (gSession);
+ gSession->Load (ref);
+ }
+ catch (ErrCode errCode)
+ {
+ Hordes::TurnOn (false);
+
+ Errors::SetParameter ("%filename", ref.GetName ());
+ Errors::ReportIfError (kStr_CmdOpen, errCode, 0, true);
+
+ returnedErrCode = errCode;
+ }
+
+ return returnedErrCode;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::LoadRootState
+ *
+ * DESCRIPTION: Creates a file reference to where the root state
+ * should be loaded. Then calls a
+ * routine to do the actual loading.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode
+Hordes::LoadRootState (void)
+{
+ EmFileRef fileRef = Hordes::SuggestFileRef (kHordeRootFile);
+
+ ErrCode result = Hordes::LoadState (fileRef);
+
+ if (result == 0)
+ {
+ // There are no events to load, but we need to make sure we at
+ // least clear out any old events.
+
+ EmEventPlayback::Clear ();
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SaveSuspendedState
+ *
+ * DESCRIPTION: Creates a file reference to where the suspended state
+ * should be saved. Then calls a platform-specific
+ * routine to do the actual saving.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::SaveSuspendedState (void)
+{
+ EmFileRef fileRef = Hordes::SuggestFileRef (kHordeSuspendFile);
+
+ gSession->Save (fileRef, false);
+
+ // This sort of overloads the function, but right now, any time we
+ // save the suspend state, we also want to save any recorded events.
+
+ Hordes::SaveEvents ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::LoadSuspendedState
+ *
+ * DESCRIPTION: Creates a file reference to where the suspended state
+ * should be loaded. Then calls a routine to do the actual
+ * loading.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode
+Hordes::LoadSuspendedState (void)
+{
+ EmFileRef fileRef = Hordes::SuggestFileRef (kHordeSuspendFile);
+
+ ErrCode result = Hordes::LoadState (fileRef);
+
+ if (result == 0)
+ {
+ // Load the events from the associated file holding them. Do this
+ // *after* Hordes::LoadState, as gSession->Load will try to load
+ // events from *its* file, overwriting the ones in our holding file.
+ //
+ // Note also that we load events in LoadSuspendedState but not
+ // LoadRootState, as there should not be any events associated
+ // with the root state (none have been generated!).
+
+ Hordes::LoadEvents ();
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::SaveEvents
+ *
+ * DESCRIPTION: Write out the current set of events to the designated
+ * event file. This file contains the root (initial)
+ * Gremlin state, to which we append the events.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::SaveEvents (void)
+{
+ EmFileRef eventRef = Hordes::SuggestFileRef (kHordeEventFile);
+
+ EmStreamFile eventStream (eventRef, kCreateOrEraseForWrite,
+ kFileCreatorEmulator, kFileTypeEvents);
+ ChunkFile eventChunkFile (eventStream);
+ SessionFile eventSessionFile (eventChunkFile);
+
+ // Copy over the root state to the session file, first.
+
+ EmFileRef rootRef = Hordes::SuggestFileRef (kHordeRootFile);
+ EmStreamFile rootStream (rootRef, kOpenExistingForRead,
+ kFileCreatorEmulator, kFileTypeEvents);
+
+ {
+ int32 length = rootStream.GetLength ();
+ ByteList buffer (length);
+ rootStream.GetBytes (&buffer[0], length);
+ eventStream.PutBytes (&buffer[0], length);
+ }
+
+ // Finally, write the events to the file.
+
+ EmEventPlayback::SaveEvents (eventSessionFile);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::LoadEvents
+ *
+ * DESCRIPTION: Load the events from the current event file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+Hordes::LoadEvents (void)
+{
+ EmFileRef eventRef = Hordes::SuggestFileRef (kHordeEventFile);
+
+ EmStreamFile stream (eventRef, kOpenExistingForRead,
+ kFileCreatorEmulator, kFileTypeEvents);
+ ChunkFile chunkFile (stream);
+ SessionFile eventFile (chunkFile);
+
+ EmEventPlayback::LoadEvents (eventFile);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::StartLog
+ *
+ * DESCRIPTION: Starts Hordes logging
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: none
+ *
+ ***********************************************************************/
+
+void
+Hordes::StartLog (void)
+{
+ LogClear ();
+ LogStartNew ();
+
+ LogAppendMsg ("********************************************************************************");
+ LogAppendMsg ("************* Gremlin Hordes started");
+ LogAppendMsg ("********************************************************************************");
+ LogAppendMsg ("Running Gremlins %ld to %ld", gGremlinStartNumber, gGremlinStopNumber);
+
+ if (gSwitchDepth != -1)
+ LogAppendMsg ("Will run each Gremlin %ld events at a time until all Gremlins have terminated in error", gSwitchDepth);
+
+ else
+ LogAppendMsg ("Will run each Gremlin until all Gremlins have terminated in error", gSwitchDepth);
+
+ if (gMaxDepth != -1)
+ LogAppendMsg ("or have reached a maximum of %ld events", gMaxDepth);
+
+ LogAppendMsg ("********************************************************************************");
+
+ LogDump ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Hordes::GetGremlinDirectory
+ *
+ * DESCRIPTION: Return an EmDirRef for directory where information
+ * about the current Gremlin is saved.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The desired EmDirRef.
+ *
+ ***********************************************************************/
+
+EmDirRef
+Hordes::GetGremlinDirectory (void)
+{
+ // If requested, create the directory to use.
+
+ if (gForceNewHordesDirectory)
+ {
+ gForceNewHordesDirectory = false;
+
+ time_t now_time;
+ time (&now_time);
+ struct tm* now_tm = localtime (&now_time);
+
+ char buffer[30];
+ strftime (buffer, countof (buffer), "%Y-%m-%d.%H-%M-%S", now_tm); // 19 chars + NULL
+
+ char stateName[30];
+ sprintf (stateName, "Gremlins.%s", buffer);
+
+ EmAssert (strlen(stateName) <= 31); // Max on Macs
+
+ EmDirRef homeDir;
+
+ if (!Hordes::GetGremlinsHome (homeDir))
+ {
+ homeDir = EmDirRef::GetEmulatorDirectory ();
+ }
+
+ gGremlinDir = EmDirRef (homeDir, stateName);
+
+ if (!gGremlinDir.Exists ())
+ {
+ try
+ {
+ gGremlinDir.Create ();
+ }
+ catch (...)
+ {
+ // !!! Put up some error message
+
+ gGremlinDir = EmDirRef ();
+ }
+ }
+ }
+
+ // Otherwise, return the previously specified directory.
+
+ return gGremlinDir;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Hordes::UseNewAutoSaveDirectory
+// ---------------------------------------------------------------------------
+
+void Hordes::UseNewAutoSaveDirectory (void)
+{
+ gForceNewHordesDirectory = true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Hordes::ComputeStatistics
+// ---------------------------------------------------------------------------
+
+void Hordes::ComputeStatistics (int32 &min,
+ int32 &max,
+ int32 &avg,
+ int32 &stdDev,
+ int32 &smallErrorIndex)
+{
+ // I'm worried about overflow, but in practice this should be sufficiently large
+
+ int32 sum = 0;
+
+ // this is the largest value possible with an int32; it is effectively infinity
+
+ min = 0x7FFFFFFF;
+ max = 0;
+
+ // initialize this to a sentinel value
+
+ smallErrorIndex = 0x7FFFFFFF;
+
+ int32 numEventsToErr = 0;
+ int32 counter = 0;
+ int32 errorCounter = 0;
+
+ EmAssert (gGremlinStartNumber <= gGremlinStopNumber);
+
+ for (counter = gGremlinStartNumber; counter <= gGremlinStopNumber; counter++)
+ {
+ numEventsToErr = gGremlinHaltedInError[counter].fErrorEvent;
+ sum += numEventsToErr;
+
+ if (numEventsToErr > max)
+ {
+ max = numEventsToErr;
+ }
+
+ if (numEventsToErr < min && numEventsToErr > 0)
+ {
+ min = numEventsToErr;
+ }
+
+ if (numEventsToErr != 0)
+ {
+ errorCounter++;
+
+ if ((smallErrorIndex == 0x7FFFFFFF) ||
+ (numEventsToErr < gGremlinHaltedInError[smallErrorIndex].fErrorEvent))
+ {
+ smallErrorIndex = counter;
+ }
+ }
+ }
+
+ if (sum > 0 && errorCounter > 0)
+ {
+ avg = sum / errorCounter;
+ }
+ else
+ {
+ avg = 0;
+ stdDev = 0;
+
+ return;
+ }
+
+ // now to calculate the standard deviation
+
+ int32 diffSquaredSum = 0;
+
+ for (counter = gGremlinStartNumber; counter <= gGremlinStopNumber; counter++)
+ {
+ numEventsToErr = gGremlinHaltedInError[counter].fErrorEvent - avg;
+ diffSquaredSum += (numEventsToErr * numEventsToErr);
+ }
+
+ // I'm assuming that MAXGREMLINS is not 0. Since it is defined, and
+ // constant, I think this is a safe assumption.
+
+ diffSquaredSum /= MAXGREMLINS; // total - 1
+
+ stdDev = (int32) sqrt (diffSquaredSum);
+
+ return;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Hordes::GremlinReport
+// ---------------------------------------------------------------------------
+
+void Hordes::GremlinReport (void)
+{
+ int32 counter = 0;
+ int32 lastSmallIndex = 0;
+ int32 numGremlinsWithError = 0;
+ int32 highestFrequency = 1;
+
+ // We want a table of sorts showing all of the errors encountered,
+ // sorted by frequency. Errors that didn't crop up will be omitted,
+ // as they are uninteresting. Alongside each error will be the count
+ // of how many discrete Gremlins terminated with the error, and the
+ // Gremlin number of the offender which terminated after the least
+ // number of events. The errors that will be handled have their
+ // constants defined in Strings.r.h
+
+ // There are several interesting problems to deal with: the error
+ // distribution, as compared to the number of Gremlins that were run,
+ // is likely to be quite low; we would like to come up with the
+ // Gremlin that terminates quickest, for each error; and we would like
+ // to know which error is most prevalent.
+
+ // According to Strings.r.h, error codes will be in the range {1000, 1199}.
+ // Let's set up some offsets, and an array that will eventually hold
+ // the error prevalence data.
+
+ const int32 errorBase = 1000;
+ const int32 errorLast = 1199;
+
+ EmGremlinErrorFrequencyInfo errorCountArray [errorLast - errorBase + 1];
+
+ // Let's initialize the array, using the offset notation that will be
+ // used further on, just to be consistent. The first field will contain
+ // the count of the error, the second will contain the Gremlin that
+ // terminated quickest with the error.
+
+ for (counter = errorBase; counter <= errorLast; counter++)
+ {
+ errorCountArray [counter - errorBase].fCount = 0;
+ errorCountArray [counter - errorBase].fErrorFrequency = 0;
+
+ // sentinel value, so that we know that we haven't seen this error before
+
+ errorCountArray [counter - errorBase].fFirstErrantGremlinIndex = -1;
+ }
+
+ // Now let's walk through the gGremlinHaltedInError array, and for each
+ // Gremlin that terminated in error, increment the error count for the
+ // appropriate error
+
+ int32 errorTypeNumber = 0;
+ int32 temp = 0;
+
+ EmAssert (gGremlinStartNumber <= gGremlinStopNumber);
+ for (counter = gGremlinStartNumber; counter <= gGremlinStopNumber; counter++)
+ {
+ if (gGremlinHaltedInError[counter].fHalted != false)
+ {
+ errorTypeNumber = gGremlinHaltedInError[counter].fMessageID - errorBase;
+
+ errorCountArray[errorTypeNumber].fErrorFrequency += 1;
+ numGremlinsWithError += 1;
+
+ // if we have not seen this error before, then this Gremlin's index
+ // is, by definition, the index of the Gremlin which terminated first
+ // with this error.
+
+ lastSmallIndex = errorCountArray[errorTypeNumber].fFirstErrantGremlinIndex;
+
+ if (lastSmallIndex == -1)
+ {
+ errorCountArray[errorTypeNumber].fCount = gGremlinHaltedInError[counter].fErrorEvent;
+ errorCountArray[errorTypeNumber].fFirstErrantGremlinIndex = counter;
+ }
+
+ // otherwise, we have seen this error before, so check whether this
+ // Gremlin terminated before the last frontrunner did.
+
+ else
+ {
+ highestFrequency += 1;
+
+ temp = gGremlinHaltedInError[counter].fErrorEvent;
+
+ if (temp < gGremlinHaltedInError[lastSmallIndex].fErrorEvent)
+ {
+ errorCountArray[errorTypeNumber].fCount = temp;
+ errorCountArray[errorTypeNumber].fFirstErrantGremlinIndex = counter;
+ }
+ }
+ }
+ }
+
+ // So now we have an array filled with the number of times each error occurred,
+ // and the # of the first-offending Gremlin. Now all that remains is to sort
+ // the errors by their frequency, and then output our results. Some vital
+ // information about the frequencies: their sum is numGremlinsWithError, and
+ // the highest frequency of any single error is <= the number of Gremlins with
+ // errors - 2 * the number of discrete errors that occurred multiple times.
+ // With these constraints in mind, this following algorithm, ostensibly n^2
+ // time, is in reality of managable time since n is constrained as above.
+ // Why I am doing this is because I don't think that n is sufficiently large
+ // to warrant the overhead of a quicksort, and because I don't feel like
+ // writing a quicksort for a multi-dimensional array.
+
+ if (numGremlinsWithError == 0)
+ {
+ return;
+ }
+
+ LogAppendMsg ("%d of %d Gremlins terminated in error.", numGremlinsWithError,
+ gGremlinStopNumber - gGremlinStartNumber + 1);
+ LogAppendMsg ("");
+ LogAppendMsg ("Count Error name Shortest Gremlin Events");
+
+ int32 errorNumber = 0;
+ int32 frequency = 0;
+ string str;
+
+ // We only go down to 1, since we don't care about the errors that didn't
+ // occur.
+
+ for (frequency = highestFrequency;
+ frequency > 0;
+ frequency--)
+ {
+ for (errorNumber = errorBase; errorNumber <= errorLast; errorNumber++)
+ {
+ if (errorCountArray[errorNumber - errorBase].fErrorFrequency == frequency)
+ {
+ str = Hordes::TranslateErrorCode (errorNumber);
+ LogAppendMsg ("%-4d %-29s Gremlin #%-3d %-4d",
+ frequency,
+ str.c_str (),
+ errorCountArray[errorNumber - errorBase].fFirstErrantGremlinIndex,
+ errorCountArray[errorNumber - errorBase].fCount);
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Hordes::GetAppList
+// ---------------------------------------------------------------------------
+// Return the of applications that can be run under this Gremlin.
+
+DatabaseInfoList Hordes::GetAppList (void)
+{
+ // If it looks like some of the fields need to filled out,
+ // then do that now (some versions of Poser saved only the
+ // creator, type, and version fields, leaving the others blank
+ // -- we have to put back that information now).
+
+ if (gGremlinAppList.size () > 0 && gGremlinAppList.front ().dbID == 0)
+ {
+ // Get the list of applications.
+
+ DatabaseInfoList appList;
+ ::GetDatabases (appList, kApplicationsOnly);
+
+ // Iterate over all the allowed Gremlins applications and all the
+ // installed applications, and use information in the latter to
+ // fill in the former.
+
+ DatabaseInfoList::iterator gremlin_iter = gGremlinAppList.begin ();
+ while (gremlin_iter != gGremlinAppList.end ())
+ {
+ DatabaseInfoList::iterator installed_iter = appList.begin ();
+ while (installed_iter != appList.end ())
+ {
+ if (gremlin_iter->creator == installed_iter->creator &&
+ gremlin_iter->type == installed_iter->type &&
+ gremlin_iter->version == installed_iter->version)
+ {
+ *gremlin_iter = *installed_iter;
+ break;
+ }
+
+ ++installed_iter;
+ }
+
+ ++gremlin_iter;
+ }
+ }
+
+ return gGremlinAppList;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Hordes::TranslateErrorCode
+// ---------------------------------------------------------------------------
+
+string Hordes::TranslateErrorCode (UInt32 errCode)
+{
+ switch (errCode)
+ {
+ case kStr_OpError:
+ return "OpError";
+ break;
+
+ case kStr_OpErrorRecover:
+ return "OpErrorRecover";
+ break;
+
+ case kStr_ErrBusError:
+ return "ErrBusError";
+ break;
+
+ case kStr_ErrAddressError:
+ return "ErrAddressError";
+ break;
+
+ case kStr_ErrIllegalInstruction:
+ return "ErrIllegalInstruction";
+ break;
+
+ case kStr_ErrDivideByZero:
+ return "ErrDivideByZero";
+ break;
+
+ case kStr_ErrCHKInstruction:
+ return "ErrCHKInstruction";
+ break;
+
+ case kStr_ErrTRAPVInstruction:
+ return "ErrTRAPVInstruction";
+ break;
+
+ case kStr_ErrPrivilegeViolation:
+ return "ErrPrivilegeViolation";
+ break;
+
+ case kStr_ErrTrace:
+ return "ErrTrace";
+ break;
+
+ case kStr_ErrATrap:
+ return "ErrATrap";
+ break;
+
+ case kStr_ErrFTrap:
+ return "ErrFTrap";
+ break;
+
+ case kStr_ErrTRAPx:
+ return "ErrTRAPx";
+ break;
+
+ case kStr_ErrStorageHeap:
+ return "ErrStorageHeap";
+ break;
+
+ case kStr_ErrNoDrawWindow:
+ return "ErrNoDrawWindow";
+ break;
+
+ case kStr_ErrNoGlobals:
+ return "ErrNoGlobals";
+ break;
+
+ case kStr_ErrSANE:
+ return "ErrSANE";
+ break;
+
+ case kStr_ErrTRAP0:
+ return "ErrTRAP0";
+ break;
+
+ case kStr_ErrTRAP8:
+ return "ErrTRAP8";
+ break;
+
+ case kStr_ErrStackOverflow:
+ return "ErrStackOverflow";
+ break;
+
+ case kStr_ErrUnimplementedTrap:
+ return "ErrUnimplementedTrap";
+ break;
+
+ case kStr_ErrInvalidRefNum:
+ return "ErrInvalidRefNum";
+ break;
+
+ case kStr_ErrCorruptedHeap:
+ return "ErrCorruptedHeap";
+ break;
+
+ case kStr_ErrInvalidPC1:
+ return "ErrInvalidPC1";
+ break;
+
+ case kStr_ErrInvalidPC2:
+ return "ErrInvalidPC2";
+ break;
+
+ case kStr_ErrLowMemory:
+ return "ErrLowMemory";
+ break;
+
+ case kStr_ErrSystemGlobals:
+ return "ErrSystemGlobals";
+ break;
+
+ case kStr_ErrScreen:
+ return "ErrScreen";
+ break;
+
+ case kStr_ErrHardwareRegisters:
+ return "ErrHardwareRegisters";
+ break;
+
+ case kStr_ErrROM:
+ return "ErrROM";
+ break;
+
+ case kStr_ErrMemMgrStructures:
+ return "ErrMemMgrStructures";
+ break;
+
+ case kStr_ErrMemMgrSemaphore:
+ return "ErrMemMgrSemaphore";
+ break;
+
+ case kStr_ErrFreeChunk:
+ return "ErrFreeChunk";
+ break;
+
+ case kStr_ErrUnlockedChunk:
+ return "ErrUnlockedChunk";
+ break;
+
+ case kStr_ErrLowStack:
+ return "ErrLowStack";
+ break;
+
+ case kStr_ErrStackFull:
+ return "ErrStackFull";
+ break;
+
+ case kStr_ErrSizelessObject:
+ return "ErrSizelessObject";
+ break;
+
+ case kStr_ErrOffscreenObject:
+ return "ErrOffscreenObject";
+ break;
+
+ case kStr_ErrFormAccess:
+ return "ErrFormAccess";
+ break;
+
+ case kStr_ErrFormObjectListAccess:
+ return "ErrFormObjectListAccess";
+ break;
+
+ case kStr_ErrFormObjectAccess:
+ return "ErrFormObjectAccess";
+ break;
+
+ case kStr_ErrWindowAccess:
+ return "ErrWindowAccess";
+ break;
+
+ case kStr_ErrBitmapAccess:
+ return "ErrBitmapAccess";
+ break;
+
+ case kStr_ErrProscribedFunction:
+ return "ErrProscribedFunction";
+ break;
+
+ case kStr_ErrStepSpy:
+ return "ErrStepSpy";
+ break;
+
+ case kStr_ErrWatchpoint:
+ return "ErrWatchpoint";
+ break;
+
+ case kStr_ErrSysFatalAlert:
+ return "ErrSysFatalAlert";
+ break;
+
+ case kStr_ErrDbgMessage:
+ return "ErrDbgMessage";
+ break;
+
+ case kStr_BadChecksum:
+ return "BadChecksum";
+ break;
+
+ case kStr_UnknownDeviceWarning:
+ return "UnknownDeviceWarning";
+ break;
+
+ case kStr_UnknownDeviceError:
+ return "UnknownDeviceError";
+ break;
+
+ case kStr_MissingSkins:
+ return "MissingSkins";
+ break;
+
+ case kStr_InconsistentDatabaseDates:
+ return "InconsistentDatabaseDates";
+ break;
+
+ case kStr_NULLDatabaseDate:
+ return "NULLDatabaseDate";
+ break;
+
+ case kStr_NeedHostFS:
+ return "NeedHostFS";
+ break;
+
+ case kStr_InvalidAddressNotEven:
+ return "InvalidAddressNotEven";
+ break;
+
+ case kStr_InvalidAddressNotInROMOrRAM:
+ return "InvalidAddressNotInROMOrRAM";
+ break;
+
+ case kStr_CannotParseCondition:
+ return "CannotParseCondition";
+ break;
+
+ case kStr_UserNameTooLong:
+ return "UserNameTooLong";
+ break;
+
+ case kStr_ErrMemoryLeak:
+ return "ErrMemoryLeak";
+ break;
+
+ case kStr_ErrMemoryLeaks:
+ return "ErrMemoryLeaks";
+ break;
+
+ default:
+ EmAssert (false);
+ }
+
+ return "";
+}
+
diff --git a/SrcShared/Hordes.h b/SrcShared/Hordes.h
new file mode 100644
index 0000000..bbf6bd0
--- /dev/null
+++ b/SrcShared/Hordes.h
@@ -0,0 +1,153 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _HORDES_H_
+#define _HORDES_H_
+
+#include "EmStructs.h" // HordeInfo, DatabaseInfoList
+#include "EmTypes.h" // ErrCode
+#include "CGremlins.h" // GremlinEventType
+
+
+enum HordeFileType
+{
+ kHordeProgressFile = 0x00,
+ kHordeRootFile = 0x01,
+ kHordeSuspendFile = 0x02,
+ kHordeEventFile = 0x03,
+ kHordeMinimalEventFile = 0x04,
+ kHordeAutoCurrentFile = 0x05
+};
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////
+// HORDES CLASS
+
+class SessionFile;
+
+// Gremlins::Save, Gremlins::Load
+extern long gGremlinSaveFrequency;
+extern DatabaseInfoList gGremlinAppList;
+
+extern Bool gWarningHappened;
+extern Bool gErrorHappened;
+
+class Hordes
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void New (const HordeInfo& info);
+
+ // Support to run a "horde" of just a single Gremlin -- for example, from a session
+ // file load, or from a UI only supporting single Gremlins. "Gremlins classic":
+
+ static void NewGremlin (const GremlinInfo& info);
+
+ static void SaveSearchProgress (void);
+ static void ResumeSearchProgress (const EmFileRef& f);
+
+ static Bool IsOn (void);
+ static Bool InSingleGremlinMode (void);
+ static Bool QuitWhenDone (void);
+
+ static Bool CanNew (void);
+ static Bool CanSuspend (void);
+ static Bool CanStep (void);
+ static Bool CanResume (void);
+ static Bool CanStop (void);
+
+ static void Status (unsigned short* currentNumber,
+ unsigned long* currentStep,
+ unsigned long* currentUntil);
+
+ static void TurnOn (Bool hordesOn);
+
+ static int32 GremlinNumber (void);
+ static int32 EventCounter (void);
+ static int32 EventLimit (void);
+
+ static void StopEventReached (void);
+ static void ErrorEncountered (void);
+ static void RecordErrorStats (StrCode messageID = -1);
+
+ static void Suspend (void);
+ static void Step (void);
+ static void Resume (void);
+ static void Stop (void);
+
+ static string SuggestFileName (HordeFileType category, uint32 num = 0);
+ static EmFileRef SuggestFileRef (HordeFileType category, uint32 num = 0);
+
+ static void PostLoad (void);
+
+ static Bool PostFakeEvent (void);
+ static void PostFakePenEvent (void);
+ static Bool SendCharsToType (void);
+ static void BumpCounter (void);
+
+ static uint32 ElapsedMilliseconds (void);
+
+ static Bool CanSwitchToApp (UInt16 cardNo, LocalID dbID);
+
+ static void SetGremlinsHome (const EmDirRef& gremlinsHome);
+ static void SetGremlinsHomeToDefault(void);
+ static Bool GetGremlinsHome (EmDirRef& outPath);
+
+ static void AutoSaveState (void);
+ static void SaveSuspendedState (void);
+ static void SaveRootState (void);
+ static ErrCode LoadRootState (void);
+ static ErrCode LoadSuspendedState (void);
+
+ static void LoadEvents (void);
+ static void SaveEvents (void);
+
+ static void StartGremlinFromLoadedRootState (void);
+ static void StartGremlinFromLoadedSuspendedState(void);
+ static void SetGremlinStatePathFromControlFile (EmFileRef& controlFile);
+
+ static EmDirRef GetGremlinDirectory (void);
+ static void UseNewAutoSaveDirectory (void);
+ static DatabaseInfoList GetAppList (void);
+
+ static string TranslateErrorCode (UInt32 errCode);
+
+ private:
+ static void NextGremlin();
+ static void ProposeNextGremlin (long& outNextGremlin,
+ long& outNextDepth,
+ long inFromGremlin,
+ long inFromDepth);
+ static void EndHordes (void);
+
+ static ErrCode LoadState (const EmFileRef& ref);
+
+ static void StartLog (void);
+ static string GremlinsFlagsToString (void);
+ static void GremlinsFlagsFromString (string& inFlags);
+ static void ComputeStatistics (int32 &min,
+ int32 &max,
+ int32 &avg,
+ int32 &stdDev,
+ int32 &smallErrorIndex);
+ static void GremlinReport (void);
+};
+
+#endif /* _HORDES_H_ */
+
diff --git a/SrcShared/HostControl.cpp b/SrcShared/HostControl.cpp
new file mode 100644
index 0000000..7cb505e
--- /dev/null
+++ b/SrcShared/HostControl.cpp
@@ -0,0 +1,4989 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "HostControl.h"
+#include "HostControlPrv.h"
+
+#include "DebugMgr.h" // gDebuggerGlobals
+#include "EmApplication.h" // gApplication, ScheduleQuit
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmCPU68K.h" // gCPU68K, gStackHigh, etc.
+#include "EmDirRef.h" // EmDirRefList
+#include "EmDlg.h" // DoGetFile, DoPutFile, DoGetDirectory
+#include "EmDocument.h" // gDocument, HostSaveScreen, ScheduleNewHorde
+#include "EmErrCodes.h" // kError_NoError
+#include "EmExgMgr.h" // EmExgMgr::GetExgMgr
+#include "EmFileImport.h" // EmFileImport::LoadPalmFileList
+#include "EmFileRef.h" // EmFileRefList
+#include "EmMemory.h" // EmMem_strlen, EmMem_strcpy
+#include "EmPalmStructs.h" // EmAliasErr
+#include "EmPatchState.h" // EmPatchState::UIInitialized
+#include "EmRPC.h" // RPC::HandlingPacket, RPC::DeferCurrentPacket
+#include "EmSession.h" // ResumeByExternal
+#include "EmStreamFile.h" // EmStreamFile
+#include "EmStructs.h" // StringList, ByteList
+#include "Hordes.h" // Hordes::IsOn
+#include "LoadApplication.h" // SavePalmFile
+#include "Logging.h" // LogFile
+#include "Miscellaneous.h" // GetDeviceTextList, GetMemoryTextList
+#include "Platform.h" // Platform::GetShortVersionString
+#include "Profiling.h" // ProfileInit, ProfileStart, ProfileStop, etc.
+#include "ROMStubs.h" // EvtWakeup
+#include "Strings.r.h" // kStr_ProfileResults
+
+#include <ctype.h> // isdigit
+
+#if HAS_TRACER
+#include "TracerPlatform.h" // Tracer
+#endif
+
+
+#include "EmSubroutine.h"
+#include "Marshal.h"
+
+#define CALLED_GET_PARAM_FILE(name) \
+ CALLED_GET_PARAM_VAL (emuptr, name); \
+ \
+ FILE* fh = PrvToFILE (name)
+
+
+#if PLATFORM_WINDOWS
+
+#include <direct.h> // _mkdir, _rmdir
+#include <sys/types.h> //
+#include <sys/stat.h> // struct _stat
+#include <sys/utime.h> // _utime, _utimbuf
+#include <io.h> // _open
+#include <fcntl.h> // O_RDWR
+#include <time.h> // asctime, clock, clock_t, etc.
+
+typedef struct _stat _stat_;
+typedef struct _utimbuf _utimbuf_;
+
+#else
+
+#include "sys/stat.h" // mkdir(???), stat
+#include "unistd.h" // rmdir
+#include "fcntl.h" // O_RDWR
+#include "utime.h" // utime
+#include <time.h> // asctime, clock, clock_t, etc.
+#include "errno.h" // EACCES
+
+
+#define _O_RDWR O_RDWR
+
+typedef struct stat _stat_;
+typedef struct utimbuf _utimbuf_;
+
+inline int _mkdir (const char* path)
+{
+#if PLATFORM_MAC
+ return mkdir (path);
+#else
+ return mkdir (path, 0777);
+#endif
+}
+
+inline int _rmdir (const char* path)
+{
+ return rmdir (path);
+}
+
+inline int _stat (const char * path, struct stat * buf)
+{
+ return stat (path, buf);
+}
+
+inline int _open (const char * path, int mode)
+{
+ return open (path, mode);
+}
+
+inline int _chsize (int s, off_t offset)
+{
+ return ftruncate (s, offset);
+}
+
+inline int _close (int s)
+{
+ return close (s);
+}
+
+inline int _utime (const char * path, const utimbuf * times)
+{
+ return utime (path, times);
+}
+
+#endif
+
+struct MyDIR
+{
+ EmDirRefList fDirs;
+ EmFileRefList fFiles;
+
+ EmDirRefList::iterator fDirIter;
+ EmFileRefList::iterator fFileIter;
+
+ int fState; // 0 = new, 1 = iterating dirs, 2 = iterating files, 3 = done
+};
+
+
+typedef void (*HostHandler) (void);
+
+static HostHandler PrvHostGetHandler (HostControlSelectorType selector);
+
+static Bool PrvCollectParameters (EmSubroutine& sub, const string& fmt,
+ ByteList& stackData, StringList& stringData);
+static void PrvPushShort (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushLong (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushDouble (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushLongDouble (EmSubroutine& sub, ByteList& stackData);
+static void PrvPushString (EmSubroutine& sub, ByteList& stackData,
+ StringList& stringData);
+
+static FILE* PrvToFILE (emuptr);
+
+static void PrvTmFromHostTm (struct tm& dest, const HostTmType& src);
+static void PrvHostTmFromTm (EmProxyHostTmType& dest, const struct tm& src);
+
+static void PrvMapAndReturn (const void* p, long size, EmSubroutine& sub);
+static void PrvMapAndReturn (const string& s, EmSubroutine& sub);
+static void PrvReturnString (const char* p, EmSubroutine& sub);
+static void PrvReturnString (const string& s, EmSubroutine& sub);
+
+static void PrvReleaseAllResources (void);
+
+static emuptr PrvMalloc (long size);
+static emuptr PrvRealloc (emuptr p, long size);
+static void PrvFree (emuptr p);
+
+
+// Write to this "file" if you want to intertwine your
+// output with that created by any host logging facilities
+// (such as event logging).
+
+#define hostLogFile ((HostFILEType*) -1)
+#define hostLogFILE ((FILE*) -1)
+
+
+inline int x_fclose (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return 0;
+ }
+
+ return fclose (f);
+}
+
+inline int x_feof (FILE* f)
+{
+ return feof (f);
+}
+
+inline int x_ferror (FILE* f)
+{
+ return ferror (f);
+}
+
+inline int x_fflush (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ LogDump ();
+ return 0;
+ }
+
+ return fflush (f);
+}
+
+inline int x_fgetc (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return EOF;
+ }
+
+ return fgetc (f);
+}
+
+inline char* x_fgets (char* s, int n, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return NULL;
+ }
+
+ return fgets (s, n, f);
+}
+
+inline int x_vfprintf (FILE* f, const char* fmt, va_list args)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->VPrintf (fmt, args);
+ }
+
+ return vfprintf (f, fmt, args);
+}
+
+inline int x_fputc (int c, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Printf ("%c", c);
+ }
+
+ return fputc (c, f);
+}
+
+inline int x_fputs (const char* s, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Printf ("%s", s);
+ }
+
+ return fputs (s, f);
+}
+
+inline size_t x_fread (void* buffer, size_t size, size_t count, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return 0;
+ }
+
+ return fread (buffer, size, count, f);
+}
+
+inline int x_fseek (FILE* f, long offset, int origin)
+{
+ if (f == hostLogFILE)
+ {
+ return -1;
+ }
+
+ return fseek (f, offset, origin);
+}
+
+inline long x_ftell (FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return -1;
+ }
+
+ return ftell (f);
+}
+
+inline size_t x_fwrite (const void* buffer, size_t size, size_t count, FILE* f)
+{
+ if (f == hostLogFILE)
+ {
+ return LogGetStdLog ()->Write (buffer, size * count);
+ }
+
+ return fwrite (buffer, size, count, f);
+}
+
+static int translate_err_no (int err_no)
+{
+ switch (err_no)
+ {
+ case 0: return hostErrNone;
+ case EACCES:
+ case EPERM: return hostErrPermissions;
+ case ENOENT: return hostErrFileNotFound;
+ case EIO: return hostErrDiskError;
+ case EBADF: return hostErrInvalidParameter;
+ case ENOMEM: return hostErrOutOfMemory;
+ case EFAULT: return hostErrInvalidParameter;
+ case EEXIST: return hostErrExists;
+ case ENOTDIR: return hostErrNotADirectory;
+ case EISDIR: return hostErrIsDirectory;
+ case EINVAL: return hostErrInvalidParameter;
+ case ENFILE:
+ case EMFILE: return hostErrTooManyFiles;
+ case EFBIG: return hostErrFileTooBig;
+ case ENOSPC: return hostErrDiskFull;
+ case EROFS: return hostErrReadOnlyFS;
+ case ENAMETOOLONG: return hostErrFileNameTooLong;
+ case ENOTEMPTY: return hostErrDirNotEmpty;
+ case ENOSYS:
+ case ENODEV: return hostErrOpNotAvailable;
+ default: return hostErrUnknownError;
+ }
+}
+
+HostHandler gHandlerTable [hostSelectorLastTrapNumber];
+
+vector<FILE*> gOpenFiles;
+vector<MyDIR*> gOpenDirs;
+vector<void*> gAllocatedBlocks;
+HostDirEntType gHostDirEnt;
+string gResultString;
+EmProxyHostTmType gGMTime;
+EmProxyHostTmType gLocalTime;
+
+
+// ---------------------------------------------------------------------------
+// ¥ HandleHostControlCall
+// ---------------------------------------------------------------------------
+
+CallROMType HandleHostControlCall (void)
+{
+ CALLED_SETUP ("UInt4", "HostControlSelectorType selector");
+
+ CALLED_GET_PARAM_VAL (HostControlSelectorType, selector);
+
+ HostHandler fn = PrvHostGetHandler (selector);
+
+ if (fn)
+ {
+ fn ();
+ }
+ else
+ {
+ // !!! Display an "unknown function" error message.
+ }
+
+ return kSkipROM;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostVersion
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostVersion (void)
+{
+ // long HostGetHostVersion (void)
+
+ CALLED_SETUP_HC ("Int32", "void");
+
+ enum { kMajor, kMinor, kFix, kBuild };
+
+ int major = 0;
+ int minor = 0;
+ int fix = 0;
+ int stage = sysROMStageRelease;
+ int buildNum = 0;
+ int state = kMajor;
+
+ string version (Platform::GetShortVersionString ());
+ string::iterator iter;
+
+ for (iter = version.begin (); iter != version.end (); ++iter)
+ {
+ char ch = *iter;
+
+ switch (state)
+ {
+ case kMajor:
+ if (isdigit (ch))
+ major = major * 10 + ch - '0';
+ else if (ch == '.')
+ state = kMinor;
+ else
+ goto VersionParseDone;
+ break;
+
+ case kMinor:
+ case kFix:
+ if (isdigit (ch))
+ {
+ if (state == kMinor)
+ minor = minor * 10 + ch - '0';
+ else
+ fix = fix * 10 + ch - '0';
+ }
+ else if (ch == '.')
+ {
+ if (state == kMinor)
+ state = kFix;
+ else
+ goto VersionParseDone;
+ }
+ else if (ch == 'd')
+ {
+ stage = sysROMStageDevelopment;
+ state = kBuild;
+ }
+ else if (ch == 'a')
+ {
+ stage = sysROMStageAlpha;
+ state = kBuild;
+ }
+ else if (ch == 'b')
+ {
+ stage = sysROMStageBeta;
+ state = kBuild;
+ }
+ else
+ goto VersionParseDone;
+ break;
+
+ case kBuild:
+ if (isdigit (ch))
+ buildNum = buildNum * 10 + ch - '0';
+ else
+ goto VersionParseDone;
+ break;
+ }
+ }
+
+VersionParseDone:
+
+ // Return the result.
+
+ Int32 result = sysMakeROMVersion (major, minor, fix, stage, buildNum);
+ PUT_RESULT_VAL (Int32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostID
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostID (void)
+{
+ // HostIDType HostGetHostID (void)
+
+ CALLED_SETUP_HC ("HostIDType", "void");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostIDType, hostIDPalmOSEmulator);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetHostPlatform
+// ---------------------------------------------------------------------------
+
+static void _HostGetHostPlatform (void)
+{
+ // HostPlatformType HostGetHostPlatform (void)
+
+ CALLED_SETUP_HC ("HostPlatformType", "void");
+
+ // Return the result.
+
+#if PLATFORM_WINDOWS
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformWindows);
+#elif PLATFORM_MAC
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformMacintosh);
+#elif PLATFORM_UNIX
+ PUT_RESULT_VAL (HostPlatformType, hostPlatformUnix);
+#else
+ #error "Unsupported platform"
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostIsSelectorImplemented
+// ---------------------------------------------------------------------------
+
+static void _HostIsSelectorImplemented (void)
+{
+ // HostBoolType HostIsSelectorImplemented (long selector)
+
+ CALLED_SETUP_HC ("HostBoolType", "long selector");
+
+ CALLED_GET_PARAM_VAL (long, selector);
+
+ HostHandler fn = PrvHostGetHandler ((HostControlSelectorType) selector);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostBoolType, (fn != NULL));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGestalt
+// ---------------------------------------------------------------------------
+
+static void _HostGestalt (void)
+{
+ // HostErrType HostGestalt (long gestSel, long* response)
+
+ CALLED_SETUP_HC ("HostErrType", "long gestSel, long* response");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrUnknownGestaltSelector);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostIsCallingTrap
+// ---------------------------------------------------------------------------
+
+static void _HostIsCallingTrap (void)
+{
+ // HostBoolType HostIsCallingTrap (void)
+
+ CALLED_SETUP_HC ("HostBoolType", "void");
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostBoolType, gSession->IsNested ());
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileInit
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileInit (void)
+{
+ // HostErrType HostProfileInit (long maxCalls, long maxDepth)
+
+ CALLED_SETUP_HC ("HostErrType", "long maxCalls, long maxDepth");
+
+ if (!::ProfileCanInit ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, maxCalls);
+ CALLED_GET_PARAM_VAL (long, maxDepth);
+
+ // Call the function.
+
+ ::ProfileInit (maxCalls, maxDepth);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileStart
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileStart (void)
+{
+ // HostErrType HostProfileStart (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanStart ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Call the function.
+
+ ::ProfileStart ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileStop
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileStop (void)
+{
+ // HostErrType HostProfileStop (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanStop ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Call the function.
+
+ ::ProfileStop ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileDump
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileDump (void)
+{
+ // HostErrType HostProfileDump (const char* filenameP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* filenameP");
+
+ if (!::ProfileCanDump ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, filenameP);
+
+ // Call the function.
+
+ ::ProfileDump (filenameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileCleanup
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileCleanup (void)
+{
+ // HostErrType HostProfileCleanup (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ if (!::ProfileCanInit ())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrProfilingNotReady);
+ return;
+ }
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ // ProfileCleanup is now performed at the end of a dump.
+// ::ProfileCleanup ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileDetailFn
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileDetailFn (void)
+{
+ // HostErrType _HostProfileDetailFn (void* addr, HostBoolType logDetails)
+
+ CALLED_SETUP_HC ("HostErrType", "void* addr, HostBoolType logDetails");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, addr);
+ CALLED_GET_PARAM_VAL (HostBoolType, logDetails);
+
+ // Call the function.
+
+ ProfileDetailFn (addr, logDetails);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, hostErrNone);
+}
+
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostProfileGetCycles
+// ---------------------------------------------------------------------------
+#if HAS_PROFILING
+
+static void _HostProfileGetCycles (void)
+{
+ // long HostProfileGetCycles(void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ // Get the caller's parameters.
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, gClockCycles);
+}
+
+#endif
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostErrNo
+// ---------------------------------------------------------------------------
+
+static void _HostErrNo (void)
+{
+ // long HostErrNo (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ // Get the caller's parameters.
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, translate_err_no (errno));
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFClose
+// ---------------------------------------------------------------------------
+
+static void _HostFClose (void)
+{
+ // long HostFClose (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fclose (fh);
+
+ vector<FILE*>::iterator iter = gOpenFiles.begin ();
+ while (iter != gOpenFiles.end ())
+ {
+ if (*iter == fh)
+ {
+ gOpenFiles.erase (iter);
+ break;
+ }
+
+ ++iter;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFEOF
+// ---------------------------------------------------------------------------
+
+static void _HostFEOF (void)
+{
+ // long HostFEOF (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, 1); // At end of file (right choice?)
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_feof (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFError
+// ---------------------------------------------------------------------------
+
+static void _HostFError (void)
+{
+ // long HostFError (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_ferror (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, translate_err_no (result));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFFlush
+// ---------------------------------------------------------------------------
+
+static void _HostFFlush (void)
+{
+ // long HostFFlush (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fflush (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetC
+// ---------------------------------------------------------------------------
+
+static void _HostFGetC (void)
+{
+ // long HostFGetC (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF); // No file, no data...
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fgetc (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetPos
+// ---------------------------------------------------------------------------
+
+static void _HostFGetPos (void)
+{
+ // long HostFGetPos (HostFILEType* fileP, long* posP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long* posP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_REF (long, posP, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (!fh || posP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ long pos = x_ftell (fh);
+
+ // If the function succeeded, return the position in
+ // the memory location pointed to by "posP".
+
+ if (pos >= 0) // success
+ {
+ *posP = pos;
+ CALLED_PUT_PARAM_REF (posP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, (pos == -1 ? 1 : 0));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFGetS
+// ---------------------------------------------------------------------------
+
+static void _HostFGetS (void)
+{
+ // char* HostFGetS (char* s, long n, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("char*", "char* s, long n, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (uint32, n);
+ CALLED_GET_PARAM_PTR (char, s, n, Marshal::kOutput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || s == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ emuptr returnVal = EmMemNULL;
+
+ if (n > 0)
+ {
+ char* result = x_fgets (s, (int) n, fh);
+
+ // If we were able to read the string, copy it into the
+ // user's buffer (using EmMem_strcpy to take care of real
+ // <-> emulated memory mapping. If the read failed,
+ // return NULL.
+
+ if (result != NULL)
+ {
+ CALLED_PUT_PARAM_REF (s);
+
+ returnVal = (emuptr) s;
+ }
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, returnVal);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFOpen
+// ---------------------------------------------------------------------------
+
+static void _HostFOpen (void)
+{
+ // HostFILEType* HostFOpen (const char* name, const char* mode)
+
+ CALLED_SETUP_HC ("HostFILEType*", "const char* name, const char* mode");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, name);
+ CALLED_GET_PARAM_STR (char, mode);
+
+ // Check the parameters.
+
+ if (name == EmMemNULL || mode == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ FILE* result = fopen (name, mode);
+
+ if (result)
+ {
+ gOpenFiles.push_back (result);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPrintF
+// ---------------------------------------------------------------------------
+
+static void _HostFPrintF (void)
+{
+ // long HostFPrintF (HostFILEType* fileP, const char* fmt, ...)
+
+ CALLED_SETUP_STDARG_HC ("long", "HostFILEType* fileP, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (!fh || fmt == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out to the file using vfprintf.
+
+ int result = x_vfprintf (fh, fmt, (va_list) &stackData[0]);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPutC
+// ---------------------------------------------------------------------------
+
+static void _HostFPutC (void)
+{
+ // long HostFPutC (long c, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "long c, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, c);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fputc ((int) c, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFPutS
+// ---------------------------------------------------------------------------
+
+static void _HostFPutS (void)
+{
+ // long HostFPutS (const char* s, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "const char* s, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, s);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || s == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, EOF);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fputs (s, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFRead
+// ---------------------------------------------------------------------------
+
+static void _HostFRead (void)
+{
+ // long HostFRead (void* buffer, long size, long count, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "void* buffer, long size, long count, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+ CALLED_GET_PARAM_VAL (long, count);
+ CALLED_GET_PARAM_PTR (void, buffer, size * count, Marshal::kOutput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || buffer == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 0);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ size_t result = x_fread (buffer, size, count, fh);
+
+ // If the read succeeded, copy the data into the user's buffer.
+
+ if (result)
+ {
+ CALLED_PUT_PARAM_REF (buffer);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFReopen
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostFReopen (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFScanF
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostFScanF (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFSeek
+// ---------------------------------------------------------------------------
+
+static void _HostFSeek (void)
+{
+ // long HostFSeek (HostFILEType* fileP, long offset, long origin)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long offset, long origin");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_VAL (long, offset);
+ CALLED_GET_PARAM_VAL (long, origin);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fseek (fh, offset, (int) origin);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFSetPos
+// ---------------------------------------------------------------------------
+
+static void _HostFSetPos (void)
+{
+ // long HostFSetPos (HostFILEType* fileP, long* posP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP, long* posP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+ CALLED_GET_PARAM_REF (long, posP, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, 1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ int result = x_fseek (fh, *posP, SEEK_SET);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFTell
+// ---------------------------------------------------------------------------
+
+static void _HostFTell (void)
+{
+ // long HostFTell (HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ long result = x_ftell (fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFWrite
+// ---------------------------------------------------------------------------
+
+static void _HostFWrite (void)
+{
+ // long HostFWrite (const void* buffer, long size, long count, HostFILEType* fileP)
+
+ CALLED_SETUP_HC ("long", "const void* buffer, long size, long count, HostFILEType* fileP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+ CALLED_GET_PARAM_VAL (long, count);
+ CALLED_GET_PARAM_PTR (void, buffer, size * count, Marshal::kInput);
+ CALLED_GET_PARAM_FILE (fileP);
+
+ // Check the parameters.
+
+ if (!fh || buffer == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, 0);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ size_t result = x_fwrite (buffer, size, count, fh);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRemove
+// ---------------------------------------------------------------------------
+
+static void _HostRemove (void)
+{
+ // long HostRemove(const char* nameP)
+
+ CALLED_SETUP_HC ("long", "const char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = remove (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRename
+// ---------------------------------------------------------------------------
+
+static void _HostRename (void)
+{
+ // long HostRename(const char* oldNameP, const char* newNameP)
+
+ CALLED_SETUP_HC ("long", "const char* oldNameP, const char* newNameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, oldNameP);
+ CALLED_GET_PARAM_STR (char, newNameP);
+
+ // Call the function.
+
+ int result = rename (oldNameP, newNameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTmpFile
+// ---------------------------------------------------------------------------
+
+static void _HostTmpFile (void)
+{
+ // HostFILEType* HostTmpFile (void)
+
+ CALLED_SETUP_HC ("HostFILEType*", "void");
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ FILE* result = tmpfile ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTmpNam
+// ---------------------------------------------------------------------------
+
+static void _HostTmpNam (void)
+{
+ // char* HostTmpNam (char* nameP)
+
+ CALLED_SETUP_HC ("char*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_PTR (char, nameP, HOST_NAME_MAX, Marshal::kOutput);
+
+ // Check the parameters.
+
+ // Call the function.
+
+#if HAVE_MKSTEMP
+
+ // Try to find a good home for this file...
+
+ char* result = NULL;
+ char* env = NULL;
+ char temp_buff[HOST_NAME_MAX];
+
+ if (!env)
+ env = getenv ("TMPDIR");
+
+ if (!env)
+ env = getenv ("TEMP");
+
+#if defined (P_tmpdir)
+ if (!env)
+ env = P_tmpdir;
+#else
+ if (!env)
+ env = "/tmp";
+#endif
+
+ strcpy (temp_buff, env);
+ strcat (temp_buff, "/pose.XXXXXX");
+
+ // Create the temporary file name.
+
+ int fd = mkstemp (temp_buff);
+
+ // If that succeeded, close the file that was created
+ // and remember the file name.
+
+ if (fd > 0 && !close (fd))
+ {
+ result = temp_buff;
+
+ if (nameP != EmMemNULL)
+ {
+ strcpy ((char*) nameP, temp_buff);
+ }
+ }
+
+#else
+
+ char* result = tmpnam (nameP);
+
+#endif
+
+ // Return the result.
+
+ if (!result)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ }
+ else
+ {
+ if (nameP != EmMemNULL)
+ {
+ CALLED_PUT_PARAM_REF (nameP);
+ PUT_RESULT_VAL (emuptr, nameP);
+ }
+ else
+ {
+ ::PrvReturnString (result, sub);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetEnv
+// ---------------------------------------------------------------------------
+
+static void _HostGetEnv (void)
+{
+ // char* HostGetEnv (const char* nameP)
+
+ CALLED_SETUP_HC ("char*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Call the function.
+
+ char* value = getenv (nameP);
+
+ // Return the result.
+
+ ::PrvReturnString (value, sub);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMalloc
+// ---------------------------------------------------------------------------
+
+static void _HostMalloc (void)
+{
+ // void* HostMalloc(long size)
+
+ CALLED_SETUP_HC ("void*", "long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Call the function.
+
+ emuptr result = ::PrvMalloc (size);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRealloc
+// ---------------------------------------------------------------------------
+
+static void _HostRealloc (void)
+{
+ // void* HostRealloc(void* p, long size)
+
+ CALLED_SETUP_HC ("void*", "void* p, long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, p);
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Call the function.
+
+ emuptr result;
+
+ if (!p)
+ {
+ result = ::PrvMalloc (size);
+ }
+ else if (!size)
+ {
+ ::PrvFree (p);
+ result = EmMemNULL;
+ }
+ else
+ {
+ result = ::PrvRealloc (p, size);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostFree
+// ---------------------------------------------------------------------------
+
+static void _HostFree (void)
+{
+ // void HostFree(void* p)
+
+ CALLED_SETUP_HC ("void", "void* p");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, p);
+
+ // Call the function.
+
+ ::PrvFree (p);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostAscTime
+// ---------------------------------------------------------------------------
+
+static void _HostAscTime (void)
+{
+ // char* HostAscTime(const HostTmType* hisTmP)
+
+ CALLED_SETUP_HC ("char*", "HostTmType* hisTmP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTmType, hisTmP, Marshal::kInput);
+
+ struct tm myTm;
+
+ ::PrvTmFromHostTm (myTm, *hisTmP);
+
+ // Call the function.
+
+ char* result = asctime (&myTm);
+
+ // Return the result.
+
+ ::PrvReturnString (result, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostClock
+// ---------------------------------------------------------------------------
+
+static void _HostClock (void)
+{
+ // HostClockType HostClock(void)
+
+ CALLED_SETUP_HC ("HostClockType", "void");
+
+ // Get the caller's parameters.
+
+ // Call the function.
+
+ clock_t result = clock ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostClockType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostCTime
+// ---------------------------------------------------------------------------
+
+static void _HostCTime (void)
+{
+ // char* HostCTime(const HostTimeType*)
+
+ CALLED_SETUP_HC ("char*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ char* result = ctime (&myTime);
+
+ // Return the result.
+
+ ::PrvReturnString (result, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDiffTime
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostDiffTime (void)
+{
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGMTime
+// ---------------------------------------------------------------------------
+
+static void _HostGMTime (void)
+{
+ // HostTmType* HostGMTime(const HostTimeType* timeP)
+
+ CALLED_SETUP_HC ("void*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ struct tm* result = gmtime (&myTime);
+
+ ::PrvHostTmFromTm (gGMTime, *result);
+
+ // Return the result.
+
+ ::PrvMapAndReturn (&gGMTime, sizeof (gGMTime), sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostLocalTime
+// ---------------------------------------------------------------------------
+
+static void _HostLocalTime (void)
+{
+ // HostTmType* HostLocalTime(const HostTimeType* timeP)
+
+ CALLED_SETUP_HC ("HostTmType*", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kInput);
+
+ time_t myTime = *timeP;
+
+ // Call the function.
+
+ struct tm* result = localtime (&myTime);
+
+ ::PrvHostTmFromTm (gLocalTime, *result);
+
+ // Return the result.
+
+ ::PrvMapAndReturn (&gLocalTime, sizeof (gLocalTime), sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMkTime
+// ---------------------------------------------------------------------------
+
+static void _HostMkTime (void)
+{
+ // HostTimeType HostMkTime(HostTmType* timeP)
+
+ CALLED_SETUP_HC ("HostTimeType", "HostTmType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTmType, timeP, Marshal::kInput);
+
+ struct tm myTm;
+
+ ::PrvTmFromHostTm (myTm, *timeP);
+
+ // Call the function.
+
+ time_t result = mktime (&myTm);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostTimeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostStrFTime
+// ---------------------------------------------------------------------------
+
+static void _HostStrFTime (void)
+{
+ // HostSizeType HostStrFTime(char*, HostSizeType, const char*, const HostTmType*)
+
+ CALLED_SETUP_HC ("HostSizeType", "char* strDest, HostSizeType maxsize, const char* format,"
+ "const HostTmType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (HostSizeType, maxsize);
+ CALLED_GET_PARAM_PTR (char, strDest, maxsize, Marshal::kOutput);
+ CALLED_GET_PARAM_STR (char, format);
+ CALLED_GET_PARAM_REF (HostTmType, timeP, Marshal::kInput);
+
+ if (strDest == EmMemNULL || format == EmMemNULL || timeP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (HostSizeType, 0);
+ return;
+ }
+
+ struct tm myTime;
+
+ ::PrvTmFromHostTm (myTime, *timeP);
+
+ // Call the function.
+
+ size_t result = strftime (strDest, maxsize, format, &myTime);
+
+ CALLED_PUT_PARAM_REF (strDest);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostSizeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTime
+// ---------------------------------------------------------------------------
+
+static void _HostTime (void)
+{
+ // HostTimeType HostTime(HostTimeType*)
+
+ CALLED_SETUP_HC ("HostTimeType", "HostTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostTimeType, timeP, Marshal::kOutput);
+
+ // Call the function.
+
+ time_t result2;
+ time_t result = time (&result2);
+
+ if (timeP)
+ {
+ *timeP = result2;
+ CALLED_PUT_PARAM_REF (timeP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostTimeType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostMkDir
+// ---------------------------------------------------------------------------
+
+static void _HostMkDir (void)
+{
+ // long HostMkDir (const char* nameP)
+
+ CALLED_SETUP_HC ("long", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = _mkdir (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostRmDir
+// ---------------------------------------------------------------------------
+
+static void _HostRmDir (void)
+{
+ // long HostRmDir (const char* nameP)
+
+ CALLED_SETUP_HC ("long", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // Call the function.
+
+ int result = _rmdir (nameP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOpenDir
+// ---------------------------------------------------------------------------
+
+static void _HostOpenDir (void)
+{
+ // HostDIRType* HostOpenDir(const char*)
+
+ CALLED_SETUP_HC ("HostDIRType*", "char* nameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+
+ // See if the directory exists.
+
+ EmDirRef dirRef (nameP);
+ if (!dirRef.Exists ())
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+ }
+
+ // Create a new MyDIR object to pass back as the HostDIRType.
+
+ MyDIR* dir = new MyDIR;
+ if (!dir)
+ {
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+ }
+
+ // Initialize the MyDIR with the child entries.
+
+ dirRef.GetChildren (&dir->fFiles, &dir->fDirs);
+ dir->fState = 0;
+
+ // Remember this on our list of open directories and
+ // pass it back to the user.
+
+ gOpenDirs.push_back (dir);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (emuptr, dir);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostReadDir
+// ---------------------------------------------------------------------------
+
+static void _HostReadDir(void)
+{
+ // HostDirEntType* HostReadDir(HostDIRType* dirP)
+
+ CALLED_SETUP_HC ("HostDIRType*", "HostDIRType* dirP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, dirP);
+
+ MyDIR* dir = (MyDIR*) (emuptr) dirP;
+
+ // Make sure dir is valid.
+
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ // It appears to be on our list, so let's use it.
+ if (*iter == dir)
+ goto FoundIt;
+
+ ++iter;
+ }
+
+ // hostDir was not on our list. Return NULL.
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ return;
+
+FoundIt:
+
+ // Initialize our result in case of failure.
+
+ gHostDirEnt.d_name[0] = 0;
+
+ // Get the next dir or file, as the case may be.
+
+ switch (dir->fState)
+ {
+ // Just starting out. Initialize the directory iterator
+ // and fall through to the code that uses it.
+
+ case 0:
+ dir->fDirIter = dir->fDirs.begin ();
+ dir->fState = 1;
+ // Fall thru
+
+ // Iterating over directories; get the next one. If there
+ // are no more, start iterating over files.
+
+ case 1:
+ if (dir->fDirIter != dir->fDirs.end ())
+ {
+ strcpy (gHostDirEnt.d_name, dir->fDirIter->GetName().c_str());
+ ++dir->fDirIter;
+ break;
+ }
+
+ dir->fFileIter = dir->fFiles.begin ();
+ dir->fState = 2;
+ // Fall thru
+
+ // Iterating over files; get the next one. If there
+ // are no more, stop iterating.
+
+ case 2:
+ if (dir->fFileIter != dir->fFiles.end ())
+ {
+ strcpy (gHostDirEnt.d_name, dir->fFileIter->GetName().c_str());
+ ++dir->fFileIter;
+ break;
+ }
+ dir->fState = 3;
+
+ // No longer iterating. Just return NULL.
+
+ case 3:
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ break;
+ }
+
+ // If we're returning a value in gHostDirEnt, make
+ // sure it's mapped into emulated space.
+
+ if (gHostDirEnt.d_name[0] != 0)
+ {
+ emuptr result = EmBankMapped::GetEmulatedAddress (&gHostDirEnt);
+ if (result == EmMemNULL)
+ {
+ EmBankMapped::MapPhysicalMemory (&gHostDirEnt, sizeof (gHostDirEnt));
+ result = EmBankMapped::GetEmulatedAddress (&gHostDirEnt);
+ }
+
+ PUT_RESULT_VAL (emuptr, result);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostCloseDir
+// ---------------------------------------------------------------------------
+
+static void _HostCloseDir (void)
+{
+ // long HostCloseDir(HostDIRType*)
+
+ CALLED_SETUP_HC ("long", "HostDIRType* dirP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (emuptr, dirP);
+
+ MyDIR* dir = (MyDIR*) (emuptr) dirP;
+
+ // Make sure dir is valid.
+
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ if (*iter == dir)
+ {
+ // It's on our list. Remove it from the list and delete it.
+
+ gOpenDirs.erase (iter);
+ delete dir;
+ break;
+ }
+
+ ++iter;
+ }
+
+ // Unmap any mapped gHostDirEnt if we're not iterating over any
+ // other directories.
+
+ if (gOpenDirs.size () == 0)
+ {
+ EmBankMapped::UnmapPhysicalMemory (&gHostDirEnt);
+ }
+
+ // Return no error (should we return an error if DIR was not found?)
+
+ PUT_RESULT_VAL (long, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostStat
+// ---------------------------------------------------------------------------
+
+static void _HostStat(void)
+{
+ // long HostStat(const char*, HostStatType*)
+
+ CALLED_SETUP_HC ("long", "const char* nameP, HostStatType* statP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (HostStatType, statP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || statP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ _stat_ local_stat;
+ int result = _stat (nameP, &local_stat);
+
+ if (result == 0)
+ {
+ (*statP).st_dev_ = local_stat.st_dev;
+ (*statP).st_ino_ = local_stat.st_ino;
+ (*statP).st_mode_ = local_stat.st_mode;
+ (*statP).st_nlink_ = local_stat.st_nlink;
+ (*statP).st_uid_ = local_stat.st_uid;
+ (*statP).st_gid_ = local_stat.st_gid;
+ (*statP).st_rdev_ = local_stat.st_rdev;
+ (*statP).st_atime_ = local_stat.st_atime;
+ (*statP).st_mtime_ = local_stat.st_mtime;
+ (*statP).st_ctime_ = local_stat.st_ctime;
+ (*statP).st_size_ = local_stat.st_size;
+#if PLATFORM_WINDOWS
+ (*statP).st_blksize_ = 0;
+ (*statP).st_blocks_ = 0;
+ (*statP).st_flags_ = 0;
+#elif PLATFORM_MAC
+ (*statP).st_blksize_ = local_stat.st_blksize;
+ (*statP).st_blocks_ = local_stat.st_blocks;
+ (*statP).st_flags_ = local_stat.st_flags;
+#else
+ (*statP).st_blksize_ = local_stat.st_blksize;
+ (*statP).st_blocks_ = local_stat.st_blocks;
+ (*statP).st_flags_ = 0;
+#endif
+
+ CALLED_PUT_PARAM_REF (statP);
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTruncate
+// ---------------------------------------------------------------------------
+
+static void _HostTruncate (void)
+{
+ // long HostTruncate(const char*, long)
+
+ CALLED_SETUP_HC ("long", "char* nameP, long size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_VAL (long, size);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || size < 0)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ int result;
+
+ int fd = _open (nameP, _O_RDWR);
+ if (fd)
+ {
+ result = _chsize (fd, size);
+ _close (fd);
+ }
+ else
+ {
+ result = errno;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostUTime
+// ---------------------------------------------------------------------------
+
+static void _HostUTime (void)
+{
+ // long HostUTime (const char*, HostUTimeType*)
+
+ CALLED_SETUP_HC ("long", "char* nameP, HostUTimeType* timeP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (HostUTimeType, timeP, Marshal::kOutput);
+
+ if (nameP == EmMemNULL || timeP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, -1);
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ _utimbuf_ buf;
+ _utimbuf_* bufP = NULL;
+
+ if (timeP)
+ {
+// buf.crtime = (*timeP).crtime_;
+ buf.actime = (*timeP).actime_;
+ buf.modtime = (*timeP).modtime_;
+
+ bufP = &buf;
+ }
+
+ // Make the call
+
+ int result = _utime (nameP, bufP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (long, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetFileAttr
+// ---------------------------------------------------------------------------
+
+static void _HostGetFileAttr(void)
+{
+ // long HostGetFileAttr(const char*, unsigned long * attr)
+
+ CALLED_SETUP_HC ("long", "char* nameP, unsigned long * attrP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_REF (unsigned long, attrP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL || attrP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ EmFileRef fRef (nameP);
+
+ int attr = 0;
+ errno = fRef.GetAttr (&attr);
+
+ // Return the result.
+
+ if (errno != 0)
+ {
+ PUT_RESULT_VAL (long, -1);
+ return;
+ }
+
+ *attrP = attr;
+ CALLED_PUT_PARAM_REF (attrP);
+
+ PUT_RESULT_VAL (long, hostErrNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSetFileAttr
+// ---------------------------------------------------------------------------
+
+static void _HostSetFileAttr(void)
+{
+ // long HostSetFileAttr(const char*, unsigned long attr)
+
+ CALLED_SETUP_HC ("long", "char* nameP, unsigned long attr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, nameP);
+ CALLED_GET_PARAM_VAL (unsigned long, attr);
+
+ // Check the parameters.
+
+ if (nameP == EmMemNULL)
+ {
+ PUT_RESULT_VAL (long, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ EmFileRef fRef(nameP);
+
+ errno = fRef.SetAttr(attr);
+
+ // Return the result.
+
+ if (errno != 0)
+ {
+ PUT_RESULT_VAL (long, -1);
+ return;
+ }
+
+ PUT_RESULT_VAL (long, hostErrNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinIsRunning
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinIsRunning (void)
+{
+ // HostBoolType HostGremlinIsRunning (void)
+
+ CALLED_SETUP_HC ("HostBoolType", "void");
+
+ PUT_RESULT_VAL (HostBoolType, (Hordes::IsOn () ? 1 : 0));
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinNumber
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinNumber (void)
+{
+ // long HostGremlinNumber (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::GremlinNumber ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinCounter
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinCounter (void)
+{
+ // long HostGremlinCounter (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::EventCounter ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinLimit
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinLimit (void)
+{
+ // long HostGremlinLimit (void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ PUT_RESULT_VAL (long, Hordes::EventLimit ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGremlinNew
+// ---------------------------------------------------------------------------
+
+static void _HostGremlinNew (void)
+{
+ // HostErrType HostGremlinNew (const HostGremlinInfoType*)
+
+ CALLED_SETUP_HC ("HostErrType", "const HostGremlinInfoType* infoP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_REF (HostGremlinInfoType, infoP, Marshal::kInput);
+
+ // Get the easy parts.
+
+ HordeInfo info;
+
+ info.fStartNumber = (*infoP).fFirstGremlin;
+ info.fStopNumber = (*infoP).fLastGremlin;
+ info.fSaveFrequency = (*infoP).fSaveFrequency;
+ info.fSwitchDepth = (*infoP).fSwitchDepth;
+ info.fMaxDepth = (*infoP).fMaxDepth;
+
+ info.OldToNew (); // Transfer the old fields to the new fields.
+
+ // Get the list of installed applications so that we can compare it to
+ // the list of applications requested by the caller.
+
+ DatabaseInfoList installedAppList;
+ ::GetDatabases (installedAppList, kApplicationsOnly);
+
+ // Get the list of applications requested by the caller. Break up the
+ // string into a list of individual names, and check to see if the whole
+ // thing was preceded by a '-'.
+
+ string appNames ((*infoP).fAppNames);
+
+ Bool exclude = false;
+ if (appNames[0] == '-')
+ {
+ exclude = true;
+ appNames = appNames.substr(1);
+ }
+
+ StringList requestedAppList;
+ ::SeparateList (requestedAppList, appNames, ',');
+
+ // For each requested application, see if it's installed in the device.
+ // If so, add it to the list of applications Gremlins should be run on.
+
+ StringList::iterator iter1 = requestedAppList.begin();
+ while (iter1 != requestedAppList.end())
+ {
+ // Get the application info based on the given name.
+
+ DatabaseInfoList::iterator iter2 = installedAppList.begin ();
+ while (iter2 != installedAppList.end ())
+ {
+ Bool addIt;
+
+ if (exclude)
+ addIt = *iter1 != iter2->name;
+ else
+ addIt = *iter1 == iter2->name;
+
+ if (addIt)
+ {
+ info.fAppList.push_back (*iter2);
+ }
+
+ ++iter2;
+ }
+
+ ++iter1;
+ }
+
+ // Start up the gremlin sub-system.
+
+ EmAssert (gDocument);
+ gDocument->ScheduleNewHorde (info);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostImportFile
+// ---------------------------------------------------------------------------
+
+static void _HostImportFile (void)
+{
+ // HostErrType HostImportFile (const char* fileName, long cardNum)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+// CALLED_GET_PARAM_VAL (long, cardNum);
+
+ // Check the parameters.
+
+ if (fileName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef fileRef (fileName);
+ EmFileRefList fileList;
+ fileList.push_back (fileRef);
+
+ vector<LocalID> idList;
+ EmFileImport::LoadPalmFileList (fileList, kMethodBest, idList);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostImportFileWithID
+// ---------------------------------------------------------------------------
+
+static void _HostImportFileWithID (void)
+{
+ // HostErrType HostImportFileWithID (const char* fileName, long cardNum, LocalID *newIDP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum, LocalID *newIDP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+// CALLED_GET_PARAM_VAL (long, cardNum);
+ CALLED_GET_PARAM_REF (LocalID, newIDP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ if (fileName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ *newIDP = 0;
+
+ try
+ {
+ EmFileRef fileRef (fileName);
+ EmFileRefList fileList;
+ fileList.push_back (fileRef);
+
+ vector<LocalID> idList;
+ EmFileImport::LoadPalmFileList (fileList, kMethodBest, idList);
+
+ EmAssert (idList.size () == fileList.size ());
+
+ *newIDP = idList.front ();
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF(newIDP);
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExportFile
+// ---------------------------------------------------------------------------
+
+static void _HostExportFile (void)
+{
+ // HostErrType HostExportFile (const char* dbNameP, long cardNum, const char* fileNameP)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* fileName, long cardNum, const char* dbName");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileName);
+ CALLED_GET_PARAM_VAL (long, cardNum);
+ CALLED_GET_PARAM_STR (char, dbName);
+
+ // Check the parameters.
+
+ if (fileName == NULL || dbName == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef ref (fileName);
+ EmStreamFile stream (ref, kCreateOrEraseForUpdate,
+ kFileCreatorInstaller, kFileTypePalmApp);
+ ::SavePalmFile (stream, cardNum, dbName);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSaveScreen
+// ---------------------------------------------------------------------------
+
+static void _HostSaveScreen (void)
+{
+ // HostErrType HostSaveScreen (const char* fileNameP)
+
+ CALLED_SETUP_HC ("HostErrType", "char* fileNameP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, fileNameP);
+
+ // Check the parameters.
+
+ if (fileNameP == NULL)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Make the call
+
+ ErrCode result = kError_NoError;
+ try
+ {
+ EmFileRef ref (fileNameP);
+
+ EmAssert (gDocument);
+ gDocument->HostSaveScreen (ref);
+ }
+ catch (ErrCode errCode)
+ {
+ result = errCode;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, result);
+}
+
+
+#pragma mark -
+
+#define exgErrBadData (exgErrorClass | 8) // internal data was not valid
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibOpen
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibOpen (void)
+{
+ // Err ExgLibOpen (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibOpen (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibClose
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibClose (void)
+{
+ // Err ExgLibClose (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibClose (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibSleep
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibSleep (void)
+{
+ // Err ExgLibSleep (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibSleep (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibWake
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibWake (void)
+{
+ // Err ExgLibWake (UInt16 libRefNum)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibWake (libRefNum);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibHandleEvent
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibHandleEvent (void)
+{
+ // Boolean ExgLibHandleEvent (UInt16 libRefNum, void* eventP)
+
+ CALLED_SETUP_HC ("Boolean", "UInt16 libRefNum, void* eventP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, eventP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Boolean result = exgMgr->ExgLibHandleEvent (libRefNum, eventP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Boolean, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibConnect
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibConnect (void)
+{
+ // Err ExgLibConnect (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibConnect (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibAccept
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibAccept (void)
+{
+ // Err ExgLibAccept (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibAccept (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibDisconnect
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibDisconnect (void)
+{
+ // Err ExgLibDisconnect (UInt16 libRefNum, void* exgSocketP, Err error)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP, Err error");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (Err, error);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibDisconnect (libRefNum, exgSocketP, error);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibPut
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibPut (void)
+{
+ // Err ExgLibPut (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibPut (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibGet
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibGet (void)
+{
+ // Err ExgLibGet (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibGet (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibSend
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibSend (void)
+{
+ // UInt32 ExgLibSend (UInt16 libRefNum, void* exgSocketP,
+ // const void* const bufP, const UInt32 bufLen, Err* errP)
+
+ CALLED_SETUP_HC ("UInt32", "UInt16 libRefNum, void* exgSocketP,"
+ "const void* const bufP, const UInt32 bufLen, Err* errP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (UInt32, bufLen);
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ *errP = exgErrBadData;
+ PUT_RESULT_VAL (UInt32, 0);
+ return;
+ }
+
+ // Make the call
+
+ UInt32 result = exgMgr->ExgLibSend (libRefNum, exgSocketP, bufP, bufLen, errP);
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF (errP);
+
+ PUT_RESULT_VAL (UInt32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibReceive
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibReceive (void)
+{
+ // UInt32 ExgLibReceive (UInt16 libRefNum, void* exgSocketP,
+ // void* bufP, const UInt32 bufLen, Err* errP)
+
+ CALLED_SETUP_HC ("UInt32", "UInt16 libRefNum, void* exgSocketP,"
+ "const void* const bufP, const UInt32 bufLen, Err* errP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+ CALLED_GET_PARAM_VAL (UInt32, bufLen);
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ *errP = exgErrBadData;
+ PUT_RESULT_VAL (UInt32, 0);
+ return;
+ }
+
+ // Make the call
+
+ UInt32 result = exgMgr->ExgLibReceive (libRefNum, exgSocketP, bufP, bufLen, errP);
+
+ // Return the result.
+
+ CALLED_PUT_PARAM_REF (bufP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ PUT_RESULT_VAL (UInt32, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibControl
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibControl (void)
+{
+ // Err ExgLibControl (UInt16 libRefNum, UInt16 op,
+ // void* valueP, UInt16* valueLenP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, UInt16 op, void* valueP, UInt16* valueLenP");
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, op);
+ CALLED_GET_PARAM_VAL (emuptr, valueP);
+ CALLED_GET_PARAM_VAL (emuptr, valueLenP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibControl (libRefNum, op, valueP, valueLenP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostExgLibRequest
+// ---------------------------------------------------------------------------
+
+static void _HostExgLibRequest (void)
+{
+ // Err ExgLibRequest (UInt16 libRefNum, void* exgSocketP)
+
+ CALLED_SETUP_HC ("Err", "UInt16 libRefNum, void* exgSocketP");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (emuptr, exgSocketP);
+
+ // Check the parameters.
+
+ EmExgMgr* exgMgr = EmExgMgr::GetExgMgr (libRefNum);
+ if (!exgMgr)
+ {
+ PUT_RESULT_VAL (Err, exgErrBadData);
+ return;
+ }
+
+ // Make the call
+
+ Err result = exgMgr->ExgLibRequest (libRefNum, exgSocketP);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (Err, result);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetPreference
+// ---------------------------------------------------------------------------
+
+static void _HostGetPreference (void)
+{
+ // HostBoolType HostGetPreference (const char* key, char* value);
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* key, char* value");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, key);
+ CALLED_GET_PARAM_VAL (emuptr, value);
+
+ string keyStr ((const char*) key);
+
+ if (keyStr == "ReportIntlStrictChecks")
+ {
+ keyStr = "ReportStrictIntlChecks";
+ }
+
+ Preference<string> pref (keyStr.c_str ());
+
+ PUT_RESULT_VAL (HostBoolType, 0);
+
+ if (pref.Loaded ())
+ {
+ EmMem_strcpy ((emuptr) value, pref->c_str ());
+ PUT_RESULT_VAL (HostBoolType, 1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSet1Preference
+// ---------------------------------------------------------------------------
+
+static void _HostSetPreference (void)
+{
+ // void HostSetPreference (const char*, const char*);
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* key, char* value");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_STR (char, key);
+ CALLED_GET_PARAM_STR (char, value);
+
+ string keyStr ((const char*) key);
+
+ if (keyStr == "ReportIntlStrictChecks")
+ {
+ keyStr = "ReportStrictIntlChecks";
+ }
+
+ Preference<string> pref (keyStr.c_str ());
+ pref = string (value);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostLogFile
+// ---------------------------------------------------------------------------
+
+static void _HostLogFile (void)
+{
+ // HostFILEType* HostLogFile (void)
+
+ CALLED_SETUP_HC ("HostFILEType", "void");
+
+ PUT_RESULT_VAL (emuptr, hostLogFile);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSetLogFileSize
+// ---------------------------------------------------------------------------
+
+static void _HostSetLogFileSize (void)
+{
+ // void HostSetLogFileSize (long newSize)
+
+ CALLED_SETUP_HC ("void", "long newSize");
+
+ CALLED_GET_PARAM_VAL (long, newSize);
+
+ Preference<long> logFileSize (kPrefKeyLogFileSize);
+ logFileSize = (long) newSize;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionCreate
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostSessionCreate (void)
+{
+ // HostErrType HostSessionCreate(const char* device, long ramSize, const char* romPath)
+
+ struct StackFrame
+ {
+ const char* device;
+ long ramSize;
+ const char* romPath;
+ };
+
+ string deviceStr = ToString (GET_PARAMETER (device));
+ RAMSizeType ramSize = GET_PARAMETER (ramSize);
+ string romPathStr = ToString (GET_PARAMETER (romPath));
+
+ // See if it's OK to create a session.
+
+ if (Platform::SessionRunning())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ // Convert the device string into a DeviceType
+
+ DeviceType device = kDeviceUnspecified;
+ EmDeviceMenuItemList devices = EmDevice::GetMenuItemList ();
+ EmDeviceMenuItemList::iterator deviceIter = devices.begin();
+
+ while (deviceIter != devices.end())
+ {
+ if (_stricmp (deviceStr.c_str(), deviceIter->second.c_str()) == 0)
+ {
+ device = deviceIter->first;
+ break;
+ }
+ }
+
+ if (device == kDeviceUnspecified)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidDeviceType);
+ return;
+ }
+
+ // Validate the RAM size
+
+ Bool sizeOK = false;
+ MemoryTextList sizes;
+ ::GetMemoryTextList (sizes);
+
+ MemoryTextList::iterator sizeIter = sizes.begin();
+ while (sizeIter != sizes.end())
+ {
+ if (ramSize == sizeIter->first)
+ {
+ sizeOK = true;
+ break;
+ }
+ }
+
+ if (!sizeOK)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidRAMSize);
+ return;
+ }
+
+ // Convert the ROM file string into a EmFileRef.
+
+ EmFileRef romRef(romPathStr);
+ if (!romRef.Exists())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrFileNotFound);
+ return;
+ }
+
+ // Kick this all off.
+
+ Configuration cfg (device, ramSize, romRef);
+ EmAssert (gApplication);
+ gApplication->ScheduleCreateSession (cfg);
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionOpen
+// ---------------------------------------------------------------------------
+
+#if 0
+static void _HostSessionOpen (void)
+{
+ // HostErrType HostSessionOpen (const char* psfFileName);
+
+ struct StackFrame
+ {
+ const char* psfFileName;
+ };
+
+ string psfFileName = ToString (GET_PARAMETER (psfFileName));
+
+ // See if it's OK to open a session.
+
+ if (Platform::SessionRunning())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ // Validate the file to open.
+
+ EmFileRef psfFileRef(psfFileName);
+ if (!psfFileRef.Exists())
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrFileNotFound);
+ return;
+ }
+
+ // Kick this all off.
+
+ EmAssert (gApplication);
+ gApplication->ScheduleOpenSession (psfFileRef);
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionSave
+// ---------------------------------------------------------------------------
+
+static void _HostSessionSave (void)
+{
+ // HostBoolType HostSessionSave (const char* saveFileName)
+
+ CALLED_SETUP_HC ("HostBoolType", "const char* saveFileName");
+
+ CALLED_GET_PARAM_STR (char, saveFileName);
+
+ // See if it's OK to close a session.
+
+ if (!gSession)
+ {
+ // !!! Oops. Returning an error code as a Boolean...
+ PUT_RESULT_VAL (HostBoolType, hostErrSessionNotRunning);
+ return;
+ }
+
+ EmFileRef saveFileRef (saveFileName);
+
+ // Saving will save the PC at the current instruction, which saves the state.
+ // Upon resumption, the current instruction will cause a save again. This
+ // will repeat infinitely. So advance the PC to the following instruction
+ // before saving.
+
+ // First, get the address of the function that got us here.
+ // If the system call is being made by a TRAP $F, the PC has already
+ // been bumped past the opcode. If being made with a JSR via the
+ // SYS_TRAP_FAST macro, the PC has not been adjusted.
+ //
+ // !!! Note that the following is 68K-specific!
+
+ emuptr startPC = gCPU->GetPC ();
+ if ((EmMemGet16 (startPC) & 0xF000) == 0xA000)
+ {
+ startPC -= 2; // Back us up to the TRAP $F
+ }
+
+ SystemCallContext context;
+ if (GetSystemCallContext (startPC, context))
+ {
+ gCPU->SetPC (context.fNextPC);
+
+ // Set the return value to something else so that the code that is restored can distinguish
+ // the saved case from not saved case.
+
+ PUT_RESULT_VAL (HostBoolType, true);
+
+ gSession->Save (saveFileRef, false);
+ }
+
+ PUT_RESULT_VAL (HostBoolType, false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionClose
+// ---------------------------------------------------------------------------
+
+static void _HostSessionClose (void)
+{
+ // HostErrType HostSessionClose (const char* saveFileName)
+
+ CALLED_SETUP_HC ("HostErrType", "const char* saveFileName");
+
+ CALLED_GET_PARAM_STR (char, saveFileName);
+
+ // See if it's OK to close a session.
+
+ if (!gSession)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrSessionNotRunning);
+ return;
+ }
+
+ EmFileRef saveFileRef(saveFileName);
+
+ // Kick this all off.
+
+ gApplication->ScheduleSessionClose (saveFileRef);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSessionQuit
+// ---------------------------------------------------------------------------
+
+static void _HostSessionQuit (void)
+{
+ // HostErrType HostSessionQuit (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ // See if it's OK to quit Poser.
+
+ if (gSession)
+ {
+// PUT_RESULT_VAL (HostErrType, hostErrSessionRunning);
+// return;
+ }
+
+ // Kick this all off.
+
+ gApplication->ScheduleQuit ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalSend
+// ---------------------------------------------------------------------------
+// Called by anyone wanting to send a signal to any waiting scripts.
+
+static void _HostSignalSend (void)
+{
+ // HostErrType HostSignalSend (HostSignalType signalNumber)
+
+ CALLED_SETUP_HC ("HostErrType", "HostSignalType signalNumber");
+
+ CALLED_GET_PARAM_VAL (HostSignalType, signalNumber);
+
+ RPC::SignalWaiters (signalNumber);
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalWait
+// ---------------------------------------------------------------------------
+// Called by scripts that want to get a signal sent from HostSignalSend.
+
+static void _HostSignalWait (void)
+{
+ // HostErrType HostSignalWait (long timeout)
+
+ CALLED_SETUP_HC ("HostErrType", "long timeout");
+
+ CALLED_GET_PARAM_VAL (long, timeout);
+
+ // Unblock the CPU thread if it's suspended from a previous
+ // HostSignalSend call.
+
+ EmAssert (gSession);
+ gSession->ScheduleResumeExternal ();
+
+ if (RPC::HandlingPacket ())
+ {
+ RPC::DeferCurrentPacket (timeout);
+
+ if (EmPatchState::UIInitialized ())
+ {
+ ::EvtWakeup (); // Wake up the process in case the caller is looking
+ // for an idle event (which would never otherwise
+ // happen if EvtGetEvent has already been called and
+ // is blocking).
+ }
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSignalResume
+// ---------------------------------------------------------------------------
+// Called by scripts to restart the emulator after it has sent a signal and
+// then suspended itself.
+
+static void _HostSignalResume (void)
+{
+ // HostErrType HostSignalResume (void)
+
+ CALLED_SETUP_HC ("HostErrType", "void");
+
+ EmAssert (gSession);
+ gSession->ScheduleResumeExternal ();
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+#if HAS_TRACER
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceInit
+// ---------------------------------------------------------------------------
+
+static void _HostTraceInit (void)
+{
+ gTracer.InitOutputPort ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceClose
+// ---------------------------------------------------------------------------
+
+static void _HostTraceClose (void)
+{
+ gTracer.CloseOutputPort ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceOutputT
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputT (void)
+{
+ // void HostTraceOutputT (unsigned short, const char*, ...)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVT( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostTraceOutputTL
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputTL (void)
+{
+ // void HostTraceOutputTL (unsigned short, const char*, ...)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVTL( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputVT
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputVT (void)
+{
+ // void HostTraceOutputVT (unsigned short module, const char* fmt, char* va_addr)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt, const char* va_addr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+ CALLED_GET_PARAM_VAL (emuptr, va_addr);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // We get the parameters from va_addr, not the stack, so create a new
+ // EmSubroutine object to access them.
+
+ EmSubroutine sub2;
+ sub2.PrepareStack (va_addr);
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub2, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVT( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputVTL
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputVTL (void)
+{
+ // void HostTraceOutputVTL (unsigned short module, const char* fmt, char* va_addr)
+
+ CALLED_SETUP_STDARG_HC ("void", "UInt16 module, const char* fmt, const char* va_addr");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_STR (char, fmt);
+ CALLED_GET_PARAM_VAL (emuptr, va_addr);
+
+ // Check the parameters.
+
+ if (fmt == NULL)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // We get the parameters from va_addr, not the stack, so create a new
+ // EmSubroutine object to access them.
+
+ EmSubroutine sub2;
+ sub2.PrepareStack (va_addr);
+
+ // Collect the specified parameters. We need to make copies of everything
+ // so that it's in the right endian order and to reverse any effects
+ // of wordswapping. The values specified on the stack (the integers,
+ // chars, doubles, pointers, etc.) get converted and placed in stackData.
+ // The data pointed to by the pointers gets converted and placed in stringData.
+
+ ByteList stackData;
+ StringList stringData;
+
+ if (!::PrvCollectParameters (sub2, string (fmt), stackData, stringData))
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ // Write everything out
+
+ gTracer.OutputVTL( module, fmt, (va_list) &stackData[0]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostOutputB
+// ---------------------------------------------------------------------------
+
+static void _HostTraceOutputB (void)
+{
+ // void HostTraceOutputB (unsigned short, const void*, HostSizeType)
+
+ CALLED_SETUP_HC ("void", "UInt16 module, const void* buf, HostSizeType length");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt16, module);
+ CALLED_GET_PARAM_VAL (HostSizeType, length);
+ CALLED_GET_PARAM_PTR (void, buf, length, Marshal::kInput);
+
+ // Check the parameters.
+
+ if (buf == NULL || length == 0)
+ {
+ errno = hostErrInvalidParameter;
+ return;
+ }
+
+ gTracer.OutputB (module, buf, length);
+}
+
+#endif // HAS_TRACER
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDbgSetDataBreak
+// ---------------------------------------------------------------------------
+
+static void _HostDbgSetDataBreak (void)
+{
+ // HostErr HostDbgSetDataBreak (UInt32 addr, UInt32 size)
+
+ CALLED_SETUP_HC ("HostErr", "UInt32 addr, UInt32 size");
+
+ // Get the caller's parameters.
+
+ CALLED_GET_PARAM_VAL (UInt32, addr);
+ CALLED_GET_PARAM_VAL (UInt32, size);
+
+ // Check the parameters.
+
+ if (!addr || !size)
+ {
+ PUT_RESULT_VAL (HostErrType, hostErrInvalidParameter);
+ return;
+ }
+
+ // Set data breakpoint.
+
+ gDebuggerGlobals.watchEnabled = true;
+
+ if (gDebuggerGlobals.watchEnabled)
+ {
+ gDebuggerGlobals.watchAddr = addr;
+ gDebuggerGlobals.watchBytes = size;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostDbgClearDataBreak
+// ---------------------------------------------------------------------------
+
+static void _HostDbgClearDataBreak (void)
+{
+ // HostErr HostDbgClearDataBreak (void)
+
+ CALLED_SETUP_HC ("HostErr", "void");
+
+ // Get the caller's parameters.
+
+ // Check the parameters.
+
+ // Set data breakpoint
+
+ gDebuggerGlobals.watchEnabled = false;
+
+ if (!gDebuggerGlobals.watchEnabled)
+ {
+ gDebuggerGlobals.watchAddr = 0;
+ gDebuggerGlobals.watchBytes = 0;
+ }
+
+ // Return the result.
+
+ PUT_RESULT_VAL (HostErrType, errNone);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotMax
+// ---------------------------------------------------------------------------
+
+static void _HostSlotMax (void)
+{
+ // long HostSlotMax(void)
+
+ CALLED_SETUP_HC ("long", "void");
+
+ int maxSlotNo = 0;
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (maxSlotNo < iter->fSlotNumber)
+ {
+ maxSlotNo = iter->fSlotNumber;
+ }
+
+ ++iter;
+ }
+
+ PUT_RESULT_VAL (long, maxSlotNo);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotRoot
+// ---------------------------------------------------------------------------
+
+static void _HostSlotRoot (void)
+{
+ // const char* HostSlotRoot(long slotNo)
+
+ CALLED_SETUP_HC ("char*", "long slotNo");
+
+ CALLED_GET_PARAM_VAL (long, slotNo);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (slotNo == iter->fSlotNumber)
+ {
+ if (iter->fSlotOccupied)
+ {
+ ::PrvReturnString (iter->fSlotRoot.GetFullPath (), sub);
+ }
+
+ break;
+ }
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostSlotHasCard
+// ---------------------------------------------------------------------------
+
+static void _HostSlotHasCard (void)
+{
+ // HostBoolType HostSlotHasCard(long slotNo)
+
+ CALLED_SETUP_HC ("HostBoolType", "long slotNo");
+
+ CALLED_GET_PARAM_VAL (long, slotNo);
+
+ PUT_RESULT_VAL (HostBoolType, false);
+
+ Preference<SlotInfoList> slots (kPrefKeySlotList);
+
+ SlotInfoList::const_iterator iter = (*slots).begin ();
+ while (iter != (*slots).end ())
+ {
+ if (slotNo == iter->fSlotNumber)
+ {
+ PUT_RESULT_VAL (HostBoolType, iter->fSlotOccupied);
+ break;
+ }
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetFile
+// ---------------------------------------------------------------------------
+
+static void _HostGetFile (void)
+{
+ // const char* HostGetFile(const char* prompt, const char* defaultDirName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmFileRef result;
+ EmFileTypeList filterList (1, kFileTypeAll);
+
+ if (EmDlg::DoGetFile (result, string (prompt), defaultDir, filterList) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostPutFile
+// ---------------------------------------------------------------------------
+
+static void _HostPutFile (void)
+{
+ // const char* HostPutFile(const char* prompt, const char* defaultDirName, const char* defaultName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName, const char* defaultName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+ CALLED_GET_PARAM_STR (char, defaultName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmFileRef result;
+ EmFileTypeList filterList (1, kFileTypeAll);
+
+ if (EmDlg::DoPutFile (result, string (prompt), defaultDir,
+ filterList, string (defaultName)) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ _HostGetDirectory
+// ---------------------------------------------------------------------------
+
+static void _HostGetDirectory (void)
+{
+ // const char* HostGetDirectory(const char* prompt, const char* defaultDirName)
+
+ CALLED_SETUP_HC ("char*", "const char* prompt, const char* defaultDirName");
+
+ CALLED_GET_PARAM_STR (char, prompt);
+ CALLED_GET_PARAM_STR (char, defaultDirName);
+
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+
+ EmDirRef defaultDir (defaultDirName);
+
+ EmDirRef result;
+
+ if (EmDlg::DoGetDirectory (result, string (prompt), defaultDir) == kDlgItemOK)
+ {
+ ::PrvReturnString (result.GetFullPath (), sub);
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ PrvHostGetHandler
+// ---------------------------------------------------------------------------
+
+HostHandler PrvHostGetHandler (HostControlSelectorType selector)
+{
+ HostHandler fn = NULL;
+
+ // Hack for GremlinIsOn; see comments at head of HostTraps.h.
+
+ if ((selector & 0xFF00) == 0)
+ {
+ selector = hostSelectorGremlinIsRunning;
+ }
+
+ if (selector < hostSelectorLastTrapNumber)
+ {
+ fn = gHandlerTable [selector];
+ }
+
+ return fn;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCollectParameters
+// ---------------------------------------------------------------------------
+
+Bool PrvCollectParameters (EmSubroutine& sub, const string& fmt, ByteList& stackData, StringList& stringData)
+{
+ // Start parsing up the format string.
+
+ string::const_iterator iter;
+
+ for (iter = fmt.begin (); iter != fmt.end ();)
+ {
+ char ch = *iter++;
+
+ /*
+ Format specification:
+
+ % ? 12 .4 h d
+ | | | | | |
+ | | | | | +-- conversion letter
+ | | | | +---- size modifier (l, L, or h)
+ | | | +------ precision
+ | | +--------- minimum width field
+ | +------------ flags (one or more of +, -, #, 0, or space)
+ +-------------- start of specification
+ */
+
+ if (ch == '%')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+
+ // Skip over any flags.
+
+ while (ch == '+' || ch == '-' || ch == ' ' || ch == '#' || ch == '0')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+
+ // Skip over any minimum width field.
+
+ if (ch == '*')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ else
+ {
+ while (ch >= '0' && ch <= '9')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ }
+
+ // Skip over any precision.
+
+ if (ch == '.')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+
+ while (ch >= '0' && ch <= '9')
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+ }
+
+ // Get any size modifier.
+
+ enum { kSizeNone, kSizeLongInt, kSizeLongDouble, kSizeShortInt };
+
+ int mod = kSizeNone;
+
+ if (ch == 'l')
+ mod = kSizeLongInt;
+ else if (ch == 'L')
+ mod = kSizeLongDouble;
+ else if (ch == 'h')
+ mod = kSizeShortInt;
+
+ // If there was a modifier, it's been handled,
+ // so skip over it.
+
+ if (mod != kSizeNone)
+ {
+ if (iter == fmt.end ())
+ return false;
+
+ ch = *iter++;
+ }
+
+ switch (ch)
+ {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ // int, short, or long
+ if (mod == kSizeNone || mod == kSizeShortInt)
+ PrvPushShort (sub, stackData);
+ else
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ // double or long double
+ if (mod == kSizeNone)
+ PrvPushDouble (sub, stackData);
+ else
+ PrvPushLongDouble (sub, stackData);
+ break;
+
+ case 'c':
+ // int or wint_t
+ if (mod == kSizeNone)
+ PrvPushShort (sub, stackData);
+#if defined (_MSC_VER)
+ else if (sizeof (wint_t) == 2)
+ PrvPushShort (sub, stackData);
+#endif
+ else
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 's':
+ PrvPushString (sub, stackData, stringData);
+ break;
+
+ case 'p':
+ PrvPushLong (sub, stackData);
+ break;
+
+ case 'n':
+ // pointer
+ // !!! Not supported for now...
+ return false;
+
+ case '%':
+ // none
+ break;
+
+ default:
+ // Bad conversion...
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushShort
+// ---------------------------------------------------------------------------
+
+void PrvPushShort (EmSubroutine& sub, ByteList& stackData)
+{
+ // Read a 2-byte int from the caller's stack, and push it
+ // onto our stack as a 4-byte int.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "UInt16 %s", paramName);
+
+ sub.AddParam (decl);
+
+ UInt16 value;
+ sub.GetParamVal (paramName, value);
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (int), 0); // Make space for an "int"
+
+ *(int*) &stackData[oldSize] = value;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushLong
+// ---------------------------------------------------------------------------
+
+void PrvPushLong (EmSubroutine& sub, ByteList& stackData)
+{
+ // Read a 4-byte long int from the caller's stack, and push it
+ // onto our stack as a 4-byte long int.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "UInt32 %s", paramName);
+
+ sub.AddParam (decl);
+
+ UInt32 value;
+ sub.GetParamVal (paramName, value);
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (long), 0); // Make space for a "long int"
+
+ *(long*) &stackData[oldSize] = value;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushDouble
+// ---------------------------------------------------------------------------
+
+void PrvPushDouble (EmSubroutine& sub, ByteList& stackData)
+{
+ UNUSED_PARAM(sub)
+ UNUSED_PARAM(stackData)
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushLongDouble
+// ---------------------------------------------------------------------------
+
+void PrvPushLongDouble (EmSubroutine& sub, ByteList& stackData)
+{
+ UNUSED_PARAM(sub)
+ UNUSED_PARAM(stackData)
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvPushString
+// ---------------------------------------------------------------------------
+
+void PrvPushString (EmSubroutine& sub, ByteList& stackData, StringList& stringData)
+{
+ // Get the string pointer and clone the string into a new string object.
+
+ char paramName[20];
+ sprintf (paramName, "param%d", (int) stackData.size ());
+
+ char decl[20];
+ sprintf (decl, "char* %s", paramName);
+
+ sub.AddParam (decl);
+
+ emuptr stringPtr;
+ sub.GetParamVal (paramName, stringPtr);
+
+ string strCopy;
+ size_t strLen = EmMem_strlen (stringPtr);
+
+ if (strLen > 0)
+ {
+ strCopy.resize (strLen);
+ EmMem_strcpy (&strCopy[0], stringPtr);
+ }
+
+ // Add this string to the string array.
+
+ stringData.push_back (strCopy);
+
+ // In the stack data byte array, add a pointer to the string.
+
+ ByteList::size_type oldSize = stackData.size ();
+ stackData.insert (stackData.end (), sizeof (char*), 0); // Make space for a "char*"
+ *(const char**) &stackData[oldSize] = (*(stringData.end () - 1)).c_str ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvToFILE
+// ---------------------------------------------------------------------------
+
+FILE* PrvToFILE (emuptr f)
+{
+ if ((HostFILEType*) f == hostLogFile)
+ {
+ return hostLogFILE;
+ }
+
+ return (FILE*) f;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvTmFromHostTm
+// ---------------------------------------------------------------------------
+
+void PrvTmFromHostTm (struct tm& dest, const HostTmType& src)
+{
+ dest.tm_sec = src.tm_sec_;
+ dest.tm_min = src.tm_min_;
+ dest.tm_hour = src.tm_hour_;
+ dest.tm_mday = src.tm_mday_;
+ dest.tm_mon = src.tm_mon_;
+ dest.tm_year = src.tm_year_;
+ dest.tm_wday = src.tm_wday_;
+ dest.tm_yday = src.tm_yday_;
+ dest.tm_isdst = src.tm_isdst_;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvHostTmFromTm
+// ---------------------------------------------------------------------------
+
+void PrvHostTmFromTm (EmProxyHostTmType& dest, const struct tm& src)
+{
+ dest.tm_sec_ = src.tm_sec;
+ dest.tm_min_ = src.tm_min;
+ dest.tm_hour_ = src.tm_hour;
+ dest.tm_mday_ = src.tm_mday;
+ dest.tm_mon_ = src.tm_mon;
+ dest.tm_year_ = src.tm_year;
+ dest.tm_wday_ = src.tm_wday;
+ dest.tm_yday_ = src.tm_yday;
+ dest.tm_isdst_ = src.tm_isdst;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMapAndReturn
+// ---------------------------------------------------------------------------
+
+void PrvMapAndReturn (const void* p, long size, EmSubroutine& sub)
+{
+ emuptr result = EmBankMapped::GetEmulatedAddress (p);
+
+ if (result == EmMemNULL)
+ {
+ EmBankMapped::MapPhysicalMemory (p, size);
+ result = EmBankMapped::GetEmulatedAddress (p);
+ }
+
+ PUT_RESULT_VAL (emuptr, result);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMapAndReturn
+// ---------------------------------------------------------------------------
+
+void PrvMapAndReturn (const string& s, EmSubroutine& sub)
+{
+ ::PrvMapAndReturn (s.c_str (), s.size () + 1, sub);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReturnString
+// ---------------------------------------------------------------------------
+
+void PrvReturnString (const char* p, EmSubroutine& sub)
+{
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+
+ if (p)
+ {
+ gResultString = p;
+ ::PrvMapAndReturn (gResultString, sub);
+ }
+ else
+ {
+ gResultString.erase ();
+ PUT_RESULT_VAL (emuptr, EmMemNULL);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReturnString
+// ---------------------------------------------------------------------------
+
+void PrvReturnString (const string& s, EmSubroutine& sub)
+{
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+
+ gResultString = s;
+
+ ::PrvMapAndReturn (gResultString, sub);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Initialize
+// ---------------------------------------------------------------------------
+
+void Host::Initialize (void)
+{
+ memset (gHandlerTable, 0, sizeof (gHandlerTable));
+
+ gHandlerTable [hostSelectorGetHostVersion] = _HostGetHostVersion;
+ gHandlerTable [hostSelectorGetHostID] = _HostGetHostID;
+ gHandlerTable [hostSelectorGetHostPlatform] = _HostGetHostPlatform;
+ gHandlerTable [hostSelectorIsSelectorImplemented] = _HostIsSelectorImplemented;
+ gHandlerTable [hostSelectorGestalt] = _HostGestalt;
+ gHandlerTable [hostSelectorIsCallingTrap] = _HostIsCallingTrap;
+
+#if HAS_PROFILING
+ gHandlerTable [hostSelectorProfileInit] = _HostProfileInit;
+ gHandlerTable [hostSelectorProfileStart] = _HostProfileStart;
+ gHandlerTable [hostSelectorProfileStop] = _HostProfileStop;
+ gHandlerTable [hostSelectorProfileDump] = _HostProfileDump;
+ gHandlerTable [hostSelectorProfileCleanup] = _HostProfileCleanup;
+ gHandlerTable [hostSelectorProfileDetailFn] = _HostProfileDetailFn;
+ gHandlerTable [hostSelectorProfileGetCycles] = _HostProfileGetCycles;
+#endif
+
+ gHandlerTable [hostSelectorErrNo] = _HostErrNo;
+
+ gHandlerTable [hostSelectorFClose] = _HostFClose;
+ gHandlerTable [hostSelectorFEOF] = _HostFEOF;
+ gHandlerTable [hostSelectorFError] = _HostFError;
+ gHandlerTable [hostSelectorFFlush] = _HostFFlush;
+ gHandlerTable [hostSelectorFGetC] = _HostFGetC;
+ gHandlerTable [hostSelectorFGetPos] = _HostFGetPos;
+ gHandlerTable [hostSelectorFGetS] = _HostFGetS;
+ gHandlerTable [hostSelectorFOpen] = _HostFOpen;
+ gHandlerTable [hostSelectorFPrintF] = _HostFPrintF;
+ gHandlerTable [hostSelectorFPutC] = _HostFPutC;
+ gHandlerTable [hostSelectorFPutS] = _HostFPutS;
+ gHandlerTable [hostSelectorFRead] = _HostFRead;
+ gHandlerTable [hostSelectorRemove] = _HostRemove;
+ gHandlerTable [hostSelectorRename] = _HostRename;
+// gHandlerTable [hostSelectorFReopen] = _HostFReopen;
+// gHandlerTable [hostSelectorFScanF] = _HostFScanF;
+ gHandlerTable [hostSelectorFSeek] = _HostFSeek;
+ gHandlerTable [hostSelectorFSetPos] = _HostFSetPos;
+ gHandlerTable [hostSelectorFTell] = _HostFTell;
+ gHandlerTable [hostSelectorFWrite] = _HostFWrite;
+ gHandlerTable [hostSelectorTmpFile] = _HostTmpFile;
+ gHandlerTable [hostSelectorTmpNam] = _HostTmpNam;
+ gHandlerTable [hostSelectorGetEnv] = _HostGetEnv;
+
+ gHandlerTable [hostSelectorMalloc] = _HostMalloc;
+ gHandlerTable [hostSelectorRealloc] = _HostRealloc;
+ gHandlerTable [hostSelectorFree] = _HostFree;
+
+ gHandlerTable [hostSelectorAscTime] = _HostAscTime;
+ gHandlerTable [hostSelectorClock] = _HostClock;
+ gHandlerTable [hostSelectorCTime] = _HostCTime;
+// gHandlerTable [hostSelectorDiffTime] = _HostDiffTime;
+ gHandlerTable [hostSelectorGMTime] = _HostGMTime;
+ gHandlerTable [hostSelectorLocalTime] = _HostLocalTime;
+ gHandlerTable [hostSelectorMkTime] = _HostMkTime;
+ gHandlerTable [hostSelectorStrFTime] = _HostStrFTime;
+ gHandlerTable [hostSelectorTime] = _HostTime;
+
+ gHandlerTable [hostSelectorMkDir] = _HostMkDir;
+ gHandlerTable [hostSelectorRmDir] = _HostRmDir;
+ gHandlerTable [hostSelectorOpenDir] = _HostOpenDir;
+ gHandlerTable [hostSelectorReadDir] = _HostReadDir;
+ gHandlerTable [hostSelectorCloseDir] = _HostCloseDir;
+
+// gHandlerTable [hostSelectorFStat] = _HostFStat;
+ gHandlerTable [hostSelectorStat] = _HostStat;
+
+ gHandlerTable [hostSelectorGetFileAttr] = _HostGetFileAttr;
+ gHandlerTable [hostSelectorSetFileAttr] = _HostSetFileAttr;
+
+// gHandlerTable [hostSelectorFTruncate] = _HostFTruncate;
+ gHandlerTable [hostSelectorTruncate] = _HostTruncate;
+
+ gHandlerTable [hostSelectorUTime] = _HostUTime;
+
+ gHandlerTable [hostSelectorGremlinIsRunning] = _HostGremlinIsRunning;
+ gHandlerTable [hostSelectorGremlinNumber] = _HostGremlinNumber;
+ gHandlerTable [hostSelectorGremlinCounter] = _HostGremlinCounter;
+ gHandlerTable [hostSelectorGremlinLimit] = _HostGremlinLimit;
+ gHandlerTable [hostSelectorGremlinNew] = _HostGremlinNew;
+
+ gHandlerTable [hostSelectorImportFile] = _HostImportFile;
+ gHandlerTable [hostSelectorExportFile] = _HostExportFile;
+ gHandlerTable [hostSelectorSaveScreen] = _HostSaveScreen;
+ gHandlerTable [hostSelectorImportFileWithID] = _HostImportFileWithID;
+
+ gHandlerTable [hostSelectorExgLibOpen] = _HostExgLibOpen;
+ gHandlerTable [hostSelectorExgLibClose] = _HostExgLibClose;
+ gHandlerTable [hostSelectorExgLibSleep] = _HostExgLibSleep;
+ gHandlerTable [hostSelectorExgLibWake] = _HostExgLibWake;
+ gHandlerTable [hostSelectorExgLibHandleEvent] = _HostExgLibHandleEvent;
+ gHandlerTable [hostSelectorExgLibConnect] = _HostExgLibConnect;
+ gHandlerTable [hostSelectorExgLibAccept] = _HostExgLibAccept;
+ gHandlerTable [hostSelectorExgLibDisconnect] = _HostExgLibDisconnect;
+ gHandlerTable [hostSelectorExgLibPut] = _HostExgLibPut;
+ gHandlerTable [hostSelectorExgLibGet] = _HostExgLibGet;
+ gHandlerTable [hostSelectorExgLibSend] = _HostExgLibSend;
+ gHandlerTable [hostSelectorExgLibReceive] = _HostExgLibReceive;
+ gHandlerTable [hostSelectorExgLibControl] = _HostExgLibControl;
+ gHandlerTable [hostSelectorExgLibRequest] = _HostExgLibRequest;
+
+ gHandlerTable [hostSelectorGetPreference] = _HostGetPreference;
+ gHandlerTable [hostSelectorSetPreference] = _HostSetPreference;
+
+ gHandlerTable [hostSelectorLogFile] = _HostLogFile;
+ gHandlerTable [hostSelectorSetLogFileSize] = _HostSetLogFileSize;
+
+// gHandlerTable [hostSelectorSessionCreate] = _HostSessionCreate;
+// gHandlerTable [hostSelectorSessionOpen] = _HostSessionOpen;
+ gHandlerTable [hostSelectorSessionSave] = _HostSessionSave;
+ gHandlerTable [hostSelectorSessionClose] = _HostSessionClose;
+ gHandlerTable [hostSelectorSessionQuit] = _HostSessionQuit;
+ gHandlerTable [hostSelectorSignalSend] = _HostSignalSend;
+ gHandlerTable [hostSelectorSignalWait] = _HostSignalWait;
+ gHandlerTable [hostSelectorSignalResume] = _HostSignalResume;
+
+#if HAS_TRACER
+ gHandlerTable [hostSelectorTraceInit] = _HostTraceInit;
+ gHandlerTable [hostSelectorTraceClose] = _HostTraceClose;
+ gHandlerTable [hostSelectorTraceOutputT] = _HostTraceOutputT;
+ gHandlerTable [hostSelectorTraceOutputTL] = _HostTraceOutputTL;
+ gHandlerTable [hostSelectorTraceOutputVT] = _HostTraceOutputVT;
+ gHandlerTable [hostSelectorTraceOutputVTL] = _HostTraceOutputVTL;
+ gHandlerTable [hostSelectorTraceOutputB] = _HostTraceOutputB;
+#endif
+
+ gHandlerTable [hostSelectorDbgSetDataBreak] = _HostDbgSetDataBreak;
+ gHandlerTable [hostSelectorDbgClearDataBreak] = _HostDbgClearDataBreak;
+
+ gHandlerTable [hostSelectorSlotMax] = _HostSlotMax;
+ gHandlerTable [hostSelectorSlotRoot] = _HostSlotRoot;
+ gHandlerTable [hostSelectorSlotHasCard] = _HostSlotHasCard;
+
+ gHandlerTable [hostSelectorGetFile] = _HostGetFile;
+ gHandlerTable [hostSelectorPutFile] = _HostPutFile;
+ gHandlerTable [hostSelectorGetDirectory] = _HostGetDirectory;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Reset
+// ---------------------------------------------------------------------------
+
+void Host::Reset (void)
+{
+ ::PrvReleaseAllResources ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Save
+// ---------------------------------------------------------------------------
+
+void Host::Save (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Load
+// ---------------------------------------------------------------------------
+
+void Host::Load (SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Host::Dispose
+// ---------------------------------------------------------------------------
+
+void Host::Dispose (void)
+{
+ ::PrvReleaseAllResources ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvReleaseAllResources
+// ---------------------------------------------------------------------------
+
+void PrvReleaseAllResources (void)
+{
+ // Close all open files.
+
+ {
+ vector<FILE*>::iterator iter = gOpenFiles.begin ();
+ while (iter != gOpenFiles.end ())
+ {
+ fclose (*iter);
+ ++iter;
+ }
+
+ gOpenFiles.clear ();
+ }
+
+ // Close all open directories.
+
+ {
+ vector<MyDIR*>::iterator iter = gOpenDirs.begin ();
+ while (iter != gOpenDirs.end ())
+ {
+ delete *iter;
+ ++iter;
+ }
+
+ gOpenDirs.clear ();
+
+ // Unmap any mapped gHostDirEnt.
+
+ EmBankMapped::UnmapPhysicalMemory (&gHostDirEnt);
+ }
+
+ // Release all allocated memory.
+
+ {
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ EmBankMapped::UnmapPhysicalMemory (*iter);
+ Platform::DisposeMemory (*iter);
+ ++iter;
+ }
+
+ gAllocatedBlocks.clear ();
+ }
+
+ // Unmap misc memory.
+
+ EmBankMapped::UnmapPhysicalMemory (gResultString.c_str ());
+ EmBankMapped::UnmapPhysicalMemory (&gGMTime);
+ EmBankMapped::UnmapPhysicalMemory (&gLocalTime);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMalloc
+// ---------------------------------------------------------------------------
+
+emuptr PrvMalloc (long size)
+{
+ // Prepare the return value.
+
+ emuptr result = EmMemNULL;
+
+ // Call the function.
+
+ void* newPtr = NULL;
+
+ try
+ {
+ newPtr = Platform::AllocateMemory (size);
+ }
+ catch (...)
+ {
+ }
+
+ // If the call worked, remember the pointer, map
+ // it into emulated space, and return the mapped
+ // pointer to the caller.
+
+ if (newPtr)
+ {
+ gAllocatedBlocks.push_back (newPtr);
+ EmBankMapped::MapPhysicalMemory (newPtr, size);
+
+ result = EmBankMapped::GetEmulatedAddress (newPtr);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvRealloc
+// ---------------------------------------------------------------------------
+
+emuptr PrvRealloc (emuptr p, long size)
+{
+ // Prepare the return value.
+
+ emuptr result = EmMemNULL;
+
+ // Recover the real pointer
+
+ void* oldPtr = EmBankMapped::GetRealAddress (p);
+ if (oldPtr)
+ {
+ // Find the saved pointer in our list so that we can
+ // remove it.
+
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ if (*iter == oldPtr)
+ {
+ // Found the saved pointer. Now try the realloc.
+
+ void* newPtr = NULL;
+
+ try
+ {
+ newPtr = Platform::ReallocMemory (oldPtr, size);
+ }
+ catch (...)
+ {
+ }
+
+ // If that worked, then do the bookkeeping.
+
+ if (newPtr)
+ {
+ gAllocatedBlocks.erase (iter);
+ gAllocatedBlocks.push_back (newPtr);
+
+ EmBankMapped::UnmapPhysicalMemory (oldPtr);
+ EmBankMapped::MapPhysicalMemory (newPtr, size);
+
+ result = EmBankMapped::GetEmulatedAddress (newPtr);
+ }
+ else
+ {
+ // Could not realloc! Just return NULL
+ // (already stored in "result").
+ }
+
+ return result;
+ }
+
+ ++iter;
+ }
+
+ EmAssert (false);
+ // !!! Handle not finding saved pointer
+ }
+ else
+ {
+ EmAssert (false);
+ // !!! Handle not finding real address.
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvFree
+// ---------------------------------------------------------------------------
+
+void PrvFree (emuptr p)
+{
+ // Check the parameters.
+
+ if (p)
+ {
+ // Recover the real pointer
+
+ void* oldPtr = EmBankMapped::GetRealAddress (p);
+ if (oldPtr)
+ {
+ // Find the saved pointer in our list so that we can
+ // remove it.
+
+ vector<void*>::iterator iter = gAllocatedBlocks.begin ();
+ while (iter != gAllocatedBlocks.end ())
+ {
+ if (*iter == oldPtr)
+ {
+ Platform::DisposeMemory (oldPtr);
+
+ EmBankMapped::UnmapPhysicalMemory (*iter);
+ gAllocatedBlocks.erase (iter);
+
+ return;
+ }
+
+ ++iter;
+ }
+
+ EmAssert (false);
+ // !!! Handle not finding saved pointer
+ }
+ else
+ {
+ EmAssert (false);
+ // !!! Handle not finding real address.
+ }
+ }
+}
diff --git a/SrcShared/HostControl.h b/SrcShared/HostControl.h
new file mode 100644
index 0000000..6bc70fd
--- /dev/null
+++ b/SrcShared/HostControl.h
@@ -0,0 +1,938 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _HOSTCONTROL_H_
+#define _HOSTCONTROL_H_
+
+#if !defined (__SYSTRAPS_H_) && !defined (__CORETRAPS_H_)
+#error "Please #include either <CoreTraps.h> or <SysTraps.h>, depending on what's in your Palm Includes directory."
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ Set the values for selectors. Note that these values MUST be
+ two bytes long and have the high byte be non-zero. The reason
+ for this has to do with the way SysGremlins was originally
+ declared. It took a GremlinsSelector enumerated value. Originally,
+ there was only one value, and it was zero. The way the 68K compiler
+ works, it decides that GremlinsSelectors are only one byte long,
+ so a call to SysGremlins would push one byte onto the stack. Because
+ all values on the stack need to be word-aligned, the processor
+ subtracts 1 from the stack before pushing on the byte. Therefore,
+ the stack looks like:
+
+ previous contents
+ garbage byte
+ selector
+ return address
+
+ When the two middle bytes are read together as a word, they appear
+ as: <selector> * 256 + <garbage byte>.
+
+ With this setup, we have two choices: leave the selector size at
+ one byte and limit ourselves to 256 functions, or define the selector
+ to be a two byte value, with the first 256 values (all those with 0x00
+ in the upper byte) to be GremlinIsOn. The latter sounds preferable, so
+ we start the new selectors at 0x0100.
+*/
+
+
+ // Host information selectors
+
+#define hostSelectorGetHostVersion 0x0100
+#define hostSelectorGetHostID 0x0101
+#define hostSelectorGetHostPlatform 0x0102
+#define hostSelectorIsSelectorImplemented 0x0103
+#define hostSelectorGestalt 0x0104
+#define hostSelectorIsCallingTrap 0x0105
+
+
+ // Profiler selectors
+
+#define hostSelectorProfileInit 0x0200
+#define hostSelectorProfileStart 0x0201
+#define hostSelectorProfileStop 0x0202
+#define hostSelectorProfileDump 0x0203
+#define hostSelectorProfileCleanup 0x0204
+#define hostSelectorProfileDetailFn 0x0205
+#define hostSelectorProfileGetCycles 0x0206
+
+
+ // Std C Library wrapper selectors
+
+#define hostSelectorErrNo 0x0300
+
+#define hostSelectorFClose 0x0301
+#define hostSelectorFEOF 0x0302
+#define hostSelectorFError 0x0303
+#define hostSelectorFFlush 0x0304
+#define hostSelectorFGetC 0x0305
+#define hostSelectorFGetPos 0x0306
+#define hostSelectorFGetS 0x0307
+#define hostSelectorFOpen 0x0308
+#define hostSelectorFPrintF 0x0309 /* Floating point not yet supported in Poser */
+#define hostSelectorFPutC 0x030A
+#define hostSelectorFPutS 0x030B
+#define hostSelectorFRead 0x030C
+#define hostSelectorRemove 0x030D
+#define hostSelectorRename 0x030E
+#define hostSelectorFReopen 0x030F /* Not yet implemented in Poser */
+#define hostSelectorFScanF 0x0310 /* Not yet implemented */
+#define hostSelectorFSeek 0x0311
+#define hostSelectorFSetPos 0x0312
+#define hostSelectorFTell 0x0313
+#define hostSelectorFWrite 0x0314
+#define hostSelectorTmpFile 0x0315
+#define hostSelectorTmpNam 0x0316
+
+#define hostSelectorGetEnv 0x0317
+
+#define hostSelectorMalloc 0x0318
+#define hostSelectorRealloc 0x0319
+#define hostSelectorFree 0x031A
+
+ // time.h wrappers
+#define hostSelectorAscTime 0x0370
+#define hostSelectorClock 0x0371
+#define hostSelectorCTime 0x0372
+// #define hostSelectorDiffTime 0x0373
+#define hostSelectorGMTime 0x0374
+#define hostSelectorLocalTime 0x0375
+#define hostSelectorMkTime 0x0376
+#define hostSelectorStrFTime 0x0377
+#define hostSelectorTime 0x0378
+
+ // dirent.h wrappers
+#define hostSelectorOpenDir 0x0380
+#define hostSelectorReadDir 0x0381
+// #define hostSelectorRewindDir 0x0382
+#define hostSelectorCloseDir 0x0383
+// #define hostSelectorTellDir 0x0384
+// #define hostSelectorSeekDir 0x0385
+// #define hostSelectorScanDir 0x0386
+
+ // fcntl.h wrappers
+// #define hostSelectorOpen 0x0386
+// #define hostSelectorCreat 0x0388
+// #define hostSelectorFcntl 0x0389
+
+ // unistd.h wrappers
+// #define hostSelectorAccess 0x038A
+// #define hostSelectorChDir 0x038B
+// #define hostSelectorClose 0x038C
+// #define hostSelectorDup 0x038D
+// #define hostSelectorDup2 0x038E
+// #define hostSelectorGetCwd 0x038F
+// #define hostSelectorIsATTY 0x0390
+// #define hostSelectorLink 0x0391
+// #define hostSelectorLSeek 0x0392
+// #define hostSelectorRead 0x0393
+#define hostSelectorRmDir 0x0394
+// #define hostSelectorTTYName 0x0395
+// #define hostSelectorUnlink 0x0396
+// #define hostSelectorWrite 0x0397
+
+// #define hostSelectorFChDir 0x0398
+// #define hostSelectorFChMod 0x0399
+// #define hostSelectorFileNo 0X039A
+// #define hostSelectorFSync 0x039B
+// #define hostSelectorFTruncate 0x039C
+// #define hostSelectorGetHostName 0x039D
+// #define hostSelectorGetWD 0x039E
+// #define hostSelectorMkSTemp 0x039F
+// #define hostSelectorMkTemp 0x03A0
+// #define hostSelectorRe_Comp 0x03A1
+// #define hostSelectorRe_Exec 0x03A2
+// #define hostSelectorReadLink 0x03A3
+// #define hostSelectorSetHostName 0x03A4
+// #define hostSelectorSymLink 0x03A5
+// #define hostSelectorSync 0x03A6
+#define hostSelectorTruncate 0x03A7
+
+ // sys/stat.h wrappers
+// #define hostSelectorChMod 0x03A8
+// #define hostSelectorFStat 0x03A9
+#define hostSelectorMkDir 0x03AA
+#define hostSelectorStat 0x03AB
+// #define hostSelectorLStat 0x03AC
+
+ // sys/time.h wrappers
+// #define hostSelectorGetTimeOfDay 0x03AD
+#define hostSelectorUTime 0x03AE
+
+ // DOS attr
+#define hostSelectorGetFileAttr 0x03AF
+#define hostSelectorSetFileAttr 0x03B0
+
+ // Gremlin selectors
+
+#define hostSelectorGremlinIsRunning 0x0400
+#define hostSelectorGremlinNumber 0x0401
+#define hostSelectorGremlinCounter 0x0402
+#define hostSelectorGremlinLimit 0x0403
+#define hostSelectorGremlinNew 0x0404
+
+
+ // Database selectors
+
+#define hostSelectorImportFile 0x0500
+#define hostSelectorExportFile 0x0501
+#define hostSelectorSaveScreen 0x0502
+#define hostSelectorImportFileWithID 0x0503
+
+#define hostSelectorExgLibOpen 0x0580
+#define hostSelectorExgLibClose 0x0581
+#define hostSelectorExgLibSleep 0x0582
+#define hostSelectorExgLibWake 0x0583
+#define hostSelectorExgLibHandleEvent 0x0584
+#define hostSelectorExgLibConnect 0x0585
+#define hostSelectorExgLibAccept 0x0586
+#define hostSelectorExgLibDisconnect 0x0587
+#define hostSelectorExgLibPut 0x0588
+#define hostSelectorExgLibGet 0x0589
+#define hostSelectorExgLibSend 0x058A
+#define hostSelectorExgLibReceive 0x058B
+#define hostSelectorExgLibControl 0x058C
+#define hostSelectorExgLibRequest 0x058D
+
+
+ // Preferences selectors
+
+#define hostSelectorGetPreference 0x0600
+#define hostSelectorSetPreference 0x0601
+
+
+ // Logging selectors
+
+#define hostSelectorLogFile 0x0700
+#define hostSelectorSetLogFileSize 0x0701
+
+
+ // RPC selectors
+
+#define hostSelectorSessionCreate 0x0800 /* Not yet implemented in Poser */
+#define hostSelectorSessionOpen 0x0801 /* Not yet implemented in Poser */
+#define hostSelectorSessionClose 0x0802
+#define hostSelectorSessionQuit 0x0803
+#define hostSelectorSignalSend 0x0804
+#define hostSelectorSignalWait 0x0805
+#define hostSelectorSignalResume 0x0806
+#define hostSelectorSessionSave 0x0807
+
+
+ // External tracing tool support
+
+#define hostSelectorTraceInit 0x0900
+#define hostSelectorTraceClose 0x0901
+#define hostSelectorTraceOutputT 0x0902
+#define hostSelectorTraceOutputTL 0x0903
+#define hostSelectorTraceOutputVT 0x0904
+#define hostSelectorTraceOutputVTL 0x0905
+#define hostSelectorTraceOutputB 0x0906
+
+
+ // External debugger support
+
+#define hostSelectorDbgSetDataBreak 0x0980 // mcc 13 june 2001
+#define hostSelectorDbgClearDataBreak 0x0981 // mcc 13 june 2001
+
+
+ // Slot support
+
+#define hostSelectorSlotMax 0x0A00
+#define hostSelectorSlotRoot 0x0A01
+#define hostSelectorSlotHasCard 0x0A02
+
+
+ // File choosing support
+
+#define hostSelectorGetFile 0x0B00
+#define hostSelectorPutFile 0x0B01
+#define hostSelectorGetDirectory 0x0B02
+
+#define hostSelectorLastTrapNumber 0x0BFF
+
+
+ // * Types
+
+typedef UInt16 HostControlSelectorType;
+typedef Int32 HostBoolType;
+typedef Int32 HostClockType;
+typedef Int32 HostErrType;
+typedef Int32 HostIDType;
+typedef Int32 HostPlatformType;
+typedef Int32 HostSignalType;
+typedef Int32 HostSizeType;
+typedef Int32 HostTimeType;
+
+
+ // * HostDIRType
+
+struct HostDIRType
+{
+ long _field;
+};
+
+typedef struct HostDIRType HostDIRType;
+
+
+ // * HostDirEntType
+
+#define HOST_NAME_MAX 255
+
+struct HostDirEntType
+{
+ char d_name[HOST_NAME_MAX + 1];
+};
+
+typedef struct HostDirEntType HostDirEntType;
+
+
+ // * HostFILEType
+
+struct HostFILEType
+{
+ long _field;
+};
+
+typedef struct HostFILEType HostFILEType;
+
+
+ // * HostGremlinInfoType
+
+struct HostGremlinInfoType
+{
+ long fFirstGremlin;
+ long fLastGremlin;
+ long fSaveFrequency;
+ long fSwitchDepth;
+ long fMaxDepth;
+ char fAppNames[200]; // Comma-seperated list of application names
+ // to run Gremlins on. If the string is empty,
+ // all applications are fair game. If the string
+ // begins with a '-' (e.g., "-Address,Datebook"),
+ // then all applications named in the list are
+ // excluded instead of included.
+};
+
+typedef struct HostGremlinInfoType HostGremlinInfoType;
+
+
+ // * HostStatType
+ // Note that the field names here have an underscore appended to
+ // them in order to differentiate them from "compatibility macros"
+ // under Solaris.
+
+struct HostStatType
+{
+ unsigned long st_dev_;
+ unsigned long st_ino_;
+ unsigned long st_mode_;
+ unsigned long st_nlink_;
+ unsigned long st_uid_;
+ unsigned long st_gid_;
+ unsigned long st_rdev_;
+ HostTimeType st_atime_;
+ HostTimeType st_mtime_;
+ HostTimeType st_ctime_;
+ unsigned long st_size_;
+ unsigned long st_blksize_;
+ unsigned long st_blocks_;
+ unsigned long st_flags_;
+};
+
+typedef struct HostStatType HostStatType;
+
+
+ // * HostTmType
+ // Note that the field names here have an underscore appended to
+ // them for consistancy with HostStatType.
+
+struct HostTmType
+{
+ long tm_sec_; /* seconds after the minute - [0,59] */
+ long tm_min_; /* minutes after the hour - [0,59] */
+ long tm_hour_; /* hours since midnight - [0,23] */
+ long tm_mday_; /* day of the month - [1,31] */
+ long tm_mon_; /* months since January - [0,11] */
+ long tm_year_; /* years since 1900 */
+ long tm_wday_; /* days since Sunday - [0,6] */
+ long tm_yday_; /* days since January 1 - [0,365] */
+ long tm_isdst_; /* daylight savings time flag */
+};
+
+typedef struct HostTmType HostTmType;
+
+
+ // * HostUTimeType
+ // Note that the field names here have an underscore appended to
+ // them for consistancy with HostStatType.
+
+struct HostUTimeType
+{
+ HostTimeType crtime_; /* creation time */
+ HostTimeType actime_; /* access time */
+ HostTimeType modtime_; /* modification time */
+};
+
+typedef struct HostUTimeType HostUTimeType;
+
+
+ // * Backward compatiblity
+
+typedef HostControlSelectorType HostControlTrapNumber;
+typedef HostBoolType HostBool;
+typedef HostErrType HostErr;
+typedef HostIDType HostID;
+typedef HostPlatformType HostPlatform;
+typedef HostSignalType HostSignal;
+typedef HostFILEType HostFILE;
+
+
+
+#ifndef hostErrorClass
+ #define hostErrorClass 0x1C00 // Host Control Manager
+#else
+ #if hostErrorClass != 0x1C00
+ #error "You cannot change hostErrorClass without telling us."
+ #endif
+#endif
+
+enum // HostErrType values
+{
+ hostErrNone = 0,
+
+ hostErrBase = hostErrorClass,
+
+ hostErrUnknownGestaltSelector,
+ hostErrDiskError,
+ hostErrOutOfMemory,
+ hostErrMemReadOutOfRange,
+ hostErrMemWriteOutOfRange,
+ hostErrMemInvalidPtr,
+ hostErrInvalidParameter,
+ hostErrTimeout,
+ hostErrInvalidDeviceType,
+ hostErrInvalidRAMSize,
+ hostErrFileNotFound,
+ hostErrRPCCall, // Issued if the following functions are not called remotely:
+ // HostSessionCreate
+ // HostSessionOpen
+ // HostSessionClose
+ // HostSessionQuit
+ // HostSignalWait
+ // HostSignalResume
+ hostErrSessionRunning, // Issued by HostSessionCreate, HostSessionOpen, and
+ // HostSessionQuit if a session is running.
+ hostErrSessionNotRunning, // Issued by HostSessionClose or HostSessionSave if no session is running.
+ hostErrNoSignalWaiters, // Issued by HostSendSignal if no one's waiting for a signal.
+ hostErrSessionNotPaused, // Issued when HostSignalResume, but the session was not
+ // halted from a HostSignalSend call.
+
+ hostErrPermissions,
+ hostErrFileNameTooLong,
+ hostErrNotADirectory,
+ hostErrTooManyFiles,
+ hostErrFileTooBig,
+ hostErrReadOnlyFS,
+ hostErrIsDirectory,
+ hostErrExists,
+ hostErrOpNotAvailable,
+ hostErrDirNotEmpty,
+ hostErrDiskFull,
+ hostErrUnknownError,
+ hostErrProfilingNotReady
+
+ // (Add new error codes here at the end.)
+};
+
+
+enum // HostIDType values
+{
+ hostIDPalmOS, // The plastic thingy
+ hostIDPalmOSEmulator, // The Copilot thingy
+ hostIDPalmOSSimulator // The Mac libraries you link with thingy
+};
+
+
+enum // HostPlatformType values
+{
+ hostPlatformPalmOS,
+ hostPlatformWindows,
+ hostPlatformMacintosh,
+ hostPlatformUnix
+};
+
+enum // HostSignalType values
+{
+ hostSignalReserved,
+ hostSignalIdle,
+ hostSignalQuit,
+#if 0
+ // (Proposed...not supported yet)
+ hostSignalSessionStarted,
+ hostSignalSessionStopped,
+ hostSignalHordeStarted,
+ hostSignalGremlinStarted,
+ hostSignalGremlinSuspended,
+ hostSignalGremlinResumed,
+ hostSignalGremlinStopped,
+ hostSignalHordeStopped,
+#endif
+ hostSignalUser = 0x4000 // User-defined values start here and go up.
+};
+
+enum // HostGet/SetFileAttr flags, matching EmFileAttr flags
+{
+ hostFileAttrReadOnly = 1,
+ hostFileAttrHidden = 2,
+ hostFileAttrSystem = 4
+};
+
+// Use these to call FtrGet to see if you're running under the
+// Palm OS Emulator. If not, FtrGet will return ftrErrNoSuchFeature.
+
+#define kPalmOSEmulatorFeatureCreator ('pose')
+#define kPalmOSEmulatorFeatureNumber (0)
+
+
+// Define this, since SysTraps.h doesn't have it.
+
+#ifdef __SYSTRAPS_H_
+#define sysTrapHostControl sysTrapSysGremlins
+#endif
+
+
+// Define HOST_TRAP
+
+#if defined (_SYSTEM_API)
+
+#define HOST_TRAP(selector) \
+ _SYSTEM_API(_CALL_WITH_16BIT_SELECTOR)(_SYSTEM_TABLE, sysTrapHostControl, selector)
+
+#else
+
+#define HOST_TRAP(selector) \
+ FIVEWORD_INLINE( \
+ 0x3F3C, selector, /* MOVE.W #selector, -(A7) */ \
+ m68kTrapInstr + sysDispatchTrapNum, /* TRAP $F */ \
+ sysTrapHostControl, /* sysTrapHostControl */ \
+ 0x544F) /* ADD.Q #2, A7 */
+#endif
+
+
+/* ==================================================================== */
+/* Host environment-related calls */
+/* ==================================================================== */
+
+Int32 HostGetHostVersion(void)
+ HOST_TRAP(hostSelectorGetHostVersion);
+
+HostIDType HostGetHostID(void)
+ HOST_TRAP(hostSelectorGetHostID);
+
+HostPlatformType HostGetHostPlatform(void)
+ HOST_TRAP(hostSelectorGetHostPlatform);
+
+HostBoolType HostIsSelectorImplemented(long selector)
+ HOST_TRAP(hostSelectorIsSelectorImplemented);
+
+HostErrType HostGestalt(long gestSel, long* response)
+ HOST_TRAP(hostSelectorGestalt);
+
+HostBoolType HostIsCallingTrap(void)
+ HOST_TRAP(hostSelectorIsCallingTrap);
+
+
+/* ==================================================================== */
+/* Profiling-related calls */
+/* ==================================================================== */
+
+HostErrType HostProfileInit(long maxCalls, long maxDepth)
+ HOST_TRAP(hostSelectorProfileInit);
+
+HostErrType HostProfileDetailFn(void* addr, HostBoolType logDetails)
+ HOST_TRAP(hostSelectorProfileDetailFn);
+
+HostErrType HostProfileStart(void)
+ HOST_TRAP(hostSelectorProfileStart);
+
+HostErrType HostProfileStop(void)
+ HOST_TRAP(hostSelectorProfileStop);
+
+HostErrType HostProfileDump(const char* filenameP)
+ HOST_TRAP(hostSelectorProfileDump);
+
+HostErrType HostProfileCleanup(void)
+ HOST_TRAP(hostSelectorProfileCleanup);
+
+long HostProfileGetCycles(void)
+ HOST_TRAP(hostSelectorProfileGetCycles);
+
+
+/* ==================================================================== */
+/* Std C Library-related calls */
+/* ==================================================================== */
+
+long HostErrNo(void)
+ HOST_TRAP(hostSelectorErrNo);
+
+
+long HostFClose(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFClose);
+
+long HostFEOF(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFEOF);
+
+long HostFError(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFError);
+
+long HostFFlush(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFFlush);
+
+long HostFGetC(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFGetC);
+
+long HostFGetPos(HostFILEType* fileP, long* posP)
+ HOST_TRAP(hostSelectorFGetPos);
+
+char* HostFGetS(char* s, long n, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFGetS);
+
+HostFILEType* HostFOpen(const char* name, const char* mode)
+ HOST_TRAP(hostSelectorFOpen);
+
+long HostFPrintF(HostFILEType* fileP, const char* fmt, ...)
+ HOST_TRAP(hostSelectorFPrintF);
+
+long HostFPutC(long c, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFPutC);
+
+long HostFPutS(const char* s, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFPutS);
+
+long HostFRead(void* buffer, long size, long count, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFRead);
+
+HostFILEType* HostFReopen(const char* name, const char* mode, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFReopen);
+
+long HostFScanF(HostFILEType* fileP, const char* fmt, ...)
+ HOST_TRAP(hostSelectorFScanF);
+
+long HostFSeek(HostFILEType* fileP, long offset, long origin)
+ HOST_TRAP(hostSelectorFSeek);
+
+long HostFSetPos(HostFILEType* fileP, long* pos)
+ HOST_TRAP(hostSelectorFSetPos);
+
+long HostFTell(HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFTell);
+
+long HostFWrite(const void* buffer, long size, long count, HostFILEType* fileP)
+ HOST_TRAP(hostSelectorFWrite);
+
+long HostRemove(const char* nameP)
+ HOST_TRAP(hostSelectorRemove);
+
+long HostRename(const char* oldNameP, const char* newNameP)
+ HOST_TRAP(hostSelectorRename);
+
+HostFILEType* HostTmpFile(void)
+ HOST_TRAP(hostSelectorTmpFile);
+
+char* HostTmpNam(char* nameP)
+ HOST_TRAP(hostSelectorTmpNam);
+
+char* HostGetEnv(const char* nameP)
+ HOST_TRAP(hostSelectorGetEnv);
+
+
+void* HostMalloc(long size)
+ HOST_TRAP(hostSelectorMalloc);
+
+void* HostRealloc(void* p, long size)
+ HOST_TRAP(hostSelectorRealloc);
+
+void HostFree(void* p)
+ HOST_TRAP(hostSelectorFree);
+
+
+char* HostAscTime(const HostTmType*)
+ HOST_TRAP(hostSelectorAscTime);
+
+HostClockType HostClock(void)
+ HOST_TRAP(hostSelectorClock);
+
+char* HostCTime(const HostTimeType*)
+ HOST_TRAP(hostSelectorCTime);
+
+//double HostDiffTime(HostTimeType, HostTimeType)
+// HOST_TRAP(hostSelectorDiffTime);
+
+HostTmType* HostGMTime(const HostTimeType*)
+ HOST_TRAP(hostSelectorGMTime);
+
+HostTmType* HostLocalTime(const HostTimeType*)
+ HOST_TRAP(hostSelectorLocalTime);
+
+HostTimeType HostMkTime(HostTmType*)
+ HOST_TRAP(hostSelectorMkTime);
+
+HostSizeType HostStrFTime(char*, HostSizeType, const char*, const HostTmType*)
+ HOST_TRAP(hostSelectorStrFTime);
+
+HostTimeType HostTime(HostTimeType*)
+ HOST_TRAP(hostSelectorTime);
+
+
+long HostMkDir(const char*)
+ HOST_TRAP(hostSelectorMkDir);
+
+long HostRmDir(const char*)
+ HOST_TRAP(hostSelectorRmDir);
+
+HostDIRType* HostOpenDir(const char*)
+ HOST_TRAP(hostSelectorOpenDir);
+
+HostDirEntType* HostReadDir(HostDIRType*)
+ HOST_TRAP(hostSelectorReadDir);
+
+long HostCloseDir(HostDIRType*)
+ HOST_TRAP(hostSelectorCloseDir);
+
+
+long HostStat(const char*, HostStatType*)
+ HOST_TRAP(hostSelectorStat);
+
+long HostTruncate(const char*, long)
+ HOST_TRAP(hostSelectorTruncate);
+
+
+long HostUTime (const char*, HostUTimeType*)
+ HOST_TRAP(hostSelectorUTime);
+
+long HostGetFileAttr(const char*, long*)
+ HOST_TRAP(hostSelectorGetFileAttr);
+
+long HostSetFileAttr(const char*, long)
+ HOST_TRAP(hostSelectorSetFileAttr);
+
+
+/* ==================================================================== */
+/* Gremlin-related calls */
+/* ==================================================================== */
+
+HostBoolType HostGremlinIsRunning(void)
+ HOST_TRAP(hostSelectorGremlinIsRunning);
+
+long HostGremlinNumber(void)
+ HOST_TRAP(hostSelectorGremlinNumber);
+
+long HostGremlinCounter(void)
+ HOST_TRAP(hostSelectorGremlinCounter);
+
+long HostGremlinLimit(void)
+ HOST_TRAP(hostSelectorGremlinLimit);
+
+HostErrType HostGremlinNew(const HostGremlinInfoType*)
+ HOST_TRAP(hostSelectorGremlinNew);
+
+
+/* ==================================================================== */
+/* Import/export-related calls */
+/* ==================================================================== */
+
+HostErrType HostImportFile(const char* fileName, long cardNum)
+ HOST_TRAP(hostSelectorImportFile);
+
+HostErrType HostImportFileWithID(const char* fileName, long cardNum, LocalID* newIDP)
+ HOST_TRAP(hostSelectorImportFileWithID);
+
+HostErrType HostExportFile(const char* fileName, long cardNum, const char* dbName)
+ HOST_TRAP(hostSelectorExportFile);
+
+HostErrType HostSaveScreen(const char* fileName)
+ HOST_TRAP(hostSelectorSaveScreen);
+
+ // These are private, internal functions. Third party applications
+ // should not be calling them.
+
+Err HostExgLibOpen (UInt16 libRefNum)
+ HOST_TRAP(hostSelectorExgLibOpen);
+
+Err HostExgLibClose (UInt16 libRefNum)
+ HOST_TRAP(hostSelectorExgLibClose);
+
+Err HostExgLibSleep (UInt16 libRefNum)
+ HOST_TRAP(hostSelectorExgLibSleep);
+
+Err HostExgLibWake (UInt16 libRefNum)
+ HOST_TRAP(hostSelectorExgLibWake);
+
+Boolean HostExgLibHandleEvent (UInt16 libRefNum, void* eventP)
+ HOST_TRAP(hostSelectorExgLibHandleEvent);
+
+Err HostExgLibConnect (UInt16 libRefNum, void* exgSocketP)
+ HOST_TRAP(hostSelectorExgLibConnect);
+
+Err HostExgLibAccept (UInt16 libRefNum, void* exgSocketP)
+ HOST_TRAP(hostSelectorExgLibAccept);
+
+Err HostExgLibDisconnect (UInt16 libRefNum, void* exgSocketP,Err error)
+ HOST_TRAP(hostSelectorExgLibDisconnect);
+
+Err HostExgLibPut (UInt16 libRefNum, void* exgSocketP)
+ HOST_TRAP(hostSelectorExgLibPut);
+
+Err HostExgLibGet (UInt16 libRefNum, void* exgSocketP)
+ HOST_TRAP(hostSelectorExgLibGet);
+
+UInt32 HostExgLibSend (UInt16 libRefNum, void* exgSocketP, const void* const bufP, const UInt32 bufLen, Err* errP)
+ HOST_TRAP(hostSelectorExgLibSend);
+
+UInt32 HostExgLibReceive (UInt16 libRefNum, void* exgSocketP, void* bufP, const UInt32 bufSize, Err* errP)
+ HOST_TRAP(hostSelectorExgLibReceive);
+
+Err HostExgLibControl (UInt16 libRefNum, UInt16 op, void* valueP, UInt16* valueLenP)
+ HOST_TRAP(hostSelectorExgLibControl);
+
+Err HostExgLibRequest (UInt16 libRefNum, void* exgSocketP)
+ HOST_TRAP(hostSelectorExgLibRequest);
+
+
+/* ==================================================================== */
+/* Preference-related calls */
+/* ==================================================================== */
+
+HostBoolType HostGetPreference(const char*, char*)
+ HOST_TRAP(hostSelectorGetPreference);
+
+void HostSetPreference(const char*, const char*)
+ HOST_TRAP(hostSelectorSetPreference);
+
+
+/* ==================================================================== */
+/* Logging-related calls */
+/* ==================================================================== */
+
+HostFILEType* HostLogFile(void)
+ HOST_TRAP(hostSelectorLogFile);
+
+void HostSetLogFileSize(long)
+ HOST_TRAP(hostSelectorSetLogFileSize);
+
+
+/* ==================================================================== */
+/* RPC-related calls */
+/* ==================================================================== */
+
+HostErrType HostSessionCreate(const char* device, long ramSize, const char* romPath)
+ HOST_TRAP(hostSelectorSessionCreate);
+
+HostErrType HostSessionOpen(const char* psfFileName)
+ HOST_TRAP(hostSelectorSessionOpen);
+
+HostBoolType HostSessionSave(const char* saveFileName)
+ HOST_TRAP(hostSelectorSessionSave);
+
+HostErrType HostSessionClose(const char* saveFileName)
+ HOST_TRAP(hostSelectorSessionClose);
+
+HostErrType HostSessionQuit(void)
+ HOST_TRAP(hostSelectorSessionQuit);
+
+HostErrType HostSignalSend(HostSignalType signalNumber)
+ HOST_TRAP(hostSelectorSignalSend);
+
+HostErrType HostSignalWait(long timeout, HostSignalType* signalNumber)
+ HOST_TRAP(hostSelectorSignalWait);
+
+HostErrType HostSignalResume(void)
+ HOST_TRAP(hostSelectorSignalResume);
+
+
+/* ==================================================================== */
+/* Tracing calls */
+/* ==================================================================== */
+
+void HostTraceInit(void)
+ HOST_TRAP(hostSelectorTraceInit);
+
+void HostTraceClose(void)
+ HOST_TRAP(hostSelectorTraceClose);
+
+void HostTraceOutputT(unsigned short, const char*, ...)
+ HOST_TRAP(hostSelectorTraceOutputT);
+
+void HostTraceOutputTL(unsigned short, const char*, ...)
+ HOST_TRAP(hostSelectorTraceOutputTL);
+
+void HostTraceOutputVT(unsigned short, const char*, char* /*va_list*/)
+ HOST_TRAP(hostSelectorTraceOutputVT);
+
+void HostTraceOutputVTL(unsigned short, const char*, char* /*va_list*/)
+ HOST_TRAP(hostSelectorTraceOutputVTL);
+
+void HostTraceOutputB(unsigned short, const void*, HostSizeType)
+ HOST_TRAP(hostSelectorTraceOutputB);
+
+
+/* ==================================================================== */
+/* Debugger calls */
+/* ==================================================================== */
+
+HostErr HostDbgSetDataBreak (UInt32 addr, UInt32 size)
+ HOST_TRAP(hostSelectorDbgSetDataBreak);
+
+HostErr HostDbgClearDataBreak (void)
+ HOST_TRAP(hostSelectorDbgClearDataBreak);
+
+
+/* ==================================================================== */
+/* Slot related calls */
+/* ==================================================================== */
+
+long HostSlotMax(void)
+ HOST_TRAP(hostSelectorSlotMax);
+
+const char* HostSlotRoot(long slotNo)
+ HOST_TRAP(hostSelectorSlotRoot);
+
+HostBoolType HostSlotHasCard(long slotNo)
+ HOST_TRAP(hostSelectorSlotHasCard);
+
+
+/* ==================================================================== */
+/* File Choosing support */
+/* ==================================================================== */
+
+const char* HostGetFile(const char* prompt, const char* defaultDir)
+ HOST_TRAP(hostSelectorGetFile);
+
+const char* HostPutFile(const char* prompt, const char* defaultDir, const char* defaultName)
+ HOST_TRAP(hostSelectorPutFile);
+
+const char* HostGetDirectory(const char* prompt, const char* defaultDir)
+ HOST_TRAP(hostSelectorGetDirectory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HOSTCONTROL_H_ */
diff --git a/SrcShared/HostControlPrv.h b/SrcShared/HostControlPrv.h
new file mode 100644
index 0000000..22dc89b
--- /dev/null
+++ b/SrcShared/HostControlPrv.h
@@ -0,0 +1,35 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _HOSTCONTROLPRV_H_
+#define _HOSTCONTROLPRV_H_
+
+#include "EmPatchIf.h" // CallROMType
+
+class SessionFile;
+
+CallROMType HandleHostControlCall (void);
+
+class Host
+{
+ public:
+
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+};
+
+#endif /* _HOSTCONTROLPRV_H_ */
+
diff --git a/SrcShared/LoadApplication.cpp b/SrcShared/LoadApplication.cpp
new file mode 100644
index 0000000..f3c8211
--- /dev/null
+++ b/SrcShared/LoadApplication.cpp
@@ -0,0 +1,381 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "LoadApplication.h"
+
+#include "EmErrCodes.h" // kError_OutOfMemory
+#include "EmMemory.h" // EmMem_memcpy
+#include "EmPalmStructs.h" // RecordEntryType, RsrcEntryType, etc.
+#include "EmStreamFile.h" // EmStreamFile
+#include "ErrorHandling.h" // Errors::ThrowIfPalmError
+#include "Miscellaneous.h" // StMemory
+#include "ROMStubs.h" // DmFindDatabase, DmGetLastErr, DmDatabaseInfo, DmOpenDatabase, ...
+#include "Strings.r.h" // kStr_ values
+
+
+static Bool PrvIsResources (UInt16 attributes)
+{
+ return (attributes & dmHdrAttrResDB);
+}
+
+
+/************************************************************
+ * Export a resource or record database as a normal data file in
+ * Pilot format.
+ *************************************************************/
+
+static void PrvMyShlExportAsPilotFile(EmStreamFile& fh, UInt16 cardNo, const char* nameP)
+{
+ DmOpenRef dbP = 0;
+ Err err;
+ UInt16 numRecords;
+ int size;
+ long offset;
+ int i;
+
+ try
+ {
+ //------------------------------------------------------------
+ // Locate the Database and see what kind of database it is
+ //------------------------------------------------------------
+
+ LocalID dbID;
+ dbID = ::DmFindDatabase (cardNo, (Char*) nameP);
+ if (!dbID)
+ Errors::ThrowIfPalmError (::DmGetLastErr ());
+
+ UInt16 attributes, version;
+ UInt32 crDate, modDate, bckUpDate;
+ UInt32 type, creator;
+ UInt32 modNum;
+ LocalID appInfoID, sortInfoID;
+ const int kGapSize = 2;
+
+ err = ::DmDatabaseInfo (cardNo, dbID, 0,
+ &attributes, &version, &crDate,
+ &modDate, &bckUpDate,
+ &modNum, &appInfoID,
+ &sortInfoID, &type,
+ &creator);
+ Errors::ThrowIfPalmError(err);
+
+ dbP = ::DmOpenDatabase (cardNo, dbID, dmModeReadOnly);
+ if (!dbP)
+ Errors::ThrowIfPalmError (::DmGetLastErr ());
+
+ //------------------------------------------------------------
+ // Write out a resource database
+ //------------------------------------------------------------
+ if (::PrvIsResources (attributes))
+ {
+ DmResType resType;
+ DmResID resID;
+ UInt32 resSize;
+
+ numRecords = ::DmNumRecords(dbP);
+
+ size = EmAliasDatabaseHdrType<LAS>::GetSize () + numRecords * EmAliasRsrcEntryType<LAS>::GetSize () + kGapSize;
+ StMemory outP (size, true);
+
+ // Fill in header
+ EmAliasDatabaseHdrType<LAS> hdr (outP.Get ());
+
+ strcpy ((char*) hdr.name.GetPtr (), nameP);
+ hdr.attributes = attributes;
+ hdr.version = version;
+ hdr.creationDate = crDate;
+ hdr.modificationDate = modDate;
+ hdr.lastBackupDate = bckUpDate;
+ hdr.modificationNumber = modNum;
+ hdr.appInfoID = 0;
+ hdr.sortInfoID = 0;
+ hdr.type = type;
+ hdr.creator = creator;
+
+ hdr.recordList.nextRecordListID = 0;
+ hdr.recordList.numRecords = numRecords;
+
+ // Get the size of the appInfo and sort Info if they exist
+ offset = size;
+ MemHandle appInfoH=0, sortInfoH=0;
+ UInt32 appInfoSize=0, sortInfoSize=0;
+ if (appInfoID)
+ {
+ hdr.appInfoID = offset;
+ appInfoH = (MemHandle) ::MemLocalIDToGlobal (appInfoID, cardNo);
+ if (!appInfoH)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+ appInfoSize = ::MemHandleSize (appInfoH);
+ offset += appInfoSize;
+ }
+
+ if (sortInfoID)
+ {
+ hdr.sortInfoID = offset;
+ sortInfoH = (MemHandle) ::MemLocalIDToGlobal (sortInfoID, cardNo);
+ if (!sortInfoH)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+ sortInfoSize = ::MemHandleSize (sortInfoH);
+ offset += sortInfoSize;
+ }
+
+
+ // Fill in the info on each resource into the header
+ offset = size;
+ for (i=0; i < numRecords; i++)
+ {
+ EmAliasRsrcEntryType<LAS> entry (hdr.recordList.resources[i]);
+
+ ::DmResourceInfo (dbP, i, &resType, &resID, NULL);
+ MemHandle resH = ::DmGetResourceIndex (dbP, i);
+ if (resH)
+ {
+ resSize = ::MemHandleSize (resH);
+ ::DmReleaseResource (resH);
+ }
+ else
+ {
+ resSize = 0;
+ }
+
+ entry.type = resType;
+ entry.id = resID;
+ entry.localChunkID = offset;
+
+ offset += resSize;
+ }
+
+ // Clear out gap
+ if (kGapSize > 0)
+ memset (outP.Get() + (size - kGapSize), 0, kGapSize);
+
+ // Write out entry table
+ fh.PutBytes (outP.Get (), size);
+
+ // Write out the appInfo followed by sortInfo, if they exist
+ if (appInfoID && appInfoSize)
+ {
+ UInt32 srcP;
+ StMemory outP (appInfoSize);
+ srcP = (UInt32) ::MemHandleLock (appInfoH);
+ EmMem_memcpy ((void*) outP.Get(), srcP, appInfoSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), appInfoSize);
+ }
+
+ if (sortInfoID && sortInfoSize)
+ {
+ UInt32 srcP;
+ StMemory outP (sortInfoSize);
+ srcP = (UInt32) ::MemHandleLock (sortInfoH);
+ EmMem_memcpy ((void*) outP.Get(), srcP, sortInfoSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), sortInfoSize);
+ }
+
+ // Write out each resource
+ for (i=0; i < numRecords; i++)
+ {
+ MemHandle srcResH;
+ LocalID resChunkID;
+
+ ::DmResourceInfo (dbP, i, &resType, &resID, &resChunkID);
+
+ if (resChunkID)
+ {
+ UInt32 srcP;
+ srcResH = ::DmGetResourceIndex (dbP, i);
+ if (!srcResH)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+ resSize = ::MemHandleSize (srcResH);
+
+ StMemory outP (resSize);
+ srcP = (UInt32) ::MemHandleLock (srcResH);
+ EmMem_memcpy ((void*) outP.Get (), srcP, resSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), resSize);
+
+ ::DmReleaseResource (srcResH);
+ }
+ }
+ } // Resource database
+
+ //------------------------------------------------------------
+ // Write out a records database
+ //------------------------------------------------------------
+ else
+ {
+ UInt16 attr;
+ UInt32 uniqueID;
+ MemHandle srcH;
+
+ numRecords = ::DmNumRecords (dbP);
+
+ size = EmAliasDatabaseHdrType<LAS>::GetSize () + numRecords * EmAliasRecordEntryType<LAS>::GetSize () + kGapSize;
+ StMemory outP(size);
+
+ // Fill in header
+ EmAliasDatabaseHdrType<LAS> hdr (outP.Get ());
+
+ strcpy ((char*) hdr.name.GetPtr (), nameP);
+ hdr.attributes = attributes;
+ hdr.version = version;
+ hdr.creationDate = crDate;
+ hdr.modificationDate = modDate;
+ hdr.lastBackupDate = bckUpDate;
+ hdr.modificationNumber = modNum;
+ hdr.appInfoID = 0;
+ hdr.sortInfoID = 0;
+ hdr.type = type;
+ hdr.creator = creator;
+
+ hdr.recordList.nextRecordListID = 0;
+ hdr.recordList.numRecords = numRecords;
+
+
+ // Get the size of the appInfo and sort Info if they exist
+ offset = size;
+ MemHandle appInfoH=0, sortInfoH=0;
+ UInt32 appInfoSize=0, sortInfoSize=0;
+ if (appInfoID)
+ {
+ hdr.appInfoID = offset;
+ appInfoH = (MemHandle) ::MemLocalIDToGlobal (appInfoID, cardNo);
+ if (!appInfoH)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+ appInfoSize = ::MemHandleSize (appInfoH);
+ offset += appInfoSize;
+ }
+
+ if (sortInfoID)
+ {
+ hdr.sortInfoID = offset;
+ sortInfoH = (MemHandle) ::MemLocalIDToGlobal (sortInfoID, cardNo);
+ if (!sortInfoH)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+ sortInfoSize = ::MemHandleSize (sortInfoH);
+ offset += sortInfoSize;
+ }
+
+
+ // Fill in the info on each resource into the header
+ for (i=0; i < numRecords; i++)
+ {
+ EmAliasRecordEntryType<LAS> entry (hdr.recordList.records[i]);
+
+ err = ::DmRecordInfo (dbP, i, &attr, &uniqueID, 0);
+ if (err)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+
+ srcH = ::DmQueryRecord (dbP, i);
+
+ entry.localChunkID = offset;
+ entry.attributes = attr;
+ entry.uniqueID[0] = (uniqueID >> 16) & 0x00FF;
+ entry.uniqueID[1] = (uniqueID >> 8) & 0x00FF;
+ entry.uniqueID[2] = uniqueID & 0x00FF;
+
+ if (srcH)
+ offset += ::MemHandleSize (srcH);
+ }
+
+ // Clear out gap
+ if (kGapSize > 0)
+ memset (outP.Get() + (size - kGapSize), 0, kGapSize);
+
+ // Write out entry table
+ fh.PutBytes (outP.Get (), size);
+
+ // Write out the appInfo followed by sortInfo, if they exist
+ if (appInfoID && appInfoSize)
+ {
+ UInt32 srcP;
+ StMemory outP (appInfoSize);
+ srcP = (UInt32) ::MemHandleLock (appInfoH);
+ EmMem_memcpy ((void*) outP.Get(), srcP, appInfoSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), appInfoSize);
+ }
+
+ if (sortInfoID && sortInfoSize)
+ {
+ UInt32 srcP;
+ StMemory outP (sortInfoSize);
+ srcP = (UInt32) ::MemHandleLock (sortInfoH);
+ EmMem_memcpy ((void*) outP.Get(), srcP, sortInfoSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), sortInfoSize);
+ }
+
+ // Write out each record
+ for (i=0; i<numRecords; i++)
+ {
+ UInt32 recSize;
+
+ err = ::DmRecordInfo (dbP, i, &attr, &uniqueID, 0);
+ if (err)
+ {
+ Errors::ThrowIfPalmError (-1);
+ }
+
+ srcH = ::DmQueryRecord (dbP, i);
+
+ if (srcH)
+ {
+ UInt32 srcP;
+
+ recSize = ::MemHandleSize(srcH);
+ StMemory outP (recSize);
+ srcP = (UInt32) ::MemHandleLock (srcH);
+ EmMem_memcpy ((void*) outP.Get(), srcP, recSize);
+ ::MemPtrUnlock ((MemPtr) srcP);
+ fh.PutBytes (outP.Get (), recSize);
+ }
+ }
+ }
+
+ // Clean up
+ ::DmCloseDatabase (dbP);
+ }
+ catch (...)
+ {
+ if (dbP)
+ ::DmCloseDatabase (dbP);
+
+ throw;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SavePalmFile
+// ---------------------------------------------------------------------------
+// Saves a Palm OS program or database file to a file.
+
+void SavePalmFile (EmStreamFile& appFile, UInt16 cardNo, const char* databaseName)
+{
+ ::PrvMyShlExportAsPilotFile (appFile, cardNo, databaseName);
+}
diff --git a/SrcShared/LoadApplication.h b/SrcShared/LoadApplication.h
new file mode 100644
index 0000000..f14c76c
--- /dev/null
+++ b/SrcShared/LoadApplication.h
@@ -0,0 +1,22 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _LOADAPPLICATION_H_
+#define _LOADAPPLICATION_H_
+
+class EmStreamFile;
+
+void SavePalmFile (EmStreamFile& applicationFile, UInt16 cardNo, const char* databaseName);
+
+#endif /* _LOADAPPLICATION_H_ */
+
diff --git a/SrcShared/Logging.cpp b/SrcShared/Logging.cpp
new file mode 100644
index 0000000..db84f3d
--- /dev/null
+++ b/SrcShared/Logging.cpp
@@ -0,0 +1,1547 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Logging.h"
+
+#include "EmApplication.h" // gApplication, IsBound
+#include "EmMemory.h" // EmMemGet32, EmMemGet16, EmMem_strcpy, EmMem_strncat
+#include "EmStreamFile.h" // EmStreamFile
+#include "Hordes.h" // Hordes::IsOn, Hordes::EventCounter
+#include "Platform.h" // GetMilliseconds
+#include "PreferenceMgr.h" // Preference<>
+#include "ROMStubs.h" // FrmGetTitle, WinGetFirstWindow
+#include "Strings.r.h" // kStr_LogFileSize
+#include "StringData.h" // virtual key descriptions
+
+#include <ctype.h> // isprint
+
+//#define LOG_TO_TRACE
+
+#ifdef LOG_TO_TRACE
+#include "TracerPlatform.h"
+#endif
+
+static LogStream* gStdLog;
+uint8 gLogCache[kCachedPrefKeyDummy];
+
+
+LogStream* LogGetStdLog (void)
+{
+ return gStdLog;
+}
+
+
+static void PrvPrefsChanged (PrefKeyType key, void*)
+{
+#define UPDATE_ONE_PREF(name) \
+ if (::PrefKeysEqual (key, kPrefKey##name)) \
+ { \
+ Preference<uint8> pref(kPrefKey##name, false); \
+ gLogCache[kCachedPrefKey##name] = *pref; \
+ }
+
+ FOR_EACH_SCALAR_PREF (UPDATE_ONE_PREF)
+}
+
+
+void LogStartup (void)
+{
+#define REGISTER_ONE_PREF(name) \
+ gPrefs->AddNotification (PrvPrefsChanged, kPrefKey##name); \
+ PrvPrefsChanged (kPrefKey##name, NULL);
+
+#define HARDCODE_ONE_PREF(name) \
+ gLogCache[kCachedPrefKey##name] = 0;
+
+ if (gApplication->IsBound ())
+ {
+ FOR_EACH_SCALAR_PREF (HARDCODE_ONE_PREF)
+ }
+ else
+ {
+ FOR_EACH_SCALAR_PREF (REGISTER_ONE_PREF)
+ }
+
+ EmAssert (gStdLog == NULL);
+ gStdLog = new LogStream ("Log");
+}
+
+
+void LogShutdown (void)
+{
+#define UNREGISTER_ONE_PREF(name) \
+ gPrefs->RemoveNotification (PrvPrefsChanged);
+
+ FOR_EACH_SCALAR_PREF (UNREGISTER_ONE_PREF)
+
+ EmAssert (gStdLog != NULL);
+ delete gStdLog; // Dumps it to a file, too.
+ gStdLog = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CLASS LogStream
+// ---------------------------------------------------------------------------
+
+const long kFindUniqueFile = -1;
+const uint32 kInvalidTimestamp = (uint32) -1;
+const int32 kInvalidGremlinCounter = -2;
+const long kEventTextMaxLen = 255;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::LogStream
+ *
+ * DESCRIPTION: Constructor.
+ *
+ * PARAMETERS: baseName - base name to use for the file the data gets
+ * written to. This base name will be prepended with
+ * the path of the directory to write the file to, and
+ * appended with "%04d.txt", where %04d will be
+ * replaced with a number to make sure the file's
+ * name is unique.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+LogStream::LogStream (const char* baseName) :
+ fMutex (),
+ fInner (baseName)
+{
+ gPrefs->AddNotification (PrefChanged, kPrefKeyLogFileSize, this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::~LogStream
+ *
+ * DESCRIPTION: Destructor. Writes any buffered text to the file and
+ * closes the file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+LogStream::~LogStream (void)
+{
+ gPrefs->RemoveNotification (PrefChanged);
+
+ omni_mutex_lock lock (fMutex);
+ fInner.DumpToFile ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::Printf
+ *
+ * DESCRIPTION: A printf-like function for adding text to the log file.
+ * The text is preceded by a timestamp, and is suffixed
+ * with a newline.
+ *
+ * PARAMETERS: fmt - a printf-like string for formatting the output
+ * text.
+ *
+ * ... - additional printf-like parameters.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStream::Printf (const char* fmt, ...)
+{
+ int n;
+ va_list arg;
+
+ omni_mutex_lock lock (fMutex);
+
+ va_start (arg, fmt);
+
+ n = fInner.VPrintf (fmt, arg);
+
+ va_end (arg);
+
+// fInner.DumpToFile ();
+ return n;
+}
+
+
+int LogStream::PrintfNoTime (const char* fmt, ...)
+{
+ int n;
+ va_list arg;
+
+ omni_mutex_lock lock (fMutex);
+
+ va_start (arg, fmt);
+
+ n = fInner.VPrintf (fmt, arg, false);
+
+ va_end (arg);
+
+// fInner.DumpToFile ();
+ return n;
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::DataPrintf
+ *
+ * DESCRIPTION: A printf-like function for adding text to the log file.
+ * The text is preceded by a timestamp, and is suffixed
+ * with a newline.
+ *
+ * PARAMETERS: data - binary data to be included in the output
+ *
+ * dataLen - length of binary data
+ *
+ * fmt - a printf-like string for formatting the output
+ * text.
+ *
+ * ... - additional printf-like parameters.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStream::DataPrintf (const void* data, long dataLen, const char* fmt, ...)
+{
+ omni_mutex_lock lock (fMutex);
+
+ int n;
+ va_list arg;
+
+ va_start (arg, fmt);
+
+ n = fInner.VPrintf (fmt, arg);
+
+ // Dump the data nicely formatted
+
+ n += fInner.DumpHex (data, dataLen);
+
+ return n;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::VPrintf
+ *
+ * DESCRIPTION: A vprintf-like function for adding text to the log file.
+ *
+ * PARAMETERS: fmt - a vprintf-like string for formatting the output
+ * text.
+ *
+ * args - additional vprintf-like parameters.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStream::VPrintf (const char* fmt, va_list args)
+{
+ omni_mutex_lock lock (fMutex);
+
+ return fInner.VPrintf (fmt, args);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::Write
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStream::Write (const void* buffer, long size)
+{
+ omni_mutex_lock lock (fMutex);
+
+ return fInner.Write (buffer, size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::Clear
+ *
+ * DESCRIPTION: Clear any currently logged data
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStream::Clear (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fInner.Clear ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::GetLogSize
+ *
+ * DESCRIPTION: Returns the maximum amount of text to be written to
+ * the log file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: The maximum size.
+ *
+ ***********************************************************************/
+
+long LogStream::GetLogSize (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ return fInner.GetLogSize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::SetLogSize
+ *
+ * DESCRIPTION: Sets the maximum amount of text to be written to the
+ * log file. Any currently logged data is lost.
+ *
+ * PARAMETERS: size - the new maximum value.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStream::SetLogSize (long size)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fInner.SetLogSize (size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::EnsureNewFile
+ *
+ * DESCRIPTION: Ensure that the logged data is written to a new file the
+ * next time DumpToFile is called. Otherwise, the data
+ * will be written to the same file it was written to the
+ * previous time DumpToFile was called.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStream::EnsureNewFile (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fInner.EnsureNewFile ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::DumpToFile
+ *
+ * DESCRIPTION: Dumps any buffered text to the log file, prepending
+ * a message saying that only the last <mumble> bytes
+ * of text are buffered.
+ *
+ * If no data has been logged (or has been discarded with
+ * a call to Clear), nothing is written out and no file is
+ * created.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStream::DumpToFile (void)
+{
+ omni_mutex_lock lock (fMutex);
+
+ fInner.DumpToFile ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStream::PrefChanged
+ *
+ * DESCRIPTION: Outputs and EOL to the log stream.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStream::PrefChanged (PrefKeyType, PrefRefCon data)
+{
+ Preference<long> size (kPrefKeyLogFileSize);
+ ((LogStream*) data)->SetLogSize (*size);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::LogStreamInner
+ *
+ * DESCRIPTION: Constructor.
+ *
+ * PARAMETERS: baseName - base name to use for the file the data gets
+ * written to. This base name will be prepended with
+ * the path of the directory to write the file to, and
+ * appended with "%04d.txt", where %04d will be
+ * replaced with a number to make sure the file's
+ * name is unique.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+LogStreamInner::LogStreamInner (const char* baseName) :
+ fBaseName (baseName),
+ fFileIndex (kFindUniqueFile),
+ fBuffer (),
+ fBufferSize (0),
+ fDiscarded (false),
+ fLastGremlinEventCounter (kInvalidGremlinCounter),
+ fLastTimestampTime (kInvalidTimestamp),
+ fBaseTimestampTime (kInvalidTimestamp)
+{
+ Preference<long> size (kPrefKeyLogFileSize);
+ fBufferSize = *size;
+
+#ifdef LOG_TO_TRACE
+ gTracer.InitOutputPort ();
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::~LogStreamInner
+ *
+ * DESCRIPTION: Destructor. Writes any buffered text to the file and
+ * closes the file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+LogStreamInner::~LogStreamInner (void)
+{
+#ifdef LOG_TO_TRACE
+ gTracer.CloseOutputPort ();
+#else
+ this->DumpToFile ();
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::DumpHex
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStreamInner::DumpHex (const void* data, long dataLen)
+{
+ int n = 0;
+ const uint8* dataP = (const uint8*) data;
+
+ if (dataP && dataLen)
+ {
+ for (long ii = 0; ii < dataLen; ii += 16)
+ {
+ char text[16 * 4 + 4]; // 16 bytes * (3 for hex + 1 for ASCII) + 2 tabs + 1 space + 1 NULL
+ char* p = text;
+
+ *p++ = '\t';
+
+ // Print up to 16 bytes of hex on the left
+ long jj;
+ for (jj = ii; jj < ii + 16 ; ++jj)
+ {
+ if (jj < dataLen)
+ p += sprintf (p, "%02X ", dataP[jj]);
+ else
+ p += sprintf (p, " ");
+
+ if (jj == ii + 7)
+ p += sprintf (p, " ");
+
+ EmAssert (p - text < (ptrdiff_t) sizeof (text));
+ }
+
+ // Print the ascii on the right
+ *p++ = '\t';
+ for (jj = ii; jj < ii + 16 && jj < dataLen; ++jj)
+ {
+ char c = dataP[jj];
+ if (!isprint(c))
+ c = '.';
+ *p++ = c;
+
+ EmAssert (p - text < (ptrdiff_t) sizeof (text));
+ }
+
+ EmAssert (p - text <= (ptrdiff_t) sizeof (text));
+
+ this->Write (text, p - text);
+ }
+ }
+
+ return n;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::VPrintf
+ *
+ * DESCRIPTION: A vprintf-like function for adding text to the log file.
+ *
+ * PARAMETERS: fmt - a vprintf-like string for formatting the output
+ * text.
+ *
+ * args - additional vprintf-like parameters.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStreamInner::VPrintf (const char* fmt, va_list args, Bool timestamp)
+{
+ char buffer[2000];
+
+ int n = vsprintf (buffer, fmt, args);
+
+ // debug check, watch for buffer overflows here
+ if (n < 0 || n >= (int) sizeof (buffer))
+ {
+ Platform::Debugger();
+ }
+
+ this->Write (buffer, n, timestamp);
+
+ return n;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::Write
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+int LogStreamInner::Write (const void* buffer, long size, Bool timestamp)
+{
+ if (timestamp)
+ this->Timestamp ();
+
+ this->Append ((const char*) buffer, size);
+ this->NewLine ();
+
+ return size;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::Clear
+ *
+ * DESCRIPTION: Clear any currently logged data
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::Clear (void)
+{
+ fBuffer.clear ();
+ fBaseTimestampTime = kInvalidTimestamp;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::GetLogSize
+ *
+ * DESCRIPTION: Returns the maximum amount of text to be written to
+ * the log file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: The maximum size.
+ *
+ ***********************************************************************/
+
+long LogStreamInner::GetLogSize (void)
+{
+ return fBufferSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::SetLogSize
+ *
+ * DESCRIPTION: Sets the maximum amount of text to be written to the
+ * log file. Any currently logged data is lost.
+ *
+ * PARAMETERS: size - the new maximum value.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::SetLogSize (long size)
+{
+ fBufferSize = size;
+
+ this->TrimLeading ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::EnsureNewFile
+ *
+ * DESCRIPTION: Ensure that the logged data is written to a new file the
+ * next time DumpToFile is called. Otherwise, the data
+ * will be written to the same file it was written to the
+ * previous time DumpToFile was called.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::EnsureNewFile (void)
+{
+ fFileIndex = kFindUniqueFile;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::DumpToFile
+ *
+ * DESCRIPTION: Dumps any buffered text to the log file, prepending
+ * a message saying that only the last <mumble> bytes
+ * of text are buffered.
+ *
+ * If no data has been logged (or has been discarded with
+ * a call to Clear), nothing is written out and no file is
+ * created.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::DumpToFile (void)
+{
+ if (fBuffer.size () == 0)
+ return;
+
+ // Open the output stream. No need to open it as a "text" file;
+ // our Dump method does any host-specific conversion.
+
+ EmFileRef ref = this->CreateFileReference ();
+ EmStreamFile stream (ref, kCreateOrEraseForUpdate,
+ kFileCreatorCodeWarrior, kFileTypeText);
+
+ // If we lost data off the front print a message saying that only
+ // the last portion of the text is begin saved/dumped.
+
+ if (fDiscarded)
+ {
+ char buffer[200];
+ string templ = Platform::GetString (kStr_LogFileSize);
+ sprintf (buffer, templ.c_str (), fBufferSize / 1024L);
+ this->DumpToFile (stream, buffer, strlen (buffer));
+ }
+
+ // Dump the text.
+
+ const int kChunkSize = 1 * 1024L * 1024L;
+ StMemory chunk (kChunkSize);
+ ByteDeque::iterator iter = fBuffer.begin ();
+
+ while (iter != fBuffer.end ())
+ {
+ long amtToCopy = kChunkSize;
+ long amtLeft = fBuffer.end () - iter;
+
+ if (amtToCopy > amtLeft)
+ {
+ amtToCopy = amtLeft;
+ }
+
+ copy (iter, iter + amtToCopy, chunk.Get ());
+
+ this->DumpToFile (stream, chunk.Get (), amtToCopy);
+
+ iter += amtToCopy;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::DumpToFile
+ *
+ * DESCRIPTION: Dumps the given text to the log file, converting any
+ * EOL characters along the way.
+ *
+ * PARAMETERS: f - open file to write the text to.
+ *
+ * s - text to write.
+ *
+ * size - number of characters to write (the input text
+ * is not necessarily NULL terminated).
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::DumpToFile (EmStreamFile& f, const char* s, long size)
+{
+ StMemory converted;
+ long convertedLength;
+
+ Platform::ToHostEOL (converted, convertedLength, s, size);
+
+ f.PutBytes (converted.Get (), convertedLength);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::CreateFileReference
+ *
+ * DESCRIPTION: Creates a file reference based on the base file name
+ * passed in to the constructor and the current fFileIndex.
+ * If fFileIndex is kFindUniqueFile, this routine attempts
+ * to find a file index that results in a new file being
+ * created. Otherwise, the current fFileIndex is used to
+ * either open an existing file or create a new one.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: The desired EmFileRef.
+ *
+ ***********************************************************************/
+
+EmFileRef LogStreamInner::CreateFileReference (void)
+{
+ EmFileRef result;
+ char buffer[32];
+
+ // Figure out where to put the log file. If a Gremlin Horde is
+ // running, then put the log file in the directory created to
+ // hold Gremlin output files. Otherwise, use the directory the
+ // use specified in the preferences. If no such directory was
+ // specified, use the Emulator's directory.
+
+ Preference<EmDirRef> logDirPref (kPrefKeyLogDefaultDir);
+
+ EmDirRef defaultDir = *logDirPref;
+ EmDirRef poserDir = EmDirRef::GetEmulatorDirectory ();
+ EmDirRef gremlinDir = Hordes::GetGremlinDirectory ();
+ EmDirRef logDir;
+
+ if (Hordes::IsOn ())
+ {
+ logDir = gremlinDir;
+ }
+ else if (defaultDir.Create (), defaultDir.Exists ())
+ {
+ logDir = defaultDir;
+ }
+ else
+ {
+ logDir = poserDir;
+ }
+
+ // If being forced to write to a new file, look for an unused
+ // file name.
+
+ if (fFileIndex == kFindUniqueFile)
+ {
+ fFileIndex = 0;
+
+ do
+ {
+ ++fFileIndex;
+
+ sprintf (buffer, "%s_%04ld.txt", fBaseName, fFileIndex);
+
+ result = EmFileRef (logDir, buffer);
+ }
+ while (result.IsSpecified () && result.Exists ());
+ }
+
+ // Otherwise, use the previously-used file name.
+
+ else
+ {
+ sprintf (buffer, "%s_%04ld.txt", fBaseName, fFileIndex);
+
+ result = EmFileRef (logDir, buffer);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::Timestamp
+ *
+ * DESCRIPTION: Outputs a timestamp to the log stream.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::Timestamp (void)
+{
+ Bool reformat = false;
+ uint32 now = Platform::GetMilliseconds ();
+
+ // This may be a case of pre-optimization, but we try to keep around
+ // a formatted timestamp string for as long as possible. If either
+ // the time changes or the Gremlin event number changes, we force
+ // the regeneration of the cached timestamp string.
+
+ if (fLastTimestampTime != now)
+ reformat = true;
+
+ if (!reformat && Hordes::IsOn () && fLastGremlinEventCounter != Hordes::EventCounter ())
+ reformat = true;
+
+ if (reformat)
+ {
+ fLastTimestampTime = now;
+
+ // We try to print out logged data with timestamps that are
+ // relative to the first event recorded.
+
+ if (fBaseTimestampTime == kInvalidTimestamp)
+ fBaseTimestampTime = now;
+
+ now -= fBaseTimestampTime;
+
+ // If a Gremlin is running, use a formatting string that includes
+ // the event number. Otherwise, use a format string that omits it.
+
+ if (Hordes::IsOn ())
+ {
+ fLastGremlinEventCounter = Hordes::EventCounter ();
+ sprintf (fLastTimestampString, "%ld.%03ld (%ld):\t", now / 1000, now % 1000, fLastGremlinEventCounter);
+ }
+ else
+ {
+ sprintf (fLastTimestampString, "%ld.%03ld:\t", now / 1000, now % 1000);
+ }
+ }
+
+ this->Append (fLastTimestampString, strlen (fLastTimestampString));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::NewLine
+ *
+ * DESCRIPTION: Outputs and EOL to the log stream.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::NewLine (void)
+{
+ this->Append ("\n", 1);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::Append
+ *
+ * DESCRIPTION: Generic function for adding text (actually, any kind of
+ * unformatted data) to the output stream. If the amount
+ * of text in the buffer exceeds the maximum specified
+ * amount, any old text is deleted. This function is
+ * the bottleneck for all such functions in this class.
+ *
+ * PARAMETERS: buffer - pointer to the text to be added.
+ *
+ * size - length of the text (in bytes) to be added.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::Append (const char* buffer, long size)
+{
+ if (size != 0)
+ {
+#ifdef LOG_TO_TRACE
+ // Convert the text to a string
+
+ string s (buffer, size);
+
+ // Write out the string, breaking it up manually at
+ // '\n's (OutputVT doesn't know that's what we're using
+ // for line endings).
+
+ string::size_type pos = s.find ('\n');
+
+ while (pos != string::npos)
+ {
+ string substr = s.substr (0, pos) + " ";
+ gTracer.OutputVTL (0, substr.c_str (), (va_list) NULL);
+
+ s = s.substr (pos + 1);
+ pos = s.find ('\n');
+ }
+
+ // If there's anything left, write it out without the CR.
+
+ if (s.size () > 0)
+ {
+ gTracer.OutputVT (0, s.c_str (), (va_list) NULL);
+ }
+#else
+ copy (buffer, buffer + size, back_inserter (fBuffer));
+
+ this->TrimLeading ();
+#endif
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LogStreamInner::TrimLeading
+ *
+ * DESCRIPTION: If the buffer has exceeded the maximum size we've
+ * established for it, drop any leading characters.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void LogStreamInner::TrimLeading (void)
+{
+ long amtToDiscard = fBuffer.size () - fBufferSize;
+
+ if (amtToDiscard > 0)
+ {
+ fDiscarded = true;
+ fBuffer.erase (fBuffer.begin (), fBuffer.begin () + amtToDiscard);
+
+ // Keep chopping up to the next '\n' so that we don't leave
+ // any partial lines.
+
+ while (fBuffer.front () != '\n')
+ {
+ fBuffer.pop_front ();
+ }
+
+ fBuffer.pop_front ();
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ StubEmFrmGetTitle
+// ---------------------------------------------------------------------------
+// Returns a pointer to the title string of a form. Copied from Form.c.
+
+static string StubEmFrmGetTitle (const FormPtr frm)
+{
+ const Char* title = FrmGetTitle (frm);
+
+ if (title)
+ {
+ char buffer[256];
+ EmMem_strcpy (buffer, (emuptr) title);
+ return string (buffer);
+ }
+
+ return string ("Untitled");
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ StubEmPrintFormID
+// ---------------------------------------------------------------------------
+// Displays the form resource id associated with the window passed.
+
+static void StubEmPrintFormID (WinHandle winHandle, char* desc, char* eventText)
+{
+ emuptr winPtr;
+ emuptr exitWinPtr;
+
+ // Allow access to WindowType fields windowFlags and nextWindow.
+
+ CEnableFullAccess munge;
+
+ if (winHandle)
+ {
+ exitWinPtr = (emuptr) WinGetWindowPointer (winHandle);
+
+ // Check if the handle is still valid. If the form has been deleted
+ // then we can't dereference the window pointer.
+
+ // Search the window list for the pointer.
+ winHandle = WinGetFirstWindow ();
+ while (winHandle)
+ {
+ winPtr = (emuptr) WinGetWindowPointer (winHandle);
+ if (winPtr == exitWinPtr)
+ break;
+
+ winHandle = (WinHandle) EmMemGet32 (winPtr + offsetof (WindowType, nextWindow));
+ }
+
+
+ if (winHandle && /*winPtr->windowFlags.dialog*/
+ ((EmMemGet16 (winPtr + offsetof (WindowType, windowFlags)) & 0x0200) != 0))
+ {
+ string title = StubEmFrmGetTitle((FormPtr) winPtr);
+ if (!title.empty())
+ sprintf (&eventText[strlen(eventText)],"%s: \"%s\"", desc, title.c_str());
+ else
+ sprintf (&eventText[strlen(eventText)],"%s ID: %ld", desc, /*frm->formId*/
+ EmMemGet16 (winPtr + offsetof (FormType, formId)));
+ }
+ }
+}
+
+
+
+#define irObCloseChr 0x01FB // to shut down Obex from background thread
+
+
+
+
+static const char* StubEmKeyDescription (Int16 key)
+{
+ unsigned int index;
+
+ index = key - vchrLowBattery;
+
+ if (index < gVirtualKeyDescriptionsCount)
+ return kVirtualKeyDescriptions [index];
+
+ index = key - irObCloseChr;
+
+ if (index < gHardKeyDescriptionsCount)
+ return kHardKeyDescriptions [index];
+
+ return "";
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetEventText
+// ---------------------------------------------------------------------------
+// Displays the passed event in the emulator's event tracewindow if it is
+// active.
+
+static Bool PrvGetEventText(const EventType* eventP, char* eventText)
+{
+ long curLen = strlen (eventText);
+ eventText += curLen;
+
+ switch (eventP->eType)
+ {
+ case nilEvent:
+ return false;
+ //sprintf(eventText,"nilEvent");
+ //break;
+
+ case penDownEvent:
+ sprintf(eventText,"penDownEvent X:%d Y:%d",
+ eventP->screenX, eventP->screenY);
+ break;
+
+ case penUpEvent:
+ strcpy(eventText,"penUpEvent");
+ sprintf(eventText,"penUpEvent X:%d Y:%d",
+ eventP->screenX, eventP->screenY);
+ break;
+
+ case penMoveEvent:
+ strcpy(eventText,"penMoveEvent");
+ sprintf(eventText,"penMoveEvent X:%d Y:%d",
+ eventP->screenX, eventP->screenY);
+ break;
+
+ case keyDownEvent:
+ if ((eventP->data.keyDown.chr < 0x0100) && isprint (eventP->data.keyDown.chr))
+ {
+ sprintf(eventText,"keyDownEvent Key:'%c' 0x%02X%s, Modifiers: 0x%04X",
+ (char) eventP->data.keyDown.chr, eventP->data.keyDown.chr,
+ StubEmKeyDescription(eventP->data.keyDown.chr),
+ eventP->data.keyDown.modifiers);
+ }
+ else
+ {
+ sprintf(eventText,"keyDownEvent Key:0x%02X%s, Modifiers: 0x%04X",
+ eventP->data.keyDown.chr,
+ StubEmKeyDescription(eventP->data.keyDown.chr),
+ eventP->data.keyDown.modifiers);
+ }
+ break;
+
+ case winEnterEvent:
+ sprintf(eventText,"winEnterEvent Enter: %p Exit: %p",
+ eventP->data.winEnter.enterWindow, eventP->data.winEnter.exitWindow);
+ StubEmPrintFormID (eventP->data.winEnter.enterWindow, " Enter Form", eventText);
+ StubEmPrintFormID (eventP->data.winEnter.exitWindow, " Exit Form", eventText);
+ break;
+
+ case winExitEvent:
+ sprintf(eventText,"winExitEvent Enter: %p Exit: %p",
+ eventP->data.winExit.enterWindow, eventP->data.winExit.exitWindow);
+ StubEmPrintFormID (eventP->data.winExit.enterWindow, " Enter Form", eventText);
+ StubEmPrintFormID (eventP->data.winExit.exitWindow, " Exit Form", eventText);
+ break;
+
+ case ctlEnterEvent:
+ sprintf(eventText,"ctlEnterEvent ID: %u",
+ eventP->data.ctlEnter.controlID);
+ break;
+
+ case ctlSelectEvent:
+ sprintf(eventText,"ctlSelectEvent ID: %u On: %u",
+ eventP->data.ctlSelect.controlID, eventP->data.ctlSelect.on);
+ break;
+
+ case ctlRepeatEvent:
+ sprintf(eventText,"ctlRepeatEvent ID: %u Time: %lu",
+ eventP->data.ctlRepeat.controlID, eventP->data.ctlRepeat.time);
+ break;
+
+ case ctlExitEvent:
+ sprintf(eventText,"ctlExitEvent");
+ break;
+
+ case lstEnterEvent:
+ sprintf(eventText,"lstEnterEvent ID: %u Item: %u",
+ eventP->data.lstEnter.listID, eventP->data.lstEnter.selection);
+ break;
+
+ case lstSelectEvent:
+ sprintf(eventText,"lstSelectEvent ID: %u Item: %u",
+ eventP->data.lstSelect.listID, eventP->data.lstSelect.selection);
+ break;
+
+ case lstExitEvent:
+ sprintf(eventText,"lstExitEvent ID: %u",
+ eventP->data.lstExit.listID);
+ break;
+
+ case popSelectEvent:
+ sprintf(eventText,"popSelectEvent CtlID: %u ListID: %u Item: %u",
+ eventP->data.popSelect.controlID, eventP->data.popSelect.listID,
+ eventP->data.popSelect.selection);
+ break;
+
+ case fldEnterEvent:
+ sprintf(eventText,"fldEnterEvent ID: %u",
+ eventP->data.fldEnter.fieldID);
+ break;
+
+ case fldHeightChangedEvent:
+ sprintf(eventText,"fldHeightChangedEvent ID: %u Height: %u Pos: %u",
+ eventP->data.fldHeightChanged.fieldID,
+ eventP->data.fldHeightChanged.newHeight,
+ eventP->data.fldHeightChanged.currentPos);
+ break;
+
+ case fldChangedEvent:
+ sprintf(eventText,"fldChangedEvent ID: %u",
+ eventP->data.fldChanged.fieldID);
+ break;
+
+ case tblEnterEvent:
+ sprintf(eventText,"tblEnterEvent ID: %u Row: %u Col: %u",
+ eventP->data.tblEnter.tableID,
+ eventP->data.tblEnter.row,
+ eventP->data.tblEnter.column);
+ break;
+
+ case tblSelectEvent:
+ sprintf(eventText,"tblSelectEvent ID: %u Row: %u Col: %u",
+ eventP->data.tblSelect.tableID,
+ eventP->data.tblSelect.row,
+ eventP->data.tblSelect.column);
+ break;
+
+ case tblExitEvent:
+ sprintf(eventText,"tblExitEvent ID: %u Row: %u Col: %u",
+ eventP->data.tblExit.tableID,
+ eventP->data.tblExit.row,
+ eventP->data.tblExit.column);
+ break;
+
+ case daySelectEvent:
+ strcpy(eventText,"daySelectEvent");
+ break;
+
+ case menuEvent:
+ sprintf(eventText,"menuEvent ItemID: %u",
+ eventP->data.menu.itemID);
+ break;
+
+ case appStopEvent:
+ strcpy(eventText,"appStopEvent");
+ break;
+
+ case frmLoadEvent:
+ sprintf(eventText,"frmLoadEvent ID: %u",
+ eventP->data.frmOpen.formID);
+ break;
+
+ case frmOpenEvent:
+ sprintf(eventText,"frmOpenEvent ID: %u",
+ eventP->data.frmOpen.formID);
+ break;
+
+ case frmGotoEvent:
+ sprintf(eventText,"frmGotoEvent ID: %u Record: %u Field: %u",
+ eventP->data.frmGoto.formID,
+ eventP->data.frmGoto.recordNum,
+ eventP->data.frmGoto.matchFieldNum);
+ break;
+
+ case frmUpdateEvent:
+ sprintf(eventText,"frmUpdateEvent ID: %u",
+ eventP->data.frmUpdate.formID);
+ break;
+
+ case frmSaveEvent:
+ sprintf(eventText,"frmSaveEvent");
+ break;
+
+ case frmCloseEvent:
+ sprintf(eventText,"frmCloseEvent ID: %u",
+ eventP->data.frmClose.formID);
+ break;
+
+ case frmTitleEnterEvent:
+ sprintf(eventText,"frmTitleEnterEvent ID: %u",
+ eventP->data.frmTitleEnter.formID);
+ break;
+
+ case frmTitleSelectEvent:
+ sprintf(eventText,"frmTitleSelectEvent ID: %u",
+ eventP->data.frmTitleSelect.formID);
+ break;
+
+ case sclEnterEvent:
+ sprintf(eventText,"sclEnterEvent ID: %u",
+ eventP->data.sclEnter.scrollBarID);
+ break;
+
+ case sclRepeatEvent:
+ sprintf(eventText,"sclRepeatEvent ID: %u Value: %u, New value: %u",
+ eventP->data.sclRepeat.scrollBarID,
+ eventP->data.sclRepeat.value,
+ eventP->data.sclRepeat.newValue);
+ break;
+
+ case sclExitEvent:
+ sprintf(eventText,"sclExitEvent ID: %u",
+ eventP->data.sclExit.scrollBarID);
+ break;
+
+ case tsmConfirmEvent:
+ curLen += sprintf(eventText,"tsmConfirmEvent ID: %u Text: ",
+ eventP->data.tsmConfirm.formID);
+ EmMem_strncat(eventText, (emuptr)eventP->data.tsmConfirm.yomiText, kEventTextMaxLen - curLen);
+ eventText[kEventTextMaxLen] = 0; // Make sure we're terminated
+ break;
+
+ case tsmFepButtonEvent:
+ sprintf(eventText,"tsmFepButtonEvent ID: %u",
+ eventP->data.tsmFepButton.buttonID);
+ break;
+
+ case tsmFepModeEvent:
+ sprintf(eventText,"tsmFepModeEvent ID: %u",
+ eventP->data.tsmFepMode.mode);
+ break;
+
+ case menuCmdBarOpenEvent:
+ sprintf(eventText,"menuCmdBarOpenEvent preventFieldButtons: %u",
+ eventP->data.menuCmdBarOpen.preventFieldButtons);
+ break;
+
+ case menuOpenEvent:
+ sprintf(eventText,"menuOpenEvent RscID:%u, cause:%u",
+ eventP->data.menuOpen.menuRscID,
+ eventP->data.menuOpen.cause);
+ break;
+
+ case menuCloseEvent:
+ sprintf(eventText,"menuCloseEvent");
+ break;
+
+ case frmGadgetEnterEvent:
+ sprintf(eventText,"frmGadgetEnterEvent RscID:%u, gadget:0x%08lX",
+ eventP->data.gadgetEnter.gadgetID,
+ (unsigned long) eventP->data.gadgetEnter.gadgetP);
+ break;
+
+ case frmGadgetMiscEvent:
+ sprintf(eventText,"frmGadgetMiscEvent ID:%u, gadget:0x%08lX, selector:%u",
+ eventP->data.gadgetMisc.gadgetID,
+ (unsigned long) eventP->data.gadgetMisc.gadgetP,
+ eventP->data.gadgetMisc.selector);
+ break;
+
+ default:
+ if (eventP->eType >= firstINetLibEvent && eventP->eType < firstWebLibEvent)
+ {
+ sprintf(eventText, "NetLib event #%u", eventP->eType);
+ }
+ else if (eventP->eType >= firstWebLibEvent && eventP->eType < firstWebLibEvent + 0x0100)
+ {
+ sprintf(eventText, "WebLib event #%u", eventP->eType);
+ }
+ else if (eventP->eType >= firstUserEvent)
+ {
+ sprintf(eventText, "Application event #%u", eventP->eType);
+ }
+ else
+ {
+ sprintf(eventText,"Unknown Event! Event->eType #: %u",
+ eventP->eType);
+ }
+ break;
+ }
+
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtAddEventToQueue
+// ---------------------------------------------------------------------------
+
+void LogEvtAddEventToQueue (const EventType& event)
+{
+ if (LogEnqueuedEvents ())
+ {
+ // Get the text for this event. If there is such text, log it.
+
+ char eventText[kEventTextMaxLen] = " -> EvtAddEventToQueue: ";
+ if (PrvGetEventText (&event, eventText))
+ {
+ LogAppendMsg (eventText);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtAddUniqueEventToQueue
+// ---------------------------------------------------------------------------
+
+void LogEvtAddUniqueEventToQueue (const EventType& event, UInt32, Boolean)
+{
+ if (LogEnqueuedEvents ())
+ {
+ // Get the text for this event. If there is such text, log it.
+
+ char eventText[kEventTextMaxLen] = " -> EvtAddUniqueEventToQueue: ";
+ if (PrvGetEventText (&event, eventText))
+ {
+ LogAppendMsg (eventText);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtEnqueueKey
+// ---------------------------------------------------------------------------
+
+void LogEvtEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers)
+{
+ if (LogEnqueuedEvents ())
+ {
+ if ((ascii < 0x0100) && isprint (ascii))
+ {
+ LogAppendMsg (" -> EvtEnqueueKey: ascii = '%c' 0x%04X, keycode = 0x%04X, modifiers = 0x%04X.",
+ (char) ascii, ascii, keycode, modifiers);
+ }
+ else
+ {
+ LogAppendMsg (" -> EvtEnqueueKey: ascii = 0x%04X, keycode = 0x%04X, modifiers = 0x%04X.",
+ ascii, keycode, modifiers);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtEnqueuePenPoint
+// ---------------------------------------------------------------------------
+
+void LogEvtEnqueuePenPoint (const PointType& pt)
+{
+ if (LogEnqueuedEvents ())
+ {
+ LogAppendMsg (" -> EvtEnqueuePenPoint: pen->x=%d, pen->y=%d.", pt.x, pt.y);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtGetEvent
+// ---------------------------------------------------------------------------
+
+void LogEvtGetEvent (const EventType& event, Int32 timeout)
+{
+ UNUSED_PARAM(timeout)
+
+ if (LogDequeuedEvents ())
+ {
+ // Get the text for this event. If there is such text, log it.
+
+ char eventText[kEventTextMaxLen] = "<- EvtGetEvent: ";
+ if (PrvGetEventText (&event, eventText))
+ {
+ LogAppendMsg (eventText);
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtGetPen
+// ---------------------------------------------------------------------------
+
+void LogEvtGetPen (Int16 screenX, Int16 screenY, Boolean penDown)
+{
+ if (LogDequeuedEvents ())
+ {
+ static Int16 lastScreenX = -2;
+ static Int16 lastScreenY = -2;
+ static Boolean lastPenDown = false;
+ static long numCollapsedEvents;
+
+ if (screenX != lastScreenX ||
+ screenY != lastScreenY ||
+ penDown != lastPenDown)
+ {
+ lastScreenX = screenX;
+ lastScreenY = screenY;
+ lastPenDown = penDown;
+
+ numCollapsedEvents = 0;
+
+ LogAppendMsg ("<- EvtGetPen: screenX=%d, screenY=%d, penDown=%d.",
+ (int) screenX, (int) screenY, (int) penDown);
+ }
+ else
+ {
+ ++numCollapsedEvents;
+ if (numCollapsedEvents == 1)
+ LogAppendMsg ("<- EvtGetPen: <<<eliding identical events>>>.");
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LogEvtGetSysEvent
+// ---------------------------------------------------------------------------
+
+void LogEvtGetSysEvent (const EventType& event, Int32 timeout)
+{
+ UNUSED_PARAM(timeout)
+
+ if (LogDequeuedEvents ())
+ {
+ // Get the text for this event. If there is such text, log it.
+
+ char eventText[kEventTextMaxLen] = "<- EvtGetSysEvent: ";
+ if (PrvGetEventText (&event, eventText))
+ {
+ LogAppendMsg (eventText);
+ }
+ }
+}
+
diff --git a/SrcShared/Logging.h b/SrcShared/Logging.h
new file mode 100644
index 0000000..12f5225
--- /dev/null
+++ b/SrcShared/Logging.h
@@ -0,0 +1,222 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+#include "Hordes.h" // Hordes::IsOn
+#include "Miscellaneous.h" // StMemory
+#include "PreferenceMgr.h" // FOR_EACH_PREF
+#include "omnithread.h" // omni_mutex
+
+#include <stdarg.h> // va_list
+#include <deque> // deque
+
+typedef deque<uint8> ByteDeque;
+
+class EmStreamFile;
+
+
+class LogStreamInner
+{
+ // Non-multithread-safe version of LogStream. LogStream
+ // acquires a "logging mutex" and calls these functions.
+
+ public:
+ LogStreamInner (const char* baseName);
+ ~LogStreamInner (void);
+
+ int DumpHex (const void*, long dataLen);
+ int VPrintf (const char* fmt, va_list args, Bool timestamp = true);
+ int Write (const void* buffer, long size, Bool timestamp = true);
+
+ void Clear (void);
+
+ long GetLogSize (void);
+ void SetLogSize (long);
+
+ void EnsureNewFile (void);
+ void DumpToFile (void);
+
+ private:
+ void DumpToFile (EmStreamFile&, const char*, long size);
+ EmFileRef CreateFileReference (void);
+ void Timestamp (void);
+ void NewLine (void);
+ void Append (const char* buffer, long size);
+ void TrimLeading (void);
+
+ const char* fBaseName;
+ long fFileIndex;
+
+ ByteDeque fBuffer;
+ long fBufferSize;
+ Bool fDiscarded;
+
+ int32 fLastGremlinEventCounter;
+ uint32 fLastTimestampTime;
+ uint32 fBaseTimestampTime ;
+ char fLastTimestampString[30];
+};
+
+class LogStream
+{
+ public:
+ LogStream (const char* baseName);
+ ~LogStream (void);
+
+ // Multithread-safe interface for logging information.
+
+ int Printf (const char* msg, ...);
+ int PrintfNoTime (const char* msg, ...);
+ int DataPrintf (const void*, long dataLen, const char* msg, ...);
+ int VPrintf (const char* fmt, va_list args);
+ int Write (const void* buffer, long size);
+
+ void Clear (void);
+
+ long GetLogSize (void);
+ void SetLogSize (long);
+
+ void EnsureNewFile (void);
+ void DumpToFile (void);
+
+ private:
+ static void PrefChanged (PrefKeyType, PrefRefCon);
+
+ private:
+ omni_mutex fMutex;
+ LogStreamInner fInner;
+};
+
+void LogEvtAddEventToQueue (const EventType& event);
+void LogEvtAddUniqueEventToQueue (const EventType& event, UInt32, Boolean);
+void LogEvtEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers);
+void LogEvtEnqueuePenPoint (const PointType&);
+
+void LogEvtGetEvent (const EventType& event, Int32 timeout);
+void LogEvtGetPen (Int16, Int16, Boolean);
+void LogEvtGetSysEvent (const EventType& event, Int32 timeout);
+
+LogStream* LogGetStdLog (void);
+void LogStartup (void);
+void LogShutdown (void);
+
+#define LogAppendMsg if (!LogGetStdLog ()) ; else LogGetStdLog ()->Printf
+#define LogAppendMsgNoTime if (!LogGetStdLog ()) ; else LogGetStdLog ()->PrintfNoTime
+#define LogAppendData if (!LogGetStdLog ()) ; else LogGetStdLog ()->DataPrintf
+#define LogClear if (!LogGetStdLog ()) ; else LogGetStdLog ()->Clear
+#define LogDump if (!LogGetStdLog ()) ; else LogGetStdLog ()->DumpToFile
+#define LogEnsureNewFile if (!LogGetStdLog ()) ; else LogGetStdLog ()->EnsureNewFile
+#define LogStartNew LogDump (); LogClear (); LogEnsureNewFile
+
+
+// The LogFoo macros below are called all the time. When implemented in
+// terms of a function that instantiates a Preference<> object all the
+// time, they can slow down the overall execution of Poser significantly.
+// Therefore, the logging sub-system caches the relevent values and
+// works from those, instead.
+
+#define DECLARE_CACHED_PREF_KEYS(name, type, init) kCachedPrefKey##name,
+enum
+{
+ FOR_EACH_PREF(DECLARE_CACHED_PREF_KEYS)
+ kCachedPrefKeyDummy
+};
+
+extern uint8 gLogCache[];
+inline Bool LogCommon(int key)
+{
+ if (key >= kCachedPrefKeyLogErrorMessages &&
+ key <= kCachedPrefKeyLogRPCData)
+ {
+ if (Hordes::IsOn ())
+ return (gLogCache[key] & kGremlinLogging) != 0;
+
+ return (gLogCache[key] & kNormalLogging) != 0;
+ }
+
+ EmAssert (false);
+
+ return 0;
+}
+
+inline Bool ReportCommon(int key)
+{
+ if (key >= kCachedPrefKeyReportFreeChunkAccess &&
+ key <= kCachedPrefKeyReportUnlockedChunkAccess)
+ {
+ return gLogCache[key] != 0;
+ }
+
+ EmAssert (false);
+
+ return 0;
+}
+
+#define FOR_EACH_LOG_PREF(DO_TO_LOG_PREF) \
+ DO_TO_LOG_PREF (LogErrorMessages) \
+ DO_TO_LOG_PREF (LogWarningMessages) \
+ DO_TO_LOG_PREF (LogGremlins) \
+ DO_TO_LOG_PREF (LogCPUOpcodes) \
+ DO_TO_LOG_PREF (LogEnqueuedEvents) \
+ DO_TO_LOG_PREF (LogDequeuedEvents) \
+ DO_TO_LOG_PREF (LogSystemCalls) \
+ DO_TO_LOG_PREF (LogApplicationCalls) \
+ DO_TO_LOG_PREF (LogSerial) \
+ DO_TO_LOG_PREF (LogSerialData) \
+ DO_TO_LOG_PREF (LogNetLib) \
+ DO_TO_LOG_PREF (LogNetLibData) \
+ DO_TO_LOG_PREF (LogExgMgr) \
+ DO_TO_LOG_PREF (LogExgMgrData) \
+ DO_TO_LOG_PREF (LogHLDebugger) \
+ DO_TO_LOG_PREF (LogHLDebuggerData) \
+ DO_TO_LOG_PREF (LogLLDebugger) \
+ DO_TO_LOG_PREF (LogLLDebuggerData) \
+ DO_TO_LOG_PREF (LogRPC) \
+ DO_TO_LOG_PREF (LogRPCData)
+
+#define FOR_EACH_REPORT_PREF(DO_TO_REPORT_PREF) \
+ DO_TO_REPORT_PREF (ReportFreeChunkAccess) \
+ DO_TO_REPORT_PREF (ReportHardwareRegisterAccess) \
+ DO_TO_REPORT_PREF (ReportLowMemoryAccess) \
+ DO_TO_REPORT_PREF (ReportLowStackAccess) \
+ DO_TO_REPORT_PREF (ReportMemMgrDataAccess) \
+ DO_TO_REPORT_PREF (ReportMemMgrLeaks) \
+ DO_TO_REPORT_PREF (ReportMemMgrSemaphore) \
+ DO_TO_REPORT_PREF (ReportOffscreenObject) \
+ DO_TO_REPORT_PREF (ReportOverlayErrors) \
+ DO_TO_REPORT_PREF (ReportProscribedFunction) \
+ DO_TO_REPORT_PREF (ReportROMAccess) \
+ DO_TO_REPORT_PREF (ReportScreenAccess) \
+ DO_TO_REPORT_PREF (ReportSizelessObject) \
+ DO_TO_REPORT_PREF (ReportStackAlmostOverflow) \
+ DO_TO_REPORT_PREF (ReportStrictIntlChecks) \
+ DO_TO_REPORT_PREF (ReportSystemGlobalAccess) \
+ DO_TO_REPORT_PREF (ReportUIMgrDataAccess) \
+ DO_TO_REPORT_PREF (ReportUnlockedChunkAccess)
+
+#define FOR_EACH_SCALAR_PREF(DO_TO_SCALAR_PREF) \
+ FOR_EACH_LOG_PREF(DO_TO_SCALAR_PREF) \
+ FOR_EACH_REPORT_PREF(DO_TO_SCALAR_PREF)
+
+#define CREATE_LOG_ACCESSOR(name) \
+ inline Bool name (void) { return LogCommon(kCachedPrefKey##name); }
+
+#define CREATE_REPORT_ACCESSOR(name) \
+ inline Bool name (void) { return ReportCommon(kCachedPrefKey##name); }
+
+FOR_EACH_LOG_PREF(CREATE_LOG_ACCESSOR)
+FOR_EACH_REPORT_PREF(CREATE_REPORT_ACCESSOR)
+
+#endif /* _LOGGING_H_ */
diff --git a/SrcShared/Marshal.cpp b/SrcShared/Marshal.cpp
new file mode 100644
index 0000000..1239bf4
--- /dev/null
+++ b/SrcShared/Marshal.cpp
@@ -0,0 +1,1828 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Marshal.h"
+
+#include "EmPalmStructs.h" // EmAliasHostGremlinInfoType, etc.
+#include "EmPatchState.h" // EmPatchState::OSMajorVersion
+#include "HostControl.h" // HostGremlinInfoType, etc.
+#include "ROMStubs.h" // NetHToNL, NetHToNS
+
+#if PLATFORM_UNIX || PLATFORM_MAC
+#include <netinet/in.h> // ntohl, ntohs
+#endif
+
+// -------------------------
+// ----- Binary buffer -----
+// -------------------------
+
+void* Marshal::GetBuffer (emuptr p, long len)
+{
+ void* result = NULL;
+
+ if (p)
+ {
+ result = Platform::AllocateMemory (len);
+
+ if (result)
+ {
+ EmMem_memcpy (result, p, len);
+ }
+ }
+
+ return result;
+}
+
+#if 0 // inline
+template <class T>
+void Marshal::PutBuffer (emuptr p, const T*& buf, long len)
+{
+ if (p)
+ {
+ EmMem_memcpy (p, (void*) buf, len);
+ Platform::DisposeMemory ((void*) buf);
+ }
+}
+#endif
+
+
+#pragma mark -
+
+// ---------------------
+// ----- DlkServerSessionType -----
+// ---------------------
+
+void Marshal::GetDlkServerSessionType (emuptr p, DlkServerSessionType& dest)
+{
+ memset (&dest, 0, sizeof (DlkServerSessionType));
+
+ if (p)
+ {
+ EmAliasDlkServerSessionType<PAS> src(p);
+
+ dest.htalLibRefNum = src.htalLibRefNum;
+ dest.maxHtalXferSize = src.maxHtalXferSize;
+ dest.eventProcP = (DlkEventProcPtr) (emuptr) src.eventProcP;
+ dest.eventRef = src.eventRef;
+ dest.canProcP = (DlkUserCanProcPtr) (emuptr) src.canProcP;
+ dest.canRef = src.canRef;
+ dest.condFilterH = (MemHandle) (emuptr) src.condFilterH;
+ dest.dlkDBID = src.dlkDBID;
+ dest.reserved1 = src.reserved1;
+ dest.dbR = (DmOpenRef) (emuptr) src.dbR;
+ dest.cardNo = src.cardNo;
+ dest.dbCreator = src.dbCreator;
+ // dest.dbName = src.dbName;
+ dest.dbOpenMode = src.dbOpenMode;
+ dest.created = src.created;
+ dest.isResDB = src.isResDB;
+ dest.ramBased = src.ramBased;
+ dest.readOnly = src.readOnly;
+ dest.dbLocalID = src.dbLocalID;
+ dest.initialModNum = src.initialModNum;
+ dest.curRecIndex = src.curRecIndex;
+ // dest.creatorList = src.creatorList;
+ dest.syncState = src.syncState;
+ dest.complete = src.complete;
+ dest.conduitOpened = src.conduitOpened;
+ dest.logCleared = src.logCleared;
+ dest.resetPending = src.resetPending;
+ dest.gotCommand = src.gotCommand;
+ dest.cmdTID = src.cmdTID;
+ dest.reserved2 = src.reserved2;
+ dest.cmdLen = src.cmdLen;
+ dest.cmdP = (void *) (emuptr) src.cmdP;
+ dest.cmdH = (MemHandle) (emuptr) src.cmdH;
+ dest.wStateFlags = src.wStateFlags;
+ // dest.dbSearchState = src.dbSearchState;
+ }
+}
+
+
+void Marshal::PutDlkServerSessionType (emuptr p, const DlkServerSessionType& src)
+{
+ if (p)
+ {
+ EmAliasDlkServerSessionType<PAS> dest(p);
+
+ dest.htalLibRefNum = src.htalLibRefNum;
+ dest.maxHtalXferSize = src.maxHtalXferSize;
+ dest.eventProcP = (emuptr) (DlkEventProcPtr) src.eventProcP;
+ dest.eventRef = src.eventRef;
+ dest.canProcP = (emuptr) (DlkUserCanProcPtr) src.canProcP;
+ dest.canRef = src.canRef;
+ dest.condFilterH = (emuptr) (MemHandle) src.condFilterH;
+ dest.dlkDBID = src.dlkDBID;
+ dest.reserved1 = src.reserved1;
+ dest.dbR = (emuptr) (DmOpenRef) src.dbR;
+ dest.cardNo = src.cardNo;
+ dest.dbCreator = src.dbCreator;
+ // dest.dbName = src.dbName;
+ dest.dbOpenMode = src.dbOpenMode;
+ dest.created = src.created;
+ dest.isResDB = src.isResDB;
+ dest.ramBased = src.ramBased;
+ dest.readOnly = src.readOnly;
+ dest.dbLocalID = src.dbLocalID;
+ dest.initialModNum = src.initialModNum;
+ dest.curRecIndex = src.curRecIndex;
+ // dest.creatorList = src.creatorList;
+ dest.syncState = src.syncState;
+ dest.complete = src.complete;
+ dest.conduitOpened = src.conduitOpened;
+ dest.logCleared = src.logCleared;
+ dest.resetPending = src.resetPending;
+ dest.gotCommand = src.gotCommand;
+ dest.cmdTID = src.cmdTID;
+ dest.reserved2 = src.reserved2;
+ dest.cmdLen = src.cmdLen;
+ dest.cmdP = (emuptr) (void *) src.cmdP;
+ dest.cmdH = (emuptr) (MemHandle) src.cmdH;
+ dest.wStateFlags = src.wStateFlags;
+ // dest.dbSearchState = src.dbSearchState;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------
+// ----- DmSearchStateType -----
+// ---------------------
+
+void Marshal::GetDmSearchStateType (emuptr p, DmSearchStateType& dest)
+{
+ memset (&dest, 0, sizeof (DmSearchStateType));
+
+ if (p)
+ {
+ EmAliasDmSearchStateType<PAS> src(p);
+
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ dest.info[ii] = src.info[ii];
+ }
+ }
+}
+
+
+void Marshal::PutDmSearchStateType (emuptr p, const DmSearchStateType& src)
+{
+ if (p)
+ {
+ EmAliasDmSearchStateType<PAS> dest(p);
+
+ for (int ii = 0; ii < 8; ++ii)
+ {
+ dest.info[ii] = src.info[ii];
+ }
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------
+// ----- EventType -----
+// ---------------------
+
+void Marshal::GetEventType (emuptr p, EventType& dest)
+{
+ memset (&dest, 0, sizeof (EventType));
+
+ if (p)
+ {
+ EmAliasEventType<PAS> src(p);
+
+ dest.eType = src.eType;
+ dest.penDown = src.penDown;
+ dest.screenX = src.screenX;
+ dest.screenY = src.screenY;
+
+ switch (dest.eType)
+ {
+ case nilEvent:
+ break;
+
+ case penDownEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case penUpEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case penMoveEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case keyDownEvent:
+ dest.data.keyDown.chr = src.data.keyDown.chr;
+ dest.data.keyDown.keyCode = src.data.keyDown.keyCode;
+ dest.data.keyDown.modifiers = src.data.keyDown.modifiers;
+ break;
+
+ case winEnterEvent:
+ dest.data.winEnter.enterWindow = (WinHandle) (emuptr) src.data.winEnter.enterWindow;
+ dest.data.winEnter.exitWindow = (WinHandle) (emuptr) src.data.winEnter.exitWindow;
+ break;
+
+ case winExitEvent:
+ dest.data.winExit.enterWindow = (WinHandle) (emuptr) src.data.winExit.enterWindow;
+ dest.data.winExit.exitWindow = (WinHandle) (emuptr) src.data.winExit.exitWindow;
+ break;
+
+ case ctlEnterEvent:
+ dest.data.ctlEnter.controlID = src.data.ctlEnter.controlID;
+ dest.data.ctlEnter.pControl = (struct ControlType*) (emuptr) src.data.ctlEnter.pControl;
+ break;
+
+ case ctlExitEvent:
+ dest.data.ctlExit.controlID = src.data.ctlExit.controlID;
+ dest.data.ctlExit.pControl = (struct ControlType*) (emuptr) src.data.ctlExit.pControl;
+ break;
+
+ case ctlSelectEvent:
+ dest.data.ctlSelect.controlID = src.data.ctlSelect.controlID;
+ dest.data.ctlSelect.pControl = (struct ControlType*) (emuptr) src.data.ctlSelect.pControl;
+ dest.data.ctlSelect.on = src.data.ctlSelect.on;
+ break;
+
+ case ctlRepeatEvent:
+ dest.data.ctlRepeat.controlID = src.data.ctlRepeat.controlID;
+ dest.data.ctlRepeat.pControl = (struct ControlType*) (emuptr) src.data.ctlRepeat.pControl;
+ dest.data.ctlRepeat.time = src.data.ctlRepeat.time;
+ break;
+
+ case lstEnterEvent:
+ dest.data.lstEnter.listID = src.data.lstEnter.listID;
+ dest.data.lstEnter.pList = (struct ListType*) (emuptr) src.data.lstEnter.pList;
+ dest.data.lstEnter.selection = src.data.lstEnter.selection;
+ break;
+
+ case lstSelectEvent:
+ dest.data.lstSelect.listID = src.data.lstSelect.listID;
+ dest.data.lstSelect.pList = (struct ListType*) (emuptr) src.data.lstSelect.pList;
+ dest.data.lstSelect.selection = src.data.lstSelect.selection;
+ break;
+
+ case lstExitEvent:
+ dest.data.lstExit.listID = src.data.lstExit.listID;
+ dest.data.lstExit.pList = (struct ListType*) (emuptr) src.data.lstExit.pList;
+ break;
+
+ case popSelectEvent:
+ dest.data.popSelect.controlID = src.data.popSelect.controlID;
+ dest.data.popSelect.controlP = (struct ControlType*) (emuptr) src.data.popSelect.controlP;
+ dest.data.popSelect.listID = src.data.popSelect.listID;
+ dest.data.popSelect.listP = (struct ListType*) (emuptr) src.data.popSelect.listP;
+ dest.data.popSelect.selection = src.data.popSelect.selection;
+ dest.data.popSelect.priorSelection = src.data.popSelect.priorSelection;
+ break;
+
+ case fldEnterEvent:
+ dest.data.fldEnter.fieldID = src.data.fldEnter.fieldID;
+ dest.data.fldEnter.pField = (struct FieldType*) (emuptr) src.data.fldEnter.pField;
+ break;
+
+ case fldHeightChangedEvent:
+ dest.data.fldHeightChanged.fieldID = src.data.fldHeightChanged.fieldID;
+ dest.data.fldHeightChanged.pField = (struct FieldType*) (emuptr) src.data.fldHeightChanged.pField;
+ dest.data.fldHeightChanged.newHeight = src.data.fldHeightChanged.newHeight;
+ dest.data.fldHeightChanged.currentPos = src.data.fldHeightChanged.currentPos;
+ break;
+
+ case fldChangedEvent:
+ dest.data.fldChanged.fieldID = src.data.fldChanged.fieldID;
+ dest.data.fldChanged.pField = (struct FieldType*) (emuptr) src.data.fldChanged.pField;
+ break;
+
+ case tblEnterEvent:
+ dest.data.tblEnter.tableID = src.data.tblEnter.tableID;
+ dest.data.tblEnter.pTable = (struct TableType*) (emuptr) src.data.tblEnter.pTable;
+ dest.data.tblEnter.row = src.data.tblEnter.row;
+ dest.data.tblEnter.column = src.data.tblEnter.column;
+ break;
+
+ case tblSelectEvent:
+ dest.data.tblEnter.tableID = src.data.tblEnter.tableID;
+ dest.data.tblEnter.pTable = (struct TableType*) (emuptr) src.data.tblEnter.pTable;
+ dest.data.tblEnter.row = src.data.tblEnter.row;
+ dest.data.tblEnter.column = src.data.tblEnter.column;
+ break;
+
+ case daySelectEvent:
+ dest.data.daySelect.pSelector = (struct DaySelectorType*) (emuptr) src.data.daySelect.pSelector;
+ dest.data.daySelect.selection = src.data.daySelect.selection;
+ dest.data.daySelect.useThisDate = src.data.daySelect.useThisDate;
+ break;
+
+ case menuEvent:
+ dest.data.menu.itemID = src.data.menu.itemID;
+ break;
+
+ case appStopEvent:
+ break;
+
+ case frmLoadEvent:
+ dest.data.frmLoad.formID = src.data.frmLoad.formID;
+ break;
+
+ case frmOpenEvent:
+ dest.data.frmOpen.formID = src.data.frmOpen.formID;
+ break;
+
+ case frmGotoEvent:
+ dest.data.frmGoto.formID = src.data.frmGoto.formID;
+ dest.data.frmGoto.recordNum = src.data.frmGoto.recordNum;
+ dest.data.frmGoto.matchPos = src.data.frmGoto.matchPos;
+ dest.data.frmGoto.matchLen = src.data.frmGoto.matchLen;
+ dest.data.frmGoto.matchFieldNum = src.data.frmGoto.matchFieldNum;
+ dest.data.frmGoto.matchCustom = src.data.frmGoto.matchCustom;
+ break;
+
+ case frmUpdateEvent:
+ dest.data.frmUpdate.formID = src.data.frmUpdate.formID;
+ dest.data.frmUpdate.updateCode = src.data.frmUpdate.updateCode;
+ break;
+
+ case frmSaveEvent:
+ break;
+
+ case frmCloseEvent:
+ dest.data.frmClose.formID = src.data.frmClose.formID;
+ break;
+
+ case frmTitleEnterEvent:
+ dest.data.frmTitleEnter.formID = src.data.frmTitleEnter.formID;
+ break;
+
+ case frmTitleSelectEvent:
+ dest.data.frmTitleSelect.formID = src.data.frmTitleSelect.formID;
+ break;
+
+ case tblExitEvent:
+ dest.data.tblExit.tableID = src.data.tblExit.tableID;
+ dest.data.tblExit.pTable = (struct TableType*) (emuptr) src.data.tblExit.pTable;
+ dest.data.tblExit.row = src.data.tblExit.row;
+ dest.data.tblExit.column = src.data.tblExit.column;
+ break;
+
+ case sclEnterEvent:
+ dest.data.sclEnter.scrollBarID = src.data.sclEnter.scrollBarID;
+ dest.data.sclEnter.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclEnter.pScrollBar;
+ break;
+
+ case sclExitEvent:
+ dest.data.sclExit.scrollBarID = src.data.sclExit.scrollBarID;
+ dest.data.sclExit.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclExit.pScrollBar;
+ dest.data.sclExit.value = src.data.sclExit.value;
+ dest.data.sclExit.newValue = src.data.sclExit.newValue;
+ break;
+
+ case sclRepeatEvent:
+ dest.data.sclRepeat.scrollBarID = src.data.sclRepeat.scrollBarID;
+ dest.data.sclRepeat.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclRepeat.pScrollBar;
+ dest.data.sclRepeat.value = src.data.sclRepeat.value;
+ dest.data.sclRepeat.newValue = src.data.sclRepeat.newValue;
+ dest.data.sclRepeat.time = src.data.sclRepeat.time;
+ break;
+
+ case tsmConfirmEvent:
+ dest.data.tsmConfirm.yomiText = (Char*) (emuptr) src.data.tsmConfirm.yomiText;
+ dest.data.tsmConfirm.formID = src.data.tsmConfirm.formID;
+ break;
+
+ case tsmFepButtonEvent:
+ dest.data.tsmFepButton.buttonID = src.data.tsmFepButton.buttonID;
+ break;
+
+ case tsmFepModeEvent:
+ dest.data.tsmFepMode.mode = src.data.tsmFepMode.mode;
+ break;
+
+ case attnIndicatorEnterEvent:
+ dest.data.attnIndicatorEnter.formID = src.data.attnIndicatorEnter.formID;
+ break;
+
+ case attnIndicatorSelectEvent:
+ dest.data.attnIndicatorSelect.formID = src.data.attnIndicatorSelect.formID;
+ break;
+
+ case menuCmdBarOpenEvent:
+ dest.data.menuCmdBarOpen.preventFieldButtons = src.data.menuCmdBarOpen.preventFieldButtons;
+ dest.data.menuCmdBarOpen.reserved = src.data.menuCmdBarOpen.reserved;
+ break;
+
+ case menuOpenEvent:
+ dest.data.menuOpen.menuRscID = src.data.menuOpen.menuRscID;
+ dest.data.menuOpen.cause = src.data.menuOpen.cause;
+ break;
+
+ case menuCloseEvent:
+ // Doesn't appear to be used.
+ break;
+
+ case frmGadgetEnterEvent:
+ dest.data.gadgetEnter.gadgetID = src.data.gadgetEnter.gadgetID;
+ dest.data.gadgetEnter.gadgetP = (struct FormGadgetType*) (emuptr) src.data.gadgetEnter.gadgetP;
+ break;
+
+ case frmGadgetMiscEvent:
+ dest.data.gadgetMisc.gadgetID = src.data.gadgetMisc.gadgetID;
+ dest.data.gadgetMisc.gadgetP = (struct FormGadgetType*) (emuptr) src.data.gadgetMisc.gadgetP;
+ dest.data.gadgetMisc.selector = src.data.gadgetMisc.selector;
+ dest.data.gadgetMisc.dataP = (void*) (emuptr) src.data.gadgetMisc.dataP;
+ break;
+
+ default:
+ if ((dest.eType >= firstINetLibEvent &&
+ dest.eType < firstWebLibEvent + 0x100) ||
+ dest.eType >= firstUserEvent)
+ {
+ // We don't know what's in here, so let's just blockmove it.
+
+ EmMem_memcpy ( (void*) dest.data.generic.datum,
+ src.data.generic.datum.GetPtr (),
+ 16);
+ }
+ else
+ {
+ EmAssert (false);
+ }
+ }
+ }
+}
+
+
+void Marshal::PutEventType (emuptr p, const EventType& src)
+{
+ if (p)
+ {
+ EmAliasEventType<PAS> dest(p);
+
+ dest.eType = src.eType;
+ dest.penDown = src.penDown;
+ dest.screenX = src.screenX;
+ dest.screenY = src.screenY;
+
+ switch (src.eType)
+ {
+ case nilEvent:
+ break;
+
+ case penDownEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case penUpEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case penMoveEvent:
+ dest.data.penUp.start.x = src.data.penUp.start.x;
+ dest.data.penUp.start.y = src.data.penUp.start.y;
+ dest.data.penUp.end.x = src.data.penUp.end.x;
+ dest.data.penUp.end.y = src.data.penUp.end.y;
+ break;
+
+ case keyDownEvent:
+ dest.data.keyDown.chr = src.data.keyDown.chr;
+ dest.data.keyDown.keyCode = src.data.keyDown.keyCode;
+ dest.data.keyDown.modifiers = src.data.keyDown.modifiers;
+ break;
+
+ case winEnterEvent:
+ dest.data.winEnter.enterWindow = (WinHandle) (emuptr) src.data.winEnter.enterWindow;
+ dest.data.winEnter.exitWindow = (WinHandle) (emuptr) src.data.winEnter.exitWindow;
+ break;
+
+ case winExitEvent:
+ dest.data.winExit.enterWindow = (WinHandle) (emuptr) src.data.winExit.enterWindow;
+ dest.data.winExit.exitWindow = (WinHandle) (emuptr) src.data.winExit.exitWindow;
+ break;
+
+ case ctlEnterEvent:
+ dest.data.ctlEnter.controlID = src.data.ctlEnter.controlID;
+ dest.data.ctlEnter.pControl = (struct ControlType*) (emuptr) src.data.ctlEnter.pControl;
+ break;
+
+ case ctlExitEvent:
+ dest.data.ctlExit.controlID = src.data.ctlExit.controlID;
+ dest.data.ctlExit.pControl = (struct ControlType*) (emuptr) src.data.ctlExit.pControl;
+ break;
+
+ case ctlSelectEvent:
+ dest.data.ctlSelect.controlID = src.data.ctlSelect.controlID;
+ dest.data.ctlSelect.pControl = (struct ControlType*) (emuptr) src.data.ctlSelect.pControl;
+ dest.data.ctlSelect.on = src.data.ctlSelect.on;
+ break;
+
+ case ctlRepeatEvent:
+ dest.data.ctlRepeat.controlID = src.data.ctlRepeat.controlID;
+ dest.data.ctlRepeat.pControl = (struct ControlType*) (emuptr) src.data.ctlRepeat.pControl;
+ dest.data.ctlRepeat.time = src.data.ctlRepeat.time;
+ break;
+
+ case lstEnterEvent:
+ dest.data.lstEnter.listID = src.data.lstEnter.listID;
+ dest.data.lstEnter.pList = (struct ListType*) (emuptr) src.data.lstEnter.pList;
+ dest.data.lstEnter.selection = src.data.lstEnter.selection;
+ break;
+
+ case lstSelectEvent:
+ dest.data.lstSelect.listID = src.data.lstSelect.listID;
+ dest.data.lstSelect.pList = (struct ListType*) (emuptr) src.data.lstSelect.pList;
+ dest.data.lstSelect.selection = src.data.lstSelect.selection;
+ break;
+
+ case lstExitEvent:
+ dest.data.lstExit.listID = src.data.lstExit.listID;
+ dest.data.lstExit.pList = (struct ListType*) (emuptr) src.data.lstExit.pList;
+ break;
+
+ case popSelectEvent:
+ dest.data.popSelect.controlID = src.data.popSelect.controlID;
+ dest.data.popSelect.controlP = (struct ControlType*) (emuptr) src.data.popSelect.controlP;
+ dest.data.popSelect.listID = src.data.popSelect.listID;
+ dest.data.popSelect.listP = (struct ListType*) (emuptr) src.data.popSelect.listP;
+ dest.data.popSelect.selection = src.data.popSelect.selection;
+ dest.data.popSelect.priorSelection = src.data.popSelect.priorSelection;
+ break;
+
+ case fldEnterEvent:
+ dest.data.fldEnter.fieldID = src.data.fldEnter.fieldID;
+ dest.data.fldEnter.pField = (struct FieldType*) (emuptr) src.data.fldEnter.pField;
+ break;
+
+ case fldHeightChangedEvent:
+ dest.data.fldHeightChanged.fieldID = src.data.fldHeightChanged.fieldID;
+ dest.data.fldHeightChanged.pField = (struct FieldType*) (emuptr) src.data.fldHeightChanged.pField;
+ dest.data.fldHeightChanged.newHeight = src.data.fldHeightChanged.newHeight;
+ dest.data.fldHeightChanged.currentPos = src.data.fldHeightChanged.currentPos;
+ break;
+
+ case fldChangedEvent:
+ dest.data.fldChanged.fieldID = src.data.fldChanged.fieldID;
+ dest.data.fldChanged.pField = (struct FieldType*) (emuptr) src.data.fldChanged.pField;
+ break;
+
+ case tblEnterEvent:
+ dest.data.tblEnter.tableID = src.data.tblEnter.tableID;
+ dest.data.tblEnter.pTable = (struct TableType*) (emuptr) src.data.tblEnter.pTable;
+ dest.data.tblEnter.row = src.data.tblEnter.row;
+ dest.data.tblEnter.column = src.data.tblEnter.column;
+ break;
+
+ case tblSelectEvent:
+ dest.data.tblEnter.tableID = src.data.tblEnter.tableID;
+ dest.data.tblEnter.pTable = (struct TableType*) (emuptr) src.data.tblEnter.pTable;
+ dest.data.tblEnter.row = src.data.tblEnter.row;
+ dest.data.tblEnter.column = src.data.tblEnter.column;
+ break;
+
+ case daySelectEvent:
+ dest.data.daySelect.pSelector = (struct DaySelectorType*) (emuptr) src.data.daySelect.pSelector;
+ dest.data.daySelect.selection = src.data.daySelect.selection;
+ dest.data.daySelect.useThisDate = src.data.daySelect.useThisDate;
+ break;
+
+ case menuEvent:
+ dest.data.menu.itemID = src.data.menu.itemID;
+ break;
+
+ case appStopEvent:
+ break;
+
+ case frmLoadEvent:
+ dest.data.frmLoad.formID = src.data.frmLoad.formID;
+ break;
+
+ case frmOpenEvent:
+ dest.data.frmOpen.formID = src.data.frmOpen.formID;
+ break;
+
+ case frmGotoEvent:
+ dest.data.frmGoto.formID = src.data.frmGoto.formID;
+ dest.data.frmGoto.recordNum = src.data.frmGoto.recordNum;
+ dest.data.frmGoto.matchPos = src.data.frmGoto.matchPos;
+ dest.data.frmGoto.matchLen = src.data.frmGoto.matchLen;
+ dest.data.frmGoto.matchFieldNum = src.data.frmGoto.matchFieldNum;
+ dest.data.frmGoto.matchCustom = src.data.frmGoto.matchCustom;
+ break;
+
+ case frmUpdateEvent:
+ dest.data.frmUpdate.formID = src.data.frmUpdate.formID;
+ dest.data.frmUpdate.updateCode = src.data.frmUpdate.updateCode;
+ break;
+
+ case frmSaveEvent:
+ break;
+
+ case frmCloseEvent:
+ dest.data.frmClose.formID = src.data.frmClose.formID;
+ break;
+
+ case frmTitleEnterEvent:
+ dest.data.frmTitleEnter.formID = src.data.frmTitleEnter.formID;
+ break;
+
+ case frmTitleSelectEvent:
+ dest.data.frmTitleSelect.formID = src.data.frmTitleSelect.formID;
+ break;
+
+ case tblExitEvent:
+ dest.data.tblExit.tableID = src.data.tblExit.tableID;
+ dest.data.tblExit.pTable = (struct TableType*) (emuptr) src.data.tblExit.pTable;
+ dest.data.tblExit.row = src.data.tblExit.row;
+ dest.data.tblExit.column = src.data.tblExit.column;
+ break;
+
+ case sclEnterEvent:
+ dest.data.sclEnter.scrollBarID = src.data.sclEnter.scrollBarID;
+ dest.data.sclEnter.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclEnter.pScrollBar;
+ break;
+
+ case sclExitEvent:
+ dest.data.sclExit.scrollBarID = src.data.sclExit.scrollBarID;
+ dest.data.sclExit.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclExit.pScrollBar;
+ dest.data.sclExit.value = src.data.sclExit.value;
+ dest.data.sclExit.newValue = src.data.sclExit.newValue;
+ break;
+
+ case sclRepeatEvent:
+ dest.data.sclRepeat.scrollBarID = src.data.sclRepeat.scrollBarID;
+ dest.data.sclRepeat.pScrollBar = (struct ScrollBarType*) (emuptr) src.data.sclRepeat.pScrollBar;
+ dest.data.sclRepeat.value = src.data.sclRepeat.value;
+ dest.data.sclRepeat.newValue = src.data.sclRepeat.newValue;
+ dest.data.sclRepeat.time = src.data.sclRepeat.time;
+ break;
+
+ case tsmConfirmEvent:
+ dest.data.tsmConfirm.yomiText = (Char*) (emuptr) src.data.tsmConfirm.yomiText;
+ dest.data.tsmConfirm.formID = src.data.tsmConfirm.formID;
+ break;
+
+ case tsmFepButtonEvent:
+ dest.data.tsmFepButton.buttonID = src.data.tsmFepButton.buttonID;
+ break;
+
+ case tsmFepModeEvent:
+ dest.data.tsmFepMode.mode = src.data.tsmFepMode.mode;
+ break;
+
+ case attnIndicatorEnterEvent:
+ dest.data.attnIndicatorEnter.formID = src.data.attnIndicatorEnter.formID;
+ break;
+
+ case attnIndicatorSelectEvent:
+ dest.data.attnIndicatorSelect.formID = src.data.attnIndicatorSelect.formID;
+ break;
+
+ case menuCmdBarOpenEvent:
+ dest.data.menuCmdBarOpen.preventFieldButtons = src.data.menuCmdBarOpen.preventFieldButtons;
+ dest.data.menuCmdBarOpen.reserved = src.data.menuCmdBarOpen.reserved;
+ break;
+
+ case menuOpenEvent:
+ dest.data.menuOpen.menuRscID = src.data.menuOpen.menuRscID;
+ dest.data.menuOpen.cause = src.data.menuOpen.cause;
+ break;
+
+ case menuCloseEvent:
+ // Doesn't appear to be used.
+ break;
+
+ case frmGadgetEnterEvent:
+ dest.data.gadgetEnter.gadgetID = src.data.gadgetEnter.gadgetID;
+ dest.data.gadgetEnter.gadgetP = (struct FormGadgetType*) (emuptr) src.data.gadgetEnter.gadgetP;
+ break;
+
+ case frmGadgetMiscEvent:
+ dest.data.gadgetMisc.gadgetID = src.data.gadgetMisc.gadgetID;
+ dest.data.gadgetMisc.gadgetP = (struct FormGadgetType*) (emuptr) src.data.gadgetMisc.gadgetP;
+ dest.data.gadgetMisc.selector = src.data.gadgetMisc.selector;
+ dest.data.gadgetMisc.dataP = (void*) (emuptr) src.data.gadgetMisc.dataP;
+ break;
+
+ default:
+ if ((src.eType >= firstINetLibEvent &&
+ src.eType < firstWebLibEvent + 0x100) ||
+ src.eType >= firstUserEvent)
+ {
+ // We don't know what's in here, so let's just blockmove it.
+
+ EmMem_memcpy ( dest.data.generic.datum.GetPtr (),
+ (void*) src.data.generic.datum,
+ 16);
+ }
+ else
+ {
+ EmAssert (false);
+ }
+ }
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- FieldAttrType -----
+// -------------------------------
+
+/*
+ ======== BITFIELD LAYOUT CHEAT-SHEET ========
+
+ typedef struct {
+ UInt16 usable :1;
+ UInt16 visible :1;
+ UInt16 editable :1;
+ UInt16 singleLine :1;
+ UInt16 hasFocus :1;
+ UInt16 dynamicSize :1;
+ UInt16 insPtVisible :1;
+ UInt16 dirty :1;
+ UInt16 underlined :2;
+ UInt16 justification :2;
+ UInt16 autoShift :1;
+ UInt16 hasScrollBar :1;
+ UInt16 numeric :1;
+ } FieldAttrType;
+
+ // On the Mac:
+
+ |---------- high byte ----------|---------- low byte -----------|
+
+ 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+ +---+---+---+---+---+---+---+---+-------+-------+---+---+---+---+
+ | u | v | e | s | h | d | i | d | u | j | a | h | n | * |
+ +---+---+---+---+---+---+---+---+-------+-------+---+---+---+---+
+
+
+ // On Windows (in-register representation):
+
+ |---------- high byte ----------|---------- low byte -----------|
+
+ 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+ +---+---+---+---+-------+-------+---+---+---+---+---+---+---+---+
+ | * | n | h | a | j | u | d | i | d | h | s | e | v | u |
+ +---+---+---+---+-------+-------+---+---+---+---+---+---+---+---+
+*/
+
+#define FieldAttrType_Mask_usable 0x0001
+#define FieldAttrType_Mask_visible 0x0001
+#define FieldAttrType_Mask_editable 0x0001
+#define FieldAttrType_Mask_singleLine 0x0001
+#define FieldAttrType_Mask_hasFocus 0x0001
+#define FieldAttrType_Mask_dynamicSize 0x0001
+#define FieldAttrType_Mask_insPtVisible 0x0001
+#define FieldAttrType_Mask_dirty 0x0001
+#define FieldAttrType_Mask_underlined 0x0003
+#define FieldAttrType_Mask_justification 0x0003
+#define FieldAttrType_Mask_autoShift 0x0001
+#define FieldAttrType_Mask_hasScrollBar 0x0001
+#define FieldAttrType_Mask_numeric 0x0001
+
+#define FieldAttrType_Shift_usable 15
+#define FieldAttrType_Shift_visible 14
+#define FieldAttrType_Shift_editable 13
+#define FieldAttrType_Shift_singleLine 12
+#define FieldAttrType_Shift_hasFocus 11
+#define FieldAttrType_Shift_dynamicSize 10
+#define FieldAttrType_Shift_insPtVisible 9
+#define FieldAttrType_Shift_dirty 8
+#define FieldAttrType_Shift_underlined 7
+#define FieldAttrType_Shift_justification 5
+#define FieldAttrType_Shift_autoShift 3
+#define FieldAttrType_Shift_hasScrollBar 2
+#define FieldAttrType_Shift_numeric 1
+
+void Marshal::GetFieldAttrType (emuptr p, FieldAttrType& dest)
+{
+ memset (&dest, 0, sizeof (FieldAttrType));
+
+ if (p)
+ {
+ EmAliasUInt16<PAS> src(p);
+
+ UInt16 temp = src;
+
+#undef COPY_FIELD
+#define COPY_FIELD(name) \
+ dest.name = (temp >> FieldAttrType_Shift_##name) & FieldAttrType_Mask_##name
+
+ COPY_FIELD (usable);
+ COPY_FIELD (visible);
+ COPY_FIELD (editable);
+ COPY_FIELD (singleLine);
+ COPY_FIELD (hasFocus);
+ COPY_FIELD (dynamicSize);
+ COPY_FIELD (insPtVisible);
+ COPY_FIELD (dirty);
+ COPY_FIELD (underlined);
+ COPY_FIELD (justification);
+ COPY_FIELD (autoShift);
+ COPY_FIELD (hasScrollBar);
+ COPY_FIELD (numeric);
+ }
+}
+
+
+void Marshal::PutFieldAttrType (emuptr p, const FieldAttrType& src)
+{
+ if (p)
+ {
+ EmAliasUInt16<PAS> dest(p);
+
+ UInt16 temp = 0;
+
+#undef COPY_FIELD
+#define COPY_FIELD(name) \
+ temp |= (src.name << FieldAttrType_Shift_##name)
+
+ COPY_FIELD (usable);
+ COPY_FIELD (visible);
+ COPY_FIELD (editable);
+ COPY_FIELD (singleLine);
+ COPY_FIELD (hasFocus);
+ COPY_FIELD (dynamicSize);
+ COPY_FIELD (insPtVisible);
+ COPY_FIELD (dirty);
+ COPY_FIELD (underlined);
+ COPY_FIELD (justification);
+ COPY_FIELD (autoShift);
+ COPY_FIELD (hasScrollBar);
+ COPY_FIELD (numeric);
+
+ dest = temp;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- HostGremlinInfoType -----
+// -------------------------------
+
+void Marshal::GetHostGremlinInfoType (emuptr p, HostGremlinInfoType& dest)
+{
+ memset (&dest, 0, sizeof (HostGremlinInfoType));
+
+ if (p)
+ {
+ EmAliasHostGremlinInfoType<PAS> src(p);
+
+ dest.fFirstGremlin = src.fFirstGremlin;
+ dest.fLastGremlin = src.fLastGremlin;
+ dest.fSaveFrequency = src.fSaveFrequency;
+ dest.fSwitchDepth = src.fSwitchDepth;
+ dest.fMaxDepth = src.fMaxDepth;
+
+ EmMem_strcpy (dest.fAppNames, src.fAppNames.GetPtr ());
+ }
+}
+
+
+void Marshal::PutHostGremlinInfoType (emuptr p, const HostGremlinInfoType& src)
+{
+ if (p)
+ {
+ EmAliasHostGremlinInfoType<PAS> dest(p);
+
+ dest.fFirstGremlin = src.fFirstGremlin;
+ dest.fLastGremlin = src.fLastGremlin;
+ dest.fSaveFrequency = src.fSaveFrequency;
+ dest.fSwitchDepth = src.fSwitchDepth;
+ dest.fMaxDepth = src.fMaxDepth;
+
+ EmMem_strcpy (dest.fAppNames.GetPtr (), src.fAppNames);
+ }
+}
+
+
+#pragma mark -
+
+// ------------------------
+// ----- HostStatType -----
+// ------------------------
+
+void Marshal::GetHostStatType (emuptr p, HostStatType& dest)
+{
+ memset (&dest, 0, sizeof (HostStatType));
+
+ if (p)
+ {
+ EmAliasHostStatType<PAS> src(p);
+
+ dest.st_dev_ = src.st_dev_;
+ dest.st_ino_ = src.st_ino_;
+ dest.st_mode_ = src.st_mode_;
+ dest.st_nlink_ = src.st_nlink_;
+ dest.st_uid_ = src.st_uid_;
+ dest.st_gid_ = src.st_gid_;
+ dest.st_rdev_ = src.st_rdev_;
+ dest.st_atime_ = src.st_atime_;
+ dest.st_mtime_ = src.st_mtime_;
+ dest.st_ctime_ = src.st_ctime_;
+ dest.st_size_ = src.st_size_;
+ dest.st_blksize_ = src.st_blksize_;
+ dest.st_blocks_ = src.st_blocks_;
+ dest.st_flags_ = src.st_flags_;
+ }
+}
+
+
+void Marshal::PutHostStatType (emuptr p, const HostStatType& src)
+{
+ if (p)
+ {
+ EmAliasHostStatType<PAS> dest(p);
+
+ dest.st_dev_ = src.st_dev_;
+ dest.st_ino_ = src.st_ino_;
+ dest.st_mode_ = src.st_mode_;
+ dest.st_nlink_ = src.st_nlink_;
+ dest.st_uid_ = src.st_uid_;
+ dest.st_gid_ = src.st_gid_;
+ dest.st_rdev_ = src.st_rdev_;
+ dest.st_atime_ = src.st_atime_;
+ dest.st_mtime_ = src.st_mtime_;
+ dest.st_ctime_ = src.st_ctime_;
+ dest.st_size_ = src.st_size_;
+ dest.st_blksize_ = src.st_blksize_;
+ dest.st_blocks_ = src.st_blocks_;
+ dest.st_flags_ = src.st_flags_;
+ }
+}
+
+
+#pragma mark -
+
+// ----------------------
+// ----- HostTmType -----
+// ----------------------
+
+void Marshal::GetHostTmType (emuptr p, HostTmType& dest)
+{
+ memset (&dest, 0, sizeof (HostTmType));
+
+ if (p)
+ {
+ EmAliasHostTmType<PAS> src(p);
+
+ dest.tm_sec_ = src.tm_sec_;
+ dest.tm_min_ = src.tm_min_;
+ dest.tm_hour_ = src.tm_hour_;
+ dest.tm_mday_ = src.tm_mday_;
+ dest.tm_mon_ = src.tm_mon_;
+ dest.tm_year_ = src.tm_year_;
+ dest.tm_wday_ = src.tm_wday_;
+ dest.tm_yday_ = src.tm_yday_;
+ dest.tm_isdst_ = src.tm_isdst_;
+ }
+}
+
+
+void Marshal::PutHostTmType (emuptr p, const HostTmType& src)
+{
+ if (p)
+ {
+ EmAliasHostTmType<PAS> dest(p);
+
+ dest.tm_sec_ = src.tm_sec_;
+ dest.tm_min_ = src.tm_min_;
+ dest.tm_hour_ = src.tm_hour_;
+ dest.tm_mday_ = src.tm_mday_;
+ dest.tm_mon_ = src.tm_mon_;
+ dest.tm_year_ = src.tm_year_;
+ dest.tm_wday_ = src.tm_wday_;
+ dest.tm_yday_ = src.tm_yday_;
+ dest.tm_isdst_ = src.tm_isdst_;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------
+// ----- HostUTimeType -----
+// -------------------------
+
+void Marshal::GetHostUTimeType (emuptr p, HostUTimeType& dest)
+{
+ memset (&dest, 0, sizeof (HostUTimeType));
+
+ if (p)
+ {
+ EmAliasHostUTimeType<PAS> src(p);
+
+ dest.crtime_ = src.crtime_;
+ dest.actime_ = src.actime_;
+ dest.modtime_ = src.modtime_;
+ }
+}
+
+
+void Marshal::PutHostUTimeType (emuptr p, const HostUTimeType& src)
+{
+ if (p)
+ {
+ EmAliasHostUTimeType<PAS> dest(p);
+
+ dest.crtime_ = src.crtime_;
+ dest.actime_ = src.actime_;
+ dest.modtime_ = src.modtime_;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- HwrBatCmdReadType -----
+// -------------------------------
+
+void Marshal::GetHwrBatCmdReadType (emuptr p, HwrBatCmdReadType& dest)
+{
+ memset (&dest, 0, sizeof (HwrBatCmdReadType));
+
+ if (p)
+ {
+ EmAliasHwrBatCmdReadType<PAS> src(p);
+
+ dest.mVolts = src.mVolts;
+ dest.abs = src.abs;
+ }
+}
+
+
+void Marshal::PutHwrBatCmdReadType (emuptr p, const HwrBatCmdReadType& src)
+{
+ if (p)
+ {
+ EmAliasHwrBatCmdReadType<PAS> dest(p);
+
+ dest.mVolts = src.mVolts;
+ dest.abs = src.abs;
+ }
+}
+
+
+#pragma mark -
+
+// -----------------------------
+// ----- NetSocketAddrType -----
+// -----------------------------
+
+void Marshal::GetNetSocketAddrType (emuptr p, NetSocketAddrType& d)
+{
+ memset (&d, 0, sizeof (NetSocketAddrType));
+
+ if (p)
+ {
+ EmAliasNetSocketAddrType<PAS> sockAddr (p);
+
+ switch (sockAddr.family)
+ {
+ case netSocketAddrRaw:
+ {
+ EmAliasNetSocketAddrRawType<PAS> src (p);
+ NetSocketAddrRawType& dest = (NetSocketAddrRawType&) d;
+
+ dest.family = src.family; // In HBO
+ dest.ifInstance = src.ifInstance; // Unspecified order
+ dest.ifCreator = src.ifCreator; // Unspecified order
+
+ break;
+ }
+
+ case netSocketAddrINET:
+ {
+ EmAliasNetSocketAddrINType<PAS> src (p);
+ NetSocketAddrINType& dest = (NetSocketAddrINType&) d;
+
+ dest.family = src.family; // In HBO
+ dest.port = htons (NetNToHS ((UInt16) src.port)); // In NBO
+ dest.addr = htonl (NetNToHL ((UInt32) src.addr)); // In NBO
+
+ break;
+ }
+
+ default:
+ {
+ // Do the best we can...
+ EmAliasNetSocketAddrType<PAS> src (p);
+ NetSocketAddrType& dest = (NetSocketAddrType&) d;
+
+ dest.family = src.family; // In HBO
+
+ EmMem_memcpy ((void*) &dest.data[0], src.data.GetPtr (), 14);
+ break;
+ }
+ }
+ }
+}
+
+
+void Marshal::PutNetSocketAddrType (emuptr p, const NetSocketAddrType& s)
+{
+ if (p)
+ {
+ switch (s.family)
+ {
+ case netSocketAddrRaw:
+ {
+ EmAliasNetSocketAddrRawType<PAS> dest (p);
+ NetSocketAddrRawType& src = (NetSocketAddrRawType&) s;
+
+ dest.family = src.family; // In HBO
+ dest.ifInstance = src.ifInstance; // Unspecified order
+ dest.ifCreator = src.ifCreator; // Unspecified order
+
+ break;
+ }
+
+ case netSocketAddrINET:
+ {
+ EmAliasNetSocketAddrINType<PAS> dest (p);
+ NetSocketAddrINType& src = (NetSocketAddrINType&) s;
+
+ dest.family = src.family; // In HBO
+ dest.port = NetHToNS (ntohs (src.port)); // In NBO
+ dest.addr = NetHToNL (ntohl (src.addr)); // In NBO
+
+ break;
+ }
+
+ default:
+ {
+ // Do the best we can...
+ EmAliasNetSocketAddrType<PAS> dest (p);
+ NetSocketAddrType& src = (NetSocketAddrType&) s;
+
+ dest.family = src.family; // In HBO
+
+ EmMem_memcpy (dest.data.GetPtr (), (void*) &src.data[0], 14);
+ break;
+ }
+ }
+ }
+}
+
+
+#pragma mark -
+
+// --------------------------
+// ----- NetIOParamType -----
+// --------------------------
+
+void Marshal::GetNetIOParamType (emuptr p, NetIOParamType& dest)
+{
+ memset (&dest, 0, sizeof (NetIOParamType));
+
+ if (p)
+ {
+ EmAliasNetIOParamType<PAS> src (p);
+
+ // Copy the simple fields.
+
+ dest.addrLen = src.addrLen;
+ dest.iovLen = src.iovLen;
+ dest.accessRightsLen = src.accessRightsLen;
+
+ // Copy the address field.
+
+ dest.addrP = (UInt8*) GetBuffer (src.addrP, src.addrLen);
+ if (dest.addrP)
+ {
+ // The "family" field needs to be stored in HBO, not NBO.
+ // The following sequence will assure that.
+
+ EmAliasNetSocketAddrType<PAS> addr (src.addrP);
+
+ ((NetSocketAddrType*) (dest.addrP))->family = addr.family;
+ }
+
+ // Copy the access rights field.
+
+ dest.accessRights = (UInt8*) GetBuffer (src.accessRights, dest.accessRightsLen);
+
+ // Copy the i/o buffers.
+
+ dest.iov = (NetIOVecPtr) Platform::AllocateMemory (dest.iovLen * sizeof (NetIOVecType));
+ emuptr iovP = src.iov;
+
+ for (UInt16 ii = 0; ii < dest.iovLen; ++ii)
+ {
+ EmAliasNetIOVecType<PAS> iov (iovP);
+
+ dest.iov[ii].bufLen = iov.bufLen;
+ dest.iov[ii].bufP = (UInt8*) GetBuffer (iov.bufP, iov.bufLen);
+
+ iovP += iov.GetSize ();
+ }
+ }
+}
+
+
+void Marshal::PutNetIOParamType (emuptr p, const NetIOParamType& src)
+{
+ if (p)
+ {
+ EmAliasNetIOParamType<PAS> dest (p);
+
+ // Copy the simple fields.
+
+ dest.addrLen = src.addrLen;
+ dest.iovLen = src.iovLen;
+ dest.accessRightsLen = src.accessRightsLen;
+
+ // Copy the address field.
+
+ PutBuffer (dest.addrP, src.addrP, src.addrLen);
+
+ if (src.addrP)
+ {
+ // The "family" field needs to be stored in HBO, not NBO.
+ // The following sequence will assure that.
+
+ EmAliasNetSocketAddrType<PAS> addr (dest.addrP);
+
+ addr.family = ((NetSocketAddrType*) (src.addrP))->family;
+ }
+
+ // Copy the access rights field.
+
+ PutBuffer (dest.accessRights, src.accessRights, src.accessRightsLen);
+
+ // Copy the i/o buffers.
+
+ emuptr iovP = dest.iov;
+
+ for (UInt16 ii = 0; ii < src.iovLen; ++ii)
+ {
+ EmAliasNetIOVecType<PAS> iov (iovP);
+
+ iov.bufLen = src.iov[ii].bufLen;
+ PutBuffer (iov.bufP, src.iov[ii].bufP, src.iov[ii].bufLen);
+
+ iovP += iov.GetSize ();
+ }
+
+ void* buffer = src.iov;
+ Platform::DisposeMemory (buffer);
+ }
+}
+
+
+#pragma mark -
+
+// ------------------------------
+// ----- NetHostInfoBufType -----
+// ------------------------------
+
+/*
+ typedef struct
+ {
+ NetHostInfoType hostInfo;
+ {
+ Char* nameP; -------------------------+
+ Char** nameAliasesP;-------------------|---+
+ UInt16 addrType; | |
+ UInt16 addrLen; | |
+ UInt8** addrListP;----------------------|---|---+
+ } | | |
+ | | |
+ Char name[netDNSMaxDomainName+1]; <----+ | |
+ | |
+ Char* aliasList[netDNSMaxAliases+1]; <------+ |
+ Char aliases[netDNSMaxAliases][netDNSMaxDomainName+1];
+ |
+ NetIPAddr* addressList[netDNSMaxAddresses]; <--------+
+ NetIPAddr address[netDNSMaxAddresses];
+
+ } NetHostInfoBufType, *NetHostInfoBufPtr;
+*/
+
+void Marshal::GetNetHostInfoBufType (emuptr p, NetHostInfoBufType& netHostInfoBufType)
+{
+ memset (&netHostInfoBufType, 0, sizeof (NetHostInfoBufType));
+
+ if (p)
+ {
+ }
+}
+
+
+void Marshal::PutNetHostInfoBufType (emuptr p, const NetHostInfoBufType& src)
+{
+ if (p)
+ {
+ EmAliasNetHostInfoBufType<PAS> dest (p);
+
+ // Copy the host name.
+
+ dest.hostInfo.nameP = dest.name.GetPtr ();
+ EmMem_strcpy ((emuptr) dest.hostInfo.nameP, src.name);
+
+ // Copy the aliases.
+
+ dest.hostInfo.nameAliasesP = dest.aliasList.GetPtr ();
+
+ Char** srcNameAliasesP = src.hostInfo.nameAliasesP; // Ptr to src ptrs
+ emuptr destAliasList = dest.aliasList.GetPtr (); // Ptr to dest ptrs
+ emuptr destAliases = dest.aliases.GetPtr (); // Ptr to dest buffer
+
+ while (*srcNameAliasesP)
+ {
+ EmMem_strcpy (destAliases, *srcNameAliasesP);
+
+ EmAliasemuptr<PAS> p (destAliasList);
+ p = destAliases;
+
+ destAliasList += sizeof (emuptr);
+ destAliases += strlen (*srcNameAliasesP) + 1;
+ srcNameAliasesP += 1;
+ }
+
+ EmAliasemuptr<PAS> p1 (destAliasList);
+ p1 = EmMemNULL;
+
+ // Copy the easy fields.
+
+ dest.hostInfo.addrType = src.hostInfo.addrType;
+ dest.hostInfo.addrLen = src.hostInfo.addrLen;
+
+ // Copy the address list.
+
+ dest.hostInfo.addrListP = dest.addressList.GetPtr ();
+
+ NetIPAddr** addrListP = (NetIPAddr**) src.hostInfo.addrListP;
+ emuptr destAddressList = dest.addressList.GetPtr ();
+ emuptr destAddress = dest.address.GetPtr ();
+
+ while (*addrListP)
+ {
+ // Copy them one at a time to sort out endian issues. Just how this
+ // is supposed to be done is not clear (NetLib documentation says that
+ // the addresses are in HBO, while the WinSock header says that the
+ // addresses are supplied in NBO but returned in HBO), but the following
+ // seems to work.
+
+ EmAliasNetIPAddr<PAS> addr (destAddress);
+ addr = ntohl (**addrListP);
+
+ EmAliasemuptr<PAS> p (destAddressList);
+ p = destAddress;
+
+ destAddressList += sizeof (emuptr);
+ destAddress += sizeof (NetIPAddr);
+ addrListP += 1;
+ }
+
+ EmAliasemuptr<PAS> p2 (destAddressList);
+ p2 = EmMemNULL;
+ }
+}
+
+
+#pragma mark -
+
+// ------------------------------
+// ----- NetServInfoBufType -----
+// ------------------------------
+
+void Marshal::GetNetServInfoBufType (emuptr p, NetServInfoBufType& netServInfoBuf)
+{
+ memset (&netServInfoBuf, 0, sizeof (NetServInfoBufType));
+
+ if (p)
+ {
+ }
+}
+
+
+void Marshal::PutNetServInfoBufType (emuptr p, const NetServInfoBufType& src)
+{
+ if (p)
+ {
+ EmAliasNetServInfoBufType<PAS> dest (p);
+
+ // Copy the server name.
+
+ dest.servInfo.nameP = dest.name.GetPtr ();
+ EmMem_strcpy ((emuptr) dest.servInfo.nameP, src.name);
+
+ // Copy the aliases.
+
+ dest.servInfo.nameAliasesP = dest.aliasList.GetPtr ();
+
+ Char** srcNameAliasesP = src.servInfo.nameAliasesP; // Ptr to src ptrs
+ emuptr destAliasList = dest.aliasList.GetPtr (); // Ptr to dest ptrs
+ emuptr destAliases = dest.aliases.GetPtr (); // Ptr to dest buffer
+
+ while (*srcNameAliasesP)
+ {
+ EmMem_strcpy (destAliases, *srcNameAliasesP);
+
+ EmAliasemuptr<PAS> p (destAliasList);
+ p = destAliases;
+
+ destAliasList += sizeof (emuptr);
+ destAliases += strlen (*srcNameAliasesP) + 1;
+ srcNameAliasesP += 1;
+ }
+
+ EmAliasemuptr<PAS> p1 (destAliasList);
+ p1 = EmMemNULL;
+
+ // Copy the port.
+
+ dest.servInfo.port = NetHToNS (ntohs (src.servInfo.port)); // In NBO
+
+ // Copy the proto name.
+
+ dest.servInfo.protoP = dest.protoName.GetPtr ();
+ EmMem_strcpy ((emuptr) dest.servInfo.protoP, src.protoName);
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- PointType -----
+// -------------------------------
+
+void Marshal::GetPointType (emuptr p, PointType& dest)
+{
+ memset (&dest, 0, sizeof (PointType));
+
+ if (p)
+ {
+ EmAliasPointType<PAS> src(p);
+
+ dest.x = src.x;
+ dest.y = src.y;
+ }
+}
+
+
+void Marshal::PutPointType (emuptr p, const PointType& src)
+{
+ if (p)
+ {
+ EmAliasPointType<PAS> dest(p);
+
+ dest.x = src.x;
+ dest.y = src.y;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- RectangleType -----
+// -------------------------------
+
+void Marshal::GetRectangleType (emuptr p, RectangleType& dest)
+{
+ memset (&dest, 0, sizeof (RectangleType));
+
+ if (p)
+ {
+ EmAliasRectangleType<PAS> src(p);
+
+ dest.topLeft.x = src.topLeft.x;
+ dest.topLeft.y = src.topLeft.y;
+ dest.extent.x = src.extent.x;
+ dest.extent.y = src.extent.y;
+ }
+}
+
+
+void Marshal::PutRectangleType (emuptr p, const RectangleType& src)
+{
+ if (p)
+ {
+ EmAliasRectangleType<PAS> dest(p);
+
+ dest.topLeft.x = src.topLeft.x;
+ dest.topLeft.y = src.topLeft.y;
+ dest.extent.x = src.extent.x;
+ dest.extent.y = src.extent.y;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- SndCommandType -----
+// -------------------------------
+
+void Marshal::GetSndCommandType (emuptr p, SndCommandType& dest)
+{
+ memset (&dest, 0, sizeof (SndCommandType));
+
+ if (p)
+ {
+ EmAliasSndCommandType<PAS> src(p);
+
+ dest.cmd = src.cmd;
+ dest.reserved = src.reserved;
+ dest.param1 = src.param1;
+ dest.param2 = src.param2;
+ dest.param3 = src.param3;
+ }
+}
+
+
+void Marshal::PutSndCommandType (emuptr p, const SndCommandType& src)
+{
+ if (p)
+ {
+ EmAliasSndCommandType<PAS> dest(p);
+
+ dest.cmd = src.cmd;
+ dest.reserved = src.reserved;
+ dest.param1 = src.param1;
+ dest.param2 = src.param2;
+ dest.param3 = src.param3;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- SysAppInfoType -----
+// -------------------------------
+
+void Marshal::GetSysAppInfoType (emuptr p, SysAppInfoType& dest)
+{
+ memset (&dest, 0, sizeof (SysAppInfoType));
+
+ if (p)
+ {
+ EmAliasSysAppInfoType<PAS> src(p);
+
+ dest.cmd = src.cmd;
+ dest.cmdPBP = (MemPtr) (emuptr) src.cmdPBP;
+ dest.launchFlags = src.launchFlags;
+ dest.taskID = src.taskID;
+ dest.codeH = (MemHandle) (emuptr) src.codeH;
+ dest.dbP = (DmOpenRef) (emuptr) src.dbP;
+ dest.stackP = (UInt8*) (emuptr) src.stackP;
+ dest.globalsChunkP = (UInt8*) (emuptr) src.globalsChunkP;
+ dest.memOwnerID = src.memOwnerID;
+ dest.dmAccessP = (MemPtr) (emuptr) src.dmAccessP;
+ dest.dmLastErr = src.dmLastErr;
+ dest.errExceptionP = (MemPtr) (emuptr) src.errExceptionP;
+
+ // PalmOS v3.0 fields begin here
+
+ if (EmPatchState::OSMajorVersion () >= 3)
+ {
+ dest.a5Ptr = (UInt8*) (emuptr) src.a5Ptr;
+ dest.stackEndP = (UInt8*) (emuptr) src.stackEndP;
+ dest.globalEndP = (UInt8*) (emuptr) src.globalEndP;
+ dest.rootP = (struct SysAppInfoType*) (emuptr) src.rootP;
+ dest.extraP = (MemPtr) (emuptr) src.extraP;
+ }
+ }
+}
+
+
+void Marshal::PutSysAppInfoType (emuptr p, const SysAppInfoType& src)
+{
+ if (p)
+ {
+ EmAliasSysAppInfoType<PAS> dest(p);
+
+ dest.cmd = src.cmd;
+ dest.cmdPBP = (emuptr) src.cmdPBP;
+ dest.launchFlags = src.launchFlags;
+ dest.taskID = src.taskID;
+ dest.codeH = (emuptr) src.codeH;
+ dest.dbP = (emuptr) src.dbP;
+ dest.stackP = (emuptr) src.stackP;
+ dest.globalsChunkP = (emuptr) src.globalsChunkP;
+ dest.memOwnerID = src.memOwnerID;
+ dest.dmAccessP = (emuptr) src.dmAccessP;
+ dest.dmLastErr = src.dmLastErr;
+ dest.errExceptionP = (emuptr) src.errExceptionP;
+
+ // PalmOS v3.0 fields begin here
+
+ if (EmPatchState::OSMajorVersion () >= 3)
+ {
+ dest.a5Ptr = (emuptr) src.a5Ptr;
+ dest.stackEndP = (emuptr) src.stackEndP;
+ dest.globalEndP = (emuptr) src.globalEndP;
+ dest.rootP = (emuptr) src.rootP;
+ dest.extraP = (emuptr) src.extraP;
+ }
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- SysNVParamsType -----
+// -------------------------------
+
+void Marshal::GetSysNVParamsType (emuptr p, SysNVParamsType& dest)
+{
+ memset (&dest, 0, sizeof (SysNVParamsType));
+
+ if (p)
+ {
+ EmAliasSysNVParamsType<PAS> src(p);
+
+ dest.rtcHours = src.rtcHours;
+ dest.rtcHourMinSecCopy = src.rtcHourMinSecCopy;
+ dest.swrLCDContrastValue = src.swrLCDContrastValue;
+ dest.swrLCDBrightnessValue = src.swrLCDBrightnessValue;
+ dest.splashScreenPtr = (void*) (emuptr) src.splashScreenPtr;
+ dest.hardResetScreenPtr = (void*) (emuptr) src.hardResetScreenPtr;
+ dest.localeLanguage = src.localeLanguage;
+ dest.localeCountry = src.localeCountry;
+ dest.sysNVOEMStorage1 = src.sysNVOEMStorage1;
+ dest.sysNVOEMStorage2 = src.sysNVOEMStorage2;
+ }
+}
+
+
+void Marshal::PutSysNVParamsType (emuptr p, const SysNVParamsType& src)
+{
+ if (p)
+ {
+ EmAliasSysNVParamsType<PAS> dest(p);
+
+ dest.rtcHours = src.rtcHours;
+ dest.rtcHourMinSecCopy = src.rtcHourMinSecCopy;
+ dest.swrLCDContrastValue = src.swrLCDContrastValue;
+ dest.swrLCDBrightnessValue = src.swrLCDBrightnessValue;
+ dest.splashScreenPtr = (emuptr) src.splashScreenPtr;
+ dest.hardResetScreenPtr = (emuptr) src.hardResetScreenPtr;
+ dest.localeLanguage = src.localeLanguage;
+ dest.localeCountry = src.localeCountry;
+ dest.sysNVOEMStorage1 = src.sysNVOEMStorage1;
+ dest.sysNVOEMStorage2 = src.sysNVOEMStorage2;
+ }
+}
+
+
+#pragma mark -
+
+// -------------------------------
+// ----- SysKernelInfoType -----
+// -------------------------------
+
+void Marshal::GetSysKernelInfoType (emuptr p, SysKernelInfoType& dest)
+{
+ memset (&dest, 0, sizeof (SysKernelInfoType));
+
+ if (p)
+ {
+ EmAliasSysKernelInfoType<PAS> src(p);
+
+ dest.selector = src.selector;
+ dest.reserved = src.reserved;
+ dest.id = src.id;
+
+ switch (dest.selector)
+ {
+ case sysKernelInfoSelCurTaskInfo:
+ case sysKernelInfoSelTaskInfo:
+ dest.param.task.id = src.task.id;
+ dest.param.task.nextID = src.task.nextID;
+ dest.param.task.tag = src.task.tag;
+ dest.param.task.status = src.task.status;
+ dest.param.task.timer = src.task.timer;
+ dest.param.task.timeSlice = src.task.timeSlice;
+ dest.param.task.priority = src.task.priority;
+ dest.param.task.attributes = src.task.attributes;
+ dest.param.task.pendingCalls = src.task.pendingCalls;
+ dest.param.task.senderTaskID = src.task.senderTaskID;
+ dest.param.task.msgExchangeID = src.task.msgExchangeID;
+ dest.param.task.tcbP = src.task.tcbP;
+ dest.param.task.stackP = src.task.stackP;
+ dest.param.task.stackStart = src.task.stackStart;
+ dest.param.task.stackSize = src.task.stackSize;
+ break;
+
+ case sysKernelInfoSelSemaphoreInfo:
+ dest.param.semaphore.id = src.semaphore.id;
+ dest.param.semaphore.nextID = src.semaphore.nextID;
+ dest.param.semaphore.tag = src.semaphore.tag;
+ dest.param.semaphore.initValue = src.semaphore.initValue;
+ dest.param.semaphore.curValue = src.semaphore.curValue;
+ dest.param.semaphore.nestLevel = src.semaphore.nestLevel;
+ dest.param.semaphore.ownerID = src.semaphore.ownerID;
+ break;
+
+ case sysKernelInfoSelTimerInfo:
+ dest.param.timer.id = src.timer.id;
+ dest.param.timer.nextID = src.timer.nextID;
+ dest.param.timer.tag = src.timer.tag;
+ dest.param.timer.ticksLeft = src.timer.ticksLeft;
+ dest.param.timer.period = src.timer.period;
+ dest.param.timer.proc = src.timer.proc;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+ }
+}
+
+
+void Marshal::PutSysKernelInfoType (emuptr p, const SysKernelInfoType& src)
+{
+ if (p)
+ {
+ EmAliasSysKernelInfoType<PAS> dest(p);
+
+ dest.selector = src.selector;
+ dest.reserved = src.reserved;
+ dest.id = src.id;
+
+ switch (dest.selector)
+ {
+ case sysKernelInfoSelCurTaskInfo:
+ case sysKernelInfoSelTaskInfo:
+ dest.task.id = src.param.task.id;
+ dest.task.nextID = src.param.task.nextID;
+ dest.task.tag = src.param.task.tag;
+ dest.task.status = src.param.task.status;
+ dest.task.timer = src.param.task.timer;
+ dest.task.timeSlice = src.param.task.timeSlice;
+ dest.task.priority = src.param.task.priority;
+ dest.task.attributes = src.param.task.attributes;
+ dest.task.pendingCalls = src.param.task.pendingCalls;
+ dest.task.senderTaskID = src.param.task.senderTaskID;
+ dest.task.msgExchangeID = src.param.task.msgExchangeID;
+ dest.task.tcbP = src.param.task.tcbP;
+ dest.task.stackP = src.param.task.stackP;
+ dest.task.stackStart = src.param.task.stackStart;
+ dest.task.stackSize = src.param.task.stackSize;
+ break;
+
+ case sysKernelInfoSelSemaphoreInfo:
+ dest.semaphore.id = src.param.semaphore.id;
+ dest.semaphore.nextID = src.param.semaphore.nextID;
+ dest.semaphore.tag = src.param.semaphore.tag;
+ dest.semaphore.initValue = src.param.semaphore.initValue;
+ dest.semaphore.curValue = src.param.semaphore.curValue;
+ dest.semaphore.nestLevel = src.param.semaphore.nestLevel;
+ dest.semaphore.ownerID = src.param.semaphore.ownerID;
+ break;
+
+ case sysKernelInfoSelTimerInfo:
+ dest.timer.id = src.param.timer.id;
+ dest.timer.nextID = src.param.timer.nextID;
+ dest.timer.tag = src.param.timer.tag;
+ dest.timer.ticksLeft = src.param.timer.ticksLeft;
+ dest.timer.period = src.param.timer.period;
+ dest.timer.proc = src.param.timer.proc;
+ break;
+
+ default:
+ EmAssert (false);
+ }
+ }
+}
diff --git a/SrcShared/Marshal.h b/SrcShared/Marshal.h
new file mode 100644
index 0000000..4da60f6
--- /dev/null
+++ b/SrcShared/Marshal.h
@@ -0,0 +1,755 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _MARSHAL_H_
+#define _MARSHAL_H_
+
+#include "EmBankMapped.h" // UnmapPhysicalMemory
+#include "EmMemory.h" // EmMemGet32, EmMemGet16, EmMemGet8, EmMem_memcpy
+#include "EmPalmStructs.h" // EmProxy
+#include "EmSubroutine.h" // EmSubroutine
+#include "Platform.h" // Platform::AllocateMemory
+
+
+/* ===========================================================================
+
+ Functions and macros for helping with marshaling and unmarshaling
+ parameters from and to the emulated process's stack. First, the stack
+ is described with a class called EmSubroutine which lists the function's
+ parameters in order. For example, the definition for NetLibDmReceive is
+ as follows:
+
+ EmSubroutine sub ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags, "
+ "void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP");
+
+ This class describes the format of the parameters on the stack. You
+ then use one of several macros to fetch and possibly return values from
+ and to those parameters.
+
+ Use PARAM_VAL to manage pass-by-value parameter, such as a Long or a
+ Word. Example:
+
+ PARAM_VAL(Word, libRefNum);
+
+ This defines a local variable called libRefNum that contains the value
+ passed on the stack. The variable is an instance of a class that can
+ produce a Word, and so can be passed to functions that take a Word.
+
+ Use PARAM_REF to manage a pass-by-reference parameter, such as a Long*
+ or a Word*. Example:
+
+ PARAM_REF(Word, fromLenP, kInput);
+
+ This defines a local variable called fromLenP that contains the pointer
+ passed on the stack as well as a copy of the value that it points to.
+ The variable is an instance of a class that can produce a Word*, and so
+ can be passed to functions that take a Word*. If the parameter
+ reference was NULL, then the class produces NULL as well. The third
+ parameter to the macro describes whether or not the value passed in is
+ an input parameter (kInput), output parameter (kOutput) or both
+ (kInOut). If kInput or kInOut, the referenced value is fetched and
+ converted to host format. Otherwise, it is assumed that the parameter
+ references uninitialized contents. If kOutput or kInOut, the value is
+ copied back into the memory specified by the parameter reference.
+ Values are explicitly copied back to emulated memory by calling
+ fromLenP's Put() method.
+
+ Use PARAM_PTR to manage an arbitrary block of data pointed to by a
+ function parameter, such as a void* or BytePtr. Example:
+
+ PARAM_PTR(void, recordP, len, kInOut);
+
+ This defines a local variable called recordP that points to a block of
+ data "len" bytes long. If the fourth parameter is kInput or kInOut, the
+ memory pointed to by the function parameter is copied into this block of
+ data. If the fourth parameter is kOutput or kInOut, the contents of the
+ buffer are copied back to the emulated memory when the Put() method is
+ called. NULL pointers are handled.
+
+ Use PARAM_STR as a special kind of PARAM_PTR where the length is not
+ explicitly known, but the referenced data is NULL terminated. Example:
+
+ PARAM_STR(Char, nameP);
+
+ This defines a local variable called nameP that contains a pointer to a
+ string, the contents of which are copied from emulated memory. These
+ variables are actually like PARAM_STRs with kInput as the third
+ parameter, but there's no real need for that restriction.
+
+ The above macros expand to variable definitions. The name of the
+ variable is given by the second macro parameter, and the type of the
+ variable is determined by the first parameter. The type of variable is
+ actually created from a class template. There are four class templates:
+ ParamVal, ParamRef, ParamPtr, and ParamStr.
+
+ The constructors for these classes fetch the the appropriate values from
+ memory, allocating any necessary buffers. Their destructors do nothing
+ (which really saves in terms of exception handling overhead).
+
+ When the fetched values have been used and it's time to return any
+ changed values back to the emulated stack/heap, all the classes (except
+ ParamVal) have Put methods. You must call this method when you are done
+ with the values. The Put method writes back any altered values and
+ releases any memory allocated in the constructor.
+
+=========================================================================== */
+
+struct HostGremlinInfoType;
+struct HostStatType;
+struct HostTmType;
+struct HostUTimeType;
+
+typedef struct ExgSocketType* ExgSocketPtr;
+typedef UInt8* UInt8Ptr;
+
+
+#define CALLED_SETUP(return_decl, parameter_decl) \
+ static EmSubroutine sub; \
+ \
+ static Bool initialized; \
+ if (!initialized) \
+ { \
+ initialized = true; \
+ sub.DescribeDecl (return_decl, parameter_decl); \
+ } \
+ \
+ sub.PrepareStack (kForBeingCalled, false)
+
+
+#define CALLED_SETUP_HC(return_decl, parameter_decl) \
+ static EmSubroutine sub; \
+ \
+ static Bool initialized; \
+ if (!initialized) \
+ { \
+ initialized = true; \
+ sub.DescribeDecl (return_decl, "HostControlSelectorType _selector, " parameter_decl); \
+ } \
+ \
+ sub.PrepareStack (kForBeingCalled, false)
+
+
+#define CALLED_SETUP_STDARG(return_decl, parameter_decl) \
+ EmSubroutine sub; \
+ sub.DescribeDecl (return_decl, parameter_decl); \
+ sub.PrepareStack (kForBeingCalled, true)
+
+
+#define CALLED_SETUP_STDARG_HC(return_decl, parameter_decl) \
+ EmSubroutine sub; \
+ sub.DescribeDecl (return_decl, "HostControlSelectorType selector, " parameter_decl); \
+ sub.PrepareStack (kForBeingCalled, true)
+
+
+#define CALLER_SETUP(return_decl, parameter_decl) \
+ static EmSubroutine sub; \
+ \
+ static Bool initialized; \
+ if (!initialized) \
+ { \
+ initialized = true; \
+ sub.DescribeDecl (return_decl, parameter_decl); \
+ } \
+ \
+ sub.PrepareStack (kForCalling, false)
+
+
+#define GET_RESULT_VAL(type) \
+ type result; \
+ Marshal::GetReturnVal (sub, result);
+
+
+#define GET_RESULT_PTR() \
+ emuptr result; \
+ Marshal::GetReturnVal (sub, result);
+
+
+#define PUT_RESULT_VAL(type, val) \
+ Marshal::PutReturnVal (sub, (type) val);
+
+
+#define PUT_RESULT_PTR(type, val) \
+ Marshal::PutReturnVal (sub, (type) val);
+
+
+#define RETURN_RESULT_VAL(type) \
+ GET_RESULT_VAL (type); \
+ return result
+
+
+#define RETURN_RESULT_PTR(type) \
+ GET_RESULT_PTR (); \
+ return (type) result
+
+
+
+// Macros used when being called by emulated code
+// (e.g., from trap patches).
+
+#define CALLED_GET_PARAM_VAL(type, name) \
+ ParamVal<type> name (sub, #name)
+
+#define CALLED_GET_PARAM_REF(type, name, io) \
+ ParamRef<type, io> name (sub, #name)
+
+#define CALLED_GET_PARAM_PTR(type, name, len, io) \
+ ParamPtr<type, io> name (sub, #name, len)
+
+#define CALLED_GET_PARAM_STR(type, name) \
+ ParamStr<type> name (sub, #name)
+
+#define CALLED_PUT_PARAM_REF(name) \
+ name.Put ()
+
+
+// Macros used when calling emulated code
+// (e.g., the stuff in ROMStubs.cpp)
+
+#define CALLER_PUT_PARAM_VAL(type, name) \
+ PushParamVal<type> _##name (sub, #name, (type) name); \
+ /* *Use* the variable this way. GCC will complain that the */ \
+ /* PushParamVal variable is unused otherwise. */ \
+ ((void) _##name)
+
+#define CALLER_PUT_PARAM_REF(type, name, io) \
+ PushParamRef<type, io> _##name (sub, #name, (type*) name)
+
+#define CALLER_PUT_PARAM_PTR(type, name, len, io) \
+ PushParamPtr<type, io> _##name (sub, #name, name, len)
+
+#define CALLER_PUT_PARAM_STR(type, name) \
+ PushParamStr<type> _##name (sub, #name, name)
+
+#define CALLER_GET_PARAM_REF(name) \
+ _##name.Get ()
+
+
+class Marshal
+{
+ public:
+ // VC++ is a bit medieval here...
+// static const int kInput = 0x01;
+// static const int kOutput = 0x02;
+// static const int kInOut = kInput | kOutput;
+ enum
+ {
+ kInput = 0x01,
+ kOutput = 0x02,
+ kInOut = kInput | kOutput
+ };
+
+ #define INPUT(io) (((io) & Marshal::kInput) != 0)
+ #define OUTPUT(io) (((io) & Marshal::kOutput) != 0)
+
+ static void* GetBuffer (emuptr p, long len);
+#if (__GNUC__ == 2)
+ static void PutBuffer (emuptr p, unsigned char* const buf, long len)
+ {
+ if (p)
+ {
+ EmMem_memcpy (p, (void*) buf, len);
+ void* b = buf;
+ Platform::DisposeMemory (b);
+ }
+ }
+#else
+ template <class T>
+ static void PutBuffer (emuptr p, T* const buf, long len)
+ {
+ if (p)
+ {
+ EmMem_memcpy (p, (void*) buf, len);
+ void* b = buf;
+ Platform::DisposeMemory (b);
+ }
+ }
+#endif
+
+
+ /* ===========================================================================
+ The ParamFoo classes are templatized on the type of values they are to
+ fetch. In order to perform the actual fetching, they call GetParamVal
+ (and put the value back with PutParamVal). In order for those calls to
+ succeed, we have to have overloaded versions of that function for each
+ type we ever fetch. Those overloaded functions appear below.
+ =========================================================================== */
+
+#define DECLARE_POINTER_MARSHALLER(type) \
+ inline static void GetParamVal (EmSubroutine& sub, EmParamNameArg name, type*& v) \
+ { sub.GetParamVal (name, (emuptr&) v); } \
+ \
+ inline static void PutParamVal (EmSubroutine& sub, EmParamNameArg name, const type* v) \
+ { sub.SetParamVal (name, (emuptr) v); } \
+ \
+ inline static void PutReturnVal (EmSubroutine& sub, const type* v) \
+ { sub.SetReturnVal ((emuptr) v); }
+
+
+ DECLARE_POINTER_MARSHALLER (void)
+ DECLARE_POINTER_MARSHALLER (FormType)
+ DECLARE_POINTER_MARSHALLER (ExgSocketType)
+ DECLARE_POINTER_MARSHALLER (_opaque)
+
+
+#define DECLARE_SCALAR_MARSHALLER(type, asType, num_bits) \
+ inline static void GetParamVal (EmSubroutine& sub, EmParamNameArg name, type& v) \
+ { \
+ asType temp; \
+ sub.GetParamVal (name, temp); \
+ v = (type) temp; \
+ } \
+ \
+ inline static void PutParamVal (EmSubroutine& sub, EmParamNameArg name, type v) \
+ { sub.SetParamVal (name, (asType) v); } \
+ \
+ inline static void GetParamRef (emuptr p, type& v) \
+ { v = (type) EmMemGet##num_bits (p); } \
+ \
+ inline static void PutParamRef (emuptr p, const type& v) \
+ { EmMemPut##num_bits (p, (asType) v); } \
+ \
+ inline static void GetReturnVal (EmSubroutine& sub, type& v) \
+ { \
+ asType temp; \
+ sub.GetReturnVal (temp); \
+ v = (type) temp; \
+ } \
+ \
+ inline static void PutReturnVal (EmSubroutine& sub, type v) \
+ { sub.SetReturnVal ((asType&) v); } \
+ \
+ inline static long GetBufSize (const type&) \
+ { return sizeof(asType); }
+
+
+ DECLARE_SCALAR_MARSHALLER (int8, int8, 8)
+ DECLARE_SCALAR_MARSHALLER (uint8, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (int16, int16, 16)
+ DECLARE_SCALAR_MARSHALLER (uint16, uint16, 16)
+ DECLARE_SCALAR_MARSHALLER (int32, int32, 32)
+ DECLARE_SCALAR_MARSHALLER (uint32, uint32, 32)
+
+ DECLARE_SCALAR_MARSHALLER (ClipboardFormatType, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (DlkSyncStateType, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (FormObjectKind, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (LocalIDKind, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (NetSocketAddrEnum, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (NetSocketTypeEnum, uint8, 8)
+ DECLARE_SCALAR_MARSHALLER (SystemPreferencesChoice, uint8, 8)
+
+ DECLARE_SCALAR_MARSHALLER (SysAppInfoPtr, uint32, 32)
+ DECLARE_SCALAR_MARSHALLER (UInt8Ptr, uint32, 32)
+
+
+#define DECLARE_STRUCT_MARSHALLER(type) \
+ static void Get##type (emuptr p, type&); \
+ static void Put##type (emuptr p, const type&); \
+ \
+ static long GetBufSize (const type&) \
+ { return EmProxy##type::GetSize (); } \
+ \
+ inline static void GetParamRef (emuptr p, type& v) \
+ { Get##type (p, v); } \
+ \
+ inline static void PutParamRef (emuptr p, const type& v) \
+ { Put##type (p, v); }
+
+
+ DECLARE_STRUCT_MARSHALLER (DlkServerSessionType)
+ DECLARE_STRUCT_MARSHALLER (DmSearchStateType)
+ DECLARE_STRUCT_MARSHALLER (EventType)
+ DECLARE_STRUCT_MARSHALLER (FieldAttrType)
+ DECLARE_STRUCT_MARSHALLER (HostGremlinInfoType)
+ DECLARE_STRUCT_MARSHALLER (HostStatType)
+ DECLARE_STRUCT_MARSHALLER (HostTmType)
+ DECLARE_STRUCT_MARSHALLER (HostUTimeType)
+ DECLARE_STRUCT_MARSHALLER (HwrBatCmdReadType)
+ DECLARE_STRUCT_MARSHALLER (NetSocketAddrType)
+ DECLARE_STRUCT_MARSHALLER (NetIOParamType)
+ DECLARE_STRUCT_MARSHALLER (NetHostInfoBufType)
+ DECLARE_STRUCT_MARSHALLER (NetServInfoBufType)
+ DECLARE_STRUCT_MARSHALLER (PointType)
+ DECLARE_STRUCT_MARSHALLER (RectangleType)
+ DECLARE_STRUCT_MARSHALLER (SndCommandType)
+ DECLARE_STRUCT_MARSHALLER (SysAppInfoType)
+ DECLARE_STRUCT_MARSHALLER (SysKernelInfoType)
+ DECLARE_STRUCT_MARSHALLER (SysNVParamsType)
+};
+
+
+/* ===========================================================================
+ Class that manages an immediate value from the emulated stack. This
+ class can fetch the value from the stack and produce that value via a
+ type operator. The value cannot be changed, you can't take the address
+ of it, nor can the value be written back to the stack.
+=========================================================================== */
+
+template <typename T>
+class ParamVal
+{
+ public:
+ ParamVal (EmSubroutine& sub, EmParamNameArg name)
+ {
+ Marshal::GetParamVal (sub, name, fVal);
+ }
+
+ operator T(void) { return fVal; }
+
+ private:
+ T fVal;
+};
+
+
+/* ===========================================================================
+ Class that manages a value passed by reference on the emulated stack.
+ This class can fetch the pointer to the value and make a copy of the
+ value pointed to if the pointer was NULL. The class can produce a
+ pointer to the local copy of the value, or NULL if the parameter was
+ NULL. The class has a Put method which copies the local copy back to
+ the emulated memory the original came from. Whether or not the
+ referenced value is fetched or returned is determined by the inOut
+ template parameter. If the kInput bit is set, the value is copied from
+ emulated memory to a local copy. If the kOutput bit is set, the local
+ copy is copied back to emulated memory when the Put method is called.
+=========================================================================== */
+
+template <typename T, long inOut>
+class ParamRef
+{
+ public:
+ ParamRef (EmSubroutine& sub, EmParamNameArg name) :
+ fSub (&sub),
+ fName (name),
+ fPtr (EmMemNULL)
+ {
+ // Get and cache the pointer to the data.
+
+ fSub->GetParamVal (fName.c_str (), fPtr);
+
+ // If there's a pointer and this is an input
+ // variable, get the data.
+
+ if (fPtr && INPUT(inOut))
+ {
+ Marshal::GetParamRef (fPtr, fVal);
+ }
+ }
+
+ void Put (void)
+ {
+ // If there's a pointer and this is an output
+ // variable, store the data.
+
+ if (fPtr && OUTPUT(inOut))
+ {
+ Marshal::PutParamRef (fPtr, fVal);
+ }
+ }
+
+ operator T*(void) { return fPtr ? &fVal : NULL; }
+ const T& operator *(void) const { return fVal; }
+ T& operator *(void) { return fVal; }
+
+ operator emuptr (void) { return fPtr; }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ emuptr fPtr;
+ T fVal;
+};
+
+
+/* ===========================================================================
+ Class that manages a block of memory pointed to by a pointer on the
+ emulated stack. If the pointer is non-NULL, a local block of memory is
+ allocated. If the kInput bit of the inOut template parameter is set,
+ the range of emulated memory is copied into the local buffer. This class
+ can produce a pointer to the local block of memory on demand (if the
+ stack parameter was NULL, this class produces NULL). If the kOutput bit
+ of the inOut template paraemter is set, the local block's contents are
+ copied back into emulated memory when the Put method is called.
+ Regardless of inOut values, the Put method must be called in order to
+ release the lock block of memory.
+=========================================================================== */
+
+template <typename T, long inOut>
+class ParamPtr
+{
+ public:
+ ParamPtr (EmSubroutine& sub, EmParamNameArg name, long len) :
+ fSub (&sub),
+ fName (name),
+ fPtr (EmMemNULL),
+ fLen (len),
+ fVal (NULL)
+ {
+ // Get and cache the pointer to the data.
+
+ fSub->GetParamVal (fName.c_str (), fPtr);
+
+ if (fPtr)
+ {
+ fVal = (T*) Platform::AllocateMemory (fLen);
+ if (fVal && INPUT(inOut))
+ {
+ EmMem_memcpy ((void*) fVal, fPtr, fLen);
+ }
+ }
+ }
+
+ ~ParamPtr () // !!! Update comments about d'tors and disposing memory
+ {
+ Platform::DisposeMemory (fVal);
+ }
+
+ void Put (void)
+ {
+ if (fPtr && fVal && OUTPUT(inOut))
+ {
+ EmMem_memcpy (fPtr, (const void*) fVal, fLen);
+ }
+ }
+
+ operator T*(void) { return fVal; }
+
+ operator emuptr (void) { return fPtr; }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ emuptr fPtr;
+ long fLen;
+ T* fVal;
+};
+
+
+/* ===========================================================================
+ Class that manages a NULL-terminated range of memory pointed to by a
+ pointer on the emulated stack. The input pointer can be NULL. The
+ elements of the string can be anything, but will normally be Char
+ (actually, they may *have* to be Char, since I get the length of the
+ string by calling EmMem_strlen). The string is modifiable in-place, but
+ any changes are not copied back to emulated memory (this behavior can be
+ changed if needed).
+=========================================================================== */
+
+template <typename T>
+class ParamStr
+{
+ public:
+ ParamStr (EmSubroutine& sub, EmParamNameArg name) :
+ fSub (&sub),
+ fName (name),
+ fPtr (EmMemNULL),
+ fVal (NULL)
+ {
+ fSub->GetParamVal (fName.c_str (), fPtr);
+
+ if (fPtr)
+ {
+ fVal = (T*) Platform::AllocateMemory (EmMem_strlen (fPtr) + 1);
+ if (fVal)
+ {
+ EmMem_strcpy (fVal, fPtr);
+ }
+ }
+ }
+
+ ~ParamStr () // !!! Update comments about d'tors and disposing memory
+ {
+ Platform::DisposeMemory (fVal);
+ }
+
+ void Put (void)
+ {
+ }
+
+ operator T*(void) { return fVal; }
+
+ operator emuptr (void) { return fPtr; }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ emuptr fPtr;
+ T* fVal;
+};
+
+
+template <typename T>
+class PushParamVal
+{
+ public:
+ PushParamVal (EmSubroutine& sub, EmParamNameArg name, T val)
+ {
+ Marshal::PutParamVal (sub, name, val);
+ }
+};
+
+template <typename T, long inOut>
+class PushParamRef
+{
+ public:
+ PushParamRef (EmSubroutine& sub, EmParamNameArg name, T* ptr) :
+ fSub (&sub),
+ fName (name),
+ fHostPtr (ptr),
+ fMappedData (NULL),
+ fMappedPtr (EmMemNULL)
+ {
+ if (fHostPtr)
+ {
+ // Allocate a buffer big enough for the mapped/translated data.
+
+ long size = Marshal::GetBufSize (*fHostPtr);
+ fMappedData = Platform::AllocateMemory (size);
+
+ // Map the buffer
+
+ EmBankMapped::MapPhysicalMemory (fMappedData, size);
+ fMappedPtr = EmBankMapped::GetEmulatedAddress (fMappedData);
+
+ // Copy/translate the data into it.
+
+ if (INPUT(inOut))
+ {
+ Marshal::PutParamRef (fMappedPtr, *fHostPtr);
+ }
+
+ // Pass the pointer to the data.
+
+ fSub->SetParamVal (fName.c_str (), fMappedPtr);
+ }
+ else
+ {
+ fMappedPtr = EmMemNULL;
+ }
+
+ // Pass the pointer to the data.
+
+ fSub->SetParamVal (fName.c_str (), fMappedPtr);
+ }
+
+ ~PushParamRef (void)
+ {
+ if (fMappedData)
+ {
+ EmBankMapped::UnmapPhysicalMemory (fMappedData);
+ Platform::FreeMemory (fMappedData);
+ }
+ }
+
+ void Get (void)
+ {
+ if (fHostPtr && OUTPUT(inOut))
+ {
+ Marshal::GetParamRef (fMappedPtr, *fHostPtr);
+ }
+ }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ T* fHostPtr;
+ void* fMappedData;
+ emuptr fMappedPtr;
+};
+
+template <typename T, long inOut>
+class PushParamPtr
+{
+ public:
+ PushParamPtr (EmSubroutine& sub, EmParamNameArg name, const T* ptr, long size) :
+ fSub (&sub),
+ fName (name),
+ fHostPtr (ptr),
+ fMappedPtr (EmMemNULL)
+ {
+ if (fHostPtr)
+ {
+ // Map the buffer
+
+ EmBankMapped::MapPhysicalMemory (fHostPtr, size);
+ fMappedPtr = EmBankMapped::GetEmulatedAddress (fHostPtr);
+ }
+ else
+ {
+ fMappedPtr = EmMemNULL;
+ }
+
+ // Pass the pointer to the data.
+
+ fSub->SetParamVal (fName.c_str (), fMappedPtr);
+ }
+
+ ~PushParamPtr (void)
+ {
+ if (fHostPtr)
+ {
+ EmBankMapped::UnmapPhysicalMemory (fHostPtr);
+ }
+ }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ const T* fHostPtr;
+ emuptr fMappedPtr;
+};
+
+template <typename T>
+class PushParamStr
+{
+ public:
+ PushParamStr (EmSubroutine& sub, EmParamNameArg name, const T * const ptr) :
+ fSub (&sub),
+ fName (name),
+ fHostPtr (ptr),
+ fMappedPtr (EmMemNULL)
+ {
+ if (fHostPtr)
+ {
+ // Map the buffer
+
+ long size = strlen (ptr) + 1;
+ EmBankMapped::MapPhysicalMemory (fHostPtr, size);
+ fMappedPtr = EmBankMapped::GetEmulatedAddress (fHostPtr);
+ }
+ else
+ {
+ fMappedPtr = EmMemNULL;
+ }
+
+ // Pass the pointer to the data.
+
+ fSub->SetParamVal (fName.c_str (), fMappedPtr);
+ }
+
+ ~PushParamStr (void)
+ {
+ if (fHostPtr)
+ {
+ EmBankMapped::UnmapPhysicalMemory (fHostPtr);
+ }
+ }
+
+ private:
+ EmSubroutine* fSub;
+ EmParamName fName;
+ const T* const fHostPtr;
+ emuptr fMappedPtr;
+};
+
+#endif // _MARSHAL_H_
diff --git a/SrcShared/MetaMemory.cpp b/SrcShared/MetaMemory.cpp
new file mode 100644
index 0000000..c98d55a
--- /dev/null
+++ b/SrcShared/MetaMemory.cpp
@@ -0,0 +1,4096 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "MetaMemory.h"
+
+#include "DebugMgr.h" // Debug::GetRoutineName
+#include "EmBankSRAM.h" // gRAMBank_Size
+#include "EmCPU68K.h" // gCPU68K
+#include "EmHAL.h" // EmHAL
+#include "EmLowMem.h" // LowMem_SetGlobal, LowMem_GetGlobal
+#include "EmMemory.h" // CEnableFullAccess, EmMemGetMetaAddress
+#include "EmPalmFunction.h" // InFoo functions
+#include "EmPalmOS.h" // StackRange, GetBootStack
+#include "EmPalmStructs.h" // EmAliasWindowType, EmAliasFormType
+#include "EmPatchState.h" // IsInSysBinarySearch, OSMajorMinorVersion
+#include "EmSession.h" // gSession->ScheduleDeferredError
+#include "Logging.h" // ReportUIMgrDataAccess
+#include "Miscellaneous.h" // FindFunctionName
+#include "ROMStubs.h" // SysKernelInfo
+#include "SessionFile.h" // SessionFile::Write
+
+#include <algorithm> // find
+#include <ctype.h> // islower
+
+struct EmTaggedPalmChunk : public EmPalmChunk
+{
+ EmTaggedPalmChunk (void) {}
+ EmTaggedPalmChunk (const EmPalmChunk& chunk, Bool isSystemChunk) :
+ EmPalmChunk (chunk),
+ fIsSystemChunk (isSystemChunk)
+ {}
+
+ Bool fIsSystemChunk;
+};
+
+typedef vector<EmTaggedPalmChunk> EmTaggedPalmChunkList;
+
+static EmTaggedPalmChunkList gTaggedChunks;
+static Bool gHaveLastChunk;
+static EmTaggedPalmChunk gLastChunk;
+
+static vector<MemHandle> gBitmapHandleList;
+static vector<MemPtr> gBitmapPointerList;
+
+enum
+{
+ kUIWindow,
+ kUIBitmap
+};
+
+typedef Bool (*IterFn) (emuptr object, void* data, int type);
+static Bool PrvCheckUIObject (emuptr object, void* data, int type);
+static Bool PrvMarkUIObject (emuptr object, void* data, int type);
+static Bool PrvUnmarkUIObject (emuptr object, void* data, int type);
+static Bool PrvForEachBitmap (IterFn fn, void* data);
+static Bool PrvForEachWindow (IterFn fn, void* data);
+static Bool PrvForEachUIObject (IterFn fn, void* data);
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Initialize
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Initialize (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Reset
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Reset (void)
+{
+ gTaggedChunks.clear ();
+ gHaveLastChunk = false;
+
+ gBitmapHandleList.clear ();
+ gBitmapPointerList.clear ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Save
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Save (SessionFile& f)
+{
+ const long kCurrentVersion = 1;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ gBitmapHandleList.clear ();
+ gBitmapPointerList.clear ();
+
+ s << gBitmapHandleList;
+ s << gBitmapPointerList;
+
+ f.WriteMetaInfo (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Load
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Load (SessionFile& f)
+{
+ gTaggedChunks.clear ();
+ gHaveLastChunk = false;
+
+ Chunk chunk;
+ if (f.ReadMetaInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ s >> gBitmapHandleList;
+ s >> gBitmapPointerList;
+
+ gBitmapHandleList.clear ();
+ gBitmapPointerList.clear ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Dispose
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Dispose (void)
+{
+}
+
+
+#if FOR_LATER
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkUninitialized
+// ---------------------------------------------------------------------------
+
+void MetaMemory::MarkUninitialized (emuptr begin, emuptr end)
+{
+ MarkRange (begin, end, kUninitialized);
+}
+#endif
+
+
+#if FOR_LATER
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MoveUninitialized
+// ---------------------------------------------------------------------------
+// Transfer the initialized/uninitialized state of a range of bytes to a
+// new location. Called during MemMove, so that the state of the bytes
+// being moved can be preserved.
+
+void MetaMemory::MoveUninitialized (emuptr source, emuptr dest, uint32 size)
+{
+ source = MASK (source);
+ dest = MASK (dest);
+
+ if (source > fgMetaMemorySize)
+ return;
+
+ if (dest > fgMetaMemorySize)
+ return;
+
+ uint8* p0 = fgMetaMemory + source;
+ uint8* p1 = fgMetaMemory + dest;
+
+ while (size--)
+ {
+ uint8 dValue = *p0;
+ uint8 sValue = *p1;
+
+ dValue = (dValue & ~kUninitialized) | (sValue & kUninitialized);
+
+ *p0 = dValue;
+
+ ++p0;
+ ++p1;
+ }
+}
+#endif
+
+
+#if FOR_LATER
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkInitialized
+// ---------------------------------------------------------------------------
+
+void MetaMemory::MarkInitialized (emuptr begin, emuptr end)
+{
+ UnmarkRange (begin, end, kUninitialized);
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::SyncHeap
+// ---------------------------------------------------------------------------
+// Find chunk headers and mark them as memory manager structures. Mark
+// unlocked relocatable chunks as "unlocked" and "initialized" (as we don't
+// have any idea any more what their state was before they were moved).
+// Mark free blocks as "uninitialized".
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::SyncOneChunk
+// ---------------------------------------------------------------------------
+// Mark the chunk header, free chunks, and unlocked chunks.
+
+void MetaMemory::SyncOneChunk (const EmPalmChunk& chunk)
+{
+ // Set the access for the chunk header.
+
+ MarkChunkHeader (chunk.HeaderStart (), chunk.HeaderEnd ());
+
+ // Set the access for the body of the chunk.
+
+ // Check for free chunks.
+
+ if (chunk.Free ())
+ {
+ MarkFreeChunk (chunk.BodyStart (), chunk.BodyEnd ());
+ }
+
+ // It's not a free chunk; see if it's unlocked.
+
+ else if (chunk.LockCount () == 0)
+ {
+ MarkUnlockedChunk (chunk.BodyStart (), chunk.BodyEnd ());
+ }
+
+ // It's an allocated, locked chunk.
+
+ else
+ {
+ MarkTotalAccess (chunk.BodyStart (), chunk.BodyEnd ());
+ }
+
+ // Set the access for any unallocated trailing bytes.
+
+ if (chunk.TrailerSize () > 0)
+ {
+ MarkChunkTrailer (chunk.TrailerStart (), chunk.TrailerEnd ());
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::Resync
+// ---------------------------------------------------------------------------
+
+void MetaMemory::Resync (const EmPalmChunkList& delta)
+{
+ if (delta.size () == 0)
+ return;
+
+ // Get the heap that was changed. Assume that all chunks in the
+ // delta list are in the same heap for now.
+
+ EmPalmChunkList::const_iterator iter = delta.begin ();
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (iter->Start ());
+ if (!heap)
+ return;
+
+ // Only support syncing with dynamic heap for now.
+
+ if (heap->HeapID () != 0)
+ return;
+
+ while (iter != delta.end ())
+ {
+ SyncOneChunk (*iter);
+ ++iter;
+ }
+
+ // This process has just wiped out any access bits we've set
+ // for UI objects. Re-establish those.
+
+ MetaMemory::MarkUIObjects ();
+
+ // Mark the master pointer tables. Mark the MPT headers as
+ // for use by the Memory Manager. However, mark the tables
+ // themselves as usable by any of the OS; a lot of the OS
+ // uses a MemMgr macro to deref handles directly.
+
+ ITERATE_MPTS(*heap, mpt_iter, end)
+ {
+ MarkMPT (mpt_iter->Start (), mpt_iter->TableStart ());
+ MarkMPT (mpt_iter->TableStart (), mpt_iter->End ());
+ ++mpt_iter;
+ }
+
+ // Hack for startup time. When MemInit is called, it creates
+ // a free block spanning the entire dynamic heap. However,
+ // that's where the current stack happens to be. We still need
+ // access to that, so free it up.
+
+ StackRange range = EmPalmOS::GetBootStack ();
+ MarkTotalAccess (range.fBottom, range.fTop);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetWhatHappened
+// ---------------------------------------------------------------------------
+// Some memory access violation was detected. Nail down more closely what
+// it was. These checks can be expensive, as they only occur when we're
+// pretty sure we're about to report an error in a dialog.
+
+Errors::EAccessType MetaMemory::GetWhatHappened (emuptr address, long size, Bool forRead)
+{
+ // If we've whisked away all memory access checking, return now.
+
+ if (CEnableFullAccess::AccessOK ())
+ return Errors::kOKAccess;
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ Errors::EAccessType whatHappened = Errors::kUnknownAccess;
+
+ // Now figure out what just happened.
+
+ if (MetaMemory::IsLowMemory (address, size))
+ {
+ whatHappened = Errors::kLowMemAccess;
+ }
+
+ else if (MetaMemory::IsSystemGlobal (address, size))
+ {
+ whatHappened = Errors::kGlobalVarAccess;
+ }
+
+ else if (MetaMemory::IsScreenBuffer (address, size))
+ {
+ whatHappened = Errors::kScreenAccess;
+ }
+
+ else if (MetaMemory::IsLowStack (address, size))
+ {
+ whatHappened = Errors::kLowStackAccess;
+ }
+
+#if FOR_LATER
+ else if (MetaMemory::IsUninitialized (address, size))
+ {
+ if (MetaMemory::IsStack (address, size))
+ {
+ whatHappened = Errors::kUninitializedStack;
+ }
+
+ else if (MetaMemory::IsAllocatedChunk (address, size))
+ {
+ whatHappened = Errors::kUninitializedChunk;
+ }
+ }
+#endif
+
+ else
+ {
+ Bool inUIObject, butItsOK;
+ CheckUIObjectAccess (address, size, forRead, inUIObject, butItsOK);
+
+ if (inUIObject)
+ {
+ // We don't really need to do anything else (like return an
+ // error or check "butItsOK", since if an error occurred,
+ // an error object will be scheduled with the EmSession.
+
+ whatHappened = Errors::kOKAccess;
+ }
+ else
+ {
+ WhatHappenedData info;
+ info.result = Errors::kUnknownAccess;
+ info.address = address;
+ info.size = size;
+ info.forRead = forRead;
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByID (0);
+
+ if (heap)
+ GWH_ExamineHeap (*heap, info);
+
+ if (info.result != Errors::kUnknownAccess)
+ {
+ whatHappened = info.result;
+ }
+ }
+ }
+
+ whatHappened = AllowForBugs (address, size, forRead, whatHappened);
+
+ return whatHappened;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::AllowForBugs
+// ---------------------------------------------------------------------------
+
+Errors::EAccessType MetaMemory::AllowForBugs (emuptr address, long size, Bool forRead, Errors::EAccessType whatHappened)
+{
+ if (whatHappened == Errors::kOKAccess)
+ {
+ return whatHappened;
+ }
+
+ if (forRead)
+ {
+ // Let PrvFindMemoryLeaks have the run of the show.
+
+ if (::InPrvFindMemoryLeaks ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // SecPrvRandomSeed calls Crc16CalcBlock (NULL, 0x1000, 0).
+
+ emuptr a6 = gCPU68K->GetRegister (e68KRegID_A6);
+ if (::IsEven (a6) && EmPalmOS::IsInStack (a6))
+ {
+ emuptr rtnAddr = EmMemGet32 (a6 + 4);
+
+ if (address < 0x1000 &&
+ ::InCrc16CalcBlock () &&
+ ::InSecPrvRandomSeed (rtnAddr))
+ {
+ return Errors::kOKAccess;
+ }
+ }
+
+ if (whatHappened == Errors::kLowMemAccess)
+ {
+ // See if the the low-memory checksummer is at work.
+
+ if (size == 4 &&
+ ::InPrvSystemTimerProc ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // There's a bug in BackspaceChar (pre-3.2) that accesses the word at 0x0000.
+
+ if (EmPatchState::HasBackspaceCharBug () &&
+ address == 0x0000 && size == 2 &&
+ InBackspaceChar ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // There's a bug in FldDelete (pre-3.2) that accesses the word at 0x0000.
+
+ if (EmPatchState::HasFldDeleteBug () &&
+ address == 0x0000 && size == 2 &&
+ ::InFldDelete ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // There's a bug in GrfProcessStroke (pre-3.1) that accesses the word at 0x0002.
+
+ if (EmPatchState::HasGrfProcessStrokeBug () &&
+ address == 0x0002 && size == 2 &&
+ ::InGrfProcessStroke ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // There's a bug in NetPrvTaskMain (pre-3.2) that accesses low-memory.
+
+ if (EmPatchState::HasNetPrvTaskMainBug () &&
+ ::InNetPrvTaskMain ())
+ {
+ return Errors::kOKAccess;
+ }
+ }
+
+ // 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.
+
+ if (EmPatchState::HasSysBinarySearchBug () &&
+ EmPatchState::IsInSysBinarySearch ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // The Certicom Encryption library snags 20 bytes of data from some
+ // unspecified place in RAM to help randomize its keys. Allow this
+ // access. (Note: the test for the function that performs the access
+ // is fragile. An alternative may be to allow full-memory access
+ // while SecLibEncryptBegin is active, which appears to be the only
+ // place where the Certicom function is called from.
+
+ if (::In_CerticomMemCpy ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // dns_decode_name appears to walk off the end of an input buffer.
+ // I'm not sure why that happens, yet, but let's allow it for now.
+
+ if (::Indns_decode_name () &&
+ whatHappened == Errors::kMemMgrAccess)
+ {
+ return Errors::kOKAccess;
+ }
+ }
+
+ if (whatHappened == Errors::kLowMemAccess)
+ {
+ // Visor replaces the exception vector at 0x0008;
+ // allow for that.
+
+ if (size == 4 && address == 0x0008 && (::InHsPrvInit () || ::InHsPrvInitCard ()))
+ {
+ return Errors::kOKAccess;
+ }
+ }
+
+ if (whatHappened == Errors::kGlobalVarAccess)
+ {
+ // Let TSM glue routines (linked with applications) access
+ // the TSM global vars.
+
+
+ if ((address == EmLowMem_AddressOf (tsmFepLibStatusP) ||
+ address == EmLowMem_AddressOf (tsmFepLibRefNum)) &&
+ ::InTsmGlueGetFepGlobals ())
+ {
+ return Errors::kOKAccess;
+ }
+
+ // Let locale modules access the Intl Mgr global pointer.
+
+ if ((address == EmLowMem_AddressOf (intlMgrGlobalsP)) &&
+ (::InPrvGetIntlMgrGlobalsP() ||
+ ::InPrvSetIntlMgrGlobalsP()))
+ {
+ return Errors::kOKAccess;
+ }
+
+ // Always allow access to this for our Test Harness.
+
+ if (address == EmLowMem_AddressOf (testHarnessGlobalsP))
+ {
+ return Errors::kOKAccess;
+ }
+ }
+
+ return whatHappened;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetLowMemoryBegin
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetLowMemoryBegin (void)
+{
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetLowMemoryEnd
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetLowMemoryEnd (void)
+{
+ return offsetof (LowMemHdrType, globals);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetSysGlobalsBegin
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetSysGlobalsBegin (void)
+{
+ return offsetof (LowMemHdrType, globals);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetSysGlobalsEnd
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetSysGlobalsEnd (void)
+{
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ return EmLowMem_GetGlobal (sysDispatchTableP) +
+ EmLowMem_GetGlobal (sysDispatchTableSize) * (sizeof (void*));
+}
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetHeapHdrBegin
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetHeapHdrBegin (UInt16 heapID)
+{
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByID (heapID);
+ if (!heap)
+ return EmMemNULL;
+
+ return heap->HeaderStart ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GetHeapHdrEnd
+// ---------------------------------------------------------------------------
+
+emuptr MetaMemory::GetHeapHdrEnd (UInt16 heapID)
+{
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByID (heapID);
+ if (!heap)
+ return EmMemNULL;
+
+ return heap->HeaderEnd ();
+}
+
+
+Bool MetaMemory::IsLowMemory (emuptr testAddress, uint32 size)
+{
+ return testAddress >= GetLowMemoryBegin () && testAddress + size <= GetLowMemoryEnd ();
+}
+
+
+Bool MetaMemory::IsSystemGlobal (emuptr testAddress, uint32 size)
+{
+ return testAddress >= GetSysGlobalsBegin () && testAddress + size <= GetSysGlobalsEnd ();
+}
+
+
+Bool MetaMemory::IsScreenBuffer (emuptr testAddress, uint32 size)
+{
+ return IsScreenBuffer (EmMemGetMetaAddress (testAddress), size);
+}
+
+
+Bool MetaMemory::IsMemMgrData (emuptr testAddress, uint32 size)
+{
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (testAddress);
+
+ if (heap)
+ {
+ ITERATE_CHUNKS (*heap, iter, end)
+ {
+ if ((iter->HeaderContains (testAddress) &&
+ iter->HeaderContains (testAddress + size)) ||
+ (iter->TrailerContains (testAddress) &&
+ iter->TrailerContains (testAddress + size)))
+ {
+ return true;
+ }
+
+ ++iter;
+ }
+ }
+
+ return false;
+}
+
+
+Bool MetaMemory::IsUnlockedChunk (emuptr testAddress, uint32 size)
+{
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (testAddress);
+
+ if (heap)
+ {
+ ITERATE_CHUNKS (*heap, iter, end)
+ {
+ if (iter->BodyContains (testAddress) &&
+ iter->BodyContains (testAddress + size) &&
+ iter->LockCount () == 0)
+ {
+ return true;
+ }
+
+ ++iter;
+ }
+ }
+
+ return false;
+}
+
+
+Bool MetaMemory::IsFreeChunk (emuptr testAddress, uint32 size)
+{
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (testAddress);
+
+ if (heap)
+ {
+ ITERATE_CHUNKS (*heap, iter, end)
+ {
+ if (iter->BodyContains (testAddress) &&
+ iter->BodyContains (testAddress + size) &&
+ iter->Free () == 0)
+ {
+ return true;
+ }
+
+ ++iter;
+ }
+ }
+
+ return false;
+}
+
+
+Bool MetaMemory::IsUninitialized (emuptr testAddress, uint32 size)
+{
+#if FOR_LATER
+ return (fgMetaMemory [MASK(testAddress)] & kUninitialized) != 0;
+#else
+ UNUSED_PARAM(testAddress)
+ UNUSED_PARAM(size)
+
+ return false;
+#endif
+}
+
+
+Bool MetaMemory::IsStack (emuptr testAddress, uint32 size)
+{
+ UNUSED_PARAM(testAddress)
+ UNUSED_PARAM(size)
+
+ return false;
+}
+
+
+Bool MetaMemory::IsLowStack (emuptr testAddress, uint32 size)
+{
+ UNUSED_PARAM(testAddress)
+ UNUSED_PARAM(size)
+
+ return false;
+}
+
+
+Bool MetaMemory::IsAllocatedChunk (emuptr testAddress, uint32 size)
+{
+ return !IsFreeChunk (testAddress, size);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkRange
+// ---------------------------------------------------------------------------
+
+void MetaMemory::MarkRange (emuptr start, emuptr end, uint8 v)
+{
+ // If there's no meta-memory (not needed for dedicated framebuffers)
+ // just leave.
+
+ if (EmMemGetBank(start).xlatemetaaddr == NULL)
+ return;
+
+ // If the beginning and end of the buffer are not in the same address
+ // space, just leave. This can happen while initializing the Dragonball's
+ // LCD -- for a while, the LCD framebuffer range falls off the end
+ // of the dynamic heap.
+
+ if (start >= 0 && start < 0 + gRAMBank_Size
+ && end >= 0 + gRAMBank_Size)
+ {
+ end = gRAMBank_Size - 1;
+ }
+
+ if (start >= gMemoryStart && start < gMemoryStart + gRAMBank_Size
+ && end >= gMemoryStart + gRAMBank_Size)
+ {
+ end = gMemoryStart + gRAMBank_Size - 1;
+ }
+
+ uint8* startP = EmMemGetMetaAddress (start);
+ uint8* endP = startP + (end - start); // EmMemGetMetaAddress (end);
+ uint8* end4P = (uint8*) (((uint32) endP) & ~3);
+ uint8* p = startP;
+
+ EmAssert (end >= start);
+ EmAssert (endP >= startP);
+ EmAssert (endP - startP == (ptrdiff_t) (end - start));
+
+#if 1
+ // Optimization: if there are no middle longs to fill, just
+ // do everything a byte at a time.
+
+ if (end - start < 12)
+ {
+ while (p < endP)
+ {
+ *p++ &= v;
+ }
+ }
+ else
+ {
+ uint32 longValue = v;
+ longValue |= (longValue << 8);
+ longValue |= (longValue << 16);
+
+ while (((uint32) p) & 3) // while there are leading bytes
+ {
+ *p++ |= v;
+ }
+
+ while (p < end4P) // while there are middle longs
+ {
+ *(uint32*) p |= longValue;
+ p += sizeof (uint32);
+ }
+
+ while (p < endP) // while there are trailing bytes
+ {
+ *p++ |= v;
+ }
+ }
+#else
+ for (p = startP; p < endP; ++p)
+ {
+ *p |= v;
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkRange
+// ---------------------------------------------------------------------------
+
+void MetaMemory::UnmarkRange (emuptr start, emuptr end, uint8 v)
+{
+ // If there's no meta-memory (not needed for dedicated framebuffers)
+ // just leave.
+
+ if (EmMemGetBank(start).xlatemetaaddr == NULL)
+ return;
+
+ // If the beginning and end of the buffer are not in the same address
+ // space, just leave. This can happen while initializing the Dragonball's
+ // LCD -- for a while, the LCD framebuffer range falls off the end
+ // of the dynamic heap.
+
+ if (start >= 0 && start < 0 + gRAMBank_Size
+ && end >= 0 + gRAMBank_Size)
+ {
+ end = gRAMBank_Size - 1;
+ }
+
+ if (start >= gMemoryStart && start < gMemoryStart + gRAMBank_Size
+ && end >= gMemoryStart + gRAMBank_Size)
+ {
+ end = gMemoryStart + gRAMBank_Size - 1;
+ }
+
+ uint8* startP = EmMemGetMetaAddress (start);
+ uint8* endP = startP + (end - start); // EmMemGetMetaAddress (end);
+ uint8* end4P = (uint8*) (((uint32) endP) & ~3);
+ uint8* p = startP;
+
+ EmAssert (end >= start);
+ EmAssert (endP >= startP);
+ EmAssert (endP - startP == (ptrdiff_t) (end - start));
+
+ v = ~v;
+
+#if 1
+ // Optimization: if there are no middle longs to fill, just
+ // do everything a byte at a time.
+
+ if (end - start < 12)
+ {
+ while (p < endP)
+ {
+ *p++ &= v;
+ }
+ }
+ else
+ {
+ uint32 longValue = v;
+ longValue |= (longValue << 8);
+ longValue |= (longValue << 16);
+
+ while (((uint32) p) & 3) // while there are leading bytes
+ {
+ *p++ &= v;
+ }
+
+ while (p < end4P) // while there are middle longs
+ {
+ *(uint32*) p &= longValue;
+ p += sizeof (uint32);
+ }
+
+ while (p < endP) // while there are trailing bytes
+ {
+ *p++ &= v;
+ }
+ }
+#else
+ for (p = startP; p < endP; ++p)
+ {
+ *p &= v;
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkUnmarkRange
+// ---------------------------------------------------------------------------
+
+void MetaMemory::MarkUnmarkRange (emuptr start, emuptr end,
+ uint8 andValue, uint8 orValue)
+{
+ // If there's no meta-memory (not needed for dedicated framebuffers)
+ // just leave.
+
+ if (EmMemGetBank(start).xlatemetaaddr == NULL)
+ return;
+
+ // If the beginning and end of the buffer are not in the same address
+ // space, just leave. This can happen while initializing the Dragonball's
+ // LCD -- for a while, the LCD framebuffer range falls off the end
+ // of the dynamic heap.
+
+ if (start >= 0 && start < 0 + gRAMBank_Size
+ && end >= 0 + gRAMBank_Size)
+ {
+ end = gRAMBank_Size - 1;
+ }
+
+ if (start >= gMemoryStart && start < gMemoryStart + gRAMBank_Size
+ && end >= gMemoryStart + gRAMBank_Size)
+ {
+ end = gMemoryStart + gRAMBank_Size - 1;
+ }
+
+ uint8* startP = EmMemGetMetaAddress (start);
+ uint8* endP = startP + (end - start); // EmMemGetMetaAddress (end);
+ uint8* end4P = (uint8*) (((uint32) endP) & ~3);
+ uint8* p = startP;
+
+ EmAssert (end >= start);
+ EmAssert (endP >= startP);
+ EmAssert (endP - startP == (ptrdiff_t) (end - start));
+
+ if (andValue == 0xFF)
+ {
+ while (p < endP)
+ {
+ *p++ |= orValue;
+ }
+ }
+ else if (orValue == 0x00)
+ {
+ while (p < endP)
+ {
+ *p++ &= andValue;
+ }
+ }
+ else
+ {
+#if 1
+ // Optimization: if there are no middle longs to fill, just
+ // do everything a byte at a time.
+
+ if (end - start < 12)
+ {
+ while (p < endP) // while there are trailing bytes
+ {
+ *p = (*p & andValue) | orValue;
+ p += sizeof (char);
+ }
+ }
+ else
+ {
+ uint32 longAnd = andValue;
+ longAnd |= (longAnd << 8);
+ longAnd |= (longAnd << 16);
+
+ uint32 longOr = orValue;
+ longOr |= (longOr << 8);
+ longOr |= (longOr << 16);
+
+ while (((uint32) p) & 3) // while there are leading bytes
+ {
+ *p = (*p & andValue) | orValue;
+ p += sizeof (char);
+ }
+
+ while (p < end4P) // while there are middle longs
+ {
+ *(uint32*) p = ((*(uint32*) p) & longAnd) | longOr;
+ p += sizeof (long);
+ }
+
+ while (p < endP) // while there are trailing bytes
+ {
+ *p = (*p & andValue) | orValue;
+ p += sizeof (char);
+ }
+ }
+#else
+ for (p = startP; p < endP; ++p)
+ {
+ *p = (*p & andValue) | orValue;
+ }
+#endif
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::WhatHappenedCallback
+// ---------------------------------------------------------------------------
+// Check to see if there was an access to memory manager data, an unlocked
+// block, or a free block.
+
+void MetaMemory::GWH_ExamineHeap ( const EmPalmHeap& heap,
+ WhatHappenedData& info)
+{
+ // Bail out if the address to test is not even in this heap.
+
+ if (!heap.Contains (info.address))
+ {
+ return;
+ }
+
+ // See if we touched a memory manager structure.
+ // Let's start with the headers.
+
+ // Is it in the heap header?
+
+ if (heap.HeaderContains (info.address))
+ {
+ info.result = Errors::kMemMgrAccess;
+ return;
+ }
+
+ // Is it in any of the master pointer tables?
+
+ {
+ ITERATE_MPTS(heap, iter, end)
+ {
+ if (iter->Contains (info.address))
+ {
+ info.result = Errors::kMemMgrAccess;
+ return;
+ }
+
+ ++iter;
+ }
+ }
+
+ // Check against all of the memory manager chunks.
+
+ {
+ ITERATE_CHUNKS (heap, iter, end)
+ {
+ GWH_ExamineChunk (*iter, info);
+ if (info.result != Errors::kUnknownAccess)
+ return;
+
+ ++iter;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::GWH_ExamineChunk
+// ---------------------------------------------------------------------------
+// Check to see if there was an access to memory manager data, an unlocked
+// block, or a free block.
+
+void MetaMemory::GWH_ExamineChunk ( const EmPalmChunk& chunk,
+ WhatHappenedData& info)
+{
+ emuptr addrStart = info.address;
+ emuptr addrEnd = info.address + info.size;
+
+ // Sort out some ranges we'll be comparing against.
+
+ emuptr hdrStart = chunk.HeaderStart ();
+ emuptr bodyStart = chunk.BodyStart ();
+ emuptr trlStart = chunk.BodyEnd ();
+ emuptr chunkEnd = chunk.End ();
+
+ /*
+ A note on the comparison below (I had to draw this on the whiteboard
+ before I could figure it out). I need to see if one range of memory
+ (the test address, extending for 1, 2, or 4 byte) overlaps another
+ range of memory (the chunk header, the chunk body, etc.). I started
+ by drawing the second range as follows:
+
+ +---------+---------+---------+
+ | A | B | C |
+ +---------+---------+---------+
+
+ "B" is the range I'm interested in testing against, "A" is everything
+ before it, and "C" is everything after it.
+
+ The range of memory I want to test to see if it overlaps can be thought
+ of as starting in region A, B, or C, and ending in A, B, or C. We can
+ identify all possible ranges by labelling each range "xy", where x is
+ the starting section and y is the ending section. Thus, all the possible
+ ranges are AA, AB, AC, BB, BC, and CC. From inspection, we can see that
+ only segments AA and CC don't overlap B in any way. Looking at it
+ another way, any segment ending in A or starting in C will not overlap
+ B. All other ranges will.
+ */
+
+ // See if we hit this chunk at all. If not, leave.
+
+ if (addrEnd > hdrStart && addrStart < chunkEnd)
+ {
+ // See if the access was to the body of the block.
+
+ if (addrEnd > bodyStart && addrStart < trlStart)
+ {
+ // See if this is a free (unallocated) block.
+
+ if (chunk.Free ())
+ {
+ info.result = Errors::kFreeChunkAccess;
+ }
+
+ // See if this is an unlocked block.
+
+ else if (chunk.LockCount () == 0)
+ {
+ info.result = Errors::kUnlockedChunkAccess;
+ }
+ }
+
+ // See if the access was to the chunk header.
+
+ if (addrEnd > hdrStart && addrStart < bodyStart)
+ {
+ info.result = Errors::kMemMgrAccess;
+ }
+
+ // See if the access was to the chunk trailer.
+
+ if (addrEnd > trlStart && addrStart < chunkEnd)
+ {
+ info.result = Errors::kMemMgrAccess;
+ }
+
+
+ // ============================== ALLOW FOR BUGS ==============================
+
+ // Allow the screen driver some liberty. Some BitBlt functions get a running
+ // start or come to a skidding halt before or after an allocated chunk. They
+ // read these two bytes, but the logic is such that those bits get masked out
+ // or shifted away.
+
+ if (info.result == Errors::kMemMgrAccess &&
+ info.forRead &&
+ // info.size == sizeof (UInt16) && // Can be 1-byte access in cases
+ (::InPrvCompressedInnerBitBlt () ||
+ ::InPrvMisAlignedForwardInnerBitBlt () ||
+ ::InPrvMisAlignedBackwardInnerBitBlt ()))
+ {
+ goto HideBug;
+ }
+
+
+ if (EmPatchState::HasConvertDepth1To2BWBug () &&
+ info.result == Errors::kMemMgrAccess &&
+ info.forRead &&
+ info.size == sizeof (UInt8) &&
+ ::InPrvConvertDepth1To2BW ())
+ {
+ goto HideBug;
+ }
+
+
+ // Similarly, allow NetLibBitMove some liberty. It will occassionally
+ // scoot off the end of the source buffer, but making sure that it
+ // masks off the data that it reads.
+
+ if (info.result == Errors::kMemMgrAccess &&
+ info.forRead &&
+ info.size == sizeof (UInt8) &&
+ ::InNetLibBitMove ())
+ {
+ goto HideBug;
+ }
+
+
+ // There's a bug in MenuHandleEvent (pre-3.1 only) that causes it to read a
+ // random long (actually, the random location is the result of using a -1 to index
+ // into a menu array).
+
+ if (EmPatchState::HasMenuHandleEventBug () &&
+ info.forRead &&
+ info.size == sizeof (WinHandle) && // MenuPullDownType.menuWin
+ ::InMenuHandleEvent ())
+ {
+ goto HideBug;
+ }
+
+
+ // There's a bug in NetPrvSettingSet that causes it to read 0x020C bytes
+ // from the beginning of its globals buffer when that buffer is only 8 bytes long.
+
+ if (EmPatchState::HasNetPrvSettingSetBug () &&
+ info.forRead &&
+ info.size == 4 &&
+ ::InNetPrvSettingSet ())
+ {
+ goto HideBug;
+ }
+
+
+ // SysAppExit deletes the block of memory containing the current task's stack
+ // and TCB before the task has been deleted. When SysTaskDelete is called,
+ // there are many accesses to both the stack (as functions are called) and
+ // the TCB (as tasks are scheduled and as the task to be deleted is finally
+ // deleted).
+ //
+ // We need to detect when any of these SysTaskDelete accesses occurs and
+ // allow them. One hueristic that gets most of them is to see if there
+ // are any TCBs with a pointer into the deleted memory chunk. That will
+ // work up until the point the TCB is marked as deleted. This marking
+ // occurs in the AMX function cj_kptkdelete. At that point, we can just
+ // check to see if the access occurred in that function and allow it.
+
+ if (info.result == Errors::kFreeChunkAccess &&
+ EmPatchState::HasDeletedStackBug ())
+ {
+ // First see if there is an active TCB with a stack pointer
+ // pointing into this deleted memory chunk.
+
+ SysKernelInfoType taskInfo;
+
+ taskInfo.selector = sysKernelInfoSelTaskInfo;
+ taskInfo.id = 0; // Ask for the first task
+
+ // Get the first task. Remember the task IDs so that we can
+ // detect when we've looped through them all. Remembering *all*
+ // the IDs (instead of just the first one) is necessary in case
+ // we're called with the linked list of TCBs is inconsistent
+ // (that is, it's in the process of being updated -- when that's
+ // happening, we may find a loop that doesn't necessarily involve
+ // the first TCB).
+
+ vector<UInt32> taskIDList;
+ Err err = SysKernelInfo (&taskInfo);
+
+ while (err == 0)
+ {
+ // See if we've seen this task ID before. If so, leave.
+
+ vector<UInt32>::iterator iter = taskIDList.begin ();
+ while (iter != taskIDList.end ())
+ {
+ if (*iter++ == taskInfo.param.task.id)
+ {
+ goto PlanB; // I'd really like a break(2) here... :-)
+ }
+ }
+
+ // We haven't looked at this task before; check the stack.
+ // Check against "stackStart" instead of stackP, as the
+ // latter sometimes contains values outside of the current
+ // stack range (such as the faux stacks we set up when
+ // doing ATrap calls).
+
+ if (taskInfo.param.task.stackStart >= bodyStart &&
+ taskInfo.param.task.stackStart < trlStart)
+ {
+ goto HideBug;
+ }
+
+ // Save this task ID so we can see if we've visited this
+ // record before.
+
+ taskIDList.push_back (taskInfo.param.task.id);
+
+ // Get the next TCB.
+
+ taskInfo.selector = sysKernelInfoSelTaskInfo;
+ taskInfo.id = taskInfo.param.task.nextID;
+ err = SysKernelInfo (&taskInfo);
+ }
+
+ // Plan B...
+PlanB:
+ // If there is no TCB pointing into the deleted chunk, see if the current
+ // function is cj_kptkdelete. If not, see if it looks like we're in a
+ // function called by cj_kptkdelete.
+
+ if ( gCPU->GetSP () >= bodyStart &&
+ gCPU->GetSP () < trlStart)
+ {
+ // See if we're currently in cj_kptkdelete.
+
+ if (::Incj_kptkdelete ())
+ {
+ info.result = Errors::kOKAccess;
+ }
+
+ // If not, see if it's in the current call chain. Normally (!)
+ // I'd walk the a6 stack frame links, but there's a lot of
+ // assembly stuff going on here, and not all of them set up
+ // stack frames. a6 *should* point to a valid stack frame
+ // somewhere up the line, but it may be cj_kptkdelete's
+ // stack frame, resulting in our skipping over it.
+ //
+ // It's important that gcj_kptkdelete.InRange() has returned
+ // true at least once before entering this section of code.
+ // That's because if it hasn't, the cached range of the
+ // function will be empty, causing InRange to look for the
+ // beginning and ending of the function containing the address
+ // passed to it. Since we're passing random contents of the
+ // stack, it's very unlikely that there is a function range
+ // corresponding to the values passed to InRange, sending it
+ // on wild goose chases. Fortunately, "Plan B" goes into effect
+ // only after the TCB has been marked as deleted, which occurs
+ // in cj_kptkdelete. The very next thing cj_kptkdelete does is
+ // push a parameter on the stack, causing us to get here while
+ // the PC is in cj_kptkdelete. This will cause the call to InRange
+ // immediately above to return true, satisfying the precondition
+ // we need here.
+
+ else
+ {
+ // Get the current stack pointer and use it to iterate
+ // over the contents of the stack. We examine every
+ // longword on every even boundary to see if it looks
+ // like a return address into cj_kptkdelete.
+
+ emuptr a7 = gCPU->GetSP ();
+
+ while (a7 >= bodyStart && a7 < trlStart)
+ {
+ if (::Incj_kptkdelete (EmMemGet32 (a7)))
+ {
+ goto HideBug;
+ }
+
+ a7 += 2;
+ }
+ } // end: checking the stack for cj_kptkdelete
+ } // end: A7 is in the deleted chunk
+ } // end: accessed a deleted chunk
+
+
+ // There's a bug in FindShowResults (pre-3.0) that accesses
+ // a byte in an unlocked block.
+
+ if (info.result == Errors::kUnlockedChunkAccess &&
+ EmPatchState::HasFindShowResultsBug () &&
+ info.forRead &&
+ info.size == sizeof (Boolean) &&
+ addrStart == bodyStart + sizeof (UInt16) * 2 /*offsetof (FindParamsType, more)*/ &&
+ ::InFindShowResults ())
+ {
+ goto HideBug;
+ }
+
+
+ // There's a bug in FindSaveFindStr that causes it to possibly read
+ // off the end of the source handle. The invalid access will be
+ // generated in MemMove, which is called by DmWrite, which is called
+ // by FindSaveFindStr. So look up the stack a bit to see who's calling us.
+
+ emuptr a6_0 = gCPU68K->GetRegister (e68KRegID_A6); // MemMove's A6 (points to caller's A6 and return address to caller)
+ if (::IsEven (a6_0) && EmPalmOS::IsInStack (a6_0))
+ {
+ emuptr a6_1 = EmMemGet32 (a6_0); // DmWrite's (points to caller's A6 and return address to caller)
+
+ if (EmPatchState::HasFindSaveFindStrBug () &&
+ info.forRead &&
+ ::InMemMove () && // See if we're in MemMove
+ ::InDmWrite (EmMemGet32 (a6_0 + 4)) && // See if DmWrite is MemMove's caller
+ ::InFindSaveFindStr (EmMemGet32 (a6_1 + 4))) // See if FindSaveFindStr is DmWrite's caller
+ {
+ goto HideBug;
+ }
+ }
+
+ // There's a bug in FntDefineFont that causes it to possibly read
+ // off the end of the source handle. The invalid access will be
+ // generated in MemMove, which is called by FntDefineFont. So look
+ // up the stack a bit to see who's calling us.
+
+ if (EmPatchState::HasFntDefineFontBug () &&
+ info.forRead &&
+ ::InMemMove () && // See if we're in MemMove
+ ::InFntDefineFont (EmMemGet32 (a6_0 + 4))) // See if FntDefineFont is MemMove's caller
+ {
+ goto HideBug;
+ }
+ }
+
+ return;
+
+HideBug:
+ info.result = Errors::kOKAccess;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ CheckUIObjectAccess
+// ---------------------------------------------------------------------------
+
+#define WindowFlagsType_format 0x8000 // window format: 0=screen mode; 1=generic mode
+#define WindowFlagsType_offscreen 0x4000 // offscreen flag: 0=onscreen ; 1=offscreen
+#define WindowFlagsType_modal 0x2000 // modal flag: 0=modeless window; 1=modal window
+#define WindowFlagsType_focusable 0x1000 // focusable flag: 0=non-focusable; 1=focusable
+#define WindowFlagsType_enabled 0x0800 // enabled flag: 0=disabled; 1=enabled
+#define WindowFlagsType_visible 0x0400 // visible flag: 0-invisible; 1=visible
+#define WindowFlagsType_dialog 0x0200 // dialog flag: 0=non-dialog; 1=dialog
+#define WindowFlagsType_freeBitmap 0x0100 // free bitmap w/window: 0=don't free, 1=free
+
+#define FormAttrType_usable 0x8000 // Set if part of ui
+#define FormAttrType_enabled 0x4000 // Set if interactable (not grayed out)
+#define FormAttrType_visible 0x2000 // Set if drawn, used internally
+#define FormAttrType_dirty 0x1000 // Set if dialog has been modified
+#define FormAttrType_saveBehind 0x0800 // Set if bits behind form are save when form ids drawn
+#define FormAttrType_graffitiShift 0x0400 // Set if graffiti shift indicator is supported
+#define FormAttrType_globalsAvailable 0x0200 // Set by Palm OS if globals are available for the form event handler
+#define FormAttrType_doingDialog 0x0100 // FrmDoDialog is using for nested event loop
+#define FormAttrType_exitDialog 0x0080 // tells FrmDoDialog to bail out and stop using this form
+
+#define ControlAttrType_usable 0x8000 // set if part of ui
+#define ControlAttrType_enabled 0x4000 // set if interactable (not grayed out)
+#define ControlAttrType_visible 0x2000 // set if drawn (set internally)
+#define ControlAttrType_on 0x1000 // set if on (checked)
+#define ControlAttrType_leftAnchor 0x0800 // set if bounds expand to the right, clear if bounds expand to the left
+#define ControlAttrType_frame 0x0700
+#define ControlAttrType_drawnAsSelected 0x0080 // support for old-style graphic controls where control overlaps a bitmap
+#define ControlAttrType_graphical 0x0040 // set if images are used instead of text
+#define ControlAttrType_vertical 0x0020 // true for vertical sliders
+
+// Here are some symbols to search for when looking for more things
+// to which to prohibit access:
+//
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_CLIPBOARDS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_CONTROLS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_FIELDS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_FINDPARAMS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_FORMS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_LISTS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_MENUS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_PROGRESS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_SCROLLBARS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_TABLES
+//
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_BITMAPS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_FONTS
+// #define ALLOW_ACCESS_TO_INTERNALS_OF_WINDOWS
+
+/*
+ AccessorGlueTrapsAvailable TRUE if sysFtrNumROMVersion indicates 4.0 or later
+ AccessorGlueEmu68KAccAvail TRUE if sysFtrNumAccessorTrapPresent feature exists and is non-zero
+
+ The following functions access the following fields directly, as of
+ SDK 4.0 Update 1 (DR1):
+
+ Glue function Field accessed Under this condition
+ --------------------------- --------------------------- --------------------
+ TblGlueGetNumberOfColumns tableP->numColumns !AccessorGlueTrapsAvailable
+
+ TblGlueGetTopRow tableP->topRow !AccessorGlueTrapsAvailable
+
+ TblGlueSetSelection tableP->numColumns !AccessorGlueTrapsAvailable
+ tableP->numRows
+ tableP->attr.visible
+ tableP->rowAttrs
+ tableP->attr.selected
+ tableP->currentRow
+ tableP->currentColumn
+
+ TblGlueGetColumnMasked tableP->numColumns !AccessorGlueEmu68KAccAvail
+ tableP->columnAttrs
+
+ BmpGlueGetDimensions bitmapP->width !AccessorGlueTrapsAvailable
+ bitmapP->height
+ bitmapP->rowBytes
+
+ BmpGlueGetBitDepth bitmapP->version !AccessorGlueTrapsAvailable
+ bitmapP->pixelSize
+
+ BmpGlueGetNextBitmap bitmapP->version !AccessorGlueTrapsAvailable
+ bitmapP->nextDepthOffset
+
+ BmpGlueGetTransparentValue bitmapP->version !AccessorGlueEmu68KAccAvail
+ bitmapP->flags.hasTransparency
+ ((BitmapTypeV2*)bitmapP)->transparentValue
+ bitmapP->transparentIndex
+
+ BmpGlueSetTransparentValue bitmapP->flags.forScreen !AccessorGlueEmu68KAccAvail
+ bitmapP->version
+ bitmapP->pixelSize
+ bitmapP->transparentIndex
+ bitmapP->flags.hasTransparency
+
+ BmpGlueGetCompressionType bitmapP->flags.compressed !AccessorGlueEmu68KAccAvail
+ bitmapP->version
+ bitmapP->compressionType
+
+ CtlGlueGetControlStyle ctlP->style !AccessorGlueEmu68KAccAvail
+
+ CtlGlueGetFont ctlP->font !AccessorGlueEmu68KAccAvail
+
+ CtlGlueSetFont ctlP->font !AccessorGlueEmu68KAccAvail
+
+ CtlGlueGetGraphics ctlP->attr.graphical !AccessorGlueEmu68KAccAvail
+ gctlP->bitmapID
+ gctlP->selectedBitmapID
+
+ CtlGlueNewSliderControl sctlP->attr.graphical !AccessorGlueEmu68KAccAvail
+
+ CtlGlueSetLeftAnchor ctlP->attr.leftAnchor !AccessorGlueEmu68KAccAvail
+
+ FldGlueGetLineInfo fldP->lines !AccessorGlueEmu68KAccAvail
+
+ FrmGlueGetObjectUsable obj.control->attr.usable !AccessorGlueEmu68KAccAvail
+ obj.list->attr.usable
+ obj.bitmap->attr.usable
+ obj.label->attr.usable
+ obj.gadget->attr.usable
+ obj.scrollBar->attr.usable
+ obj.table->attr.usable AccessorGlueTrapsAvailable
+
+ FrmGlueGetLabelFont formLabelP->fontID !AccessorGlueEmu68KAccAvail
+
+ FrmGlueSetLabelFont formLabelP->fontID !AccessorGlueEmu68KAccAvail
+
+ FrmGlueGetDefaultButtonID formP->defaultButton !AccessorGlueEmu68KAccAvail
+
+ FrmGlueSetDefaultButtonID formP->defaultButton !AccessorGlueEmu68KAccAvail
+
+ FrmGlueGetHelpID formP->helpRscId !AccessorGlueEmu68KAccAvail
+
+ FrmGlueSetHelpID formP->helpRscId !AccessorGlueEmu68KAccAvail
+
+ FrmGlueGetMenuBarID formP->menuRscId !AccessorGlueEmu68KAccAvail
+
+ FrmGlueGetEventHandler formP->handler !AccessorGlueEmu68KAccAvail
+
+ LstGlueGetFont listP->font !AccessorGlueEmu68KAccAvail
+
+ LstGlueGetTopItem listP->topItem !AccessorGlueTrapsAvailable
+
+ LstGlueSetFont listP->font !AccessorGlueEmu68KAccAvail
+
+ LstGlueGetItemsText listP->itemsText !AccessorGlueEmu68KAccAvail
+
+ LstGlueSetIncrementalSearch listP->attr.search !AccessorGlueEmu68KAccAvail
+
+ WinGlueGetFrameType winP->frameType.word !AccessorGlueEmu68KAccAvail
+
+ WinGlueSetFrameType winP->frameType.word !AccessorGlueEmu68KAccAvail
+*/
+// ---------------------------------------------------------------------------
+// ¥ PrvTrapsAvailable
+// ---------------------------------------------------------------------------
+
+static Bool PrvTrapsAvailable (void)
+{
+ // If the OS is 4.0 or later, the API should be used.
+
+ Bool result = EmPatchState::OSMajorVersion () >= 4;
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAccessorTrapAvailable
+// ---------------------------------------------------------------------------
+
+static Bool PrvAccessorTrapAvailable (void)
+{
+ // Magic Accessor Trap is available. Defined but not implemented
+ // in 4.0, but magically implemented in the Timulator.
+
+ #ifndef sysFtrNumAccessorTrapPresent
+ #define sysFtrNumAccessorTrapPresent 25 // If accessor trap exists (PalmOS 4.0)
+ #endif
+
+ UInt32 value;
+ Bool result = (FtrGet (sysFtrCreator, sysFtrNumAccessorTrapPresent, &value) == errNone) && (value != 0);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFieldObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFieldObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ FieldType
+ UInt16 id; // FrmGetObjectId
+ RectangleType rect; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition, FldGetBounds, FldSetBounds
+ FieldAttrType attr; // FldGetAttributes, FldSetAttributes
+ usable // FrmShowObject, FrmHideObject, FldSetUsable
+ visible
+ editable
+ singleLine
+ hasFocus
+ dynamicSize
+ insPtVisible
+ dirty // FldSetDirty
+ underlined
+ justification
+ autoShift
+ hasScrollBar
+ numeric
+ Char* text; // FldGetTextPtr, FldSetTextPtr, FldSetText
+ MemHandle textHandle; // FldGetTextHandle, FldSetTextHandle, FldSetText
+ LineInfoPtr lines; // (FldGetScrollPosition, FldSetScrollPosition, FldGetTextHeight, FldGetVisibleLines)
+ UInt16 textLen; // FldGetTextLength, FldSetText
+ UInt16 textBlockSize; // FldGetTextAllocatedSize, FldSetTextAllocatedSize
+ UInt16 maxChars; // FldGetMaxChars, FldSetMaxChars
+ UInt16 selFirstPos; // FldGetSelection, FldSetSelection
+ UInt16 selLastPos; // FldGetSelection, FldSetSelection
+ UInt16 insPtXPos; // FldGetInsPtPosition, FldSetInsPtPosition, FldSetInsertionPoint
+ UInt16 insPtYPos; // FldGetInsPtPosition, FldSetInsPtPosition, FldSetInsertionPoint
+ FontID fontID; // FldGetFont, FldSetFont
+ UInt8 maxVisibleLines; // FldSetMaxVisibleLines
+ */
+
+ // Allow read access to "lines" if Emu68KAccessorTrapAvailable / AccFldGetLineInfo
+ // not available -- FldGlueGetLineInfo needs access to it.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t lines_offset = EmAliasFieldType<PAS>::offsetof_lines ();
+ const size_t lines_size = EmAliasemuptr<PAS>::GetSize ();
+
+ if (offset >= lines_offset && offset < lines_offset + lines_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow read/write access to "attr" before Palm OS 3.3. Catherine
+ // says there's a bug before those versions they need to workaround.
+
+// if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasFieldType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFieldAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ if (EmPatchState::OSMajorMinorVersion () < 33)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedControlObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedControlObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ ControlType
+ UInt16 id; // FrmGetObjectId
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ Char* text;
+ ControlAttrType attr;
+ usable // FrmShowObject, FrmHideObject, CtlSetUsable
+ enabled
+ visible
+ on // FrmGetControlValue, CtlGetValue, FrmSetControlValue, CtlSetValue
+ leftAnchor
+ frame
+ drawnAsSelected
+ graphical
+ vertical
+ reserved
+ ControlStyleType style;
+ FontID font;
+ UInt8 group; // FrmGetControlGroupSelection
+ UInt8 reserved;
+
+ GraphicControlType
+ UInt16 id; // FrmGetObjectId
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ DmResID bitmapID;
+ DmResID selectedBitmapID;
+ ControlAttrType attr;
+ ControlStyleType style;
+ FontID unused;
+ UInt8 group;
+ UInt8 reserved;
+
+ SliderControlType
+ UInt16 id; // FrmGetObjectId
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ DmResID thumbID;
+ DmResID backgroundID;
+ ControlAttrType attr;
+ ControlStyleType style;
+ UInt8 reserved;
+ Int16 minValue;
+ Int16 maxValue;
+ Int16 pageSize;
+ Int16 value; // FrmGetControlValue, CtlGetValue, FrmSetControlValue, CtlSetValue
+ MemPtr activeSliderP;
+ */
+
+ // Allow read access to "attr" and "style" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable and CtlGlueGetControlStyle need access to them.
+ //
+ // Allow read access to "attr.graphical", bitmapID, and selectedBitmapID fields
+ // for CtlGlueGetGraphics.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+
+ const size_t attr_offset = EmAliasControlType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasControlAttrType<PAS>::GetSize ();
+
+ const size_t style_offset= EmAliasControlType<PAS>::offsetof_style ();
+ const size_t style_size = EmAliasUInt8<PAS>::GetSize ();
+
+ if ((offset >= attr_offset && offset < attr_offset + attr_size) ||
+ (offset >= style_offset && offset < style_offset + style_size))
+ {
+ return true;
+ }
+
+ EmAliasGraphicControlType<PAS> control (objectP);
+ if (((Int16) control.attr.flags) & ControlAttrType_graphical)
+ {
+ const size_t bitmapID_offset = EmAliasGraphicControlType<PAS>::offsetof_bitmapID ();
+ const size_t bitmapID_size = EmAliasDmResID<PAS>::GetSize ();
+
+ const size_t selectedBitmapID_offset = EmAliasGraphicControlType<PAS>::offsetof_selectedBitmapID ();
+ const size_t selectedBitmapID_size = EmAliasDmResID<PAS>::GetSize ();
+
+ if ((offset >= bitmapID_offset && offset < bitmapID_offset + bitmapID_size) ||
+ (offset >= selectedBitmapID_offset && offset < selectedBitmapID_offset + selectedBitmapID_size))
+ {
+ return true;
+ }
+ }
+ }
+
+ // Allow read/write access to "font" field for CtlGlueGetFont / CtlGlueSetFont.
+ //
+ // Allow read/write access to "attr.graphical" and "attr.leftAnchor" fields
+ // for CtlGlueNewSliderControl and CtlGlueSetLeftAnchor.
+
+ {
+ size_t offset = address - objectP;
+
+ const size_t attr_offset = EmAliasControlType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasControlAttrType<PAS>::GetSize ();
+
+ const size_t font_offset = EmAliasControlType<PAS>::offsetof_font ();
+ const size_t font_size = EmAliasFontID<PAS>::GetSize ();
+
+ if ((offset >= attr_offset && offset < attr_offset + attr_size) ||
+ (offset >= font_offset && offset < font_offset + font_size))
+ {
+ return true;
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedListObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedListObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (forRead)
+
+ /*
+ ListType
+ UInt16 id; // FrmGetObjectId
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition, LstSetHeight, LstSetPosition
+ ListAttrType attr; // FrmShowObject, FrmHideObject
+ usable // FrmShowObject, FrmHideObject
+ enabled // (not used)
+ visible // LstDrawList, LstEraseList
+ poppedUp // LstPopupList
+ hasScrollBar // (Tested, but what sets it?)
+ search // (Tested, but what sets it?)
+ Char** itemsText; // LstGetSelectionText, LstSetListChoices
+ Int16 numItems; // LstGetNumberOfItems
+ Int16 currentItem; // LstGetSelection, LstSetSelection
+ Int16 topItem; // LstGetTopItem, LstSetTopItem
+ FontID font; // ?
+ UInt8 reserved; //
+ WinHandle popupWin; // (Used internally)
+ ListDrawDataFuncPtr drawItemsCallback; // LstSetDrawFunction
+ */
+
+ // Allow read access to "attr" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable needs access to it.
+
+ // Actually, always allow full read/write access to attr. LstGlueSetIncrementalSearch
+ // accesses it.
+
+// if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasListType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasListAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow read access to itemsText for LstGlueGetItemsText.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t itemsText_offset = EmAliasListType<PAS>::offsetof_itemsText ();
+ const size_t itemsText_size = EmAliasemuptr<PAS>::GetSize ();
+
+ if (offset >= itemsText_offset && offset < itemsText_offset + itemsText_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow read access to topItem before 4.0. In 4.0 and later, use LstGetTopItem.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t topItem_offset = EmAliasListType<PAS>::offsetof_topItem ();
+ const size_t topItem_size = EmAliasUInt16<PAS>::GetSize ();
+
+ if (offset >= topItem_offset && offset < topItem_offset + topItem_size)
+ {
+ if (!::PrvTrapsAvailable ())
+ {
+ return true;
+ }
+ }
+ }
+
+ // Allow read/write access to "font" field for LstGlueGetFont / LstGlueSetFont.
+
+ {
+ size_t offset = address - objectP;
+
+ const size_t font_offset = EmAliasListType<PAS>::offsetof_font ();
+ const size_t font_size = EmAliasFontID<PAS>::GetSize ();
+
+ if ((offset >= font_offset && offset < font_offset + font_size))
+ {
+ return true;
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedTableObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedTableObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ TableType
+ UInt16 id;
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition, TblGetBounds, TblSetBounds
+ TableAttrType attr;
+ visible // TblEraseTable
+ editable
+ editing // TblEditing, TblGrabFocus
+ selected // TblEraseTable
+ hasScrollBar // TblHasScrollBar(sets)
+ usable // FrmShowObject, FrmHideObject [Added later]
+ Int16 numColumns; // TblGetNumberOfColumns [4.0]
+ Int16 numRows; // TblGetNumberOfRows
+ Int16 currentRow; // TblGetSelection, TblSelectItem, TblGrabFocus, TblSetSelection [4.0]
+ Int16 currentColumn; // TblGetSelection, TblSelectItem, TblGrabFocus, TblSetSelection [4.0]
+ Int16 topRow; // TblGetTopRow [4.0]
+ TableColumnAttrType* columnAttrs; //
+ width; // TblGetColumnWidth, TblSetColumnWidth
+ reserved1 : 5;
+ masked : 1; // TblSetColumnMasked
+ editIndicator : 1; // TblSetColumnEditIndicator
+ usable : 1; // TblSetColumnUsable
+ reserved2 : 8;
+ spacing; // TblGetColumnSpacing, TblSetColumnSpacing
+ drawCallback; // TblSetCustomDrawProcedure
+ loadDataCallback; // TblSetLoadDataProcedure
+ saveDataCallback; // TblSetSaveDataProcedure
+ TableRowAttrType* rowAttrs; //
+ id; // TblFindRowID, TblGetRowID, TblSetRowID
+ height; // TblGetRowHeight, TblSetRowHeight
+ data; // TblFindRowData, TblGetRowData, TblSetRowData
+ reserved1 : 7;
+ usable : 1; // TblRowUsable, TblSetRowUsable
+ reserved2 : 4;
+ masked : 1; // TblRowMasked, TblSetRowMasked
+ invalid : 1; // TblRowInvalid, TblMarkRowInvalid, TblMarkTableInvalid
+ staticHeight : 1; // TblSetRowStaticHeight
+ selectable : 1; // TblRowSelectable, TblSetRowSelectable
+ reserved3;
+ TableItemPtr items; //
+ itemType; // TblSetItemStyle
+ fontID; // TblGetItemFont, TblSetItemFont
+ intValue; // TblGetItemInt, TblSetItemInt
+ ptr; // TblGetItemPtr, TblSetItemPtr
+ FieldType currentField; // TblGetCurrentField
+ */
+
+ // TblGlueGetNumberOfColumns
+ // Give read access to numColumns before 4.0
+
+ // TblGlueGetTopRow
+ // Give read access to topRow before 4.0
+
+ // TblGlueSetSelection
+ // Give read access to numColumns before 4.0
+ // Give read access to numRows before 4.0
+ // Give r/w access to attr
+ // * need r/w access to "selected" if !TrapsAvailable because of code in TblGlueSetSelection
+ // * need r/w access to "usable" if TrapsAvailable (actually, if Palm OS > 4.0 for now)
+ // Give read access to rowAttrs before 4.0
+ // Give r/w access to currentRow before 4.0
+ // Give r/w access to currentColumn before 4.0
+ //
+ // TblGlueGetColumnMasked
+ // Give read access to numColumns
+ // Give read access to columnAttrs
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t numRows_offset = EmAliasTableType<PAS>::offsetof_numRows ();
+ const size_t numRows_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t numColumns_offset = EmAliasTableType<PAS>::offsetof_numColumns ();
+ const size_t numColumns_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t topRow_offset = EmAliasTableType<PAS>::offsetof_topRow ();
+ const size_t topRow_size = EmAliasUInt16<PAS>::GetSize ();
+
+ if ((offset >= numRows_offset && offset < numRows_offset + numRows_size) ||
+ (offset >= numColumns_offset && offset < numColumns_offset + numColumns_size) ||
+ (offset >= topRow_offset && offset < topRow_offset + topRow_size))
+ {
+ if (!::PrvTrapsAvailable ())
+ {
+ return true;
+ }
+ }
+ }
+
+ // Allow read access to these fields so that applications can get
+ // to sub-fields that have no APIs.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+
+ const size_t items_offset = EmAliasTableType<PAS>::offsetof_items ();
+ const size_t items_size = EmAliasemuptr<PAS>::GetSize ();
+
+ const size_t numColumns_offset = EmAliasTableType<PAS>::offsetof_numColumns ();
+ const size_t numColumns_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t rowAttrs_offset = EmAliasTableType<PAS>::offsetof_rowAttrs ();
+ const size_t rowAttrs_size = EmAliasemuptr<PAS>::GetSize ();
+
+ const size_t columnAttrs_offset = EmAliasTableType<PAS>::offsetof_columnAttrs ();
+ const size_t columnAttrs_size = EmAliasemuptr<PAS>::GetSize ();
+
+ if ((offset >= items_offset && offset < items_offset + items_size) ||
+ (offset >= numColumns_offset && offset < numColumns_offset + numColumns_size) ||
+ (offset >= rowAttrs_offset && offset < rowAttrs_offset + rowAttrs_size) ||
+ (offset >= columnAttrs_offset && offset < columnAttrs_offset + columnAttrs_size))
+ {
+ return true;
+ }
+ }
+
+ {
+ size_t offset = address - objectP;
+
+ const size_t currentRow_offset = EmAliasTableType<PAS>::offsetof_currentRow ();
+ const size_t currentRow_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t currentColumn_offset= EmAliasTableType<PAS>::offsetof_currentColumn ();
+ const size_t currentColumn_size = EmAliasUInt16<PAS>::GetSize ();
+
+ if ((offset >= currentRow_offset && offset < currentRow_offset + currentRow_size) ||
+ (offset >= currentColumn_offset && offset < currentColumn_offset + currentColumn_size))
+ {
+ if (!::PrvTrapsAvailable ())
+ {
+ return true;
+ }
+ }
+ }
+
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasTableType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasTableAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Chain to the function that checks FieldType field access.
+
+ return PrvAllowedFieldObjectAccess (
+ objectP + EmAliasTableType<PAS>::offsetof_currentField (),
+ address, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormBitmapObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormBitmapObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ FormBitmapType
+ FormObjAttrType attr;
+ usable // FrmShowObject, FrmHideObject
+ PointType pos; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ UInt16 rscID; // FrmGetObjectId
+ */
+
+ // Allow read access to "attr" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable needs access to it.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasFormBitmapType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFormObjAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow read/write access to "attr" before 3.2 -- FrmHideObject didn't
+ // change the usable bit before then.
+
+ {
+ size_t offset = address - objectP;
+
+ const size_t attr_offset = EmAliasFormBitmapType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFormObjAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ if (EmPatchState::OSMajorMinorVersion () < 32)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormLineObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormLineObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormLineType
+ FormObjAttrType attr;
+ PointType point1;
+ PointType point2;
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormFrameObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormFrameObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormFrameType
+ UInt16 id;
+ FormObjAttrType attr;
+ RectangleType rect;
+ UInt16 frameType;
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormRectangleObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormRectangleObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormRectangleType
+ FormObjAttrType attr;
+ RectangleType rect;
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormLabelObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormLabelObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ FormLabelType
+ UInt16 id; // FrmGetObjectId
+ PointType pos; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ FormObjAttrType attr;
+ usable // FrmShowObject, FrmHideObject
+ FontID fontID; //
+ UInt8 reserved; //
+ Char* text; // FrmGetLabel, FrmCopyLabel
+ */
+
+ // Allow read access to "attr" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable needs access to it.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasFormLabelType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFormObjAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow read/write access to "font" field for FrmGlueGetLabelFont / FrmGlueSetLabelFont.
+
+ {
+ size_t offset = address - objectP;
+
+ const size_t font_offset = EmAliasFormLabelType<PAS>::offsetof_fontID ();
+ const size_t font_size = EmAliasFontID<PAS>::GetSize ();
+
+ if ((offset >= font_offset && offset < font_offset + font_size))
+ {
+ return true;
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormTitleObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormTitleObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormTitleType
+ RectangleType rect; // FrmSetObjectBounds
+ Char* text; // FrmGetTitle, FrmSetTitle, FrmCopyTitle
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormPopupObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormPopupObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormPopupType
+ UInt16 controlID; //
+ UInt16 listID; //
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormGraffitiStateObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormGraffitiStateObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ UNUSED_PARAM (objectP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FrmGraffitiStateType
+ PointType pos; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ */
+
+ // No access to any fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormGadgetObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormGadgetObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ FormGadgetType
+ UInt16 id; // FrmGetObjectId
+ FormGadgetAttrType attr;
+ usable // FrmShowObject, FrmHideObject
+ extended //
+ visible //
+ RectangleType rect; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, FrmSetObjectPosition
+ const void* data; // FrmGetGadgetData, FrmSetGadgetData
+ FormGadgetHandlerType* handler; // FrmSetGadgetHandler
+ */
+
+#if 1
+ UNUSED_PARAM (objectP);
+ UNUSED_PARAM (address);
+ UNUSED_PARAM (forRead);
+
+ // Return "true" for all gadget fields. Gadget callback functions
+ // provide just a pointer to the gadget, with no reference to the
+ // form through which to make access calls. So the only way to
+ // access fields is directly.
+
+ return true;
+#else
+ // Allow read access to "attr" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable needs access to it.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasFormGadgetType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFormGadgetAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow write access to "attr" before 3.5, as that version added support for
+ // showing and hiding gadgets. And write-access implies read-access.
+
+// if (!forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasFormGadgetType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasFormGadgetAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ if (EmPatchState::OSMajorMinorVersion () < 35)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedScrollBarObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedScrollBarObjectAccess (emuptr objectP, emuptr address, Bool forRead)
+{
+ /*
+ ScrollBarType
+ RectangleType bounds; // FrmGetObjectBounds, FrmGetObjectPosition, FrmSetObjectBounds, , FrmSetObjectPosition
+ UInt16 id; // FrmGetObjectId
+ ScrollBarAttrType attr;
+ usable // FrmShowObject, FrmHideObject
+ visible //
+ hilighted //
+ shown //
+ activeRegion //
+ Int16 value; // SclGetScrollBar, SclSetScrollBar
+ Int16 minValue; // SclGetScrollBar, SclSetScrollBar
+ Int16 maxValue; // SclGetScrollBar, SclSetScrollBar
+ Int16 pageSize; // SclGetScrollBar, SclSetScrollBar
+ Int16 penPosInCar; //
+ Int16 savePos; //
+ */
+
+ // Allow read access to "attr" if Emu68KAccessorTrapAvailable / AccFrmGetObjectUsable
+ // not available -- FrmGlueGetObjectUsable needs access to it.
+
+ if (forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasScrollBarType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasScrollBarAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow write access to "attr" before 3.5, as that version added support for
+ // showing and hiding scrollbars. And write-access implies read-access.
+
+// if (!forRead)
+ {
+ size_t offset = address - objectP;
+ const size_t attr_offset = EmAliasScrollBarType<PAS>::offsetof_attr ();
+ const size_t attr_size = EmAliasScrollBarAttrType<PAS>::GetSize ();
+
+ if (offset >= attr_offset && offset < attr_offset + attr_size)
+ {
+ if (EmPatchState::OSMajorMinorVersion () < 35)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormObjectAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form object is allowed
+// on the current platform.
+
+static Bool PrvAllowedFormObjectAccess (EmAliasFormObjListType<PAS>& formObject,
+ emuptr address, Bool forRead)
+{
+ //
+ // No access is allowed if Accessor Functions are available.
+ //
+
+ if (::PrvAccessorTrapAvailable ())
+ return false;
+
+ FormObjectKind kind = formObject.objectType;
+
+ Bool (*check_function) (emuptr, emuptr, Bool) = NULL;
+
+ switch (kind)
+ {
+ case frmFieldObj: check_function = PrvAllowedFieldObjectAccess; break;
+ case frmControlObj: check_function = PrvAllowedControlObjectAccess; break;
+ case frmListObj: check_function = PrvAllowedListObjectAccess; break;
+ case frmTableObj: check_function = PrvAllowedTableObjectAccess; break;
+ case frmBitmapObj: check_function = PrvAllowedFormBitmapObjectAccess; break;
+ case frmLineObj: check_function = PrvAllowedFormLineObjectAccess; break;
+ case frmFrameObj: check_function = PrvAllowedFormFrameObjectAccess; break;
+ case frmRectangleObj: check_function = PrvAllowedFormRectangleObjectAccess; break;
+ case frmLabelObj: check_function = PrvAllowedFormLabelObjectAccess; break;
+ case frmTitleObj: check_function = PrvAllowedFormTitleObjectAccess; break;
+ case frmPopupObj: check_function = PrvAllowedFormPopupObjectAccess; break;
+ case frmGraffitiStateObj: check_function = PrvAllowedFormGraffitiStateObjectAccess; break;
+ case frmGadgetObj: check_function = PrvAllowedFormGadgetObjectAccess; break;
+ case frmScrollBarObj: check_function = PrvAllowedScrollBarObjectAccess; break;
+ }
+
+ if (check_function)
+ {
+ return check_function (formObject.object, address, forRead);
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedWindowAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given window is allowed on
+// the current platform.
+
+static Bool PrvAllowedWindowAccess (emuptr windowP, emuptr address, Bool forRead)
+{
+ //
+ // No access is allowed if Accessor Functions are available.
+ //
+
+ if (::PrvAccessorTrapAvailable ())
+ return false;
+
+ UNUSED_PARAM (forRead)
+
+ size_t offset = address - windowP;
+ EmAliasWindowType<PAS> window (windowP);
+
+#undef ACCESSED
+#define ACCESSED(fieldName) \
+ ((offset >= window.offsetof_##fieldName ()) && \
+ (offset < window.offsetof_##fieldName () + window.fieldName.GetSize ()))
+
+ // Allow access to the following fields before 2.0:
+ //
+ // displayWidthV20
+ // displayHeightV20
+
+ if (forRead && EmPatchState::OSMajorMinorVersion () < 20)
+ {
+ if (ACCESSED (displayWidthV20) ||
+ ACCESSED (displayHeightV20))
+ {
+ return true;
+ }
+ }
+
+ // Allow access to the following fields before 3.5:
+ //
+ // displayAddrV20
+ // bitmapP
+
+ if (forRead && EmPatchState::OSMajorMinorVersion () < 35)
+ {
+ if (ACCESSED (displayAddrV20) ||
+ ACCESSED (bitmapP))
+ {
+ return true;
+ }
+ }
+
+ // Allow access to the following field for WinGlueGetFrameType, WinGlueSetFrameType.
+
+ {
+ if (ACCESSED (frameType))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedFormAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given form is allowed on the
+// current platform.
+
+static Bool PrvAllowedFormAccess (emuptr formP, emuptr address, Bool forRead)
+{
+ //
+ // No access is allowed if Accessor Functions are available.
+ //
+
+ if (::PrvAccessorTrapAvailable ())
+ return false;
+
+ UNUSED_PARAM (formP)
+ UNUSED_PARAM (address)
+ UNUSED_PARAM (forRead)
+
+ /*
+ FormType
+ WindowType window;
+ UInt16 formId; // FrmGetFormId
+ FormAttrType attr;
+ usable //
+ enabled //
+ visible // FrmVisible
+ dirty // FrmGetUserModifiedState, FrmSetNotUserModified
+ saveBehind //
+ graffitiShift //
+ globalsAvailable //
+ doingDialog //
+ exitDialog //
+ WinHandle bitsBehindForm; //
+ FormEventHandlerType* handler; // FrmSetEventHandler
+ UInt16 focus; // FrmGetFocus, FrmSetFocus
+ UInt16 defaultButton; //
+ UInt16 helpRscId; //
+ UInt16 menuRscId; // FrmSetMenu
+ UInt16 numObjects; // FrmGetNumberOfObjects
+ FormObjListType* objects; // FrmGetObjectPtr, FrmGetObjectType
+ */
+
+ // Allow read access to "handler" for FrmGlueGetEventHandler.
+
+ if (forRead)
+ {
+ size_t offset = address - formP;
+ const size_t handler_offset = EmAliasFormType<PAS>::offsetof_handler ();
+ const size_t handler_size = EmAliasemuptr<PAS>::GetSize ();
+
+ if (offset >= handler_offset && offset < handler_offset + handler_size)
+ {
+ return true;
+ }
+ }
+
+ // Allow full access to defaultButton, menuRscId, and helpRscId for FrmGlueGetDefaultButtonID,
+ // FrmGlueSetDefaultButtonID, FrmGlueGetHelpID, FrmGlueSetHelpID, and FrmGlueGetMenuBarID.
+
+ {
+ size_t offset = address - formP;
+ const size_t defaultButton_offset = EmAliasFormType<PAS>::offsetof_defaultButton ();
+ const size_t defaultButton_size = EmAliasUInt16<PAS>::GetSize ();
+ const size_t helpRscId_offset = EmAliasFormType<PAS>::offsetof_helpRscId ();
+ const size_t helpRscId_size = EmAliasUInt16<PAS>::GetSize ();
+ const size_t menuRscId_offset = EmAliasFormType<PAS>::offsetof_menuRscId ();
+ const size_t menuRscId_size = EmAliasUInt16<PAS>::GetSize ();
+
+ if ((offset >= defaultButton_offset && offset < defaultButton_offset + defaultButton_size) ||
+ (offset >= helpRscId_offset && offset < helpRscId_offset + helpRscId_size) ||
+ (offset >= menuRscId_offset && offset < menuRscId_offset + menuRscId_size))
+ {
+ return true;
+ }
+ }
+
+ // Chain to the function that checks WindowType field access.
+
+ return PrvAllowedWindowAccess (formP, address, forRead);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAllowedBitmapAccess
+// ---------------------------------------------------------------------------
+// Return whether or not the given access to the given bitmap is allowed
+// on the current platform.
+
+static Bool PrvAllowedBitmapAccess (EmAliasBitmapTypeV2<PAS>& bitmap, emuptr address, Bool forRead)
+{
+ //
+ // No access is allowed if Accessor Functions are available.
+ //
+
+ if (::PrvAccessorTrapAvailable ())
+ return false;
+
+ /*
+ BitmapType
+1.0 Int16 width;
+1.0 Int16 height;
+1.0 UInt16 rowBytes;
+1.0 BitmapFlagsType flags;
+1.0 UInt16 compressed:1; // Data format: 0=raw; 1=compressed
+3.0 UInt16 hasColorTable:1; // if true, color table stored before bits[]
+3.5 UInt16 hasTransparency:1; // true if transparency is used
+3.5 UInt16 indirect:1; // true if bits are stored indirectly
+3.5 UInt16 forScreen:1; // system use only
+3.0 UInt8 pixelSize; // bits/pixel
+3.0 UInt8 version; // version of bitmap. This is vers 2
+3.0 UInt16 nextDepthOffset; // # of DWords to next BitmapType
+ // from beginnning of this one
+3.5 UInt8 transparentIndex; // v2 only, if flags.hasTransparency is true,
+ // index number of transparent color
+3.5 UInt8 compressionType; // v2 only, if flags.compressed is true, this is
+ // the type, see BitmapCompressionType
+
+ UInt16 reserved; // for future use, must be zero!
+
+ // [colorTableType] pixels | pixels*
+ // If hasColorTable != 0, we have:
+ // ColorTableType followed by pixels.
+ // If hasColorTable == 0:
+ // this is the start of the pixels
+ // if indirect != 0 bits are stored indirectly.
+ // the address of bits is stored here
+ // In some cases the ColorTableType will
+ // have 0 entries and be 2 bytes long.
+ */
+
+ /*
+ width - Needs r/w access before 3.5. In 3.5, use BmpCreate.
+ - Needs read access before 4.0. In 4.0, use BmpGetDimensions.
+ - No access in 4.0 and later.
+ height - Same as width.
+ rowBytes - Same as width.
+ flags - Needs r/w access always. (to get to hasTransparency)
+ compressed - Needs r/w access before 3.5. In 3.5, use BmpCompress.
+ - No access in 3.5 and later.
+ hasColorTable - Needs r/w access before 3.5. In 3.5, use BmpCreate.
+ - No access in 3.5 and later.
+ hasTransparency - Needs r/w access always.
+ indirect - No access -- system use only
+ forScreen - No access -- system use only
+ pixelSize - Needs r/w access before 3.5. In 3.5, use BmpCreate.
+ - Needs read access before 4.0. In 4.0, use BmpGetBitDepth.
+ - No access in 4.0 and later.
+ version - Needs r/w access before 3.5. In 3.5, use BmpCreate.
+ - Needs read access before 4.0. In 4.0, use BmpGetNextBitmap.
+ - No access in 4.0 and later.
+ nextDepthOffset - Needs r/w access before 3.5. In 3.5, use BmpCreate.
+ - Needs read access before 4.0. In 4.0, use BmpGetNextBitmap.
+ - No access in 4.0 and later.
+ transparentIndex - Needs r/w access always.
+ compressionType - Needs r/w access before 3.5. In 3.5, use BmpCompress.
+ - No access in 3.5 and later.
+ reserved - No access
+ */
+
+ /*
+ // 3.5
+ #define sysTrapBmpGetBits 0xA376 // was BltGetBitsAddr
+
+ // Bitmap manager functions
+ #define sysTrapBmpCreate 0xA3DD // width, height, depth, colortable.
+ #define sysTrapBmpDelete 0xA3DE
+ #define sysTrapBmpCompress 0xA3DF // compressed, compressionType
+
+ // sysTrapBmpGetBits defined in Screen driver traps
+ #define sysTrapBmpGetColortable 0xA3E0
+ #define sysTrapBmpSize 0xA3E1
+ #define sysTrapBmpBitsSize 0xA3E2
+ #define sysTrapBmpColortableSize 0xA3E3
+
+ // 4.0
+ #define sysTrapBmpGetDimensions 0xA44E
+ #define sysTrapBmpGetBitDepth 0xA44F
+ #define sysTrapBmpGetNextBitmap 0xA450
+ #define sysTrapBmpGetSizes 0xA455
+ */
+
+ // Since the rules are largely dependent on OS version, let's order
+ // our first-level checks based on that.
+
+ if (EmPatchState::OSMajorMinorVersion () < 35)
+ {
+ // Have full access before 3.5, since there's no API.
+
+ return true;
+ }
+ else if (EmPatchState::OSMajorMinorVersion () < 40)
+ {
+ // The following functions were added in 3.5:
+ //
+ // BmpGetBits
+ // BmpCreate -- Allows setting of all fields except hasTransparency and transparentIndex.
+ // BmpDelete
+ // BmpCompress -- Allows changing of compressed, compressionType
+ // BmpGetColortable
+ // BmpSize
+ // BmpBitsSize
+ // BmpColortableSize
+ //
+ // Therefore, all fields except hasTransparency and transparentIndex
+ // now have read-only access. Those two fields still have read/write access.
+
+ if (forRead)
+ {
+ return true;
+ }
+ else
+ {
+ emuptr bitmapP = bitmap.GetPtr ();
+ size_t offset = address - bitmapP;
+
+ const size_t flags_offset = EmAliasBitmapTypeV2<PAS>::offsetof_flags ();
+ const size_t flags_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t transparentIndex_offset = EmAliasBitmapTypeV2<PAS>::offsetof_transparentIndex ();
+ const size_t transparentIndex_size = EmAliasUInt8<PAS>::GetSize ();
+
+ if (offset >= flags_offset && offset < flags_offset + flags_size)
+ {
+ return true;
+ }
+
+ if (offset >= transparentIndex_offset && offset < transparentIndex_offset + transparentIndex_size)
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ // The following functions were added in 4.0:
+ //
+ // BmpGetDimensions
+ // BmpGetBitDepth
+ // BmpGetNextBitmap
+ // BmpGetSizes
+ //
+ // With these, complete supported access to all fields is provided
+ // except for hasTransparency and transparentIndex.
+
+ emuptr bitmapP = bitmap.GetPtr ();
+ size_t offset = address - bitmapP;
+
+ const size_t flags_offset = EmAliasBitmapTypeV2<PAS>::offsetof_flags ();
+ const size_t flags_size = EmAliasUInt16<PAS>::GetSize ();
+
+ const size_t transparentIndex_offset = EmAliasBitmapTypeV2<PAS>::offsetof_transparentIndex ();
+ const size_t transparentIndex_size = EmAliasUInt8<PAS>::GetSize ();
+
+ if (offset >= flags_offset && offset < flags_offset + flags_size)
+ {
+ return true;
+ }
+
+ if (offset >= transparentIndex_offset && offset < transparentIndex_offset + transparentIndex_size)
+ {
+ return true;
+ }
+ }
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+static Bool PrvAllowedBitmapAccess (EmAliasBitmapTypeV3<PAS>&, emuptr, Bool)
+{
+ // Access to all fields is provided by accessor functions in all versions
+ // of the OS that support this data structure.
+
+ // Don't allow access to any other fields.
+
+ return false;
+}
+
+
+#pragma mark -
+
+/*
+ In order to track Bitmaps, we have to do some pretty fancy footwork.
+ We need to be able to tell when Bitmaps are allocated and deallocated
+ so that we know which memory blocks to mark as inaccessible.
+
+ One way that a bitmap can be allocated/deallocated is with BmpCreate
+ and BmpDelete. To support this method, we patch those two functions
+ and call RegisterBitmapPointer and UnregisterBitmapPointer as
+ appropriate.
+
+ The other way that a bitmap can be allocated/deallocated is from a
+ resource. The resource is read in with DmGetResource or DmGet1Resource,
+ locked with MemHandleLock, unlocked with MemHandleUnlock or MemPtrUnlock
+ (or possibly MemHandleResetLock), and then possibly released with
+ DmReleaseResource. To support this method, we patch DmGetResource
+ and DmGet1Resource so that we know which handles contain bitmaps (passing
+ them to RegisterBitmapHandle), and MemHandleLock so that we can get the
+ pointer to the bitmap and pass it to RegisterBitmapPointer. We also
+ monitor MemHandleUnlock, MemPtrUnlock, and MemHandleResetLock so that we
+ can call UnregisterBitmapPointer, and MemHandleFree and MemPtrFree so
+ that we can call UnregisterBitmapHandle.
+
+ With all the handles and pointers registered, we now have the information
+ we need in order to mark the blocks as inaccessible in PrvForEachBitmap.
+*/
+
+// !!! NOTE: bitmap tracking is turned off for now. The heuristics for
+// determining when to stop tracking a memory handle are incomplete
+// and need to be rethought out. In particular, the case of installing
+// an application with a color icon, running it, and then trying to
+// re-install that application doesn't work.
+//
+// As well, Poser doesn't handle invalid bitmap families very well.
+// It can easily try to use bogus nextDepthOffset values when stepping
+// to the next icon in the family.
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::RegisterBitmapHandle
+// ---------------------------------------------------------------------------
+
+void MetaMemory::RegisterBitmapHandle (MemHandle /*h*/)
+{
+#if 0
+ if (h && !IsBitmapHandle (h))
+ {
+ MetaMemory::UnmarkUIObjects ();
+ gBitmapHandleList.push_back (h);
+ MetaMemory::MarkUIObjects ();
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::RegisterBitmapPointer
+// ---------------------------------------------------------------------------
+
+void MetaMemory::RegisterBitmapPointer (MemPtr /*p*/)
+{
+#if 0
+ if (p && !IsBitmapPointer (p))
+ {
+ MetaMemory::UnmarkUIObjects ();
+ gBitmapPointerList.push_back (p);
+ MetaMemory::MarkUIObjects ();
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::IsBitmapHandle
+// ---------------------------------------------------------------------------
+
+Bool MetaMemory::IsBitmapHandle (MemHandle h)
+{
+ return h && find (
+ gBitmapHandleList.begin (),
+ gBitmapHandleList.end (), h) != gBitmapHandleList.end ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::IsBitmapPointer
+// ---------------------------------------------------------------------------
+
+Bool MetaMemory::IsBitmapPointer (MemPtr p)
+{
+ return p && find (
+ gBitmapPointerList.begin (),
+ gBitmapPointerList.end (), p) != gBitmapPointerList.end ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnregisterBitmapHandle
+// ---------------------------------------------------------------------------
+
+void MetaMemory::UnregisterBitmapHandle (MemHandle h)
+{
+ if (h)
+ {
+ vector<MemHandle>::iterator iter = find (
+ gBitmapHandleList.begin (),
+ gBitmapHandleList.end (), h);
+
+ if (iter != gBitmapHandleList.end ())
+ {
+ MetaMemory::UnmarkUIObjects ();
+ gBitmapHandleList.erase (iter);
+ MetaMemory::MarkUIObjects ();
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnregisterBitmapPointer
+// ---------------------------------------------------------------------------
+
+void MetaMemory::UnregisterBitmapPointer (MemPtr p)
+{
+ if (p)
+ {
+ vector<MemPtr>::iterator iter = find (
+ gBitmapPointerList.begin (),
+ gBitmapPointerList.end (), p);
+
+ if (iter != gBitmapPointerList.end ())
+ {
+ MetaMemory::UnmarkUIObjects ();
+ gBitmapPointerList.erase (iter);
+ MetaMemory::MarkUIObjects ();
+ }
+ }
+}
+
+
+#pragma mark -
+
+struct EmCheckIterData
+{
+ emuptr address;
+ size_t size;
+ Bool forRead;
+ Bool isInUIObject;
+ Bool butItsOK;
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetObjectSize
+// ---------------------------------------------------------------------------
+// Get and return the size of the object. A bitmap object's size is based on
+// the version number in the bitmap. A window object's size is the size of
+// the memory chunk the window's in.
+
+static int PrvGetObjectSize (emuptr object, int type)
+{
+ int result = 0;
+
+ if (type == kUIWindow)
+ {
+ // Get the heap the window is in. Use that to get information about
+ // the chunk the window is in.
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr ((MemPtr) object);
+
+ // Can't find the heap? Aip!
+
+ EmAssert (heap != NULL);
+
+ if (!heap)
+ return result;
+
+ // Get information on this chunk so that we can get its size.
+
+ EmPalmChunk chunk (*heap, object - heap->ChunkHeaderSize ());
+
+ result = chunk.BodySize ();
+ }
+ else if (type == kUIBitmap)
+ {
+ EmAliasBitmapTypeV3<PAS> bitmapV3 (object);
+
+ if (bitmapV3.version <= 2)
+ {
+ result = EmProxyBitmapTypeV2::GetSize ();
+ }
+ else
+ {
+ result = bitmapV3.size;
+ }
+ }
+ else
+ {
+ EmAssert (false);
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetNextBitmap
+// ---------------------------------------------------------------------------
+
+static emuptr PrvGetNextBitmap (emuptr p)
+{
+ emuptr nextBitmap = EmMemNULL;
+
+ EmAliasBitmapTypeV2<PAS> bitmapV2 (p);
+
+ // If this is a version 3 bitmap, then format the structure as a
+ // version 3 structure and extract the nextDepthOffset field.
+
+ if (bitmapV2.version >= 3)
+ {
+ EmAliasBitmapTypeV3<PAS> bitmapV3 (p);
+
+ if (bitmapV3.nextDepthOffset != 0)
+ {
+ nextBitmap = p + bitmapV3.nextDepthOffset * sizeof (UInt32);
+ }
+ }
+
+ // If this is a version 0, 1, or 2 bitmap, extract the
+ // nextDepthOffset field.
+
+ else if (bitmapV2.nextDepthOffset != 0)
+ {
+ nextBitmap = p + bitmapV2.nextDepthOffset * sizeof (UInt32);
+ }
+
+ // If that was NULL, then check to see if this looks like a "dummy"
+ // bitmap used to hide the existance and format of high density
+ // bitmap families from the unprepared application.
+
+ else if (bitmapV2.version == 1 && bitmapV2.pixelSize == 255)
+ {
+ nextBitmap = p + bitmapV2.GetSize ();
+ }
+
+ EmAssert (nextBitmap == EmMemNULL || EmMemCheckAddress (nextBitmap, 0) != false);
+
+ return nextBitmap;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckFormObject
+// ---------------------------------------------------------------------------
+
+static Bool PrvCheckFormObject (EmAliasFormType<PAS>& form,
+ EmAliasFormObjListType<PAS>& formObject,
+ EmCheckIterData* data)
+{
+ // Get the form object kind, so that we can determine its size.
+
+ emuptr formP = form.GetPtr ();
+ emuptr formObjectP = formObject.GetPtr ();
+
+ FormObjectKind kind = formObject.objectType;
+ emuptr objectAddr = formObject.object;
+
+ static int kSizeArray[] =
+ {
+ EmAliasFieldType<PAS>::GetSize (), // frmFieldObj
+ -1, // frmControlObj
+ EmAliasListType<PAS>::GetSize (), // frmListObj
+ EmAliasTableType<PAS>::GetSize (), // frmTableObj
+ EmAliasFormBitmapType<PAS>::GetSize (), // frmBitmapObj
+ EmAliasFormLineType<PAS>::GetSize (), // frmLineObj
+ EmAliasFormFrameType<PAS>::GetSize (), // frmFrameObj
+ EmAliasFormRectangleType<PAS>::GetSize (), // frmRectangleObj
+ EmAliasFormLabelType<PAS>::GetSize (), // frmLabelObj
+ EmAliasFormTitleType<PAS>::GetSize (), // frmTitleObj
+ EmAliasFormPopupType<PAS>::GetSize (), // frmPopupObj
+ EmAliasFrmGraffitiStateType<PAS>::GetSize (), // frmGraffitiStateObj
+ EmAliasFormGadgetType<PAS>::GetSize (), // frmGadgetObj
+ EmAliasScrollBarType<PAS>::GetSize () // frmScrollBarObj
+ };
+
+ // If the access was to a form object, flag an error.
+
+ int itsSize = kSizeArray[kind];
+
+ if (itsSize < 0) // Special cases
+ {
+ // Some controls have special sizes. Determine and use those.
+
+ EmAliasControlType<PAS> control (objectAddr);
+ uint16 attr = control.attr.flags;
+ uint8 style = control.style;
+
+ itsSize = control.GetSize (); // Standard ControlType size
+
+ if (attr & ControlAttrType_graphical)
+ {
+ // It's a GraphicControlType.
+
+ itsSize = EmAliasGraphicControlType<PAS>::GetSize ();
+ }
+ else if (style == sliderCtl || style == feedbackSliderCtl)
+ {
+ // It's a SliderControlType.
+
+ itsSize = EmAliasSliderControlType<PAS>::GetSize ();
+ }
+ }
+
+ // Now check access to the form object.
+
+ if (data->address >= objectAddr && data->address < objectAddr + itsSize)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedFormObjectAccess (formObject, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrFormObjectAccess (formObjectP, formP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+#if 0 // There's no good API for altering the text, and so many developers
+ // write to it "in place". Allow this for now, until we come up with
+ // a better API.
+
+ // If there's text associated with this object, check access to it, too.
+ // Allow read access, since some functions (like CtrlGetLabel) return
+ // pointers to the text that the application will expect to access.
+
+ emuptr textPtr = EmMemNULL;
+
+ switch (kind)
+ {
+ case frmControlObj:
+ {
+ EmAliasControlType<PAS> control (objectAddr);
+ uint16 attr = control.attr.flags;
+ uint8 style = control.style;
+
+ if (attr & ControlAttrType_graphical)
+ {
+ // No text with graphical controls.
+ }
+ else if (style == sliderCtl || style == feedbackSliderCtl)
+ {
+ // No text with slider controls.
+ }
+ else
+ {
+ textPtr = control.text;
+ }
+
+ break;
+ }
+
+ case frmLabelObj:
+ {
+ EmAliasFormLabelType<PAS> label (objectAddr);
+ textPtr = label.text;
+ break;
+ }
+
+ case frmTitleObj:
+ {
+ EmAliasFormTitleType<PAS> title (objectAddr);
+ textPtr = title.text;
+ break;
+ }
+
+ case frmFieldObj: // Yes, there's text associated with this object,
+ // but it's never in the same memory chunk as the
+ // form and its objects, and so will not currently
+ // get marked as off limits.
+ case frmListObj:
+ case frmTableObj:
+ case frmBitmapObj:
+ case frmLineObj:
+ case frmFrameObj:
+ case frmRectangleObj:
+ case frmPopupObj:
+ case frmGraffitiStateObj:
+ case frmGadgetObj:
+ case frmScrollBarObj:
+ break;
+ }
+
+ if (textPtr && !data->forRead)
+ {
+ size_t textSize = EmMem_strlen (textPtr) + 1;
+
+ if (data->address >= textPtr && data->address < textPtr + textSize)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedFormObjectAccess (formObject, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrFormObjectAccess (formObjectP, formP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+ }
+#endif
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckForm
+// ---------------------------------------------------------------------------
+
+static Bool PrvCheckForm (EmAliasFormType<PAS>& form, EmCheckIterData* data)
+{
+ // If the access was to the form, flag an error.
+
+ emuptr formP = form.GetPtr ();
+ size_t size = form.GetSize ();
+
+ if (data->address >= formP && data->address < formP + size)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedFormAccess (formP, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrFormAccess (formP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+ // If the access was to the form item list, flag an error.
+
+ // Get the number of objects in the form. Use this value to determine
+ // the range of memory the form spans.
+
+ uint16 numObjects = form.numObjects;
+ emuptr firstObject = form.objects;
+ emuptr lastObject = firstObject + numObjects * EmAliasFormObjListType<PAS>::GetSize ();
+
+ if (data->address >= firstObject && data->address < lastObject)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedFormAccess (formP, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrFormAccess (formP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+ // Walk the objects in the form. Check each one to see
+ // if the access was made to one of them.
+
+ emuptr thisObject = firstObject;
+
+ for (int ii = 0; ii < numObjects; ++ii)
+ {
+ EmAliasFormObjListType<PAS> formObject (thisObject);
+
+ if (::PrvCheckFormObject (form, formObject, data))
+ return true;
+
+ // Go to the next form object.
+
+ thisObject += formObject.GetSize ();
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckWindow
+// ---------------------------------------------------------------------------
+
+static Bool PrvCheckWindow (EmAliasWindowType<PAS>& window, EmCheckIterData* data)
+{
+ // Plain old window. Check the access against the window size.
+ // While a couple of the fields of WindowTyp have changed from
+ // Palm OS 1.0 to 4.0 (viewOrigin has changed to bitMapP, gstate
+ // has changed to drawStateP, and compressed has changed to
+ // freeBitmap), the size is still the same.
+
+ emuptr windowP = window.GetPtr ();
+ size_t size = window.GetSize ();
+
+ if (data->address >= windowP && data->address < windowP + size)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedWindowAccess (windowP, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrWindowAccess (windowP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckBitmap
+// ---------------------------------------------------------------------------
+
+static Bool PrvCheckBitmap (EmAliasBitmapTypeV2<PAS>& bitmapV2, EmCheckIterData* data)
+{
+ emuptr bitmapP = bitmapV2.GetPtr ();
+ size_t size = bitmapV2.GetSize ();
+
+ if (data->address >= bitmapP && data->address < bitmapP + size)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedBitmapAccess (bitmapV2, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrBitmapAccess (bitmapP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckBitmap
+// ---------------------------------------------------------------------------
+
+static Bool PrvCheckBitmap (EmAliasBitmapTypeV3<PAS>& bitmapV3, EmCheckIterData* data)
+{
+ emuptr bitmapP = bitmapV3.GetPtr ();
+ size_t size = bitmapV3.size;
+
+ if (data->address >= bitmapP && data->address < bitmapP + size)
+ {
+ data->isInUIObject = true;
+
+ if (!::PrvAllowedBitmapAccess (bitmapV3, data->address, data->forRead))
+ {
+ gSession->ScheduleDeferredError (new EmDeferredErrBitmapAccess (bitmapP, data->address, data->size, data->forRead));
+ data->butItsOK = false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvCheckUIObject
+// ---------------------------------------------------------------------------
+// Check to see if the given access is in a proscribed area of memory. Will
+// first check to see if:
+//
+// * this check is turned off
+// * the system is initialized enough to make this check
+// * the access is made from a RAM-based system component
+// * full memory access is allowed
+//
+// Only if checking seems indicated is the full-winded check made. If
+// a proscribed access is indeed made, a "deferred error" object is posted
+// to the session.
+
+Bool PrvCheckUIObject (emuptr objectP, void* d, int type)
+{
+ // Walk the window list, looking for windows and forms
+
+ EmAssert (d);
+ EmCheckIterData* data = (EmCheckIterData*) d;
+
+ if (type == kUIWindow)
+ {
+ // See if this window is a plain window, or a form.
+
+ EmAliasWindowType<PAS> window (objectP);
+ uint16 flags = window.windowFlags.flags;
+
+ if (flags & WindowFlagsType_dialog)
+ {
+ // It's a form.
+
+ EmAliasFormType<PAS> form (objectP);
+
+ if (::PrvCheckForm (form, data))
+ return true;
+ }
+ else
+ {
+ // It's a plain old window.
+
+ if (::PrvCheckWindow (window, data))
+ return true;
+ }
+ }
+ else if (type == kUIBitmap)
+ {
+ EmAliasBitmapTypeV2<PAS> bitmapV2 (objectP);
+
+ if (bitmapV2.version <= 2)
+ {
+ if (::PrvCheckBitmap (bitmapV2, data))
+ return true;
+ }
+ else
+ {
+ EmAliasBitmapTypeV3<PAS> bitmapV3 (objectP);
+
+ if (::PrvCheckBitmap (bitmapV3, data))
+ return true;
+ }
+ }
+ else
+ {
+ EmAssert (false);
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvMarkUIObject
+// ---------------------------------------------------------------------------
+// Get the size of the UI object, use it to get the end of the object, and
+// mark the whole thing as off-limits.
+
+Bool PrvMarkUIObject (emuptr object, void* /*data*/, int type)
+{
+ emuptr begin = object;
+ emuptr end = begin + ::PrvGetObjectSize (object, type);
+
+ MetaMemory::MarkUIObject (begin, end);
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvUnmarkUIObject
+// ---------------------------------------------------------------------------
+// Get the size of the UI object, use it to get the end of the object, and
+// mark the whole thing as accessible.
+
+static Bool PrvUnmarkUIObject (emuptr object, void* /*data*/, int type)
+{
+ emuptr begin = object;
+ emuptr end = begin + ::PrvGetObjectSize (object, type);
+
+ MetaMemory::UnmarkUIObject (begin, end);
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvForEachWindow
+// ---------------------------------------------------------------------------
+// Iterate over all window objects, calling a generic iteration function for
+// each one. If the iteration function returns true, that means that the
+// iteration should stop. This function returns true or false to indicate if
+// the iteration was aborted.
+
+Bool PrvForEachWindow (IterFn fn, void* data)
+{
+ // If the UI is not initialized for this application, the FirstWindow
+ // pointer in uiGlobals will be non-NULL, but invalid (it will point
+ // to the FirstWindow for the previous application, which has been
+ // disposed of by now). Wait until UIReset has been called.
+
+ if (!EmPatchState::UIReset ())
+ return false;
+
+ // Walk the window list, looking for windows and forms
+
+ emuptr w = EmLowMem_GetGlobal (uiGlobals.firstWindow);
+ while (w)
+ {
+ if (fn (w, data, kUIWindow))
+ return true;
+
+ // Go to the next window.
+
+ EmAliasWindowType<PAS> window (w);
+ w = window.nextWindow;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvForEachBitmap
+// ---------------------------------------------------------------------------
+// Iterate over all bitmap objects, calling a generic iteration function for
+// each one. If the iteration function returns true, that means that the
+// iteration should stop. This function returns true or false to indicate if
+// the iteration was aborted.
+
+Bool PrvForEachBitmap (IterFn /*fn*/, void* /*data*/)
+{
+#if 0
+ // Iterate over each bitmap in our list.
+
+ vector<MemPtr>::iterator iter = gBitmapPointerList.begin ();
+ while (iter != gBitmapPointerList.end ())
+ {
+ emuptr p = (emuptr) *iter;
+
+ // Iterate over each bitmap in the bitmap family.
+
+ while (p)
+ {
+ if (fn (p, data, kUIBitmap))
+ return true;
+
+ p = ::PrvGetNextBitmap (p);
+ }
+
+ ++iter;
+ }
+#endif
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvForEachUIObject
+// ---------------------------------------------------------------------------
+// Iterate over all UI objects, calling a generic iteration function for each
+// one. If the iteration function returns true, that means that the iteration
+// should stop. This function returns true or false to indicate if the
+// iteration was aborted.
+
+Bool PrvForEachUIObject (IterFn fn, void* data)
+{
+ // Give us full access to memory.
+
+ CEnableFullAccess munge;
+
+ // Check windows and forms.
+
+ if (::PrvForEachWindow (fn, data))
+ return true;
+
+ // Check bitmaps.
+
+ if (::PrvForEachBitmap (fn, data))
+ return true;
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CheckUIObjectAccess
+// ---------------------------------------------------------------------------
+// Iterate over all UI objects, calling a function that will check to see
+// which -- if any -- object was accessed and if that access was OK.
+
+void MetaMemory::CheckUIObjectAccess (emuptr address, size_t size, Bool forRead,
+ Bool& isInUIObject, Bool& butItsOK)
+{
+ EmCheckIterData data;
+
+ data.address = address;
+ data.size = size;
+ data.forRead = forRead;
+ data.isInUIObject = false;
+ data.butItsOK = true;
+
+ ::PrvForEachUIObject (&::PrvCheckUIObject, &data);
+
+ isInUIObject = data.isInUIObject;
+ butItsOK = data.butItsOK;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkUIObjects
+// ---------------------------------------------------------------------------
+// Iterate over all UI objects, calling a function that will mark each one
+// as off limits to applications.
+
+void MetaMemory::MarkUIObjects (void)
+{
+ ::PrvForEachUIObject (&::PrvMarkUIObject, NULL);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkUIObjects
+// ---------------------------------------------------------------------------
+// Iterate over all UI objects, calling a function that will mark each one
+// as accessible to applications.
+
+void MetaMemory::UnmarkUIObjects (void)
+{
+ ::PrvForEachUIObject (&::PrvUnmarkUIObject, NULL);
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ PrvLocalIDToPtr
+// ---------------------------------------------------------------------------
+// Local/native version of MemLocalIDToPtr. Implemented natively instead
+// of calling emulated version for speed.
+
+static emuptr PrvLocalIDToPtr (LocalID local)
+{
+ emuptr memCardInfoP = EmLowMem_GetGlobal (memCardInfoP);
+ EmAliasCardInfoType<PAS> cardInfo (memCardInfoP);
+ emuptr p = (local & 0xFFFFFFFE) + cardInfo.baseP;
+
+ // If it's a handle, dereference it
+
+ if (local & 0x01)
+ p = EmMemGet32 (p);
+
+ return p;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetRAMDatabaseDirectory
+// ---------------------------------------------------------------------------
+// Return a pointer to the database directory for RAM-based databases.
+
+static emuptr PrvGetRAMDatabaseDirectory(void)
+{
+ emuptr memCardInfoP = EmLowMem_GetGlobal (memCardInfoP);
+ EmAliasCardInfoType<PAS> cardInfo (memCardInfoP);
+ emuptr storeP = cardInfo.ramStoreP;
+
+ EmAliasStorageHeaderType<PAS> store (storeP);
+ LocalID databaseDirID = store.databaseDirID;
+
+ return ::PrvLocalIDToPtr (databaseDirID);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvIsOKCharacter
+// ---------------------------------------------------------------------------
+
+static inline Bool PrvIsOKCharacter (char ch)
+{
+ return islower (ch);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvIsLowerCaseCreator
+// ---------------------------------------------------------------------------
+// Return whether or not the given creator is composed of all lower-case
+// letters (as defined by the islower macro in ctypes.h).
+
+static inline Bool PrvIsLowerCaseCreator (UInt32 creator)
+{
+ const char* p = (const char*) &creator;
+
+ return PrvIsOKCharacter (p[0]) &&
+ PrvIsOKCharacter (p[1]) &&
+ PrvIsOKCharacter (p[2]) &&
+ PrvIsOKCharacter (p[3]);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvIsPalmCreator
+// ---------------------------------------------------------------------------
+
+static Bool PrvIsPalmCreator (UInt32 creator)
+{
+ // Creator IDs consisting of all lowercase letters are reserved for use
+ // by Palm Inc. Additionally, it has reserved the following creator
+ // IDs, as of 8/17/01.
+
+ static const UInt32 kNonStandardCreators[] =
+ {
+ 'a68k',
+ 'mfx1',
+ 'u328',
+ 'u650',
+ 'u8EZ'
+ };
+
+ // Check to see if the creator ID follows the Palm standard. If so,
+ // return TRUE.
+
+ if (::PrvIsLowerCaseCreator (creator))
+ {
+ return true;
+ }
+
+ // See if the creator is in the list of creators registered by
+ // Palm that don't follow the Palm standard. If so, return TRUE.
+
+ for (size_t ii = 0; ii < countof (kNonStandardCreators); ++ii)
+ {
+ if (creator == kNonStandardCreators[ii])
+ {
+ return true;
+ }
+ }
+
+ // It's not a Palm creator. Return FALSE.
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvIsRegisteredPalmCreator
+// ---------------------------------------------------------------------------
+
+static Bool PrvIsRegisteredPalmCreator (UInt32 creator)
+{
+ // Registered Palm applications as of 8/17/01.
+
+ static const UInt32 kPalmRegisteredCreators[] =
+ {
+ 'a68k', 'actv', 'addr', 'blth', 'btcp',
+ 'btex', 'bttn', 'bttx', 'calc', 'cinf',
+ 'clpr', 'date', 'dbmn', 'dial', 'dict',
+ 'digi', 'dmfx', 'dttm', 'econ', 'expn',
+ 'exps', 'fatf', 'fins', 'flsh', 'fone',
+ 'frmt', 'gafd', 'gdem', 'gnrl', 'graf',
+ 'gsmf', 'hidd', 'hpad', 'hrel', 'hssu',
+ 'htcp', 'inet', 'ircm', 'irda', 'iwrp',
+ 'lnch', 'locl', 'lpkr', 'mail', 'mdem',
+ 'memo', 'memr', 'mfgc', 'mfgf', 'mfx1',
+ 'mine', 'mmfx', 'modm', 'msgs', 'netl',
+ 'netp', 'nett', 'netw', 'olbi', 'ownr',
+ 'patd', 'pdil', 'pdvc', 'phop', 'ping',
+ 'pnps', 'poem', 'port', 'pref', 'psys',
+ 'ptch', 'pusb', 'puzl', 'rfcm', 'rfdg',
+ 'sdsd', 'secl', 'secr', 'setp', 'shct',
+ 'smgr', 'smsl', 'smsm', 'spht', 'srvr',
+ 'stgd', 'swrp', 'sync', 'tmgr', 'todo',
+ 'tsml', 'u328', 'u650', 'u8EZ', 'udic',
+ 'usbc', 'usbd', 'usbp', 'vfsm', 'wclp',
+ 'webl', 'wwww'
+ };
+
+ const UInt32* begin = &kPalmRegisteredCreators[0];
+ const UInt32* end = &kPalmRegisteredCreators[countof (kPalmRegisteredCreators)];
+
+ return binary_search (begin, end, creator);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvAddTaggedChunk
+// ---------------------------------------------------------------------------
+
+static void PrvAddTaggedChunk (const EmTaggedPalmChunk& chunk)
+{
+ gTaggedChunks.push_back (chunk);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvLoadTaggedChunk
+// ---------------------------------------------------------------------------
+// Return whether or not the given memory address is in a chunk on our cache
+// of RAM-based system components.
+
+static void PrvLoadTaggedChunk (emuptr pc)
+{
+ EmTaggedPalmChunkList::iterator iter = gTaggedChunks.begin ();
+ while (iter != gTaggedChunks.end ())
+ {
+ if (iter->BodyContains (pc))
+ {
+ gHaveLastChunk = true;
+ gLastChunk = *iter;
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::ChunkUnlocked
+// ---------------------------------------------------------------------------
+// If a chunk is unlocked, see if that chunk is on our cache of RAM-based
+// system components. If so, remove that chunk from our cache.
+
+void MetaMemory::ChunkUnlocked (emuptr addr)
+{
+ EmTaggedPalmChunkList::iterator iter = gTaggedChunks.begin ();
+ while (iter != gTaggedChunks.end ())
+ {
+ if (iter->BodyContains (addr))
+ {
+ gTaggedChunks.erase (iter);
+
+ if (gLastChunk.BodyContains (addr))
+ {
+ gHaveLastChunk = false;
+ }
+
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ PrvIsSystemDatabase
+// ---------------------------------------------------------------------------
+// See if the database is one that we want to treat as a RAM-based system
+// component.
+
+static Bool PrvIsSystemDatabase (UInt32 type, UInt32 creator)
+{
+ Bool isSystemDatabase = false;
+
+ if ((type == sysFileTExtension) ||
+ (type == sysFileTLibrary) ||
+ (type == sysFileTPanel) ||
+ (type == sysFileTSystemPatch) ||
+ (type == sysFileTHtalLib) || // NetSync.prc if is of this type (creator == sysFileCTCPHtal)
+ (type == 'bttx')) // Bluetooth Extension
+ {
+ isSystemDatabase = ::PrvIsPalmCreator (creator);
+ }
+ else if (type == sysFileTApplication)
+ {
+ // I'd just check for all-lower-case letters here, but I'm
+ // dubious as to how strictly 3rd party applications adhere
+ // to that requirement. Checking a directory full of 3rd
+ // party applications on our server, 9 of the 250 or so
+ // application had all-lower-case creators (and more than
+ // one of those was 'memo'!).
+
+ isSystemDatabase = ::PrvIsRegisteredPalmCreator (creator);
+ }
+
+ // Handspring has RAM-based extensions that access system globals
+ // low-memory, and hardware registers. From Bob Petersen:
+ //
+ // HsHal.prc and HsExtensions.prc are the only Handspring
+ // databases that are allowed to perform "system-only" functions
+ // like accessing low memory or touching the Dragonball. On
+ // Prism, we copy HsExtensions.prc to RAM. Potentially either
+ // PRC could be run from RAM.
+ //
+ // From James Phillips:
+ //
+ // The HsExtensions.prc is type 'HsPt' creator 'HsEx' and
+ // the Hal.prc is type 'HwAl' creator 'HsEx'.
+
+ else if (creator == 'HsEx' && (type == 'HsPt' || type == 'HwAl'))
+ {
+ isSystemDatabase = true;
+ }
+
+ return isSystemDatabase;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvSearchForCodeChunk
+// ---------------------------------------------------------------------------
+
+static void PrvSearchForCodeChunk (emuptr pc)
+{
+ // We don't already know about the code chunk containing the given PC.
+ // Iterate over the RAM-based databases, looking for one containing a
+ // resource containing the given PC. When we find it, cache it for
+ // subsequent searches.
+
+ // Give us full access to memory.
+
+ CEnableFullAccess munge;
+
+ // Get the directory for the RAM store. Assumes Card 0.
+
+ emuptr dirP = ::PrvGetRAMDatabaseDirectory ();
+ EmAliasDatabaseDirType<PAS> dir (dirP);
+
+ // Iterate over all the entries.
+
+ UInt16 numDatabases = dir.numDatabases;
+ for (UInt16 ii = 0; ii < numDatabases; ++ii)
+ {
+ // Get the database header for the current entry.
+
+ LocalID dbID = dir.databaseID[ii].baseID;
+ emuptr hdrP = ::PrvLocalIDToPtr (dbID);
+ EmAliasDatabaseHdrType<PAS> hdr (hdrP);
+
+ // Skip this if it's a record database, not a resource database.
+
+ if ((hdr.attributes & dmHdrAttrResDB) == 0)
+ continue;
+
+ // Get a reference to the list of resources in the database.
+
+ EmAliasRecordListType<PAS> recList (hdr.recordList);
+
+ // Grovel over all of the resources.
+
+ UInt16 numRecords = recList.numRecords;
+ for (UInt16 jj = 0; jj < numRecords; ++jj)
+ {
+ EmAliasRsrcEntryType<PAS> entry (recList.resources[jj]);
+
+ // Convert the resource's LocalID into a pointer to the resource data.
+
+ LocalID entryLocalID = entry.localChunkID;
+ emuptr resourceP = ::PrvLocalIDToPtr (entryLocalID);
+
+ // Get the heap the resource is in. Use that to get information about
+ // the chunk the resource is in.
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr ((MemPtr) resourceP);
+
+ // Can't find the heap? Aip!
+
+ EmAssert (heap != NULL);
+
+ if (!heap)
+ continue;
+
+ // If not in this resource, move to the next one.
+
+ EmPalmChunk chunk (*heap, resourceP - heap->ChunkHeaderSize ());
+
+ if (!chunk.BodyContains (pc))
+ continue;
+
+ // The PC is in this resource. Tag it as a system resource
+ // or not and add it to our cache of tagged resources.
+
+ UInt32 type = hdr.type;
+ UInt32 creator = hdr.creator;
+ Bool okType = ::PrvIsSystemDatabase (type, creator);
+
+ gHaveLastChunk = true;
+ gLastChunk = EmTaggedPalmChunk (chunk, okType);
+
+ ::PrvAddTaggedChunk (gLastChunk);
+
+ // We found what we were looking for, so we can leave now.
+
+ return;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::InRAMOSComponent
+// ---------------------------------------------------------------------------
+// Determine if the given memory address is in a RAM-based system component.
+
+Bool MetaMemory::InRAMOSComponent (emuptr pc)
+{
+ // If any access is OK, return true.
+
+ if (CEnableFullAccess::AccessOK ())
+ return true;
+
+ // See if we have cached the last known code chunk. If so, see if it
+ // contains the given pc.
+
+ if (!(gHaveLastChunk && gLastChunk.BodyContains (pc)))
+ {
+ // No, either there's no cached chunk or it doesn't contain the pc.
+ // Check our cache of known code chunks.
+
+ ::PrvLoadTaggedChunk (pc);
+
+ if (!(gHaveLastChunk && gLastChunk.BodyContains (pc)))
+ {
+ // No, it's not in our cached list of chunks. Walk the databases
+ // looking for a new code chunk to add to our list.
+
+ ::PrvSearchForCodeChunk (pc);
+
+ // If we don't have it by now, it means that the PC is not in
+ // a database code resource! That can happen with some system
+ // function patch stubs. If it does, assume it's not system code.
+
+ if (!(gHaveLastChunk && gLastChunk.BodyContains (pc)))
+ {
+ return false;
+ }
+ }
+ }
+
+ // Return whether or not it's a system code chunk.
+
+ return gLastChunk.fIsSystemChunk;
+}
diff --git a/SrcShared/MetaMemory.h b/SrcShared/MetaMemory.h
new file mode 100644
index 0000000..d14133f
--- /dev/null
+++ b/SrcShared/MetaMemory.h
@@ -0,0 +1,668 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _METAMEMORY_H_
+#define _METAMEMORY_H_
+
+#include "EmMemory.h" // EmMemGetMetaAddress
+#include "EmPalmHeap.h" // EmPalmHeap, EmPalmChunkList
+#include "ErrorHandling.h" // Errors::EAccessType
+
+
+class MetaMemory
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ // Called to mark and unmark some areas of memory.
+
+ static void MarkTotalAccess (emuptr begin, emuptr end);
+
+ static void SetAccess (emuptr begin, emuptr end, uint8 bits);
+
+ static void MarkLowMemory (emuptr begin, emuptr end);
+ static void MarkSystemGlobals (emuptr begin, emuptr end);
+ static void MarkHeapHeader (emuptr begin, emuptr end);
+ static void MarkMPT (emuptr begin, emuptr end);
+ static void MarkChunkHeader (emuptr begin, emuptr end);
+ static void MarkChunkTrailer (emuptr begin, emuptr end);
+ static void MarkLowStack (emuptr begin, emuptr end);
+ static void MarkUnlockedChunk (emuptr begin, emuptr end);
+ static void MarkFreeChunk (emuptr begin, emuptr end);
+
+ static void MarkScreen (emuptr begin, emuptr end);
+ static void UnmarkScreen (emuptr begin, emuptr end);
+
+ static void MarkUIObject (emuptr begin, emuptr end);
+ static void UnmarkUIObject (emuptr begin, emuptr end);
+
+ static void MarkUIObjects (void);
+ static void UnmarkUIObjects (void);
+
+ static void MarkInstructionBreak (emuptr opcodeLocation);
+ static void UnmarkInstructionBreak (emuptr opcodeLocation);
+
+ static void MarkDataBreak (emuptr begin, emuptr end);
+ static void UnmarkDataBreak (emuptr begin, emuptr end);
+
+ // Called when memory needs to be marked as initialized or not.
+
+#if FOR_LATER
+ static void MarkUninitialized (emuptr begin, emuptr end);
+ static void MoveUninitialized (emuptr source, emuptr dest, uint32 size);
+ static void MarkInitialized (emuptr begin, emuptr end);
+ static void MarkLongInitialized (emuptr); // Inlined, defined below
+ static void MarkWordInitialized (emuptr); // Inlined, defined below
+ static void MarkByteInitialized (emuptr); // Inlined, defined below
+#endif
+
+ // Called after a heap is created or changed.
+
+ static void Resync (const EmPalmChunkList&);
+
+ // Can a normal application access this memory location?
+ // Forbidden locations are low-memory, system globals, screen
+ // memory, memory manager structures, unlocked handles, and
+ // uninitialized memory.
+
+ static Bool CanAppGetLong (uint8*); // Inlined, defined below
+ static Bool CanAppGetWord (uint8*); // Inlined, defined below
+ static Bool CanAppGetByte (uint8*); // Inlined, defined below
+
+ static Bool CanAppSetLong (uint8*); // Inlined, defined below
+ static Bool CanAppSetWord (uint8*); // Inlined, defined below
+ static Bool CanAppSetByte (uint8*); // Inlined, defined below
+
+ // Can the non-Memory Manager parts of the system access this memory location?
+ // Forbidden locations are low-memory, memory manager structures,
+ // unlocked handles, and uninitialized memory.
+
+ static Bool CanSystemGetLong (uint8*); // Inlined, defined below
+ static Bool CanSystemGetWord (uint8*); // Inlined, defined below
+ static Bool CanSystemGetByte (uint8*); // Inlined, defined below
+
+ static Bool CanSystemSetLong (uint8*); // Inlined, defined below
+ static Bool CanSystemSetWord (uint8*); // Inlined, defined below
+ static Bool CanSystemSetByte (uint8*); // Inlined, defined below
+
+ // Can the Memory Managers parts of the system access this memory location?
+ // Forbidden locations are low-memory and uninitialized memory.
+
+ static Bool CanMemMgrGetLong (uint8*); // Inlined, defined below
+ static Bool CanMemMgrGetWord (uint8*); // Inlined, defined below
+ static Bool CanMemMgrGetByte (uint8*); // Inlined, defined below
+
+ static Bool CanMemMgrSetLong (uint8*); // Inlined, defined below
+ static Bool CanMemMgrSetWord (uint8*); // Inlined, defined below
+ static Bool CanMemMgrSetByte (uint8*); // Inlined, defined below
+
+ static Errors::EAccessType
+ GetWhatHappened (emuptr address, long size, Bool forRead);
+ static Errors::EAccessType
+ AllowForBugs (emuptr address, long size, Bool forRead, Errors::EAccessType);
+ static void CheckUIObjectAccess (emuptr address, size_t size, Bool forRead,
+ Bool& isInUIObject, Bool& butItsOK);
+ static Bool InRAMOSComponent (emuptr pc);
+ static void ChunkUnlocked (emuptr addr);
+
+ static void RegisterBitmapHandle (MemHandle);
+ static void RegisterBitmapPointer (MemPtr);
+ static Bool IsBitmapHandle (MemHandle);
+ static Bool IsBitmapPointer (MemPtr);
+ static void UnregisterBitmapHandle (MemHandle);
+ static void UnregisterBitmapPointer (MemPtr);
+
+ // Accessors for getting ranges of memory.
+
+ static emuptr GetLowMemoryBegin (void);
+ static emuptr GetLowMemoryEnd (void);
+ static emuptr GetSysGlobalsBegin (void);
+ static emuptr GetSysGlobalsEnd (void);
+ static emuptr GetHeapHdrBegin (UInt16 heapID);
+ static emuptr GetHeapHdrEnd (UInt16 heapID);
+
+ // Predicates to help determine what kind of access error
+ // just occurred.
+
+ static Bool IsLowMemory (emuptr testAddress, uint32 size);
+ static Bool IsSystemGlobal (emuptr testAddress, uint32 size);
+ static Bool IsScreenBuffer (emuptr testAddress, uint32 size);
+ static Bool IsMemMgrData (emuptr testAddress, uint32 size);
+ static Bool IsUnlockedChunk (emuptr testAddress, uint32 size);
+ static Bool IsFreeChunk (emuptr testAddress, uint32 size);
+ static Bool IsUninitialized (emuptr testAddress, uint32 size);
+ static Bool IsStack (emuptr testAddress, uint32 size);
+ static Bool IsLowStack (emuptr testAddress, uint32 size);
+ static Bool IsAllocatedChunk (emuptr testAddress, uint32 size);
+
+ static Bool IsScreenBuffer8 (uint8* metaAddress); // Inlined, defined below
+ static Bool IsScreenBuffer16 (uint8* metaAddress); // Inlined, defined below
+ static Bool IsScreenBuffer32 (uint8* metaAddress); // Inlined, defined below
+ static Bool IsScreenBuffer (uint8* metaAddress, uint32 size);
+
+ static Bool IsCPUBreak (emuptr opcodeLocation);
+ static Bool IsCPUBreak (uint8* metaLocation);
+
+ private:
+ struct ChunkCheck
+ {
+ emuptr testAddress;
+ uint32 size;
+ Bool result;
+ };
+
+ struct WhatHappenedData
+ {
+ Errors::EAccessType result;
+ emuptr address;
+ uint32 size;
+ Bool forRead;
+ };
+
+ static void MarkRange (emuptr start, emuptr end, uint8 v);
+ static void UnmarkRange (emuptr start, emuptr end, uint8 v);
+ static void MarkUnmarkRange (emuptr start, emuptr end,
+ uint8 andValue, uint8 orValue);
+
+ static void SyncOneChunk (const EmPalmChunk& chunk);
+
+ static void GWH_ExamineHeap (const EmPalmHeap& heap,
+ WhatHappenedData& info);
+ static void GWH_ExamineChunk (const EmPalmChunk& chunk,
+ WhatHappenedData& info);
+ /*
+ Memory is laid out as follows:
+
+ +-------------------+
+ | Low Memory | Off Limits to everyone except IRQ handlers, SysSleep, and SysDoze
+ +-------------------+
+ | |
+ | System Globals | Off Limits to applications
+ | |
+ +-------------------+
+ | Dynamic Heap |
+ |+-----------------+|
+ || Heap Header || Off Limits to applications and non-MemMgr system
+ |+-----------------+|
+ || Chunks || Off Limits to apps and non-MemMgr system if unlocked
+ |+-----------------+|
+ || Free chunk || Off Limits to applications and non-MemMgr system
+ |+-----------------+|
+ || Chunks ||
+ |+-----------------+|
+ || Chunks ||
+ |+-----------------+|
+ || Chunks ||
+ |+-----------------+|
+ || Stack Chunk || Off Limits to everyone if below A7
+ |+-----------------+|
+ || Screen Chunk || Off Limits to applications
+ |+-----------------+|
+ +-------------------+
+
+ Any memory location can be marked as "uninitialized", which means that
+ it can be written to but not read from. An exception to this would be
+ the parts of the memory manager that move around blocks (which may
+ contain uninitialized sections).
+ */
+
+ enum
+ {
+ kNoAppAccess = 0x0001,
+ kNoSystemAccess = 0x0002,
+ kNoMemMgrAccess = 0x0004,
+ kUnusedMeta1 = 0x0008,
+ kStackBuffer = 0x0010, // Stack buffer; check to see if below-SP access is made.
+ kScreenBuffer = 0x0020, // Screen buffer; update host screen if these bytes are changed.
+ kInstructionBreak = 0x0040, // Halt CPU emulation and check to see why.
+ kDataBreak = 0x0080, // Halt CPU emulation and check to see why.
+
+ kLowMemoryBits = kNoAppAccess | kNoSystemAccess | kNoMemMgrAccess,
+ kGlobalsBits = kNoAppAccess,
+ kMPTBits = kNoAppAccess,
+ kMemStructBits = kNoAppAccess | kNoSystemAccess,
+ kLowStackBits = kNoAppAccess | kNoSystemAccess | kNoMemMgrAccess,
+ kFreeChunkBits = kNoAppAccess | kNoSystemAccess,
+ kUnlockedChunkBits = kNoAppAccess | kNoSystemAccess,
+ kScreenBits = kNoAppAccess | kScreenBuffer,
+ kUIObjectBits = kNoAppAccess,
+ kAccessBitMask = kNoAppAccess | kNoSystemAccess | kNoMemMgrAccess,
+ kFreeAccessBits = 0
+ };
+};
+
+
+// Macros to take a byte of bits and produce an
+// 8-bit, 16-bit, or 32-bit version of it.
+
+#define META_BITS_32(bits) \
+ (((uint32) (bits)) << 24) | \
+ (((uint32) (bits)) << 16) | \
+ (((uint32) (bits)) << 8) | \
+ (((uint32) (bits)))
+
+#define META_BITS_16(bits) \
+ (((uint16) (bits)) << 8) | \
+ (((uint16) (bits)))
+
+#define META_BITS_8(bits) \
+ (((uint8) (bits)))
+
+// Macros to fetch the appropriate 8-bit, 16-bit, or
+// 32-bit value from meta-memory.
+//
+// Fetch the values with byte operations in order to
+// support CPUs that don't allow, say, 16-bit fetches
+// on odd boundaries or 32-bit fetches on odd 16-bit
+// boundaries.
+
+#define META_VALUE_32(p) \
+ ((((uint32)((uint8*) p)[0]) << 24) | \
+ (((uint32)((uint8*) p)[1]) << 16) | \
+ (((uint32)((uint8*) p)[2]) << 8) | \
+ (((uint32)((uint8*) p)[3])))
+
+#define META_VALUE_16(p) \
+ ((((uint16)((uint8*) p)[0]) << 8) | \
+ (((uint16)((uint8*) p)[1])))
+
+#define META_VALUE_8(p) \
+ (*(uint8*) p)
+
+// Macros to define CanAppGetLong, CanAppSetLong,
+// CanSystemGetLong, CanSystemSetLong, etc.
+
+#define DEFINE_FUNCTIONS(kind, bits) \
+ \
+inline Bool MetaMemory::Can##kind##Long (uint8* metaAddress) \
+{ \
+ const uint32 kMask = META_BITS_32 (bits); \
+ \
+ return (META_VALUE_32 (metaAddress) & kMask) == 0; \
+} \
+ \
+inline Bool MetaMemory::Can##kind##Word (uint8* metaAddress) \
+{ \
+ const uint16 kMask = META_BITS_16 (bits); \
+ \
+ return (META_VALUE_16 (metaAddress) & kMask) == 0; \
+} \
+ \
+inline Bool MetaMemory::Can##kind##Byte (uint8* metaAddress) \
+{ \
+ const uint8 kMask = META_BITS_8 (bits); \
+ \
+ return (META_VALUE_8 (metaAddress) & kMask) == 0; \
+}
+
+
+#if FOR_LATER
+DEFINE_FUNCTIONS(AppGet, kNoAppAccess | kUninitialized)
+DEFINE_FUNCTIONS(AppSet, kNoAppAccess)
+
+DEFINE_FUNCTIONS(SystemGet, kNoSystemAccess | kUninitialized)
+DEFINE_FUNCTIONS(SystemSet, kNoSystemAccess)
+
+DEFINE_FUNCTIONS(MemMgrGet, kNoMemMgrAccess | kUninitialized)
+DEFINE_FUNCTIONS(MemMgrSet, kNoMemMgrAccess)
+#else
+DEFINE_FUNCTIONS(AppGet, kNoAppAccess)
+DEFINE_FUNCTIONS(AppSet, kNoAppAccess)
+
+DEFINE_FUNCTIONS(SystemGet, kNoSystemAccess)
+DEFINE_FUNCTIONS(SystemSet, kNoSystemAccess)
+
+DEFINE_FUNCTIONS(MemMgrGet, kNoMemMgrAccess)
+DEFINE_FUNCTIONS(MemMgrSet, kNoMemMgrAccess)
+#endif
+
+
+#if FOR_LATER
+inline void MetaMemory::MarkLongInitialized (emuptr p)
+{
+ const uint32 kMask = META_BITS_32 (kUninitialized);
+
+ META_VALUE_32 (p) &= ~kMask;
+}
+#endif
+
+#if FOR_LATER
+inline void MetaMemory::MarkWordInitialized (emuptr p)
+{
+ const uint16 kMask = META_BITS_16 (kUninitialized);
+
+ META_VALUE_16 (p) &= ~kMask;
+}
+#endif
+
+#if FOR_LATER
+inline void MetaMemory::MarkByteInitialized (emuptr p)
+{
+ const uint8 kMask = META_BITS_8 (kUninitialized);
+
+ META_VALUE_8 (p) &= ~kMask;
+}
+#endif
+
+
+inline Bool MetaMemory::IsScreenBuffer (uint8* metaAddress, uint32 size)
+{
+ if (size == 1)
+ {
+ const uint8 kMask = META_BITS_8 (kScreenBuffer);
+
+ return (META_VALUE_8 (metaAddress) & kMask) != 0;
+ }
+ else if (size == 2)
+ {
+ const uint16 kMask = META_BITS_16 (kScreenBuffer);
+
+ return (META_VALUE_16 (metaAddress) & kMask) != 0;
+ }
+ else if (size == 4)
+ {
+ const uint32 kMask = META_BITS_32 (kScreenBuffer);
+
+ return (META_VALUE_32 (metaAddress) & kMask) != 0;
+ }
+
+ const uint8 kMask = META_BITS_8 (kScreenBuffer);
+
+ for (uint32 ii = 0; ii < size; ++ii)
+ {
+ if (((*(uint8*) (metaAddress + ii)) & kMask) != 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+inline Bool MetaMemory::IsScreenBuffer8 (uint8* metaAddress)
+{
+ const uint8 kMask = META_BITS_8 (kScreenBuffer);
+
+ return (META_VALUE_8 (metaAddress) & kMask) != 0;
+}
+
+inline Bool MetaMemory::IsScreenBuffer16 (uint8* metaAddress)
+{
+ const uint16 kMask = META_BITS_16 (kScreenBuffer);
+
+ return (META_VALUE_16 (metaAddress) & kMask) != 0;
+}
+
+inline Bool MetaMemory::IsScreenBuffer32 (uint8* metaAddress)
+{
+ const uint32 kMask = META_BITS_32 (kScreenBuffer);
+
+ return (META_VALUE_32 (metaAddress) & kMask) != 0;
+}
+
+
+inline Bool MetaMemory::IsCPUBreak (emuptr opcodeLocation)
+{
+ EmAssert ((opcodeLocation & 1) == 0);
+ return IsCPUBreak (EmMemGetMetaAddress (opcodeLocation));
+}
+
+
+inline Bool MetaMemory::IsCPUBreak (uint8* metaLocation)
+{
+ return ((*metaLocation) & kInstructionBreak) != 0;
+}
+
+
+#define META_CHECK(metaAddress, address, op, size, forRead) \
+do { \
+ if (Memory::IsPCInRAM ()) \
+ { \
+ if (!MetaMemory::CanApp##op (metaAddress)) \
+ { \
+ if (!MetaMemory::InRAMOSComponent (gCPU->GetPC ())) \
+ { \
+ ProbableCause (address, sizeof (size), forRead);\
+ } \
+ else if (!MetaMemory::CanSystem##op (metaAddress)) \
+ { \
+ ProbableCause (address, sizeof (size), forRead);\
+ } \
+ } \
+ } \
+ else if (EmPatchState::IsPCInMemMgr ()) \
+ { \
+ if (!MetaMemory::CanMemMgr##op (metaAddress)) \
+ { \
+ ProbableCause (address, sizeof (size), forRead); \
+ } \
+ } \
+ else \
+ { \
+ if (!MetaMemory::CanSystem##op (metaAddress)) \
+ { \
+ ProbableCause (address, sizeof (size), forRead); \
+ } \
+ } \
+} while (0)
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkTotalAccess
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkTotalAccess (emuptr begin, emuptr end)
+{
+ UnmarkRange (begin, end, kAccessBitMask);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::SetAccess
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::SetAccess (emuptr begin, emuptr end, uint8 bits)
+{
+ MarkUnmarkRange (begin, end, ~kAccessBitMask, bits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkLowMemory
+// ---------------------------------------------------------------------------
+// Mark the "low memory" range of memory (the first 256 bytes of
+// memory that hold exception vectors).
+
+inline void MetaMemory::MarkLowMemory (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kLowMemoryBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkSystemGlobals
+// ---------------------------------------------------------------------------
+// Mark the "system globals" range of memory. This range holds the
+// global variables used by the Palm OS, as well as the jump table.
+
+inline void MetaMemory::MarkSystemGlobals (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kGlobalsBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkHeapHeader
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkHeapHeader (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kMemStructBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkMPT
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkMPT (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kMPTBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkChunkHeader
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkChunkHeader (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kMemStructBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkChunkTrailer
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkChunkTrailer (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kMemStructBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkLowStack
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkLowStack (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kLowStackBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkUnlockedChunk
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkUnlockedChunk (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kUnlockedChunkBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkFreeChunk
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkFreeChunk (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kFreeChunkBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkScreen
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkScreen (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kScreenBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkScreen
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::UnmarkScreen (emuptr begin, emuptr end)
+{
+ MarkTotalAccess (begin, end);
+ UnmarkRange (begin, end, kScreenBuffer);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkUIObject
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkUIObject (emuptr begin, emuptr end)
+{
+ SetAccess (begin, end, kUIObjectBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkUIObject
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::UnmarkUIObject (emuptr begin, emuptr end)
+{
+ MarkTotalAccess (begin, end);
+// UnmarkRange (begin, end, kUIObjectBits);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkInstructionBreak
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkInstructionBreak (emuptr opcodeLocation)
+{
+ EmAssert ((opcodeLocation & 1) == 0);
+
+ uint8* ptr = EmMemGetMetaAddress (opcodeLocation);
+
+ *ptr |= kInstructionBreak;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkInstructionBreak
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::UnmarkInstructionBreak (emuptr opcodeLocation)
+{
+ EmAssert ((opcodeLocation & 1) == 0);
+
+ uint8* ptr = EmMemGetMetaAddress (opcodeLocation);
+
+ *ptr &= ~kInstructionBreak;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::MarkDataBreak
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::MarkDataBreak (emuptr begin, emuptr end)
+{
+ MarkRange (begin, end, kDataBreak);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ MetaMemory::UnmarkDataBreak
+// ---------------------------------------------------------------------------
+
+inline void MetaMemory::UnmarkDataBreak (emuptr begin, emuptr end)
+{
+ UnmarkRange (begin, end, kDataBreak);
+}
+
+
+#endif /* _METAMEMORY_H_ */
diff --git a/SrcShared/Miscellaneous.cpp b/SrcShared/Miscellaneous.cpp
new file mode 100644
index 0000000..e8bded5
--- /dev/null
+++ b/SrcShared/Miscellaneous.cpp
@@ -0,0 +1,2954 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Miscellaneous.h"
+
+#include "Byteswapping.h" // Canonical
+#include "ChunkFile.h" // Chunk::GetPointer
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmErrCodes.h" // kError_UnimplementedTrap
+#include "EmHAL.h" // EmHAL::ResetTimer, EmHAL::ResetRTC
+#include "EmLowMem.h" // EmLowMem_SetGlobal, EmLowMem_GetGlobal
+#include "EmMemory.h" // Memory::MapPhysicalMemory, EmMem_strcpy, EmMem_memcmp
+#include "EmPalmFunction.h" // GetFunctionAddress
+#include "EmPatchState.h" // EmPatchState::OSMajorVersion
+#include "EmSession.h" // ScheduleDeferredError
+#include "EmStreamFile.h" // EmStreamFile, kOpenExistingForRead
+#include "ErrorHandling.h" // Errors::Throw
+#include "Logging.h" // LogDump
+#include "Platform.h" // Platform::AllocateMemory
+#include "ROMStubs.h" // WinGetDisplayExtent, FrmGetNumberOfObjects, FrmGetObjectType, FrmGetObjectId, ...
+#include "Strings.r.h" // kStr_INetLibTrapBase, etc.
+#include "UAE.h" // m68k_dreg, etc.
+
+#include <algorithm> // sort()
+#include <locale.h> // localeconv, lconv
+#include <strstream> // strstream
+#include <time.h> // time, localtime
+
+
+extern "C" {
+ // These are defined in machdep_maccess.h, too
+#undef get_byte
+#undef put_byte
+#undef put_long
+#include "gzip.h"
+#include "lzw.h"
+
+int (*write_buf_proc)(char *buf, unsigned size);
+
+DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
+DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+DECLARE(ush, d_buf, DIST_BUFSIZE);
+DECLARE(uch, window, 2L*WSIZE);
+DECLARE(ush, tab_prefix, 1L<<BITS);
+
+int test = 0; /* test .gz file integrity */
+int level = 1; /* compression level */
+int exit_code = OK; /* program exit code */
+int verbose = 2; /* be verbose (-v) */
+int quiet = 0; /* be quiet (-q) */
+
+char ifname[] = "ifname";
+char ofname[] = "ofname";
+char* progname = "progname";
+
+long bytes_in; /* number of input bytes */
+long bytes_out; /* number of output bytes */
+int ifd; /* input file descriptor */
+int ofd; /* output file descriptor */
+unsigned insize; /* valid bytes in inbuf */
+unsigned inptr; /* index of next byte to be processed in inbuf */
+unsigned outcnt; /* bytes in output buffer */
+
+#include <setjmp.h>
+jmp_buf env;
+
+RETSIGTYPE abort_gzip()
+{
+ LogDump ();
+ abort ();
+// longjmp (env, 1);
+}
+
+int my_fprintf (FILE*, const char* fmt, ...)
+{
+ int n;
+ va_list arg;
+
+ va_start (arg, fmt);
+ n = LogGetStdLog ()->VPrintf (fmt, arg);
+ va_end (arg);
+
+ return n;
+}
+
+} // extern "C"
+
+
+extern "C"
+{
+ int PrvGzipReadProc (char* buf, unsigned size);
+ int PrvGzipWriteProc (char* buf, unsigned size);
+}
+
+static void* gSrcP;
+static void* gDstP;
+static long gSrcBytes;
+static long gDstBytes;
+static long gSrcOffset;
+static long gDstOffset;
+
+// ===========================================================================
+// ¥ StMemory Class
+// ===========================================================================
+// Constructor allocates the Ptr
+// Destructor disposes of the Ptr
+
+StMemory::StMemory(
+ char* inPtr)
+{
+ mIsOwner = (inPtr != NULL);
+ mPtr = inPtr;
+}
+
+StMemory::StMemory(
+ long inSize, // Bytes to allocate
+ Bool inClearBytes) // Whether to clear all bytes to zero
+{
+ mIsOwner = true;
+
+ if (inClearBytes)
+ mPtr = (char*) Platform::AllocateMemoryClear (inSize);
+ else
+ mPtr = (char*) Platform::AllocateMemory (inSize);
+}
+
+
+StMemory::StMemory(
+ const StMemory &inPointerBlock)
+{
+ UNUSED_PARAM(inPointerBlock)
+}
+
+
+StMemory::~StMemory()
+{
+ Dispose ();
+}
+
+
+StMemory&
+StMemory::operator = (
+ const StMemory &inPointerBlock)
+{
+ UNUSED_PARAM(inPointerBlock)
+
+ return *this;
+}
+
+
+void
+StMemory::Adopt(
+ char* inPtr)
+{
+ if (inPtr != mPtr)
+ {
+ Dispose ();
+
+ mIsOwner = (inPtr != NULL);
+ mPtr = inPtr;
+ }
+}
+
+
+char*
+StMemory::Release() const
+{
+ mIsOwner = false;
+ return mPtr;
+}
+
+
+void
+StMemory::Dispose()
+{
+ if (mIsOwner && (mPtr != NULL))
+ {
+ Platform::DisposeMemory (mPtr);
+ }
+
+ mIsOwner = false;
+ mPtr = NULL;
+}
+
+
+
+StMemoryMapper::StMemoryMapper (const void* memory, long size) :
+ fMemory (memory)
+{
+ if (fMemory)
+ Memory::MapPhysicalMemory (fMemory, size);
+}
+
+StMemoryMapper::~StMemoryMapper (void)
+{
+ if (fMemory)
+ Memory::UnmapPhysicalMemory (fMemory);
+}
+
+
+void* Platform_AllocateMemory (size_t size)
+{
+ return Platform::AllocateMemory (size);
+}
+
+
+void* Platform_ReallocMemory (void* p, size_t size)
+{
+ return Platform::ReallocMemory (p, size);
+}
+
+
+void Platform_DisposeMemory (void* p)
+{
+ Platform::DisposeMemory (p);
+}
+
+
+StWordSwapper::StWordSwapper (void* memory, long length) :
+ fMemory (memory),
+ fLength (length)
+{
+ ::ByteswapWords (fMemory, fLength);
+}
+
+StWordSwapper::~StWordSwapper (void)
+{
+ ::ByteswapWords (fMemory, fLength);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFormObjectHasValidSize
+ *
+ * DESCRIPTION: Determine whether or not a form object's size is valid.
+ *
+ * PARAMETERS: frm - form containing the object
+ *
+ * objType - the object's type
+ *
+ * objIndex - the object's index in the form
+ *
+ * bounds - the bounding rectangle around the object
+ *
+ * RETURNED: True if the object's size is valid.
+ *
+ ***********************************************************************/
+
+static Bool PrvFormObjectHasValidSize (FormPtr frm, FormObjectKind objType, UInt16 objIndex,
+ RectangleType bounds)
+{
+ EmAssert (frm);
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // Return valid right away if we have height and width
+
+ if (bounds.extent.x > 0 &&
+ bounds.extent.y > 0)
+ {
+ return true;
+ }
+
+ // Allow zero-sized gadgets and tables. The former are often
+ // used as dummy objects merely to hold references to custom
+ // data. The latter exist because there's no other way to
+ // hide a table (there's no "usable" bit).
+
+ if (objType == frmGadgetObj ||
+ objType == frmTableObj)
+ {
+ return true;
+ }
+
+ // Allow zero-width (but not zero-height) popup triggers.
+
+ if (objType == frmControlObj)
+ {
+ emuptr ctrlPtr = (emuptr) ::FrmGetObjectPtr (frm, objIndex);
+ uint8 style = EmMemGet8 (ctrlPtr + offsetof (ControlType, style));
+
+ if (style == popupTriggerCtl)
+ {
+ if (bounds.extent.x == 0 &&
+ bounds.extent.y > 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Allow zero-height lists if the number of objects in them is zero.
+
+ if (objType == frmListObj)
+ {
+ emuptr listPtr = (emuptr) FrmGetObjectPtr (frm, objIndex);
+ Int16 numItems = ::LstGetNumberOfItems ((ListType*)listPtr);
+
+ if (numItems == 0)
+ {
+ if (bounds.extent.x > 0 &&
+ bounds.extent.y == 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ // Failed all the special cases.
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFormObjectIsOffscreen
+ *
+ * DESCRIPTION: Determine whether or not an object is off-screen.
+ *
+ * PARAMETERS: bounds - the bounding rectangle of the object
+ *
+ * winWidth - width of the window
+ *
+ * winHeight - width of the window
+ *
+ * RETURNED: True if the object is off-screen.
+ *
+ ***********************************************************************/
+
+static Bool PrvFormObjectIsOffscreen (RectangleType bounds, Int16 winWidth, Int16 winHeight)
+{
+ // Ignore objects with a zero extent
+
+ if (bounds.extent.x <= 0 ||
+ bounds.extent.y <= 0)
+ return false;
+
+ return (bounds.topLeft.x >= winWidth ||
+ bounds.topLeft.y >= winHeight ||
+ bounds.topLeft.x + bounds.extent.x <= 0 ||
+ bounds.topLeft.y + bounds.extent.y <= 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFormObjectIsUsable
+ *
+ * DESCRIPTION: Determines whether or not a form object is usable, ie
+ * should be considered part of the UI.
+ *
+ * PARAMETERS: frmP - form containing the object in question
+ *
+ * index - index of the object
+ *
+ * kind - type of the object
+ *
+ * RETURNED: True if the object is usable.
+ *
+ ***********************************************************************/
+
+
+#define ControlAttrType_usable 0x8000 // set if part of ui
+
+
+static Bool PrvFormObjectIsUsable (FormPtr frmP, uint16 index, FormObjectKind kind)
+{
+ EmAssert (frmP);
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ emuptr objP = (emuptr)::FrmGetObjectPtr (frmP, index);
+
+ if (objP == EmMemNULL)
+ {
+ return false;
+ }
+
+ switch (kind)
+ {
+ // Objects with special 'usable' flag:
+
+ case frmFieldObj:
+ {
+ FieldAttrType attr;
+ ::FldGetAttributes ((FieldType*)objP, &attr);
+
+ return attr.usable == true;
+ }
+
+ case frmControlObj:
+ {
+ EmAliasControlType<PAS> control ((emuptr)objP);
+
+ return control.attr.flags & ControlAttrType_usable;
+ }
+
+ case frmGadgetObj:
+ {
+ EmAliasFormGadgetType<PAS> gadget ((emuptr)objP);
+
+ return gadget.attr.flags & ControlAttrType_usable;
+ }
+
+ case frmListObj:
+ {
+ EmAliasListType<PAS> list ((emuptr)objP);
+
+ return list.attr.flags & ControlAttrType_usable;
+ }
+
+ case frmScrollBarObj:
+ {
+ EmAliasScrollBarType<PAS> scrollbar ((emuptr)objP);
+
+ return scrollbar.attr.flags & ControlAttrType_usable;
+ }
+
+ // Objects assumed to be usable:
+
+ case frmTableObj:
+ case frmGraffitiStateObj:
+
+ return true;
+
+ // Objects assumed to be unusable:
+
+ case frmBitmapObj:
+ case frmLineObj:
+ case frmFrameObj:
+ case frmRectangleObj:
+ case frmLabelObj:
+ case frmPopupObj:
+ case frmTitleObj:
+
+ return false;
+ }
+
+ // Everything else:
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ValidateFormObjects
+ *
+ * DESCRIPTION: Iterate over all the objects in a form and complain
+ * if we find one that is invalid in some way.
+ *
+ * PARAMETERS: frm - the form to validate
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void ValidateFormObjects (FormPtr frm)
+{
+ if (!frm)
+ return;
+
+ Int16 winWidth, winHeight;
+ ::WinGetDisplayExtent (&winWidth, &winHeight);
+
+ UInt16 numObjects = ::FrmGetNumberOfObjects (frm);
+ for (UInt16 objIndex = 0; objIndex < numObjects; ++objIndex)
+ {
+ FormObjectKind objType = ::FrmGetObjectType (frm, objIndex);
+ UInt16 objID = ::FrmGetObjectId (frm, objIndex);
+
+ switch (objType)
+ {
+ case frmBitmapObj:
+ case frmLineObj:
+ case frmFrameObj:
+ case frmRectangleObj:
+ case frmLabelObj:
+ case frmTitleObj:
+ case frmPopupObj:
+ // do nothing for these
+ break;
+
+ default:
+ {
+ // Check for completely offscreen objects.
+ // (The jury is still out on partially offscreen objects.)
+ RectangleType bounds;
+ ::FrmGetObjectBounds (frm, objIndex, &bounds);
+
+ if (!::PrvFormObjectHasValidSize (frm, objType, objIndex, bounds))
+ {
+ // Report any errors. For now, don't report errors on 1.0
+ // devices. They may not follow the rules, either. In
+ // particular, someone noticed that the Graffiti state
+ // indicator has a size of 0,0.
+
+ if (EmPatchState::OSMajorVersion () > 1)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (
+ new EmDeferredErrSizelessObject (objID, bounds));
+ }
+ }
+ else if (::PrvFormObjectIsOffscreen (bounds, winWidth, winHeight))
+ {
+ if (EmPatchState::OSMajorVersion () > 1)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (
+ new EmDeferredErrOffscreenObject (objID, bounds));
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CollectOKObjects
+ *
+ * DESCRIPTION: Iterate over the objects in a form and make a list of
+ * the ones that are fair game for tapping on. Exclude
+ * objects that aren't interactive (ie a label), aren't
+ * usable, or aren't valid.
+ *
+ * PARAMETERS: frm - the form in question
+ *
+ * okObjects - vector list of objects that are deemed 'ok'.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void CollectOKObjects (FormPtr frm, vector<UInt16>& okObjects)
+{
+ if (!frm)
+ return;
+
+ Int16 winWidth, winHeight;
+ ::WinGetDisplayExtent (&winWidth, &winHeight);
+
+ UInt16 numObjects = ::FrmGetNumberOfObjects (frm);
+ for (UInt16 objIndex = 0; objIndex < numObjects; ++objIndex)
+ {
+ FormObjectKind objType = ::FrmGetObjectType (frm, objIndex);
+
+ switch (objType)
+ {
+ case frmBitmapObj:
+ case frmLineObj:
+ case frmFrameObj:
+ case frmRectangleObj:
+ case frmLabelObj:
+ case frmTitleObj:
+ case frmPopupObj:
+ // do nothing for these
+ break;
+
+ default:
+ {
+ RectangleType bounds;
+ ::FrmGetObjectBounds (frm, objIndex, &bounds);
+
+ if (!::PrvFormObjectHasValidSize (frm, objType, objIndex, bounds) ||
+ ::PrvFormObjectIsOffscreen (bounds, winWidth, winHeight) ||
+ !::PrvFormObjectIsUsable (frm, objIndex, objType))
+ {
+ break;
+ }
+ else
+ {
+ okObjects.push_back (objIndex);
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PinRectInRect
+// ---------------------------------------------------------------------------
+
+Bool PinRectInRect (EmRect& inner, const EmRect& outer)
+{
+ // Do this in a way such that if the incoming rectangle is
+ // taller or wider than gdRect that we ensure we see the
+ // top and left.
+
+ Bool result = false;
+
+ if (inner.fBottom > outer.fBottom)
+ {
+ inner.Offset (0, outer.fBottom - inner.fBottom); // Move it up
+ result = true;
+ }
+
+ if (inner.fRight > outer.fRight)
+ {
+ inner.Offset (outer.fRight - inner.fRight, 0); // Move it left
+ result = true;
+ }
+
+ if (inner.fTop < outer.fTop)
+ {
+ inner.Offset (0, outer.fTop - inner.fTop); // Move it down
+ result = true;
+ }
+
+ if (inner.fLeft < outer.fLeft)
+ {
+ inner.Offset (outer.fLeft - inner.fLeft, 0); // Move it right
+ result = true;
+ }
+
+ return result;
+}
+
+
+// For "data" databases, we look to see if they have the following structure
+// in their appInfo block. If so, we grab the icon and version string from here.
+// WARNING: This structure contains variable size fields and must be generated
+// and parsed at programmatically.
+#define dataAppInfoSignature 'lnch'
+#define dataAppInfoVersion 3 // current version of header
+
+#include "PalmPack.h"
+
+struct DataAppInfoType
+{
+ UInt32 signature; // must be 'lnch' (0x6C6E6338)
+ UInt16 hdrVersion; // version of this header - must be 3
+ UInt16 encVersion; // encoder version
+ UInt16 verStrWords; // length of version string array that
+ // follows in 16-bit words.
+ //UInt8 verStr[verStrWords]; // 0 terminated version string with
+ // possible extra NULL byte at end for
+ // padding
+
+ //--- The title is only present in version 2 or later
+ UInt16 titleWords; // length of title string array that follows
+ // in 16-bit words.
+ //UInt8 title[titleWords]; // 0 terminated title string with possible
+ // extra NULL at end for padding.
+
+
+ UInt16 iconWords; // length of icon data that follows in 16-bit
+ // words.
+ //UInt8 icon[iconWords]; // icon in "BitmapType" format with possible NULL
+ // byte at end for even UInt16 padding
+ UInt16 smIconWords; // length of small icon data that follows in
+ // 16-bit words
+ //UInt8 smIcon[smIconWords]; // small icon in "BitmapType" format with
+ // possible NULL byte at end for even UInt16
+ // padding
+ //--------- Version 2 Fields ------------
+};
+
+// Size of appInfo block.
+#define dataAppInfoVersionSize (sizeof(DataAppInfoType))
+
+#include "PalmPackPop.h"
+
+
+/***********************************************************************
+ *
+ * FUNCTION: IsExecutable
+ *
+ * DESCRIPTION: Returns whether or not the given database contains an
+ * application in which case we want to present only
+ * the database with the most recent version number (in
+ * case there's more than one database with this one's
+ * type and creator).
+ *
+ * PARAMETERS: dbType - type of the database
+ *
+ * dbCreator - creator signature of the database
+ *
+ * dbAttrs - attributes of the database
+ *
+ * RETURNED: True if this database is an executable.
+ *
+ ***********************************************************************/
+
+Bool IsExecutable (UInt32 dbType, UInt32 dbCreator, UInt16 dbAttrs)
+{
+ UNUSED_PARAM(dbCreator)
+ UNUSED_PARAM(dbAttrs)
+
+ if (dbType == sysFileTApplication)
+ return true;
+
+ if (dbType == sysFileTPanel)
+ return true;
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: IsVisible
+ *
+ * DESCRIPTION: Returns whether or not the given database represents
+ * an item we want to display.
+ *
+ * PARAMETERS: dbType - type of the database
+ *
+ * dbCreator - creator signature of the database
+ *
+ * dbAttrs - attributes of the database
+ *
+ * RETURNED: True if we should include this database in our list.
+ *
+ ***********************************************************************/
+
+Bool IsVisible (UInt32 dbType, UInt32 dbCreator, UInt16 dbAttrs)
+{
+ UNUSED_PARAM(dbCreator)
+
+ // Don't show anything concerning the Launcher
+ // (That comment and the following commented out code was from the
+ // Launcher application. I've take it out so that we can run
+ // Gremlins over the Launcher).
+// if (dbCreator == sysFileCLauncher)
+// return false;
+
+ // The following test can come and go. Currently, it's here
+ // so that things like Clipper don't show up in the list (just
+ // as it doesn't show up in the Launcher). However, there may
+ // be time when we want to show it. An example would be in
+ // an experiemental version of the New Gremlin dialog that
+ // separated apps and documents. Selecting an app in one list
+ // would display a list of its documents in the other list. In
+ // that case, we'd need to show clipper in order to be able to
+ // display its documents.
+
+ // OK, the test is now gone. From Scott Johnson:
+ //
+ // The New Gremlin list doesn't show apps with the dmHdrAttrHidden attribute.
+ // This is a problem for mine, which is a sort of runtime forms engine. The
+ // runtime is a hidden app and the user-built apps are visible. The user app
+ // launches by just doing an app switch to the runtime. (Sort of a launchable
+ // database concept for pre-3.2 systems.) To Gremlin this, both apps need to
+ // be selected in the New Gremlin list. But the hidden one isn't shown. Oops.
+
+
+// if (dbAttrs & dmHdrAttrHidden)
+// return false;
+
+ if (dbAttrs & dmHdrAttrLaunchableData)
+ return true;
+
+ if (dbType == sysFileTApplication)
+ return true;
+
+ if (dbType == sysFileTPanel)
+ return true;
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetLoadableFileList
+ *
+ * DESCRIPTION: Scan the given directory for files that can be loaded
+ * into the Palm OS environment and add them to the
+ * given collection object. Loadable files are PRCs,
+ * PDBs, and PQAs.
+ *
+ * PARAMETERS: directoryName - name of the directory to search.
+ * This directory is assumed to be in the emulator's
+ * containing directory.
+ *
+ * fileList - collection to receive the found files.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void GetLoadableFileList (string directoryName, EmFileRefList& fileList)
+{
+ // Get the application's directory.
+
+ EmDirRef poserDir = EmDirRef::GetEmulatorDirectory ();
+
+ // Get the directory we're asked to look into.
+
+ EmDirRef searchDir (poserDir, directoryName);
+ if (!searchDir.Exists ())
+ return;
+
+ // Get all of its children.
+
+ EmFileRefList children;
+ searchDir.GetChildren (&children, NULL);
+
+ // Filter for the types that we want.
+
+ EmFileRefList::iterator iter = children.begin ();
+ while (iter != children.end ())
+ {
+ if (iter->IsType (kFileTypePalmApp) ||
+ iter->IsType (kFileTypePalmDB) ||
+ iter->IsType (kFileTypePalmQA))
+ {
+ fileList.push_back (*iter);
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetFileContents
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void GetFileContents (const EmFileRef& file, Chunk& contents)
+{
+ EmStreamFile stream (file, kOpenExistingForRead);
+ int32 length = stream.GetLength ();
+
+ contents.SetLength (length);
+
+ stream.GetBytes (contents.GetPointer (), length);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: AppGetExtraInfo
+ *
+ * DESCRIPTION: Returns additional information on the application. This
+ * information is usually pretty expensive to get, so we
+ * defer getting it until as late as possible.
+ *
+ * This function is derived from one in the Launcher with
+ * the same name. That function returned a lot more
+ * information. This one has been simplified to return
+ * only the application's (or special database's) name.
+ *
+ * PARAMETERS: infoP - pointer to the DatabaseInfo struct for the application
+ * we need to get more information on.
+ *
+ * RETURNED: Any errors encountered while processing this request.
+ * The requested information is returned back in the DatabaseInfo
+ * struct.
+ *
+ ***********************************************************************/
+
+static Err AppGetExtraInfo (DatabaseInfo* infoP)
+{
+ Err err = errNone;
+
+ infoP->name[0] = 0;
+
+ //====================================================================
+ // If it's a resource database, we must open it to get the appName
+ //====================================================================
+ if (infoP->dbAttrs & dmHdrAttrResDB)
+ {
+ DmOpenRef appDB = NULL;
+ MemHandle strH;
+
+ // Open database
+ appDB = DmOpenDatabase (infoP->cardNo, infoP->dbID, dmModeReadOnly);
+ if (appDB == NULL)
+ {
+ err = DmGetLastErr ();
+ goto Exit;
+ }
+
+ //...............................
+ // Get app name if we don't already have it.
+ //...............................
+ strH = DmGet1Resource (ainRsc, ainID);
+
+ // copy launcher name, if present
+ if (strH != NULL)
+ {
+ emuptr strP = (emuptr) MemHandleLock (strH);
+ EmMem_strcpy (infoP->name, strP);
+ MemHandleUnlock (strH);
+ DmReleaseResource (strH);
+ }
+
+ ::DmCloseDatabase (appDB);
+ } // if resource database
+
+ //====================================================================
+ // If it's a record database, we look in the appInfo block.
+ //====================================================================
+ else
+ {
+ LocalID appInfoID;
+ MemHandle appInfoH = 0;
+ MemPtr appInfoP = 0;
+ emuptr specialInfoP;
+ emuptr bP;
+ UInt16 verStrWords, titleWords;
+
+ // Look for app info
+ err = DmDatabaseInfo (infoP->cardNo, infoP->dbID, 0,
+ 0, 0, 0, 0, 0, 0, &appInfoID, 0, 0, 0);
+
+ if (!err && appInfoID)
+ {
+ // Get handle (if RAM based) and ptr to app Info
+ if (MemLocalIDKind (appInfoID) == memIDHandle)
+ {
+ appInfoH = (MemHandle) MemLocalIDToGlobal (appInfoID, infoP->cardNo);
+ appInfoP = MemHandleLock (appInfoH);
+ }
+ else
+ {
+ appInfoP = MemLocalIDToGlobal(appInfoID, infoP->cardNo);
+ }
+
+ // See if this is the special launcher info and if so, get the icons
+ // out of that.
+ specialInfoP = (emuptr) appInfoP;
+ DataAppInfoType specialInfo;
+
+ specialInfo.signature = EmMemGet32 (specialInfoP + offsetof (DataAppInfoType, signature));
+ specialInfo.hdrVersion = EmMemGet16 (specialInfoP + offsetof (DataAppInfoType, hdrVersion));
+ specialInfo.encVersion = EmMemGet16 (specialInfoP + offsetof (DataAppInfoType, encVersion));
+
+ if (MemPtrSize (appInfoP) >= dataAppInfoVersionSize &&
+ specialInfo.signature == dataAppInfoSignature &&
+ specialInfo.hdrVersion >= dataAppInfoVersion)
+ {
+ // Get ptr to version string
+ bP = specialInfoP + offsetof (DataAppInfoType, verStrWords);
+ verStrWords = EmMemGet16 (bP);
+ bP += sizeof(UInt16);
+ bP += verStrWords * sizeof(UInt16);
+
+ // Get ptr to name string
+ titleWords = EmMemGet16 (bP);
+ bP += sizeof(UInt16);
+ if (titleWords)
+ {
+ EmMem_strcpy (infoP->name, bP);
+ }
+ } // If valid appInfo
+
+ if (appInfoH)
+ {
+ MemHandleUnlock(appInfoH);
+ }
+ } // if (!err && appInfoID)
+ } // Record Database.
+
+Exit:
+
+ // If no luck getting the visible name, put in default
+ if (infoP->name[0] == 0)
+ {
+ // Get DB name
+ strcpy (infoP->name, infoP->dbName);
+ }
+
+ return err;
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: AppCompareDataBaseNames
+ *
+ * DESCRIPTION: sort() callback function to sort entries by name.
+ *
+ * PARAMETERS: a, b - references to two DatabaseInfo's to compare.
+ *
+ * RETURNED: True if a should appear before b, false otherwise.
+ *
+ ***********************************************************************/
+
+static bool AppCompareDataBaseNames (const DatabaseInfo& a, const DatabaseInfo& b)
+{
+ return _stricmp (a.name, b.name) < 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetDatabases
+ *
+ * DESCRIPTION: Collects the list of entries that should be displayed
+ * in the New Gremlin dialog box.
+ *
+ * This function is derived from the Launcher function
+ * AppCreateDataBaseList, as rewritten by Ron for the
+ * 3.2 ROMs.
+ *
+ * PARAMETERS: dbList -- collection into which we store the found
+ * DatabaseInfo entries.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void GetDatabases (DatabaseInfoList& dbList, Bool applicationsOnly)
+{
+ UInt16 cardNo;
+ UInt16 numCards;
+ UInt16 numDBs;
+ Int16 dbIndex; // UInt16 results in a bug
+ LocalID dbID;
+ Err err = errNone;
+ DatabaseInfo dbInfo;
+ Boolean needToAddNewEntry;
+
+ //=======================================================================
+ // Cycle through all databases in the ROM and RAM and place them into our list.
+ //=======================================================================
+ numCards = ::MemNumCards ();
+ for (cardNo = 0; cardNo < numCards; ++cardNo)
+ {
+ numDBs = ::DmNumDatabases (cardNo);
+
+ //---------------------------------------------------------------
+ // Loop through databases on this card, DmGetDatabase() returns ROM
+ // databases first, followed by RAM databases.
+ //---------------------------------------------------------------
+ for (dbIndex = 0; dbIndex < numDBs; ++dbIndex)
+ {
+ //--------------------------------------------------------
+ // Get info on the next database and see if it should be visible.
+ //--------------------------------------------------------
+ dbID = ::DmGetDatabase (cardNo, dbIndex);
+ err = ::DmDatabaseInfo (
+ cardNo,
+ dbID,
+ dbInfo.dbName, /*nameP*/
+ &dbInfo.dbAttrs,
+ &dbInfo.version,
+ NULL, /*create date*/
+ &dbInfo.modDate,
+ NULL, /*backup date*/
+ NULL, /*modNum*/
+ NULL, /*appInfoID*/
+ NULL, /*sortInfoID*/
+ &dbInfo.type,
+ &dbInfo.creator);
+
+ Errors::ThrowIfPalmError (err);
+
+
+ // If it's not supposed to be visible, skip it
+ if (applicationsOnly && !::IsVisible (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs))
+ {
+ continue;
+ }
+
+ //--------------------------------------------------------------
+ // Save info on this database
+ //--------------------------------------------------------------
+ dbInfo.dbID = dbID;
+ dbInfo.cardNo = cardNo;
+
+ //--------------------------------------------------------------
+ // If it's an executable, make sure it's the most recent version in our
+ // list
+ //--------------------------------------------------------------
+ needToAddNewEntry = true;
+ if (applicationsOnly && ::IsExecutable (dbInfo.type, dbInfo.creator, dbInfo.dbAttrs))
+ {
+ // Search for database of same type and creator and check version
+ DatabaseInfoList::iterator thisIter = dbList.begin ();
+ while (thisIter != dbList.end ())
+ {
+ if ((*thisIter).type == dbInfo.type &&
+ (*thisIter).creator == dbInfo.creator)
+ {
+ // If this new one is a newer or same version than the previous one,
+ // replace the previous entry. Checking for == version allows RAM
+ // executables to override ROM ones.
+ if (dbInfo.version >= (*thisIter).version)
+ {
+ ::AppGetExtraInfo (&dbInfo);
+ *thisIter = dbInfo;
+ }
+
+ // Since there's already an item with this type/creator
+ // already in the list, there's no need to add another one.
+ needToAddNewEntry = false;
+
+ break;
+ }
+
+ ++thisIter;
+ }
+ }
+
+
+ //--------------------------------------------------------------
+ // If we still need to add this entry, do so now.
+ //--------------------------------------------------------------
+ if (needToAddNewEntry)
+ {
+ ::AppGetExtraInfo (&dbInfo);
+ dbList.push_back (dbInfo);
+ }
+ } // for (dbIndex = 0; dbIndex < numDBs; dbIndex++)
+ } // for (cardNo = 0; cardNo < MemNumCards(); cardNo++)
+
+
+ //===========================================================================
+ // Sort the list by name
+ //===========================================================================
+ // Sort the databases by their name.
+ sort (dbList.begin (), dbList.end (), AppCompareDataBaseNames);
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: InstallCalibrationInfo
+ *
+ * DESCRIPTION: Sets the pen calibration info to be "perfect": no
+ * translation or scaling.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void InstallCalibrationInfo (void)
+{
+ // Open the preferences database. If the new version of PrefOpenPreferenceDB
+ // exists, then call it. Otherwise, call the old version. We can't just
+ // unconditionally call the old version, as that has a bug in the newer
+ // ROMs that causes it to create the database incorrectly if it doesn't
+ // already exist.
+
+ DmOpenRef dbP;
+ if (EmLowMem::TrapExists (sysTrapPrefOpenPreferenceDB))
+ dbP = ::PrefOpenPreferenceDB (false);
+ else
+ dbP = ::PrefOpenPreferenceDBV10 ();
+
+ if (dbP)
+ {
+ // Get the calibration information.
+
+ MemHandle resourceH = ::DmGetResource (sysResTSysPref, sysResIDSysPrefCalibration);
+
+ // If that information doesn't exist, go about creating it.
+
+ if (!resourceH)
+ {
+ resourceH = ::DmNewResource (dbP, sysResTSysPref, sysResIDSysPrefCalibration,
+ 4 * sizeof(UInt16));
+ }
+
+ if (resourceH)
+ {
+ // Write in the calibration information. The information has the
+ // following format and values:
+ //
+ // scaleX : 256
+ // scaleY : 256
+ // offsetX : 0
+ // offsetY : 0
+ //
+ // We encode that data here as a string of bytes to avoid endian problems.
+
+ MemPtr resP = ::MemHandleLock (resourceH);
+
+ unsigned char data[] = { 1, 0, 1, 0, 0, 0, 0, 0 };
+
+ ::DmWrite (resP, 0, data, 4 * sizeof (UInt16));
+
+ ::MemHandleUnlock (resourceH);
+ ::DmReleaseResource (resourceH);
+ }
+
+ ::DmCloseDatabase (dbP);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ResetCalibrationInfo
+ *
+ * DESCRIPTION: Sets the pen calibration info to be "perfect": no
+ * translation or scaling.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void ResetCalibrationInfo (void)
+{
+ // Reset the pen calibration info by calling PenCalibrate with the right
+ // parameters. Unfortunately, due presumably to division rounding errors,
+ // doing this just once doesn't necessarily get the scaling and offset
+ // values exactly. However, making a few calls to PenCalibrate seems
+ // to get us to home in on the perfect calibration values.
+
+ Bool perfect = false;
+
+ for (int kk = 0; kk < 3 && !perfect; ++kk)
+ {
+ #define target0X 10 // top left
+ #define target0Y 10
+ #define target1X (160-10) // bottom right
+ #define target1Y (160-10)
+
+ Err err;
+ PointType digPoints[2];
+ PointType scrPoints[2];
+
+ scrPoints[0].x = target0X;
+ scrPoints[0].y = target0Y;
+ scrPoints[1].x = target1X;
+ scrPoints[1].y = target1Y;
+
+ digPoints[0].x = 0x100 - target0X;
+ digPoints[0].y = 0x100 - target0Y;
+ digPoints[1].x = 0x100 - target1X;
+ digPoints[1].y = 0x100 - target1Y;
+
+ err = ::PenRawToScreen(&digPoints[0]);
+ err = ::PenRawToScreen(&digPoints[1]);
+ err = ::PenCalibrate(&digPoints[0], &digPoints[1], &scrPoints[0], &scrPoints[1]);
+
+ DmOpenRef dbP;
+ if (EmLowMem::TrapExists (sysTrapPrefOpenPreferenceDB))
+ dbP = ::PrefOpenPreferenceDB (false);
+ else
+ dbP = ::PrefOpenPreferenceDBV10 ();
+
+ if (dbP)
+ {
+ MemHandle resourceH = ::DmGetResource (sysResTSysPref, sysResIDSysPrefCalibration);
+
+ if (resourceH)
+ {
+ MemPtr resP = ::MemHandleLock (resourceH);
+ unsigned char perfect_pattern[] = { 1, 0, 1, 0, 0, 0, 0, 0 };
+
+ perfect = (EmMem_memcmp ((void*) perfect_pattern, (emuptr) resP, 8) == 0);
+
+ ::MemHandleUnlock (resourceH);
+ ::DmReleaseResource (resourceH);
+ }
+
+ ::DmCloseDatabase (dbP);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ResetClocks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void ResetClocks (void)
+{
+ EmHAL::ResetTimer ();
+
+ EmLowMem_SetGlobal (hwrCurTicks, 0);
+
+ emuptr sysKernelDataP = EmLowMem_GetGlobal (sysKernelDataP);
+ EmMemPut32 (sysKernelDataP + 0x20, 0);
+
+ EmHAL::ResetRTC ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SetHotSyncUserName
+ *
+ * DESCRIPTION: Calls the Data Link Manager to set the user's HotSync
+ * name. Many applications key off this name for things
+ * like copy protection, so we set this value when they
+ * boot up.
+ *
+ * PARAMETERS: userNameP - the user's name.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+const UInt16 kMagicRefNum = 0x666; // See comments in HtalLibSendReply.
+
+void SetHotSyncUserName (const char* userNameP)
+{
+ if (EmLowMem::GetTrapAddress (sysTrapDlkDispatchRequest) == EmMemNULL)
+ return;
+
+ if (!userNameP)
+ return;
+
+ size_t userNameLen = strlen (userNameP) + 1;
+
+ // If the name is too long, just return. This should really only
+ // happen if the user hand-edits the preference file to contain
+ // a name that's too long. The Preferences dialog box handler
+ // checks as well, so the name shouldn't get too long from that path.
+
+ if (userNameLen > dlkMaxUserNameLength + 1)
+ return;
+
+ // We need to prepare a command block for the DataLink Manager.
+ // Define one large enough to hold all the data we'll pass in.
+ //
+ // The format of the data block is as follows:
+ //
+ // [byte] DlpReqHeaderType.id : Command request number (== dlpWriteUserInfo)
+ // [byte] DlpReqHeaderType.argc : # of arguments for this command (== 1)
+ //
+ // [byte] DlpTinyArgWrapperType.bID : ID of first argument (== dlpWriteUserInfoReqArgID)
+ // [byte] DlpTinyArgWrapperType.bSize : Size in bytes of first argument (== whatever)
+ //
+ // [long] DlpWriteUserInfoReqHdrType.userID : Not used here - set to zero
+ // [long] DlpWriteUserInfoReqHdrType.viewerID : Not used here - set to zero
+ // [long] DlpWriteUserInfoReqHdrType.lastSyncPC : Not used here - set to zero
+ // [8byt] DlpWriteUserInfoReqHdrType.lastSyncDate : Not used here - set to zero
+ // [long] DlpWriteUserInfoReqHdrType.modFlags : Bits saying what values are being set
+ // [byte] DlpWriteUserInfoReqHdrType.userNameLen : Length of user name + NULL
+ //
+ // [str ] userName
+
+ char buffer[ sizeof (DlpReqHeaderType) +
+ sizeof (DlpTinyArgWrapperType) +
+ sizeof (DlpWriteUserInfoReqHdrType) +
+ dlpMaxUserNameSize];
+
+ // Get handy pointers to all of the above.
+ DlpReqHeaderType* reqHdr = (DlpReqHeaderType*) buffer;
+ DlpTinyArgWrapperType* reqWrapper = (DlpTinyArgWrapperType*) (((char*) reqHdr) + sizeof(DlpReqHeaderType));
+ DlpWriteUserInfoReqHdrType* reqArgHdr = (DlpWriteUserInfoReqHdrType*) (((char*) reqWrapper) + sizeof(DlpTinyArgWrapperType));
+ char* reqName = ((char*) reqArgHdr) + sizeof (DlpWriteUserInfoReqHdrType);
+
+ // Fill in request header
+ reqHdr->id = dlpWriteUserInfo;
+ reqHdr->argc = 1;
+
+ // Fill in the request arg wrapper
+ reqWrapper->bID = (UInt8) dlpWriteUserInfoReqArgID;
+ reqWrapper->bSize = (UInt8) (sizeof (*reqArgHdr) + userNameLen);
+
+ // Fill in request arg header
+ reqArgHdr->modFlags = dlpUserInfoModName;
+ reqArgHdr->userNameLen = userNameLen;
+
+ // Copy in the user name.
+ strcpy (reqName, userNameP);
+
+ // Build up a session block to hold the command block.
+ DlkServerSessionType session;
+ memset (&session, 0, sizeof (session));
+ session.htalLibRefNum = kMagicRefNum; // See comments in HtalLibSendReply.
+ session.gotCommand = true;
+ session.cmdLen = sizeof (buffer);
+ session.cmdP = buffer;
+
+ // For simplicity, byteswap here so that we don't have to reparse all
+ // that above data in DlkDispatchRequest.
+
+ Canonical (reqHdr->id);
+ Canonical (reqHdr->argc);
+
+ Canonical (reqWrapper->bID);
+ Canonical (reqWrapper->bSize);
+
+ Canonical (reqArgHdr->modFlags);
+ Canonical (reqArgHdr->userNameLen);
+
+ // Patch up cmdP and map in the buffer it points to.
+
+ StMemoryMapper mapper (session.cmdP, session.cmdLen);
+ session.cmdP = (void*) EmBankMapped::GetEmulatedAddress (session.cmdP);
+
+ // Finally, install the name.
+ /*Err err =*/ DlkDispatchRequest (&session);
+
+#if 0
+ ULong lastSyncDate;
+ char userName[dlkUserNameBufSize];
+ Err err = DlkGetSyncInfo(0/*succSyncDateP*/, &lastSyncDate, 0/*syncStateP*/,
+ userName, 0/*logBufP*/, 0/*logLenP*/);
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SeparateList
+ *
+ * DESCRIPTION: Break up a comma-delimited list of items, returning the
+ * pieces in a StringList.
+ *
+ * PARAMETERS: stringList - the StringList to receive the broken-up
+ * pieces of the comma-delimited list. This collection
+ * is *not* first cleared out, so it's possible to add
+ * to the collection with this function.
+ *
+ * str - the string containing the comma-delimited items.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SeparateList (StringList& stringList, string str, char delimiter)
+{
+ string::size_type offset;
+
+ while ((offset = str.find (delimiter)) != string::npos)
+ {
+ string nextElement = str.substr (0, offset);
+ str = str.substr (offset + 1);
+ stringList.push_back (nextElement);
+ }
+
+ stringList.push_back (str);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RunLengthEncode
+ *
+ * DESCRIPTION: Pack data according to the scheme used in QuickDraw's
+ * PackBits routine. This is the format, according to
+ * Macintosh Technote 1023:
+ *
+ * The first byte is a flag-counter byte that specifies
+ * whether or not the following data is packed, and the
+ * number of bytes involved.
+ *
+ * If this first byte is a negative number, the following
+ * data is packed and the number is a zero-based count of
+ * the number of times the data byte repeats when expanded.
+ * There is one data byte following the flag-counter byte
+ * in packed data; the byte after the data byte is the next
+ * flag-counter byte.
+ *
+ * If the flag-counter byte is a positive number, then the
+ * following data is unpacked and the number is a zero-based
+ * count of the number of incompressible data bytes that
+ * follow. There are (flag-counter+1) data bytes following
+ * the flag-counter byte. The byte after the last data byte
+ * is the next flag-counter byte.
+ *
+ * Consider the following example:
+ *
+ * Unpacked data:
+ *
+ * AA AA AA 80 00 2A AA AA AA AA 80 00
+ * 2A 22 AA AA AA AA AA AA AA AA AA AA
+ *
+ * After being packed by PackBits:
+ *
+ * FE AA ; (-(-2)+1) = 3 bytes of the pattern $AA
+ * 02 80 00 2A ; (2)+1 = 3 bytes of discrete data
+ * FD AA ; (-(-3)+1) = 4 bytes of the pattern $AA
+ * 03 80 00 2A 22 ; (3)+1 = 4 bytes of discrete data
+ * F7 AA ; (-(-9)+1) = 10 bytes of the pattern $AA
+ *
+ * or
+ *
+ * FE AA 02 80 00 2A FD AA 03 80 00 2A 22 F7 AA
+ * * * * * *
+ *
+ * The bytes with the asterisk (*) under them are the
+ * flag-counter bytes. PackBits packs the data only when
+ * there are three or more consecutive bytes with the same
+ * data; otherwise it just copies the data byte for byte
+ * (and adds the count byte).
+ *
+ * PARAMETERS: srcPP - pointer to the pointer to the source bytes. The
+ * referenced pointer gets udpated to point past the
+ * last byte included the packed output.
+ *
+ * dstPP - pointer to the pointer to the destination buffer.
+ * The referenced pointer gets updated to point past
+ * the last byte stored in the output buffer.
+ *
+ * srcBytes - length of the buffer referenced by srcPP
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void RunLengthEncode (void** srcPP, void** dstPP, long srcBytes, long dstBytes)
+{
+ UNUSED_PARAM(dstBytes)
+
+ enum { kBeginRun, kRepeatRun, kCopyRun };
+
+ uint8* srcP = (uint8*) *srcPP;
+ uint8* dstP = (uint8*) *dstPP;
+ uint8* opP = NULL;
+ long sample[3] = { -1, -1, -1 }; // Type must be > uint8 so that it can hold -1.
+ long opCount = 0;
+ long state = kBeginRun;
+
+ for (srcBytes += 1; srcBytes >= 0; --srcBytes)
+ {
+ sample[0] = sample[1];
+ sample[1] = sample[2];
+ sample[2] = -1;
+
+ if (srcBytes > 1)
+ {
+ sample[2] = *srcP++;
+ }
+
+ switch (state)
+ {
+ case kBeginRun: // Determine whether or not to pack the bytes
+ if (sample[2] == sample[0] && sample[2] == sample[1])
+ {
+ state = kRepeatRun;
+ opCount = -2;
+ }
+ else if (sample[0] != -1)
+ {
+ state = kCopyRun;
+ opCount = 0;
+ opP = dstP++;
+ *dstP++ = (uint8) sample[0];
+ }
+ break;
+
+ case kRepeatRun: // We're packing bytes
+ if (sample[2] == sample[1])
+ {
+ --opCount;
+
+ if (opCount > -127)
+ {
+ break;
+ }
+
+ sample[2] = -1;
+ }
+
+ sample[1] = -1;
+ *dstP++ = (uint8) opCount;
+ *dstP++ = (uint8) sample[0];
+ state = kBeginRun;
+ break;
+
+ case kCopyRun: // We're copying bytes
+ if (sample[0] != sample[1] || sample[0] != sample[2])
+ {
+ *dstP++ = (uint8) sample[0];
+ ++opCount;
+
+ if (opCount >= 127)
+ {
+ *opP = (uint8) opCount;
+ state = kBeginRun;
+ break;
+ }
+ }
+ else
+ {
+ *opP = (uint8) opCount;
+ state = kRepeatRun;
+ opCount = -2;
+ }
+ break;
+
+ default:
+ EmAssert (false);
+ break;
+ }
+ }
+
+ if (state == kCopyRun)
+ {
+ *opP = (uint8) opCount;
+ }
+
+ *srcPP = (void*) srcP;
+ *dstPP = (void*) dstP;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RunLengthDecode
+ *
+ * DESCRIPTION: Decode the data packed by RunLengthEncode.
+ *
+ * PARAMETERS: srcPP -
+ *
+ * dstPP -
+ *
+ * dstBytes -
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void RunLengthDecode (void** srcPP, void** dstPP, long srcBytes, long dstBytes)
+{
+ UNUSED_PARAM(srcBytes)
+
+ int8* srcP = (int8*) *srcPP;
+ int8* dstP = (int8*) *dstPP;
+ int8* limitP = dstP + dstBytes;
+
+ while (dstP < limitP)
+ {
+ int op = *srcP++;
+ if (op == -128)
+ {
+ // Nothing
+ }
+ else if (op >= 0)
+ {
+ int count = op + 1;
+ do
+ {
+ *dstP++ = *srcP++;
+ } while (--count);
+ }
+ else
+ {
+ int count = 1 - op;
+ uint8 fillData = *srcP++;
+ do
+ {
+ *dstP++ = fillData;
+ } while (--count);
+ }
+ }
+
+ *srcPP = (void*) srcP;
+ *dstPP = (void*) dstP;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RunLengthWorstSize
+ *
+ * DESCRIPTION: Calculate the largest buffer needed when packing a
+ * buffer "srcBytes" long. The algorithm is based on
+ * that found in Macintosh Technote 1023.
+ *
+ * PARAMETERS: srcBytes - number of bytes in the buffer to be encoded.
+ *
+ * RETURNED: Largest buffer size needed to encode source buffer.
+ *
+ ***********************************************************************/
+
+long RunLengthWorstSize (long srcBytes)
+{
+ long maxDestBytes = (srcBytes + (srcBytes + 126) / 127);
+
+ return maxDestBytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GzipEncode
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: srcPP - pointer to the pointer to the source bytes. The
+ * referenced pointer gets udpated to point past the
+ * last byte included the packed output.
+ *
+ * dstPP - pointer to the pointer to the destination buffer.
+ * The referenced pointer gets updated to point past
+ * the last byte stored in the output buffer.
+ *
+ * srcBytes - length of the buffer referenced by srcPP
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void GzipEncode (void** srcPP, void** dstPP, long srcBytes, long dstBytes)
+{
+ gSrcP = *srcPP;
+ gDstP = *dstPP;
+ gSrcBytes = srcBytes;
+ gDstBytes = dstBytes;
+ gSrcOffset = 0;
+ gDstOffset = 0;
+
+ bytes_in = srcBytes; // (for gzip internal debugging)
+
+ ush attr = 0; /* ascii/binary flag */
+ ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
+ int method;
+
+ clear_bufs ();
+
+ read_buf = &::PrvGzipReadProc;
+ write_buf_proc = &::PrvGzipWriteProc;
+
+ bi_init (NO_FILE);
+ ct_init (&attr, &method);
+ lm_init (level, &deflate_flags);
+
+ deflate ();
+
+ // Perform a put_byte(0) to pad out the
+ // compressed buffer. gzip apparently can skid off the
+ // end of the compressed data when inflating it, so we need
+ // an extra zero.
+
+ put_byte (0);
+
+ flush_outbuf ();
+
+ *srcPP = ((char*) gSrcP) + gSrcOffset;
+ *dstPP = ((char*) gDstP) + gDstOffset;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GzipDecode
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: srcPP -
+ *
+ * dstPP -
+ *
+ * dstBytes -
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void GzipDecode (void** srcPP, void** dstPP, long srcBytes, long dstBytes)
+{
+ gSrcP = *srcPP;
+ gDstP = *dstPP;
+ gSrcBytes = srcBytes;
+ gDstBytes = dstBytes;
+ gSrcOffset = 0;
+ gDstOffset = 0;
+
+ clear_bufs ();
+
+ read_buf = &::PrvGzipReadProc;
+ write_buf_proc = &::PrvGzipWriteProc;
+
+ inflate ();
+
+ *srcPP = ((char*) gSrcP) + gSrcOffset;
+ *dstPP = ((char*) gDstP) + gDstOffset;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GzipWorstSize
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: srcBytes - number of bytes in the buffer to be encoded.
+ *
+ * RETURNED: Largest buffer size needed to encode source buffer.
+ *
+ ***********************************************************************/
+
+long GzipWorstSize (long srcBytes)
+{
+ long maxDestBytes = srcBytes * 2;
+
+ return maxDestBytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGzipReadProc
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+int PrvGzipReadProc (char* buf, unsigned size)
+{
+ if (gSrcOffset == gSrcBytes)
+ return EOF;
+
+ if (size > (unsigned) (gSrcBytes - gSrcOffset))
+ size = gSrcBytes - gSrcOffset;
+
+ if (size > 0)
+ {
+ memcpy (buf, ((char*) gSrcP) + gSrcOffset, size);
+ gSrcOffset += size;
+ }
+
+ return size;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGzipWriteProc
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+int PrvGzipWriteProc (char* buf, unsigned size)
+{
+ if (gDstOffset == gDstBytes)
+ return EOF;
+
+ if (size > (unsigned) (gDstBytes - gDstOffset))
+ size = gDstBytes - gDstOffset;
+
+ if (size > 0)
+ {
+ memcpy (((char*) gDstP) + gDstOffset, buf, size);
+ gDstOffset += size;
+ }
+
+ return size;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: StackCrawlStrings
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void StackCrawlStrings (const EmStackFrameList& stackCrawl, StringList& stackCrawlStrings)
+{
+ EmStackFrameList::const_iterator iter = stackCrawl.begin ();
+ while (iter != stackCrawl.end ())
+ {
+ // Get the function name.
+
+ char funcName[256] = {0};
+ ::FindFunctionName (iter->fAddressInFunction, funcName, NULL, NULL, 255);
+
+ // If we can't find the name, dummy one up.
+
+ if (strlen (funcName) == 0)
+ {
+ sprintf (funcName, "<Unknown @ 0x%08lX>", iter->fAddressInFunction);
+ }
+
+ stackCrawlStrings.push_back (string (funcName));
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: StackCrawlString
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+string StackCrawlString (const EmStackFrameList& stackCrawl, long maxLen, Bool includeFrameSize, emuptr oldStackLow)
+{
+ StringList strings;
+ ::StackCrawlStrings (stackCrawl, strings);
+
+ string stackCrawlString;
+
+ EmStackFrameList::const_iterator iter = stackCrawl.begin ();
+ StringList::const_iterator s_iter = strings.begin ();
+
+ while (iter != stackCrawl.end ())
+ {
+ // Catenate the function name to the built-up string.
+
+ if (iter != stackCrawl.begin ())
+ {
+ stackCrawlString += ", ";
+ }
+
+ stackCrawlString += *s_iter;
+
+ if (includeFrameSize)
+ {
+ // Get the stack size used by the function.
+
+ char stackSize[20];
+ sprintf (stackSize, "%ld", iter->fA6 - oldStackLow);
+
+ stackCrawlString += string ("(") + string (stackSize) + ")";
+ }
+
+ // If the string looks long enough, stop.
+
+ if (maxLen > 0 && (long) stackCrawlString.size () > maxLen)
+ {
+ stackCrawlString += "...";
+ break;
+ }
+
+ oldStackLow = iter->fA6;
+
+ ++iter;
+ ++s_iter;
+ }
+
+ return stackCrawlString;
+}
+
+#pragma mark -
+
+static int kBitCount[16] =
+{
+ 0, 1, 1, 2,
+ 1, 2, 2, 3,
+ 1, 2, 2, 3,
+ 2, 3, 3, 4
+};
+
+int CountBits (uint32 v)
+{
+ return kBitCount[ (v >> 0) & 0x0F ] +
+ kBitCount[ (v >> 4) & 0x0F ] +
+ kBitCount[ (v >> 8) & 0x0F ] +
+ kBitCount[ (v >> 12) & 0x0F ];
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NextPowerOf2
+ *
+ * DESCRIPTION: Calculates the next power of two above the given number
+ * If the given number is already a power of two, it is
+ * returned.
+ *
+ * PARAMETERS: n - probe number
+ *
+ * RETURNED: Next power of two above the probe number, or the number
+ * itself if it is a power of two.
+ *
+ ***********************************************************************/
+
+// Seven implementations! No waiting!
+
+uint32 NextPowerOf2 (uint32 n)
+{
+ // Smear down the upper 1 bit to all bits lower than it.
+
+ uint32 n2 = n;
+
+ n2 |= n2 >> 1;
+ n2 |= n2 >> 2;
+ n2 |= n2 >> 4;
+ n2 |= n2 >> 8;
+ n2 |= n2 >> 16;
+
+ // Now use itself to clear all the lower bits.
+
+ n2 &= ~(n2 >> 1);
+
+ // If n2 ends up being the same as what we started with, keep it.
+ // Otherwise, we need to bump it by a factor of two (round up).
+
+ if (n2 != n)
+ n2 <<= 1;
+
+ return n2;
+}
+
+
+#if 0
+uint32 NextPowerOf2 (uint32 n)
+{
+ uint32 startn = n;
+ uint32 prevn = 0;
+
+ while (n) // Loop until we're out of bits
+ {
+ prevn = n; // Remember what we're starting with. When "n"
+ // reaches zero, prevn will hold the previous value,
+ // which will have a single bit in it. Since we're
+ // whacking off bits from the bottom, this will be
+ // the highest bit.
+ n &= n - 1; // Mask off the low bit
+ }
+
+ // If prevn ends up being the same as what we started with, keep it.
+ // Otherwise, we need to bump it by a factor of two.
+
+ if (prevn != startn)
+ prevn <<= 1;
+
+ return prevn;
+}
+#endif
+
+
+#if 0
+ // This was my own first attempt. Pretty lame...
+
+uint32 NextPowerOf2 (uint32 x)
+{
+ // Figure out the next power-of-2 higher than or equal to 'x'. We do
+ // this by continually shifting x to the left until we get a '1' in
+ // the upper bit. At the same time, we shift 0x80000000 to the right.
+ // When we find that '1' in the upper bit, the shifted 0x80000000
+ // pattern should hold our power-of-two.
+ //
+ // That approach is good for finding the next power-of-2 higher than
+ // a given value, so in order to deal with the 'or equal to' part
+ // of the task, we decrement x by 1 before embarking on this adventure.
+ //
+ // This function'll fail for x == 0 or x == 1, as well x > 0x80000000,
+ // so handle those cases up front:
+
+ if (x > 0x80000000)
+ return -1;
+
+ if (x == 0 || x == 1)
+ return x;
+
+ --x;
+
+ unsigned long result = 0x80000000;
+ while (((x <<= 1) & 0x80000000) == 0) // check for the highest set bit.
+ result >>= 1;
+
+ return result;
+}
+#endif
+
+#if 0
+ // This one was posted to the net. Seems most reasonable.
+ // Fails when n == 0.
+uint32 HighBitNumber (uint32 n)
+{
+ uint32 i = (n & 0xffff0000) ? 16 : 0;
+
+ if ((n >>= i) & 0xff00)
+ {
+ i |= 8;
+ n >>= 8;
+ }
+
+ if (n & 0xf0)
+ {
+ i |= 4;
+ n >>= 4;
+ }
+
+ if (n & 0xc)
+ {
+ i |= 2;
+ n >>= 2;
+ }
+
+ return (i | (n >> 1));
+}
+#endif
+
+#if 0
+ // This one was posted to the net. Uses a loop; not quite as effecient.
+ // Seems pretty buggy, since it doesn't work for x == 0, 1, or 2.
+uint32 HighBitNumber (uint32 x)
+{
+ unsigned long mask=2, numBits=1;
+ while (mask < x)
+ {
+ mask += mask;
+ numBits++;
+ }
+
+ return numBits;
+}
+#endif
+
+#if 0
+ // This one was posted to the net. Makes up to 5 comparisons, which is
+ // more than the one we're using.
+uint32 HighBitNumber (uint32 x)
+{
+#define hi_bit(n)\
+ ((n)>=1<<16?(n)>=1<<24?(n)>=1<<28?(n)>=1<<30?(n)>=1<<31?31:30:(n)>=1<<29?\
+ 29:28:(n)>=1<<26?(n)>=1<<27?27:26:(n)>=1<<25?25:24:(n)>=1<<20?(n)>=1<<22?\
+ (n)>=1<<23?23:22:(n)>=1<<21?21:20:(n)>=1<<18?(n)>=1<<19?19:18:(n)>=1<<17?\
+ 17:16:(n)>=1<<8?(n)>=1<<12?(n)>=1<<14?(n)>=1<<15?15:14:(n)>=1<<13?13:12:(\
+ n)>=1<<10?(n)>=1<<11?11:10:(n)>=1<<9?9:8:(n)>=1<<4?(n)>=1<<6?(n)>=1<<7?7:\
+ 6:(n)>=1<<5?5:4:(n)>=1<<2?(n)>=1<<3?3:2:(n)>=1<<1?1:(n)>=1<<0?0:-1)
+
+ return hi_bit (x);
+}
+#endif
+
+#if 0
+ // This one was posted to the net (by the same guy posting that macro).
+ // Pretty neat until that divide by 37.
+uint32 HighBitNumber (uint32 x)
+{
+ static const int t[] =
+ {
+ -1, 0, 25, 1, 22, 26, 31, 2, 15, 23, 29, 27, 10, -1, 12, 3, 6, 16,
+ -1, 24, 21, 30, 14, 28, 9, 11, 5, -1, 20, 13, 8, 4, 19, 7, 18, 17
+ };
+
+ return t[(n |= n >> 1, n |= n >> 2, n |= n >> 4, n |= n >> 8, n |= n >> 16) % 37];
+}
+#endif
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DateToDays
+ *
+ * DESCRIPTION: Convert a year, month, and day into the number of days
+ * since 1/1/1904.
+ *
+ * Parameters are not checked for valid dates, so it's
+ * possible to feed in things like March 35, 1958. This
+ * function also assumes that year is at least 1904, and
+ * will only work up until 2040 or so.
+ *
+ * PARAMETERS: year - full year
+ *
+ * month - 1..12
+ *
+ * day - 1..31
+ *
+ * RETURNED: Number of days since 1/1/1904.
+ *
+ ***********************************************************************/
+
+uint32 DateToDays (uint32 year, uint32 month, uint32 day)
+{
+ static const int month2days[] =
+ {
+ 0, 31, 59, 90, 120, 151,
+ 181, 212, 243, 273, 304, 334
+ };
+
+
+ // Normalize the values.
+
+ year -= 1904;
+ month -= 1;
+ day -= 1;
+
+ // Not counting any possible leap-day in the current year, figure out
+ // the number of days between now and 1/1/1904.
+
+ const uint32 kNumDaysInLeapCycle = 4 * 365 + 1;
+
+ uint32 days = day + month2days[month] +
+ (year * kNumDaysInLeapCycle + 3) / 4;
+
+ // Now add in this year's leap-day, if there is one.
+
+ if ((month >= 2) && ((year & 3) == 0))
+ days++;
+
+ return days;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetLibraryName
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: The libraries name, or an empty string if the library
+ * could not be found.
+ *
+ ***********************************************************************/
+
+string GetLibraryName (uint16 refNum)
+{
+ if (refNum == sysInvalidRefNum)
+ return string();
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ /*
+ The System Library Table (sysLibTableP) is an array of
+ sysLibTableEntries entries. Each entry has the following
+ format:
+
+ Ptr* dispatchTblP; // pointer to library dispatch table
+ void* globalsP; // Library globals
+ LocalID dbID; // database id of the library
+ MemPtr codeRscH; // library code resource handle for RAM-based libraries
+
+ The latter two fields are present only in Palm OS 2.0 and
+ later. So our first steps are to (a) get the pointer to
+ the array, (b) make sure that the index into the array (the
+ refNum passed as the first parameter to all library calls)
+ is within range, (c) get a pointer to the right entry,
+ taking into account the Palm OS version, and (d) getting the
+ dispatchTblP field.
+
+ The "library dispatch table" is an array of 16-bit offsets. The
+ values are all relative to the beginning of the table (dispatchTblP).
+ The first entry in the array corresponds to the library name. All
+ subsequent entries are offsets to the various library functions,
+ starting with the required four: sysLibTrapOpen, sysLibTrapClose,
+ sysLibTrapSleep, and sysLibTrapWake.
+ */
+
+ emuptr sysLibTableP = EmLowMem_GetGlobal (sysLibTableP);
+ UInt16 sysLibTableEntries = EmLowMem_GetGlobal (sysLibTableEntries);
+
+ if (sysLibTableP == EmMemNULL)
+ {
+ // !!! No library table!
+ EmAssert (false);
+ return string();
+ }
+
+ if (refNum >= sysLibTableEntries)
+ {
+ if (refNum != 0x0666)
+ {
+ // !!! RefNum out of range!
+ EmAssert (false);
+ }
+
+ return string();
+ }
+
+ emuptr libEntry;
+ emuptr dispatchTblP;
+
+ if (EmPatchState::OSMajorVersion () > 1)
+ {
+ libEntry = sysLibTableP + refNum * sizeof (SysLibTblEntryType);
+ dispatchTblP = EmMemGet32 (libEntry + offsetof (SysLibTblEntryType, dispatchTblP));
+ }
+ else
+ {
+ libEntry = sysLibTableP + refNum * sizeof (SysLibTblEntryTypeV10);
+ dispatchTblP = EmMemGet32 (libEntry + offsetof (SysLibTblEntryTypeV10, dispatchTblP));
+ }
+
+ // The first entry in the table is always the offset from the
+ // start of the table to the library name. Use this information
+ // get the library name.
+
+ int16 offset = EmMemGet16 (dispatchTblP + LibTrapIndex (sysLibTrapName) * 2);
+ emuptr libNameP = dispatchTblP + offset;
+
+ char libName[256];
+ EmMem_strcpy (libName, libNameP);
+
+ return string (libName);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetSystemCallContext
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool GetSystemCallContext (emuptr pc, SystemCallContext& context)
+{
+ context.fPC = pc;
+
+ // Determine how the system function is being called. There are two ways:
+ //
+ // * Via SYS_TRAP macro:
+ //
+ // TRAP $F
+ // DC.W $Axxx
+ //
+ // * Via SYS_TRAP_FAST macro:
+ //
+ // MOVE.L struct(LowMemType.fixed.globals.sysDispatchTableP), A1
+ // MOVE.L ((trapNum-sysTrapBase)*4)(A1), A1
+ // JSR (A1) ; opcode == 0x4e91
+ //
+ // The PC is current pointing to either the TRAP $F or the JSR (A1),
+ // so we can look at the opcode to determine how we got here.
+
+ uint8* realMem = EmMemGetRealAddress (pc);
+ uint16 opcode = EmMemDoGet16 (realMem);
+
+ context.fViaTrap = opcode == (m68kTrapInstr + sysDispatchTrapNum);
+ context.fViaJsrA1 = opcode == (0x4e91);
+
+
+ if (context.fViaTrap)
+ {
+ // Not all development systems generate the correct dispatch
+ // numbers; some leave off the preceding "A". Make sure it's
+ // set so that we can recognize it as a trap dispatch number.
+ // (This code is here specifically so that the profiling routines
+ // will work, which check for trap numbers masquerading as function
+ // addresses by checking to see if they are in the sysTrapBase range.)
+
+ context.fTrapWord = EmMemGet16 (pc + 2) | sysTrapBase;
+ context.fNextPC = pc + 4;
+ }
+ else if (context.fViaJsrA1)
+ {
+ context.fTrapWord = (EmMemGet16 (pc - 2) / 4) | sysTrapBase;
+ context.fNextPC = pc + 2;
+ }
+ else
+ {
+ EmAssert (false);
+ return false;
+ }
+
+ if (::IsSystemTrap (context.fTrapWord))
+ {
+ context.fTrapIndex = SysTrapIndex (context.fTrapWord);
+ context.fExtra = m68k_dreg (regs, 2);
+ }
+ else
+ {
+ context.fTrapIndex = LibTrapIndex (context.fTrapWord);
+ context.fExtra = EmMemGet16 (m68k_areg (regs, 7));
+ }
+
+ EmAssert ((context.fTrapWord >= sysTrapBase) && (context.fTrapWord < sysTrapBase + 0x1000));
+
+ try
+ {
+ context.fError = 0;
+ context.fDestPC1 = ::GetFunctionAddress (context.fTrapWord, context.fExtra, false);
+ context.fDestPC2 = ::GetFunctionAddress (context.fTrapWord, context.fExtra, true);
+ }
+ catch (EmUnimplementedFunctionException& e)
+ {
+ context.fDestPC1 = EmMemNULL;
+ context.fDestPC2 = EmMemNULL;
+ context.fError = kError_UnimplementedTrap;
+ context.fLibIndex = e.fLibIndex;
+ return false;
+ }
+ catch (EmInvalidRefNumException& e)
+ {
+ context.fDestPC1 = EmMemNULL;
+ context.fDestPC2 = EmMemNULL;
+ context.fError = kError_InvalidLibraryRefNum;
+ context.fLibIndex = e.fLibIndex;
+ return false;
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetHostTime
+ *
+ * DESCRIPTION: Returns the current time in hours, minutes, and seconds.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void GetHostTime (long* hour, long* min, long* sec)
+{
+ time_t t;
+ struct tm tm;
+
+ time (&t);
+ tm = *localtime (&t);
+
+ *hour = tm.tm_hour; // 0...23
+ *min = tm.tm_min; // 0...59
+ *sec = tm.tm_sec; // 0...59
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetHostDate
+ *
+ * DESCRIPTION: Returns years since 1900, month as 0-11, and day as 1-31
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void GetHostDate (long* year, long* month, long* day)
+{
+ time_t t;
+ struct tm tm;
+
+ time (&t);
+ tm = *localtime (&t);
+
+ *year = tm.tm_year + 1900; // 1904...2040
+ *month = tm.tm_mon + 1; // 1...12
+ *day = tm.tm_mday; // 1...31
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: StartsWith
+ *
+ * DESCRIPTION: Determine if a string starts with the given pattern.
+ *
+ * PARAMETERS: s - string to test.
+ *
+ * p - pattern to test with.
+ *
+ * RETURNED: True if "s" starts with "p".
+ *
+ ***********************************************************************/
+
+Bool StartsWith (const char* s, const char* p)
+{
+ if (strlen (s) < strlen (p))
+ return false;
+
+ return (_strnicmp (s, p, strlen (p)) == 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EndsWith
+ *
+ * DESCRIPTION: Determine if a string end with the given pattern.
+ *
+ * PARAMETERS: s - string to test.
+ *
+ * p - pattern to test with.
+ *
+ * RETURNED: True if "s" ends with "p".
+ *
+ ***********************************************************************/
+
+Bool EndsWith (const char* s, const char* p)
+{
+ if (strlen (s) < strlen (p))
+ return false;
+
+ const char* buffer = s + strlen(s) - strlen(p);
+ return (_stricmp (buffer, p) == 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Strip
+ *
+ * DESCRIPTION: Remove leading or trailing instances of the given
+ * character(s).
+ *
+ * PARAMETERS: s - string to modify.
+ *
+ * ch - character(s) to remove.
+ *
+ * leading - true if leading characters should be removed.
+ *
+ * trailing - true if trailing characters should be removed.
+ *
+ * RETURNED: Modified string.
+ *
+ ***********************************************************************/
+
+string Strip (const char* s, const char* ch, Bool leading, Bool trailing)
+{
+ string result (s);
+ string chars (ch);
+
+ if (leading)
+ {
+ // Iterate over the string, looking to see if the leading character
+ // is in the given character set.
+
+ string::iterator iter = result.begin ();
+ while (iter != result.end ())
+ {
+ if (chars.find (*iter) == string::npos)
+ break;
+
+ result.erase (iter);
+ iter = result.begin ();
+ }
+ }
+
+ if (trailing)
+ {
+ // Iterate over the string, looking to see if the trailing character
+ // is in the given character set.
+
+ string::reverse_iterator iter = result.rbegin ();
+ while (iter != result.rend ())
+ {
+ if (chars.find (*iter) == string::npos)
+ break;
+
+ result.erase (iter.base () - 1);
+ iter = result.rbegin ();
+ }
+ }
+
+ return result;
+}
+string Strip (const string& s, const char* ch, Bool leading, Bool trailing)
+{
+ return ::Strip (s.c_str (), ch, leading, trailing);
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: ReplaceString
+ *
+ * DESCRIPTION: Replace all occurances of one string inside of a second
+ * string with a third string.
+ *
+ * PARAMETERS: source - the string on which the replacements are to
+ * be made.
+ *
+ * pattern - substring to search for.
+ *
+ * replacement - string with which to replace the patterm.
+ *
+ * RETURNED: The changed string.
+ *
+ ***********************************************************************/
+
+string ReplaceString (const string& source,
+ const string& pattern,
+ const string& replacement)
+{
+ string result (source);
+ string::size_type pos = 0;
+
+ for (;;)
+ {
+ pos = result.find (pattern, pos);
+ if (pos == string::npos)
+ break;
+ result.replace (pos, pattern.size (), replacement);
+ pos += replacement.size ();
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvInsertString
+ *
+ * DESCRIPTION: Insert one string into the middle of another. The
+ * buffer containing the string being modified should be
+ * large enough to hold the resulting string.
+ *
+ * PARAMETERS: dest - buffer containing the string to receive the
+ * inserted text.
+ *
+ * insertBefore - character index at which the inserted
+ * text should appear. Assumed to be [0, strlen(dest)].
+ *
+ * src - text to be inserted.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+static void PrvInsertString (char* dest, int insertBefore, const char* src)
+{
+ size_t destLen = strlen (dest);
+ size_t srcLen = strlen (src);
+
+ // Move down the part of the string after the insertion point. Don't
+ // use strcpy or memcpy, as we're dealing with an overlapping range.
+ // Add 1 to the range length to get the terminating NULL.
+
+ memmove (dest + insertBefore + srcLen, dest + insertBefore, destLen - insertBefore + 1);
+
+ // Insert the new string. *Don't* copy the NULL!
+
+ memmove (dest + insertBefore, src, srcLen);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FormatInteger
+ *
+ * DESCRIPTION: Convert an integral value into a formatted string,
+ * adding thousands seperators as necessary.
+ *
+ * PARAMETERS: dest - buffer for the outputted string
+ *
+ * integer - input value
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void FormatInteger (char* dest, uint32 integer)
+{
+ sprintf (dest, "%ld", integer);
+
+ // Get the thousands separator character(s).
+
+ struct lconv* locale_data = localeconv ();
+ char* thousands_sep = locale_data->thousands_sep;
+
+ if (strlen (thousands_sep) == 0)
+ {
+ thousands_sep = ",";
+ }
+
+ // Insert the thousands separator(s).
+
+ // Divide by three to get the number of 3 digit groupings remaining
+ // (subtracting one to get the math to come out right)
+ //
+ // 1 -> 0
+ // 2 -> 0
+ // 3 -> 0
+ // 4 -> 1
+ // 5 -> 1
+ // 6 -> 1
+ // 7 -> 2
+ // 8 -> 2
+ // 9 -> 2
+ // 10 -> 3
+ //
+ // etc...
+
+ int numCommas = (strlen (dest) - 1) / 3;
+
+ // Special case the stupid rule about not putting a comma
+ // in a number like xxxx.
+
+ if (strlen (dest) <= 4)
+ {
+ numCommas = 0;
+ }
+
+ for (int ii = 1; ii <= numCommas; ++ii)
+ {
+ // Back up four for every comma (skip past every ",xxx" pattern).
+
+ ::PrvInsertString (dest, strlen (dest) + 1 - (4 * ii), thousands_sep);
+ }
+}
+
+string FormatInteger (uint32 integer)
+{
+ // Format the integer as a plain string.
+
+ strstream stream;
+
+ stream << integer;
+
+ string result (stream.str (), stream.pcount ());
+
+ // Unfreeze the stream, or else its storage will be leaked.
+
+ stream.freeze (false);
+
+ // Get the thousands separator character(s).
+
+ struct lconv* locale_data = localeconv ();
+ char* thousands_sep = locale_data->thousands_sep;
+
+ if (strlen (thousands_sep) == 0)
+ {
+ thousands_sep = ",";
+ }
+
+ // Insert the thousands separator(s).
+
+ // Divide by three to get the number of 3 digit groupings remaining
+ // (subtracting one to get the math to come out right)
+ //
+ // 1 -> 0
+ // 2 -> 0
+ // 3 -> 0
+ // 4 -> 1
+ // 5 -> 1
+ // 6 -> 1
+ // 7 -> 2
+ // 8 -> 2
+ // 9 -> 2
+ // 10 -> 3
+ //
+ // etc...
+
+ int numCommas = (result.size () - 1) / 3;
+
+ // Special case the stupid rule about not putting a comma
+ // in a number like xxxx.
+
+ if (result.size () <= 4)
+ {
+ numCommas = 0;
+ }
+
+ for (int ii = 1; ii <= numCommas; ++ii)
+ {
+ // Back up four for every comma (skip past every ",xxx" pattern).
+
+ result.insert (result.size () + 1 - (4 * ii), thousands_sep);
+ }
+
+ return result;
+}
+
+
+string FormatElapsedTime (uint32 mSecs)
+{
+ // Get hours, minutes, and seconds.
+
+ const long kMillisecondsPerSecond = 1000;
+ const long kSecondsPerMinute = 60;
+ const long kMinutesPerHour = 60;
+
+ const long kMillisecondsPerMinute = kMillisecondsPerSecond * kSecondsPerMinute;
+ const long kMillisecondsPerHour = kMillisecondsPerMinute * kMinutesPerHour;
+
+ long hours = mSecs / kMillisecondsPerHour; mSecs -= hours * kMillisecondsPerHour;
+ long minutes = mSecs / kMillisecondsPerMinute; mSecs -= minutes * kMillisecondsPerMinute;
+ long seconds = mSecs / kMillisecondsPerSecond; mSecs -= seconds * kMillisecondsPerSecond;
+
+ // Format them into a string.
+
+ char formattedTime[20];
+ sprintf (formattedTime, "%ld:%02ld:%02ld", hours, minutes, seconds);
+
+ return string (formattedTime);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: LaunchCmdToString
+ *
+ * DESCRIPTION: Convert the given launch command (the command that's
+ * passed to PilotMain in a Palm OS application) into a
+ * text form suitable for displaying to a user.
+ *
+ * PARAMETERS: cmd - the launch command (from SystemMgr.h)
+ *
+ * RETURNED: A pointer to a string representing the command. If
+ * the command is unrecognized (probably because this
+ * function is out-of-date and needs to be updated for
+ * newly-added commands), a default string containing
+ * the command number is returned.
+ *
+ ***********************************************************************/
+
+const char* LaunchCmdToString (UInt16 cmd)
+{
+#undef DOCASE
+#define DOCASE(name) \
+ case name: \
+ return #name;
+
+ switch (cmd)
+ {
+ DOCASE (sysAppLaunchCmdNormalLaunch)
+ DOCASE (sysAppLaunchCmdFind)
+ DOCASE (sysAppLaunchCmdGoTo)
+ DOCASE (sysAppLaunchCmdSyncNotify)
+ DOCASE (sysAppLaunchCmdTimeChange)
+ DOCASE (sysAppLaunchCmdSystemReset)
+ DOCASE (sysAppLaunchCmdAlarmTriggered)
+ DOCASE (sysAppLaunchCmdDisplayAlarm)
+ DOCASE (sysAppLaunchCmdCountryChange)
+ DOCASE (sysAppLaunchCmdSyncRequestLocal)
+ DOCASE (sysAppLaunchCmdSaveData)
+ DOCASE (sysAppLaunchCmdInitDatabase)
+ DOCASE (sysAppLaunchCmdSyncCallApplicationV10)
+ DOCASE (sysAppLaunchCmdPanelCalledFromApp)
+ DOCASE (sysAppLaunchCmdReturnFromPanel)
+ DOCASE (sysAppLaunchCmdLookup)
+ DOCASE (sysAppLaunchCmdSystemLock)
+ DOCASE (sysAppLaunchCmdSyncRequestRemote)
+ DOCASE (sysAppLaunchCmdHandleSyncCallApp)
+ DOCASE (sysAppLaunchCmdAddRecord)
+ DOCASE (sysSvcLaunchCmdSetServiceID)
+ DOCASE (sysSvcLaunchCmdGetServiceID)
+ DOCASE (sysSvcLaunchCmdGetServiceList)
+ DOCASE (sysSvcLaunchCmdGetServiceInfo)
+ DOCASE (sysAppLaunchCmdFailedAppNotify)
+ DOCASE (sysAppLaunchCmdEventHook)
+ DOCASE (sysAppLaunchCmdExgReceiveData)
+ DOCASE (sysAppLaunchCmdExgAskUser)
+ DOCASE (sysDialLaunchCmdDial)
+ DOCASE (sysDialLaunchCmdHangUp)
+ DOCASE (sysSvcLaunchCmdGetQuickEditLabel)
+ DOCASE (sysAppLaunchCmdURLParams)
+ DOCASE (sysAppLaunchCmdNotify)
+ DOCASE (sysAppLaunchCmdOpenDB)
+ DOCASE (sysAppLaunchCmdAntennaUp)
+ DOCASE (sysAppLaunchCmdGoToURL)
+ }
+
+ static char buffer[20];
+ sprintf (buffer, "#%ld", (long) cmd);
+ return buffer;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: GetMemoryList
+ *
+ * DESCRIPTION: Return the list of items that should appear in the
+ * various listboxes and menus that allow the user to
+ * select a memory size. The list is returned as a
+ * collection of pairs. The first element of the pair is
+ * the memory size (in K), and the second element of the
+ * pair is the same thing in textform, suitable for
+ * displaying to the user.
+ *
+ * PARAMETERS: memoryList - reference to the collection to receive
+ * the results.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void GetMemoryTextList (MemoryTextList& memoryList)
+{
+ memoryList.push_back (make_pair (RAMSizeType (128), string ("128K")));
+ memoryList.push_back (make_pair (RAMSizeType (256), string ("256K")));
+ memoryList.push_back (make_pair (RAMSizeType (512), string ("512K")));
+ memoryList.push_back (make_pair (RAMSizeType (1024), string ("1024K")));
+ memoryList.push_back (make_pair (RAMSizeType (2048), string ("2048K")));
+ memoryList.push_back (make_pair (RAMSizeType (4096), string ("4096K")));
+ memoryList.push_back (make_pair (RAMSizeType (8192), string ("8192K")));
+ memoryList.push_back (make_pair (RAMSizeType (16384), string ("16,384K")));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MyAssertFailed
+ *
+ * DESCRIPTION: Called by the EmAssert macro if NDEBUG is defined.
+ * EmAssert and MyAssertFailed are moral replacements for
+ * the assert macro of the Standard C Library and the
+ * underlying function it calls. However, those facilities
+ * don't necessarily work the way we'd like. In
+ * particular, on Linux, they will abort the application.
+ * Sometimes, we'd like the ability to continue application
+ * execution.
+ *
+ * PARAMETERS: exp - expression that evaluate to false.
+ * file - name of file containing the expression.
+ * line - line number in the file containing the expression.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void MyAssertFailed (const char* expr, const char* file, unsigned int line)
+{
+ char message[2000];
+
+ sprintf (message, "Assertion Failure: Expression: \"%s\", File: %s, Line: %d",
+ expr, file, line);
+
+ LogDump ();
+
+ Platform::Debugger (message);
+}
diff --git a/SrcShared/Miscellaneous.h b/SrcShared/Miscellaneous.h
new file mode 100644
index 0000000..08b5230
--- /dev/null
+++ b/SrcShared/Miscellaneous.h
@@ -0,0 +1,178 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _MISCELLANEOUS_H_
+#define _MISCELLANEOUS_H_
+
+#include "EmStructs.h" // DatabaseInfoList
+
+class Chunk;
+class EmRect;
+
+class StMemory
+{
+ public:
+ StMemory ( char* inPtr = NULL);
+
+ StMemory ( long inSize,
+ Bool inClearBytes = false);
+
+ ~StMemory ();
+
+ operator char* () { return mPtr; }
+
+ char* Get () const { return mPtr; }
+ Bool IsOwner () const { return mIsOwner; }
+ Bool IsValid () const { return (mPtr != NULL); }
+
+ void Adopt ( char* inPtr);
+ char* Release () const;
+ void Dispose ();
+
+ protected:
+ char* mPtr;
+ mutable Bool mIsOwner;
+
+ private:
+ StMemory ( const StMemory &inPointerBlock);
+ StMemory& operator = (const StMemory &inPointerBlock);
+};
+
+
+class StMemoryMapper
+{
+ public:
+ StMemoryMapper (const void* memory, long size);
+ ~StMemoryMapper (void);
+
+ private:
+ const void* fMemory;
+};
+
+class StWordSwapper
+{
+ public:
+ StWordSwapper (void* memory, long length);
+ ~StWordSwapper (void);
+
+ private:
+ void* fMemory;
+ long fLength;
+};
+
+
+// ================================================================================
+//
+// EmValueChanger
+//
+// Use EmValueChanger to temporarily change the value of a variable. The
+// constructor saves the old value and sets the new value. The destructor
+// restores the old value.
+//
+// ================================================================================
+
+template <class T>
+class EmValueChanger
+{
+ public:
+ EmValueChanger(T& variable, T newValue) :
+ fVariable(variable),
+ fOrigValue(variable)
+ {
+ fVariable = newValue;
+ }
+
+ ~EmValueChanger()
+ {
+ fVariable = fOrigValue;
+ }
+
+ private:
+ T& fVariable;
+ T fOrigValue;
+};
+
+void ValidateFormObjects (FormPtr frm);
+void CollectOKObjects (FormPtr frm, vector<UInt16>& okObjects);
+
+Bool PinRectInRect (EmRect& inner, const EmRect& outer);
+
+const Bool kAllDatabases = false;
+const Bool kApplicationsOnly = true;
+
+void GetDatabases (DatabaseInfoList& appList, Bool applicationsOnly);
+
+Bool IsExecutable (UInt32 dbType, UInt32 dbCreator, UInt16 dbAttrs);
+Bool IsVisible (UInt32 dbType, UInt32 dbCreator, UInt16 dbAttrs);
+void GetLoadableFileList (string directoryName, EmFileRefList& fileList);
+void GetFileContents (const EmFileRef& file, Chunk& contents);
+
+void InstallCalibrationInfo (void);
+void ResetCalibrationInfo (void);
+void ResetClocks (void);
+void SetHotSyncUserName (const char*);
+
+void SeparateList (StringList& stringList, string str, char delimiter);
+
+void RunLengthEncode (void** srcPP, void** dstPP, long srcBytes, long dstBytes);
+void RunLengthDecode (void** srcPP, void** dstPP, long srcBytes, long dstBytes);
+long RunLengthWorstSize (long);
+
+void GzipEncode (void** srcPP, void** dstPP, long srcBytes, long dstBytes);
+void GzipDecode (void** srcPP, void** dstPP, long srcBytes, long dstBytes);
+long GzipWorstSize (long);
+
+int CountBits (uint32 v);
+inline int CountBits (uint16 v) { return CountBits ((uint32) (uint16) v); }
+inline int CountBits (uint8 v) { return CountBits ((uint32) (uint8) v); }
+
+inline int CountBits (int32 v) { return CountBits ((uint32) (uint32) v); }
+inline int CountBits (int16 v) { return CountBits ((uint32) (uint16) v); }
+inline int CountBits (int8 v) { return CountBits ((uint32) (uint8) v); }
+
+inline Bool IsEven (uint32 v) { return (v & 1) == 0; }
+inline Bool IsOdd (uint32 v) { return (v & 1) != 0; }
+
+uint32 NextPowerOf2 (uint32 x);
+uint32 DateToDays (uint32 year, uint32 month, uint32 day);
+
+string GetLibraryName (uint16 refNum);
+
+Bool GetSystemCallContext (emuptr, SystemCallContext&);
+
+void GetHostTime (long* hour, long* min, long* sec);
+void GetHostDate (long* year, long* month, long* day);
+
+Bool StartsWith (const char* s, const char* pattern);
+Bool EndsWith (const char* s, const char* pattern);
+string Strip (const char* s, const char*, Bool leading, Bool trailing);
+string Strip (const string& s, const char*, Bool leading, Bool trailing);
+string ReplaceString (const string& source,
+ const string& pattern,
+ const string& replacement);
+void FormatInteger (char* dest, uint32 integer);
+string FormatInteger (uint32 integer);
+string FormatElapsedTime (uint32 mSecs);
+const char* LaunchCmdToString (UInt16 cmd);
+void StackCrawlStrings (const EmStackFrameList& stackCrawl,
+ StringList& stackCrawlStrings);
+string StackCrawlString (const EmStackFrameList& stackCrawl,
+ long maxLen, Bool includeFrameSize,
+ emuptr oldStackLow);
+
+typedef pair <RAMSizeType, string> MemoryText;
+typedef vector <MemoryText> MemoryTextList;
+
+void GetMemoryTextList (MemoryTextList& memoryList);
+
+#endif // _MISCELLANEOUS_H_
diff --git a/SrcShared/Palm.h b/SrcShared/Palm.h
new file mode 100644
index 0000000..5c38181
--- /dev/null
+++ b/SrcShared/Palm.h
@@ -0,0 +1,233 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _PALM_H_
+#define _PALM_H_
+
+#include "PalmPack.h"
+
+// Remap some types that also appear in the Mac headers.
+#define ControlPtr Palm_ControlPtr
+#define ListPtr Palm_ListPtr
+#define AlertType Palm_AlertType
+
+// Defined in both CharAttr.h and ...\VC\Includes\xlocinfo.h
+#undef _XA
+#undef _XS
+#undef _BB
+#undef _CN
+#undef _DI
+#undef _LO
+#undef _PU
+#undef _SP
+#undef _UP
+#undef _XD
+
+// From PalmOS.h
+
+// To override build options in a local component, include <BuildDefines.h>
+// first, then define switches as need, and then include <PalmTypes.h>.
+
+ #include "BuildDefines.h"
+
+ // Not really needed (BuildDefaults.h sets this to EMULATION_MAC
+ // if undefined, which is fine for us, since all relevent headers
+ // only check to see if it's EMULATION_NONE or not), but let's do
+ // it right anyway.
+
+ #if PLATFORM_MAC
+ #define EMULATION_LEVEL EMULATION_MAC
+ #elif PLATFORM_UNIX
+ #define EMULATION_LEVEL EMULATION_UNIX
+ #elif PLATFORM_WINDOWS
+ #define EMULATION_LEVEL EMULATION_WINDOWS
+ #else
+ #error "Unknown platform"
+ #endif
+
+ #include "PalmTypes.h"
+// #include <SystemPublic.h>
+// #include <UIPublic.h>
+
+ // From SystemPublic.h
+
+// #include <AlarmMgr.h>
+// #include <AppLaunchCmd.h>
+ #include <Bitmap.h>
+ #include <CharAttr.h>
+ #include <Chars.h>
+// #include <ConnectionMgr.h>
+// #include <ConsoleMgr.h>
+ #include <Incs/Core/System/Crc.h> // Differentiate this from the one in gdb.
+ #include <DataMgr.h>
+ #include <DateTime.h>
+// #include <DebugMgr.h>
+// #include <Encrypt.h>
+ #include <ErrorBase.h>
+// #include <ErrorMgr.h>
+// #include <ExgLib.h>
+// #include <ExgMgr.h>
+ #include <FeatureMgr.h>
+// #include <FileStream.h>
+// #include <FloatMgr.h>
+ #include <Font.h>
+// #include <Graffiti.h>
+// #include <HostControl.h>
+// #include <ImcUtils.h>
+ #include <IntlMgr.h>
+// #include <IrLib.h>
+ #include <KeyMgr.h>
+ #include <Localize.h>
+ #include <MemoryMgr.h>
+// #include <ModemMgr.h>
+ #include <NetBitUtils.h>
+ #include <SysEvent.h> // must come before NetMgr.h due to weird dependency in NetMgr.h
+ #include <NetMgr.h>
+// #include <NotifyMgr.h>
+ #include <OverlayMgr.h>
+ #include <PalmLocale.h>
+// #include <Password.h>
+ #include <PenMgr.h>
+ #include <Preferences.h>
+ #include <Rect.h>
+// #include <ScriptPlugin.h>
+// #include <SerialDrvr.h>
+ #include <SerialMgr.h>
+ #include <SerialLinkMgr.h>
+// #include <SerialSdrv.h>
+// #include <SerialVdrv.h>
+ #include <SoundMgr.h>
+// #include <StringMgr.h>
+ #include <SysEvtMgr.h>
+ #include <SystemMgr.h>
+ #include <SystemResources.h>
+ #include <SystemPkt.h>
+// #include <SysUtils.h>
+ #include <TextMgr.h>
+// #include <TextServicesMgr.h>
+// #include <TimeMgr.h>
+ #include <Window.h>
+
+ // From UIPublic.h
+
+ #include <CoreTraps.h>
+
+// #include <AboutBox.h>
+// #include <Category.h>
+// #include <Clipboard.h>
+ #include <Control.h>
+// #include <Day.h>
+ #include <Event.h>
+ #include <FatalAlert.h>
+ #include <Field.h>
+ #include <Find.h>
+// #include <FontSelect.h>
+ #include <Form.h>
+// #include <GraffitiReference.h>
+// #include <GraffitiShift.h>
+ #include <InsPoint.h>
+// #include <Keyboard.h>
+// #include <Launcher.h>
+ #include <List.h>
+// #include <Menu.h>
+// #include <PhoneLookup.h>
+// #include <PrivateRecords.h>
+// #include <Progress.h>
+ #include <ScrollBar.h>
+// #include <SelDay.h>
+// #include <SelTime.h>
+ #include <Table.h>
+// #include <UIColor.h>
+// #include <UIControls.h>
+ #include <UIResources.h>
+
+// Additional bits we need
+
+ // Copied from Clipboard.h
+enum clipboardFormats { clipboardText, clipboardInk, clipboardBitmap };
+typedef enum clipboardFormats ClipboardFormatType;
+#define cbdMaxTextLength 1000
+
+#define NON_PORTABLE
+ #include "M68KHwr.h" // M68KRegsType (used in EmulatorTypes.h)
+ // Include before DebugPrv.h, which needs M68KRegsType
+ #include "DebugPrv.h" // BreakpointType (used in EmulatorTypes.h)
+ #include "SystemPrv.h" // SysKernelInfoType (used in MetaMemory::GWH_ExamineChunk)
+
+ #include "DataPrv.h" // DatabaseDirType, DatabaseHdrType, DmAccessType, DmOpenInfoType
+ // RecordListType, RecordEntryType, RsrcEntryType
+ #undef small // Defined in a VC++ header (RPCNDR.H).
+ #include "DLCommon.h" // DlpReqHeaderType, etc.
+ #include "DLServer.h" // DlkServerSessionType, DlkServerSessionPtr
+
+ #include "EZAustin/IncsPrv/SED1375Hwr.h" // SED1375RegsType
+
+ #include "M68328Hwr.h" // HwrM68328Type
+ #undef HwrDBallType
+ #undef HwrDBallPtr
+
+ #include "M68EZ328Hwr.h" // HwrM68EZ328Type
+ #undef HwrDBallType
+ #undef HwrDBallPtr
+
+ #include "M68VZ328Hwr.h" // HwrM68VZ328Type
+ #undef HwrDBallType
+ #undef HwrDBallPtr
+
+ #include "M68SZ328Hwr.h" // HwrM68SZ328Type
+ #undef HwrDBallType
+ #undef HwrDBallPtr
+#undef NON_PORTABLE
+
+
+struct HwrBatCmdReadType // from HwrBattery.h
+{
+ UInt16 mVolts; // level in millivolts (2500 = 2.5 volts)
+ UInt16 abs; // absolute level (0 -> 255)
+};
+
+
+#include "PalmPackPop.h"
+
+#undef ControlPtr
+#undef ListPtr
+#undef AlertType
+
+// Defined in both CharAttr.h and ...\VC\Includes\xlocinfo.h
+#undef _XA
+#undef _XS
+#undef _BB
+#undef _CN
+#undef _DI
+#undef _LO
+#undef _PU
+#undef _SP
+#undef _UP
+#undef _XD
+
+// PalmTypes.h defines these, but they conflict with the STL functions
+
+#undef min
+#undef max
+
+// UIResources.h defines this, but it messes up Icon.h on the Mac, which declares
+// parameters with this name.
+
+#undef iconType
+
+// DateTime.h defines this, but it messes up Icon.h on the Mac, which declares
+// parameters with this name.
+
+#undef maxTime
+
+#endif /* _PALM_H_ */
diff --git a/SrcShared/Palm/Device/328Jerry/IncsPrv/HardwareTD1.h b/SrcShared/Palm/Device/328Jerry/IncsPrv/HardwareTD1.h
new file mode 100644
index 0000000..a55dd3e
--- /dev/null
+++ b/SrcShared/Palm/Device/328Jerry/IncsPrv/HardwareTD1.h
@@ -0,0 +1,221 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HardwareTD1.h
+ *
+ * Description:
+ * Hardware Equates for the TD1 platform. This header file
+ * contains equates specific to Hardware platform TD1.
+ * It is included only in the modules "ROMHardwareTD1.c" and
+ * "AMXHardwareTD1.c".
+ *
+ * History:
+ * 6/13/95 RM Created by Ron Marianetti
+ * 6/ 8/98 jhl Added defines for PF3 & PE6 for Jerry DVT
+ * 6/ 8/98 jhl Added defines for PF3 & PE6 for Jerry DVT
+ * 6/ 8/98 jhl Added defines for PF3 & PE6 for Jerry DVT
+ * 5/31/99 SCL Moved TD1-specific stuff into this file from <HardwarePrv.h>
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HARDWARETD1_H__
+#define __HARDWARETD1_H__
+
+
+
+/***********************************************************************
+ * First Rev of the Pilot Hardware
+ ***********************************************************************/
+
+// Define the base of card 0 and the size of each card slot.
+#define hwrCardBase0 0x10000000L // starts here
+#define hwrCardSize 0x10000000L // Size of each card slot
+#define hwrFlashBase 0x10C00000L // Base of Flash ROM
+#define hwrFlashSize 0x00200000L // Size of Flash ROM
+#define hwrCardOffsetMask 0x0FFFFFFFL // Used to convert a pointer to a card offset
+#define hwrMinBigROMOffset 0x00008000L // Minimum ROM offset to BigROM
+
+
+// Define the Flash width
+#define hwrROMWidth 2
+
+// Define location and setup for the 68681 Duart
+#define hwrDuartBase 0x10E00000 // Base address of DUART
+
+#define hwrDuartClock 3686400 // in Hertz (3.6864 MHz)
+
+// Setting of ACR register except for baud rate select
+// Timer mode - Crystal clock /1
+#define hwrDuartACRReg 0x60
+
+
+
+/************************************************************************
+ * Dragonball Port D Bit settings
+ ************************************************************************/
+#define hwrTD1PortDNoExtPower 0x80 // (L) External DC input
+
+/************************************************************************
+ * Dragonball Port E Bit settings
+ ************************************************************************/
+// used in Jerry except EVT
+#define hwrTD1PortEPLLLock 0x40 // (IH) Jerry - Indicates PLL lock
+
+#define hwrTD1PortENoBacklight 0x80 // (H) high if no backlight present
+
+/************************************************************************
+ * Dragonball Port F Bit settings
+ ************************************************************************/
+// following 4 used in Jerry except EVT
+#define hwrTD1PortFDSPOn 0x01 // (H) Jerry - DSP Power On
+#define hwrTD1PortFChrgOn 0x02 // (H) Jerry - NiCad Charge On
+#define hwrTD1PortF3vRefOn 0x04 // (H) Jerry - 3v Reference On
+#define hwrTD1PortFPABiasOn 0x08 // (H) Jerry - PA Bias On (and NiCd sense)
+
+#define hwrTD1PortFPanelYPOff 0x01 // (L) Vcc to Y Panel
+#define hwrTD1PortFPanelYMOn 0x02 // (H) Gnd to Y Panel
+#define hwrTD1PortFPanelXPOff 0x04 // (L) Vcc to X Panel
+#define hwrTD1PortFPanelXMOn 0x08 // (H) Gnd to X Panel
+#define hwrTD1PortFLCDEnableOn 0x10 // (H) LCD Display on
+#define hwrTD1PortFLCDVccOff 0x20 // (L) LCD Vcc
+#define hwrTD1PortFLCDVeeOn 0x40 // (H) LCD Vee
+#define hwrTD1PortFADCSOff 0x80 // (L) A/D Chip Select
+
+
+// Configurations of the panel control bits
+#define hwrTD1PortFPanelMask 0x0F // Panel control bits
+
+// Configure for lowest power
+#define hwrTD1PortFPanelCfgOff (hwrTD1PortFPanelYPOff | \
+ hwrTD1PortFPanelXPOff)
+
+// Configure to generate pen interrupt
+#define hwrTD1PortFPanelCfgPenIRQ (hwrTD1PortFPanelXMOn | \
+ hwrTD1PortFPanelYPOff | \
+ hwrTD1PortFPanelXPOff)
+
+// Configure to Measure Y Position
+#define hwrTD1PortFPanelCfgYMeas (hwrTD1PortFPanelXMOn | \
+ hwrTD1PortFPanelYPOff)
+
+// Configure to Measure X Position
+#define hwrTD1PortFPanelCfgXMeas (hwrTD1PortFPanelXPOff | \
+ hwrTD1PortFPanelYMOn)
+
+
+/************************************************************************
+ * Dragonball Port G Bit Assignments
+ ************************************************************************/
+#define hwrTD1PortGSerialOn 0x08 // (H) Serial Driver Enable
+#define hwrTD1PortGBattOff 0x10 // (L) Battery Voltage Measure
+#define hwrTD1PortGRefreshOut 0x20 // (L) Timer 1 output to signal refresh
+#define hwrTD1PortGSelfRefOff 0x40 // (L) PSRAM Self Refresh mode
+#define hwrTD1PortGSelfRefOffBit 6 // Bit # for above
+#define hwrTD1PortGBacklightOn 0x80 // (H) Turn on backlight
+
+/************************************************************************
+ * Dragonball Port J Bit Assignments
+ ************************************************************************/
+#define hwrTD1PortJDSPReset 0x08 // (H) Jerry - DSP Reset
+#define hwrTD1PortJIrOn 0x10 // (L) IrDA Driver Enable
+#define hwrTD1PortJLedOn 0x20 // (H) LED On
+// following 2 used in EVT Jerry only
+#define hwrTD1PortJChrgOn 0x40 // (H) Jerry - NiCad Charge On
+#define hwrTD1PortJDSPOn 0x80 // (H) Jerry - DSP Power On
+
+/************************************************************************
+ * Dragonball Port M Bit Assignments
+ ************************************************************************/
+#define hwrTD1PortMVccFail 0x04 // (L) Input indicates 3.3v is too low
+#define hwrTD1PortMCardIRQ 0x08 // (L) IRQ3 input from card
+#define hwrTD1PortMUnused4 0x10 // Unused (IRQ2)
+#define hwrTD1PortMDockButton 0x20 // (L) Sync button from Serial Doc
+#define hwrTD1PortMPenIO 0x40 // Pen input/output
+#define hwrTD1PortMDockIn 0x80 // (L) Gen. Purpose input from Serial Doc
+
+
+
+/************************************************************************
+ * SPIM Base Configuration
+ ************************************************************************/
+#define hwrTD1SPIMBaseControl (hwr328SPIMControlRateDiv16 | \
+ hwr328SPIMControlIntEnable | \
+ hwr328SPIMControlInvPolarity | \
+ hwr328SPIMControlOppPhase | \
+ 16-1)
+
+
+#if 0
+ // We can't use these macros in Palm OS any more.
+ // This code is now access through the HAL routines
+ // HwrEnableDataWrites and HwrDisableDataWrites.
+
+/************************************************************************
+ * Macros for turning write-protection on/off
+ * These are used in-line for MemSemaphoreReserve and MemSemaphoreRelease
+ * for performance reasons.
+ ************************************************************************/
+#define hwrWriteProtectOff() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ /* UInt16 mask; */ \
+ \
+ /* DOLATER.. take this out.... */ \
+ /* mask = baseP->csAGroupMask; */ \
+ \
+ /* Clr read-only bit in chip select register for storage area */ \
+ baseP->csASelect1 &= ~(0x0008); \
+ baseP->csASelect3 &= ~(0x0008); \
+ \
+ /* DOLATER.. take this out... */ \
+ /*baseP->csAGroupMask = mask; */ \
+ }
+
+#ifndef BUILD_OPTION_WP_OFF
+#define hwrWriteProtectOn() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ /* UInt16 mask; */ \
+ \
+ /* DOLATER.. take this out.... */ \
+ /* mask = baseP->csAGroupMask; */ \
+ \
+ /* Set read-only bit in chip select register for storage area */ \
+ baseP->csASelect1 |= (0x0008); \
+ baseP->csASelect3 |= (0x0008); \
+ \
+ /* DOLATER.. take this out... */ \
+ /*baseP->csAGroupMask = mask; */ \
+ }
+#else
+#define hwrWriteProtectOn()
+#endif
+
+#endif
+
+
+/************************************************************************
+ *Initial values for the PLL. We set the system clock to be VCO/2 so
+ * the system clock speed becomes:
+ *
+ * 32768 * ((hwrTD1FreqSelP + 1) * 14 + hwrTD1FreqSelQ + 1)
+ * --------------------------------------------------------
+ * 2
+ ************************************************************************/
+// NEW ASIC versions run at 16.580608 Mhz
+#define hwrTD1PLLControl (hwr328PLLControlClkEn | \
+ hwr328PLLControlSysVCODiv1 | \
+ hwr328PLLControlPixVCODiv1)
+#define hwrTD1FreqSelQ 0x01
+#define hwrTD1FreqSelP 0x23
+#define hwrTD1Frequency (32768*((hwrTD1FreqSelP+1)*14+hwrTD1FreqSelQ+1)/1)
+
+
+
+#endif //__HARDWARETD1_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Device/EZAustin/IncsPrv/HardwareAustin.h b/SrcShared/Palm/Device/EZAustin/IncsPrv/HardwareAustin.h
new file mode 100644
index 0000000..f08fe36
--- /dev/null
+++ b/SrcShared/Palm/Device/EZAustin/IncsPrv/HardwareAustin.h
@@ -0,0 +1,214 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HardwareAustin.h
+ *
+ * Description:
+ * Hardware Equates for the EZ (Austin) platform. This header file
+ * contains equates specific to Hardware platform EZ.
+ *
+ * History:
+ * 03/04/99 ben Created from HardwareEZ.h
+ * 07/15/99 kwk Added hwrDigitizerWidth & hwrDigitizerHeight.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HARDWAREAUSTIN_H__
+#define __HARDWAREAUSTIN_H__
+
+
+/***********************************************************************
+ * EZ Rev of the Pilot Hardware
+ ***********************************************************************/
+#define hwr68328Base 0xFFFFF000L // Base address of 68328
+
+// Define the base of card 0 and the size of each card slot.
+#define hwrCardBase0 0x00000000L // starts here (just above Dheap)
+#define hwrCardSize 0x20000000L // Size of each card slot
+#define hwrFlashBase 0x10C00000L // Base of Flash ROM
+//#define hwrFlashSize 0x00400000L // Size of Flash ROM
+#define hwrCardOffsetMask 0x1FFFFFFFL // Used to convert a pointer to a card offset
+#define hwrMinBigROMOffset 0x00008000L // Minimum ROM offset to BigROM
+
+
+// Define the Flash width
+#define hwrROMWidth 2
+
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrEZPortBLCD_CS 0x01 // (L) LCD Chip Select
+#define hwrEZPortBCS_ADC 0x02 // (L) BurrBrown Chip-select
+#define hwrEZPortBLCDBright 0x08 // (L) LCD Brightness controller SYNC
+#define hwrEZPortBRS232Enable 0x40 // (H) Enable the RS232 Transceiver
+#define hwrEZPortBSoundUnfiltered 0x80 // (-) Unfiltered Sound
+
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+#define hwrEZPortCKbdRow0 0x01 // (H) Keyboard Row 0
+#define hwrEZPortCKbdRow1 0x02 // (H) Keyboard Row 1
+#define hwrEZPortCKbdRow2 0x04 // (H) Keyboard Row 2
+#define hwrEZPortCCharging 0x08 // (L) Battery Charging - Low if battery is charging.
+#define hwrEZPortCKbdRows 0x07 // All Keyboard Rows
+
+#define hwrEZPortCBacklightEnable 0x10 // (H) Enable SED1375 Backlight
+#define hwrEZPortCChargerShutdown 0x20 // (H) Output high to disable the charger
+#define hwrEZPortCEnable5V 0x40 // (H) Enable 5V power supply for screen
+#define hwrEZPortCEnableDTR 0x80 // (H) Assert Serial DTR signal.
+
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+
+#define hwrEZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+#define hwrEZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+#define hwrEZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+#define hwrEZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+#define hwrEZPortDKeyBits 0x0F // All Keyboard Columns
+
+#define hwrEZPortDDockButton 0x10 // (L) IRQ1 HotSync/Dock Button
+#define hwrEZPortDGoodBattery 0x20 // (H) IRQ2 Good Battery
+#define hwrEZPortDAdapterInstalled 0x40 // (L) IRQ3 Adapter installed
+#define hwrEZPortDPowerFail 0x80 // (L) Power Fail interrupt (IRQ6)
+
+
+// DANGER: Writing to PortD to (for example) toggle the serial enable bit has potential side effects.
+// For example, if we |= or &= the serial enable bit (as PrvSerialEnable used to do) and inadvertently
+// write other one-bits to portDData, we may clear pending edge interrupts on those other bits, like
+// for example, the keyboard edge interrupt bits. Though the docs are somewhat ambiguous (surprise!),
+// it would APPEAR that this is only the case for the keyboard interrupt bits (INT0-INT3). This DID
+// cause problems when re-enabling the serial port during HwrWake->SerialWake, as it would clear any
+// pending keyboard interrupts that woke the device (such as the power key or application buttons).
+// SO, when writing to the serial enable bit, we MUST be sure to mask against hwrEZPortDDataMaskBeforeWrite
+// before writing to portDData. This is ALSO VERY IMPORTANT for anyone who might make use of bit 6 (IRQ3)
+// as an output pin. Whenever writing to hwrEZPortDFree3, one should always read portDData first, twiddle
+// hwrEZPortDFree3 as appropriate, and with hwrEZPortDDataMaskBeforeWrite and finally write to portDData.
+// Maybe in future parts, Moto can spare us a PortDIntStatus register, separate from portDData.
+
+#define hwrEZPortDDataMaskBeforeWrite (~(hwrEZPortDKeyBits)) // Don't write ones to these bits!
+
+#define hwrEZPortDKeyOffset 0x0 // bits to shift to put Col 0 in lsb
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrEZPortESpiTxD 0x01 // (L) SPI TXD (Internal)
+#define hwrEZPortESpiRxD 0x02 // (L) SPI RXD (Internal)
+#define hwrEZPortESpiClk 0x04 // SPI Clock
+#define hwrEZPortESpiBits 0x07 // all the SPI bits
+#define hwrEZPortERXD 0x10 // external RXD
+#define hwrEZPortETXD 0x20 // external TXD
+#define hwrEZPortERTS 0x40 // external RTS
+#define hwrEZPortECTS 0x80 // external CTS
+
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+
+#define hwrEZPortFLCDPowered 0x01 // (H) Input asserted when LCD is at full power.
+#define hwrEZPortFPenIO 0x02 // (H) Pen Interrupt, Pen IO (IRQ5)
+#define hwrEZPortFBusClock 0x04 // (H) Bus Clock
+#define hwrEZPortFA20 0x08 // (H) A20
+
+#define hwrEZPortFA21 0x10 // (H) A21
+#define hwrEZPortFVideoClkEnable 0x20 // (H) Enable Video clock.
+#define hwrEZPortFBatteryEnable 0x40 // (H) Battery Enable
+#define hwrEZPortFIXTRNL2 0x80 // (L) IXTRNL2 line, used to ID the device connected to the sync port.
+
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+
+#define hwrEZPortGDTACK 0x01 // (-) DTACK
+#define hwrEZPortGA0 0x02 // (-) A0
+#define hwrEZPortGIDDetect 0x04 // (L) ID select (drives kbd)
+#define hwrEZPortGHiZ 0x08 // (L) Used in ICT to tristate dragonball pins
+#define hwrEZPortGIRShutdown 0x10 // (H) Shutdown IRDA
+#define hwrEZPortGEmuBrk 0x20 // (-) EMUBRK
+
+
+/************************************************************************
+ * SPIM Base Configuration
+ ************************************************************************/
+#define hwrEZSPIMBaseControl (hwrEZ328SPIMControlRateDiv16 | \
+ hwrEZ328SPIMControlIntEnable | \
+ hwrEZ328SPIMControlInvPolarity | \
+ hwrEZ328SPIMControlOppPhase | \
+ 16-1)
+
+
+
+/************************************************************************
+ *Initial values for the PLL. We set the system clock to be VCO/1 so
+ * the system clock speed becomes:
+ *
+ * 32768 * ((hwrEZFreqSelP + 1) * 14 + hwrEZFreqSelQ + 1)
+ * --------------------------------------------------------
+ * VCO divider
+ ************************************************************************/
+// NEW ASIC versions run at 16.580608 Mhz
+
+#define hwrEZPLLControl (hwrEZ328PLLControlClkEn | \
+ hwrEZ328PLLControlSysDMADiv1 | \
+ hwrEZ328PLLControlPixDMADiv1 | \
+ hwrEZ328PLLControlDMAVCODiv1)
+
+
+// The Frequency needs to be lowered on the older DragonBall-EZ processors.
+//
+// The values are:
+// 15MHz: Allows processor to operate without screen noise within the voltage
+// range specified for the Power Supply (3.3V +- 100mV)
+// P = 0x1F, Q=0x9
+// 13.5 MHz: Brings processor into voltage spec (runs as low as 3.0V without noise)
+// P = 0x1C, Q=0x7
+//
+// The following are the OK values for 0J83C processors (id 4)
+// 16.580608 is the spec'd frequency for the part. HK admits that 20MHz works
+// 16.580608MHz: P = 0x23, Q=0x01
+// 20.0 MHz: P = 0x2A, Q=0x9
+
+#define hwrEZFreqSelPQ_13_5MHz (0x1C | (0x07 << 8))
+
+#define hwrEZFreqSelPQ_14_75MHz (0x1F | (0x01 << 8))
+
+#define hwrEZFreqSelPQ_15MHz (0x1F | (0x09 << 8))
+
+#define hwrEZFreqSelPQ_16MHz (0x23 | (0x01 << 8))
+
+#define hwrEZFreqSelPQ_20MHz (0x2A | (0x09 << 8))
+
+
+/************************************************************************
+ * Display constants specific to Austin product.
+ ************************************************************************/
+
+#define hwrDisplayBootDepth 8 // Boot time bits per pixel (system default)
+
+#define hwrDisplayWidth 160 // Physical Screen Width
+#define hwrDisplayHeight 160 // Physical Screen Height
+#define hwrDisplayMaxDepth 8 // Maximum bits per pixel hardware supports
+
+#define hwrDigitizerWidth hwrDisplayWidth // Same as width of display
+#define hwrDigitizerHeight 220 // Height of digitizer area
+
+// Screen refresh rate
+#define hwrDisplayPeriod 13 // frame period in ms.
+
+// Brightness Control Adjuster special values
+#define hwrDisplayBrightAdjLowPwr 0x2000 // Sets special low power state for brightness adjust.
+
+
+#endif // __HARDWAREAUSTIN_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Device/EZAustin/IncsPrv/SED1375Hwr.h b/SrcShared/Palm/Device/EZAustin/IncsPrv/SED1375Hwr.h
new file mode 100644
index 0000000..dc85e2a
--- /dev/null
+++ b/SrcShared/Palm/Device/EZAustin/IncsPrv/SED1375Hwr.h
@@ -0,0 +1,240 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1998-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SED1375Hwr.h
+ *
+ * Description:
+ * Hardware definitions for SED1375 controller.
+ *
+ * History:
+ * 12/14/98 BRM Adpated from SED1374 Test tool by Bob Ebert.
+ *
+ *****************************************************************************/
+
+//-----------------------------------------------------------------------
+// SED1375 Registers
+//-----------------------------------------------------------------------
+
+typedef struct SED1375RegsType {
+ UInt8 productRevisionCode; // 0x00
+ UInt8 mode0; // 0x01
+
+ UInt8 mode1; // 0x02
+ UInt8 mode2; // 0x03
+
+ UInt8 horizontalPanelSize; // 0x04
+ UInt8 verticalPanelSizeLSB; // 0x05
+
+ UInt8 verticalPanelSizeMSB; // 0x06
+ UInt8 FPLineStartPosition; // 0x07
+
+ UInt8 horizontalNonDisplayPeriod; // 0x08
+ UInt8 FPFRAMEStartPosition; // 0x09
+
+ UInt8 verticalNonDisplayPeriod; // 0x0A
+ UInt8 MODRate; // 0x0B
+
+ UInt8 screen1StartAddressLSB; // 0x0C
+ UInt8 screen1StartAddressMSB; // 0x0D
+
+ UInt8 screen2StartAddressLSB; // 0x0E
+ UInt8 screen2StartAddressMSB; // 0x0F
+
+ UInt8 screen1StartAddressMSBit; // 0x10 !!! YES, screen1MSBit in a weird place. Send complaints to Epson.
+ UInt8 memoryAddressOffset; // 0x11
+
+ UInt8 screen1VerticalSizeLSB; // 0x12
+ UInt8 screen1VerticalSizeMSB; // 0x13
+
+ UInt8 unused1; // 0x14
+ UInt8 lookUpTableAddress; // 0x15
+
+ UInt8 unused2; // 0x16
+ UInt8 lookUpTableData; // 0x17
+
+ UInt8 GPIOConfigurationControl; // 0x18
+ UInt8 GPIOStatusControl; // 0x19
+
+ UInt8 scratchPad; // 0x1A
+ UInt8 portraitMode; // 0x1B
+
+ UInt8 lineByteCountRegister; // 0x1C, for portrait mode only
+ UInt8 unused3; // 0x01D not used
+
+ UInt8 unused4; // 0x1E
+ UInt8 unused5; // 0x1F
+} SED1375RegsType;
+
+typedef volatile SED1375RegsType *SED1375RegsPtr;
+
+
+//-----------------------------------------------------------------------
+// Register constants and definitions
+//-----------------------------------------------------------------------
+#define sed1375BaseAddress 0x1F000000
+#define sed1375RegisterOffset 0x1FFE0
+#define sed1375RegsAddr ((UInt8 *)sed1375BaseAddress + sed1375RegisterOffset)
+
+#define sed1375VideoMemStart sed1375BaseAddress
+#define sed1375VideoMemSize 81920 // 80K of memory for VRAM and CLUT's
+
+
+// REG[0x00] Revision Code Register
+// bits 7-2 are product code, bits 1-0 are revision code
+#define sed1375RevisionCodeRegister 0x00
+#define sed1375ProductCodeMask 0xFC
+#define sed1375RevisionCodeMask 0x03
+#define sed1375ProductCode 0x06
+#define sed1375ProductCodeExpected (sed1375ProductCode << 2)
+#define sed1375RevisionCodeExpected 0x00
+
+// REG[0x01] Mode Register 0
+// bits 6 (Dual/Single) and 5 (Color/Mono) and 1 (mode) are ignored if bit 7 is set.
+#define sed1375ModeRegister0 0x01
+#define sed1375ModeTFT 0x80 // bit 7
+#define sed1375ModeDual 0x40 // bit 6
+#define sed1375ModeColor 0x20 // bit 5
+#define sed1375FPLineActiveHigh 0x10 // bit 4
+#define sed1375FPFramePolarityActiveHigh 0x07 // bit 3
+#define sed1375FPShiftMasked 0x04 // bit 2
+#define sed1375DataWidth12BitTFTPanel 0x01 // bits 1-0
+
+// REG[0x02] Mode Register 1
+#define sed1375ModeRegister1 0x02
+#define sed1375BPPMask 0xC0 // bits 7,6
+#define sed1375BPPShift 6
+#define sed1375BPP(n) ((((n) - 1) & 0x04) << sed1375BPPShift)
+#define sed13758bpp 0xC0
+#define sed13754bpp 0x80
+#define sed13752bpp 0x40
+#define sed13751bpp 0x00
+#define sed1375HighPerformance 0x20 // bit 5
+#define sed1375InputClockDiv2 0x10 // bit 4
+#define sed1375DisplayBlank 0x08 // bit 3
+#define sed1375FrameRepeat 0x04 // bit 2
+#define sed1375HardwareVideoInvertEnable 0x02 // bit 1
+#define sed1375SoftwareVideoInvert 0x01 // bit 0
+
+// REG[0x03] Mode Register 2
+#define sed1375ModeRegister2 0x03
+#define sed1375LCDPWROverride 0x08 // bit 3
+#define sed1375HwrPowerSaveEnable 0x04 // bit 2
+#define sed1375PowerSaveMode 0x00 // bits 1,0
+#define sed1375PowerSaveNormalOperation 0x03
+
+// REG[0x04] Horizontal Panel Size Register
+// (Horizontal Panel Resolution pixels / 8)-1
+#define sed1375HorizontalPanelSizeRegister 0x04
+#define sed1375HorizontalResolutionMask 0x7F // bits 6-0
+
+// REG[0x05] Vertical Panel Size Register (LSB)
+// REG[0x06] Vertical Panel Size Register (MSB)
+// together define 10 bits of vertical lines, set to # of lines - 1
+#define sed1375VerticalPanelSizeRegisterLSB 0x05
+#define sed1375VerticalPanelSizeRegisterMSB 0x06
+#define sed1375VerticalResolutionMSBMask 0x30 // bits 1,0
+
+// REG[0x07] FPLINE Start Position
+#define sed1375FPLINEStartPosition 0x07
+#define sed1375FPLINEStartPositionMask 0x1F // bits 4-0
+
+// REG[0x08] Horizontal Non-Display Period
+#define sed1375HorizontalNonDisplayPeriod 0x08
+#define sed1375HorizontalNonDisplayMask 0x1F // bits 4-0
+#define sed1375NoHorizontalNonDisplay 0x00
+
+// REG[0x09] FPFRAME Start Position
+#define sed1375FPFRAMEStartPosition 0x09
+#define sed1375FPFRAMEStartPositionMask 0x3F // bits 5-0
+
+// REG[0x0A] Vertical Non-Display Period
+#define sed1375VerticalNonDisplayPeriod 0x0A
+#define sed1375VerticalNonDisplayStatus 0x80 // bit 7
+#define sed1375VerticalNonDisplayMask 0x3F // bits 5-0
+#define sed1375NoVerticalNonDisplay 0x00
+
+// REG[0x0B] MOD Rate Register (passive LCD only)
+#define sed1375MODRateRegister 0x0B
+#define sed1375MODRateUnused 0x00
+
+// REG[0x0C] Screen 1 Start Address Register (LSB)
+// REG[0x0D] Screen 1 Start Address Register (MSB)
+#define sed1375Screen1StartAddressRegisterLSB 0x0C
+#define sed1375Screen1StartAddressRegisterMSB 0x0D
+
+// REG[0x0F] Screen 2 Start Address Register (LSB)
+// REG[0x10] Screen 2 Start Address Register (MSB)
+#define sed1375Screen2StartAddressRegisterLSB 0x0F
+#define sed1375Screen2StartAddressRegisterMSB 0x10
+
+// REG[0x12] Memory Address Offset Register
+#define sed1375MemoryAddressOffsetRegister 0x12
+
+// REG[0x13] Screen 1 Vertical Size Register (LSB)
+// REG[0x14] Screen 1 Vertical Size Register (MSB)
+#define sed1375Screen1VerticalSizeRegisterLSB 0x13
+#define sed1375Screen1VerticalSizeRegisterMSB 0x14
+
+// REG[0x15] Look-Up Table Address Register
+#define sed1375LookUpTableAddressRegister 0x15
+#define sed1375LookUpAutoIncrement 0x00
+#define sed1375LookUpRedTableSelect 0x10
+#define sed1375LookUpGrayGreenTableSelect 0x20
+#define sed1375LookUpBlueTableSelect 0x30
+#define sed1375LookUpTableAddressMask 0x0F
+
+// REG[0x16] Look-Up Table Bank Select Register
+#define sed1375LookUpTableBankSelectRegister 0x16
+#define sed1375LookUpTableRedBank(n) (((n) & 0x03) << 4)
+#define sed1375LookUpTableGreenBank(n) (((n) & 0x03) << 2)
+#define sed1375LookUpTableBlueBank(n) ((n) & 0x03)
+#define sed1375LookUpTableBank(n) (sed1375LookUpTableRedBank(n) | sed1375LookUpTableGreenBank(n) | sed1375LookUpTableBlueBank(n))
+
+// REG[0x17] Look-Up Table Data Register
+#define sed1375LookUpTableDataRegister 0x17
+#define sed1375LookUpTableDataMask 0x0F
+
+// REG[0x18] GPIO Configuration Control Register
+#define sed1375GPIOConfigurationControlRegister 0x18
+#define sed1375GPIOPinOut(n, v) (((v) ? 1:0) << (n))
+
+// REG[0x19] GPIO Status/Control Register
+#define sed1375GPIOStatusControlRegister 0x19
+#define sed1375GPIOPinStatusMask(n) (1 << (n))
+#define sed1375GPIOPinSet(n, v) (((v) ? 1:0) << (n))
+
+// REG[0x1A] Scratch Pad Register
+#define sed1375ScratchPadRegister 0x1A
+
+// REG[0x1B] Portrait Mode Register
+#define sed1375PortraitModeRegister 0x1B
+#define sed1375LandscapeMode 0x00
+#define sed1375PortraitModeEnable 0x80 // bit 7
+#define sed1375X2SchemeSelect 0x40 // bit 6
+#define sed1375MCLKAutoDisable 0x04 // bit 2
+#define sed1375PCLKSelectBit1 0x02 // bit 1
+#define sed1375PCLKSelectBit0 0x01 // bit 0
+
+// REG[0x1C] Line UInt8 Count Register (for Portrait Mode)
+#define sed1375LineByteCountRegister 0x1C
+
+// REG[0x1D] ???? Register
+#define sed1375UnusualRegister 0x1D
+#define sed1375RepeatFrame 0x80
+#define sed1375Skip128FramesDuringPS 0x40
+#define sed1375OverlayEnable 0x20
+#define sed1375OverlayOperationBit1 0x10
+#define sed1375OverlayOperationBit0 0x08
+#define sed1375ForceHighClock 0x04
+#define sed1375FrameSkip 0x02
+#define sed1375FrameSkipStatus 0x01
+
+// REG[0x1F] Test Mode Register
+#define sed1375TestModeRegister 0x1F
+#define sed1375TestMode(n) ((n & 0x03) << 6)
+#define sed1375TestInput(n) ((n & 0x07) << 3)
+#define sed1375TestOutputMask 0x07
+#define sed1375TestModeNormal 0x00
+#define sed1375TestModeUnusual sed1375TestMode(1)
diff --git a/SrcShared/Palm/Device/EZSumo/IncsPrv/HardwareEZ.h b/SrcShared/Palm/Device/EZSumo/IncsPrv/HardwareEZ.h
new file mode 100644
index 0000000..2987958
--- /dev/null
+++ b/SrcShared/Palm/Device/EZSumo/IncsPrv/HardwareEZ.h
@@ -0,0 +1,239 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HardwareEZ.h
+ *
+ * Description:
+ * Hardware Equates for the EZ (Razor) platform. This header file
+ * contains equates specific to Hardware platform EZ.
+ * It is included only in the modules "ROMHardwareEZ.c" and
+ * "AMXHardwareEZ.c".
+ *
+ * History:
+ * 11/14/97 srj Started life from HardwareTD1.h
+ * 3/30/99 JB Added hwrEZPortDJerryAntenna
+ * 3/31/99 JB Added more Jerry pin definitions
+ * 6/04/99 srj Added EZ specific stuff from HardwarePrv.h
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HARDWAREEZ_H__
+#define __HARDWAREEZ_H__
+
+
+
+/************************************************************************
+ * Sumo/Brad/Sparky. Definitions from HardwarePrv.h.
+ ***********************************************************************/
+// Define the base of card 0 and the size of each card slot.
+#define hwrCardBase0 0x00000000L // starts here (just above Dheap)
+#define hwrCardSize 0x20000000L // Size of each card slot
+#define hwrFlashBase 0x10C00000L // Base of Flash ROM
+//#define hwrFlashSize 0x00200000L // Size of Flash ROM
+#define hwrCardOffsetMask 0x1FFFFFFFL // Used to convert a pointer to a card offset
+#define hwrMinBigROMOffset 0x00008000L // Minimum ROM offset to BigROM
+
+
+// Define the Flash width
+#define hwrROMWidth 2
+
+/************************************************************************
+ * Jerry EZ cost reduction. Set the PLD address.
+ ***********************************************************************/
+#define hwrJerryPldBase 0x11000000L
+
+
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+#define hwrEZPortBBacklightOn 0x01 // Backlight (Cobra 2)
+#define hwrEZPortBFree1 0x01 // (-) FREE1
+#define hwrEZPortBLCDVccOff 0x02 // (L) LCD Vcc On
+#define hwrEZPortBLCDAdjOn 0x40 // (L) LCD Contrast Adjust On (Brad Rev 0)
+#define hwrEZPortBFree4 0x40 // (-) FREE4
+//#define hwrEZPortBIORail2 0x40 // (L) I/O Rail Pin 2
+
+//#define hwrEZPortBIORail2Bit 6 // Bit number of Rail Pin 2
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+#define hwrEZPortCLCDEnableOn 0x80 // (H) LCD Enable
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+#define hwrEZPortDDockButton 0x10 // (L) Dock Button (aka IRQ1) (edge, negative)
+#define hwrEZPortD232Enable 0x20 // (L) Serial Shutdown on Sumo Rev 1 (aka IRQ2)
+#define hwrEZPortDJerryAntenna 0x20 // Jerry Antenna interrupt (aka IRQ2)
+//#define hwrEZPortDDockIn 0x20 // (L) Dock Input (free on Sumo Rev 0) (aka IRQ2)
+#define hwrEZPortDFree3 0x40 // (-) FREE3 (aka IRQ3)
+//#define hwrEZPortDIORail1 0x40 // (L) IO Rail 1 (aka IRQ3)
+#define hwrEZPortDPowerFail 0x80 // (L) Power Fail Interrupt (aka IRQ6) (level, low)
+#define hwrEZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+#define hwrEZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+#define hwrEZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+#define hwrEZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+#define hwrEZPortDKeyBits 0x0F // (H) All Keyboard Columns
+
+// DANGER: Writing to PortD to (for example) toggle the serial enable bit has potential side effects.
+// For example, if we |= or &= the serial enable bit (as PrvSerialEnable used to do) and inadvertently
+// write other one-bits to portDData, we may clear pending edge interrupts on those other bits, like
+// for example, the keyboard edge interrupt bits. Though the docs are somewhat ambiguous (surprise!),
+// it would APPEAR that this is only the case for the keyboard interrupt bits (INT0-INT3). This DID
+// cause problems when re-enabling the serial port during HwrWake->SerialWake, as it would clear any
+// pending keyboard interrupts that woke the device (such as the power key or application buttons).
+// SO, when writing to the serial enable bit, we MUST be sure to mask against hwrEZPortDDataMaskBeforeWrite
+// before writing to portDData. This is ALSO VERY IMPORTANT for anyone who might make use of bit 6 (IRQ3)
+// as an output pin. Whenever writing to hwrEZPortDFree3, one should always read portDData first, twiddle
+// hwrEZPortDFree3 as appropriate, and with hwrEZPortDDataMaskBeforeWrite and finally write to portDData.
+// Maybe in future parts, Moto can spare us a PortDIntStatus register, separate from portDData.
+#define hwrEZPortDDataMaskBeforeWrite (~(hwrEZPortDKeyBits)) // Don't write ones to these bits!
+
+// OBSOLETE
+#define hwrEZPortDKeyRow0 0x0F // (H) App keys on row 0
+#define hwrEZPortDKeyRow1 0x3 // (H) PgUp/PgDn on row 1
+#define hwrEZPortDKeyRow2 0x3 // (H) Power and Contrast on row 2
+#define hwrEZPortDKeyOffset 0x0 // bits to shift to put Col 0 in msb
+
+//#define hwrEZPortDIORail1Bit 6 // Bit number of Rail Pin 1
+//#define hwrEZPortDIntRailBit 3 // Bit number for Rail Pin 1 in Port D interrupt reg.
+
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+#define hwrEZPortESpiTxD 0x01 // (L) SPI TXD (Internal)
+#define hwrEZPortESpiRxD 0x02 // (L) SPI RXD (Internal)
+#define hwrEZPortESpiClk 0x04 // SPI Clock
+#define hwrEZPortESpiBits 0x07 // all the SPI bits
+#define hwrEZPortERXD 0x10 // external RXD
+#define hwrEZPortETXD 0x20 // external TXD
+#define hwrEZPortECTS 0x80 // external CTS
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+#define hwrEZPortFContrastPWM 0x01 // (L) PWM output for LCD contrast (Sumo)
+#define hwrEZPortFLCDAdjOn 0x01 // (L) LCD Contrast Adjust On (Brad Rev 1)
+#define hwrEZPortFJerryFReset 0x01 // Jerry flash reset
+#define hwrEZPortFPenIO 0x02 // (L) Pen Interrupt,Pen I/O
+#define hwrEZPortF232Enable 0x04 // (L) Shutdown Serial
+#define hwrEZPortFJerryPlatform 0x04 // Jerry-specific HW detect
+#define hwrEZPortFCobra2KbdRow0 0x20 // (L) Keyboard Row 0 (Cobra 2)
+#define hwrEZPortFCobra2KbdRow1 0x40 // (L) Keyboard Row 1 (Cobra 2)
+#define hwrEZPortFCobra2KbdRow2 0x80 // (L) Keyboard Row 2 (Cobra 2)
+#define hwrEZPortFCobra2KbdRows 0xE0 // (L) All Keyboard Rows (Cobra 2)
+#define hwrEZPortFKbdRow0 0x10 // (L) Keyboard Row 0 (Sumo/Brad)
+#define hwrEZPortFKbdRow1 0x20 // (L) Keyboard Row 1 (Sumo/Brad)
+#define hwrEZPortFKbdRow2 0x40 // (L) Keyboard Row 2 (Sumo/Brad)
+#define hwrEZPortFKbdRows 0x70 // (L) All Keyboard Rows (Sumo/Brad)
+#define hwrEZPortFBacklightOn 0x80 // (L) Backlight on (Sumo/Brad)
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+#define hwrEZPortGDTACK 0x01 // (L) DTACK
+#define hwrEZPortFree5 0x02 // (-) FREE5
+#define hwrEZPortGIDDetect 0x04 // (L) ID select (drives kbd)
+#define hwrEZPortGLiIonVoltReadDis 0x08 // (L) Enable A/D Voltage Divider
+#define hwrEZPortGJerry12Venable 0x08 // Jerry 12Volt enable for flash
+#define hwrEZPortGIRShutdown 0x10 // (H) Shutdown IRDA
+#define hwrEZPortGADCOff 0x20 // (L) A/D Select
+
+
+/************************************************************************
+ * SPIM Base Configuration
+ ************************************************************************/
+#define hwrEZSPIMBaseControl (hwrEZ328SPIMControlRateDiv16 | \
+ hwrEZ328SPIMControlIntEnable | \
+ hwrEZ328SPIMControlInvPolarity | \
+ hwrEZ328SPIMControlOppPhase | \
+ 16-1)
+
+
+/************************************************************************
+ * Macros for turning write-protection on/off
+ * These are used in-line for MemSemaphoreReserve and MemSemaphoreRelease
+ * for performance reasons.
+ ************************************************************************/
+#define hwrWriteProtectOff() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ \
+ /* Clr read-only bit in chip select register for storage area */ \
+ baseP->csDSelect &= ~(0x2000); \
+ \
+ }
+
+#ifndef BUILD_OPTION_WP_OFF
+#define hwrWriteProtectOn() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ \
+ /* Set read-only bit in chip select register for storage area */ \
+ baseP->csDSelect |= (0x2000); \
+ \
+ }
+#else
+#define hwrWriteProtectOn()
+#endif
+
+
+/************************************************************************
+ *Initial values for the PLL. We set the system clock to be VCO/1 so
+ * the system clock speed becomes:
+ *
+ * 32768 * ((hwrEZFreqSelP + 1) * 14 + hwrEZFreqSelQ + 1)
+ * --------------------------------------------------------
+ * VCO divider
+ ************************************************************************/
+// NEW ASIC versions run at 16.580608 Mhz
+#define hwrEZPLLControl (hwrEZ328PLLControlClkEn | \
+ hwrEZ328PLLControlSysDMADiv1 | \
+ hwrEZ328PLLControlPixDMADiv1 | \
+ hwrEZ328PLLControlDMAVCODiv1)
+// The Frequency needs to be lowered on the older DragonBall-EZ processors.
+//
+// The values are:
+// 15MHz: Allows processor to operate without screen noise within the voltage
+// range specified for the Power Supply (3.3V +- 100mV)
+// P = 0x1F, Q=0x9
+// 13.5 MHz: Brings processor into voltage spec (runs as low as 3.0V without noise)
+// P = 0x1C, Q=0x7
+//
+// The following are the OK values for 0J83C processors (id 4)
+// 16.580608 is the spec'd frequency for the part. HK admits that 20MHz works
+// 16.580608MHz: P = 0x23, Q=0x01
+// 20.0 MHz: P = 0x2A, Q=0x9
+
+#define hwrEZFreqSelPQ_13_5MHz (0x1C | (0x07 << 8))
+
+#define hwrEZFreqSelPQ_14_75MHz (0x1F | (0x01 << 8))
+
+#define hwrEZFreqSelPQ_15MHz (0x1F | (0x09 << 8))
+
+#define hwrEZFreqSelPQ_16MHz (0x23 | (0x01 << 8))
+
+#define hwrEZFreqSelPQ_20MHz (0x2A | (0x09 << 8))
+
+
+// Time needed to get to full battery voltage on EZ
+// this is used only in case of a constant-voltage charger, and Razor doesn't use that
+// right now. See PrvSystemTimerProc() for more gory details.
+#if 0
+#define hwrEZSecToFullCharge 60
+#endif
+
+// Bit definitions for Miscflags that are needed for the EZSumo HAL
+//#define hwrEZSubIDCobra2Mask 0x6
+#define hwrMiscFlagExtNewKeyboard 0x00000006 // This value tells us we have Cobra2 keyboard
+#define hwrMiscFlagExtNewKeyboardMask 0x00000006 // Mask for the Cobra2 bits
+#define hwrMiscFlagExt20MHzSpeed 0x00000001 // Set on Cobra 2 for 20MHz operation
+
+#endif //__HARDWAREEZ_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Device/VZTrn/IncsPrv/HardwareVZ.h b/SrcShared/Palm/Device/VZTrn/IncsPrv/HardwareVZ.h
new file mode 100644
index 0000000..fcf3458
--- /dev/null
+++ b/SrcShared/Palm/Device/VZTrn/IncsPrv/HardwareVZ.h
@@ -0,0 +1,285 @@
+//******************************************************************
+// Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+// All rights reserved.
+//
+// Pilot Software
+//
+//-------------------------------------------------------------------
+// FileName:
+// HardwareVZ.h
+//
+// Description:
+// Hardware Equates for the VZ (Palm V) platform. This header file
+// contains equates specific to Hardware platform VZ.
+// It is included only in the modules "ROMHardwareVZ.c" and
+// "AMXHardwareVZ.c".
+//
+// History:
+//
+// Name Date Description
+// ---- ---- ------------
+// agk 2/1/00 Change name of port bits to match Battra's spec
+//
+//*******************************************************************
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HARDWAREVZ_H__
+#define __HARDWAREVZ_H__
+
+
+
+/************************************************************************
+ * Palm V/Palm IIIx/Palm IIIe. Definitions from HardwarePrv.h.
+ ***********************************************************************/
+// Define the base of card 0 and the size of each card slot.
+#define hwrCardBase0 0x00000000L // starts here (just above Dheap)
+#define hwrCardSize 0x20000000L // Size of each card slot
+#define hwrFlashBase 0x10C00000L // Base of Flash ROM
+#define hwrFlashSize 0x00200000L // Size of Flash ROM
+#define hwrCardOffsetMask 0x1FFFFFFFL // Used to convert a pointer to a card offset
+#define hwrMinBigROMOffset 0x00008000L // Minimum ROM offset to BigROM
+
+
+// Define the Flash width
+#define hwrROMWidth 2
+
+//#define USE_VZTRN_UART1_FOR_DEBUG 1
+
+/************************************************************************
+ * Port B Bit settings
+ ************************************************************************/
+
+#define hwrVZPortBUSB_CS_N 0x01 // (L) USB Chip Select #
+#define hwrVZPortBSDWE_N 0x02 // (L) SDRAM Control - SDWE#
+#define hwrVZPortBSDRAS_N 0x04 // (L) SDRAM Control - SDRAS#
+#define hwrVZPortBSDCAS_N 0x08 // (L) SDRAM Control - SDCAS#
+
+#define hwrVZPortBSDCS_N 0x10 // (L) SDRAM Control - SDCS#
+#define hwrVZPortBRadio_IN_SVC 0x20 // (L) Radio in-service signal
+#define hwrVZPortBALARM_LED 0x40 // (L) Alarm LED
+#define hwrVZPortBSoundUnfiltered 0x80 // (P) Unfiltered Sound PWM
+
+/************************************************************************
+ * Port C Bit settings
+ ************************************************************************/
+
+#define hwrVZPortCLCDData0 0x01 // (L) Mono LCD Data Bit 0
+#define hwrVZPortCLCDData1 0x02 // (L) Mono LCD Data Bit 1
+#define hwrVZPortCLCDData2 0x04 // (L) Mono LCD Data Bit 2
+#define hwrVZPortCLCDData3 0x08 // (L) Mono LCD Data Bit 3
+
+#define hwrVZPortCLCDFramePulse 0x10 // (L) Mono LCD Frame Pulse
+#define hwrVZPortCLCDLinePulse 0x20 // (L) Mono LCD Line Pulse
+#define hwrVZPortCLCDClock 0x40 // (L) Mono LCD Clock
+#define hwrVZPortCLCDOn 0x80 // (L) Enable the LCD controller
+
+/************************************************************************
+ * Port D Bit settings
+ ************************************************************************/
+
+#define hwrVZPortDKbdCol0 0x01 // (H) Keyboard Column 0 (aka INT0)
+#define hwrVZPortDKbdCol1 0x02 // (H) Keyboard Column 1 (aka INT1)
+#define hwrVZPortDKbdCol2 0x04 // (H) Keyboard Column 2 (aka INT2)
+#define hwrVZPortDKbdCol3 0x08 // (H) Keyboard Column 3 (aka INT3)
+
+#define hwrVZPortDDockButton 0x10 // (L) HotSync/Dock Button (aka IRQ1)
+#define hwrVZPortDRadio_RING_IN 0x20 // (L) Radio Ring Indicate (aka IRQ2)
+#define hwrVZPortDUSB_INT_N 0x40 // (L) USB Interrupt (aka IRQ3)
+#define hwrVZPortDPowerFail 0x80 // (L) Power Fail interrupt (aka IRQ6)
+
+#define hwrVZPortDKeyBits 0x0F // All Keyboard Columns
+#define hwrVZPortDKeyOffset 0x0 // bits to shift to put Col 0 in lsb
+
+// DANGER: Writing to PortD to (for example) toggle the serial enable bit has potential side effects.
+// For example, if we |= or &= the serial enable bit (as PrvSerialEnable used to do) and inadvertently
+// write other one-bits to portDData, we may clear pending edge interrupts on those other bits, like
+// for example, the keyboard edge interrupt bits. Though the docs are somewhat ambiguous,
+// it would APPEAR that this is only the case for the keyboard interrupt bits (INT0-INT3). This DID
+// cause problems when re-enabling the serial port during HwrWake->SerialWake, as it would clear any
+// pending keyboard interrupts that woke the device (such as the power key or application buttons).
+// SO, when writing to the serial enable bit, we MUST be sure to mask against hwrVZPortDDataMaskBeforeWrite
+// before writing to portDData. This is ALSO VERY IMPORTANT for anyone who might make use of bit 6 (IRQ3)
+// as an output pin. Whenever writing to hwrVZPortDFree3, one should always read portDData first, twiddle
+// hwrVZPortDFree3 as appropriate, and with hwrVZPortDDataMaskBeforeWrite and finally write to portDData.
+// Maybe in future parts, Moto can spare us a PortDIntStatus register, separate from portDData.
+#define hwrVZPortDDataMaskBeforeWrite (~(hwrVZPortDKeyBits)) // Don't write ones to these bits!
+
+/************************************************************************
+ * Port E Bit settings
+ ************************************************************************/
+
+#define hwrVZPortESpiTxD 0x01 // (L) SPI TXD
+#define hwrVZPortESpiRxD 0x02 // (L) SPI RXD
+#define hwrVZPortESpiClk 0x04 // (L) SPI Clock
+#define hwrVZPortERadio_READY 0x08 // (L) Radio ready (XDR on radio)
+
+#define hwrVZPortERadio_RXD 0x10 // (H) RXD1# (used by Radio)
+#define hwrVZPortERadio_TXD 0x20 // (H) TXD1# (used by Radio)
+#define hwrVZPortETXD hwrVZPortERadio_TXD // keep the old name for now
+
+#ifndef USE_VZTRN_UART1_FOR_DEBUG
+#define hwrVZPortERadio_RTS 0x40 // (L) Radio RTS
+#define hwrVZPortERadio_CTS 0x80 // (L) Radio CTS
+#else // USE_VZTRN_UART1_FOR_DEBUG
+#define hwrVZPortERTS 0x40 // (L) RTS1#
+#define hwrVZPortECTS 0x80 // (L) CTS1#
+#endif // USE_VZTRN_UART1_FOR_DEBUG
+
+#define hwrVZPortESpiBits 0x07 // all the SPI bits
+
+/************************************************************************
+ * Port F Bit settings
+ ************************************************************************/
+// Spitfire
+#define hwrVZPortFLCD_CONTRAST 0x01 // (P) LCD Contrast
+#define hwrVZPortFPenIO 0x02 // (L) Pen Interrupt, Pen IO (IRQ5)
+#define hwrVZPortFFree2 0x04 // (-) Free (CLKO)
+#define hwrVZPortFA20 0x08 // (P) A20
+
+#define hwrVZPortFA21 0x10 // (P) A21
+#define hwrVZPortFA22 0x20 // (-) A22
+#define hwrVZPortFRadio_DTR 0x40 // (L) DTR to radio (XER on radio)
+#define hwrVZPortFROM_CS 0x80 // (L) Mass ROM chip select
+
+/************************************************************************
+ * Port G Bit settings
+ ************************************************************************/
+
+#define hwrVZPortGLCD_VCC_ON_N 0x01 // (L) LCD VCC control
+#define hwrVZPortGEL_ON 0x02 // (L) EL_ON
+#define hwrVZPortGFID_DETECT_N 0x04 // (-) ID_DETECT#
+#define hwrVZPortG232_SHDN_N 0x08 // (L) 232_SHDN# // Obsolete! (2/10/00)
+#define hwrVZPortG232a_SHDN_N 0x08 // (L) 232_SHDN#
+
+#define hwrVZPortGUSB_SPND 0x10 // (H) USB_SPND
+#define hwrVZPortGADC_CS_N 0x20 // (H) ADC_CS#
+#define hwrVZPortGUnused6 0x40 // (-) Unused6
+#define hwrVZPortGUnused7 0x80 // (-) Unused7
+
+/************************************************************************
+ * Port J Bit settings
+ ************************************************************************/
+
+#define hwrVZPortJRadio_ANT3 0x01 // (L) Radio RSSI 3
+#define hwrVZPortJRadio_ANT2 0x02 // (L) Radio RSSI 2
+#define hwrVZPortJRadio_ANT1 0x04 // (L) Radio RSSI 1
+#define hwrVZPortJRadio_PWR_STATE 0x08 // (L) Radio Power State
+
+#define hwrVZPortJRXD 0x10 // (L) RXD2#
+#define hwrVZPortJTXD 0x20 // (L) TXD2#
+#define hwrVZPortJRTS 0x40 // (L) RTS2#
+#define hwrVZPortJCTS 0x80 // (L) CTS2#
+
+/************************************************************************
+ * Port K Bit settings
+ ************************************************************************/
+
+ // Move KbdRowX to upper nibble so RW#, LDS#, & UDS# are available
+ // to Logic Analyzer to allow for instruction disassembly.
+ // Note: This requires a modified PCB.
+#define hwrVZPortKRadio_PWR_KEY 0x01 // (L) Radio power on/off
+#define hwrVZPortKFree1 0x02 // (-) FREE1 (RW#)
+#define hwrVZPortKEncharge 0x04 // (L) Charging Enable
+#define hwrVZPortKFree3 0x08 // (-) Free 3
+
+#define hwrVZPortKRadio_CD 0x10 // (L) Radio Carrier Detect
+#define hwrVZPortKKbdRow0 0x20 // (H) Keyboard Row 0
+#define hwrVZPortKKbdRow1 0x40 // (H) Keyboard Row 1
+#define hwrVZPortKKbdRow2 0x80 // (H) Keyboard Row 2
+
+#define hwrVZPortKKbdRows 0xE0 // All Keyboard Rows
+
+
+/************************************************************************
+ * Port M Bit settings
+ ************************************************************************/
+
+#define hwrVZPortMSDClk 0x01 // (-) SDClk
+#define hwrVZPortMSDCE 0x02 // (-) SDCE
+#define hwrVZPortMSDDQMH 0x04 // (-) SDDQMH
+#define hwrVZPortMSDDQML 0x08 // (-) SDDQML
+
+#define hwrVZPortMSDA10 0x10 // (-) SDA10
+// TEMPORARY - Tornado board uses this pin to enable either IrDA or UART2 VT (2/10/00)
+// 0: IrDA is on
+// 1: RS-232 Voltage Translator is on
+#define hwrVZPortMIR_SD 0x20 // (L) Infrared Shut-down (UART 2)
+#define hwrVZPortM232b_SHDN_N 0x20 // (L) Voltage Translator shutdown (UART 2)
+#define hwrVZPortMUnused6 0x40 // (-) Unused6
+#define hwrVZPortMUnused7 0x80 // (-) Unused7
+
+/************************************************************************
+ * SPIM Base Configuration
+ ************************************************************************/
+#define hwrVZSPIMBaseControl (hwrVZ328SPIMControlRateDiv16 | \
+ hwrVZ328SPIMControlIntEnable | \
+ hwrVZ328SPIMControlInvPolarity | \
+ hwrVZ328SPIMControlOppPhase | \
+ 16-1)
+
+
+/************************************************************************
+ * Macros for turning write-protection on/off
+ * These are used in-line for MemSemaphoreReserve and MemSemaphoreRelease
+ * for performance reasons.
+ ************************************************************************/
+#define hwrWriteProtectOff() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ \
+ /* Clr read-only bit in chip select register for storage area */ \
+ baseP->csDSelect &= ~(0x2000); \
+ \
+ }
+
+#ifndef BUILD_OPTION_WP_OFF
+#define hwrWriteProtectOn() \
+ { \
+ HwrDBallPtr baseP = (HwrDBallPtr)hwr68328Base; \
+ \
+ /* Set read-only bit in chip select register for storage area */ \
+ baseP->csDSelect |= (0x2000); \
+ \
+ }
+#else
+#define hwrWriteProtectOn()
+#endif
+
+
+/************************************************************************
+ *Initial values for the PLL. We set the system clock to be VCO/1 so
+ * the system clock speed becomes:
+ *
+ * 32768 * 2 * ((hwrVZFreqSelP + 1) * 14 + hwrVZFreqSelQ + 1)
+ * --------------------------------------------------------
+ * VCO divider
+ ************************************************************************/
+// Dragonball VZ runs at 33.161216 Mhz
+#define hwrVZPLLControl (hwrVZ328PLLControlSysDMADiv1 | \
+ hwrVZ328PLLControlPixDMADiv4 | \
+ hwrVZ328PLLControlPreSc1Div1 | \
+ hwrVZ328PLLControlPreSc2Div1)
+
+// The values are:
+// 33.16MHz: P = 0x23, Q=0x01
+// 26.01MHz: P = 0x1B, Q=0x04
+//
+#define hwrVZFreqSelPQ_33_16MHz (0x23 | (0x01 << 8))
+
+#define hwrVZFreqSelPQ_26_01MHz (0x1B | (0x04 << 8))
+
+
+/***** Oboselete! Should be removed eventually - agk 03/01/00 ***/
+#define hwrVZPortERadioXDR hwrVZPortERadio_READY
+#define hwrVZPortERadioRXD hwrVZPortERadio_RXD
+#define hwrVZPortERadioTXD hwrVZPortERadio_TXD
+#define hwrVZPortERadioRTS hwrVZPortERadio_RTS
+#define hwrVZPortERadioCTS hwrVZPortERadio_CTS
+
+
+
+
+#endif //__HARDWAREVZ_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/Hardware.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/Hardware.h
new file mode 100644
index 0000000..bf620c4
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/Hardware.h
@@ -0,0 +1,156 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Hardware.h
+ *
+ * Description:
+ * General Hardware Equates. This header file
+ * contains general hardware configuration equates that are not dependent on
+ * the version of the hardware we're running on. Equates specific to
+ * a certain component like the 68328, etc. are contained in separate
+ * header files.
+ *
+ * History:
+ * 4/27/95 RM Created by Ron Marianetti
+ * 6/12/98 jhl Updated definitions for hwrNVPrefSet/Get
+ * 6/17/98 jhl added 'mbtx' ROM token def
+ * 8/17/98 SCL Synchronized HwrMiscFlags between Sumo/Eleven
+ * 9/14/98 jfs Added PrvKeyBootKeys def (see ROMBoot.c for info)
+ * 10/06/98 jfs Added software-only hardware ID and features detection defs
+ * 10/07/98 jfs Cleaned up hardware ID bit defs and made unused combos obvious
+ * 10/07/98 Bob Up max depth support to 8 bits per pixel
+ * 01/18/99 kwk Added Sumo TSM button heights.
+ * 05/27/99 lyl Added hwrROMTokenBoot7 and hwrROMTokenBoot8
+ * 06/14/99 SCL Split out most pieces to separate Hwr*.h files
+ * 07/14/99 kwk Addded HwrGetSilkscreenID.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HARDWARE_H__
+#define __HARDWARE_H__
+
+#include <CoreTraps.h>
+#include <HAL.h> // NOTE: needs to be reflected in Makefiles
+
+
+// Define # of card slots
+#if EMULATION_LEVEL == EMULATION_NONE
+#define hwrNumCardSlots 1 // 1 card slot
+#else
+#define hwrNumCardSlots 2 // 2 card slots for emulation
+#endif
+
+
+// HwrLCDGetDepth requests
+#define hwrLCDGetCurrentDepth 0 // Get depth display is currently set to
+
+// HwrGetSilkscreenID results
+// DOLATER kwk - should these go here or in UICommon.h?
+// DOLATER kwk - does Austin have a different layout?
+#define silkscreenOriginal 10000
+#define silkscreenPalmV 10001 // Screen is slightly narrower at bottom.
+
+#define silkscreenCustom 19000 // First id for custom silkscreens
+
+/**************************************************************************
+ * Prototypes of functions used only when running on the real hardware
+ ***************************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // HAL routines installed into system traps from ROMHardwareXXX.c:
+ void HwrPreDebugInit(UInt32 cardHeaderAddr)
+ HAL_CALL(sysTrapHwrPreDebugInit);
+
+ void HwrResetNMI(void)
+ HAL_CALL(sysTrapHwrResetNMI);
+
+ void HwrResetPWM(void)
+ HAL_CALL(sysTrapHwrResetPWM);
+
+ UInt32 HwrMemWritable(void *addr)
+ HAL_CALL(sysTrapHwrMemWritable);
+
+ UInt32 HwrMemReadable(void *addr)
+ HAL_CALL(sysTrapHwrMemReadable);
+
+ Boolean HwrEnableDataWrites(void)
+ HAL_CALL(sysTrapHwrEnableDataWrites);
+
+ void HwrDisableDataWrites(void)
+ HAL_CALL(sysTrapHwrDisableDataWrites);
+
+
+ // HAL routines NOT installed into system traps from ROMHardwareXXX.c:
+ void PrvShutDownPLL(void);
+
+
+ // HAL routines installed into system traps from ROMHiHardwareXXX.c:
+ void HwrDoze(Boolean onlyNMI)
+ HAL_CALL(sysTrapHwrDoze);
+
+ Err HwrSetSystemClock(UInt32 *freqP)
+ HAL_CALL(sysTrapHwrSetSystemClock);
+
+ Err HwrSetCPUDutyCycle(UInt16 *dutyP)
+ HAL_CALL(sysTrapHwrSetCPUDutyCycle);
+
+ void HwrGetRAMMapping(void * /*CardInfoPtr*/ cardInfoP, UInt16 *numBlocksP,
+ UInt32 *physBlockInfoP, UInt32 *logBlockInfoP)
+ HAL_CALL(sysTrapHwrGetRAMMapping);
+
+ void HwrSleep(Boolean untilReset, Boolean emergency)
+ HAL_CALL(sysTrapHwrSleep);
+
+ Err HwrWake(void)
+ HAL_CALL(sysTrapHwrWake);
+
+ void HwrPostDebugInit(void)
+ HAL_CALL(sysTrapHwrPostDebugInit);
+
+ void HwrIdentifyFeatures(void)
+ HAL_CALL(sysTrapHwrIdentifyFeatures);
+
+ void HwrModelSpecificInit(void)
+ HAL_CALL(sysTrapHwrModelSpecificInit);
+
+ void HwrModelInitStage2(void)
+ HAL_CALL(sysTrapHwrModelInitStage2);
+
+
+ // Other routines:
+
+ UInt16 HwrGetSilkscreenID(void)
+ HAL_CALL(sysTrapHwrGetSilkscreenID);
+
+ void HwrWakeupIntHandler(void);
+
+/*
+ void PrvExecuteROMToken1(void);
+
+
+ void HwrRadioShutdown(void);
+*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+/************************************************************
+ * Assembly Function Prototypes
+ *************************************************************/
+#define _HwrWake \
+ ASM_SYS_TRAP(sysTrapHwrWake)
+
+
+#endif //__HARDWARE_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/HwrROMToken.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/HwrROMToken.h
new file mode 100644
index 0000000..cfa3d7d
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/HwrROMToken.h
@@ -0,0 +1,136 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HwrROMToken.h
+ *
+ * Description:
+ * Hardware ROM Token Equates.
+ *
+ * History:
+ * 5/31/99 SCL Created by Steve Lemke, extracted from <Hardware.h>
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HWR_ROM_TOKEN_H__
+#define __HWR_ROM_TOKEN_H__
+
+
+
+//--------------------------------------------------------------------
+// Layout of the A to D convertor calibration ROM token.
+// This data is calculated for each unit during production, and burnt
+// into the ROM. It consists of 2 precise voltages which are
+// applied to the A to D convertor, as well as their respective outputs
+// from the A/D convertor. Because of manufacturing tolerances in the
+// convertor, its important that the conversion of the output (0-255)
+// into centivolts is tailored to each device during manufacturing.
+//--------------------------------------------------------------------
+typedef struct {
+ UInt16 lowCentivolts;
+ UInt16 lowAToDOutput;
+ UInt16 highCentivolts;
+ UInt16 highAToDOutput;
+} SysAToDCalibrationTokenType;
+
+
+
+#define hwrROMTokenSnum 'snum' // MUST be the first token, should be 12 bytes long
+ // Snum == Memory Card Flash ID (serial number)
+#define hwrROMTokenIrda 'irda' // present ONLY on memory card w/IrDA (Gordon)
+#define hwrROMTokenFlex 'flex' // present ONLY on memory card w/Flex pager (Cessna)
+#define hwrROMTokenBrst 'brst' // present ONLY when Sharp PSRAM is used (triggers PrvHwrBurstRefresh)
+#define hwrROMTokenBoot1 'cd01' // boot time code plug-in #1 (See RomBoot.c and HwrROMToken.c)
+#define hwrROMTokenBoot2 'cd02' // boot time code plug-in #2 (See RomBoot.c)
+#define hwrROMTokenBoot3 'cd03' // boot time code plug-in #3 (See RomBoot.c)
+#define hwrROMTokenBoot4 'cd04' // boot time code plug-in #4 (See RomBoot.c)
+#define hwrROMTokenBoot5 'cd05' // boot time code plug-in #5 (See HwrDisplayBootTD1.c)
+#define hwrROMTokenBoot6 'cd06' // boot time code plug-in #6 (See KeyMgrTD1.c)
+#define hwrROMTokenBoot7 'cd07' // boot time code plug-in #7 (See ROMHardwareEZ.c)
+#define hwrROMTokenBoot8 'cd08' // boot time code plug-in #8 (See ROMHardwareEZ.c)
+#define hwrROMTokenAToD 'adcc' // Data for the A to D Convertor calibration
+// 6/17/98 jhl
+#define hwrROMTokenMobitex 'mbtx' // Mobitex calibration and serial number
+#define hwrROMTokenAlkCal 'calk' // alkaline calibration value
+#define hwrROMTokenNicadCal 'cncd' // nicad calibration value
+
+
+// 3/2/99 SCL
+// The following defines are for the first ("manufacturer") digit of the 'snum' token.
+#define hwrManu
+typedef enum {
+ hwrSnumManu3Com1 = '1',
+ hwrSnumManuTRG = '4',
+ hwrSnumManu3Com5 = '5',
+ hwrSnumManu3Com6 = '6',
+ hwrSnumManuMotorola = '7',
+ hwrSnumManuSymbol = '8',
+ hwrSnumManuQualcomm = '9',
+ hwrSnumManu3ComE = 'E'
+ } HwrSnumManufacturerEnum;
+
+
+// 10/06/98 jfs
+// The following structure describes the format of the data field of the hwrROMTokenHardwareID ROM token.
+// Note the featureIDs field is a variable length structure in which the OEM can place any number
+// of IDs representing features of THEIR particular hardware. Only the oemID and productID fields
+// are mandatory, the values of which are assigned to the OEM partner by Palm Computing.
+typedef struct {
+ UInt32 oemID;
+ UInt32 productID;
+ UInt32 featureIDs[1]; // OEM-specific variable length data goes here (0 or more DWords)
+} HwrIDRec, *HwrIDRecP;
+
+// The following ROM token activates the software-only hardware ID and features detection code.
+// See HwrIdentifyFeatures for details.
+#define hwrROMTokenHardwareID 'hwid'
+
+// GHwrMiscFlags ROM tokens (each has a corresponding hwrMiscFlagXXX bit definition)
+#define hwrROMTokenHasBacklight 'hbkl'
+#define hwrROMTokenHasMbdIrDA 'hirm'
+#define hwrROMTokenHasCardIrDA 'hirc'
+#define hwrROMTokenHasBurrBrown 'hbbd'
+#define hwrROMTokenHasJerryHW 'hjrm'
+#define hwrROMTokenNoRTCBug 'hrtc'
+#define hwrROMTokenHas3vRef 'h3vr'
+#define hwrROMTokenHasAntennaSw 'hant'
+
+#define hwrROMTokenHasCradleDetect 'hcrd'
+#define hwrROMTokenHasSWContrast 'hswc'
+#define hwrROMTokenInvertLCDForBL 'hibl'
+#define hwrROMTokenHasMiscFlagExt 'hmfe'
+
+// GHwrMiscFlagsExt ROM tokens (each has a corresponding hwrMiscFlagExtXXX bit definition)
+#define hwrROMTokenExtHasLiIon 'hbli'
+#define hwrROMTokenExtHasRailIO 'hrio'
+
+// NOTE: The following (flash) tokens should never be used; they're ignored by HwrIdentifyFeatures
+//#define hwrROMTokenExtHasFlash 'hflr'
+//#define hwrROMTokenExtHasFParms 'hfpr'
+
+#define hwrROMTokenExt115KIrOK 'h115'
+
+
+
+/**************************************************************************
+ * Prototypes of functions used only when running on the real hardware
+ ***************************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Err HwrGetROMToken (UInt16 cardNo, UInt32 token, UInt8 **dataP, UInt16 * sizeP )
+ HAL_CALL(sysTrapHwrGetROMToken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif //__HWR_ROM_TOKEN_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68328Hwr.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68328Hwr.h
new file mode 100644
index 0000000..730dcfe
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68328Hwr.h
@@ -0,0 +1,644 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: M68328Hwr.h
+ *
+ * Description:
+ * Hardware Equates for the Motorola 68328 Dragonball chip
+ *
+ * History:
+ * 4/19/95 RM - Created by Ron Marianetti
+ * 5/15/95 VMK - Added macros for RTC bits
+ * 6/12/98 jhl - Added define for chip select readonly bit
+ * 10/8/98 jhl - Imported chip ID stuff from EZ defs
+ * (not applicable to some earlier devices)
+ * 5/31/99 SCL - Moved hwr68328Base into this file from <HardwarePrv.h>
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So apps don't include this...
+
+
+#ifndef __M68328HWR_H__
+#define __M68328HWR_H__
+
+
+#include <PalmTypes.h> // Touchdown includes
+
+
+// Define location of the 68328 Dragonball chip
+#define hwr68328Base 0xFFFFF000L // Base address of 68328
+
+
+/***********************************************************************
+ * Motorola 68328 registers
+ ***********************************************************************/
+struct HwrM68328Type {
+
+ UInt8 scr; // $000: System Control Register
+ UInt8 ___filler0[0x004-0x001];
+
+ // The following ID stuff is not present on earlier chips (before ??)
+ UInt8 chipID; // $004: Chip ID Register
+ UInt8 maskID; // $005: Mask ID Register
+ UInt16 swID; // $006: Software ID Register
+ UInt8 ___filler1[0x100-0x008];
+
+ UInt16 csAGroupBase; // $100: Chip Select Group A Base Register
+ UInt16 csBGroupBase; // $102: Chip Select Group B Base Register
+ UInt16 csCGroupBase; // $104: Chip Select Group C Base Register
+ UInt16 csDGroupBase; // $106: Chip Select Group D Base Register
+
+ UInt16 csAGroupMask; // $108: Chip Select Group A Mask Register
+ UInt16 csBGroupMask; // $10A: Chip Select Group B Mask Register
+ UInt16 csCGroupMask; // $10C: Chip Select Group C Mask Register
+ UInt16 csDGroupMask; // $10E: Chip Select Group D Mask Register
+
+ UInt32 csASelect0; // $110: Group A Chip Select 0 Register
+ UInt32 csASelect1; // $114: Group A Chip Select 1 Register
+ UInt32 csASelect2; // $118: Group A Chip Select 2 Register
+ UInt32 csASelect3; // $11C: Group A Chip Select 3 Register
+
+ UInt32 csBSelect0; // $120: Group B Chip Select 0 Register
+ UInt32 csBSelect1; // $124: Group B Chip Select 1 Register
+ UInt32 csBSelect2; // $128: Group B Chip Select 2 Register
+ UInt32 csBSelect3; // $12C: Group B Chip Select 3 Register
+
+ UInt32 csCSelect0; // $130: Group C Chip Select 0 Register
+ UInt32 csCSelect1; // $134: Group C Chip Select 1 Register
+ UInt32 csCSelect2; // $138: Group C Chip Select 2 Register
+ UInt32 csCSelect3; // $13C: Group C Chip Select 3 Register
+
+ UInt32 csDSelect0; // $140: Group D Chip Select 0 Register
+ UInt32 csDSelect1; // $144: Group D Chip Select 1 Register
+ UInt32 csDSelect2; // $148: Group D Chip Select 2 Register
+ UInt32 csDSelect3; // $14C: Group D Chip Select 3 Register
+
+ UInt16 csDebug; // $150: Chip Select debug register
+ UInt8 ___filler2[0x200-0x152];
+
+ UInt16 pllControl; // $200: PLL Control Register
+ UInt16 pllFreqSel; // $202: PLL Frequency Select Register
+ UInt16 pllTest; // $204: PLL Test Register
+ UInt8 __filler44;
+ UInt8 pwrControl; // $207: Power Control Register
+
+ UInt8 ___filler3[0x300-0x208];
+
+ UInt8 intVector; // $300: Interrupt Vector Register
+ UInt8 ___filler4;
+ UInt16 intControl; // $302: Interrupt Control Register
+ UInt16 intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ UInt16 intMaskLo; // $306: Interrupt Mask Register/LOW word
+ UInt16 intWakeupEnHi; // $308: Interrupt Wakeup Enable Register
+ UInt16 intWakeupEnLo; // $30A: Interrupt Wakeup Enable Register
+ UInt16 intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ UInt16 intStatusLo; // $30E: Interrupt Status Register/LOW word
+ UInt16 intPendingHi; // $310: Interrupt Pending Register
+ UInt16 intPendingLo; // $312: Interrupt Pending Register
+
+ UInt8 ___filler4a[0x400-0x314];
+
+ UInt8 portADir; // $400: Port A Direction Register
+ UInt8 portAData; // $401: Port A Data Register
+ UInt8 ___filler5;
+ UInt8 portASelect; // $403: Port A Select Register
+
+ UInt8 ___filler6[4];
+
+ UInt8 portBDir; // $408: Port B Direction Register
+ UInt8 portBData; // $409: Port B Data Register
+ UInt8 ___filler7;
+ UInt8 portBSelect; // $40B: Port B Select Register
+
+ UInt8 ___filler8[4];
+
+ UInt8 portCDir; // $410: Port C Direction Register
+ UInt8 portCData; // $411: Port C Data Register
+ UInt8 ___filler9;
+ UInt8 portCSelect; // $413: Port C Select Register
+
+ UInt8 ___filler10[4];
+
+ UInt8 portDDir; // $418: Port D Direction Register
+ UInt8 portDData; // $419: Port D Data Register
+ UInt8 portDPullupEn; // $41A: Port D Pull-up Enable
+ UInt8 ___filler11;
+ UInt8 portDPolarity; // $41C: Port D Polarity Register
+ UInt8 portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ UInt8 ___filler12;
+ UInt8 portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ UInt8 portEDir; // $420: Port E Direction Register
+ UInt8 portEData; // $421: Port E Data Register
+ UInt8 portEPullupEn; // $422: Port E Pull-up Enable
+ UInt8 portESelect; // $423: Port E Select Register
+
+ UInt8 ___filler14[4];
+
+ UInt8 portFDir; // $428: Port F Direction Register
+ UInt8 portFData; // $429: Port F Data Register
+ UInt8 portFPullupEn; // $42A: Port F Pull-up Enable
+ UInt8 portFSelect; // $42B: Port F Select Register
+
+ UInt8 ___filler16[4];
+
+ UInt8 portGDir; // $430: Port G Direction Register
+ UInt8 portGData; // $431: Port G Data Register
+ UInt8 portGPullupEn; // $432: Port G Pull-up Enable
+ UInt8 portGSelect; // $433: Port G Select Register
+
+ UInt8 ___filler18[4];
+
+ UInt8 portJDir; // $438: Port J Direction Register
+ UInt8 portJData; // $439: Port J Data Register
+ UInt8 ___filler19;
+ UInt8 portJSelect; // $43B: Port J Select Register
+
+ UInt8 ___filler19a[4];
+
+ UInt8 portKDir; // $440: Port K Direction Register
+ UInt8 portKData; // $441: Port K Data Register
+ UInt8 portKPullupEn; // $442: Port K Pull-up Enable
+ UInt8 portKSelect; // $443: Port K Select Register
+
+ UInt8 ___filler21[4];
+
+ UInt8 portMDir; // $448: Port M Direction Register
+ UInt8 portMData; // $449: Port M Data Register
+ UInt8 portMPullupEn; // $44A: Port M Pull-up Enable Register
+ UInt8 portMSelect; // $44B: Port M Select Register
+
+ UInt8 ___filler22[4];
+
+ UInt8 ___filler23[0x500-0x450];
+
+ UInt16 pwmControl; // $500: PWM Control Register
+ UInt16 pwmPeriod; // $502: PWM Period Register
+ UInt16 pwmWidth; // $504: PWM Width Register
+ UInt16 pwmCounter; // $506: PWM Counter
+
+ UInt8 ___filler24[0x600-0x508];
+
+ UInt16 tmr1Control; // $600: Timer 1 Control Register
+ UInt16 tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ UInt16 tmr1Compare; // $604: Timer 1 Compare Register
+ UInt16 tmr1Capture; // $606: Timer 1 Capture Register
+ UInt16 tmr1Counter; // $608: Timer 1 Counter Register
+ UInt16 tmr1Status; // $60A: Timer 1 Status Register
+
+ UInt16 tmr2Control; // $60C: Timer 2 Control Register
+ UInt16 tmr2Prescaler; // $60E: Timer 2 Prescaler Register
+ UInt16 tmr2Compare; // $610: Timer 2 Compare Register
+ UInt16 tmr2Capture; // $612: Timer 2 Capture Register
+ UInt16 tmr2Counter; // $614: Timer 2 Counter Register
+ UInt16 tmr2Status; // $616: Timer 2 Status Register
+
+ UInt16 wdControl; // $618: Watchdog Control Register
+ UInt16 wdReference; // $61A: Watchdog Reference Register
+ UInt16 wdCounter; // $61C: Watchdog Counter
+
+ UInt8 ___filler25[0x700-0x61E];
+
+ UInt16 spiSlave; // $700: SPI Slave Register
+
+ UInt8 ___filler26[0x800-0x702];
+
+ UInt16 spiMasterData; // $800: SPI Master Data Register
+ UInt16 spiMasterControl; // $802: SPI Master Control Register
+
+ UInt8 ___filler27[0x900-0x804];
+
+ UInt16 uControl; // $900: Uart Control Register
+ UInt16 uBaud; // $902: Uart Baud Control Register
+ UInt16 uReceive; // $904: Uart Receive Register
+ UInt16 uTransmit; // $906: Uart Transmit Register
+ UInt16 uMisc; // $908: Uart Miscellaneous Register
+
+ UInt8 ___filler28[0xA00-0x90A];
+
+ UInt32 lcdStartAddr; // $A00: Screen Starting Address Register
+ UInt8 ___filler29;
+ UInt8 lcdPageWidth; // $A05: Virtual Page Width Register
+ UInt8 ___filler30[2];
+ UInt16 lcdScreenWidth; // $A08: Screen Width Register
+ UInt16 lcdScreenHeight; // $A0A: Screen Height Register
+ UInt8 ___filler31[0xA18-0xA0C];
+ UInt16 lcdCursorXPos; // $A18: Cursor X Position
+ UInt16 lcdCursorYPos; // $A1A: Cursor Y Position
+ UInt16 lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ UInt8 ___filler32;
+ UInt8 lcdBlinkControl; // $A1F: Blink Control Register
+ UInt8 lcdPanelControl; // $A20: Panel Interface Control Register
+ UInt8 lcdPolarity; // $A21: Polarity Config Register
+ UInt8 ___filler33;
+ UInt8 lcdACDRate; // $A23: ACD (M) Rate Control Register
+ UInt8 ___filler34;
+ UInt8 lcdPixelClock; // $A25: Pixel Clock Divider Register
+ UInt8 ___filler35;
+ UInt8 lcdClockControl; // $A27: Clocking Control Register
+ UInt8 ___filler36;
+ UInt8 lcdLastBufferAddr; // $A29: Last Buffer Address Register
+ UInt8 ___filler37;
+ UInt8 lcdOctetTermCount; // $A2B: Octet Terminal Count Register
+ UInt8 ___filler38;
+ UInt8 lcdPanningOffset; // $A2D: Panning Offset Register
+ UInt8 ___filler39[3];
+ UInt8 lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ UInt16 lcdGrayPalette; // $A32: Gray Palette Mapping Register
+ UInt8 lcdReserved; // $A34: Reserved
+
+ UInt8 ___filler40[0xB00-0xA35];
+
+ UInt32 rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ UInt32 rtcAlarm; // $B04: RTC Alarm Register
+ UInt32 rtcReserved; // $B08: RTC Reserved
+ UInt16 rtcControl; // $B0C: RTC Control Register
+ UInt16 rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ UInt16 rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ UInt16 stopWatch; // $B12: Stopwatch Minutes
+};
+
+typedef volatile struct HwrM68328Type* HwrM68328Ptr;
+
+#define HwrDBallType HwrM68328Type
+#define HwrDBallPtr HwrM68328Ptr
+
+/************************************************************************
+ * Chip Select Bits
+ ************************************************************************/
+#define hwr328ChipSelectReadonly 0x00000008
+
+/************************************************************************
+ * LCD Controller Bits
+ ************************************************************************/
+#define hwr328LcdCursorXPosCtlMask 0xC000
+ #define hwr328LcdCursorXPosCtlTrans 0x0000
+ #define hwr328LcdCursorXPosCtlBlack 0x4000
+ #define hwr328LcdCursorXPosCtlReverse 0x8000
+
+#define hwr328LcdBlinkControlEnable 0x80
+
+#define hwr328LcdPanelControlBusMask 0x06
+ #define hwr328LcdPanelControlBus1Bit 0x00
+ #define hwr328LcdPanelControlBus2Bit 0x02
+ #define hwr328LcdPanelControlBus4Bit 0x04
+#define hwr328LcdPanelControlGrayScale 0x01
+
+#define hwr328LcdPolarityShiftClock 0x08
+#define hwr328LcdPolarityFLM 0x04
+#define hwr328LcdPolarityLP 0x02
+#define hwr328LcdPolarityPixel 0x01
+
+#define hwr328LcdClockControlEnable 0x80
+#define hwr328LcdClockControl16WordBursts 0x40
+#define hwr328LcdClockControlBurstRateMask 0x30
+
+// New dragonball allows up to 16 clocks/word
+#define hwr328LcdClockControlBurstRate1 0x00
+#define hwr328LcdClockControlBurstRate2 0x04
+#define hwr328LcdClockControlBurstRate3 0x08
+#define hwr328LcdClockControlBurstRate4 0x0C
+#define hwr328LcdClockControlBurstRate5 0x10
+#define hwr328LcdClockControlBurstRate6 0x14
+#define hwr328LcdClockControlBurstRate7 0x18
+#define hwr328LcdClockControlBurstRate8 0x1C
+#define hwr328LcdClockControlBurstRate9 0x20
+#define hwr328LcdClockControlBurstRate10 0x24
+#define hwr328LcdClockControlBurstRate11 0x28
+#define hwr328LcdClockControlBurstRate12 0x2C
+#define hwr328LcdClockControlBurstRate13 0x30
+#define hwr328LcdClockControlBurstRate14 0x34
+#define hwr328LcdClockControlBurstRate15 0x38
+#define hwr328LcdClockControlBurstRate16 0x3C
+
+#define hwr328LcdClockControl8BitBus 0x02
+#define hwr328LcdClockControlPixelClkSrc 0x01
+
+
+/************************************************************************
+ * Interrupt Controller Bits
+ ************************************************************************/
+// intMaskHi bits
+// NOTE: Due to a bug in early rev's of the DragonBall, the clear bits for
+// IRQ[1236] on those early chips were different than the indicator bits
+// (the order was reversed). So some older code uses the OR of the IRQ1 and
+// IRQ6 bits for either, and the OR of the IRQ2 and IRQ3 bits for either.
+#define hwr328IntHiNMI 0x0080
+#define hwr328IntHiTimer1 0x0040
+#define hwr328IntHiSPIS 0x0020
+#define hwr328IntHiPen 0x0010
+#define hwr328IntHiIRQ6 0x0008
+#define hwr328IntHiIRQ3 0x0004
+#define hwr328IntHiIRQ2 0x0002
+#define hwr328IntHiIRQ1 0x0001
+
+//NOTE: Due to a bug in early rev's of the DragonBall, the clear bits for
+/// IRQ1,2,3,6 are different than the indicator bits
+#define hwr328IntHiIRQ6Clr 0x0001
+#define hwr328IntHiIRQ3Clr 0x0002
+#define hwr328IntHiIRQ2Clr 0x0004
+#define hwr328IntHiIRQ1Clr 0x0008
+
+// intMaskLo bits
+#define hwr328IntLoInt7 0x8000
+#define hwr328IntLoInt6 0x4000
+#define hwr328IntLoInt5 0x2000
+#define hwr328IntLoInt4 0x1000
+#define hwr328IntLoInt3 0x0800
+#define hwr328IntLoInt2 0x0400
+#define hwr328IntLoInt1 0x0200
+#define hwr328IntLoInt0 0x0100
+#define hwr328IntLoAllKeys 0xFF00
+#define hwr328IntLoInt0Bit 8
+#define hwr328IntLoPWM 0x0080
+#define hwr328IntLoPWMBit 7
+#define hwr328IntLoKbd 0x0040
+#define hwr328IntLoLCDC 0x0020
+#define hwr328IntLoRTC 0x0010
+#define hwr328IntLoRTCBit 4
+#define hwr328IntLoWDT 0x0008
+#define hwr328IntLoUART 0x0004
+#define hwr328IntLoUARTBit 2
+#define hwr328IntLoTimer2 0x0002
+#define hwr328IntLoTimer2Bit 1
+#define hwr328IntLoSPIM 0x0001
+
+// intControl bits
+// NOTE: These are different (at least in version 0G58E) that documented in the
+// User's manual
+#define hwr328IntCtlEdge1 0x0800
+#define hwr328IntCtlEdge2 0x0400
+#define hwr328IntCtlEdge3 0x0200
+#define hwr328IntCtlEdge6 0x0100
+#define hwr328IntCtlPol1 0x8000
+#define hwr328IntCtlPol2 0x4000
+#define hwr328IntCtlPol3 0x2000
+#define hwr328IntCtlPol6 0x1000
+
+
+/************************************************************************
+ * Timer bits
+ ************************************************************************/
+#define hwr328TmrControlUnused 0xFE00
+#define hwr328TmrControlFreeRun 0x0100
+#define hwr328TmrControlCaptureEdgeMask 0x00C0
+ #define hwr328TmrControlCaptureEdgeNone 0x0000
+ #define hwr328TmrControlCaptureEdgeRising 0x0040
+ #define hwr328TmrControlCaptureEdgeFalling 0x0080
+ #define hwr328TmrControlCaptureEdgeBoth 0x00C0
+#define hwr328TmrControlOutputModeToggle 0x0020
+#define hwr328TmrControlEnInterrupt 0x0010
+#define hwr328TmrControlClkSrcMask 0x000E
+ #define hwr328TmrControlClkSrcStop 0x0000
+ #define hwr328TmrControlClkSrcSys 0x0002
+ #define hwr328TmrControlClkSrcSysBy16 0x0004
+ #define hwr328TmrControlClkSrcTIN 0x0006
+ #define hwr328TmrControlClkSrc32KHz 0x0008
+#define hwr328TmrControlEnable 0x0001
+
+#define hwr328TmrStatusCapture 0x0002
+#define hwr328TmrStatusCaptureBit 1
+#define hwr328TmrStatusCompare 0x0001
+#define hwr328TmrStatusCompareBit 0
+
+
+/************************************************************************
+ * 68328 Serial Port Register Bits
+ ************************************************************************/
+// uControl Register
+#define hwr328UControlUARTEnable 0x8000
+#define hwr328UControlRxEnable 0x4000
+#define hwr328UControlTxEnable 0x2000
+#define hwr328UControlRxClock1x 0x1000
+#define hwr328UControlParityEn 0x0800
+#define hwr328UControlParityOdd 0x0400
+#define hwr328UControlStopBits2 0x0200
+#define hwr328UControlDataBits8 0x0100
+#define hwr328UControlGPIODeltaEn 0x0080
+#define hwr328UControlCTSDeltaEn 0x0040
+#define hwr328UControlRxFullEn 0x0020
+#define hwr328UControlRxHalfEn 0x0010
+#define hwr328UControlRxRdyEn 0x0008
+#define hwr328UControlTxEmptyEn 0x0004
+#define hwr328UControlTxHalfEn 0x0002
+#define hwr328UControlTxAvailEn 0x0001
+
+#define hwr328UControlEnableAll (hwr328UControlUARTEnable | \
+ hwr328UControlRxEnable | \
+ hwr328UControlTxEnable)
+
+// uBaud Register
+#define hwr328UBaudGPIODelta 0x8000
+#define hwr328UBaudGPIOData 0x4000
+#define hwr328UBaudGPIODirOut 0x2000
+#define hwr328UBaudGPIOSrcBaudGen 0x1000
+#define hwr328UBaudBaudSrcGPIO 0x0800
+#define hwr328UBaudDivider 0x0700
+#define hwr328UBaudPrescaler 0x003F
+
+#define hwr328UBaudDivideBitOffset 8
+
+
+// uReceive Register
+#define hwr328UReceiveFIFOFull 0x8000
+#define hwr328UReceiveFIFOHalf 0x4000
+#define hwr328UReceiveDataRdy 0x2000
+#define hwr328UReceiveDataRdyBit 13
+#define hwr328UReceiveOverrunErr 0x0800
+#define hwr328UReceiveOverrunErrBit 11
+#define hwr328UReceiveFrameErr 0x0400
+#define hwr328UReceiveFrameErrBit 10
+#define hwr328UReceiveBreakErr 0x0200
+#define hwr328UReceiveBreakErrBit 9
+#define hwr328UReceiveParityErr 0x0100
+#define hwr328UReceiveParityErrBit 8
+#define hwr328UReceiveData 0x00FF
+
+#define hwr328UReceiveErrsMask (hwr328UReceiveOverrunErr | \
+ hwr328UReceiveFrameErr | \
+ hwr328UReceiveBreakErr | \
+ hwr328UReceiveParityErr)
+
+// uTransmit Register
+#define hwr328UTransmitFIFOEmpty 0x8000
+#define hwr328UTransmitFIFOHalf 0x4000
+#define hwr328UTransmitTxAvail 0x2000
+#define hwr328UTransmitSendBreak 0x1000
+#define hwr328UTransmitIgnoreCTS 0x0800
+#define hwr328UTransmitCTSStatus 0x0200
+#define hwr328UTransmitCTSDelta 0x0100
+#define hwr328UTransmitData 0x00FF
+
+// uMisc Register
+#define hwr328UMiscClkSrcGPIO 0x4000
+#define hwr328UMiscForceParityErr 0x2000
+#define hwr328UMiscLoopback 0x1000
+#define hwr328UMiscReservedMask 0x8F00
+#define hwr328UMiscRTSThruFIFO 0x0080
+#define hwr328UMiscRTSOut 0x0040
+#define hwr328UMiscIRDAEn 0x0020
+#define hwr328UMiscLoopIRDA 0x0010
+#define hwr328UMiscUnused 0x000F
+
+
+
+/************************************************************************
+ * PWM Bits
+ ************************************************************************/
+// PWM register bits of interest
+#define hwr328PWMControlEnable 0x0010
+#define hwr328PWMControlEnableBit 4
+#define hwr328PWMControlEnableIRQ 0x4000
+#define hwr328PWMControlLoad 0x0100
+#define hwr328PWMIRQStatus 0x8000
+// PWM divider chain output selectors
+#define hwr328PWMControlDivMask 0x0007
+#define hwr328PWMControlDivBy2 0x0
+#define hwr328PWMControlDivBy4 0x1
+#define hwr328PWMControlDivBy8 0x2
+#define hwr328PWMControlDivBy16 0x3
+#define hwr328PWMControlDivBy32 0x4
+#define hwr328PWMControlDivBy64 0x5
+#define hwr328PWMControlDivBy128 0x6
+#define hwr328PWMControlDivBy256 0x7
+
+
+/************************************************************************
+ * PLL Bits
+ ************************************************************************/
+#define hwr328PLLControlDisable 0x0008
+#define hwr328PLLControlClkEn 0x0010
+
+#define hwr328PLLControlSysVCODiv2 0x0000
+#define hwr328PLLControlSysVCODiv4 0x0100
+#define hwr328PLLControlSysVCODiv8 0x0200
+#define hwr328PLLControlSysVCODiv16 0x0300
+#define hwr328PLLControlSysVCODiv1 0x0400
+
+#define hwr328PLLControlPixVCODiv2 0x0000
+#define hwr328PLLControlPixVCODiv4 0x080
+#define hwr328PLLControlPixVCODiv8 0x1000
+#define hwr328PLLControlPixVCODiv16 0x1800
+#define hwr328PLLControlPixVCODiv1 0x2000
+
+/************************************************************************
+ * Real Time Clock (RTC) Bits
+ ************************************************************************/
+
+// RTC Control Register (RTCCTL) bits
+#define hwr328RTCControlRTCEnable 0x80
+#define hwr328RTCControlRefSelMask 0x20
+#define hwr328RTCControlRefSel38400 0x20 // 38.4 kHz reference frequency
+#define hwr328RTCControlRefSel32768 0x00 // 32.768 kHz reference frequency
+
+// RTC Interrupt Enable Register (RTCIENR) bits
+#define hwr328RTCIntEnableSec 0x10
+#define hwr328RTCIntEnable24Hr 0x08
+#define hwr328RTCIntEnableAlarm 0x04
+#define hwr328RTCIntEnableMinute 0x02
+#define hwr328RTCIntEnableStopWatch 0x01
+
+// RTC Interrupt Status Register bits
+#define hwr328RTCIntStatusSec 0x10
+#define hwr328RTCIntStatus24Hr 0x08
+#define hwr328RTCIntStatusAlarm 0x04
+#define hwr328RTCIntStatusMinute 0x02
+#define hwr328RTCIntStatusStopWatch 0x01
+
+// RTC Alarm register (RTCALRM) masks and offsets
+#define hwr328RTCAlarmSecondsMask 0x0000003fL
+#define hwr328RTCAlarmSecondsOffset 0
+#define hwr328RTCAlarmMinutesMask 0x003f0000L
+#define hwr328RTCAlarmMinutesOffset 16
+#define hwr328RTCAlarmHoursMask 0x1f000000L
+#define hwr328RTCAlarmHoursOffset 24
+
+// RTC hours/minutes/seconds register (RTCHMS) masks and offsets
+#define hwr328RTCHourMinSecSecondsMask 0x0000003fL
+#define hwr328RTCHourMinSecSecondsOffset 0
+#define hwr328RTCHourMinSecMinutesMask 0x003f0000L
+#define hwr328RTCHourMinSecMinutesOffset 16
+#define hwr328RTCHourMinSecHoursMask 0x1f000000L
+#define hwr328RTCHourMinSecHoursOffset 24
+
+
+/************************************************************************
+ * SPI Master bits
+ ************************************************************************/
+#define hwr328SPIMControlRateMask 0xE000
+ #define hwr328SPIMControlRateDiv4 0x0000
+ #define hwr328SPIMControlRateDiv8 0x2000
+ #define hwr328SPIMControlRateDiv16 0x4000
+ #define hwr328SPIMControlRateDiv32 0x6000
+ #define hwr328SPIMControlRateDiv64 0x8000
+ #define hwr328SPIMControlRateDiv128 0xA000
+ #define hwr328SPIMControlRateDiv256 0xC000
+ #define hwr328SPIMControlRateDiv512 0xE000
+#define hwr328SPIMControlEnable 0x0200
+#define hwr328SPIMControlExchange 0x0100
+#define hwr328SPIMControlIntStatus 0x0080
+#define hwr328SPIMControlIntEnable 0x0040
+#define hwr328SPIMControlOppPhase 0x0020
+#define hwr328SPIMControlInvPolarity 0x0010
+#define hwr328SPIMControlBitsMask 0x000F
+
+
+/************************************************************************
+ * I/O Port C pins
+ ************************************************************************/
+#define hwr328PortCMOClk 0x01
+#define hwr328PortCUDS 0x02
+#define hwr328PortCLDS 0x04
+#define hwr328PortCNMI 0x10
+#define hwr328PortCDTack 0x20
+#define hwr328PortCPcmciaWE 0x40
+
+
+/************************************************************************
+ * I/O Port G pins
+ ************************************************************************/
+#define hwr328PortGUartTxD 0x01
+#define hwr328PortGUartRxD 0x02
+#define hwr328PortGPwmOut 0x04
+#define hwr328PortGTOut2 0x08
+#define hwr328PortGTIn2 0x10
+#define hwr328PortGTOut1 0x20
+#define hwr328PortGTIn1 0x40
+#define hwr328PortGRtcOut 0x80
+
+
+/************************************************************************
+ * I/O Port K pins
+ ************************************************************************/
+#define hwr328PortKSpimTxD 0x01
+#define hwr328PortKSpimRxD 0x02
+#define hwr328PortKSpimClkO 0x04
+#define hwr328PortKSpisEn 0x08
+#define hwr328PortKSpisRxD 0x10
+#define hwr328PortKSpisClkI 0x20
+#define hwr328PortKPcmciaCE2 0x40
+#define hwr328PortKPcmciaCE1 0x80
+
+
+/************************************************************************
+ * I/O Port M pins
+ ************************************************************************/
+#define hwr328PortMCTS 0x01
+#define hwr328PortMRTS 0x02
+#define hwr328PortMIRQ6 0x04
+#define hwr328PortMIRQ3 0x08
+#define hwr328PortMIRQ2 0x10
+#define hwr328PortMIRQ1 0x20
+#define hwr328PortMPenIRQ 0x40
+#define hwr328PortMUnused7 0x80
+
+
+
+
+
+#endif // __M68328_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68EZ328Hwr.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68EZ328Hwr.h
new file mode 100644
index 0000000..0645d09
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68EZ328Hwr.h
@@ -0,0 +1,708 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: M68EZ328Hwr.h
+ *
+ * Description:
+ * Hardware Equates for the Motorola 68EZ328 Dragonball-EZ chip
+ *
+ * History:
+ * 11/13/97 srj Created from M68328Hwr.h
+ * 3/30/99 jrb Added JerryEZ pld defines
+ * 4/ 5/99 jrb Added JerryEZ pld shadow register bit defines
+ * 5/31/99 SCL Moved hwr68328Base into this file from <HardwarePrv.h>
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So apps don't include this...
+
+
+#ifndef __M68EZ328HWR_H__
+#define __M68EZ328HWR_H__
+
+
+#include <PalmTypes.h> // Touchdown includes
+
+
+// Define location of the 68328 Dragonball chip
+#define hwr68328Base 0xFFFFF000L // Base address of 68328
+
+
+/***********************************************************************
+ * Motorola 68328 registers
+ ***********************************************************************/
+struct HwrM68EZ328Type {
+
+ UInt8 scr; // $000: System Control Register
+ UInt8 ___filler0[0x004-0x001];
+ UInt8 chipID; // $004: Chip ID Register
+ UInt8 maskID; // $005: Mask ID Register
+ UInt16 swID; // $006: Software ID Register
+ UInt8 ___filler1[0x100-0x008];
+
+ UInt16 csAGroupBase; // $100: Chip Select Group A Base Register
+ UInt16 csBGroupBase; // $102: Chip Select Group B Base Register
+ UInt16 csCGroupBase; // $104: Chip Select Group C Base Register
+ UInt16 csDGroupBase; // $106: Chip Select Group D Base Register
+
+ UInt8 ___filler6[0x110-0x108];
+
+ UInt16 csASelect; // $110: Group A Chip Select Register
+ UInt16 csBSelect; // $112: Group B Chip Select Register
+ UInt16 csCSelect; // $114: Group C Chip Select Register
+ UInt16 csDSelect; // $116: Group D Chip Select Register
+
+ UInt16 emuCS; // $118: EMU Chip Select Register
+
+ UInt8 ___filler2[0x200-0x11A];
+
+ UInt16 pllControl; // $200: PLL Control Register
+ UInt16 pllFreqSel; // $202: PLL Frequency Select Register
+ UInt16 pllTest; // $204: PLL Test Register (do not access)
+ UInt8 ___filler44;
+ UInt8 pwrControl; // $207: Power Control Register
+
+ UInt8 ___filler3[0x300-0x208];
+
+ UInt8 intVector; // $300: Interrupt Vector Register
+ UInt8 ___filler4;
+ UInt16 intControl; // $302: Interrupt Control Register
+ UInt16 intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ UInt16 intMaskLo; // $306: Interrupt Mask Register/LOW word
+ UInt8 ___filler7[0x30c-0x308];
+ UInt16 intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ UInt16 intStatusLo; // $30E: Interrupt Status Register/LOW word
+ UInt16 intPendingHi; // $310: Interrupt Pending Register
+ UInt16 intPendingLo; // $312: Interrupt Pending Register
+
+ UInt8 ___filler4a[0x400-0x314];
+
+ UInt8 portADir; // $400: Port A Direction Register
+ UInt8 portAData; // $401: Port A Data Register
+ UInt8 portAPullupEn; // $402: Port A Pullup Enable (similar to Select on DB)
+ UInt8 ___filler8[5];
+
+ UInt8 portBDir; // $408: Port B Direction Register
+ UInt8 portBData; // $409: Port B Data Register
+ UInt8 portBPullupEn; // $40A: Port B Pullup Enable
+ UInt8 portBSelect; // $40B: Port B Select Register
+
+ UInt8 ___filler9[4];
+
+ UInt8 portCDir; // $410: Port C Direction Register
+ UInt8 portCData; // $411: Port C Data Register
+ UInt8 portCPulldnEn; // $412: Port C Pulldown Enable
+ UInt8 portCSelect; // $413: Port C Select Register
+
+ UInt8 ___filler10[4];
+
+ UInt8 portDDir; // $418: Port D Direction Register
+ UInt8 portDData; // $419: Port D Data Register
+ UInt8 portDPullupEn; // $41A: Port D Pull-up Enable
+ UInt8 portDSelect; // $41B: Port D Select Register
+ UInt8 portDPolarity; // $41C: Port D Polarity Register
+ UInt8 portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ UInt8 portDKbdIntEn; // $41E: Port D Keyboard Interrupt Enable
+ UInt8 portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ UInt8 portEDir; // $420: Port E Direction Register
+ UInt8 portEData; // $421: Port E Data Register
+ UInt8 portEPullupEn; // $422: Port E Pull-up Enable
+ UInt8 portESelect; // $423: Port E Select Register
+
+ UInt8 ___filler14[4];
+
+ UInt8 portFDir; // $428: Port F Direction Register
+ UInt8 portFData; // $429: Port F Data Register
+ UInt8 portFPullupdnEn; // $42A: Port F Pull-up/down Enable
+ UInt8 portFSelect; // $42B: Port F Select Register
+
+ UInt8 ___filler16[4];
+
+ UInt8 portGDir; // $430: Port G Direction Register
+ UInt8 portGData; // $431: Port G Data Register
+ UInt8 portGPullupEn; // $432: Port G Pull-up Enable
+ UInt8 portGSelect; // $433: Port G Select Register
+
+ UInt8 ___filler2000[0x500-0x434];
+
+ UInt16 pwmControl; // $500: PWM Control Register
+ UInt8 pwmSampleHi; // $502: PWM Sample - high byte
+ UInt8 pwmSampleLo; // $503: PWM Sample - low byte
+ UInt8 pwmPeriod; // $504: PWM Period
+ UInt8 pwmCounter; // $505: PWM Counter
+
+ UInt8 ___filler24[0x600-0x506];
+
+ UInt16 tmr1Control; // $600: Timer 1 Control Register
+ UInt16 tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ UInt16 tmr1Compare; // $604: Timer 1 Compare Register
+ UInt16 tmr1Capture; // $606: Timer 1 Capture Register
+ UInt16 tmr1Counter; // $608: Timer 1 Counter Register
+ UInt16 tmr1Status; // $60A: Timer 1 Status Register
+
+ UInt8 ___filler25[0x800-0x60C];
+
+ UInt16 spiMasterData; // $800: SPI Master Data Register
+ UInt16 spiMasterControl; // $802: SPI Master Control Register
+
+ UInt8 ___filler27[0x900-0x804];
+
+ UInt16 uControl; // $900: Uart Control Register
+ UInt16 uBaud; // $902: Uart Baud Control Register
+ UInt16 uReceive; // $904: Uart Receive Register
+ UInt16 uTransmit; // $906: Uart Transmit Register
+ UInt16 uMisc; // $908: Uart Miscellaneous Register
+ UInt16 uNonIntPresc; // $90A: Uart IRDA Non-Integer Prescaler
+
+ UInt8 ___filler28[0xA00-0x90C];
+
+ UInt32 lcdStartAddr; // $A00: Screen Starting Address Register
+ UInt8 ___filler29;
+ UInt8 lcdPageWidth; // $A05: Virtual Page Width Register
+ UInt8 ___filler30[2];
+ UInt16 lcdScreenWidth; // $A08: Screen Width Register
+ UInt16 lcdScreenHeight; // $A0A: Screen Height Register
+ UInt8 ___filler31[0xA18-0xA0C];
+ UInt16 lcdCursorXPos; // $A18: Cursor X Position
+ UInt16 lcdCursorYPos; // $A1A: Cursor Y Position
+ UInt16 lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ UInt8 ___filler32;
+ UInt8 lcdBlinkControl; // $A1F: Blink Control Register
+ UInt8 lcdPanelControl; // $A20: Panel Interface Control Register
+ UInt8 lcdPolarity; // $A21: Polarity Config Register
+ UInt8 ___filler33;
+ UInt8 lcdACDRate; // $A23: ACD (M) Rate Control Register
+ UInt8 ___filler34;
+ UInt8 lcdPixelClock; // $A25: Pixel Clock Divider Register
+ UInt8 ___filler35;
+ UInt8 lcdClockControl; // $A27: Clocking Control Register
+ UInt8 ___filler36;
+ UInt8 lcdRefreshRateAdj; // $A29: Refresh Rate Adjustment Register
+ UInt8 ___filler2003[0xA2D-0xA2A];
+ UInt8 lcdPanningOffset; // $A2D: Panning Offset Register
+
+ UInt8 ___filler37[0xA31-0xA2E];
+
+ UInt8 lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ UInt8 ___filler2004;
+ UInt8 lcdGrayPalette; // $A33: Gray Palette Mapping Register
+ UInt8 lcdReserved; // $A34: Reserved
+ UInt8 ___filler2005;
+ UInt16 lcdContrastControlPWM; // $A36: Contrast Control
+
+ UInt8 ___filler40[0xB00-0xA38];
+
+ UInt32 rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ UInt32 rtcAlarm; // $B04: RTC Alarm Register
+ UInt8 ___filler2001[0xB0A-0xB08];
+ UInt16 rtcWatchDog; // $B0A: RTC Watchdog Timer
+ UInt16 rtcControl; // $B0C: RTC Control Register
+ UInt16 rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ UInt16 rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ UInt16 stopWatch; // $B12: Stopwatch Minutes
+ UInt8 ___filler2002[0xB1A-0xB14];
+ UInt16 rtcDay; // $B1A: RTC Day
+ UInt16 rtcDayAlarm; // $B1C: RTC Day Alarm
+
+ UInt8 ___filler41[0xC00-0xB1E];
+
+ UInt16 dramConfig; // $C00: DRAM Memory Config Register
+ UInt16 dramControl; // $C02: DRAM Control Register
+
+ UInt8 ___filler42[0xD00-0xC04];
+
+ UInt32 emuAddrCompare; // $D00: Emulation Address Compare Register
+ UInt32 emuAddrMask; // $D04: Emulation Address Mask Register
+ UInt16 emuControlCompare; // $D08: Emulation Control Compare Register
+ UInt16 emuControlMask; // $D0A: Emulation Control Mask Register
+ UInt16 emuControl; // $DOC: Emulation Control Register
+ UInt16 emuStatus; // $D0E: Emulation Status Register
+};
+
+typedef volatile struct HwrM68EZ328Type* HwrM68EZ328Ptr;
+
+#define HwrDBallType HwrM68EZ328Type
+#define HwrDBallPtr HwrM68EZ328Ptr
+
+
+/************************************************************************
+ * Jerry EZ cost reduction PLD I/O register
+ ***********************************************************************/
+typedef struct HwrJerryPLDType {
+
+ UInt8 dspOn; // pld output turn dsp on/off
+ UInt8 unused1;
+ UInt8 chargeOn; // pld output turn charger on/off
+ UInt8 unused2;
+ UInt8 refOn; // pld output turn 3.0 volt reference on/off
+ UInt8 unused3;
+ UInt8 pipaBiasEnable; // pld output turn PA bias on/off
+ UInt8 unused4;
+ UInt8 dspReset; // pld output control dsp reset pin up/down
+ UInt8 unused5;
+ UInt8 ezToDsl; // pld output comm. pin to dsp
+ UInt8 unused6;
+ UInt8 rs232Shdn; // pld output control rs232 interface chip on/off
+ UInt8 unused7;
+ UInt8 spareOut; // pld output not used
+ UInt8 unused8;
+ UInt16 dTo3Sln; // pld input comm. from dsp
+ UInt16 iXtrnl2; // pld input cradle connector pin
+} HwrJerryPLDType;
+
+typedef volatile HwrJerryPLDType* HwrJerryPldPtr;
+
+/************************************************************************
+ * Jerry EZ cost reduction. PLD settings
+ ***********************************************************************/
+#define hwrJerryPld232Enable 0x80
+#define hwrJerryPld232Disable 0
+#define hwrJerryPldChargerOn 0x80
+#define hwrJerryPldChargerOff 0
+#define hwrJerryPldPaBiasEnable 0x80
+#define hwrJerryPldPaBiasDisable 0
+#define hwrJerryPldRefOn 0x80
+#define hwrJerryPldRefOff 0
+#define hwrJerryPldDspSelect 0x80
+#define hwrJerryPldDspDeselect 0
+#define hwrJerryPldDspResetAssert 0x80
+#define hwrJerryPldDspResetDeassert 0
+#define hwrJerryPldDspPowerOn 0x80
+#define hwrJerryPldDspPowerOff 0
+
+/************************************************************************
+ * Jerry EZ cost reduction. PLD shadow settings
+ ***********************************************************************/
+#define hwrJerryPldDspOnBit 0x0001
+#define hwrJerryPldChargeOnBit 0x0002
+#define hwrJerryPldRefOnBit 0x0004
+#define hwrJerryPldPaBiasEnableBit 0x0008
+#define hwrJerryPldDspResetBit 0x0010
+#define hwrJerryPldEzToDslBit 0x0020
+#define hwrJerryPldRs232Bit 0x0040
+
+/************************************************************************
+ * Chip ID register for EZ
+ ***********************************************************************/
+ #define hwrEZ328chipIDEZ 0x45
+
+/************************************************************************
+ * Mask ID register for EZ
+ ***********************************************************************/
+#define hwrEZ328maskID0H31J 0x01
+#define hwrEZ328maskID0J75C 0x02
+#define hwrEZ328maskID1J75C 0x03
+#define hwrEZ328maskID0J83G 0x04
+
+/************************************************************************
+ * LCD Controller Bits
+ ************************************************************************/
+// lcdCursorXPos Register
+#define hwrEZ328LcdCursorXPosCtlMask 0xC000
+ #define hwrEZ328LcdCursorXPosCtlTrans 0x0000
+ #define hwrEZ328LcdCursorXPosCtlBlack 0x4000
+ #define hwrEZ328LcdCursorXPosCtlReverse 0x8000
+ #define hwrEZ328LcdCursorXPosCtlWhite 0xC000
+#define hwrEZ328LcdCursorXPosValueMask 0x1FF
+#define hwrEZ328LcdCursorYPosValueMask 0x1FF
+
+#define hwrEZ328LcdCursorWidthMask 0x1F
+ #define hwrEZ328LcdCursorWidthOffset 0x8
+#define hwrEZ328LcdCursorHeightMask 0x1F
+
+// lcdBlinkControl Register
+#define hwrEZ328LcdBlinkControlEnable 0x80
+#define hwrEZ328LcdBlinkDivisorMask 0x7F
+
+// lcdPanelControl Register
+#define hwrEZ328LcdPanelControlBusMask 0x0C
+ #define hwrEZ328LcdPanelControlBus1Bit 0x00
+ #define hwrEZ328LcdPanelControlBus2Bit 0x04
+ #define hwrEZ328LcdPanelControlBus4Bit 0x08
+#define hwrEZ328LcdPanelControlGrayScale 0x01
+#define hwrEZ328LcdPanelControl4BitGrayScale 0x02
+
+// lcdPolarity Register
+#define hwrEZ328LcdPolarityShiftClock 0x08
+#define hwrEZ328LcdPolarityFLM 0x04
+#define hwrEZ328LcdPolarityLP 0x02
+#define hwrEZ328LcdPolarityPixel 0x01
+
+// lcdClockControl Register
+#define hwrEZ328LcdClockControlEnable 0x80
+#define hwrEZ328LcdClockControl8BitBus 0x40
+
+#define hwrEZ328LcdClockControlBurstRateMask 0x0F
+#define hwrEZ328LcdClockControlBurstRate1 0x00
+#define hwrEZ328LcdClockControlBurstRate2 0x01
+#define hwrEZ328LcdClockControlBurstRate3 0x02
+#define hwrEZ328LcdClockControlBurstRate4 0x03
+#define hwrEZ328LcdClockControlBurstRate5 0x04
+#define hwrEZ328LcdClockControlBurstRate6 0x05
+#define hwrEZ328LcdClockControlBurstRate7 0x06
+#define hwrEZ328LcdClockControlBurstRate8 0x07
+#define hwrEZ328LcdClockControlBurstRate9 0x08
+#define hwrEZ328LcdClockControlBurstRate10 0x09
+#define hwrEZ328LcdClockControlBurstRate11 0x0A
+#define hwrEZ328LcdClockControlBurstRate12 0x0B
+#define hwrEZ328LcdClockControlBurstRate13 0x0C
+#define hwrEZ328LcdClockControlBurstRate14 0x0D
+#define hwrEZ328LcdClockControlBurstRate15 0x0E
+#define hwrEZ328LcdClockControlBurstRate16 0x0F
+
+#define hwrEZ328LcdContrastPWMWidthMask 0x00FF
+#define hwrEZ328LcdContrastEnable 0x0100
+
+
+
+/************************************************************************
+ * Interrupt Controller Bits
+ ************************************************************************/
+// intMaskHi bits
+// NOTE: Due to a bug in early rev's of the DragonBall, the clear bits for
+// IRQ[1236] on those early chips were different than the indicator bits
+// (the order was reversed). So some older code uses the OR of the IRQ1 and
+// IRQ6 bits for either, and the OR of the IRQ2 and IRQ3 bits for either.
+#define hwrEZ328IntHiEMU 0x0080
+#define hwrEZ328IntHiSampleTimer 0x0040
+#define hwrEZ328IntHiPen 0x0010
+#define hwrEZ328IntHiIRQ6 0x0008
+#define hwrEZ328IntHiIRQ3 0x0004
+#define hwrEZ328IntHiIRQ2 0x0002
+#define hwrEZ328IntHiIRQ1 0x0001
+
+// intMaskLo bits
+#define hwrEZ328IntLoInt3 0x0800
+#define hwrEZ328IntLoInt2 0x0400
+#define hwrEZ328IntLoInt1 0x0200
+#define hwrEZ328IntLoInt0 0x0100
+#define hwrEZ328IntLoAllKeys 0x0F00
+#define hwrEZ328IntLoInt0Bit 8
+#define hwrEZ328IntLoPWM 0x0080
+#define hwrEZ328IntLoPWMBit 7
+#define hwrEZ328IntLoKbd 0x0040
+#define hwrEZ328IntLoRTC 0x0010
+#define hwrEZ328IntLoRTCBit 4
+#define hwrEZ328IntLoWDT 0x0008
+#define hwrEZ328IntLoUART 0x0004
+#define hwrEZ328IntLoUARTBit 2
+#define hwrEZ328IntLoTimer 0x0002
+#define hwrEZ328IntLoTimerBit 1
+#define hwrEZ328IntLoSPIM 0x0001
+
+// intControl bits
+// NOTE: These are different than that documented in the User's manual
+// for the DragonBall (see erratas). The DragonBall is the same as the EZ.
+#define hwrEZ328IntCtlEdge1 0x0800
+#define hwrEZ328IntCtlEdge2 0x0400
+#define hwrEZ328IntCtlEdge3 0x0200
+#define hwrEZ328IntCtlEdge6 0x0100
+#define hwrEZ328IntCtlPol1 0x8000
+#define hwrEZ328IntCtlPol2 0x4000
+#define hwrEZ328IntCtlPol3 0x2000
+#define hwrEZ328IntCtlPol6 0x1000
+#define hwrEZ328IntCtlPol5 0x0080
+
+/************************************************************************
+ * DRAM Controller Bits bits
+ * Not all the bits are defined here-- some are pretty bad to muck with
+ * in anything but initial setup of the DRAM.
+ ************************************************************************/
+#define hwrEZ328dramControlEnable 0x8000
+#define hwrEZ328dramControlSelfRefreshEn 0x4000
+#define hwrEZ328dramControlLightSleep 0x0010
+#define hwrEZ328dramControlLowPowerRefreshEn 0x0004
+#define hwrEZ328dramControlDWEEnable 0x0001
+
+
+/************************************************************************
+ * Timer bits
+ ************************************************************************/
+#define hwrEZ328TmrControlUnused 0xFC00
+#define hwrEZ328TmrControlTIOOutput 0x0200
+#define hwrEZ328TmrControlFreeRun 0x0100
+#define hwrEZ328TmrControlCaptureEdgeMask 0x00C0
+ #define hwrEZ328TmrControlCaptureEdgeNone 0x0000
+ #define hwrEZ328TmrControlCaptureEdgeRising 0x0040
+ #define hwrEZ328TmrControlCaptureEdgeFalling 0x0080
+ #define hwrEZ328TmrControlCaptureEdgeBoth 0x00C0
+#define hwrEZ328TmrControlOutputModeToggle 0x0020
+#define hwrEZ328TmrControlEnInterrupt 0x0010
+#define hwrEZ328TmrControlClkSrcMask 0x000E
+ #define hwrEZ328TmrControlClkSrcStop 0x0000
+ #define hwrEZ328TmrControlClkSrcSys 0x0002
+ #define hwrEZ328TmrControlClkSrcSysBy16 0x0004
+ #define hwrEZ328TmrControlClkSrcTIN 0x0006
+ #define hwrEZ328TmrControlClkSrc32KHz 0x0008
+#define hwrEZ328TmrControlEnable 0x0001
+
+#define hwrEZ328TmrStatusCapture 0x0002
+#define hwrEZ328TmrStatusCaptureBit 1
+#define hwrEZ328TmrStatusCompare 0x0001
+#define hwrEZ328TmrStatusCompareBit 0
+
+
+/************************************************************************
+ * 68EZ328 Serial Port Register Bits
+ ************************************************************************/
+// uControl Register
+#define hwrEZ328UControlUARTEnable 0x8000
+#define hwrEZ328UControlRxEnable 0x4000
+#define hwrEZ328UControlTxEnable 0x2000
+#define hwrEZ328UControlRxClock1xSync 0x1000
+#define hwrEZ328UControlParityEn 0x0800
+#define hwrEZ328UControlParityOdd 0x0400
+#define hwrEZ328UControlStopBits2 0x0200
+#define hwrEZ328UControlDataBits8 0x0100
+#define hwrEZ328UControlOldDataEn 0x0080
+#define hwrEZ328UControlCTSDeltaEn 0x0040
+#define hwrEZ328UControlRxFullEn 0x0020
+#define hwrEZ328UControlRxHalfEn 0x0010
+#define hwrEZ328UControlRxRdyEn 0x0008
+#define hwrEZ328UControlTxEmptyEn 0x0004
+#define hwrEZ328UControlTxHalfEn 0x0002
+#define hwrEZ328UControlTxAvailEn 0x0001
+
+#define hwrEZ328UControlEnableAll (hwrEZ328UControlUARTEnable | \
+ hwrEZ328UControlRxEnable | \
+ hwrEZ328UControlTxEnable)
+
+// uBaud Register
+// UCLK output requires PE3 Select to be 0
+#define hwrEZ328UBaudUCLKDirOut 0x2000
+#define hwrEZ328UBaudBaudSrcUCLK 0x0800
+#define hwrEZ328UBaudDivider 0x0700
+#define hwrEZ328UBaudPrescaler 0x003F
+
+#define hwrEZ328UBaudDivideBitOffset 8
+
+
+// uReceive Register
+#define hwrEZ328UReceiveFIFOFull 0x8000
+#define hwrEZ328UReceiveFIFOHalf 0x4000
+#define hwrEZ328UReceiveDataRdy 0x2000
+#define hwrEZ328UReceiveDataRdyBit 13
+#define hwrEZ328UReceiveOldData 0x1000
+#define hwrEZ328UReceiveOverrunErr 0x0800
+#define hwrEZ328UReceiveOverrunErrBit 11
+#define hwrEZ328UReceiveFrameErr 0x0400
+#define hwrEZ328UReceiveFrameErrBit 10
+#define hwrEZ328UReceiveBreakErr 0x0200
+#define hwrEZ328UReceiveBreakErrBit 9
+#define hwrEZ328UReceiveParityErr 0x0100
+#define hwrEZ328UReceiveParityErrBit 8
+#define hwrEZ328UReceiveData 0x00FF
+
+#define hwrEZ328UReceiveErrsMask (hwrEZ328UReceiveOverrunErr | \
+ hwrEZ328UReceiveFrameErr | \
+ hwrEZ328UReceiveBreakErr | \
+ hwrEZ328UReceiveParityErr)
+
+// uTransmit Register
+#define hwrEZ328UTransmitFIFOEmpty 0x8000
+#define hwrEZ328UTransmitFIFOHalf 0x4000
+#define hwrEZ328UTransmitTxAvail 0x2000
+#define hwrEZ328UTransmitSendBreak 0x1000
+#define hwrEZ328UTransmitIgnoreCTS 0x0800
+#define hwrEZ328UTransmitBusy 0x0400
+#define hwrEZ328UTransmitCTSStatus 0x0200
+#define hwrEZ328UTransmitCTSDelta 0x0100
+#define hwrEZ328UTransmitData 0x00FF
+
+// uMisc Register
+#define hwrEZ328UMiscBaudTest 0x8000
+#define hwrEZ328UMiscClkSrcUCLK 0x4000
+#define hwrEZ328UMiscForceParityErr 0x2000
+#define hwrEZ328UMiscLoopback 0x1000
+#define hwrEZ328UMiscBaudReset 0x0800
+#define hwrEZ328UMiscIRTestEn 0x0400
+#define hwrEZ328UMiscReservedMask 0x0300
+#define hwrEZ328UMiscRTSThruFIFO 0x0080
+#define hwrEZ328UMiscRTSOut 0x0040
+#define hwrEZ328UMiscIRDAEn 0x0020
+#define hwrEZ328UMiscLoopIRDA 0x0010
+#define hwrEZ328UMiscRXPolarityInv 0x0008
+#define hwrEZ328UMiscTXPolarityInv 0x0004
+#define hwrEZ328UMiscUnused 0x0003
+
+// uNonIntPresc Register
+#define hwrEZ328UNonIntPrescSrcIntPresc 0x0000
+#define hwrEZ328UNonIntPrescSrcNonIntPresc 0x8000
+
+#define hwrEZ328UNonIntPrescSelDiv128 0x0000
+#define hwrEZ328UNonIntPrescSelDiv64 0x0100
+#define hwrEZ328UNonIntPrescSelDiv32 0x0200
+#define hwrEZ328UNonIntPrescSelDiv16 0x0300
+#define hwrEZ328UNonIntPrescSelDiv8 0x0400
+#define hwrEZ328UNonIntPrescSelDiv4 0x0500
+#define hwrEZ328UNonIntPrescSelDiv2 0x0600
+#define hwrEZ328UNonIntPrescSelDiv1 0x0700
+
+#define hwrEZ328UNonIntPrescStepMask 0x00FF
+#define hwrEZ328UNonIntPrescSelOffset 8
+
+// see EZ docs for explanation of the following. This provides the correct
+// pulse width for IRDA, and is just a statement in the docs. The values don't
+// appear to make sense, but I just push the buttons.
+
+// This has been deprecated in favor of a prv function in the serial driver and
+// the SerialMgr (depending on whether you have Bond or not) that calculates
+// the value of this register based on the clock frequency you're running on.
+// There was a bug when running EZ at 20MHz that caused the IrDA pulsewidth to
+// get too short.
+
+#if 0
+#define hwrEZ328UNonIntPrescIRDAMode (hwrEZ328UNonIntPrescSrcIntPresc \
+ | hwrEZ328UNonIntPrescSelDiv32 \
+ | (hwrEZ328UNonIntPrescStepMask & 0x20))
+#endif
+
+/************************************************************************
+ * PWM Bits
+ ************************************************************************/
+// PWM register bits of interest
+#define hwrEZ328PWMControlEnable 0x0010
+#define hwrEZ328PWMControlEnableBit 4
+#define hwrEZ328PWMControlEnableIRQ 0x0040
+#define hwrEZ328PWMIRQStatus 0x0080
+// PWM divider chain output selectors
+#define hwrEZ328PWMControlDivMask 0x0003
+#define hwrEZ328PWMControlDivBy2 0x0
+#define hwrEZ328PWMControlDivBy4 0x1
+#define hwrEZ328PWMControlDivBy8 0x2
+#define hwrEZ328PWMControlDivBy16 0x3
+// PWM Repeat Counts
+#define hwrEZ328PWMRepeatSample1x 0x0
+#define hwrEZ328PWMRepeatSample2x 0x4
+#define hwrEZ328PWMRepeatSample4x 0x8
+#define hwrEZ328PWMRepeatSample8x 0xC
+// PWM hardware constraints
+#define hwrEZ328PWMFifoSizeInBytes 4
+#define hwrEZ328PWMPrescalerMask 0x7F00
+#define hwrEZ328PWMPrescalerOffset 8
+
+/************************************************************************
+ * PLL Bits
+ * note that these do not follow the '328 spec-- however, they seem to
+ * follow the 'EZ328 spec, so maybe Motorola is behind in their tech pubs
+ * department?? (Naah.)
+ ************************************************************************/
+#define hwrEZ328PLLControlDisable 0x0008
+#define hwrEZ328PLLControlClkEn 0x0010
+
+#define hwrEZ328PLLControlSysDMADiv2 0x0000
+#define hwrEZ328PLLControlSysDMADiv4 0x0100
+#define hwrEZ328PLLControlSysDMADiv8 0x0200
+#define hwrEZ328PLLControlSysDMADiv16 0x0300
+#define hwrEZ328PLLControlSysDMADiv1 0x0400
+
+#define hwrEZ328PLLControlPixDMADiv2 0x0000
+#define hwrEZ328PLLControlPixDMADiv4 0x0800
+#define hwrEZ328PLLControlPixDMADiv8 0x1000
+#define hwrEZ328PLLControlPixDMADiv16 0x1800
+#define hwrEZ328PLLControlPixDMADiv1 0x2000
+
+#define hwrEZ328PLLControlDMAVCODiv2 0x0000
+#define hwrEZ328PLLControlDMAVCODiv4 0x0020
+#define hwrEZ328PLLControlDMAVCODiv8 0x0040
+#define hwrEZ328PLLControlDMAVCODiv16 0x0060
+#define hwrEZ328PLLControlDMAVCODiv1 0x0080
+
+#define hwrEZ328PLLFreqSelCLK32 0x8000
+
+/************************************************************************
+ * Real Time Clock (RTC) Bits
+ ************************************************************************/
+
+// RTC Control Register (RTCCTL) bits
+#define hwrEZ328RTCControlRTCEnable 0x80
+#define hwrEZ328RTCControlRefSelMask 0x20
+#define hwrEZ328RTCControlRefSel38400 0x20 // 38.4 kHz reference frequency
+#define hwrEZ328RTCControlRefSel32768 0x00 // 32.768 kHz reference frequency
+
+// RTC Interrupt Enable Register (RTCIENR) bits
+#define hwrEZ328RTCIntEnableSample7 0x8000
+#define hwrEZ328RTCIntEnableSample6 0x4000
+#define hwrEZ328RTCIntEnableSample5 0x2000
+#define hwrEZ328RTCIntEnableSample4 0x1000
+#define hwrEZ328RTCIntEnableSample3 0x0800
+#define hwrEZ328RTCIntEnableSample2 0x0400
+#define hwrEZ328RTCIntEnableSample1 0x0200
+#define hwrEZ328RTCIntEnableSample0 0x0100
+#define hwrEZ328RTCIntEnableHour 0x0020
+#define hwrEZ328RTCIntEnableSec 0x0010
+#define hwrEZ328RTCIntEnable24Hr 0x0008
+#define hwrEZ328RTCIntEnableAlarm 0x0004
+#define hwrEZ328RTCIntEnableMinute 0x0002
+#define hwrEZ328RTCIntEnableStopWatch 0x0001
+
+// RTC Interrupt Status Register bits
+#define hwrEZ328RTCIntStatusSample7 0x8000
+#define hwrEZ328RTCIntStatusSample6 0x4000
+#define hwrEZ328RTCIntStatusSample5 0x2000
+#define hwrEZ328RTCIntStatusSample4 0x1000
+#define hwrEZ328RTCIntStatusSample3 0x0800
+#define hwrEZ328RTCIntStatusSample2 0x0400
+#define hwrEZ328RTCIntStatusSample1 0x0200
+#define hwrEZ328RTCIntStatusSample0 0x0100
+#define hwrEZ328RTCIntStatusHour 0x0020
+#define hwrEZ328RTCIntStatusSec 0x0010
+#define hwrEZ328RTCIntStatus24Hr 0x0008
+#define hwrEZ328RTCIntStatusAlarm 0x0004
+#define hwrEZ328RTCIntStatusMinute 0x0002
+#define hwrEZ328RTCIntStatusStopWatch 0x0001
+
+// RTC Alarm register (RTCALRM) masks and offsets
+#define hwrEZ328RTCAlarmSecondsMask 0x0000003fL
+#define hwrEZ328RTCAlarmSecondsOffset 0
+#define hwrEZ328RTCAlarmMinutesMask 0x003f0000L
+#define hwrEZ328RTCAlarmMinutesOffset 16
+#define hwrEZ328RTCAlarmHoursMask 0x1f000000L
+#define hwrEZ328RTCAlarmHoursOffset 24
+
+// RTC hours/minutes/seconds register (RTCHMS) masks and offsets
+#define hwrEZ328RTCHourMinSecSecondsMask 0x0000003fL
+#define hwrEZ328RTCHourMinSecSecondsOffset 0
+#define hwrEZ328RTCHourMinSecMinutesMask 0x003f0000L
+#define hwrEZ328RTCHourMinSecMinutesOffset 16
+#define hwrEZ328RTCHourMinSecHoursMask 0x1f000000L
+#define hwrEZ328RTCHourMinSecHoursOffset 24
+
+// RTC Day register masks/offsets
+#define hwrEZ328RTCDayDayMask 0x01FF
+#define hwrEZ328RTCDayDayOffset 0
+
+// RTC Watchdog Timer masks/offsets
+#define hwrEZ328RTCWatchdogEnable 0x0001
+#define hwrEZ328RTCWatchdogIntSel 0x0002
+#define hwrEZ328RTCWatchdogIntStatus 0x0080
+#define hwrEZ328RTCWatchdogCountMask 0x0300
+#define hwrEZ328RTCWatchdogCountOffset 8
+
+/************************************************************************
+ * SPI Master bits
+ ************************************************************************/
+#define hwrEZ328SPIMControlRateMask 0xE000
+ #define hwrEZ328SPIMControlRateDiv4 0x0000
+ #define hwrEZ328SPIMControlRateDiv8 0x2000
+ #define hwrEZ328SPIMControlRateDiv16 0x4000
+ #define hwrEZ328SPIMControlRateDiv32 0x6000
+ #define hwrEZ328SPIMControlRateDiv64 0x8000
+ #define hwrEZ328SPIMControlRateDiv128 0xA000
+ #define hwrEZ328SPIMControlRateDiv256 0xC000
+ #define hwrEZ328SPIMControlRateDiv512 0xE000
+#define hwrEZ328SPIMControlEnable 0x0200
+#define hwrEZ328SPIMControlExchange 0x0100
+#define hwrEZ328SPIMControlIntStatus 0x0080
+#define hwrEZ328SPIMControlIntEnable 0x0040
+#define hwrEZ328SPIMControlOppPhase 0x0020
+#define hwrEZ328SPIMControlInvPolarity 0x0010
+#define hwrEZ328SPIMControlBitsMask 0x000F
+
+
+#endif // __M68EZ328_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68SZ328Hwr.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68SZ328Hwr.h
new file mode 100644
index 0000000..bfabe11
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68SZ328Hwr.h
@@ -0,0 +1,1078 @@
+/*******************************************************************
+ * Pilot Software
+ *
+ * Copyright(c) 1995-1999, Palm Computing Inc., All Rights Reserved
+ *
+ *-------------------------------------------------------------------
+ * FileName:
+ * M68SZ328Hwr.h
+ *
+ * Description:
+ * Hardware Equates for the Motorola 68SZ328 Dragonball-SZ chip
+ *
+ * History:
+ * 07/05/99 TJC Created; integrated from M68VZ328Hwr.h
+ *
+ *******************************************************************/
+
+#ifdef NON_PORTABLE // So apps don't include this...
+
+
+#ifndef __M68SZ328HWR_H__
+#define __M68SZ328HWR_H__
+
+#if INCLUDE_SECRET_STUFF
+
+
+#include <PalmTypes.h> // Touchdown includes
+
+
+// Define location of the 68328 Dragonball chip
+// Note: this is not the same as kMemoryStart in this chip
+#define hwr68328Base 0xFFFFF000L // Base address of 68328
+
+
+/***********************************************************************
+ * Motorola 68SZ328 registers
+ ***********************************************************************/
+struct HwrM68SZ328Type
+{
+ UInt16 dmaControl; // $00000: DMA Control Register
+ UInt16 dmaInterruptStatus; // $00002: DMA Interrupt Status Register
+ UInt16 dmaInterruptMask; // $00004: DMA Interrupt Mask Register
+ UInt16 dmaBurstTimeOutStatus; // $00006: DMA Burst Time-Out Status Register
+ UInt16 dmaRequestTimeOutStatus; // $00008: DMA Request Time-Out Status Register
+
+ // Note, the spaces around the minus sign are
+ // necessary. Without them, a proper compiler
+ // like gcc 3.0 thinks that the expression
+ // is an invalid scientific notion number.
+ UInt8 ___filler00[0x00E - 0x00A];
+
+ UInt16 dmaBurstTimeOutControl; // $0000E: DMA Burst Time-Out Control Register
+
+ UInt8 ___filler01[0x040-0x010];
+
+ UInt32 mem0SourceAddress; // $00040: Memory Channel 0 Source Address Register
+ UInt32 mem0DestAddress; // $00044: Memory Channel 0 Destination Address Register
+ UInt32 mem0Count; // $00048: Memory Channel 0 Count Register
+ UInt16 mem0Control; // $0004C: Memory Channel 0 Control Register
+ UInt16 mem0BurstLength; // $0004E: Memory Channel 0 Burst Length Register
+ UInt16 mem0BusUtilizationControl; // $00050: Memory Channel 0 Bus Utilization Control Register
+ UInt16 mem0BlockLength; // $00052: Memory Channel 0 Block Length Register
+ UInt16 mem0BlockSeparationDist; // $00054: Memory Channel 0 Block Separation Distance Register
+ UInt16 mem0DMARequestTimeOut; // $00056: Memory Channel 0 DMA Request Time Out Register
+
+ UInt8 ___filler02[0x080-0x058];
+
+ UInt32 mem1SourceAddress; // $00080: Memory Channel 1 Source Address Register
+ UInt32 mem1DestAddress; // $00084: Memory Channel 1 Destination Address Register
+ UInt32 mem1Count; // $00088: Memory Channel 1 Count Register
+ UInt16 mem1Control; // $0008C: Memory Channel 1 Control Register
+ UInt16 mem1BurstLength; // $0008E: Memory Channel 1 Burst Length Register
+ UInt16 mem1BusUtilizationControl; // $00090: Memory Channel 1 Bus Utilization Control Register
+ UInt16 mem1BlockLength; // $00092: Memory Channel 1 Block Length Register
+ UInt16 mem1BlockSeparationDist; // $00094: Memory Channel 1 Block Separation Distance Register
+ UInt16 mem1DMARequestTimeOut; // $00096: Memory Channel 1 DMA Request Time Out Register
+
+ UInt8 ___filler03[0x0C0-0x098];
+
+ UInt32 io2MemoryAddress; // $000C0: I/O Channel 2 Memory Address Register
+ UInt32 io2PeripheralAddress; // $000C4: I/O Channel 2 Peripheral Address Register
+ UInt32 io2CountRegister; // $000C8: I/O Channel 2 Count Register
+ UInt16 io2Control; // $000CC: I/O Channel 2 Control Register
+ UInt16 io2RequestSourceSelect; // $000CE: I/O Channel 2 Request Source Select Register
+ UInt16 io2BurstLength; // $000D0: I/O Channel 2 Burst Length Register
+ UInt16 io2DMARequestTimeOut; // $000D2: I/O Channel 2 DMA Request Time-Out Register
+
+ UInt8 ___filler04[0x100-0x0D4];
+
+ UInt32 io3MemoryAddress; // $00100: I/O Channel 3 Memory Address Register
+ UInt32 io3PeripheralAddress; // $00104: I/O Channel 3 Peripheral Address Register
+ UInt32 io3CountRegister; // $00108: I/O Channel 3 Count Register
+ UInt16 io3Control; // $0010C: I/O Channel 3 Control Register
+ UInt16 io3RequestSourceSelect; // $0010E: I/O Channel 3 Request Source Select Register
+ UInt16 io3BurstLength; // $00110: I/O Channel 3 Burst Length Register
+ UInt16 io3DMARequestTimeOut; // $00112: I/O Channel 3 DMA Request Time-Out Register
+
+ UInt8 ___filler05[0x140-0x114];
+
+ UInt32 io4MemoryAddress; // $00140: I/O Channel 4 Memory Address Register
+ UInt32 io4PeripheralAddress; // $00144: I/O Channel 4 Peripheral Address Register
+ UInt32 io4CountRegister; // $00148: I/O Channel 4 Count Register
+ UInt16 io4Control; // $0014C: I/O Channel 4 Control Register
+ UInt16 io4RequestSourceSelect; // $0014E: I/O Channel 4 Request Source Select Register
+ UInt16 io4BurstLength; // $00150: I/O Channel 4 Burst Length Register
+ UInt16 io4DMARequestTimeOut; // $00152: I/O Channel 4 DMA Request Time-Out Register
+
+ UInt8 ___filler06[0x180-0x154];
+
+ UInt32 io5MemoryAddress; // $00180: I/O Channel 5 Memory Address Register
+ UInt32 io5PeripheralAddress; // $00184: I/O Channel 5 Peripheral Address Register
+ UInt32 io5CountRegister; // $00188: I/O Channel 5 Count Register
+ UInt16 io5Control; // $0018C: I/O Channel 5 Control Register
+ UInt16 io5RequestSourceSelect; // $0018E: I/O Channel 5 Request Source Select Register
+ UInt16 io5BurstLength; // $00190: I/O Channel 5 Burst Length Register
+ UInt16 io5DMARequestTimeOut; // $00192: I/O Channel 5 DMA Request Time-Out Register
+
+ UInt8 ___filler07[0x200-0x194];
+
+ UInt16 adcPenSampleFifo; // $00200: ADC Pen Sample FIFO
+
+ UInt8 ___filler08[0x210-0x202];
+
+ UInt32 adcControl; // $00210: ADC Control Register
+ UInt16 adcPenADSampleRateControl; // $00214: ADC Pen A/D Sample Rate Control Register
+
+ UInt8 ___filler09[0x218-0x216];
+
+ UInt16 adcInterruptControl; // $00218: ADC Interrupt Control Register
+ UInt16 adcInterruptErrorStatus; // $0021A: ADC Interrupt/Error Status Register
+
+ UInt8 ___filler10[0x22C-0x21C];
+
+ UInt16 adcClockDivide; // $0022C: ADC Clock Divide Register
+
+ UInt8 ___filler11[0x230-0x22E];
+
+ UInt32 adcCompareControl; // $00230: ADC Compare Control Register
+
+ UInt8 ___filler12[0x300-0x234];
+
+ UInt16 mmcClockControl; // $00300: MMC Clock Control Register
+
+ UInt8 ___filler13[0x304-0x302];
+
+ UInt16 mmcStatus; // $00304: MMC Status Register
+
+ UInt8 ___filler14[0x308-0x306];
+
+ UInt16 mmcClockRate; // $00308: MMC Clock Rate Register
+
+ UInt8 ___filler15[0x310-0x30A];
+
+ UInt16 mmcCommandDataControl; // $00310: MMC Command and Data Control Register
+
+ UInt8 ___filler16[0x314-0x312];
+
+ UInt16 mmcResponseTimeOut; // $00314: MMC Response Time Out Register
+
+ UInt8 ___filler17[0x318-0x316];
+
+ UInt16 mmcReadTimeOut; // $00318: MMC Read Time Out Register
+
+ UInt8 ___filler18[0x31C-0x31A];
+
+ UInt16 mmcBlockLength; // $0031C: MMC Block Length Register
+
+ UInt8 ___filler19[0x320-0x31E];
+
+ UInt16 mmcNumberOfBlocks; // $00320: MMC Number of Blocks Register
+
+ UInt8 ___filler20[0x324-0x322];
+
+ UInt16 mmcRevisionNumber; // $00324: MMC Revision Number Register
+
+ UInt16 mmcIOPort; // $00326: MMC IO Port Register
+ UInt16 mmcInterruptMask; // $00328: MMC Interrupt Mask Register
+
+ UInt8 ___filler21[0x32C-0x32A];
+
+ UInt16 mmcCommandNumber; // $0032C: MMC Command Number Register
+
+ UInt8 ___filler22[0x330-0x32E];
+
+ UInt16 mmcHigherArgument; // $00330: MMC HIGHER Argument Register
+ UInt16 mmcLowerArgument; // $00332: MMC LOWER Argument Register
+ UInt16 mmcResponseFifo; // $00334: MMC Response FIFO Register;
+
+ UInt8 ___filler23[0x338-0x336];
+
+ UInt16 mmcBufferAccess; // $00338: MMC Buffer Access Register
+
+ UInt8 ___filler24[0x33C-0x33A];
+
+ UInt16 mmcBufferPartFull; // $0033C: MMC Buffer Part Full Register
+
+ UInt8 ___filler25[0x400-0x33E];
+
+ UInt32 usbFrameNumberMatch; // $00400: USB Frame Number and Match
+ UInt32 usbSpecificationRelease; // $00404: USB Specification/Release Number
+ UInt32 usbStatus; // $00408: USB Status
+ UInt32 usbControl; // $0040C: USB Control
+ UInt32 usbConfigurationStatus; // $00410: USB Configuration Status
+ UInt32 usbEndpointBufferData; // $00414: USB Endpoint Buffer Data
+ UInt32 usbGeneralInterruptStatus; // $00418: USB General Interrupt Status Register
+ UInt32 usbInterruptMask; // $0041C: USB Interrupt Mask
+
+ UInt8 ___filler26[0x424-0x420];
+
+ UInt32 usbEnable; // $00424: USB Enable
+ UInt32 usbInterruptStatus; // $00428: USB Interrupt Status Register
+
+ UInt8 ___filler27[0x430-0x42C];
+
+ UInt32 usbEP0StatusControl; // $00430: USB Endpoint 0 Status/Control
+ UInt32 usbEP0InterruptStatus; // $00434: USB Endpoint 0 Interrupt Status
+ UInt32 usbEP0InterruptMask; // $00438: USB Endpoint 0 Interrupt Mask
+ UInt16 usbEP0FifoData; // $0043C: USB Endpoint 0 FIFO Data
+
+ UInt8 ___filler28[0x440-0x43E];
+
+ UInt32 usbEP0FifoStatus; // $00440: USB Endpoint 0 FIFO Status
+ UInt32 usbEP0FifoControl; // $00444: USB Endpoint 0 FIFO Control
+ UInt32 usbEP0LastReadFramePointer; // $00448: USB Endpoint 0 FIFO Last Read Frame Pointer
+ UInt32 usbEP0LastWriteFramePointer; // $0044C: USB Endpoint 0 FIFO Last Write Frame Pointer
+ UInt32 usbEP0FifoAlarm; // $00450: USB Endpoint 0 FIFO Alarm
+ UInt32 usbEP0FifoReadPointer; // $00454: USB Endpoint 0 FIFO Read Pointer
+ UInt32 usbEP0FifoWritePointer; // $00458: USB Endpoint 0 FIFO Write Pointer
+
+ UInt8 ___filler29[0x460-0x45C];
+
+ UInt32 usbEP1StatusControl; // $00460: USB Endpoint 1 Status/Control
+ UInt32 usbEP1InterruptStatus; // $00464: USB Endpoint 1 Interrupt Status
+ UInt32 usbEP1InterruptMask; // $00468: USB Endpoint 1 Interrupt Mask
+ UInt16 usbEP1FifoData; // $0046C: USB Endpoint 1 FIFO Data
+
+ UInt8 ___filler30[0x470-0x46E];
+
+ UInt32 usbEP1FifoStatus; // $00470: USB Endpoint 1 FIFO Status
+ UInt32 usbEP1FifoControl; // $00474: USB Endpoint 1 FIFO Control
+ UInt32 usbEP1LastReadFramePointer; // $00478: USB Endpoint 1 FIFO Last Read Frame Pointer
+ UInt32 usbEP1LastWriteFramePointer; // $0047C: USB Endpoint 1 FIFO Last Write Frame Pointer
+ UInt32 usbEP1FifoAlarm; // $00480: USB Endpoint 1 FIFO Alarm
+ UInt32 usbEP1FifoReadPointer; // $00484: USB Endpoint 1 FIFO Read Pointer
+ UInt32 usbEP1FifoWritePointer; // $00488: USB Endpoint 1 FIFO Write Pointer
+
+ UInt8 ___filler31[0x490-0x48C];
+
+ UInt32 usbEP2StatusControl; // $00490: USB Endpoint 2 Status/Control
+ UInt32 usbEP2InterruptStatus; // $00494: USB Endpoint 2 Interrupt Status
+ UInt32 usbEP2InterruptMask; // $00498: USB Endpoint 2 Interrupt Mask
+ UInt16 usbEP2FifoData; // $0049C: USB Endpoint 2 FIFO Data
+
+ UInt8 ___filler32[0x4A0-0x49E];
+
+ UInt32 usbEP2FifoStatus; // $004A0: USB Endpoint 2 FIFO Status
+ UInt32 usbEP2FifoControl; // $004A4: USB Endpoint 2 FIFO Control
+ UInt32 usbEP2LastReadFramePointer; // $004A8: USB Endpoint 2 FIFO Last Read Frame Pointer
+ UInt32 usbEP2LastWriteFramePointer; // $004AC: USB Endpoint 2 FIFO Last Write Frame Pointer
+ UInt32 usbEP2FifoAlarm; // $004B0: USB Endpoint 2 FIFO Alarm
+ UInt32 usbEP2FifoReadPointer; // $004B4: USB Endpoint 2 FIFO Read Pointer
+ UInt32 usbEP2FifoWritePointer; // $004B8: USB Endpoint 2 FIFO Write Pointer
+
+ UInt8 ___filler33[0x4C0-0x4BC];
+
+ UInt32 usbEP3StatusControl; // $004C0: USB Endpoint 3 Status/Control
+ UInt32 usbEP3InterruptStatus; // $004C4: USB Endpoint 3 Interrupt Status
+ UInt32 usbEP3InterruptMask; // $004C8: USB Endpoint 3 Interrupt Mask
+ UInt16 usbEP3FifoData; // $004CC: USB Endpoint 3 FIFO Data
+
+ UInt8 ___filler34[0x4D0-0x4CE];
+
+ UInt32 usbEP3FifoStatus; // $004D0: USB Endpoint 3 FIFO Status
+ UInt32 usbEP3FifoControl; // $004D4: USB Endpoint 3 FIFO Control
+ UInt32 usbEP3LastReadFramePointer; // $004D8: USB Endpoint 3 FIFO Last Read Frame Pointer
+ UInt32 usbEP3LastWriteFramePointer; // $004DC: USB Endpoint 3 FIFO Last Write Frame Pointer
+ UInt32 usbEP3FifoAlarm; // $004E0: USB Endpoint 3 FIFO Alarm
+ UInt32 usbEP3FifoReadPointer; // $004E4: USB Endpoint 3 FIFO Read Pointer
+ UInt32 usbEP3FifoWritePointer; // $004E8: USB Endpoint 3 FIFO Write Pointer
+
+ UInt8 ___filler35[0x4F0-0x4EC];
+
+ UInt32 usbEP4StatusControl; // $004F0: USB Endpoint 4 Status/Control
+ UInt32 usbEP4InterruptStatus; // $004F4: USB Endpoint 4 Interrupt Status
+ UInt32 usbEP4InterruptMask; // $004F8: USB Endpoint 4 Interrupt Mask
+ UInt16 usbEP4FifoData; // $004FC: USB Endpoint 4 FIFO Data
+
+ UInt8 ___filler36[0x500-0x4FE];
+
+ UInt32 usbEP4FifoStatus; // $00500: USB Endpoint 4 FIFO Status
+ UInt32 usbEP4FifoControl; // $00504: USB Endpoint 4 FIFO Control
+ UInt32 usbEP4LastReadFramePointer; // $00508: USB Endpoint 4 FIFO Last Read Frame Pointer
+ UInt32 usbEP4LastWriteFramePointer; // $0050C: USB Endpoint 4 FIFO Last Write Frame Pointer
+ UInt32 usbEP4FifoAlarm; // $00510: USB Endpoint 4 FIFO Alarm
+ UInt32 usbEP4FifoReadPointer; // $00514: USB Endpoint 4 FIFO Read Pointer
+ UInt32 usbEP4FifoWritePointer; // $00518: USB Endpoint 4 FIFO Write Pointer
+
+ UInt8 ___filler37[0x800-0x51C];
+
+ UInt32 lcdStartAddr; // $00800: LCD Screen Starting Address Register
+ UInt16 lcdScreenSize; // $00804: LCD Screen Size Register
+ UInt16 lcdPageWidth; // $00806: LCD Virtual Page Width Register
+ UInt16 lcdCursorXPos; // $00808: LCD Cursor X Position
+ UInt16 lcdCursorYPos; // $0080A: LCD Cursor Y Position
+ UInt16 lcdCursorSize; // $0080C: LCD Cursor Size
+ UInt16 lcdBlinkControl; // $0080E: LCD Blink Control Register
+ UInt16 lcdColorCursorMapping; // $00810: LCD Color Cursor Mapping Register
+ UInt16 lcdPanelControl0; // $00812: LCD Panel Configuration Register 0
+ UInt16 lcdPanelControl1; // $00814: LCD Panel Configuration Register 1
+ UInt16 lcdHorizontalConfig0; // $00816: LCD Horizontal Configuration Register 0
+ UInt16 lcdHorizontalConfig1; // $00818: LCD Horizontal Configuration Register 1
+ UInt16 lcdVerticalConfig0; // $0081A: LCD Vertical Configuration Register 0
+ UInt16 lcdVerticalConfig1; // $0081C: LCD Vertical Configuration Register 1
+ UInt16 lcdPanningOffset; // $0081E: LCD Panning Offset Register
+ UInt16 lcdGrayPalette; // $00820: LCD Gray Palette Mapping Register
+ UInt16 lcdPWMContrastControl; // $00822: LCD PWM Contrast Control Register
+ UInt16 lcdDMAControl; // $00824: LCD DMA Control Register
+ UInt16 lcdRefreshModeControl; // $00826: LCD Refresh Mode Control Register
+ UInt16 lcdInterruptConfiguration; // $00828: LCD Interrupt Configuration
+ UInt16 lcdInterruptStatus; // $0082A: LCD Interrupt Status
+
+ UInt8 ___filler38[0x1F000-0x0082C];
+
+ UInt8 scr; // $10000: System Control Register
+
+ UInt8 ___filler39[0x003-0x001];
+
+ UInt8 pcr; // $10003: Peripheral Control Register
+ UInt8 chipID; // $10004: Chip ID Register
+ UInt8 maskID; // $10005: Mask ID Register
+ UInt16 swID; // $10006: Software ID Register
+ UInt16 ioDriveControl; // $10008: I/O Drive Control Register
+
+ UInt8 ___filler40[0x100-0x00A];
+
+ UInt16 csAGroupBase; // $10100: Chip Select Group A Base Register
+ UInt16 csBGroupBase; // $10102: Chip Select Group B Base Register
+ UInt16 csCGroupBase; // $10104: Chip Select Group C Base Register
+ UInt16 csDGroupBase; // $10106: Chip Select Group D Base Register
+
+ UInt8 ___filler41[0x10c-0x108];
+
+ UInt16 csControl2; // $1010C: Chip Select Control Register 2
+
+ UInt8 ___filler42[0x110-0x10e];
+
+ UInt16 csASelect; // $10110: Group A Chip Select Register
+ UInt16 csBSelect; // $10112: Group B Chip Select Register
+ UInt16 csCSelect; // $10114: Group C Chip Select Register
+ UInt16 csDSelect; // $10116: Group D Chip Select Register
+
+ UInt16 emuCS; // $10118: EMU Chip Select Register
+
+ UInt8 ___filler43[0x150-0x11A];
+
+ UInt16 csControl3; // $10150: Chip Select Control Register 3
+
+ UInt8 ___filler43a[0x180-0x152];
+
+ UInt16 csEGroupBase; // $10180: Chip Select Group E Base Register
+ UInt16 csFGroupBase; // $10182: Chip Select Group F Base Register
+ UInt16 csGGroupBase; // $10184: Chip Select Group G Base Register
+
+ UInt8 ___filler44[0x18A-0x186];
+
+ UInt16 csControl1; // $1018A: Chip Select Control Register 1
+
+ UInt8 ___filler45[0x190-0x18C];
+
+ UInt16 csESelect; // $10190: Group E Chip Select Register
+ UInt16 csFSelect; // $10192: Group F Chip Select Register
+ UInt16 csGSelect; // $10194: Group G Chip Select Register
+
+ UInt8 ___filler46[0x200-0x196];
+
+ UInt16 pllControl; // $10200: PLL Control Register
+ UInt16 pllFreqSel0; // $10202: MCU PLL Frequency Select Register 0
+ UInt16 pllFreqSel1; // $10204: MCU PLL Frequency Select Register 1
+
+ UInt8 ___filler47;
+
+ UInt8 pwrControl; // $10207: CPU Power Control Register
+
+ UInt16 usbpllFreqSel0; // $10208: USBPLL Frequency Select Register 0
+ UInt16 usbpllFreqSel1; // $1020A: USBPLL Frequency Select Register 1
+
+ UInt16 clockSrcCtl; // $1020C: Clock Source Control Register
+
+ UInt8 ___filler48[0x300-0x20E];
+
+ UInt8 intVector; // $10300: Interrupt Vector Register
+
+ UInt8 ___filler49;
+
+ UInt16 intControl; // $10302: Interrupt Control Register
+ UInt16 intMaskHi; // $10304: Interrupt Mask Register (high word)
+ UInt16 intMaskLo; // $10306: Interrupt Mask Register (low word)
+
+ UInt8 ___filler50[0x30C-0x308];
+
+ UInt16 intStatusHi; // $1030C: Interrupt Status Register (high word)
+ UInt16 intStatusLo; // $1030E: Interrupt Status Register (low word)
+ UInt16 intPendingHi; // $10310: Interrupt Pending Register (high word)
+ UInt16 intPendingLo; // $10312: Interrupt Pending Register (low word)
+ UInt16 intLevelControl; // $10314: Interrupt Level Control Register
+ UInt16 intLevelControl2; // $10316: Interrupt Level Control Register 2
+ UInt16 intLevelControl3; // $10318: Interrupt Level Control Register 3
+ UInt16 intLevelControl4; // $1031A: Interrupt Level Control Register 4
+ UInt16 intLevelControl5; // $1031C: Interrupt Level Control Register 5
+ UInt16 intLevelControl6; // $1031E: Interrupt Level Control Register 6
+ UInt16 intLevelControl7; // $10320: Interrupt Level Control Register 7
+
+ UInt8 ___filler51[0x400-0x322];
+
+ UInt8 portADir; // $10400: Port A Direction Register
+ UInt8 portAData; // $10401: Port A Data Register
+ UInt8 portAPullupEn; // $10402: Port A Pullup Enable
+
+ UInt8 ___filler52[0x408-0x403];
+
+ UInt8 portBDir; // $10408: Port B Direction Register
+ UInt8 portBData; // $10409: Port B Data Register
+ UInt8 portBPullupEn; // $1040A: Port B Pullup Enable
+ UInt8 portBSelect; // $1040B: Port B Select Register
+
+ UInt8 ___filler53[0x410-0x40C];
+
+ UInt8 portCDir; // $10410: Port C Direction Register
+ UInt8 portCData; // $10411: Port C Data Register
+ UInt8 portCPulldnEn; // $10412: Port C Pulldown Enable
+ UInt8 portCSelect; // $10413: Port C Select Register
+
+ UInt8 ___filler54[0x418-0x414];
+
+ UInt8 portDDir; // $10418: Port D Direction Register
+ UInt8 portDData; // $10419: Port D Data Register
+ UInt8 portDPullupEn; // $1041A: Port D Pull-up Enable
+ UInt8 portDSelect; // $1041B: Port D Select Register
+ UInt8 portDIntMask; // $1041C: Port D Interrupt Mask Register
+ UInt8 portDIntStatus; // $1041D: Port D Interrupt Status Register
+ UInt8 portDIntEdge; // $1041E: Port D Interrupt Edge Register
+ UInt8 portDIntPolarity; // $1041F: Port D Interrupt Polarity Register
+
+ UInt8 portEDir; // $10420: Port E Direction Register
+ UInt8 portEData; // $10421: Port E Data Register
+ UInt8 portEPullupEn; // $10422: Port E Pull-up Enable
+ UInt8 portESelect; // $10423: Port E Select Register
+ UInt8 portEIntMask; // $10424: Port E Interrupt Mask Register
+ UInt8 portEIntStatus; // $10425: Port E Interrupt Status Register
+ UInt8 portEIntEdge; // $10426: Port E Interrupt Edge Register
+ UInt8 portEIntPolarity; // $10427: Port E Interrupt Polarity Register
+
+ UInt8 portFDir; // $10428: Port F Direction Register
+ UInt8 portFData; // $10429: Port F Data Register
+ UInt8 portFPullupdnEn; // $1042A: Port F Pull-up/down Enable
+ UInt8 portFSelect; // $1042B: Port F Select Register
+ UInt8 portFIntMask; // $1042C: Port F Interrupt Mask Register
+ UInt8 portFIntStatus; // $1042D: Port F Interrupt Status Register
+ UInt8 portFIntEdge; // $1042E: Port F Interrupt Edge Register
+ UInt8 portFIntPolarity; // $1042F: Port F Interrupt Polarity Register
+
+ UInt8 portGDir; // $10430: Port G Direction Register
+ UInt8 portGData; // $10431: Port G Data Register
+ UInt8 portGPullupEn; // $10432: Port G Pull-up Enable
+ UInt8 portGSelect; // $10433: Port G Select Register
+ UInt8 portGIntMask; // $10434: Port G Interrupt Mask Register
+ UInt8 portGIntStatus; // $10435: Port G Interrupt Status Register
+ UInt8 portGIntEdge; // $10436: Port G Interrupt Edge Register
+ UInt8 portGIntPolarity; // $10437: Port G Interrupt Polarity Register
+
+ UInt8 portJDir; // $10438: Port J Direction Register
+ UInt8 portJData; // $10439: Port J Data Register
+ UInt8 portJPullupEn; // $1043A: Port J Pull-up Enable
+ UInt8 portJSelect; // $1043B: Port J Select Register
+ UInt8 portJIntMask; // $1043C: Port J Interrupt Mask Register
+ UInt8 portJIntStatus; // $1043D: Port J Interrupt Status Register
+ UInt8 portJIntEdge; // $1043E: Port J Interrupt Edge Register
+ UInt8 portJIntPolarity; // $1043F: Port J Interrupt Polarity Register
+
+ UInt8 portKDir; // $10440: Port K Direction Register
+ UInt8 portKData; // $10441: Port K Data Register
+ UInt8 portKPullupdnEn; // $10442: Port K Pull-up/down Enable
+ UInt8 portKSelect; // $10443: Port K Select Register
+ UInt8 portKIntMask; // $10444: Port K Interrupt Mask Register
+ UInt8 portKIntStatus; // $10445: Port K Interrupt Status Register
+ UInt8 portKIntEdge; // $10446: Port K Interrupt Edge Register
+ UInt8 portKIntPolarity; // $10447: Port K Interrupt Polarity Register
+
+ UInt8 portMDir; // $10448: Port M Direction Register
+ UInt8 portMData; // $10449: Port M Data Register
+ UInt8 portMPullupdnEn; // $1044A: Port M Pull-up/down Enable
+ UInt8 portMSelect; // $1044B: Port M Select Register
+ UInt8 portMIntMask; // $1044C: Port M Interrupt Mask Register
+ UInt8 portMIntStatus; // $1044D: Port M Interrupt Status Register
+ UInt8 portMIntEdge; // $1044E: Port M Interrupt Edge Register
+ UInt8 portMIntPolarity; // $1044F: Port M Interrupt Polarity Register
+
+ UInt8 portNDir; // $10450: Port N Direction Register
+ UInt8 portNData; // $10451: Port N Data Register
+ UInt8 portNPullupdnEn; // $10452: Port N Pull-up/down Enable
+ UInt8 portNSelect; // $10453: Port N Select Register
+ UInt8 portNIntMask; // $10454: Port N Interrupt Mask Register
+ UInt8 portNIntStatus; // $10455: Port N Interrupt Status Register
+ UInt8 portNIntEdge; // $10456: Port N Interrupt Edge Register
+ UInt8 portNIntPolarity; // $10457: Port N Interrupt Polarity Register
+
+ UInt8 portPDir; // $10458: Port P Direction Register
+ UInt8 portPData; // $10459: Port P Data Register
+ UInt8 portPPullupdnEn; // $1045A: Port P Pull-up/down Enable
+ UInt8 portPSelect; // $1045B: Port P Select Register
+ UInt8 portPIntMask; // $1045C: Port P Interrupt Mask Register
+ UInt8 portPIntStatus; // $1045D: Port P Interrupt Status Register
+ UInt8 portPIntEdge; // $1045E: Port P Interrupt Edge Register
+ UInt8 portPIntPolarity; // $1045F: Port P Interrupt Polarity Register
+
+ UInt8 portRDir; // $10460: Port R Direction Register
+ UInt8 portRData; // $10461: Port R Data Register
+ UInt8 portRPullupdnEn; // $10462: Port R Pull-up/down Enable
+ UInt8 portRSelect; // $10463: Port R Select Register
+ UInt8 portRIntMask; // $10464: Port R Interrupt Mask Register
+ UInt8 portRIntStatus; // $10465: Port R Interrupt Status Register
+ UInt8 portRIntEdge; // $10466: Port R Interrupt Edge Register
+ UInt8 portRIntPolarity; // $10467: Port R Interrupt Polarity Register
+
+ UInt8 ___filler55[0x500-0x468];
+
+ UInt16 pwmControl; // $10500: PWM 1 Control Register (PWM 1 is the same as the single PWM in EZ)
+ UInt8 pwmSampleHi; // $10502: PWM 1 Sample - high byte
+ UInt8 pwmSampleLo; // $10503: PWM 1 Sample - low byte
+ UInt8 pwmPeriod; // $10504: PWM 1 Period
+ UInt8 pwmCounter; // $10505: PWM 1 Counter
+
+ UInt8 ___filler56[0x510-0x506];
+
+ UInt16 pwm2Control; // $10510: PWM 2 Control Register
+ UInt16 pwm2Period; // $10512: PWM 2 Period
+ UInt16 pwm2Width; // $10514: PWM 2 Width
+ UInt16 pwm2Counter; // $10516: PWM 2 Counter
+
+ UInt8 ___filler57[0x600-0x518];
+
+ UInt16 tmr1Control; // $10600: Timer 1 Control Register
+ UInt16 tmr1Prescaler; // $10602: Timer 1 Prescaler Register
+ UInt16 tmr1Compare; // $10604: Timer 1 Compare Register
+ UInt16 tmr1Capture; // $10606: Timer 1 Capture Register
+ UInt16 tmr1Counter; // $10608: Timer 1 Counter Register
+ UInt16 tmr1Status; // $1060A: Timer 1 Status Register
+
+ UInt8 ___filler58[0x610-0x60C];
+
+ UInt16 tmr2Control; // $10610: Timer 2 Control Register
+ UInt16 tmr2Prescaler; // $10612: Timer 2 Prescaler Register
+ UInt16 tmr2Compare; // $10614: Timer 2 Compare Register
+ UInt16 tmr2Capture; // $10616: Timer 2 Capture Register
+ UInt16 tmr2Counter; // $10618: Timer 2 Counter Register
+ UInt16 tmr2Status; // $1061A: Timer 2 Status Register
+
+ UInt8 ___filler59[0x700-0x61C];
+
+ UInt16 spiRxD; // $10700: SPI Unit 1 Receive Data Register
+ UInt16 spiTxD; // $10702: SPI Unit 1 Transmit Data Register
+ UInt16 spiCont1; // $10704: SPI Unit 1 Control/Status Register
+ UInt16 spiIntCS; // $10706: SPI Unit 1 Interrupt control/Status Register
+ UInt16 spiTest; // $10708: SPI Unit 1 Test Register
+ UInt16 spiSpc; // $1070A: SPI Unit 1 Sample period counter register
+
+ UInt8 ___filler60[0x800-0x70C];
+
+ UInt8 i2cAddress; // $10800: I2C Address Register
+
+ UInt8 ___filler61[0x804-0x801];
+
+ UInt8 i2cFreqDiv; // $10804: I2C Frequency Divider Register
+
+ UInt8 ___filler62[0x808-0x805];
+
+ UInt8 i2cControl; // $10808: I2C Control Register
+
+ UInt8 ___filler63[0x80C-0x809];
+
+ UInt8 i2cStatus; // $1080C: I2C Status Register
+
+ UInt8 ___filler64[0x810-0x80D];
+
+ UInt8 i2cDataIO; // $10810: I2C Data I/O Register
+
+ UInt8 ___filler65[0x900-0x811];
+
+ UInt16 uControl; // $10900: Uart 1 Status/Control Register (Uart 1 is the same as the single Uart in EZ)
+ UInt16 uBaud; // $10902: Uart 1 Baud Control Register
+ UInt16 uReceive; // $10904: Uart 1 Receive Register
+ UInt16 uTransmit; // $10906: Uart 1 Transmit Register
+ UInt16 uMisc; // $10908: Uart 1 Miscellaneous Register
+ UInt16 uNonIntPresc; // $1090A: Uart 1 Non-Integer Prescaler
+ UInt16 uFIFOHMark; // $1090C: Uart 1 Half Mark FIFO Register
+
+ UInt8 ___filler66[0x910-0x90E];
+
+ UInt16 u2Control; // $10910: Uart 2 Status/Control Register
+ UInt16 u2Baud; // $10912: Uart 2 Baud Control Register
+ UInt16 u2Receive; // $10914: Uart 2 Receiver Register
+ UInt16 u2Transmit; // $10916: Uart 2 Transmitter Register
+ UInt16 u2Misc; // $10918: Uart 2 Miscellaneous Register
+ UInt16 u2NonIntPresc; // $1091A: Uart 2 Non-Integer Prescaler Register
+ UInt16 u2FIFOHMark; // $1091C: Uart 2 Half Mark FIFO Register
+
+ UInt8 ___filler67[0xB00-0x91E];
+
+ UInt32 rtcHourMinSec; // $10B00: RTC Hours, Minutes, Seconds Register
+ UInt32 rtcAlarm; // $10B04: RTC Alarm Register
+
+ UInt8 ___filler68[0xB0A-0xB08];
+
+ UInt16 rtcWatchDog; // $10B0A: RTC Watchdog Timer
+ UInt16 rtcControl; // $10B0C: RTC Control Register
+ UInt16 rtcIntStatus; // $10B0E: RTC Interrupt Status Register
+ UInt16 rtcIntEnable; // $10B10: RTC Interrupt Enable Register
+ UInt16 stopWatch; // $10B12: Stopwatch Minutes
+
+ UInt8 ___filler69[0xB1A-0xB14];
+
+ UInt16 rtcDay; // $10B1A: RTC Day
+ UInt16 rtcDayAlarm; // $10B1C: RTC Day Alarm
+
+ UInt8 ___filler70[0xC00-0xB1E];
+
+ UInt32 sdramControlE; // $10C00: SDRAM Control Register for Chip Select E
+ UInt32 sdramControlF; // $10C04: SDRAM Control Register for Chip Select F
+ UInt32 edoControlE; // $10C08: EDO Control Register for Chip Select E
+ UInt32 edoControlF; // $10C0C: EDO Control Register for Chip Select F
+ UInt16 secondaryControl; // $10C10: Secondary Control Register
+
+ UInt8 ___filler71[0xD00-0xC12];
+
+ UInt32 emuAddrCompare; // $10D00: Emulation Address Compare Register
+ UInt32 emuAddrMask; // $10D04: Emulation Address Mask Register
+ UInt16 emuControlCompare; // $10D08: Emulation Control Compare Register
+ UInt16 emuControlMask; // $10D0A: Emulation Control Mask Register
+ UInt16 emuControl; // $10DOC: Emulation Control Register
+ UInt16 emuStatus; // $10D0E: Emulation Status Register
+};
+
+typedef volatile struct HwrM68SZ328Type* HwrM68SZ328Ptr;
+
+#define HwrDBallType HwrM68SZ328Type
+#define HwrDBallPtr HwrM68SZ328Ptr
+
+/************************************************************************
+ * ADC / ASP register for SZ
+ ***********************************************************************/
+#define hwrSZ328adcLowPowerOffEnable 0x04000000
+#define hwrSZ328adcVoiceEnable 0x00000004
+#define hwrSZ328adcPenEnable 0x00000002
+
+#define hwrSZ328adcIntEnable 0x00000097
+
+
+/************************************************************************
+ * Chip ID register for SZ
+ ***********************************************************************/
+ #define hwrSZ328chipIDSZ 0x45
+
+/************************************************************************
+ * Mask ID register for SZ
+ ***********************************************************************/
+#define hwrSZ328maskID0H31J 0x01
+#define hwrSZ328maskID0J75C 0x02
+#define hwrSZ328maskID1J75C 0x03
+#define hwrSZ328maskID0J83G 0x04
+
+/************************************************************************
+ * LCD Controller Bits
+ ************************************************************************/
+// lcdCursorXPos Register
+#define hwrSZ328LcdCursorXPosCtlMask 0xC000
+ #define hwrSZ328LcdCursorXPosCtlTrans 0x0000
+ #define hwrSZ328LcdCursorXPosCtlBlack 0x4000
+ #define hwrSZ328LcdCursorXPosCtlReverse 0x8000
+ #define hwrSZ328LcdCursorXPosCtlWhite 0xC000
+#define hwrSZ328LcdCursorXPosValueMask 0x1FF
+// lcdCursorYPos Register
+#define hwrSZ328LcdCursorYPosValueMask 0x1FF
+
+// lcdCursorSize Register
+#define hwrSZ328LcdCursorWidthMask 0x3F
+ #define hwrSZ328LcdCursorWidthOffset 0x8
+#define hwrSZ328LcdCursorHeightMask 0x3F
+
+// lcdBlinkControl Register
+#define hwrSZ328LcdBlinkDivisorMask 0xFF
+
+// lcdPanelControl1 Register
+#define hwrSZ328LcdPanelControlBusMask 0x3000
+ #define hwrSZ328LcdPanelControlBus1Bit 0x0000
+ #define hwrSZ328LcdPanelControlBus2Bit 0x1000
+ #define hwrSZ328LcdPanelControlBus4Bit 0x2000
+#define hwrSZ328LcdPanelControlGrayScale 0x4000
+#define hwrSZ328LcdPanelControl4BitGrayScale 0x0200
+
+// lcdPWMContrastControl Register
+#define hwrSZ328LcdContrastPWMWidthMask 0x00FF
+#define hwrSZ328LcdContrastEnable 0x0100
+#define hwrSZ328LcdLDMask 0x8000
+
+
+
+/************************************************************************
+ * Interrupt Controller Bits
+ ************************************************************************/
+
+// intMaskHi bits
+// NOTE: Due to a bug in early rev's of the DragonBall, the clear bits for
+// IRQ[1236] on those early chips were different than the indicator bits
+// (the order was reversed). So some older code uses the OR of the IRQ1 and
+// IRQ6 bits for either, and the OR of the IRQ2 and IRQ3 bits for either.
+#define hwrSZ328IntHiUSB 0x8000
+#define hwrSZ328IntHiI2C 0x4000
+#define hwrSZ328IntHiMMC 0x2000
+#define hwrSZ328IntHiPortK 0x1000
+#define hwrSZ328IntHiPortM 0x0800
+#define hwrSZ328IntHiPortN 0x0400
+#define hwrSZ328IntHiPortP 0x0200
+#define hwrSZ328IntHiADC 0x0100
+#define hwrSZ328IntHiEMU 0x0080
+#define hwrSZ328IntHiSampleTimer 0x0040
+#define hwrSZ328IntHiCSPI 0x0020
+#define hwrSZ328IntHiPortR 0x0010
+#define hwrSZ328IntHiIRQ6 0x0008
+#define hwrSZ328IntHiIRQ3 0x0004
+#define hwrSZ328IntHiIRQ2 0x0002
+#define hwrSZ328IntHiIRQ1 0x0001
+
+// intMaskLo bits
+#define hwrSZ328IntLoDMA1 0x8000
+#define hwrSZ328IntLoDMA2 0x4000
+#define hwrSZ328IntLoPWM2 0x2000
+#define hwrSZ328IntLoPWM2Bit 13
+#define hwrSZ328IntLoUART2 0x1000
+#define hwrSZ328IntLoUART2Bit 12
+#define hwrSZ328IntLoPortD 0x0800
+#define hwrSZ328IntLoPortE 0x0400
+#define hwrSZ328IntLoPortF 0x0200
+#define hwrSZ328IntLoPortG 0x0100
+#define hwrSZ328IntLoAllKeys 0x0F00
+#define hwrSZ328IntLoInt0Bit 8
+#define hwrSZ328IntLoPWM 0x0080
+#define hwrSZ328IntLoPWMBit 7
+#define hwrSZ328IntLoPortJ 0x0040
+#define hwrSZ328IntLoTimer2 0x0020
+#define hwrSZ328IntLoTimer2Bit 5
+#define hwrSZ328IntLoRTC 0x0010
+#define hwrSZ328IntLoRTCBit 4
+#define hwrSZ328IntLoWDT 0x0008
+#define hwrSZ328IntLoUART 0x0004
+#define hwrSZ328IntLoUARTBit 2
+#define hwrSZ328IntLoTimer 0x0002
+#define hwrSZ328IntLoTimerBit 1
+#define hwrSZ328IntLoLCDC 0x0001
+
+// intControl bits
+// NOTE: These are different than that documented in the User's manual
+// for the DragonBall (see erratas). The DragonBall is the same as the EZ.
+// Note 2: I am going to assume that these have not changed, since the SZ
+// manual is the same as the VZ's (even thought the manual is not followed) [TJC]
+#define hwrSZ328IntCtlEdge1 0x0800
+#define hwrSZ328IntCtlEdge2 0x0400
+#define hwrSZ328IntCtlEdge3 0x0200
+#define hwrSZ328IntCtlEdge6 0x0100
+#define hwrSZ328IntCtlPol1 0x8000
+#define hwrSZ328IntCtlPol2 0x4000
+#define hwrSZ328IntCtlPol3 0x2000
+#define hwrSZ328IntCtlPol6 0x1000
+#define hwrSZ328IntCtlPol5 0x0080
+
+
+/************************************************************************
+ * SDRAM Controller Bits bits
+ * Not all the bits are defined here-- some are pretty bad to muck with
+ * in anything but initial setup of the SDRAM.
+ ************************************************************************/
+// sdramControl[E,F] bits
+#define hwrSZ328SdramControlEnable 0x80000000
+#define hwrSZ328SdramControlOperatingMode 0x70000000
+ // rsvd
+#define hwrSZ328SdramControlIAM 0x00800000
+ // rsvd
+ // rsvd
+ // rsvd
+#define hwrSZ328SdramControlCASLatency 0x00000300
+
+// edoControl[E,F] bits
+#define hwrSZ328EdoControlEnable 0x80000000
+
+
+/************************************************************************
+ * Timer bits
+ ************************************************************************/
+#define hwrSZ328TmrControlUnused 0xFC00
+#define hwrSZ328TmrControlTIOOutput 0x0200
+#define hwrSZ328TmrControlFreeRun 0x0100
+#define hwrSZ328TmrControlCaptureEdgeMask 0x00C0
+ #define hwrSZ328TmrControlCaptureEdgeNone 0x0000
+ #define hwrSZ328TmrControlCaptureEdgeRising 0x0040
+ #define hwrSZ328TmrControlCaptureEdgeFalling 0x0080
+ #define hwrSZ328TmrControlCaptureEdgeBoth 0x00C0
+#define hwrSZ328TmrControlOutputModeToggle 0x0020
+#define hwrSZ328TmrControlEnInterrupt 0x0010
+#define hwrSZ328TmrControlClkSrcMask 0x000E
+ #define hwrSZ328TmrControlClkSrcStop 0x0000
+ #define hwrSZ328TmrControlClkSrcSys 0x0002
+ #define hwrSZ328TmrControlClkSrcSysBy16 0x0004
+ #define hwrSZ328TmrControlClkSrcTIN 0x0006
+ #define hwrSZ328TmrControlClkSrc32KHz 0x0008
+#define hwrSZ328TmrControlEnable 0x0001
+
+#define hwrSZ328TmrStatusCapture 0x0002
+#define hwrSZ328TmrStatusCaptureBit 1
+#define hwrSZ328TmrStatusCompare 0x0001
+#define hwrSZ328TmrStatusCompareBit 0
+
+
+/************************************************************************
+ * 68SZ328 Serial Port Register Bits
+ ************************************************************************/
+// uControl Register
+#define hwrSZ328UControlUARTEnable 0x8000
+#define hwrSZ328UControlRxEnable 0x4000
+#define hwrSZ328UControlTxEnable 0x2000
+#define hwrSZ328UControlRxClock1xSync 0x1000
+#define hwrSZ328UControlParityEn 0x0800
+#define hwrSZ328UControlParityOdd 0x0400
+#define hwrSZ328UControlStopBits2 0x0200
+#define hwrSZ328UControlDataBits8 0x0100
+#define hwrSZ328UControlOldDataEn 0x0080
+#define hwrSZ328UControlCTSDeltaEn 0x0040
+#define hwrSZ328UControlRxFullEn 0x0020
+#define hwrSZ328UControlRxHalfEn 0x0010
+#define hwrSZ328UControlRxRdyEn 0x0008
+#define hwrSZ328UControlTxEmptyEn 0x0004
+#define hwrSZ328UControlTxHalfEn 0x0002
+#define hwrSZ328UControlTxAvailEn 0x0001
+
+#define hwrSZ328UControlEnableAll (hwrSZ328UControlUARTEnable | \
+ hwrSZ328UControlRxEnable | \
+ hwrSZ328UControlTxEnable)
+
+// uBaud Register
+// UCLK output requires PE3 Select to be 0
+#define hwrSZ328UBaudUCLKDirOut 0x2000
+#define hwrSZ328UBaudBaudSrcUCLK 0x0800
+#define hwrSZ328UBaudDivider 0x0700
+#define hwrSZ328UBaudPrescaler 0x003F
+
+#define hwrSZ328UBaudDivideBitOffset 8
+
+
+// uReceive Register
+#define hwrSZ328UReceiveFIFOFull 0x8000
+#define hwrSZ328UReceiveFIFOHalf 0x4000
+#define hwrSZ328UReceiveDataRdy 0x2000
+#define hwrSZ328UReceiveDataRdyBit 13
+#define hwrSZ328UReceiveOldData 0x1000
+#define hwrSZ328UReceiveOverrunErr 0x0800
+#define hwrSZ328UReceiveOverrunErrBit 11
+#define hwrSZ328UReceiveFrameErr 0x0400
+#define hwrSZ328UReceiveFrameErrBit 10
+#define hwrSZ328UReceiveBreakErr 0x0200
+#define hwrSZ328UReceiveBreakErrBit 9
+#define hwrSZ328UReceiveParityErr 0x0100
+#define hwrSZ328UReceiveParityErrBit 8
+#define hwrSZ328UReceiveData 0x00FF
+
+#define hwrSZ328UReceiveErrsMask (hwrSZ328UReceiveOverrunErr | \
+ hwrSZ328UReceiveFrameErr | \
+ hwrSZ328UReceiveBreakErr | \
+ hwrSZ328UReceiveParityErr)
+
+// uTransmit Register
+#define hwrSZ328UTransmitFIFOEmpty 0x8000
+#define hwrSZ328UTransmitFIFOHalf 0x4000
+#define hwrSZ328UTransmitTxAvail 0x2000
+#define hwrSZ328UTransmitSendBreak 0x1000
+#define hwrSZ328UTransmitIgnoreCTS 0x0800
+#define hwrSZ328UTransmitBusy 0x0400
+#define hwrSZ328UTransmitCTSStatus 0x0200
+#define hwrSZ328UTransmitCTSDelta 0x0100
+#define hwrSZ328UTransmitData 0x00FF
+
+// uMisc Register
+#define hwrSZ328UMiscBaudTest 0x8000
+#define hwrSZ328UMiscClkSrcUCLK 0x4000
+#define hwrSZ328UMiscForceParityErr 0x2000
+#define hwrSZ328UMiscLoopback 0x1000
+#define hwrSZ328UMiscBaudReset 0x0800
+#define hwrSZ328UMiscIRTestEn 0x0400
+#define hwrSZ328UMiscReservedMask 0x0300
+#define hwrSZ328UMiscRTSThruFIFO 0x0080
+#define hwrSZ328UMiscRTSOut 0x0040
+#define hwrSZ328UMiscIRDAEn 0x0020
+#define hwrSZ328UMiscLoopIRDA 0x0010
+#define hwrSZ328UMiscRXPolarityInv 0x0008
+#define hwrSZ328UMiscTXPolarityInv 0x0004
+#define hwrSZ328UMiscErrorIntStatus 0x0002
+#define hwrSZ328UMiscErrorIntEnable 0x0001
+#define hwrSZ328UMiscUnused 0x0000
+
+// uNonIntPresc Register
+#define hwrSZ328UNonIntPrescSrcIntPresc 0x0000
+#define hwrSZ328UNonIntPrescSrcNonIntPresc 0x8000
+
+#define hwrSZ328UNonIntPrescSelDiv128 0x0000
+#define hwrSZ328UNonIntPrescSelDiv64 0x0100
+#define hwrSZ328UNonIntPrescSelDiv32 0x0200
+#define hwrSZ328UNonIntPrescSelDiv16 0x0300
+#define hwrSZ328UNonIntPrescSelDiv8 0x0400
+#define hwrSZ328UNonIntPrescSelDiv4 0x0500
+#define hwrSZ328UNonIntPrescSelDiv2 0x0600
+#define hwrSZ328UNonIntPrescSelDiv1 0x0700
+
+#define hwrSZ328UNonIntPrescStepMask 0x00FF
+#define hwrSZ328UNonIntPrescSelOffset 8
+
+// see SZ docs for explanation of the following. This provides the correct
+// pulse width for IRDA, and is just a statement in the docs. The values don't
+// appear to make sense, but I just push the buttons.
+
+// This has been deprecated in favor of a prv function in the serial driver and
+// the SerialMgr (depending on whether you have Bond or not) that calculates
+// the value of this register based on the clock frequency you're running on.
+// There was a bug when running EZ at 20MHz that caused the IrDA pulsewidth to
+// get too short.
+
+#if 0
+#define hwrSZ328UNonIntPrescIRDAMode (hwrSZ328UNonIntPrescSrcIntPresc \
+ | hwrSZ328UNonIntPrescSelDiv32 \
+ | (hwrSZ328UNonIntPrescStepMask & 0x20))
+#endif
+
+/************************************************************************
+ * PWM Bits
+ ************************************************************************/
+// PWM register bits of interest
+#define hwrSZ328PWMControlEnable 0x0010
+#define hwrSZ328PWMControlEnableBit 4
+#define hwrSZ328PWMControlEnableIRQ 0x0040
+#define hwrSZ328PWMIRQStatus 0x0080
+// PWM divider chain output selectors
+#define hwrSZ328PWMControlDivMask 0x0003
+#define hwrSZ328PWMControlDivBy2 0x0
+#define hwrSZ328PWMControlDivBy4 0x1
+#define hwrSZ328PWMControlDivBy8 0x2
+#define hwrSZ328PWMControlDivBy16 0x3
+// PWM Repeat Counts
+#define hwrSZ328PWMRepeatSample1x 0x0
+#define hwrSZ328PWMRepeatSample2x 0x4
+#define hwrSZ328PWMRepeatSample4x 0x8
+#define hwrSZ328PWMRepeatSample8x 0xC
+// PWM hardware constraints
+#define hwrSZ328PWMFifoSizeInBytes 4
+#define hwrSZ328PWMPrescalerMask 0x7F00
+#define hwrSZ328PWMPrescalerOffset 8
+
+/************************************************************************
+ * PLL Bits
+ ************************************************************************/
+#define hwrSZ328PLLControlMCURestart 0x8000
+#define hwrSZ328PLLControlUSBRestart 0x4000
+#define hwrSZ328PLLControlClkEnable 0x0010
+#define hwrSZ328PLLControlMCUDisable 0x0008
+#define hwrSZ328PLLControlUSBDisable 0x0004
+
+#define hwrSZ328PLLControlSysDMADiv2 0x0000
+#define hwrSZ328PLLControlSysDMADiv4 0x0100
+#define hwrSZ328PLLControlSysDMADiv8 0x0200
+#define hwrSZ328PLLControlSysDMADiv16 0x0300
+#define hwrSZ328PLLControlSysDMADiv1 0x0400
+
+#define hwrSZ328PLLControlPixDMADiv2 0x0000
+#define hwrSZ328PLLControlPixDMADiv4 0x0800
+#define hwrSZ328PLLControlPixDMADiv8 0x1000
+#define hwrSZ328PLLControlPixDMADiv16 0x1800
+#define hwrSZ328PLLControlPixDMADiv1 0x2000
+
+
+/************************************************************************
+ * Real Time Clock (RTC) Bits
+ ************************************************************************/
+
+// RTC Control Register (RTCCTL / rtcControl) bits
+#define hwrSZ328RTCControlRTCEnable 0x0080
+
+// RTC Interrupt Enable Register (RTCIENR / rtcIntEnable) bits
+#define hwrSZ328RTCIntEnableSample7 0x8000
+#define hwrSZ328RTCIntEnableSample6 0x4000
+#define hwrSZ328RTCIntEnableSample5 0x2000
+#define hwrSZ328RTCIntEnableSample4 0x1000
+#define hwrSZ328RTCIntEnableSample3 0x0800
+#define hwrSZ328RTCIntEnableSample2 0x0400
+#define hwrSZ328RTCIntEnableSample1 0x0200
+#define hwrSZ328RTCIntEnableSample0 0x0100
+#define hwrSZ328RTCIntEnableHour 0x0020
+#define hwrSZ328RTCIntEnableSec 0x0010
+#define hwrSZ328RTCIntEnable24Hr 0x0008
+#define hwrSZ328RTCIntEnableAlarm 0x0004
+#define hwrSZ328RTCIntEnableMinute 0x0002
+#define hwrSZ328RTCIntEnableStopWatch 0x0001
+
+// RTC Interrupt Status Register bits (rtcIntStatus)
+#define hwrSZ328RTCIntStatusSample7 0x8000
+#define hwrSZ328RTCIntStatusSample6 0x4000
+#define hwrSZ328RTCIntStatusSample5 0x2000
+#define hwrSZ328RTCIntStatusSample4 0x1000
+#define hwrSZ328RTCIntStatusSample3 0x0800
+#define hwrSZ328RTCIntStatusSample2 0x0400
+#define hwrSZ328RTCIntStatusSample1 0x0200
+#define hwrSZ328RTCIntStatusSample0 0x0100
+#define hwrSZ328RTCIntStatusHour 0x0020
+#define hwrSZ328RTCIntStatusSec 0x0010
+#define hwrSZ328RTCIntStatus24Hr 0x0008
+#define hwrSZ328RTCIntStatusAlarm 0x0004
+#define hwrSZ328RTCIntStatusMinute 0x0002
+#define hwrSZ328RTCIntStatusStopWatch 0x0001
+
+// RTC Alarm register (RTCALRM / rtcAlarm) masks and offsets
+#define hwrSZ328RTCAlarmSecondsMask 0x0000003fL
+#define hwrSZ328RTCAlarmSecondsOffset 0
+#define hwrSZ328RTCAlarmMinutesMask 0x003f0000L
+#define hwrSZ328RTCAlarmMinutesOffset 16
+#define hwrSZ328RTCAlarmHoursMask 0x1f000000L
+#define hwrSZ328RTCAlarmHoursOffset 24
+
+// RTC hours/minutes/seconds register (RTCHMS / rtcHourMinSec) masks and offsets
+#define hwrSZ328RTCHourMinSecSecondsMask 0x0000003fL
+#define hwrSZ328RTCHourMinSecSecondsOffset 0
+#define hwrSZ328RTCHourMinSecMinutesMask 0x003f0000L
+#define hwrSZ328RTCHourMinSecMinutesOffset 16
+#define hwrSZ328RTCHourMinSecHoursMask 0x1f000000L
+#define hwrSZ328RTCHourMinSecHoursOffset 24
+
+// RTC Day register masks/offsets
+#define hwrSZ328RTCDayDayMask 0x01FF
+#define hwrSZ328RTCDayDayOffset 0
+
+// RTC Watchdog Timer masks/offsets
+#define hwrSZ328RTCWatchdogEnable 0x0001
+#define hwrSZ328RTCWatchdogIntSel 0x0002
+#define hwrSZ328RTCWatchdogIntStatus 0x0080
+#define hwrSZ328RTCWatchdogCountMask 0x0300
+#define hwrSZ328RTCWatchdogCountOffset 8
+
+/************************************************************************
+ * SPI Master bits
+ ************************************************************************/
+
+// spiCont1 Register
+#define hwrSZ328SPIMControlRateMask 0xE000
+ #define hwrSZ328SPIMControlRateDiv4 0x0000
+ #define hwrSZ328SPIMControlRateDiv8 0x2000
+ #define hwrSZ328SPIMControlRateDiv16 0x4000
+ #define hwrSZ328SPIMControlRateDiv32 0x6000
+ #define hwrSZ328SPIMControlRateDiv64 0x8000
+ #define hwrSZ328SPIMControlRateDiv128 0xA000
+ #define hwrSZ328SPIMControlRateDiv256 0xC000
+ #define hwrSZ328SPIMControlRateDiv512 0xE000
+#define hwrSZ328SPIMControlEnable 0x0200
+#define hwrSZ328SPIMControlExchange 0x0100
+#define hwrSZ328SPIMControlIntStatus 0x0080
+#define hwrSZ328SPIMControlIntEnable 0x0040
+#define hwrSZ328SPIMControlOppPhase 0x0020
+#define hwrSZ328SPIMControlInvPolarity 0x0010
+#define hwrSZ328SPIMControlBitsMask 0x000F
+
+
+#endif // INCLUDE_SECRET_STUFF
+
+#endif // __M68SZ328_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68VZ328Hwr.h b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68VZ328Hwr.h
new file mode 100644
index 0000000..323b8c1
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/Hardware/IncsPrv/M68VZ328Hwr.h
@@ -0,0 +1,844 @@
+/*******************************************************************
+ * Pilot Software
+ *
+ * Copyright(c) 1995-1999, Palm Computing Inc., All Rights Reserved
+ *
+ *-------------------------------------------------------------------
+ * FileName:
+ * M68VZ328Hwr.h
+ *
+ * Description:
+ * Hardware Equates for the Motorola 68VZ328 Dragonball-VZ chip
+ *
+ * History:
+ * 11/19/99 EBE Created; integrated from M68EZ328Hwr.h
+ * 11/22/99 EBE Added Port Defs for J, K, & M
+ * 12/03/99 EBE Fixed up fillers @ 0x00A & 0x518
+ *
+ *******************************************************************/
+
+#ifdef NON_PORTABLE // So apps don't include this...
+
+
+#ifndef __M68VZ328HWR_H__
+#define __M68VZ328HWR_H__
+
+
+#include <PalmTypes.h> // Touchdown includes
+
+
+// Define location of the 68VZ328 Dragonball chip
+#define hwr68328Base 0xFFFFF000L // Base address of 68328
+
+
+/***********************************************************************
+ * Motorola 68VZ328 registers
+ ***********************************************************************/
+struct HwrM68VZ328Type {
+
+ UInt8 scr; // $000: System Control Register
+ UInt8 ___filler0[0x003-0x001];
+ UInt8 pcr; // $003: Peripheral Control Register
+ UInt8 chipID; // $004: Chip ID Register
+ UInt8 maskID; // $005: Mask ID Register
+ UInt16 swID; // $006: Software ID Register
+ UInt16 ioDriveControl; // $008: I/O Drive Control Register
+ UInt8 ___filler1[0x100-0x00A];
+
+ UInt16 csAGroupBase; // $100: Chip Select Group A Base Register
+ UInt16 csBGroupBase; // $102: Chip Select Group B Base Register
+ UInt16 csCGroupBase; // $104: Chip Select Group C Base Register
+ UInt16 csDGroupBase; // $106: Chip Select Group D Base Register
+
+ UInt16 csUGroupBase; // $108: Chip Select Upper Group Base Register
+
+ UInt16 csControl1; // $10A: Chip Select Control Register
+ UInt16 csControl2; // $10C: Chip Select Control Register
+
+ UInt8 ___filler2[0x110-0x10E];
+
+ UInt16 csASelect; // $110: Group A Chip Select Register
+ UInt16 csBSelect; // $112: Group B Chip Select Register
+ UInt16 csCSelect; // $114: Group C Chip Select Register
+ UInt16 csDSelect; // $116: Group D Chip Select Register
+
+ UInt16 emuCS; // $118: EMU Chip Select Register
+
+ UInt8 ___filler3[0x150-0x11A];
+
+ UInt16 csControl3; // $150: Chip Select Control Register
+
+ UInt8 ___filler3a[0x200-0x152];
+
+ UInt16 pllControl; // $200: PLL Control Register
+ UInt16 pllFreqSel; // $202: CGM Frequency Select Register
+
+ UInt8 ___filler4[0x207-0x204];
+
+ UInt8 pwrControl; // $207: Power Control Register
+
+ UInt8 ___filler5[0x300-0x208];
+
+ UInt8 intVector; // $300: Interrupt Vector Register
+ UInt8 ___filler6;
+ UInt16 intControl; // $302: Interrupt Control Register
+ UInt16 intMaskHi; // $304: Interrupt Mask Register/HIGH word
+ UInt16 intMaskLo; // $306: Interrupt Mask Register/LOW word
+ UInt8 ___filler7[0x30c-0x308];
+ UInt16 intStatusHi; // $30C: Interrupt Status Register/HIGH word
+ UInt16 intStatusLo; // $30E: Interrupt Status Register/LOW word
+ UInt16 intPendingHi; // $310: Interrupt Pending Register/HIGH word
+ UInt16 intPendingLo; // $312: Interrupt Pending Register/LOW word
+ UInt16 intLevelControl; // $314: Interrupt Level Control Register
+
+ UInt8 ___filler4a[0x400-0x316];
+
+ UInt8 portADir; // $400: Port A Direction Register
+ UInt8 portAData; // $401: Port A Data Register
+ UInt8 portAPullupEn; // $402: Port A Pullup Enable
+ UInt8 ___filler8[5];
+
+ UInt8 portBDir; // $408: Port B Direction Register
+ UInt8 portBData; // $409: Port B Data Register
+ UInt8 portBPullupEn; // $40A: Port B Pullup Enable
+ UInt8 portBSelect; // $40B: Port B Select Register
+
+ UInt8 ___filler9[4];
+
+ UInt8 portCDir; // $410: Port C Direction Register
+ UInt8 portCData; // $411: Port C Data Register
+ UInt8 portCPulldnEn; // $412: Port C Pulldown Enable
+ UInt8 portCSelect; // $413: Port C Select Register
+
+ UInt8 ___filler10[4];
+
+ UInt8 portDDir; // $418: Port D Direction Register
+ UInt8 portDData; // $419: Port D Data Register
+ UInt8 portDPullupEn; // $41A: Port D Pull-up Enable
+ UInt8 portDSelect; // $41B: Port D Select Register
+ UInt8 portDPolarity; // $41C: Port D Polarity Register
+ UInt8 portDIntReqEn; // $41D: Port D Interrupt Request Enable
+ UInt8 portDKbdIntEn; // $41E: Port D Keyboard Interrupt Enable
+ UInt8 portDIntEdge; // $41F: Port D IRQ Edge Register
+
+ UInt8 portEDir; // $420: Port E Direction Register
+ UInt8 portEData; // $421: Port E Data Register
+ UInt8 portEPullupEn; // $422: Port E Pull-up Enable
+ UInt8 portESelect; // $423: Port E Select Register
+
+ UInt8 ___filler14[4];
+
+ UInt8 portFDir; // $428: Port F Direction Register
+ UInt8 portFData; // $429: Port F Data Register
+ UInt8 portFPullupdnEn; // $42A: Port F Pull-up/down Enable
+ UInt8 portFSelect; // $42B: Port F Select Register
+
+ UInt8 ___filler16[4];
+
+ UInt8 portGDir; // $430: Port G Direction Register
+ UInt8 portGData; // $431: Port G Data Register
+ UInt8 portGPullupEn; // $432: Port G Pull-up Enable
+ UInt8 portGSelect; // $433: Port G Select Register
+
+ UInt8 ___filler17[0x438-0x434];
+
+ UInt8 portJDir; // $438: Port J Direction Register
+ UInt8 portJData; // $439: Port J Data Register
+ UInt8 portJPullupEn; // $43A: Port J Pull-up Enable
+ UInt8 portJSelect; // $43B: Port J Select Register
+
+ UInt8 ___filler18[0x440-0x43C];
+
+ UInt8 portKDir; // $440: Port K Direction Register
+ UInt8 portKData; // $441: Port K Data Register
+ UInt8 portKPullupdnEn; // $442: Port K Pull-up/down Enable
+ UInt8 portKSelect; // $443: Port K Select Register
+
+ UInt8 ___filler19[0x448-0x444];
+
+ UInt8 portMDir; // $448: Port M Direction Register
+ UInt8 portMData; // $449: Port M Data Register
+ UInt8 portMPullupdnEn; // $44A: Port M Pull-up/down Enable
+ UInt8 portMSelect; // $44B: Port M Select Register
+
+ UInt8 ___filler20[0x500-0x44C];
+
+ UInt16 pwmControl; // $500: PWM 1 Control Register (PWM 1 is the same as the single PWM in EZ)
+ UInt8 pwmSampleHi; // $502: PWM 1 Sample - high byte
+ UInt8 pwmSampleLo; // $503: PWM 1 Sample - low byte
+ UInt8 pwmPeriod; // $504: PWM 1 Period
+ UInt8 pwmCounter; // $505: PWM 1 Counter
+
+ UInt8 ___filler22[0x510-0x506];
+
+ UInt16 pwm2Control; // $510: PWM 2 Control Register
+ UInt16 pwm2Period; // $512: PWM 2 Period
+ UInt16 pwm2Width; // $514: PWM 2 Width
+ UInt16 pwm2Counter; // $516: PWM 2 Counter
+
+ UInt8 ___filler23[0x600-0x518];
+
+ UInt16 tmr1Control; // $600: Timer 1 Control Register
+ UInt16 tmr1Prescaler; // $602: Timer 1 Prescaler Register
+ UInt16 tmr1Compare; // $604: Timer 1 Compare Register
+ UInt16 tmr1Capture; // $606: Timer 1 Capture Register
+ UInt16 tmr1Counter; // $608: Timer 1 Counter Register
+ UInt16 tmr1Status; // $60A: Timer 1 Status Register
+
+ UInt8 ___filler24[0x610-0x60C];
+
+ UInt16 tmr2Control; // $610: Timer 2 Control Register
+ UInt16 tmr2Prescaler; // $612: Timer 2 Prescaler Register
+ UInt16 tmr2Compare; // $614: Timer 2 Compare Register
+ UInt16 tmr2Capture; // $616: Timer 2 Capture Register
+ UInt16 tmr2Counter; // $618: Timer 2 Counter Register
+ UInt16 tmr2Status; // $61A: Timer 2 Status Register
+
+ UInt8 ___filler25[0x700-0x61C];
+
+ UInt16 spiRxD; // $700: SPI Unit 1 Receive Data Register
+ UInt16 spiTxD; // $702: SPI Unit 1 Transmit Data Register
+ UInt16 spiCont1; // $704: SPI Unit 1 Control/Status Register
+ UInt16 spiIntCS; // $706: SPI Unit 1 Interrupt control/Status Register
+ UInt16 spiTest; // $708: SPI Unit 1 Test Register
+ UInt16 spiSpc; // $70A: SPI Unit 1 Sample period counter register
+
+ UInt8 ___filler26[0x800-0x70C];
+
+ UInt16 spiMasterData; // $800: SPI Unit 2 Data Register (SPI 2 is the same as the single SPI Master in EZ)
+ UInt16 spiMasterControl; // $802: SPI Unit 2 Control/Status Register
+
+ UInt8 ___filler27[0x900-0x804];
+
+ UInt16 uControl; // $900: Uart 1 Status/Control Register (Uart 1 is the same as the single Uart in EZ)
+ UInt16 uBaud; // $902: Uart 1 Baud Control Register
+ UInt16 uReceive; // $904: Uart 1 Receive Register
+ UInt16 uTransmit; // $906: Uart 1 Transmit Register
+ UInt16 uMisc; // $908: Uart 1 Miscellaneous Register
+ UInt16 uNonIntPresc; // $90A: Uart 1 Non-Integer Prescaler
+
+ UInt8 ___filler28[0x910-0x90C];
+
+ UInt16 u2Control; // $910: Uart 2 Status/Control Register
+ UInt16 u2Baud; // $912: Uart 2 Baud Control Register
+ UInt16 u2Receive; // $914: Uart 2 Receiver Register
+ UInt16 u2Transmit; // $916: Uart 2 Transmitter Register
+ UInt16 u2Misc; // $918: Uart 2 Miscellaneous Register
+ UInt16 u2NonIntPresc; // $91A: Uart 2 Non-Integer Prescaler
+ UInt16 u2FIFOHMark; // $91C: Uart 2 Half Mark FIFO Register
+
+ UInt8 ___filler28a[0xA00-0x91E];
+
+ UInt32 lcdStartAddr; // $A00: Screen Starting Address Register
+ UInt8 ___filler29;
+ UInt8 lcdPageWidth; // $A05: Virtual Page Width Register
+ UInt8 ___filler30[2];
+ UInt16 lcdScreenWidth; // $A08: Screen Width Register
+ UInt16 lcdScreenHeight; // $A0A: Screen Height Register
+ UInt8 ___filler31[0xA18-0xA0C];
+ UInt16 lcdCursorXPos; // $A18: Cursor X Position
+ UInt16 lcdCursorYPos; // $A1A: Cursor Y Position
+ UInt16 lcdCursorWidthHeight; // $A1C: Cursor Width and Height
+ UInt8 ___filler32;
+ UInt8 lcdBlinkControl; // $A1F: Blink Control Register
+ UInt8 lcdPanelControl; // $A20: Panel Interface Configuration Register
+ UInt8 lcdPolarity; // $A21: Polarity Config Register
+ UInt8 ___filler33;
+ UInt8 lcdACDRate; // $A23: ACD (M) Rate Control Register
+ UInt8 ___filler34;
+ UInt8 lcdPixelClock; // $A25: Pixel Clock Divider Register
+ UInt8 ___filler35;
+ UInt8 lcdClockControl; // $A27: Clocking Control Register
+// UInt8 ___filler36;
+ UInt16 lcdRefreshRateAdj; // $A28: Refresh Rate Adjustment Register
+ UInt8 ___filler37;
+ UInt8 lcdReserved1; // $A2B: Reserved
+ UInt8 ___filler38;
+ UInt8 lcdPanningOffset; // $A2D: Panning Offset Register
+
+ UInt8 ___filler39[0xA31-0xA2E];
+
+ UInt8 lcdFrameRate; // $A31: Frame Rate Control Modulation Register
+ UInt8 ___filler2004;
+ UInt8 lcdGrayPalette; // $A33: Gray Palette Mapping Register
+ UInt8 lcdReserved2; // $A34: Reserved
+ UInt8 ___filler2005;
+ UInt16 lcdContrastControlPWM; // $A36: Contrast Control
+ UInt8 lcdRefreshModeControl; // $A38: Refresh Mode Control Register
+ UInt8 lcdDMAControl; // $A39: DMA Control Register
+
+ UInt8 ___filler40[0xB00-0xA3a];
+
+ UInt32 rtcHourMinSec; // $B00: RTC Hours, Minutes, Seconds Register
+ UInt32 rtcAlarm; // $B04: RTC Alarm Register
+ UInt8 ___filler2001[0xB0A-0xB08];
+ UInt16 rtcWatchDog; // $B0A: RTC Watchdog Timer
+ UInt16 rtcControl; // $B0C: RTC Control Register
+ UInt16 rtcIntStatus; // $B0E: RTC Interrupt Status Register
+ UInt16 rtcIntEnable; // $B10: RTC Interrupt Enable Register
+ UInt16 stopWatch; // $B12: Stopwatch Minutes
+ UInt8 ___filler2002[0xB1A-0xB14];
+ UInt16 rtcDay; // $B1A: RTC Day
+ UInt16 rtcDayAlarm; // $B1C: RTC Day Alarm
+
+ UInt8 ___filler41[0xC00-0xB1E];
+
+ UInt16 dramConfig; // $C00: DRAM Memory Config Register
+ UInt16 dramControl; // $C02: DRAM Control Register
+ UInt16 sdramControl; // $C04: SDRAM Control Register
+ UInt16 sdramPwDn; // $C06: SDRAM Power Down Register
+
+ UInt8 ___filler42[0xD00-0xC08];
+
+ UInt32 emuAddrCompare; // $D00: Emulation Address Compare Register
+ UInt32 emuAddrMask; // $D04: Emulation Address Mask Register
+ UInt16 emuControlCompare; // $D08: Emulation Control Compare Register
+ UInt16 emuControlMask; // $D0A: Emulation Control Mask Register
+ UInt16 emuControl; // $DOC: Emulation Control Register
+ UInt16 emuStatus; // $D0E: Emulation Status Register
+};
+
+typedef volatile struct HwrM68VZ328Type* HwrM68VZ328Ptr;
+
+#define HwrDBallType HwrM68VZ328Type
+#define HwrDBallPtr HwrM68VZ328Ptr
+
+
+#if 0 // Take this out for Poser; it conflicts with the one in M68EZ328Hwr.h
+
+/************************************************************************
+ * Jerry EZ cost reduction PLD I/O register
+ ***********************************************************************/
+typedef volatile struct HwrJerryPLDType {
+
+ UInt8 dspOn; // pld output turn dsp on/off
+ UInt8 unused1;
+ UInt8 chargeOn; // pld output turn charger on/off
+ UInt8 unused2;
+ UInt8 refOn; // pld output turn 3.0 volt reference on/off
+ UInt8 unused3;
+ UInt8 pipaBiasEnable; // pld output turn PA bias on/off
+ UInt8 unused4;
+ UInt8 dspReset; // pld output control dsp reset pin up/down
+ UInt8 unused5;
+ UInt8 ezToDsl; // pld output comm. pin to dsp
+ UInt8 unused6;
+ UInt8 rs232Shdn; // pld output control rs232 interface chip on/off
+ UInt8 unused7;
+ UInt8 spareOut; // pld output not used
+ UInt8 unused8;
+ UInt16 dTo3Sln; // pld input comm. from dsp
+ UInt16 iXtrnl2; // pld input cradle connector pin
+} HwrJerryPLDType;
+
+typedef HwrJerryPLDType* HwrJerryPldPtr;
+
+/************************************************************************
+ * Jerry EZ cost reduction. PLD settings
+ ***********************************************************************/
+#define hwrJerryPld232Enable 0x80
+#define hwrJerryPld232Disable 0
+#define hwrJerryPldChargerOn 0x80
+#define hwrJerryPldChargerOff 0
+#define hwrJerryPldPaBiasEnable 0x80
+#define hwrJerryPldPaBiasDisable 0
+#define hwrJerryPldRefOn 0x80
+#define hwrJerryPldRefOff 0
+#define hwrJerryPldDspSelect 0x80
+#define hwrJerryPldDspDeselect 0
+#define hwrJerryPldDspResetAssert 0x80
+#define hwrJerryPldDspResetDeassert 0
+#define hwrJerryPldDspPowerOn 0x80
+#define hwrJerryPldDspPowerOff 0
+
+/************************************************************************
+ * Jerry EZ cost reduction. PLD shadow settings
+ ***********************************************************************/
+#define hwrJerryPldDspOnBit 0x0001
+#define hwrJerryPldChargeOnBit 0x0002
+#define hwrJerryPldRefOnBit 0x0004
+#define hwrJerryPldPaBiasEnableBit 0x0008
+#define hwrJerryPldDspResetBit 0x0010
+#define hwrJerryPldEzToDslBit 0x0020
+#define hwrJerryPldRs232Bit 0x0040
+#endif
+
+/************************************************************************
+ * Chip ID register for VZ
+ ***********************************************************************/
+ #define hwrVZ328chipIDVZ 0x45
+
+/************************************************************************
+ * Mask ID register for VZ
+ ***********************************************************************/
+#define hwrVZ328maskID0H31J 0x01
+#define hwrVZ328maskID0J75C 0x02
+#define hwrVZ328maskID1J75C 0x03
+#define hwrVZ328maskID0J83G 0x04
+
+/************************************************************************
+ * LCD Controller Bits
+ ************************************************************************/
+// lcdCursorXPos Register
+#define hwrVZ328LcdCursorXPosCtlMask 0xC000
+ #define hwrVZ328LcdCursorXPosCtlTrans 0x0000
+ #define hwrVZ328LcdCursorXPosCtlBlack 0x4000
+ #define hwrVZ328LcdCursorXPosCtlReverse 0x8000
+ #define hwrVZ328LcdCursorXPosCtlWhite 0xC000
+#define hwrVZ328LcdCursorXPosValueMask 0x1FF
+#define hwrVZ328LcdCursorYPosValueMask 0x1FF
+
+#define hwrVZ328LcdCursorWidthMask 0x1F
+ #define hwrVZ328LcdCursorWidthOffset 0x8
+#define hwrVZ328LcdCursorHeightMask 0x1F
+
+// lcdBlinkControl Register
+#define hwrVZ328LcdBlinkControlEnable 0x80
+#define hwrVZ328LcdBlinkDivisorMask 0x7F
+
+// lcdPanelControl Register
+#define hwrVZ328LcdPanelControlBusMask 0x0C
+ #define hwrVZ328LcdPanelControlBus1Bit 0x00
+ #define hwrVZ328LcdPanelControlBus2Bit 0x04
+ #define hwrVZ328LcdPanelControlBus4Bit 0x08
+#define hwrVZ328LcdPanelControlGrayScale 0x01
+#define hwrVZ328LcdPanelControl4BitGrayScale 0x02
+
+// lcdPolarity Register
+#define hwrVZ328LcdPolarityShiftClock 0x08
+#define hwrVZ328LcdPolarityFLM 0x04
+#define hwrVZ328LcdPolarityLP 0x02
+#define hwrVZ328LcdPolarityPixel 0x01
+
+// lcdClockControl Register
+#define hwrVZ328LcdClockControlEnable 0x80
+#define hwrVZ328LcdClockControl8BitBus 0x40
+
+#define hwrVZ328LcdClockControlBurstRateMask 0x0F
+#define hwrVZ328LcdClockControlBurstRate1 0x00
+#define hwrVZ328LcdClockControlBurstRate2 0x01
+#define hwrVZ328LcdClockControlBurstRate3 0x02
+#define hwrVZ328LcdClockControlBurstRate4 0x03
+#define hwrVZ328LcdClockControlBurstRate5 0x04
+#define hwrVZ328LcdClockControlBurstRate6 0x05
+#define hwrVZ328LcdClockControlBurstRate7 0x06
+#define hwrVZ328LcdClockControlBurstRate8 0x07
+#define hwrVZ328LcdClockControlBurstRate9 0x08
+#define hwrVZ328LcdClockControlBurstRate10 0x09
+#define hwrVZ328LcdClockControlBurstRate11 0x0A
+#define hwrVZ328LcdClockControlBurstRate12 0x0B
+#define hwrVZ328LcdClockControlBurstRate13 0x0C
+#define hwrVZ328LcdClockControlBurstRate14 0x0D
+#define hwrVZ328LcdClockControlBurstRate15 0x0E
+#define hwrVZ328LcdClockControlBurstRate16 0x0F
+
+#define hwrVZ328LcdContrastPWMWidthMask 0x00FF
+#define hwrVZ328LcdContrastEnable 0x0100
+
+
+
+/************************************************************************
+ * Interrupt Controller Bits
+ ************************************************************************/
+// intMaskHi bits
+// NOTE: Due to a bug in early rev's of the DragonBall, the clear bits for
+// IRQ[1236] on those early chips were different than the indicator bits
+// (the order was reversed). So some older code uses the OR of the IRQ1 and
+// IRQ6 bits for either, and the OR of the IRQ2 and IRQ3 bits for either.
+#define hwrVZ328IntHiEMU 0x0080
+#define hwrVZ328IntHiSampleTimer 0x0040
+#define hwrVZ328IntHiPen 0x0010
+#define hwrVZ328IntHiIRQ6 0x0008
+#define hwrVZ328IntHiIRQ3 0x0004
+#define hwrVZ328IntHiIRQ2 0x0002
+#define hwrVZ328IntHiIRQ1 0x0001
+
+// intMaskLo bits
+#define hwrVZ328IntLoPWM2 0x2000
+#define hwrVZ328IntLoPWM2Bit 13
+#define hwrVZ328IntLoUART2 0x1000
+#define hwrVZ328IntLoUART2Bit 12
+#define hwrVZ328IntLoInt3 0x0800
+#define hwrVZ328IntLoInt2 0x0400
+#define hwrVZ328IntLoInt1 0x0200
+#define hwrVZ328IntLoInt0 0x0100
+#define hwrVZ328IntLoAllKeys 0x0F00
+#define hwrVZ328IntLoInt0Bit 8
+#define hwrVZ328IntLoPWM 0x0080
+#define hwrVZ328IntLoPWMBit 7
+#define hwrVZ328IntLoKbd 0x0040
+#define hwrVZ328IntLoTimer2 0x0020
+#define hwrVZ328IntLoTimer2Bit 5
+#define hwrVZ328IntLoRTC 0x0010
+#define hwrVZ328IntLoRTCBit 4
+#define hwrVZ328IntLoWDT 0x0008
+#define hwrVZ328IntLoUART 0x0004
+#define hwrVZ328IntLoUARTBit 2
+#define hwrVZ328IntLoTimer 0x0002
+#define hwrVZ328IntLoTimerBit 1
+#define hwrVZ328IntLoSPIM 0x0001
+
+// intControl bits
+// NOTE: These are different than that documented in the User's manual
+// for the DragonBall (see erratas). The DragonBall is the same as the EZ.
+#define hwrVZ328IntCtlEdge1 0x0800
+#define hwrVZ328IntCtlEdge2 0x0400
+#define hwrVZ328IntCtlEdge3 0x0200
+#define hwrVZ328IntCtlEdge6 0x0100
+#define hwrVZ328IntCtlPol1 0x8000
+#define hwrVZ328IntCtlPol2 0x4000
+#define hwrVZ328IntCtlPol3 0x2000
+#define hwrVZ328IntCtlPol6 0x1000
+#define hwrVZ328IntCtlPol5 0x0080
+
+/************************************************************************
+ * DRAM Controller Bits bits
+ * Not all the bits are defined here-- some are pretty bad to muck with
+ * in anything but initial setup of the DRAM.
+ ************************************************************************/
+#define hwrVZ328dramControlEnable 0x8000
+#define hwrVZ328dramControlSelfRefreshEn 0x4000
+#define hwrVZ328dramControlEDOEn 0x0400
+#define hwrVZ328dramControlLightSleep 0x0010
+#define hwrVZ328dramControlLowPowerRefreshEn 0x0004
+#define hwrVZ328dramControlDWEEnable 0x0001
+
+
+/************************************************************************
+ * SDRAM Controller Bits bits
+ * Not all the bits are defined here-- some are pretty bad to muck with
+ * in anything but initial setup of the SDRAM.
+ ************************************************************************/
+// SdramControl bits
+#define hwrVZ328SdramControlEnable 0x8000
+#define hwrVZ328SdramControlContPgModeEn 0x4000
+ // rsvd
+#define hwrVZ328SdramControlRefreshEn 0x1000
+#define hwrVZ328SdramControlInitPreChg 0x0800
+#define hwrVZ328SdramControlInitModeReg 0x0400
+ // rsvd
+ // rsvd
+ // rsvd
+#define hwrVZ328SdramControlSColOpt 0x0040
+ // BnkAddH[1:0]
+ // BnkAddL[1:0]
+#define hwrVZ328SdramControlCASLatency 0x0002
+#define hwrVZ328SdramControlRefrActCmdLatency 0x0001
+
+// SdramPwDn bits
+#define hwrVZ328SdramPwDnAPEn 0x8000
+#define hwrVZ328SdramPwDnPDEn 0x4000
+ // rsvd
+ // rsvd
+ // PDTOUT[3:0]
+ // rsvd
+ // rsvd
+ // rsvd
+ // rsvd
+ // rsvd
+ // rsvd
+ // rsvd
+ // rsvd
+
+
+/************************************************************************
+ * Timer bits
+ ************************************************************************/
+#define hwrVZ328TmrControlUnused 0xFC00
+#define hwrVZ328TmrControlTIOOutput 0x0200
+#define hwrVZ328TmrControlFreeRun 0x0100
+#define hwrVZ328TmrControlCaptureEdgeMask 0x00C0
+ #define hwrVZ328TmrControlCaptureEdgeNone 0x0000
+ #define hwrVZ328TmrControlCaptureEdgeRising 0x0040
+ #define hwrVZ328TmrControlCaptureEdgeFalling 0x0080
+ #define hwrVZ328TmrControlCaptureEdgeBoth 0x00C0
+#define hwrVZ328TmrControlOutputModeToggle 0x0020
+#define hwrVZ328TmrControlEnInterrupt 0x0010
+#define hwrVZ328TmrControlClkSrcMask 0x000E
+ #define hwrVZ328TmrControlClkSrcStop 0x0000
+ #define hwrVZ328TmrControlClkSrcSys 0x0002
+ #define hwrVZ328TmrControlClkSrcSysBy16 0x0004
+ #define hwrVZ328TmrControlClkSrcTIN 0x0006
+ #define hwrVZ328TmrControlClkSrc32KHz 0x0008
+#define hwrVZ328TmrControlEnable 0x0001
+
+#define hwrVZ328TmrStatusCapture 0x0002
+#define hwrVZ328TmrStatusCaptureBit 1
+#define hwrVZ328TmrStatusCompare 0x0001
+#define hwrVZ328TmrStatusCompareBit 0
+
+
+/************************************************************************
+ * 68VZ328 Serial Port Register Bits
+ ************************************************************************/
+// uControl Register
+#define hwrVZ328UControlUARTEnable 0x8000
+#define hwrVZ328UControlRxEnable 0x4000
+#define hwrVZ328UControlTxEnable 0x2000
+#define hwrVZ328UControlRxClock1xSync 0x1000
+#define hwrVZ328UControlParityEn 0x0800
+#define hwrVZ328UControlParityOdd 0x0400
+#define hwrVZ328UControlStopBits2 0x0200
+#define hwrVZ328UControlDataBits8 0x0100
+#define hwrVZ328UControlOldDataEn 0x0080
+#define hwrVZ328UControlCTSDeltaEn 0x0040
+#define hwrVZ328UControlRxFullEn 0x0020
+#define hwrVZ328UControlRxHalfEn 0x0010
+#define hwrVZ328UControlRxRdyEn 0x0008
+#define hwrVZ328UControlTxEmptyEn 0x0004
+#define hwrVZ328UControlTxHalfEn 0x0002
+#define hwrVZ328UControlTxAvailEn 0x0001
+
+#define hwrVZ328UControlEnableAll (hwrVZ328UControlUARTEnable | \
+ hwrVZ328UControlRxEnable | \
+ hwrVZ328UControlTxEnable)
+
+// uBaud Register
+// UCLK output requires PE3 Select to be 0
+#define hwrVZ328UBaudUCLKDirOut 0x2000
+#define hwrVZ328UBaudBaudSrcUCLK 0x0800
+#define hwrVZ328UBaudDivider 0x0700
+#define hwrVZ328UBaudPrescaler 0x003F
+
+#define hwrVZ328UBaudDivideBitOffset 8
+
+
+// uReceive Register
+#define hwrVZ328UReceiveFIFOFull 0x8000
+#define hwrVZ328UReceiveFIFOHalf 0x4000
+#define hwrVZ328UReceiveDataRdy 0x2000
+#define hwrVZ328UReceiveDataRdyBit 13
+#define hwrVZ328UReceiveOldData 0x1000
+#define hwrVZ328UReceiveOverrunErr 0x0800
+#define hwrVZ328UReceiveOverrunErrBit 11
+#define hwrVZ328UReceiveFrameErr 0x0400
+#define hwrVZ328UReceiveFrameErrBit 10
+#define hwrVZ328UReceiveBreakErr 0x0200
+#define hwrVZ328UReceiveBreakErrBit 9
+#define hwrVZ328UReceiveParityErr 0x0100
+#define hwrVZ328UReceiveParityErrBit 8
+#define hwrVZ328UReceiveData 0x00FF
+
+#define hwrVZ328UReceiveErrsMask (hwrVZ328UReceiveOverrunErr | \
+ hwrVZ328UReceiveFrameErr | \
+ hwrVZ328UReceiveBreakErr | \
+ hwrVZ328UReceiveParityErr)
+
+// uTransmit Register
+#define hwrVZ328UTransmitFIFOEmpty 0x8000
+#define hwrVZ328UTransmitFIFOHalf 0x4000
+#define hwrVZ328UTransmitTxAvail 0x2000
+#define hwrVZ328UTransmitSendBreak 0x1000
+#define hwrVZ328UTransmitIgnoreCTS 0x0800
+#define hwrVZ328UTransmitBusy 0x0400
+#define hwrVZ328UTransmitCTSStatus 0x0200
+#define hwrVZ328UTransmitCTSDelta 0x0100
+#define hwrVZ328UTransmitData 0x00FF
+
+// uMisc Register
+#define hwrVZ328UMiscBaudTest 0x8000
+#define hwrVZ328UMiscClkSrcUCLK 0x4000
+#define hwrVZ328UMiscForceParityErr 0x2000
+#define hwrVZ328UMiscLoopback 0x1000
+#define hwrVZ328UMiscBaudReset 0x0800
+#define hwrVZ328UMiscIRTestEn 0x0400
+#define hwrVZ328UMiscReservedMask 0x0300
+#define hwrVZ328UMiscRTSThruFIFO 0x0080
+#define hwrVZ328UMiscRTSOut 0x0040
+#define hwrVZ328UMiscIRDAEn 0x0020
+#define hwrVZ328UMiscLoopIRDA 0x0010
+#define hwrVZ328UMiscRXPolarityInv 0x0008
+#define hwrVZ328UMiscTXPolarityInv 0x0004
+#define hwrVZ328UMiscUnused 0x0003
+
+// uNonIntPresc Register
+#define hwrVZ328UNonIntPrescSrcIntPresc 0x0000
+#define hwrVZ328UNonIntPrescSrcNonIntPresc 0x8000
+
+#define hwrVZ328UNonIntPrescSelDiv128 0x0000
+#define hwrVZ328UNonIntPrescSelDiv64 0x0100
+#define hwrVZ328UNonIntPrescSelDiv32 0x0200
+#define hwrVZ328UNonIntPrescSelDiv16 0x0300
+#define hwrVZ328UNonIntPrescSelDiv8 0x0400
+#define hwrVZ328UNonIntPrescSelDiv4 0x0500
+#define hwrVZ328UNonIntPrescSelDiv2 0x0600
+#define hwrVZ328UNonIntPrescSelDiv1 0x0700
+
+#define hwrVZ328UNonIntPrescStepMask 0x00FF
+#define hwrVZ328UNonIntPrescSelOffset 8
+
+// see VZ docs for explanation of the following. This provides the correct
+// pulse width for IRDA, and is just a statement in the docs. The values don't
+// appear to make sense, but I just push the buttons.
+
+// This has been deprecated in favor of a prv function in the serial driver and
+// the SerialMgr (depending on whether you have Bond or not) that calculates
+// the value of this register based on the clock frequency you're running on.
+// There was a bug when running EZ at 20MHz that caused the IrDA pulsewidth to
+// get too short.
+
+#if 0
+#define hwrVZ328UNonIntPrescIRDAMode (hwrVZ328UNonIntPrescSrcIntPresc \
+ | hwrVZ328UNonIntPrescSelDiv32 \
+ | (hwrVZ328UNonIntPrescStepMask & 0x20))
+#endif
+
+/************************************************************************
+ * PWM Bits
+ ************************************************************************/
+// PWM register bits of interest
+#define hwrVZ328PWMControlEnable 0x0010
+#define hwrVZ328PWMControlEnableBit 4
+#define hwrVZ328PWMControlEnableIRQ 0x0040
+#define hwrVZ328PWMIRQStatus 0x0080
+// PWM divider chain output selectors
+#define hwrVZ328PWMControlDivMask 0x0003
+#define hwrVZ328PWMControlDivBy2 0x0
+#define hwrVZ328PWMControlDivBy4 0x1
+#define hwrVZ328PWMControlDivBy8 0x2
+#define hwrVZ328PWMControlDivBy16 0x3
+// PWM Repeat Counts
+#define hwrVZ328PWMRepeatSample1x 0x0
+#define hwrVZ328PWMRepeatSample2x 0x4
+#define hwrVZ328PWMRepeatSample4x 0x8
+#define hwrVZ328PWMRepeatSample8x 0xC
+// PWM hardware constraints
+#define hwrVZ328PWMFifoSizeInBytes 4
+#define hwrVZ328PWMPrescalerMask 0x7F00
+#define hwrVZ328PWMPrescalerOffset 8
+
+/************************************************************************
+ * PLL Bits
+ ************************************************************************/
+#define hwrVZ328PLLControlDisable 0x0008
+#define hwrVZ328PLLControlClkDisable 0x0010
+
+#define hwrVZ328PLLControlSysDMADiv2 0x0000
+#define hwrVZ328PLLControlSysDMADiv4 0x0100
+#define hwrVZ328PLLControlSysDMADiv8 0x0200
+#define hwrVZ328PLLControlSysDMADiv16 0x0300
+#define hwrVZ328PLLControlSysDMADiv1 0x0400
+
+#define hwrVZ328PLLControlPixDMADiv2 0x0000
+#define hwrVZ328PLLControlPixDMADiv4 0x0800
+#define hwrVZ328PLLControlPixDMADiv8 0x1000
+#define hwrVZ328PLLControlPixDMADiv16 0x1800
+#define hwrVZ328PLLControlPixDMADiv1 0x2000
+
+#define hwrVZ328PLLControlPreSc1Div2 0x0080
+#define hwrVZ328PLLControlPreSc1Div1 0x0000
+
+#define hwrVZ328PLLControlPreSc2Div2 0x0020
+#define hwrVZ328PLLControlPreSc2Div1 0x0000
+
+#define hwrCZ328PLLControl32Periods 0x0000
+#define hwrCZ328PLLControl48Periods 0x0001
+#define hwrCZ328PLLControl64Periods 0x0002
+#define hwrCZ328PLLControl96Periods 0x0003
+
+#define hwrVZ328PLLFreqSelCLK32 0x8000
+
+/************************************************************************
+ * Real Time Clock (RTC) Bits
+ ************************************************************************/
+
+// RTC Control Register (RTCCTL) bits
+#define hwrVZ328RTCControlRTCEnable 0x80
+#define hwrVZ328RTCControlRefSelMask 0x20
+#define hwrVZ328RTCControlRefSel38400 0x20 // 38.4 kHz reference frequency
+#define hwrVZ328RTCControlRefSel32768 0x00 // 32.768 kHz reference frequency
+
+// RTC Interrupt Enable Register (RTCIENR) bits
+#define hwrVZ328RTCIntEnableSample7 0x8000
+#define hwrVZ328RTCIntEnableSample6 0x4000
+#define hwrVZ328RTCIntEnableSample5 0x2000
+#define hwrVZ328RTCIntEnableSample4 0x1000
+#define hwrVZ328RTCIntEnableSample3 0x0800
+#define hwrVZ328RTCIntEnableSample2 0x0400
+#define hwrVZ328RTCIntEnableSample1 0x0200
+#define hwrVZ328RTCIntEnableSample0 0x0100
+#define hwrVZ328RTCIntEnableHour 0x0020
+#define hwrVZ328RTCIntEnableSec 0x0010
+#define hwrVZ328RTCIntEnable24Hr 0x0008
+#define hwrVZ328RTCIntEnableAlarm 0x0004
+#define hwrVZ328RTCIntEnableMinute 0x0002
+#define hwrVZ328RTCIntEnableStopWatch 0x0001
+
+// RTC Interrupt Status Register bits
+#define hwrVZ328RTCIntStatusSample7 0x8000
+#define hwrVZ328RTCIntStatusSample6 0x4000
+#define hwrVZ328RTCIntStatusSample5 0x2000
+#define hwrVZ328RTCIntStatusSample4 0x1000
+#define hwrVZ328RTCIntStatusSample3 0x0800
+#define hwrVZ328RTCIntStatusSample2 0x0400
+#define hwrVZ328RTCIntStatusSample1 0x0200
+#define hwrVZ328RTCIntStatusSample0 0x0100
+#define hwrVZ328RTCIntStatusHour 0x0020
+#define hwrVZ328RTCIntStatusSec 0x0010
+#define hwrVZ328RTCIntStatus24Hr 0x0008
+#define hwrVZ328RTCIntStatusAlarm 0x0004
+#define hwrVZ328RTCIntStatusMinute 0x0002
+#define hwrVZ328RTCIntStatusStopWatch 0x0001
+
+// RTC Alarm register (RTCALRM) masks and offsets
+#define hwrVZ328RTCAlarmSecondsMask 0x0000003fL
+#define hwrVZ328RTCAlarmSecondsOffset 0
+#define hwrVZ328RTCAlarmMinutesMask 0x003f0000L
+#define hwrVZ328RTCAlarmMinutesOffset 16
+#define hwrVZ328RTCAlarmHoursMask 0x1f000000L
+#define hwrVZ328RTCAlarmHoursOffset 24
+
+// RTC hours/minutes/seconds register (RTCHMS) masks and offsets
+#define hwrVZ328RTCHourMinSecSecondsMask 0x0000003fL
+#define hwrVZ328RTCHourMinSecSecondsOffset 0
+#define hwrVZ328RTCHourMinSecMinutesMask 0x003f0000L
+#define hwrVZ328RTCHourMinSecMinutesOffset 16
+#define hwrVZ328RTCHourMinSecHoursMask 0x1f000000L
+#define hwrVZ328RTCHourMinSecHoursOffset 24
+
+// RTC Day register masks/offsets
+#define hwrVZ328RTCDayDayMask 0x01FF
+#define hwrVZ328RTCDayDayOffset 0
+
+// RTC Watchdog Timer masks/offsets
+#define hwrVZ328RTCWatchdogEnable 0x0001
+#define hwrVZ328RTCWatchdogIntSel 0x0002
+#define hwrVZ328RTCWatchdogIntStatus 0x0080
+#define hwrVZ328RTCWatchdogCountMask 0x0300
+#define hwrVZ328RTCWatchdogCountOffset 8
+
+/************************************************************************
+ * SPI Master bits
+ ************************************************************************/
+#define hwrVZ328SPIMControlRateMask 0xE000
+ #define hwrVZ328SPIMControlRateDiv4 0x0000
+ #define hwrVZ328SPIMControlRateDiv8 0x2000
+ #define hwrVZ328SPIMControlRateDiv16 0x4000
+ #define hwrVZ328SPIMControlRateDiv32 0x6000
+ #define hwrVZ328SPIMControlRateDiv64 0x8000
+ #define hwrVZ328SPIMControlRateDiv128 0xA000
+ #define hwrVZ328SPIMControlRateDiv256 0xC000
+ #define hwrVZ328SPIMControlRateDiv512 0xE000
+#define hwrVZ328SPIMControlEnable 0x0200
+#define hwrVZ328SPIMControlExchange 0x0100
+#define hwrVZ328SPIMControlIntStatus 0x0080
+#define hwrVZ328SPIMControlIntEnable 0x0040
+#define hwrVZ328SPIMControlOppPhase 0x0020
+#define hwrVZ328SPIMControlInvPolarity 0x0010
+#define hwrVZ328SPIMControlBitsMask 0x000F
+
+
+#endif // __M68VZ328_H__
+
+#endif // NON_PORTABLE
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/DataPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/DataPrv.h
new file mode 100644
index 0000000..87884f8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/DataPrv.h
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DataPrv.h
+ *
+ * Description:
+ * Private Header for the Data Manager
+ *
+ * History:
+ * 08/10/95 RM Created by Ron Marianetti
+ * 10/26/99 kwk Backed out overlay cache modifications, and added
+ * constants for RAM vs. ROM store ids.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+#ifndef __DATAPRV_H__
+#define __DATAPRV_H__
+
+// DOLATER kwk - find out if the decision was made to use nested includes,
+// or do I need to go through and hit all of the source files that include
+// DataPrv.h to also include OverlayMgr.h (or add OverlayMgr.h to SysAll.h)
+
+#include <OverlayMgr.h>
+
+/************************************************************
+ * Ways that a database can be open.
+ *************************************************************/
+#define openTypeRegular 0 // Nothing special.
+#define openTypeBase (openTypeRegular+1) // Rsc db opened as base.
+#define openTypeOverlay (openTypeRegular+2) // Rsc db opened as overlay.
+
+
+/************************************************************
+ * Structure of a Record entry
+ *************************************************************/
+typedef struct {
+ LocalID localChunkID; // local chunkID of a record
+ UInt8 attributes; // record attributes;
+ UInt8 uniqueID[3]; // unique ID of record; should
+ // not be 0 for a legal record.
+ } RecordEntryType;
+typedef RecordEntryType* RecordEntryPtr;
+
+
+
+/************************************************************
+ * Structure of a Resource entry
+ *************************************************************/
+typedef struct {
+ UInt32 type; // resource type
+ UInt16 id; // resource id
+ LocalID localChunkID; // resource data chunk ID
+ } RsrcEntryType;
+typedef RsrcEntryType* RsrcEntryPtr;
+
+// Attributes field
+#define dmRsrcAttrUnused 0x0000 // to be defined...
+
+
+
+/************************************************************
+ * Structure of a record list extension. This is used if all
+ * the database record/resource entries of a database can't fit into
+ * the database header.
+ *************************************************************/
+typedef struct {
+ LocalID nextRecordListID; // local chunkID of next list
+ UInt16 numRecords; // number of records in this list
+ UInt16 firstEntry; // array of Record/Rsrc entries
+ // starts here
+ } RecordListType;
+typedef RecordListType* RecordListPtr;
+
+
+
+
+/************************************************************
+ * Structure of a Database Header
+ *************************************************************/
+typedef struct {
+ UInt8 name[dmDBNameLength]; // name of database
+ UInt16 attributes; // database attributes
+ UInt16 version; // version of database
+
+ UInt32 creationDate; // creation date of database
+ UInt32 modificationDate; // latest modification date
+ UInt32 lastBackupDate; // latest backup date
+ UInt32 modificationNumber; // modification number of database
+
+ LocalID appInfoID; // application specific info
+ LocalID sortInfoID; // app specific sorting info
+
+ UInt32 type; // database type
+ UInt32 creator; // database creator
+
+ UInt32 uniqueIDSeed; // used to generate unique IDs.
+ // Note that only the low order
+ // 3 bytes of this is used (in
+ // RecordEntryType.uniqueID).
+ // We are keeping 4 bytes for
+ // alignment purposes.
+
+ RecordListType recordList; // first record list
+ } DatabaseHdrType;
+
+typedef DatabaseHdrType* DatabaseHdrPtr;
+
+
+
+
+
+/************************************************************
+ * Directory of all available databases - maintained by the
+ * Database Manager. This directory also includes resource
+ * databases. There is one of these directories for each store
+ * (either RAM or ROM store) in a memory card. The ROM store
+ * list gets copied into the RAM store list at DmInit time.
+ *************************************************************/
+
+typedef struct {
+ LocalID baseID;
+ } DatabaseDirEntryType;
+
+typedef struct {
+ LocalID nextDatabaseListID; // continuation list, if any
+ UInt16 numDatabases; // # of database ID's in this list
+ DatabaseDirEntryType databaseID[1]; // one entry per database
+ } DatabaseDirType;
+
+typedef DatabaseDirType* DatabaseDirPtr;
+
+
+
+
+/************************************************************
+ * This structure is used to hold information on an open database
+ * It gets allocated as a non-movable chunk in the dynamic heap
+ * when a database is opened and caches database information that
+ * helps speed up performance.
+ *************************************************************/
+typedef struct {
+ void * next; // MemPtr to next access structure
+ UInt16 openCount; // incremented every time it's opened
+ UInt32 ownerTaskID; // taskID of owner
+ UInt16 exclusive : 1; // true if opened with exclusive access
+ UInt16 writeAccess : 1; // true if opened with write access
+ UInt16 resDB : 1; // true if resource database
+ LocalID hdrID; // local ID of database header
+ MemHandle hdrH; // Database header handle
+ DatabaseHdrPtr hdrP; // Database header MemPtr for faster access
+ UInt16 cardNo; // card number of database
+ UInt16 numRecords; // cached here for better performance
+ MemPtr hdrMasterP; // master MemPtr to header if ROM based
+ MemPtr* handleTableP; // pointer to block of ROM handles
+ } DmOpenInfoType;
+
+typedef DmOpenInfoType* DmOpenInfoPtr;
+
+
+/************************************************************
+ * This structure is used to hold client specific information for
+ * an open database. There is one of these allocated every time
+ * a database is opened, even if it's already open. This structure
+ * holds the open mode of the client and a pointer to the DmOpenInfoType
+ * of the database which contains the common database info for all
+ * clients. The SysAppInfoPtr, referenced off of the current A5,
+ * has a pointer to the first DmAccessType in the linked list.
+ *************************************************************/
+typedef struct DmAccessType {
+ struct DmAccessType* next; // MemPtr to next access structure
+ UInt16 mode; // mode it was opened in
+ DmOpenInfoPtr openP; // MemPtr to DmOpenInfoType for database
+
+ // NEW FOR PalmOS v3.0
+ UInt32 savedModNum; // saved modification number of database
+ // at the time of opening
+
+ // NEW FOR PalmOS 3.5
+ UInt8 openType; // Regular, base, or overlay
+ UInt8 reserved;
+ } DmAccessType;
+
+typedef DmAccessType* DmAccessPtr;
+
+
+
+/************************************************************
+ * This structure is used to hold the results of a search
+ * in DmGetNextDatabaseByTypeCreator. It is the "real" structure
+ * of the generic type DmSearchStateType used by applications.
+ *************************************************************/
+#if EMULATION_LEVEL == EMULATION_NONE
+#define MAX_CARDS 1
+#else
+#define MAX_CARDS 2
+#endif
+#define MAX_STORES_PER_CARD 2
+#define MAX_STORES (MAX_CARDS * MAX_STORES_PER_CARD)
+
+typedef struct {
+ UInt16 indexes[MAX_STORES];
+ UInt16 cardNos[MAX_STORES]; // cardNo for each store
+ UInt32 latestVersionCandidateType; // saved type of latest version candidate
+ UInt32 latestVersionCandidateCreator; // saved creator of latest version candidate
+ Int16 latestVersionCandidateStore; // saved store for latest versions
+ } DmPrvSearchStateType;
+typedef DmPrvSearchStateType* DmPrvSearchStatePtr;
+
+
+/************************************************************
+ * This structure is used to keep track of protected databases. These
+ * are databases which have been protected through the DmDatabaseProtect()
+ * call. A handle to an array of these structures is stored in the
+ * low memory global GDmProtectListH. The number of entries in the array
+ * must be calculated by taking the size of the handle and dividing
+ * by sizeof (DmProtectEntryType)
+ *************************************************************/
+typedef struct {
+ UInt8 protectCount;
+ UInt8 cardNo;
+ LocalID dbID;
+ } DmProtectEntryType, *DmProtectEntryPtr;
+
+
+/************************************************************
+ * This structure is used to cache data about applications and
+ * launchable data databases in the system Launch Database.
+ * This is the record structure for the database.
+ *************************************************************/
+#define dmMaxVersionStrLength 16
+
+typedef struct {
+ // Cached database info:
+ UInt32 type; // type of database
+ UInt32 creator; // creator of database
+ LocalID dbID; // LocalID of database
+ UInt16 cardNo; // card number of database
+ UInt16 dbAttrs; // database attributes
+ UInt16 version; // version of database
+ UInt8 dbName[dmDBNameLength]; // database name
+
+ // Launcher info:
+ UInt16 lgIconOffset; // offset in bytes from beginning of record to bitmap for large icon
+ UInt16 smIconOffset; // offset in bytes from beginning of record to bitmap for small icon
+ UInt8 iconName[dmDBNameLength]; // application icon name (from tain resource)
+ Char versionStr[dmMaxVersionStrLength]; // version string to display in Launcher
+ UInt8 flags; // launch flags, defined below
+ UInt8 reserved;
+
+ // Small & Large bitmaps for the database are stored
+ // at the end of the record, and are 4-byte aligned.
+
+ } DmLaunchDBRecordType, *DmLaunchDBRecordPtr;
+
+// Constants for the 'flags' field in DmLaunchDBRecordType
+#define dmLaunchFlagDirty 0x01 // Used to tell the launcher to update
+ // the category & launcher info,
+#define dmLaunchFlagOrphaned 0x02 // Used during boot in PrvSyncLaunchDatabase()
+ // to remove superfluous entries.
+#define dmLaunchFlagLaunchable 0x04 // Used during boot in PrvSyncLaunchDatabase()
+ // to remove superfluous entries.
+#define dmLaunchFlagResetCategory 0x08 // Used to force the launcher to move the
+ // entity into its default category.
+
+
+// Type & creator for the launch database:
+#define dmLaunchDatabaseType 'lnch'
+#define dmLaunchDatabaseCreator sysFileCSystem
+#define dmLaunchDatabaseVersion 1
+#define dmLaunchDatabaseName "psysLaunchDB"
+
+// For private database searching routine
+typedef Int16 (*DmSearchFuncPtr) (void const * searchData, void const * dbData, Int32 other);
+
+/************************************************************
+ * The owner ID of chunks allocated by the Database Manager
+ *************************************************************/
+#define dmDynOwnerID 0x00 // Dynamic heap chunks
+#define dmMgrOwnerID 0x01 // Management chunks
+#define dmRecOwnerID 0x02 // Record chunks
+#define dmOrphanOwnerID 0x03 // Orphaned record chunks
+
+
+/************************************************************
+ * Private Data Manager procedures
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Err DmMoveOpenDBContext(DmAccessPtr* listHeadP, DmAccessPtr dbP)
+ SYS_TRAP(sysTrapDmMoveOpenDBContext);
+
+DmOpenRef DmOpenDBWithLocale(UInt16 cardNo, LocalID dbID, UInt16 mode, const OmLocaleType* localeP)
+ SYS_TRAP(sysTrapDmOpenDBWithLocale);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif // __DATAPRV_H__
+#endif //NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/DebugPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/DebugPrv.h
new file mode 100644
index 0000000..727ae6a
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/DebugPrv.h
@@ -0,0 +1,439 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DebugPrv.h
+ *
+ * Description:
+ * Privat«Debugging functions
+ *
+ * History:
+ * 8/10/95 RM - Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+#ifndef __DEBUGPRV_H__
+#define __DEBUGPRV_H__
+
+
+/***********************************************************************
+ * Debugger Constants
+ ***********************************************************************/
+#define dbgLoopsPerTick 0x0800
+#define dbgStackSize 0x0380 // DOLATER -- resize???
+
+#define dbgNormalBreakpoints 5
+#define dbgTempBPIndex dbgNormalBreakpoints
+#define dbgTotalBreakpoints (dbgTempBPIndex+1)
+
+#define dbgFlashCodeSpace sysInitStack // where we copy flash code
+#define dbgFlashCodeSize 0x200 // size of flash code
+
+#define dbgTotalTrapBreaks 5 // up to this many trap breaks at a time
+
+
+
+
+/***********************************************************************
+ * Structure of Debugger Breakpoints
+ ***********************************************************************/
+typedef struct BreakpointType {
+ MemPtr addr; // address of breakpoint
+ Boolean enabled; // true if enabled
+ Boolean installed; // for alignment
+ } BreakpointType;
+
+
+
+
+
+/***********************************************************************
+ * Structure of Debugger Specific System Packet Type Bodies.
+ ***********************************************************************/
+
+#define sysPktMaxNameLen 32 // Max length of a routine name
+
+//--------------------------------------------------------------
+// sysPktStateCmd
+// - get processor state
+//------------------------------------------------------------------
+// number of remote code words to send in the 'state response' packet
+#define sysPktStateRspInstWords 15
+
+
+typedef struct SysPktStateCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktStateCmdCmdType;
+typedef SysPktStateCmdCmdType* SysPktStateCmdCmdPtr;
+
+
+// Packet Body structure for the state command response packet
+typedef struct SysPktStateRspType {
+ _sysPktBodyCommon; // Common Body header
+ Boolean resetted; // true if target has just reset
+ UInt8 reserved1;
+ UInt16 exceptionId; // exception which caused the
+ // debugger to be entered.
+ M68KRegsType reg; // current remote registers.
+ UInt16 inst[sysPktStateRspInstWords];
+ // instruction buffer for
+ // code beginning at PC.
+ BreakpointType bp[dbgTotalBreakpoints]; // current breakpoints
+
+ void *startAddr; // start address of routine
+ void *endAddr; // end address of routine
+ char name[sysPktMaxNameLen];
+ // routine name (0 or more chars,
+ // no null), immediately
+ // follows the address range.
+ UInt8 trapTableRev; // rev of trap table. Used to determine
+ // when host's trap table cache is invalid
+ UInt8 reserved2;
+ } SysPktStateRspType;
+typedef SysPktStateRspType* SysPktStateRspPtr;
+
+//--------------------------------------------------------------------
+// sysPktGetRtnNameCmd
+// - get routine name
+//--------------------------------------------------------------------
+// The response packet body will contain start address(4 bytes),
+// end address(4 bytes), followed by 0 or more bytes of the routine
+// name (no null byte).
+typedef struct SysPktRtnNameCmdType {
+ _sysPktBodyCommon; // Common Body header
+ void *address; // -> address to query on
+ } SysPktRtnNameCmdType;
+typedef SysPktRtnNameCmdType* SysPktRtnNameCmdPtr;
+
+typedef struct SysPktRtnNameRspType {
+ _sysPktBodyCommon; // Common Body header
+ void *address; // -> address to query on
+ void *startAddr; // <- start address of routine
+ void *endAddr; // <- end address of routine
+ char name[sysPktMaxNameLen]; // <- routine name, if any immediately
+ // follows the address range.
+ // The balance need not be sent.
+ } SysPktRtnNameRspType;
+typedef SysPktRtnNameRspType* SysPktRtnNameRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktReadRegsCmd
+// - read registers
+//--------------------------------------------------------------------
+// Packet Body structure for the read regs command response packet
+typedef struct SysPktReadRegsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktReadRegsCmdType;
+typedef SysPktReadRegsCmdType * SysPktReadRegsCmdPtr;
+
+typedef struct SysPktReadRegsRspType {
+ _sysPktBodyCommon; // Common Body header
+ //M68KRegsType reg; // <- return registers
+ } SysPktReadRegsRspType;
+typedef SysPktReadRegsRspType * SysPktReadRegsRspPtr;
+
+
+
+//--------------------------------------------------------------------
+// sysPktWriteRegsCmd
+// - write registers
+//--------------------------------------------------------------------
+// Packet Body structure for the write regs command packet
+typedef struct SysPktWriteRegsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ M68KRegsType reg; // -> registers to write
+ } SysPktWriteRegsCmdType;
+typedef SysPktWriteRegsCmdType * SysPktWriteRegsCmdPtr;
+
+
+// Packet Body structure for the write regs command packet
+typedef struct SysPktWriteRegsRspType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktWriteRegsRspType;
+typedef SysPktWriteRegsRspType * SysPktWriteRegsRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktContinueCmd
+// - continue
+//--------------------------------------------------------------------
+// Packet Body structure for the continue command packet
+typedef struct SysPktContinueCmdType {
+ _sysPktBodyCommon; // Common Body header
+ M68KRegsType regs; // registers
+ Boolean stepSpy; // set true to do step spy
+ UInt8 reserved;
+ UInt32 ssAddr; // step spy address
+ UInt32 ssCount; // # of bytes
+ UInt32 ssCheckSum; // checksum
+ } SysPktContinueCmdType;
+
+typedef SysPktContinueCmdType *SysPktContinueCmdPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktGetBreakPointsCmd
+//
+// - Get breakpoints
+//--------------------------------------------------------------------
+typedef struct SysPktGetBreakpointsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktGetBreakpointsCmdType;
+typedef SysPktGetBreakpointsCmdType* SysPktGetBreakpointsCmdPtr;
+
+typedef struct SysPktGetBreakpointsRspType {
+ _sysPktBodyCommon; // Common Body header
+ //BreakpointType bp[dbgTotalBreakpoints];
+ } SysPktGetBreakpointsRspType;
+typedef SysPktGetBreakpointsRspType* SysPktGetBreakpointsRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktSetBreakPointsCmd
+//
+// - Set breakpoints
+//--------------------------------------------------------------------
+typedef struct SysPktSetBreakpointsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ //BreakpointType bp[dbgTotalBreakpoints];
+ } SysPktSetBreakpointsCmdType;
+typedef SysPktSetBreakpointsCmdType* SysPktSetBreakpointsCmdPtr;
+
+typedef struct SysPktSetBreakpointsRspType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktSetBreakpointsRspType;
+typedef SysPktSetBreakpointsRspType* SysPktSetBreakpointsRspPtr;
+
+
+
+
+//--------------------------------------------------------------------
+// sysPktDbgBreakToggleCmd
+// - Enable/Disable DbgBreak's command
+//--------------------------------------------------------------------
+typedef struct SysPktDbgBreakToggleCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktDbgBreakToggleCmdType;
+typedef SysPktDbgBreakToggleCmdType* SysPktDbgBreakToggleCmdPtr;
+
+typedef struct SysPktDbgBreakToggleRspType {
+ _sysPktBodyCommon; // Common Body header
+ Boolean newState;
+ UInt8 reserved;
+ } SysPktDbgBreakToggleRspType;
+typedef SysPktDbgBreakToggleRspType* SysPktDbgBreakToggleRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktFlashCmd - OBSOLETE AS OF 3.0! SEE sysPktExecFlashCmd BELOW!
+// Program Flash command - programs one sector of the FLASH ram
+// If numBytes is 0, this routine returns info on the flash in:
+// manuf - manufacturer code
+// device - device code
+// width - width of FLASH
+// ramSpaceP - buffer in RAM for flash sector
+//--------------------------------------------------------------------
+typedef struct SysPktFlashWriteType {
+ _sysPktBodyCommon; // Common Body header
+ UInt16 numBytes; // -> # of bytes in sector
+ UInt32 flashBase; // -> base address of FLASH, or 0 for default
+ UInt32 srcAddr; // -> source address of new data
+ UInt32 dstAddr; // -> dest address in flash memory
+ UInt8 manuf; // <- manufacturer
+ UInt8 device; // <- device
+ UInt8 width; // <- Flash memory width
+ UInt8 filler;
+ UInt32 ramSpaceP; // <- available space in RAM for sector
+ } SysPktFlashWriteType;
+typedef SysPktFlashWriteType *SysPktFlashWritePtr;
+
+
+//--------------------------------------------------------------------
+// sysPktExecFlashCmd
+// NEW Program Flash command - executes flash ident/write code
+// If codeAddr is 0, this routine returns address to write flash code.
+// Replaces 1.0 and 2.0 sysPktFlashCmd call above in the 3.0 ROM
+//--------------------------------------------------------------------
+typedef struct sysPktExecFlashType {
+ _sysPktBodyCommon; // Common Body header
+ UInt16 numBytes; // -> # of bytes in sector
+ UInt32 flashBase; // -> base address of FLASH
+ UInt32 srcAddr; // -> source address of new data
+ UInt32 dstAddr; // -> dest address in flash memory
+ UInt32 codeAddr; // <-> address of flash code
+ UInt16 flashResID; // <- resource ID of flash write code
+ UInt8 manuf; // <- manufacturer
+ UInt8 device; // <- device
+ UInt8 devInfo; // <- device info
+ UInt8 remoteCmd; // -> remote command (e.g.: flash/erase/both)
+ UInt8 response; // <- response from flash/ident code
+ UInt8 spareByte; // <-> filler (byte for word alignment)
+ UInt32 spareDWord; // <-> spare
+ } sysPktExecFlashType;
+typedef sysPktExecFlashType *sysPktExecFlashPtr;
+
+// remoteCmd values sent to flash code:
+#define remoteCmdErase 0x01 // tells flash code to erase block(s)
+#define remoteCmdFlash 0x02 // tells flash code to flash block(s)
+#define remoteCmdROMSig 0x04 // tells flash code to write ROM signature
+#define remoteCmdUnlocked 0x08 // tells flash code to check block lock status
+
+// response values returned by flash write/identify code:
+#define respNoErr 0 // no error
+#define respNoFlashBase 1 // flashBase not specified
+#define respIdentFailed 2 // can't identify flash part
+#define respNoBytes 3 // numBytes not specified
+#define respPartialBlock 4 // numBytes not multiple of flash sub-block size
+#define respTooManyBytes 5 // numBytes too high
+#define respEraseFailed 6 // erase command failed
+#define respNotErased 7 // erase verification failed
+#define respFlashFailed 8 // flash command failed
+#define respInvalidFlashDeviceID 9 // unrecognized device code
+#define respBlockLocked 10 // block is locked
+#define respBadCommand 11 // remoteCmd not supported
+
+//--------------------------------------------------------------------
+// sysPktGetTrapBreaksCmd
+//
+// - Get Trap Breaks
+//--------------------------------------------------------------------
+typedef struct SysPktGetTrapBreaksCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktGetTrapBreaksCmdType;
+typedef SysPktGetTrapBreaksCmdType* SysPktGetTrapBreaksCmdPtr;
+
+typedef struct SysPktGetTrapBreaksRspType {
+ _sysPktBodyCommon; // Common Body header
+ //UInt16 trapBP[dbgTotalTrapBreaks];
+ } SysPktGetTrapBreaksRspType;
+typedef SysPktGetTrapBreaksRspType* SysPktGetTrapBreaksRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktSetTrapBreaksCmd
+//
+// - Set Trap Breaks
+//--------------------------------------------------------------------
+typedef struct SysPktSetTrapBreaksCmdType {
+ _sysPktBodyCommon; // Common Body header
+ //UInt16 trapBP[dbgTotalTrapBreaks];
+ } SysPktSetTrapBreaksCmdType;
+typedef SysPktSetTrapBreaksCmdType* SysPktSetTrapBreaksCmdPtr;
+
+typedef struct SysPktSetTrapBreaksRspType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktSetTrapBreaksRspType;
+typedef SysPktSetTrapBreaksRspType* SysPktSetTrapBreaksRspPtr;
+
+
+
+//--------------------------------------------------------------------
+// sysPktGetTrapConditionsCmd
+//
+// Get Trap Conditionals. These are used to tell the debugger
+// to conditionally break on a trap depending on the value of the
+// first word on the stack. They are used when setting a-traps on
+// library calls. This is a 3.0 feature.
+//--------------------------------------------------------------------
+typedef struct SysPktGetTrapConditionsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktGetTrapConditionsCmdType;
+typedef SysPktGetTrapConditionsCmdType* SysPktGetTrapConditionsCmdPtr;
+
+typedef struct SysPktGetTrapConditionsRspType {
+ _sysPktBodyCommon; // Common Body header
+ //UInt16 trapParam[dbgTotalTrapBreaks];
+ } SysPktGetTrapConditionsRspType;
+typedef SysPktGetTrapConditionsRspType* SysPktGetTrapConditionsRspPtr;
+
+
+//--------------------------------------------------------------------
+// sysPktSetTrapConditionsCmd
+//
+// Set Trap Conditionals. These are used to tell the debugger
+// to conditionally break on a trap depending on the value of the
+// first word on the stack. They are used when setting a-traps on
+// library calls. This is a 3.0 feature.
+//--------------------------------------------------------------------
+typedef struct SysPktSetTrapConditionsCmdType {
+ _sysPktBodyCommon; // Common Body header
+ //UInt16 trapParam[dbgTotalTrapBreaks];
+ } SysPktSetTrapConditionsCmdType;
+typedef SysPktSetTrapConditionsCmdType* SysPktSetTrapConditionsCmdPtr;
+
+typedef struct SysPktSetTrapConditionsRspType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktSetTrapConditionsRspType;
+typedef SysPktSetTrapConditionsRspType* SysPktSetTrapConditionsRspPtr;
+
+
+
+
+
+// The following indicates how much space in debugger globals we've reserved for
+// the SerialLibrary globals for the Debugger. Reserve 8 extra bytes for
+// patching.
+//
+// ADH 12/21/99 Increased to 64 to allow for buffering space to be added
+// to the serial debug globals.
+#define dbgSerRsvGlobalsSize 64
+
+
+
+/***********************************************************************
+ * Stucture of Debugger Globals
+ ***********************************************************************/
+struct DbgGlobalsType {
+ // Saved registers
+ M68KRegsType reg;
+
+ // Breakpoints and saved opcodes behind each one
+ Boolean romBP;
+ Boolean stepOverBP; // true if single-stepping over a BP
+ BreakpointType bp[dbgTotalBreakpoints];
+ UInt16 bpOpcode[dbgTotalBreakpoints];
+
+ // Current trap breaks
+ UInt16 trapBreak[dbgTotalTrapBreaks];
+ UInt16 trapParam[dbgTotalTrapBreaks];
+ UInt32 oldDispatcher; // saved trap dispatcher
+ Boolean breakingOnATrap; // set by debugger trap dispatcher
+
+ // Mode settings
+ Boolean ignoreDbgBreaks; // if true, ignore DbgBreak's
+ Boolean commOpened; // if true, comm library and socket have been
+ // opened.
+
+ // Step spy support
+ Boolean stepSpy; // true if step spying.
+ UInt32 ssAddr; // address to step spy on
+ UInt32 ssValue; // saved value
+
+ // Exception type
+ UInt16 excType; // why we entered debugger
+ UInt8 reEntered; // true if we re-entered
+ UInt8 firstEntrance; // true first time we enter debugger
+
+ // Debugger Serial Library globals
+ UInt8 serGlobals[dbgSerRsvGlobalsSize]; // Debugger Serial globals
+
+ // Saved bus error exception info
+ UInt32 busErrStack[2]; // first 2 long words of bus error stack frame
+
+ // Debugger Stack
+ UInt8 stack[dbgStackSize]; // Debugger stack
+ UInt16 stackEnd; // End of stack
+
+ };
+
+typedef struct DbgGlobalsType DbgGlobalsType;
+
+typedef DbgGlobalsType* DbgGlobalsPtr;
+
+
+
+#endif // __DEBUGMGR_H__
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/Globals.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/Globals.h
new file mode 100644
index 0000000..e45c95c
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/Globals.h
@@ -0,0 +1,574 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Globals.h
+ *
+ * Description:
+ * Structure definition of Pilot globals
+ *
+ * History:
+ * 10/26/94 RM Created by Ron Marianetti
+ * 4/13/95 VMK Added Sound Manager globals
+ * 8/15/97 vmk Reused padGlobalsP for sndOffTicks
+ * 1/18/98 scl Removed lastActionCodeAppInfoP, added irq globals.
+ * 3/13/98 srj Added new battery subsystem
+ * 6/22/98 srj Added new global for software shutdown
+ * 8/17/98 SCL Synchronized globals between Sumo/Eleven
+ * 8/26/98 kwk Deleted unused FEP globals pointer.
+ * 8/28/98 SCL Synchronized globals between Sumo/Eleven
+ * 9/15/98 jfs Added two new UInt32 globals exclusively for OEM use
+ * 10/28/98 SCL Synchronized globals between Sumo/Eleven
+ * 04/05/99 jrb Added UInt16 for Jerry PLD shadow register.
+ * 04/13/99 jhl Added RadioMgr globals pointer
+ * 07/12/99 kwk Added fatal alert template ptr/btn width.
+ * 07/14/99 kwk Added silkscreen info pointer.
+ * 10/29/99 SCL REMOVED dbgHalDispatchP since it was never released.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+#include <M68KHwr.h>
+
+// The following indicates how much space in low memory we've reserved for
+// the UI globals. The UI initialization code makes sure that we don't
+// overrun this space by comparing the size of the structure UIGlobalsType
+// with this constant.
+
+// Changing this will cause globals after uiGlobals to move including flpSoftFPSCR.
+// See note below regarding flpSoftFPSCR and __SoftFPSCR__ in mc68ksfpe.s.
+#define sysUIRsvGlobalsSize 0xB0
+
+
+
+/************************************************************
+ * Structure of Fixed System Globals
+ *************************************************************/
+typedef struct FixedGlobalsType {
+
+ // Memory Manager Globals
+ UInt8 memCardSlots; // number of memory card slots
+ UInt8 dbgWasEntered; // set true the first time debugger is entered
+ void * memCardInfoP; // pointer to array of CardInfoTypes stored
+ UInt32 memSemaphoreID; // Memory Manager semaphore
+ UInt16 memDebugMode; // Current debug mode of Memory Manager
+
+ // Data Manager Globals
+ void * dmOpenList; // Linked list of open databases (DmOpenInfoPtr)
+
+ // Debugger/System Shared globals
+ UInt8 dbgInDebugger; // true if in debugger
+ UInt8 dbgTracing; // tracing in debugger
+ void * dbgGlobalsP; // pointer to dbgGlobals
+ void * dbgSerGlobalsP; // pointer to Debugger Serial globals
+
+
+ // System Manager Globals
+ void * sysAppInfoP; // pointer to SysAppInfoType for system
+ void * sysKernelDataP; // pointer to Kernel data
+ void ** sysDispatchTableP; // pointer to dispatch table
+ UInt32 sysOwnerIDsInUse; // 1 bit for each owner ID in use
+ void * sysAMXAppInfoP; // SysAppInfoType for AMX app.
+ UInt32 sysClockFreq; // processor clock frequency
+ UInt32 * sysHardKeyCreators; // ptr to array of App Creator types
+
+ Int16 sysBatteryCheckTimer; // # of ticks left before we check battery again
+ UInt8 sysBatteryMinThreshold; // System will shut down if battery falls below this
+ UInt8 hwrBatteryLevel; // current battery level
+ Int16 sysNextBatteryAlertTimer; // # of ticks till next battery warning (OBSOLETE, See Below)
+ UInt8 sysBatteryWarnThreshold; // If battery below this level, post low battery keyboard event
+
+ UInt8 sysDispatchTableRev; // incremented every time a trap is patched. Used
+ // by host debugger to invalidate it's cache.
+ UInt16 sysDispatchTableSize; // # of entries in dispatch table
+ void * sysLibTableP; // (SysLibTblEntryPtr) pointer to Library entries
+ UInt16 sysLibTableEntries; // size of library table
+ void * sysConsoleStackChunkP; // pointer to console task stack chunk
+ void * sysUIShellAppInfoP; // AppInfoPtr for UIAppShell
+
+ UInt32 sysTimerID; // TimerID of timer used for periodic system stuff
+ UInt32 sysAutoOffEvtTicks; // Ticks of last event - used to support auto-off
+ UInt16 sysAutoOffSeconds; // Auto-sleep timeout in seconds.
+
+ Int32 sysRandomSeed; // Random # seed
+
+
+
+ // Other Manager's globals
+ void * slkGlobalsP; // pointer to serial link globals
+ void * serGlobalsP; // pointer to serial manager globals
+ void * scrGlobalsP; // pointer to screen driver globals
+ void * fplGlobalsP; // pointer to Floating Point Library globals
+ void * penGlobalsP; // Pen manager globals ptr
+ void * sysEvtMgrGlobalsP; // System Event Manager Globals
+ void * sndGlobalsP; // Sound Manager globals
+ void * timGlobalsP; // Time Manager globals
+ void * almGlobalsP; // Alarm Manager globals
+ void * ftrGlobalsP; // pointer to feature manager globals
+ void * grfGlobalsP; // pointer to Graffiti globals
+ void * keyGlobalsP; // Key manager globals
+
+ // UI Globals
+ UInt8 uiGlobals[sysUIRsvGlobalsSize]; // Basic UI Globals
+ void * uiExtensionsP; // for future use...
+
+
+ // Globals used by UIAppShell in order to manage the launching of UI Apps.
+#if EMULATION_LEVEL != EMULATION_NONE
+ void * curUIAppInfoP; // SysAppInfoPtr of current UI App or
+ // last action code
+#else
+ void * unusedPtr;
+#endif
+
+ UInt32 nextUIAppDBID; // Database LocalID of next UI App to launch
+ UInt16 nextUIAppCmd; // Cmd for next UI App
+ void * nextUIAppCmdPBP; // Cmd ParamBlock Pointer for next UI App
+ UInt8 nextUIAppCardNo; // Card number of next UI App to launch
+
+
+ // Hardware Manager Globals
+ Int8 memDataWELevel; // if > 0, Data area is write enabled
+ UInt16 hwrWakeUp; // Bit mask of which peripherals need to be
+ // enabled when system wakes
+ UInt8 hwrCPUDutyCycle; // Desired Duty cycle of CPU in 31ths.
+ UInt8 hwrPenDown; // last state of pen-down (zero = up
+ // non-zero = down, number of ticks 'till next sample)
+ UInt32 hwrCurTicks; // Current hardware tickCount -
+ // maintained separately from AMX ticks for performance reasons.
+ UInt32 hwrTotalRAMSize; // total RAM Size, used by HwrMemWritable
+ UInt32 hwrDozeSubTicks; // # of subTicks we've dozed for since reset
+ // a sub-tick is 1/4096 seconds.
+
+ // Sound Manager "sound off" ticks
+ // WAS: Pad server globals pointer
+ // WAS: void * padGlobalsP; // PAD Server globals
+ UInt32 sndOffTicks; // # of ticks til disabling the PWM (0 = do nothing)
+
+ // New System globals
+ UInt8 sysResetFlags; // Reset flags sysResetFlagXXXX
+ UInt8 sysBatteryKind; // SysBatteryKind enumerated type
+
+ // New Memory Manager global for recording minimum heap free - used for debugging only
+ UInt32 memMinDynHeapFree; // Minimum free space in dynamic heap
+
+
+ // System Preferences flags
+ UInt16 sysPrefFlags; // System Pref flags: sysPrefFlagXXXX
+
+
+ // This is a pointer to the System Manager variable size globals
+ void * sysGlobalsP; // pointer to System Globals
+
+ // Miscellaneous System flags
+ UInt16 sysMiscFlags; // System Misc flags: sysMiscFlagXXX
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 2.0 release...
+ //-----------------------------------------------------------------------
+ UInt16 sysLibNet; // refnum of TCP/IP library
+ void * netPktFreeQ; // global needed by Net Library
+
+
+ // EventGroupID used by the System Event Manager for blocking on user input
+ // and by the Net Library for implementing NetLibSelect()
+ UInt32 sysEvGroupID; // AMX EventGroup ID.
+
+
+ void * irq3GlobalsP; // IRQ3 handler globals
+
+ // Tick count last time we displayed a low battery warning. This is used by
+ // the system timer procedure in AMXHardwareTD1.c to insure that it doesn't
+ // display low battery warnings more than once/minute.
+ UInt32 sysLastBatteryWarning; // tickcount of last warning.
+
+ // Checksum of exception vector area of low memory. Used when ROM built for full
+ // error checking to make sure no apps overwrite low memory by using null pointers.
+ UInt32 sysLowMemChecksum; // checksum of low memory.
+
+ // Hardware rev. This is determined during bootup time. The first shipping rev
+ // is 1.
+ UInt16 hwrHardwareRev; // hardware rev.
+
+
+ // MemHandle to list of protected databases
+ MemHandle dmProtectListH; // handle to array of protected
+ // databases (DmProtectEntryType)
+ // Miscellaneous hardware flags
+ UInt16 hwrMiscFlags; // Hardware Misc Flags: hwrMiscFlagXXX
+
+ // Support for profiling
+ UInt32 sysProfileRefcon; // Refcon value for profiler function
+ void * sysProfileProcP; // Profiler procedure, called if non-zero
+ // during tick interrupt (100/sec).
+
+ // NewFloatMgr's MWSFPE (MetroWerks Software Floating Point Emulator)
+ // needs a global to keep track of its status and control.
+ // This global (__SoftFPSCR__) is referenced by the 68K code located at
+ // :Libraries:NewFloatMgr:mc68ksfpe.s
+ UInt32 flpSoftFPSCR;
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 3.0 release...
+ //-----------------------------------------------------------------------
+ void * irLibGlobalsP; // Ir Library globals pointer
+ UInt16 exgActiveLib; // active Exchange library
+
+ UInt16 uiBusyCount; // UI busy counter
+
+ void * irq1GlobalsP; // IRQ1 handler globals
+ void * irq2GlobalsP; // IRQ2 handler globals
+ void * irq6GlobalsP; // IRQ6 handler globals
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 3.1 release...
+ //-----------------------------------------------------------------------
+
+ // Globals for Language support.
+ void * intlMgrGlobalsP; // Int16'l Manager globals
+
+ // Globals for Field inline Text Services
+ UInt16 inlineStart; // Starting position of the inline text
+ UInt16 inlineEnd; // Ending position of the inline text
+ Boolean inlineActive; // True if inline text support is active.
+ UInt8 inlineDefTerm; // True if deferred termination
+ // (inlineDefChecksum/inlineDefField are valid)
+ void * tsmFepLibStatusP; // Pointer to FEP status record.
+ UInt16 tsmFepLibRefNum; // Text Services Library Reference number
+ UInt16 inlineHighlightLen; // Length of highlighted inline text
+
+ // <chg 3/13/98 srj> Added for the battery subsystem
+ void * sysBatteryDataP; // pointer to current battery data
+ void * sysBatteryValidKindsP; // pointer to list of valid batteries
+
+ // <chg 6/22/98 srj> Added for the battery subsystem
+ Boolean sysInShutdown; // True: We are in lockout (Sumo)
+ UInt8 sysMinWakeupThreshold; // System can wake up once we're over this voltage
+
+ // <chg 7/8/98 srj> More miscellaneous hardware flags
+ UInt32 hwrMiscFlagsExt; // Hardware Misc Flags: hwrMiscFlagExtXXX
+
+ // <chg 8/15/98 srj> Added to provide critical warning timer
+ Boolean sysUseCritWarnTimer;
+ Boolean sysCritWarnTimerRunning;
+ Int16 sysCritWarnRTCDayStarted;
+ Int32 sysCritWarnTickTimer;
+ UInt32 sysCritWarnLastTick;
+ Boolean sysCharging;
+ Boolean sysUpdateVoltageLevel;
+
+ // Notification Manager globals:
+ MemHandle notifyGlobalsH; // handle to NotifyMgr globals
+
+ // Some globals reserved for future use (only available in 3.1 or later):
+ UInt32 sysReserved31DWord1;
+ UInt32 sysReserved31DWord2;
+ UInt32 sysReserved31DWord3;
+ UInt32 sysReserved31DWord4;
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 3.2 release...
+ //-----------------------------------------------------------------------
+
+ // <chg 1-28-98 RM> Added for the RAM Mobitex Network Interface
+ void * ramGlobalsP; // For Jerry radio
+
+ // <chg 4-1-98 RM> New global for the HwrBattery() call
+ void * hwrBatteryGlobalsP; // used to hold charging state, etc.
+
+ // <chg 7-10-98 JB> New global for Battery Percent
+ UInt8 hwrBatteryPercent;
+
+ // <chg 10/9/98 SOE> New global with flags indicating various types of background communications activity
+ // Used to hold off form alerts and other activities (beaming) that might screw up comm transfers
+ UInt8 commActivityFlags;
+
+ // For the new serial mgr, the 328 serial plugin needs its own global space
+ // since there is no global for the irq4 line.
+ void * uart328GlobalsP;
+
+
+ // 9/15/98 jfs New Globals added for Licensees, Partners, OEMs, etc.
+ UInt32 sysOEMGlobal1; // 4 bytes for OEM use only!
+ UInt32 sysOEMGlobal2; // 4 bytes for OEM use only!
+
+ // soe added 10/11/98 - many routines think this is constant across platforms
+ // but it was 78 on old pilots (3.3v reference) and is now 85 (3.0v reference on new pilots)
+ // The #defines in hardware.h are now specific by reference
+ UInt16 hwrBatteryStepsPerVolt;
+
+ // <chg 11/19/98 TLW> New global to maintain a list of appInfo blocks
+ // that reference the stack used by a task so both the appInfo block
+ // and the stack can be deleted after task termination is complete.
+ // The stack can't be deleted before terminating the task because the
+ // task delete call is using the stack. The appInfo block is deleted
+ // later because already has a taskId reference and a pointer to the stack.
+ void * sysPendingStackFrees;
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 3.3 release...
+ //-----------------------------------------------------------------------
+
+ // jed 1/18-99 Software day counter for the time-based critical warnings
+ UInt16 sysDayCounter;
+
+ // jed 1/15/99 New Global added during the Sumo merge
+ // jfs 4/26/99 Changed from unsigned to signed Int16
+ Int16 sysBatteryCheckPeriod;
+
+ // jrb 4/5/99 Shadow register for Jerry EZ PLD
+ UInt16 hwrJerryPldShadow;
+
+ // jhl 4/13/99 RadioMgr globals pointer
+ void * radioGlobalsP;
+
+
+ //-----------------------------------------------------------------------
+ // New Globals added for the 3.5 release...
+ //-----------------------------------------------------------------------
+
+ // kwk 07/12/99 Info used by SysFatalAlert to display localizable alert.
+ void * fatalAlertTemplateP;
+ UInt16 fatalAlertBtnWidth;
+
+ // kwk 07/14/99 Ptr to silkscreen/button list information.
+ void * silkscreenInfoP;
+
+ // kwk 08/04/99 Deferred inline termination globals.
+ UInt16 inlineDefChecksum;
+ void * inlineDefField;
+
+ // Are there any pending deferred broadcasts for the NotifyMgr to handle?
+ Boolean notifyBroadcastPending;
+
+ UInt8 sysReserved35Byte1;
+
+ // SCL 10/29/99 Globals in which to store OEM/Device/HAL identification info.
+ UInt32 hwrOEMCompanyID;
+ UInt32 hwrOEMDeviceID;
+ UInt32 hwrOEMHALID;
+
+ // mchen 11/11/99 Global used by system update patches.
+ void * sysUpdateGlobalsP;
+
+ // SCL 11/15/99 Global used to identify which SmallROM booted the OS.
+ UInt16 smallROMChecksum;
+
+ //-----------------------------------------------------------------------
+ // Put New globals here...
+ //-----------------------------------------------------------------------
+ // type newGlobal;
+
+ } FixedGlobalsType;
+
+
+/************************************************************
+ * This structure defines the start of the Low Memory Area.
+ * The complete structure of LowMemory is defined in SystemPrv.h
+ * and includes this low memory header followed by some variable
+ * size globals that may change from rev to rev of the System Software.
+ *
+ * When emulating under Windows, this structure ends up at some random
+ * place in memory and the global variable GlobalsP points to it.
+ *
+ * When running in the native environment, this structure starts at
+ * address sysGlobalsOffset.
+ *
+ * In order to simplify the source code, macros are defined for
+ * accessing commonly used globals in the optimim manner for
+ * each environment.
+ *************************************************************/
+typedef struct LowMemHdrType {
+ //---------------------------------------------------------------------------
+ // Processor exception table
+ //---------------------------------------------------------------------------
+ M68KExcTableType vectors; // Exception vectors,
+ // or Card header for RAM only cards
+
+ //---------------------------------------------------------------------------
+ // System Globals
+ //---------------------------------------------------------------------------
+ FixedGlobalsType globals; // System Globals
+
+ } LowMemHdrType;
+
+
+
+#if EMULATION_LEVEL == EMULATION_NONE
+ #define PilotGlobalsP 0
+#else
+ #ifdef __cplusplus
+ extern "C" void *PilotGlobalsP; // pointer to start of Memory card 0
+ #else
+ extern void *PilotGlobalsP; // pointer to start of Memory card 0
+ #endif
+#endif
+
+
+
+
+
+/************************************************************
+ * Macros for accessing globals.
+ * When emulating, the globals are allocated in a memory chunk and our
+ * global variable Card0P points to this chunk.
+ * In native mode, Card0P is defined to be 0 at all times.
+ *************************************************************/
+#define GMemCardSlots (((LowMemHdrType*)PilotGlobalsP)->globals.memCardSlots)
+#define GMemCardInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.memCardInfoP)
+#define GMemSemaphoreID (((LowMemHdrType*)PilotGlobalsP)->globals.memSemaphoreID)
+#define GMemDebugMode (((LowMemHdrType*)PilotGlobalsP)->globals.memDebugMode)
+#define GMemMinDynHeapFree (((LowMemHdrType*)PilotGlobalsP)->globals.memMinDynHeapFree)
+
+#define GDmOpenList (((LowMemHdrType*)PilotGlobalsP)->globals.dmOpenList)
+#define GDmProtectListH (((LowMemHdrType*)PilotGlobalsP)->globals.dmProtectListH)
+
+#define GDbgWasEntered (((LowMemHdrType*)PilotGlobalsP)->globals.dbgWasEntered)
+#define GDbgInDebugger (((LowMemHdrType*)PilotGlobalsP)->globals.dbgInDebugger)
+#define GDbgTracing (((LowMemHdrType*)PilotGlobalsP)->globals.dbgTracing)
+#define GDbgGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.dbgGlobalsP)
+
+#define GSysAppInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.sysAppInfoP)
+#define GSysKernelDataP (((LowMemHdrType*)PilotGlobalsP)->globals.sysKernelDataP)
+#define GSysDispatchTableP (((LowMemHdrType*)PilotGlobalsP)->globals.sysDispatchTableP)
+#define GSysDispatchTableSize (((LowMemHdrType*)PilotGlobalsP)->globals.sysDispatchTableSize)
+#define GSysDispatchTableRev (((LowMemHdrType*)PilotGlobalsP)->globals.sysDispatchTableRev)
+#define GSysOwnerIDsInUse (((LowMemHdrType*)PilotGlobalsP)->globals.sysOwnerIDsInUse)
+#define GSysAMXAppInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.sysAMXAppInfoP)
+#define GSysClockFreq (((LowMemHdrType*)PilotGlobalsP)->globals.sysClockFreq)
+#define GSysHardKeyCreators (((LowMemHdrType*)PilotGlobalsP)->globals.sysHardKeyCreators)
+#define GSysNextBatteryAlertTimer (((LowMemHdrType*)PilotGlobalsP)->globals.sysNextBatteryAlertTimer)
+#define GSysBatteryCheckTimer (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryCheckTimer)
+#define GSysBatteryWarnThreshold (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryWarnThreshold)
+#define GHwrBatteryLevel (((LowMemHdrType*)PilotGlobalsP)->globals.hwrBatteryLevel)
+#define GSysBatteryMinThreshold (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryMinThreshold)
+#define GSysBatteryKind (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryKind)
+#define GSysConsoleStackChunkP (((LowMemHdrType*)PilotGlobalsP)->globals.sysConsoleStackChunkP)
+#define GSysUIShellAppInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.sysUIShellAppInfoP)
+#define GSysTimerID (((LowMemHdrType*)PilotGlobalsP)->globals.sysTimerID)
+#define GSysAutoOffEvtTicks (((LowMemHdrType*)PilotGlobalsP)->globals.sysAutoOffEvtTicks)
+#define GSysAutoOffSeconds (((LowMemHdrType*)PilotGlobalsP)->globals.sysAutoOffSeconds)
+#define GSysRandomSeed (((LowMemHdrType*)PilotGlobalsP)->globals.sysRandomSeed)
+#define GSysResetFlags (((LowMemHdrType*)PilotGlobalsP)->globals.sysResetFlags)
+#define GSysPrefFlags (((LowMemHdrType*)PilotGlobalsP)->globals.sysPrefFlags)
+#define GSysMiscFlags (((LowMemHdrType*)PilotGlobalsP)->globals.sysMiscFlags)
+#define GSysGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.sysGlobalsP)
+#define GSysLibNet (((LowMemHdrType*)PilotGlobalsP)->globals.sysLibNet)
+#define GSysEvGroupID (((LowMemHdrType*)PilotGlobalsP)->globals.sysEvGroupID)
+#define GSysLastBatteryWarning (((LowMemHdrType*)PilotGlobalsP)->globals.sysLastBatteryWarning)
+#define GSysLowMemChecksum (((LowMemHdrType*)PilotGlobalsP)->globals.sysLowMemChecksum)
+#define GSysProfileRefcon (((LowMemHdrType*)PilotGlobalsP)->globals.sysProfileRefcon)
+#define GSysProfileProcP (((LowMemHdrType*)PilotGlobalsP)->globals.sysProfileProcP)
+
+#define GNetPktFreeQ (((LowMemHdrType*)PilotGlobalsP)->globals.netPktFreeQ)
+
+#define GMemDataWELevel (((LowMemHdrType*)PilotGlobalsP)->globals.memDataWELevel)
+
+#define GSlkGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.slkGlobalsP)
+#define GSerGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.serGlobalsP)
+#define GSer681GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irq3GlobalsP)
+#define GScrGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.scrGlobalsP)
+#define GFplGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.fplGlobalsP)
+#define GPenGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.penGlobalsP)
+#define GSysEvtMgrGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.sysEvtMgrGlobalsP)
+#define GSndGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.sndGlobalsP)
+#define GTimGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.timGlobalsP)
+#define GAlmGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.almGlobalsP)
+#define GFtrGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.ftrGlobalsP)
+#define GGrfGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.grfGlobalsP)
+#define GKeyGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.keyGlobalsP)
+//#define GPADGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.padGlobalsP) // not used vmk 8/15/97
+
+#define GSndOffTicks (((LowMemHdrType*)PilotGlobalsP)->globals.sndOffTicks)
+
+#define GUIGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.uiGlobals)
+
+#define GNextUIAppDBID (((LowMemHdrType*)PilotGlobalsP)->globals.nextUIAppDBID)
+#define GNextUIAppCardNo (((LowMemHdrType*)PilotGlobalsP)->globals.nextUIAppCardNo)
+#define GNextUIAppCmd (((LowMemHdrType*)PilotGlobalsP)->globals.nextUIAppCmd)
+#define GNextUIAppCmdPBP (((LowMemHdrType*)PilotGlobalsP)->globals.nextUIAppCmdPBP)
+
+#if EMULATION_LEVEL != EMULATION_NONE
+#define GCurUIAppInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.curUIAppInfoP)
+#endif
+
+#define GSysLibTableP (((LowMemHdrType*)PilotGlobalsP)->globals.sysLibTableP)
+#define GSysLibTableEntries (((LowMemHdrType*)PilotGlobalsP)->globals.sysLibTableEntries)
+#define GDbgSerGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.dbgSerGlobalsP)
+
+#define GIrLibGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irLibGlobalsP)
+#define GExgActiveLib (((LowMemHdrType*)PilotGlobalsP)->globals.exgActiveLib)
+#define GSysUIBusyCount (((LowMemHdrType*)PilotGlobalsP)->globals.uiBusyCount)
+
+#define GIrq1GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irq1GlobalsP)
+#define GIrq2GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irq2GlobalsP)
+#define GIrq3GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irq3GlobalsP)
+#define GIrq6GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.irq6GlobalsP)
+#define GUart328GlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.uart328GlobalsP)
+#define GSysOEMGlobal1 (((LowMemHdrType*)PilotGlobalsP)->globals.sysOEMGlobal1)
+#define GSysOEMGlobal2 (((LowMemHdrType*)PilotGlobalsP)->globals.sysOEMGlobal2)
+
+#define GIntlMgrGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.intlMgrGlobalsP)
+
+#define GInlineStart (((LowMemHdrType*)PilotGlobalsP)->globals.inlineStart)
+#define GInlineEnd (((LowMemHdrType*)PilotGlobalsP)->globals.inlineEnd)
+#define GInlineActive (((LowMemHdrType*)PilotGlobalsP)->globals.inlineActive)
+#define GInlineDefTerm (((LowMemHdrType*)PilotGlobalsP)->globals.inlineDefTerm)
+#define GInlineHighlightLen (((LowMemHdrType*)PilotGlobalsP)->globals.inlineHighlightLen)
+#define GInlineDefChecksum (((LowMemHdrType*)PilotGlobalsP)->globals.inlineDefChecksum)
+#define GInlineDefField (((LowMemHdrType*)PilotGlobalsP)->globals.inlineDefField)
+#define GTsmFepLibStatusP (((LowMemHdrType*)PilotGlobalsP)->globals.tsmFepLibStatusP)
+#define GTsmFepLibRefNum (((LowMemHdrType*)PilotGlobalsP)->globals.tsmFepLibRefNum)
+
+#define GSysBatteryDataP (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryDataP)
+#define GSysBatteryValidKindsP (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryValidKindsP)
+#define GSysInShutdown (((LowMemHdrType*)PilotGlobalsP)->globals.sysInShutdown)
+#define GSysMinWakeupThreshold (((LowMemHdrType*)PilotGlobalsP)->globals.sysMinWakeupThreshold)
+
+#define GSysUseCritWarnTimer (((LowMemHdrType*)PilotGlobalsP)->globals.sysUseCritWarnTimer)
+#define GSysCritWarnTimerRunning (((LowMemHdrType*)PilotGlobalsP)->globals.sysCritWarnTimerRunning)
+#define GSysCritWarnRTCDayStarted (((LowMemHdrType*)PilotGlobalsP)->globals.sysCritWarnRTCDayStarted)
+#define GSysCritWarnTickTimer (((LowMemHdrType*)PilotGlobalsP)->globals.sysCritWarnTickTimer)
+#define GSysCritWarnLastTick (((LowMemHdrType*)PilotGlobalsP)->globals.sysCritWarnLastTick)
+#define GSysCharging (((LowMemHdrType*)PilotGlobalsP)->globals.sysCharging)
+#define GSysUpdateVoltageLevel (((LowMemHdrType*)PilotGlobalsP)->globals.sysUpdateVoltageLevel)
+
+#define GSysNotifyGlobalsH (((LowMemHdrType*)PilotGlobalsP)->globals.notifyGlobalsH)
+#define GSysNotifyBroadcastPending (((LowMemHdrType*)PilotGlobalsP)->globals.notifyBroadcastPending)
+
+#define GRAMGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.ramGlobalsP)
+#define GCommActivityFlags (((LowMemHdrType*)PilotGlobalsP)->globals.commActivityFlags)
+#define GSysPendingStackFrees (((LowMemHdrType*)PilotGlobalsP)->globals.sysPendingStackFrees)
+
+#define GSysBatteryCheckPeriod (((LowMemHdrType*)PilotGlobalsP)->globals.sysBatteryCheckPeriod)
+#define GSysDayCounter (((LowMemHdrType*)PilotGlobalsP)->globals.sysDayCounter)
+
+#define GSysJerryPldShadow (((LowMemHdrType*)PilotGlobalsP)->globals.hwrJerryPldShadow)
+
+#define GRadioGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.radioGlobalsP)
+
+#define GFatalAlertTemplateP (((LowMemHdrType*)PilotGlobalsP)->globals.fatalAlertTemplateP)
+#define GFatalAlertBtnWidth (((LowMemHdrType*)PilotGlobalsP)->globals.fatalAlertBtnWidth)
+
+#define GSilkscreenInfoP (((LowMemHdrType*)PilotGlobalsP)->globals.silkscreenInfoP)
+
+#define GHwrOEMCompanyID (((LowMemHdrType*)PilotGlobalsP)->globals.hwrOEMCompanyID)
+#define GHwrOEMDeviceID (((LowMemHdrType*)PilotGlobalsP)->globals.hwrOEMDeviceID)
+#define GHwrOEMHALID (((LowMemHdrType*)PilotGlobalsP)->globals.hwrOEMHALID)
+
+#define GSysUpdateGlobalsP (((LowMemHdrType*)PilotGlobalsP)->globals.sysUpdateGlobalsP)
+#define GSmallROMChecksum (((LowMemHdrType*)PilotGlobalsP)->globals.smallROMChecksum)
+
+#endif //__GLOBALS_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/MemoryPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/MemoryPrv.h
new file mode 100644
index 0000000..668a707
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/MemoryPrv.h
@@ -0,0 +1,603 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: MemoryPrv.h
+ *
+ * Description:
+ * Private includes for Memory Manager.
+ *
+ * History:
+ * 11/11/96 RM Re-written to allow heaps > 64K in size.
+ * 10/26/99 kwk Added memRomStoreNum & memRamStoreNum defines.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+
+// SystemPrv.h must be included before this header file. SystemPrv.h will
+// then in turn include this header.
+#ifndef __SYSTEMPRV_H__
+#include "SystemPrv.h"
+#endif
+
+#ifndef __MEMORYPRV_H__
+#define __MEMORYPRV_H__
+
+
+//#include <ErrorMgr.h>
+
+#include "PalmOptErrorCheckLevel.h"
+
+/************************************************************
+ * Private Flags accepted as parameter for MemNewChunk.
+ *************************************************************/
+#define memNewChunkFlagAllowLarge 0x1000 // allow >64K allocations
+
+
+/************************************************************
+ * Store numbers for MemStoreInfo.
+ *************************************************************/
+#define memRomStoreNum 0
+#define memRamStoreNum 1
+
+
+/********************************************************************
+ * Structure of a version 2 Master Pointer Table chunk.
+ * The first master pointer chunk is always immediately following the
+ * heap header. As more movable chunks are created, new master
+ * pointer chunks are allocated dynamically and linked together through
+ * the nextTblOffset field and prevTblOffset field.
+ ********************************************************************/
+typedef struct {
+ UInt16 numEntries; // number of master pointer entries
+ UInt32 nextTblOffset; // offset from start of heap to next table
+ //void * mstrP[numEntries]; // array of pointers to movable chunks
+ } MemMstrPtrTableType;
+typedef MemMstrPtrTableType* MemMstrPtrTablePtr;
+
+
+/********************************************************************
+ * Structure of a version 1 Master Pointer Table chunk.
+ * This is included for use by the Palm Debugger so that it can do
+ * heap dumps of devices that use the version 1 Memory Manager.
+ ********************************************************************/
+typedef struct {
+ UInt16 numEntries; // number of master pointer entries
+ UInt16 nextTblOffset; // offset from start of heap to next table
+ //void * mstrP[numEntries]; // array of pointers to movable chunks
+ } Mem1MstrPtrTableType;
+typedef Mem1MstrPtrTableType* Mem1MstrPtrTablePtr;
+
+
+
+/********************************************************************
+ * Structure of a version 2 Memory Manager Chunk Header.
+ ********************************************************************/
+#if CPU_ENDIAN == CPU_ENDIAN_BIG
+
+typedef struct {
+ UInt32 free :1; // set if free chunk
+ UInt32 moved :1; // used by MemHeapScramble
+ UInt32 unused2 :1; // unused
+ UInt32 unused3 :1; // unused
+ UInt32 sizeAdj :4; // size adjustment
+ UInt32 size :24; // actual size of chunk
+
+ UInt32 lockCount :4; // lock count
+ UInt32 owner :4; // owner ID
+ Int32 hOffset :24; // signed MemHandle offset/2
+ // used in free chunks to point to next free chunk
+ } MemChunkHeaderType;
+
+#else
+
+// Since this is an internal structure, I rearranged the fields.
+// There were two reasons: the size and hOffset fields are accessed
+// more efficiently (no shifting needed) and the flags macros still
+// return the flags as defined by the API (memChunkFlagsXXXX), without
+// requiring a lot of bit manipulation.
+// But, the size field needs to be in the first DWord because the
+// MemHeapTerminatorType is assumed to be in the same position as size.
+typedef struct {
+ UInt32 size :24; // actual size of chunk
+ UInt32 sizeAdj :4; // size adjustment
+ UInt32 unused3 :1; // unused
+ UInt32 unused2 :1; // unused
+ UInt32 moved :1; // used by MemHeapScramble
+ UInt32 free :1; // set if free chunk
+
+ Int32 hOffset :24; // signed MemHandle offset/2
+ // used in free chunks to point to next free chunk
+ UInt32 owner :4; // owner ID
+ UInt32 lockCount :4; // lock count
+ } MemChunkHeaderType;
+
+#endif
+
+typedef MemChunkHeaderType * MemChunkHeaderPtr;
+
+// The MemHeapTerminatorType is stored at the end of every heap and
+// is pointed to by the last real chunk in the heap
+typedef UInt32 MemHeapTerminatorType;
+
+// This macro is a quicker way of clearing a chunk header than
+// MemSet...
+#define memClearChunkHeader(p) { *((UInt32 *)p) = 0; *(((UInt32 *)p)+1) = 0;}
+
+// This macro is used to initialize a freeChunk header
+#define memInitFreeChunkHeader(p, size, hOffset) \
+ { *((UInt32*)p) = (0x80000000 | (size)); *(((UInt32*)p)+1) = (hOffset); }
+
+// This macro returns the data portion of a chunk given a pointer to the header
+#define memChunkData(chunkP) (void *)(((MemChunkHeaderPtr)(chunkP)) + 1)
+
+// This macro returns the memChunkHeader given a pointer to the start of the data
+#define memChunkHeader(dataP) (((MemChunkHeaderPtr)(dataP)) - 1)
+
+#if CPU_ENDIAN == CPU_ENDIAN_BIG
+
+// This macro is used to grab all the flags at once and place them into
+// a byte
+#define memChunkFlags(p) (*((UInt8 *)p) & 0xF0)
+
+// This macro is used to clear all the flags at once
+#define memChunkFlagsClear(p) ((*((UInt8 *)p)) &= 0x0F)
+
+#else
+
+// This macro is used to grab all the flags at once and place them into
+// a byte
+#define memChunkFlags(p) (*(((UInt8 *)p)+3) & 0xF0)
+
+// This macro is used to clear all the flags at once
+#define memChunkFlagsClear(p) (*(((UInt8 *)p)+3) &= 0x0F)
+
+#endif
+
+// When flags are returned by the API (by MemPtrFlags, etc.)
+#define memChunkFlagFree 0x80 // free bit
+#define memChunkFlagUnused1 0x40 // unused
+#define memChunkFlagUnused2 0x20 // unused
+#define memChunkFlagUnused3 0x10 // unused
+
+// A lockcount of memPtrLockCount means a permanently unmovable chunk
+#define memPtrLockCount 15
+
+// A ownerID of 15 is used for master pointer chunks
+#define memOwnerMasterPtrTbl 15
+
+
+// This equate returns the name of the ChunkHeaderType. This was created
+// so that we can change the name of the CHunkHeaderType (as we did for V2 of
+// the Memory Manager) and souce code won't know the difference
+#define memChunkHeaderTypeName MemChunkHeaderType
+
+
+/********************************************************************
+ * Structure of a version 1 Memory Manager Chunk Header.
+ * This is included for use by the Palm Debugger so that it can do
+ * heap dumps of devices that use the version 1 Memory Manager.
+ ********************************************************************/
+typedef struct {
+ UInt16 size; // size of block in bytes, including header
+ UInt8 lockOwner; // lock count in high nibble, owner in low
+ UInt8 flags; // flags, size adj in low nibble
+ Int16 hOffset; // offset/2 to MemHandle for movables
+ } Mem1ChunkHeaderType;
+typedef Mem1ChunkHeaderType* Mem1ChunkHeaderPtr;
+
+#define mem1ChunkFlagSizeAdj 0x0F // mask for size adjustment
+
+// A non-movable chunk has 0xF as the lock count
+#define mem1ChunkLockMask 0xF0
+#define mem1ChunkOwnerMask 0x0F
+
+
+/********************************************************************
+ * Structure of a Heap
+ *
+ * A heap starts with a HeapHeader
+ * Followed by the offset table (numHandles)
+ * Followed by movable chunks
+ * Followed by non-movable chunks
+ ********************************************************************/
+
+/********************************************************************
+ * Structure of a version 3 Memory Heap Header.
+ ********************************************************************/
+typedef struct {
+ UInt16 flags; // heap flags;
+ UInt32 size; // size of heap
+ UInt32 firstFreeChunkOffset;// offset/2 to first free chunk
+ MemMstrPtrTableType mstrPtrTbl; // Master pointer table
+ } MemHeapHeaderType;
+typedef MemHeapHeaderType * MemHeapHeaderPtr;
+
+
+// Flags Field
+#define memHeapFlagReadOnly 0x0001 // heap is read-only (ROM based)
+#define memHeapFlagVers2 0x8000 // version 2 heap (> 64K)
+#define memHeapFlagVers3 0x4000 // version 3 heap (has free list)
+#define memHeapFlagVers4 0x2000 // version 4 heap (has free master pointer table entry list)
+
+#define memMstrPtrTableGrowBy 50 // # of entries to grow master pointer tables by
+#define memMstrPtrTableInitSizeD 200 // # of entries to allocate initially for dynamic heap(s)
+#define memMstrPtrTableInitSizeS 200 // # of entries to allocate initially for storage heap(s)
+
+
+
+/********************************************************************
+ * Structure of a version 1 Memory Heap Header.
+ * This is included for use by the Palm Debugger so that it can do
+ * heap dumps of devices that use the version 1 Memory Manager.
+ ********************************************************************/
+typedef struct {
+ UInt16 flags; // heap flags;
+ UInt16 size; // size of heap - 0 means 64K;
+ Mem1MstrPtrTableType mstrPtrTbl; // Master pointer table
+ } Mem1HeapHeaderType;
+typedef Mem1HeapHeaderType * Mem1HeapHeaderPtr;
+
+
+/********************************************************************
+ * Structure of a version 2 Memory Heap Header.
+ * This is included for use by the Palm Debugger so that it can do
+ * heap dumps of devices that use the version 1 Memory Manager.
+ ********************************************************************/
+typedef struct {
+ UInt16 flags; // heap flags;
+ UInt32 size; // size of heap
+ MemMstrPtrTableType mstrPtrTbl; // Master pointer table
+ } Mem2HeapHeaderType;
+typedef Mem2HeapHeaderType * Mem2HeapHeaderPtr;
+
+
+/********************************************************************
+ * These macros pave the way for the version 2 Memory Manager that
+ * supports >64K chunks.
+ *
+ * They are a general way to get info out of a Chunk header and Heap header
+ * whether it be a version 1 or version 2 header. They are used almost
+ * exclusively by the Palm Debugger and Simulator Heap Dump utility
+ * since it must be able to do heap dumps of both versions of the Palm
+ * Memory Manager.
+ *
+ * The 'ver' parameter to these macros is either 1 for version 1 or
+ * 2 for version 2 and the 'p' parameter is the chunk header pointer.
+ ********************************************************************/
+// This structure is big enough to read in a version 1 or version 2
+// Master Pointer Table into
+typedef struct {
+ union {
+ MemMstrPtrTableType ver2;
+ Mem1MstrPtrTableType ver1;
+ } header;
+ } MemMstrPtrTableUnionType;
+
+#define memUSizeOfMstrPtrTable(ver) \
+ (ver>1 ? sizeof(MemMstrPtrTableType) : sizeof(Mem1MstrPtrTableType))
+
+#define memUMstrPtrTableNextTblOffset(p,ver) \
+ (ver>1 ? ((MemMstrPtrTablePtr)p)->nextTblOffset : ((Mem1MstrPtrTablePtr)p)->nextTblOffset)
+
+#define memUMstrPtrTableNumEntries(p,ver) \
+ (ver>1 ? ((MemMstrPtrTablePtr)p)->numEntries : ((Mem1MstrPtrTablePtr)p)->numEntries)
+
+
+// This structure is big enough to read in a version 1, version 2, or version 3
+// heap header into
+typedef struct {
+ union {
+ MemHeapHeaderType ver3;
+ Mem2HeapHeaderType ver2;
+ Mem1HeapHeaderType ver1;
+ } header;
+ } MemHeapHeaderUnionType;
+
+#define memUHeapVer(p) \
+ (memUHeapFlags((p)) & memHeapFlagVers4 ? 4 : \
+ (memUHeapFlags((p)) & memHeapFlagVers3 ? 3 : \
+ (memUHeapFlags((p)) & memHeapFlagVers2 ? 2 : 1)))
+
+#define memUSizeOfHeapHeader(ver) \
+ (ver>2 ? sizeof (MemHeapHeaderType) : (ver>1 ? sizeof(Mem2HeapHeaderType) : sizeof(Mem1HeapHeaderType)))
+
+#define memUHeapSize(p,ver) \
+ (ver>2 ? ((MemHeapHeaderPtr)p)->size : (ver>1 ? ((Mem2HeapHeaderPtr)p)->size : ((Mem1HeapHeaderPtr)p)->size))
+
+#define memUHeapFlags(p) \
+ (((MemHeapHeaderPtr)p)->flags)
+
+#define memUHeapMstrPtrEntries(p,ver) \
+ (ver>2 ? ((MemHeapHeaderPtr)p)->mstrPtrTbl.numEntries : (ver>1 ? ((Mem2HeapHeaderPtr)p)->mstrPtrTbl.numEntries : ((Mem1HeapHeaderPtr)p)->mstrPtrTbl.numEntries))
+
+#define memUHeapMstrPtrAddr(p,ver) \
+ (ver>2 ? (void *)&((MemHeapHeaderPtr)p)->mstrPtrTbl : (ver>1 ? (void *)&((Mem2HeapHeaderPtr)p)->mstrPtrTbl : (void *)&((Mem1HeapHeaderPtr)p)->mstrPtrTbl))
+
+
+
+// This structure is big enough to read in a version 1 or version 2
+// chunk header into.
+typedef struct {
+ union {
+ MemChunkHeaderType ver2;
+ Mem1ChunkHeaderType ver1;
+ } header;
+ } MemChunkHeaderUnionType;
+
+#define memUSizeOfHeapTerminator(ver) \
+ (ver>1 ? sizeof(MemHeapTerminatorType) : sizeof(UInt16))
+
+#define memUSizeOfChunkHeader(ver) \
+ (ver>1 ? sizeof(MemChunkHeaderType) : sizeof(Mem1ChunkHeaderType))
+
+#define memUChunkSize(p,ver) \
+ (ver>1 ? ((MemChunkHeaderPtr)p)->size : ((Mem1ChunkHeaderPtr)p)->size)
+
+#define memUChunkFlags(p,ver) \
+ (ver>1 ? memChunkFlags(p) : ((Mem1ChunkHeaderPtr)p)->flags & 0xF0)
+
+#define memUChunkSizeAdj(p,ver) \
+ (ver>1 ? ((MemChunkHeaderPtr)p)->sizeAdj : ((Mem1ChunkHeaderPtr)p)->flags & mem1ChunkFlagSizeAdj)
+
+#define memUChunkLockCount(p,ver) \
+ (ver>1 ? ((MemChunkHeaderPtr)p)->lockCount : ((Mem1ChunkHeaderPtr)p)->lockOwner >> 4)
+
+#define memUChunkOwner(p,ver) \
+ (ver>1 ? ((MemChunkHeaderPtr)p)->owner : ((Mem1ChunkHeaderPtr)p)->lockOwner & mem1ChunkOwnerMask)
+
+#define memUChunkHOffset(p,ver) \
+ (ver>1 ? ((MemChunkHeaderPtr)p)->hOffset : ((Mem1ChunkHeaderPtr)p)->hOffset)
+
+
+
+
+/************************************************************
+ * Structure of a Card Header.
+ * There is 1 card header for in every card that has ROM. The
+ * card header is stored at sysCardHeaderOffset into the card.
+ *
+ * RAM only cards will not have a card header
+ *************************************************************/
+#define memMaxNameLen 32 // size of name and manuf fields including null
+typedef struct CardHeaderType {
+ UInt32 initStack; // initial stack pointer (v4: offset to code in RomBoot)
+ UInt32 resetVector; // reset vector
+ UInt32 signature; // must be sysCardSignature
+ UInt16 hdrVersion; // header version
+ UInt16 flags; // card flags;
+ UInt8 name[memMaxNameLen]; // card name
+ UInt8 manuf[memMaxNameLen]; // card manufacturer's name
+ UInt16 version; // card version
+ UInt32 creationDate; // card creation date
+ UInt16 numRAMBlocks; // number of RAM blocks on card
+ UInt32 blockListOffset; // offset to RAM block list
+ UInt32 readWriteParmsOffset; // v2: offset from CardBase to r/w system data if any (in ROM)
+ UInt32 readWriteParmsSize; // v2: size of read/write system data if any (in ROM)
+ UInt32 readOnlyParmsOffset; // v2: offset from CardBase to read-only system data (in ROM)
+ UInt32 bigROMOffset; // v2: in SmallROM header: where SmallROM expects bigROM to live
+ // in BigROM header: where BigROM expects itself to live
+ UInt32 checksumBytes; // v2: size of card image in bytes (for checksum)
+ UInt16 checksumValue; // v2: checksum of card image (from Crc16CalcBlock)
+
+ UInt32 readWriteWorkingOffset; // v3: offset from CardBase to r/w working area if any (in ROM)
+ UInt32 readWriteWorkingSize; // v3: size of read/write working area if any (in ROM)
+
+ UInt32 halCodeOffset; // v4: offset from CardHeader to HAL code
+
+ UInt8 reserved[130]; // to bring us to 0x100 alignment
+ } CardHeaderType;
+typedef CardHeaderType* CardHeaderPtr;
+
+#define memCardHeaderFlagRAMOnly 0x0001 // RAM only card
+#define memCardHeaderFlag328 0x0010 // ROM Supports 68328 processor
+#define memCardHeaderFlagEZ 0x0020 // ROM SUpports 68EZ328 processor
+#define memCardHeaderFlag230K 0x1000 // SmallROM supports 230Kbps
+
+
+
+/************************************************************
+ * Structure of a Storage Header.
+ * There is 1 of these for every "store" on a memory card. A
+ * "store" can be all the RAM on a card or all the ROM on a card.
+ *
+ * The RAM storage header is stored at sysRAMHeader offset into the
+ * card. and the ROM storage header is stored at sysROMHeader offset
+ * into the card.
+ *************************************************************/
+typedef struct {
+ UInt32 signature; // must be sysStoreSignature
+ UInt16 version; // version of header
+ UInt16 flags; // flags
+ UInt8 name[memMaxNameLen]; // name of store
+ UInt32 creationDate; // creation date
+ UInt32 backupDate; // last backup date
+ UInt32 heapListOffset; // offset to heap list for store
+ UInt32 initCodeOffset1; // init code for store, if any
+ UInt32 initCodeOffset2; // second init code for store, if any
+ LocalID databaseDirID; // local ID of database dir.
+ UInt32 rsvSpace; // where first heap starts.
+ UInt32 dynHeapSpace; // how big the dynamic heap area is
+ // (always 0 for ROM stores)
+ UInt32 firstRAMBlockSize; // Copy of firstRAMBlock size from cardinfo
+ // Used to determine if we're rebooting
+ // with a different amount of RAM.
+
+ // The following fields are used to store non-volatile information that
+ // must be accessed by the system but that is not convenient to store
+ // in a database due to access time or frequency. It is only valid
+ // in the RAM STORE ON CARD #0! Though some initialization values for
+ // the card 0 RAM store come from the ROM store's nvParams field.
+ SysNVParamsType nvParams;
+
+ // Filler bytes - reserved for future use. Size adjusted to
+ // keep total size of storage header at 0x100 bytes.
+ UInt8 reserved[176-sizeof(SysNVParamsType)];
+
+ // CRC value
+ UInt32 crc; // crc to check validity
+ } StorageHeaderType;
+typedef StorageHeaderType* StorageHeaderPtr;
+
+#define memStoreHeaderFlagRAMOnly 0x0001 // RAM store
+
+
+// A Heap list for each store on a card (either RAM or ROM) gives a list of
+// heaps' starting offsets for that store
+typedef struct {
+ UInt16 numHeaps; // Number of heaps in store
+ UInt32 heapOffset[1]; // offset to heap
+ } HeapListType;
+
+
+
+/********************************************************************
+ * CardInfo structure
+ * The Palm globals has a pointer to an array of CardInfo structures.
+ *
+ * This array is initialized by the Boot code before the Memory Manager
+ * starts up. Among other things, it tells the Memory Manager where
+ * every card is and the size of each card.
+ ********************************************************************/
+typedef struct CardInfoType {
+
+ // These fields are filled in by the boot code BEFORE
+ // MemInit() is called.
+ UInt8 *baseP; // base address of card
+ UInt32 size; // address range of card
+ UInt32 firstRAMBlockSize; // size of RAM block at offset 0
+ UInt32 targetROMShift; // used only under Emulation mode, must be
+ // added to emulated ROM pointers when calculating
+ // a LocalID for use in the device ROM.
+
+
+ UInt32 cardHeaderOffset; // offset to card header (usually in ROM)
+ // = 0 if RAM only card
+
+ UInt32 rsvSpace; // reserve space in RAM before first heap
+ UInt32 dynHeapSpace; // how much space to reserve for dynamic heap(s)
+ StorageHeaderPtr ramStoreP; // pointer to RAM store header
+ // This location depends on how much space
+ // was reserved on the card for the dynamic
+ // heap.
+
+ // These fields are copies of information in the card and storage headers
+ // they are cached here for quicker access by the Memory Manager. They
+ // are filled in by the Memory Manager during MemInit.
+ UInt16 numRAMHeaps; // Number of RAM heaps - for quick access
+ UInt32 *ramHeapOffsetsP; // Table of RAM heap offsets - for quick access
+ UInt16 numROMHeaps; // Number of RAM heaps - for quick access
+ UInt32 *romHeapOffsetsP; // Table of RAM heap offsets - for quick access
+
+ // This field was added for Palm OS v3.5. The HAL fills this in so the OS
+ // no longer has to use a #define'd value which can differ from device to device.
+ UInt32 cardOffsetMask; // converts a pointer to a card offset
+
+ } CardInfoType;
+typedef CardInfoType* CardInfoPtr;
+
+// The constant hwrNumCardSlots, defined in Hardware.h defines the maximum number
+// of cards supported by the hardware.
+
+
+
+
+/************************************************************
+ * Private Memory Manager Constants
+ *************************************************************/
+// Private constant - # of dynamic heaps
+#define memDynamicHeaps 1
+
+// Private constant - maximum chunk size allowed (0xFFFFFFFFL = up to available memory)
+// We're presently limiting the maximum chunk allocation because the current HotSync cannot
+// transfer records/resources larger than (0x0FFFF - 30) bytes. This restriction will
+// be removed when HotSync is extended to MemHandle larger transfers.
+#define memMaxChunkAllocSize ((UInt32)(0x0FFFFUL - 30UL))
+
+
+
+/************************************************************
+ * Private Memory Manager Macros. These macros are not
+ * guaranteed to be compatible in the future and should
+ * only be used in system code, not applications.
+ *
+ * To use these, define NON_PORTABLE at the top of your
+ * source code module.
+ *
+ * WARNING: This macro must only be used on Locked chunks!!!
+ * When running with error checking, it will verify
+ * that the chunk is locked before it dereferences it.
+ *************************************************************/
+
+#if MEMORY_FORCE_LOCK == MEMORY_FORCE_LOCK_ON
+ #define memHandleProtect(h) \
+ ((MemHandle)((UInt32)h | 0x80000000))
+ #define memHandleUnProtect(h) \
+ ((void **)((UInt32)h & 0x7FFFFFFF))
+#else
+ #define memHandleProtect(h) (h)
+ #define memHandleUnProtect(h) (h)
+#endif
+
+
+#if MEMORY_TYPE == MEMORY_LOCAL
+ #if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
+ #define MemDeref(h) \
+ ((MemHandleLockCount(h)==0 ? (*((void **)0x80000000)) : (*memHandleUnProtect(h))))
+ #else
+ #define MemDeref(h) \
+ (*(memHandleUnProtect(h)))
+ #endif
+
+#else
+ #if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
+ #define MemDeref(h) \
+ ((MemHandleLockCount(h)==0 ? (*((void **)0x80000000)) : ((void *)ShlDWord(h))) )
+ #else
+ #define MemDeref(h) \
+ ((void *)ShlDWord(memHandleUnProtect(h)))
+ #endif
+#endif
+
+
+
+
+// Typecast access to the MemCardInfo MemPtr
+#define memCardInfoP(cardNo) \
+ ( ((CardInfoPtr) ((LowMemHdrType*)PilotGlobalsP)->globals.memCardInfoP) + cardNo)
+
+
+
+/********************************************************************
+ * Memory Manager Private Routines
+ * These are used only by internal System code
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void * MemHeapPtr(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapPtr);
+
+Err MemStoreSearch(void *startP, UInt32 range, StorageHeaderPtr *storePP)
+ SYS_TRAP(sysTrapMemStoreSearch);
+
+Err MemStoreInit(UInt32 firstHeapSize, UInt16 firstHeapMstrPtrs,
+ UInt16 cardNo, UInt16 numBlocks, UInt32 *blockInfoP,
+ StorageHeaderPtr storeP, UInt16 numMstrPtrs)
+ SYS_TRAP(sysTrapMemStoreInit);
+
+Err MemNVParams(Boolean set, SysNVParamsPtr paramsP)
+ SYS_TRAP(sysTrapMemNVParams);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __MEMORYPRV_H__
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/SerialLinkPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/SerialLinkPrv.h
new file mode 100644
index 0000000..b40614e
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/SerialLinkPrv.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SerialLinkPrv.h
+ *
+ * Description:
+ * Private Serial Link includes
+ *
+ * History:
+ * 2/6/95 replaces DSerial.h from Debugger
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+
+#ifndef __SERIALLINKPRV_H
+#define __SERIALLINKPRV_H
+
+#include <SerialLinkMgr.h>
+
+
+//*************************************************************************
+// Misc Constants
+//*************************************************************************
+// Default timeout value once into receiving a packet in ticks
+#define slkDefaultInPktTimeout (sysTicksPerSecond*2)
+
+
+
+
+/*******************************************************************
+ * Serial Link Globals
+ *
+ *******************************************************************/
+#define slkMaxSockets 6 // max # of sockets
+#define slkMaxRefNums slkMaxSockets // max # of refNums in use at any one time
+#define slkAnySocket 0xFF
+
+#define slkEmptyRefNum 0xFF // used to track empty refInfos
+#define slkSendBufferSize 252
+
+// We keep an array of these (slkMaxSockets in size) to track which
+// librarie's we've received packet headers for. Since we can have up
+// to slkMaxSockets unique refNums in use at any one time, we must make
+// the array at least that size.
+typedef struct SlkRefInfoType {
+ UInt16 refNum; // refNum of library, or 0xFF if empty
+ Int8 destID; // dest socketID, or -1 if none
+ UInt8 padding;
+ } SlkRefInfoType;
+typedef SlkRefInfoType *SlkRefInfoPtr;
+
+typedef struct SlkGlobalsType {
+ UInt16 openCount;
+
+ UInt16 socketRefNum[slkMaxSockets];
+ Boolean socketOpen[slkMaxSockets];
+ SlkSocketListenPtr socketListenP[slkMaxSockets];
+ UInt16 socketTimeout[slkMaxSockets]; // inPacket timeout
+
+
+ // We can keep track of packets coming in for up to slkMaxRefNums libraries.
+ // This array holds the destination socket ID for packets received from
+ // each library.
+ SlkRefInfoType refInfo[slkMaxRefNums];
+
+ UInt8 transId; // next transaction ID
+ UInt8 padding;
+ UInt32 xmitSemaphoreID; // Semaphore ID for transmitting
+ UInt16 numReceived; // # of packets received since serial link
+ // was opened.
+ // New fields to buffer sends to prevent
+ // the header, body and checksum from being
+ // sent out as three distinct send requests.
+ Boolean socketWantsBuffering[slkMaxSockets];
+
+ UInt8 *sendBufferP; // Send buffer
+ UInt16 sendBufferSize; // Size of the allocated send buffer
+
+ } SlkGlobalsType;
+
+typedef SlkGlobalsType* SlkGlobalsPtr;
+
+
+
+#endif //__SERIALLINKPRV_H
+
+#endif //NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/SysEvtPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/SysEvtPrv.h
new file mode 100644
index 0000000..a7fb95a
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/SysEvtPrv.h
@@ -0,0 +1,227 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SysEvtPrv.h
+ *
+ * Description:
+ * Private Header for the System Event Manager
+ *
+ * History:
+ * 08/10/95 RM Created by Ron Marianetti
+ * 07/14/99 kwk Added silkscreen area info structures.
+ * 09/13/99 kwk Moved evtKeyStringEscape to SysEvtMgr.c, since
+ * that's the only file using it.
+ * 11/12/99 kwk Moved EvtGetPenBtnList and EvtGetSilkscreenAreaList
+ * to SysEvtMgr.h, since they're now public, as well
+ * as associated data structures.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+#ifndef __SYSEVTPRV_H__
+#define __SYSEVTPRV_H__
+
+#include <SysEvtMgr.h> // SilkscreenAreaType & PenBtnListType
+
+
+/************************************************************
+ * Structure of a Pen Capture Queue
+ *
+ * This structure is used to hold one or more pen strokes
+ * and is filled by the digitizer interrupt routine and emptied
+ * by application level code.
+ *
+ * A default size queue is allocated by the system and used to capture
+ * strokes for subsequent processing by the Graffiti recognizer
+ * or the hard icon recognizer. This queue pointer is stored in
+ * the System Event Manager Globals.
+ *
+ * Optionally, applications can replace the system pen queue with
+ * one of their own if it they need to hold larger strokes
+ * or more of them.
+ *
+ *
+ * Stroke data is stored in compressed form in this queue - refer
+ * to the comments on the routine EvtEnqueuPenPoint for the format
+ * of the queue data.
+ *************************************************************/
+typedef struct PenQueueType {
+ Int16 start; // start byte offset
+ Int16 end; // end byte offset
+ Int16 size; // size of queue in bytes
+
+ UInt16 strokeCount; // # of complete strokes currently in pen queue
+ Boolean returnedPenDown; // set after we return a pen-down event for
+ // the next stroke in the queue. Cleared after
+ // we return the pen-up for the stroke.
+
+ UInt8 reserved;
+
+ PointType addLast; // last point captured
+ Int16 addStrokeStart; // offset in queue to start of stroke
+ // currently being added to queue
+ // -1 : no stroke being captured
+
+
+ UInt16 strokesRemoved; // running count: # of strokes removed from queue.
+ UInt16 strokesAdded; // running count: # of strokes added to queue.
+
+ Int16 rmvStrokeStage; // -1 : not started
+ // 0 : returned stroke info
+ // 1 : returned start point
+
+ PointType rmvLast; // last point dequeued
+ PointType rmvStartPt; // copy of start point of stroke currently
+ // being removed.
+
+ UInt8 data[2]; // 'size' bytes of data
+ } PenQueueType;
+typedef PenQueueType* PenQueuePtr;
+
+
+
+/************************************************************
+ * Structure of the Key Queue
+ *
+ * This structure is used to hold one or more keystrokes
+ * and is filled by numerous places including the low level
+ * hardware key interrupt routine, the Graffiti recognizer, and
+ * the digitizer buttons recognizer.
+ *
+ * A default size queue is allocated by the system.
+ * This queue pointer is stored in the System Event Manager globals.
+ *
+ * Optionally, applications can replace the system key queue with
+ * one of their own if it they need to hold more keys in the queue
+ * at one time. This may be necessary when processing large macro
+ * strings from Graffiti.
+ *
+ * Key data is stored in compressed form in this queue. Refer to
+ * the comments for the function EvtEnqueueKeyString for the format
+ * of the compressed data.
+ *
+ *************************************************************/
+typedef struct KeyQueueType {
+ UInt16 start; // start byte offset
+ UInt16 end; // end byte offset
+ UInt16 size; // size of queue in bytes
+
+ UInt8 data[2]; // 'size' bytes of data
+ } KeyQueueType;
+typedef KeyQueueType* KeyQueuePtr;
+
+
+/************************************************************
+ * Structure of the silk resource in system overlay DBs. Note,
+ * this structure must mirror the structure of the sysResTSilkscreen
+ * resource as defined in PalmTypes.r.
+ *************************************************************/
+
+// Version of the SilkscreenInfoType structure.
+#define sysSilkscreenVers 1
+
+// Structure of the silkscreen resource (sysResTSilkscreen)
+typedef struct SilkscreenInfoType {
+ UInt16 version; // version of structure.
+
+ // The next three fields aren't used to locate the silkscreen,
+ // but help identify different silkscreen layouts.
+ UInt32 vendorCreator; // creator assigned to vendor
+ // (psys for 3Com)
+ UInt16 localeLanguage; // language for locale
+ UInt16 localeCountry; // country for locale.
+
+ UInt16 numAreas; // Count of number of silkscreen areas.
+ SilkscreenAreaType areas[1]; // Placeholder for one or more areas.
+
+ PenBtnListType buttonList; // Count + list of buttons.
+ } SilkscreenInfoType;
+
+
+/************************************************************
+ * Key constants
+ *************************************************************/
+
+#define evtDefaultPenQSize 0x100
+#define evtDefaultKeyQSize 0x40
+
+#define evtEffectiveKeyQStorage (evtDefaultKeyQSize - sizeof(KeyQueueType))
+
+
+// gremlinsFlags
+#define grmGremlinsOn 0x01
+#define grmEventTraceOn 0x02
+#define grmGremlinsIdle 0x04
+
+/************************************************************
+ * Structure of System Event Manager Globals
+ *************************************************************/
+typedef struct SysEvtMgrGlobalsType {
+ Boolean sendNullEvent; // set by EvtWakeup
+ Boolean enableGraffiti; // If true, enable Graffiti translation
+ Boolean enableSoftKeys; // If true, enable digitizer button translation
+
+
+ Boolean removeTopStroke; // if true, remove top stroke from queue
+ // next time EvtGetSysEvent is called;
+ PenQueuePtr penQP; // pointer to current pen queue
+ UInt16 penQStrokesRemoved; // saved value of penQP->strokesRemoved. Used to
+ // determine if app removed stroke from penUp
+ // event or not.
+
+ KeyQueuePtr keyQP; // pointer to current key queue
+
+ RectangleType writingR; // enclosing rect for writing area
+ UInt16 appAreaBottom; // bottom coordinate of application area.
+
+ Int16 penX; // current pen location and state
+ Int16 penY;
+ Boolean penDown;
+ Boolean displayingBatteryAlert; // to avoid re-entering battery dialog
+
+ Int16 lastPenX; // last pen location and state
+ Int16 lastPenY;
+ Boolean lastPenDown;
+
+ // This boolean is set by the Remote Screen Driver timer procedure periodically
+ // to force the event manager to call ScrSendUpdateArea which will send the update
+ // area of the screen to the host.
+ Boolean needRemoteScrUpdate; // If true, call ScrSendUpdateArea
+
+
+ UInt8 gremlinsFlags; // flag to indicate if gremlins is running and
+ // if we'er doing an event trace.
+
+ Boolean idle; // DOLATER ron - Who put this here?? What is it for???
+
+ // The following flag is used to better support background wakeup jobs.
+ // See the comments on the new EvtGotUserEvent() for details
+ Boolean gotUserEvent; // Cleared when going to sleep, set as soon as
+ // we get a user event (key press, app alarm, etc).
+
+ UInt8 reserved;
+ } SysEvtMgrGlobalsType;
+
+typedef SysEvtMgrGlobalsType* SysEvtMgrGlobalsPtr;
+
+
+
+/************************************************************
+ * System Event Manager procedures
+ *************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //__SYSEVTPRV_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/IncsPrv/SystemPrv.h b/SrcShared/Palm/Platform/Core/System/IncsPrv/SystemPrv.h
new file mode 100644
index 0000000..b9bee33
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/IncsPrv/SystemPrv.h
@@ -0,0 +1,474 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SystemPrv.h
+ *
+ * Description:
+ * Private Pilot system equates
+ *
+ * History:
+ * 08/09/95 RM Created by Ron Marianetti
+ * 01/28/98 SCL Added HotSync port "hint" for SerialHWMgr
+ * 02/04/98 srj Added HW_TARGET_EZ in appropriate places.
+ * HW_TARGET_TD1 in this file means "any
+ * handheld", not non-EZ platforms.
+ * 04/05/99 jrb bumped sysLowMemSize
+ * 04/13/99 kwk Bumped sysLowMemSize to 15B0.
+ * 05/21/99 kwk Bumped sysLowMemSize to 1700.
+ * 06/24/99 kwk Added four locale-related fields to SysNVParamsType.
+ * 07/01/99 kwk Added SysExtPrefsType structure & version/flag defs.
+ * 07/13/99 kwk Bumped sysLowMemSize to 1800.
+ * 11/01/99 kwk Moved SysWantEvent here from SystemMgr.h
+ * 12/03/99 SCL Moved SysAppInfoType, SysAppStartup, and SysAppExit
+ * to SystemMgr.h (for StartupCode/Runtime)
+ * 01/21/00 ADH Bumped sysLowMemSize to 1880
+ * 03/30/00 jmp Bumped sysLowMemSize to 1900 for the device and to 2000
+ * for the Simulator.
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE
+
+#ifndef __SYSTEMPRV_H__
+#define __SYSTEMPRV_H__
+
+#include <DataMgr.h>
+#include <Event.h>
+#include <SystemMgr.h> // for SysAppInfoType
+
+// Include fixed global type
+#include "Globals.h"
+#include "SerialMgr.h" // for serPortLocalHotSync define
+
+
+/************************************************************
+ * Common Equates between Native and Emulation mode
+ *************************************************************/
+#define sysCardSignature 0xFEEDBEEFL // card signature long word
+#define sysStoreSignature 0xFEEDFACEL // store signature long word
+
+
+// This should be set to sizeof(LowMemType) for the final version, but
+// until then we'll make it bigger than LowMemType so that we can
+// add more globals without having to re-format memory cards.
+//
+// Note: sysLowMemSize needs to be an even multiple of 0x1000 in the Simulator
+// so that MemStoreSearch() will be able to find the sysStoreSignature.
+//
+#if EMULATION_LEVEL == EMULATION_NONE
+#define sysLowMemSize 0x1900 // size of Low Memory Area
+#else
+#define sysLowMemSize 0x2000 // size of Low Memory Area
+#endif
+#define sysInitStack (sysLowMemSize+0x1000) // stack ptr during boot
+
+
+
+// The location of the Card Header (start of ROM) is plugged in at run
+// time to the global variable GSysCardHeaderOffset. This MUST be done
+// by the startup code. We make this a run-time variable so that the same
+// executable ROM image can be run from ROM or RAM.
+// #define sysCardHeaderOffset someConstant
+#define sysRAMOnlyCardHeaderOffset 0x0000000L // RAM only card header created here
+#define sysCardHeaderSize 0x0100 // size of card header
+
+
+// Offset to ROM storage header from card header
+#define sysROMStoreRelOffset sysCardHeaderSize
+#define sysStoreHeaderSize 0x0100 // size of storage header
+
+
+// This equate tells us how large of a heap info table to reserve in the
+// globals for each card
+#define sysMaxHeapsPerCard 128 // max # of heaps per card
+
+
+// This equtes tells us the initial size of the Library table as held in
+// the Low Memory area. The table is allocated in the dynamic heap by
+// the first call to SysLibInstall(), in SystemMgr.c.
+#define sysDefaultLibraries DEFAULT_LIB_ENTRIES // default size of library table
+
+
+// The default port number and baud rate for the serial port
+// (send "HotSync" port hint for SerialHWMgr)
+#define sysDefaultSerPort serPortLocalHotSync // Use port #0
+#define sysDefaultSerBaud 57600 // baud rate
+
+/************************************************************
+ * Structure of the pref=0 resource in applications. Note, this
+ * structure must mirror the structure of the sysResTAppPrefs
+ * resource as defined in SystemResourcesPrv.h.
+ *************************************************************/
+typedef struct SysAppPrefs {
+ UInt16 priority; // task priority
+ UInt32 stackSize; // required stack space
+ UInt32 minHeapSpace; // minimum heap space required
+ } SysAppPrefsType;
+typedef SysAppPrefsType *SysAppPrefsPtr;
+
+
+// Extra stack space allocated for each app to
+// account for increased stack usage by the system.
+#define sysAppStackSpaceFudgeFactor 0xD0
+
+/************************************************************
+ * Structure of the xprf=0 resource in resource DBs. Note, this
+ * structure must mirror the structure of the sysResTExtPrefs
+ * resource as defined in SystemResourcesPrv.h. Also, fields can only
+ * be added (at the end), never removed or changed.
+ *************************************************************/
+
+#define sysExtPrefsVers 1
+
+// Flags defined for SysExtPrefsType.flags
+#define sysExtPrefsNoOverlayFlag 0x00000001
+
+typedef struct SysExtPrefsType {
+ UInt16 version; // version of structure.
+ UInt32 flags; // 32 boolean flags.
+ } SysExtPrefsType;
+
+/************************************************************
+ * Structure of the user info in the TCB of a task. This structure
+ * is stored in the xtcbuser fields of the AMX TCB for a task and
+ * must not exceed 4 DWords in length (the size reserved by AMX for
+ * user info).
+ *************************************************************/
+typedef struct SysTCBUserInfoType {
+ SysAppInfoPtr tmpAppInfoP; // used to pass appInfo to nested launches
+ SysAppInfoPtr rootAppInfoP; // App info for the root application on this task
+ UInt32 initialA5; // Inital value for A5 globals MemPtr
+ } SysTCBUserInfoType;
+typedef SysTCBUserInfoType *SysTCBUserInfoPtr;
+
+
+/************************************************************
+ * An alternate use of the user info area in the TCB of a task.
+ * This is used to pass info back to the kernel when a task is
+ * being deleted. When the termination proc is called it can
+ * fill in the field stackInUseByP field to point to a taskID
+ * field. This field will be cleared by the TaskDelete routine
+ * when it is safe to delete the tasks stack.
+ *************************************************************/
+typedef struct SysExitingTaskInfoType {
+ UInt32 * stackInUseByP; // points to taskid of task using this stack
+ } SysExitingTaskInfoType;
+typedef SysExitingTaskInfoType *SysExitingTaskInfoPtr;
+
+
+//*****************************************************************
+// Structure of ParamBlock for the SysKernelInfo call
+//*****************************************************************
+
+// Selector codes
+typedef enum {
+ sysKernelInfoSelCurTaskInfo,
+ sysKernelInfoSelTaskInfo,
+ sysKernelInfoSelSemaphoreInfo,
+ sysKernelInfoSelTimerInfo
+ } SysKernelInfoSelector;
+
+typedef struct SysKernelInfoType {
+// SysKernelInfoSelector selector; // Which info to get
+ UInt8 selector; // Which info to get
+ UInt8 reserved;
+ UInt32 id; // which object to get info on
+
+ union {
+ struct {
+ UInt32 id; // ID of task
+ UInt32 nextID; // ID of next task
+
+ UInt32 tag; // task tag
+ UInt32 status; // task status
+ UInt32 timer; // # ticks left if task's timeout
+ UInt32 timeSlice; // task's time slice
+ Int16 priority; // task priority
+ UInt16 attributes; // task attributes
+ Int16 pendingCalls; // # of pending calls
+ UInt32 senderTaskID; // task ID of message sender
+ UInt32 msgExchangeID; // task's message exchange ID, if any
+
+ UInt32 tcbP; // pointer to TCB
+ UInt32 stackP; // stack pointer of task
+ UInt32 stackStart; // top of task stack (where it started).
+ UInt32 stackSize; // size of stack
+ } task;
+
+ struct {
+ UInt32 id;
+ UInt32 nextID; // ID of next semaphore
+
+ UInt32 tag; // semaphore tag
+ Int16 initValue; // semaphore initial value
+ // >= 0 for counting, -1 for resource
+ Int16 curValue; // semaphore current value
+ // >0 available
+ // 0 not available
+ // -n not available, n tasks waiting
+ Int16 nestLevel; // 0 for counting, >= 0 for resource
+ UInt32 ownerID; // owner ID
+ // 0 for counting or resource free
+ } semaphore;
+
+ struct {
+ UInt32 id;
+ UInt32 nextID; // ID of next timer
+
+ UInt32 tag; // timer tag
+ UInt32 ticksLeft; // ticks left till timer runs
+ UInt32 period; // timer period, if periodic
+ UInt32 proc; // timer procedure
+ } timer;
+ } param;
+
+ } SysKernelInfoType;
+
+
+typedef SysKernelInfoType* SysKernelInfoPtr;
+
+
+
+
+//-----------------------------------------------------------------
+// Bits for status field in task info parameter block
+//------------------------------------------------------------------
+#define sysTaskStatusTriggerWait 0x01 // (CJ_MATSWTR) Task idle (waiting for trigger)
+#define sysTaskStatusSuspended 0x02 // (CJ_MATSWSUS) Task suspended (waiting for resume)
+#define sysTaskStatusWaiting 0x04 // (CJ_MATSWAIT) Task waiting (see other bits)
+#define sysTaskStatusHalted 0x80 // (CJ_MATSWHLT) Task halted
+
+// If sysTaskStatusWaiting set, these bits tell why....
+#define sysTaskStatusWaitSemaphore 0x00100 // (CJ_MATSWSM) waiting on semaphore
+#define sysTaskStatusWaitEvent 0x00200 // (CJ_MATSWEV) waiting on event group
+#define sysTaskStatusWaitMailbox 0x00400 // (CJ_MATSWMB) waiting on mailbox
+#define sysTaskStatusWaitMsgExchange 0x00800 // (CJ_MATSWMX) waiting on message exchange
+#define sysTaskStatusWaitBuffer 0x01000 // (CJ_MATSWBUF) waiting on buffer
+#define sysTaskStatusWaitTimer 0x08000 // (CJ_MATSWTM) waiting on timer
+
+#define sysTaskStatusWaitMailboxAck 0x00010000L // (CJ_MATSWMBAK) mailbox ack
+#define sysTaskStatusWaitMsgXAck 0x00020000L // (CJ_MATSWMXAK) msg exchange ack
+#define sysTaskStatusWaitTaskSig 0x00040000L // (CJ_MATSWSIG) task signal wait
+
+//-----------------------------------------------------------------
+// Bits for attributes field in task info parameter block
+//------------------------------------------------------------------
+#define sysTaskAttrNoHalt 0x02 // (CJ_MATAHLT) Task cannot be halted
+#define sysTaskAttrMsgStack 0x08 // (CJ_MATAMSG) receives msgs on stack
+#define sysTaskAttrMsgByRef 0x10 // (CJ_MATAPBR) messages passed by reference
+#define sysTaskAttrMsgOnStack 0x4000 // (CJ_MATAMRDY) message ready on stack
+#define sysTaskAttrMsgSenderWaiting 0x8000 // (CJ_MATAMSW) msg sender waiting for ack
+
+
+
+/************************************************************
+ * This structure defines a section within the RAM storage header
+ * on Card#0 used to hold non-volatile System information. We store
+ * System information that can not be conveniently stored or accessed
+ * from a Database in this area because:
+ * 1.) it can be accessed earlier during the boot-up process and
+ * 2.) It can be accessed from an interrupt routine.
+ *************************************************************/
+typedef struct SysNVParamsType {
+ UInt32 rtcHours; // Real-Time clock hours - add to value
+ // in DragonBall RTC register to get
+ // actual date & time.
+ UInt32 rtcHourMinSecCopy; // Copy of latest value in rtcHourMinSec reg of
+ // DBall. Used as default RTC value on Reset.
+ UInt8 swrLCDContrastValue; // Contrast Value for LCD on EZ-based products
+ // that use the software contrast PWM (such as Sumo)
+ UInt8 swrLCDBrightnessValue; // Brightness value for screens with adjustable brightness.
+
+ // Note that in the ROM store, these next four fields contain the default
+ // settings for card 0's RAM store, when it has to be initialized.
+ void* splashScreenPtr; // MemPtr to splash screen bitmap
+ void* hardResetScreenPtr; // MemPtr to hard reset screen bitmap.
+ UInt16 localeLanguage; // Language for locale.
+ UInt16 localeCountry; // Country for locale.
+
+ // 11/15/99 SCL: New Globals added for Licensees, Partners, OEMs, etc.
+ // These storage locations are reserved for the HAL running on a given device.
+ UInt32 sysNVOEMStorage1; // 4 bytes for Device OEM use only!
+ UInt32 sysNVOEMStorage2; // 4 bytes for Device OEM use only!
+
+ } SysNVParamsType;
+typedef SysNVParamsType *SysNVParamsPtr;
+
+
+
+/************************************************************
+ * Structure of the System Globals. This is where we place
+ * variable size globals that the System Manager uses. This
+ * is currently not used but a pointer for it is reserved
+ * in the low memory globals
+ *************************************************************/
+/*
+typedef struct SysGlobalsType {
+ } SysGlobalsType;
+typedef SysGlobalsType *SysGlobalsPtr;
+*/
+
+
+
+/************************************************************
+ * Assignment of bits to the event group used for implementing the
+ * NetLibSelect() call. This event group is also used by the System
+ * Event Manager (SysEvtMgr.c) and includes a bit for "stdin"
+ * (pen & keyboard) besides the other bits used for Net Library socket refNums.
+ *************************************************************/
+#define sysFileDescNet (sysFileDescStdIn+1) // first available refNum for use by
+ // Net library.
+
+
+// Macro to generate a bitmask for the event group corresponding to a particular
+// refNum id and boolean indicating whether it's for input or output. The outputs
+// are in the upper 16 bits of the event group and the inputs are in the
+// lower 16 bits.
+#define sysEvtGroupMask(fd,output) \
+ (output ? (0x00010000 << (fd)) : (0x00000001 << (fd)) )
+
+
+/************************************************************
+ * This structure defines the entire the Low Memory Area
+ * and includes the low memory header defined in Globals.h,
+ * followed by some variable size globals that may change
+ * from rev to rev of the System Software.
+ *
+ * When emulating under Windows, this structure ends up at some random
+ * place in memory and the global variable GlobalsP points to it.
+ *
+ * When running in the native environment, this structure starts at
+ * address sysGlobalsOffset.
+ *
+ * In order to simplify the source code, macros are defined for
+ * accessing commonly used globals in the optimim manner for
+ * each environment.
+ *************************************************************/
+#include "SerialLinkPrv.h"
+#include "MemoryPrv.h"
+#include "SystemPkt.h"
+#include "DebugPrv.h"
+#include "Hardware.h"
+typedef struct LowMemType {
+
+
+ // Fixed size globals, defined in Globals.h
+ LowMemHdrType fixed;
+
+
+ //---------------------------------------------------------------------------
+ // These structures are always placed at the end of the LowMem area so
+ // that other globals don't generally have to move when their sizes change
+ //---------------------------------------------------------------------------
+ CardInfoType memCardInfo[hwrNumCardSlots]; // Memory Card Info Array
+
+ SlkGlobalsType slkGlobals; // Serial Link Mgr globals
+
+ DbgGlobalsType dbgGlobals; // Debugger globals
+
+ SysAppInfoType sysAppInfo; // SysAppInfoType for system
+
+ MemPtr sysDispatchTable[sysNumTraps]; // trap table
+
+ } LowMemType;
+
+
+// Access to variable size globals
+#define GMemCardInfo (((LowMemType*)PilotGlobalsP)->memCardInfo)
+#define GSlkGlobals (((LowMemType*)PilotGlobalsP)->slkGlobals)
+#define GDbgGlobals (((LowMemType*)PilotGlobalsP)->dbgGlobals)
+#define GSysAppInfo (((LowMemType*)PilotGlobalsP)->sysAppInfo)
+#define GSysLibTable (((LowMemType*)PilotGlobalsP)->sysLibTable)
+#define GSysDispatchTable (((LowMemType*)PilotGlobalsP)->sysDispatchTable)
+
+
+// Flags for the GSysResetFlags global
+#define sysResetFlagHardReset 0x01 // HardReset
+#define sysResetFlagCreateDefaultDBs 0x02 // create default databases
+#define sysResetFlagNoExtensions 0x04 // don't execute extensions
+#define sysResetFlagGoingToDebugger 0x08 // going into boot debugger
+// Flag to mark the boot start so that if we get into the loop:
+// busErr, sysReset, busErr, ... we can get out.
+#define sysResetFlagBootStarted 0x10
+
+
+
+// Flags for the GSysPrefFlags global
+#define sysPrefFlagTaxiDisable 0x0001 // Not used in >1.0 ROM.
+#define sysPrefFlagEnableEasterEggs 0x0002 // Enable easter eggs
+#define sysPrefFlagTaxiDisIdle 0x8000 // Disable Idle Taxi temporarily,
+ // (not saved in preferences)
+#define sysPrefFlagTaxiDisIdleTime 0x4000 // Copy of the 16th bit of the system
+ // time when sysPrefFlagTaxiDisIdle bit
+ // was set (not saved in preferences).
+
+
+// Flags for the GSysMiscFlags global
+#define sysMiscFlagInFatalAlert 0x0001 // Currently displaying fatal alert
+#define sysMiscFlagAlwaysSwitchApp 0x0002 // Inform UI App Shell to switch
+ // apps even if already running
+#define sysMiscFlagProfile 0x0004 // true when profiling code.
+#define sysMiscFlagGrfDisable 0x0008 // true when Graffiti is disabled
+#define sysMiscFlagInDemoAlert 0x0010 // true when Demo unit alert is displayed
+#define sysMiscFlagBacklightDisable 0x0020 // true if backlight is disabled
+#define sysMiscFlagUIInitialized 0x0040 // true after UI has been inited
+#define sysMiscFlagExgEvent 0x0080 // true when a library (Ir) has data
+
+
+// Flags for the GDbgWasEntered global
+
+// dbgEnteredFlagPseudoNMI: manually setting this flag in the GDbgWasEntered low mem global
+// causes the HotSync cradle button IRQ handler to enter the debugger. Have to
+// set each time because entering the debugger resets the flag. (this is a hack)
+#define dbgEnteredFlagPseudoNMI 0x80
+#define dbgEnteredFlagTrue 0x01
+
+// Flags for the GCommActivityFlags global
+#define sysCommActivityWlsSockOpen 0x01 // true when a wireless socket is open (Jerry Only)
+//#define sysCommActivityAntennaAlert 0x02 // true when an antenna down alert is on the screen
+#define sysCommActivityHotSync 0x04 // true when a hot sync is in progress
+//#define sysCommActivityDiscardAntKey 0x08 // true when a wireless app want antenna hard keys discarded
+
+
+/************************************************************
+ * Function Prototypes
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+SysTCBUserInfoPtr SysTaskUserInfoPtr(UInt32 taskID)
+ SYS_TRAP(sysTrapSysTaskUserInfoPtr);
+
+SysAppInfoPtr SysCurAppInfoPV20(void)
+ SYS_TRAP(sysTrapSysCurAppInfoPV20);
+
+SysAppInfoPtr SysGetAppInfo(SysAppInfoPtr *uiAppPP, SysAppInfoPtr *actionCodeAppPP)
+ SYS_TRAP(sysTrapSysGetAppInfo);
+
+Boolean SysWantEvent(EventType* eventP, Boolean *needsUI)
+ SYS_TRAP(sysTrapSysWantEvent);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/************************************************************
+ * Assembly Function Prototypes
+ *************************************************************/
+#define _SysFatalAlert \
+ ASM_SYS_TRAP(sysTrapSysFatalAlert)
+
+#define _SysReset \
+ ASM_SYS_TRAP(sysTrapSysReset)
+
+
+
+#endif //__SYSTEMPRV_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Core/System/Src/Crc.c b/SrcShared/Palm/Platform/Core/System/Src/Crc.c
new file mode 100644
index 0000000..3554e9d
--- /dev/null
+++ b/SrcShared/Palm/Platform/Core/System/Src/Crc.c
@@ -0,0 +1,257 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Crc.c
+ *
+ * Description:
+ * This file contains the CRC calculation routines for Pilot.
+ *
+ * History:
+ * May 10, 1995 Created by Vitaly Kruglikov
+ * 5/10/95 vmk Initial version.
+ * 5/11/95 vmk Added target CRC translation tables (asm),
+ * and deleted Crc16CalcChar() and Crc32CalcChar().
+ * 12/8/97 scl Added Crc16CalcBigBlock routine.
+ *
+ *****************************************************************************/
+
+/* Routines:
+ * Crc16CalcBlock
+ * Crc32CalcBlock
+ */
+
+#include <BuildDefines.h>
+#ifdef HAS_LOCAL_BUILD_DEFAULTS
+#include "LocalBuildDefaults.h"
+#endif
+#include <PalmTypes.h>
+
+// Include prototypes for this module
+#include "Crc.h"
+
+//=====================================================================
+// We are changing the CRC routines to do a simple checksum in order
+// to conserve ROM space....
+//===================================================================
+//
+// The emulation code can use the statically-defined CRC lookup tables.
+// The target code will need to store the tables in the system database.
+//
+//
+// This is the lookup table used when performing the 16-bit CRC calculation.
+//
+static const UInt16 crctt_16[ 256 ] =
+{
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+
+
+//
+// This is the lookup table used when performing the 32-bit CRC calculation.
+//
+/*
+static const UInt32 crctt_32[ 256 ] =
+{
+0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
+0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
+0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
+0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
+0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
+0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
+0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
+0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
+0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
+0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
+0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
+0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
+0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
+0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
+0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
+0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
+0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
+0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
+0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
+0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
+0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
+0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
+0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
+0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
+0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
+0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
+};
+*/
+
+
+
+
+/************************************************************
+ * API
+ *-----------------------------------------------------------
+ *
+ * FUNCTION: Crc16CalcBlock
+ *
+ * DESCRIPTION: Calculate the 16-bit CRC of a data block using the table
+ * lookup method.
+ *
+ * PARAMETERS:
+ * bufP -- pointer to the data buffer;
+ * count -- the number of bytes in the buffer;
+ * crc -- the seed crc value;
+ *
+ * RETURNS:
+ * A 16-bit CRC for the data buffer.
+ *
+ * HISTORY:
+ * 05/10/95 vmk Created by Vitaly Kruglikov.
+ * 09/12/99 kwk bufP is a const void* parameter.
+ *
+ *************************************************************/
+UInt16 Crc16CalcBlock(const void* bufP, UInt16 count, UInt16 crc)
+{
+ register const UInt8 * byteP = (UInt8 *)bufP;
+ UInt16 * crctt = (UInt16 *)crctt_16; // CRC translation table
+
+ //
+ // Calculate the 16 bit CRC using the table lookup method.
+ //
+ if ( count )
+ {
+ do {
+ crc = (crc << 8) ^ crctt[ (UInt8)((crc >> 8) ^ *byteP++) ];
+ } while ( --count );
+ }
+
+ return( crc & 0xffff );
+}
+
+
+
+/************************************************************
+ * API
+ *-----------------------------------------------------------
+ *
+ * FUNCTION: Crc16CalcBigBlock
+ *
+ * DESCRIPTION: Calculate the 16-bit CRC of a data block using the table
+ * lookup method. Accepts 32-bit value for count
+ *
+ * PARAMETERS:
+ * bufP -- pointer to the data buffer;
+ * count -- the number of bytes in the (big) buffer;
+ * crc -- the seed crc value;
+ *
+ * RETURNS:
+ * A 16-bit CRC for the data buffer.
+ *
+ * CREATED: 12/8/97
+ *
+ * BY: SCL
+ *
+ * REVISION HISTORY
+ *
+ *************************************************************/
+UInt16 Crc16CalcBigBlock(void * bufP, UInt32 count, UInt16 crc)
+{
+ register UInt8 * byteP = (UInt8 *)bufP;
+ UInt16 * crctt = (UInt16 *)crctt_16; // CRC translation table
+
+ //
+ // Calculate the 16 bit CRC using the table lookup method.
+ //
+ if ( count )
+ {
+ do {
+ crc = (crc << 8) ^ crctt[ (UInt8)((crc >> 8) ^ *byteP++) ];
+ } while ( --count );
+ }
+
+ return( crc & 0xffff );
+}
+
+
+
+/************************************************************
+ * API
+ *-----------------------------------------------------------
+ *
+ * FUNCTION: Crc32CalcBlock
+ *
+ * DESCRIPTION: Calculate the 32-bit CRC of a data block using the table
+ * lookup method.
+ *
+ * PARAMETERS:
+ * bufP -- pointer to the data buffer;
+ * count -- the number of bytes in the buffer;
+ * crc -- the seed crc value;
+ *
+ * RETURNS:
+ * A 32-bit CRC for the data buffer.
+ *
+ * CREATED: 5/10/95
+ *
+ * BY: Vitaly Kruglikov
+ *
+ * REVISION HISTORY
+ *
+ *************************************************************/
+/*UInt32 Crc32CalcBlock(void * bufP, UInt16 count, UInt32 crc)
+{
+ register UInt8 * byteP = (UInt8 *)bufP;
+ UInt32 temp1;
+ UInt32 temp2;
+ UInt32 * crctt = (UInt32 *)crctt_32; // CRC translation table
+
+ //
+ // Calculate the 32 bit CRC using the table lookup method.
+ //
+ if ( count )
+ {
+ do {
+ temp1 = ( crc >> 8 ) & 0x00FFFFFFL;
+ temp2 = crctt[ ((Int16)crc ^ *byteP++) & 0xff ];
+ crc = temp1 ^ temp2;
+ } while ( --count );
+ }
+
+ return( crc );
+}
+*/
diff --git a/SrcShared/Palm/Platform/Incs/BuildDefaults.h b/SrcShared/Palm/Platform/Incs/BuildDefaults.h
new file mode 100644
index 0000000..4259731
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/BuildDefaults.h
@@ -0,0 +1,309 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: BuildDefaults.h
+ *
+ * Description:
+ * Build variable defaults for Palm OS.
+ *
+ * This file is included by <PalmTypes.h>.
+ * This file supercedes the old <BuildRules.h> file.
+ *
+ * History:
+ * 07/16/99 SCL So many changes the old history is obsolete.
+ * 07/29/99 kwk Deleted TEXT_SERVICES & INTERNATIONAL_MGR defines.
+ * 09/15/99 kwk Changed COUNTRY & LANGUAGE defines into #errors.
+ * 10/04/99 grant Added LOCALE define (defaults to #error).
+ * 10/05/99 kwk Added LOCALE_SUFFIX define (defaults to "").
+ *
+ *****************************************************************************/
+
+#ifndef __BUILDDEFAULTS_H__
+#define __BUILDDEFAULTS_H__
+
+#include <BuildDefines.h>
+
+// To override build options in a local component, include <BuildDefines.h>
+// first, then define switches as need, and then include <PalmTypes.h>.
+
+// Some projects used to have a local copy of a file called "AppBuildRules.h"
+// or "AppBuildRulesMSC.h", which was automatically included by <BuildRules.h>
+// to override certain system default compile-time switches. These local
+// "prefix" files can still be used. The project source files should be changed
+// to include <BuildDefines.h>, then "AppBuildRules.MSC.h", then <PalmTypes.h>
+// instead of the previous <Pilot.h>
+
+
+/************************************************************
+ * Include the following when running under the CodeWarrior
+ * IDE so that default build options can be overriden. The default
+ * version of this file is in the Incs: directory. If an app wishes
+ * to override the default options, it should create a copy of this
+ * include file in its own local directory. This include file
+ * is never used when building from MPW since MPW can specify compiler
+ * defines from the command line.
+ *
+ * Other environments can override all of these settings by simply
+ * pre-defining CMD_LINE_BUILD and any other desired settings.
+ *************************************************************/
+
+#ifndef CMD_LINE_BUILD // typically pre-defined only from MPW
+
+ #if !defined(__MWERKS__) && !defined(__PALMOS_TRAPS__) && !defined(_MSC_VER)
+
+ // assume other environments generally build only PalmOS executables
+ #define __PALMOS_TRAPS__ 1
+
+ #endif
+
+
+ #if __PALMOS_TRAPS__ // defined by CodeWarrior IDE or above
+
+ // Settings to build a PalmOS executable
+ #ifndef EMULATION_LEVEL
+ #define EMULATION_LEVEL EMULATION_NONE // building Palm OS executable
+ #endif
+
+ #ifndef USE_TRAPS
+ #define USE_TRAPS 1 // use Palm OS traps
+ #endif
+
+ #endif
+
+
+#endif
+
+
+
+/************************************************************
+ * Settings that can be overriden in the makefile (for MPW)
+ * OR (for CodeWarrior) in "AppBuildRules.h". If there is no
+ * local copy of "AppBuildRules.h" within the project directory,
+ * the one in the Incs directory will be used instead.
+ *************************************************************/
+// This default option is probably ok for now
+#ifndef EMULATION_LEVEL
+ #define EMULATION_LEVEL EMULATION_MAC
+#endif
+
+// This default option is probably ok for now
+#if EMULATION_LEVEL == EMULATION_NONE
+ #define MEMORY_TYPE MEMORY_LOCAL
+#endif
+
+// This default option is probably ok for now
+#ifndef MEMORY_TYPE
+ #define MEMORY_TYPE MEMORY_LOCAL
+#endif
+
+// This default option is probably ok for now
+#ifndef ENVIRONMENT
+ #define ENVIRONMENT ENVIRONMENT_CW
+#endif
+
+// This default option is probably ok to leave as a default
+#ifndef PLATFORM_TYPE
+ #define PLATFORM_TYPE PLATFORM_VIEWER
+#endif
+
+#ifndef ERROR_CHECK_LEVEL
+ #define ERROR_CHECK_LEVEL #error "ERROR_CHECK_LEVEL not defined; Try including ''PalmOptErrorCheckLevel.h''!"
+ // The following allows <PalmOptErrorCheckLevel.h> to redefine ERROR_CHECK_LEVEL
+ // without letting it change ERROR_CHECK_LEVEL if it was already defined,
+ // such as would be the case when using a project prefix file...
+ #define ERROR_CHECK_LEVEL_OK_TO_REDEFINE
+#endif
+
+// This default option is probably ok for now
+#ifndef PUBLIC_STUFF_STRIPPED
+#ifndef CPU_TYPE
+ #if defined(__INTEL__) || defined(__i386__)
+ #define CPU_TYPE CPU_x86
+ #elif defined(__POWERPC__) || defined(__powerpc__)
+ #define CPU_TYPE CPU_PPC
+ #elif defined(__arm__)
+ #define CPU_TYPE CPU_ARM
+ #else
+ #define CPU_TYPE CPU_68K
+ #endif
+#endif
+#else // PUBLIC_STUFF_STRIPPED
+#ifndef CPU_TYPE
+ #if defined(__INTEL__) || defined(__i386__)
+ #define CPU_TYPE CPU_x86
+ #else
+ #define CPU_TYPE CPU_68K
+ #endif
+#endif
+#endif // PUBLIC_STUFF_STRIPPED
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// This default option is probably ok for now
+#ifndef CPU_ENDIAN
+ #if (CPU_TYPE == CPU_x86) || (CPU_TYPE == CPU_ARM)
+ #define CPU_ENDIAN CPU_ENDIAN_LITTLE
+ #else
+ #define CPU_ENDIAN CPU_ENDIAN_BIG
+ #endif
+#endif
+#endif // PUBLIC_STUFF_STRIPPED
+
+#ifndef MODEL
+ #define MODEL #error "MODEL not defined; Try including ''PalmOptModel.h''!"
+#endif
+
+// This default option is probably ok to leave as a default
+#ifndef MEMORY_FORCE_LOCK
+ #define MEMORY_FORCE_LOCK MEMORY_FORCE_LOCK_ON
+#endif
+
+// Must be defined (-d or prefix file) before using. See comment in <BuildDefines.h>.
+#ifndef DEBUG_LEVEL
+ #define DEBUG_LEVEL #error "DEBUG_LEVEL must be defined before using!"
+#endif
+
+#ifndef DEFAULT_LIB_ENTRIES
+ #define DEFAULT_LIB_ENTRIES 12 // space for 12 libraries in library table
+#endif
+
+#ifndef USER_MODE
+ #define USER_MODE #error "USER_MODE not defined; Try including ''PalmOptUserMode.h''!"
+#endif
+
+#ifndef INTERNAL_COMMANDS
+ #define INTERNAL_COMMANDS #error "INTERNAL_COMMANDS must be defined before using!"
+#endif
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER - this option should be driven strictly by inclusion or exclusion of a PRC file.
+// jquinn - This was turned on in the old makefiles. It should be on by default.
+// SCL - We should remove all references to this build option and just assume it's "on".
+// Mandalay builds with it "on" in all cases, even in the OS; there's no longer an extension.
+#endif // PUBLIC_STUFF_STRIPPED
+#ifndef INCLUDE_DES
+ #define INCLUDE_DES INCLUDE_DES_ON
+#endif
+
+// Unless otherwise specified, assume CML_ENCODER is off
+#ifndef CML_ENCODER
+ #define CML_ENCODER CML_ENCODER_OFF
+#endif
+
+// Derive the path for resource files.
+#ifndef RESOURCE_FILE_PREFIX
+ #define RESOURCE_FILE_PREFIX ""
+#endif
+
+// LOCALE_SUFFIX is used for the name of merged resource files,
+// and also sys.tres.
+#ifndef LOCALE_SUFFIX
+ #define LOCALE_SUFFIX ""
+#endif
+
+#ifndef PUBLIC_STUFF_STRIPPED
+#ifndef LOCALE
+ #define LOCALE #error "LOCALE not defined; Try including ''PalmOptLocale.h''!"
+ // The following allows <PalmOptLocale.h> to redefine LOCALE
+ // without letting it change LOCALE if it was already defined,
+ // such as would be the case when using a project prefix file...
+ #define LOCALE_OK_TO_REDEFINE
+#endif
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+// Set these according to which Shell commands you want to
+// link with. These are often overridden by other components
+// in a local "AppBuildRules.h" which is currently obsolete.
+#ifndef SHELL_COMMAND_DB
+ #define SHELL_COMMAND_DB 0 // Not Available
+#endif
+
+#ifndef SHELL_COMMAND_UI
+ #define SHELL_COMMAND_UI 1 // Available
+#endif
+
+#ifndef SHELL_COMMAND_APP
+ #define SHELL_COMMAND_APP 1 // Available
+#endif
+
+#ifndef SHELL_COMMAND_EMULATOR
+ #define SHELL_COMMAND_EMULATOR 1 // Available
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef DYN_MEM_SIZE_MAX
+ #define DYN_MEM_SIZE_MAX #error "DYN_MEM_SIZE_MAX is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef SMALL_ROM_SIZE
+ #define SMALL_ROM_SIZE #error "SMALL_ROM_SIZE is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef CONSOLE_SERIAL_LIB
+ #define CONSOLE_SERIAL_LIB #error "CONSOLE_SERIAL_LIB is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef PILOT_SERIAL_MGR
+ // Palm OS 3.5 code now assumes PILOT_SERIAL_MGR == PILOT_SERIAL_MGR_NEW
+ #define PILOT_SERIAL_MGR #error "PILOT_SERIAL_MGR is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef MEMORY_VERSION
+ // Palm OS 3.5 code now assumes MEMORY_VERSION == MEMORY_VERSION_2
+ #define MEMORY_VERSION #error "MEMORY_VERSION is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef GRAPHICS_VERSION
+ // Palm OS 3.5 code now assumes GRAPHICS_VERSION == GRAPHICS_VERSION_2
+ #define GRAPHICS_VERSION #error "GRAPHICS_VERSION is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef HW_TARGET
+ // Palm OS 3.5 is now hardware independent; HAL should handle this
+ #define HW_TARGET #error "HW_TARGET is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef HW_REV
+ // Palm OS 3.5 is now hardware independent; HAL should handle this
+ #define HW_REV #error "HW_REV is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef RMP_LIB_INCLUDE
+ #define RMP_LIB_INCLUDE #error "RMP_LIB_INCLUDE is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+#ifndef OEM_PRODUCT
+ #define OEM_PRODUCT #error "OEM_PRODUCT is an obsolete build flag!"
+#endif
+
+// Obsolete option; this is left here to catch any stragglers (test code, etc.)...
+// LANGUAGE/COUNTRY are no longer supported. If absolutely necessary, use LOCALE instead, but
+// build-time dependencies on the target LOCALE are a _really_ bad idea.
+#ifdef LANGUAGE
+ #undef LANGUAGE
+#endif
+#define LANGUAGE #error "LANGUAGE is now obsolete; use LOCALE and include PalmOptLocale.h"
+
+#ifndef COUNTRY
+ #undef COUNTRY
+#endif
+#define COUNTRY #error "COUNTRY is now obsolete; use LOCALE and include PalmOptLocale.h"
+
+// Moved to <PalmTypes.h>:
+//#if defined(__GNUC__) && defined(__UNIX__)
+// // Ensure that structure elements are 16-bit aligned
+// #pragma pack(2)
+//#endif
+
+#endif
diff --git a/SrcShared/Palm/Platform/Incs/BuildDefines.h b/SrcShared/Palm/Platform/Incs/BuildDefines.h
new file mode 100644
index 0000000..3f0f17d
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/BuildDefines.h
@@ -0,0 +1,159 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: BuildDefines.h
+ *
+ * Description:
+ * Build variable defines for Palm OS.
+ *
+ * This file is included by <BuildDefaults.h>.
+ * It should be included by any local component that wishes
+ * to override any system default compile-time switches.
+ * For more details, refer to <BuildDefaults.h>.
+ *
+ * This file supercedes the old <BuildRules.h> file.
+ *
+ * History:
+ * 07/16/99 SCL So many changes the old history is obsolete.
+ * 07/29/99 kwk Deleted TEXT_SERVICES & INTERNATIONAL_MGR & VENDOR.
+ * 10/04/99 grant Added LOCALE definitions.
+ *
+ *****************************************************************************/
+
+#ifndef __BUILDDEFINES_H__
+#define __BUILDDEFINES_H__
+
+
+/************************************************************
+ * Compilation Control Options
+ *************************************************************/
+
+// The makefile should set the define EMULATION_LEVEL to one of the following
+// constants:
+#define EMULATION_NONE 0 // native environment
+#define EMULATION_WINDOWS 1 // emulate on Windows
+#define EMULATION_DOS 2 // emulate on DOS
+#define EMULATION_MAC 3 // emulate on Macintosh
+#define EMULATION_UNIX 4 // emulate on Linux
+
+
+// If emulation is not EMULATION_NONE, the following define controls
+// whether we are talking to a touchdown device over the serial port,
+// or if we are emulating a memory card in local RAM.
+//
+// The makefile should set the define MEMORY_TYPE to one of the following
+// constants
+#define MEMORY_LOCAL 0 // Emulate using local memory card image
+#define MEMORY_REMOTE 1 // Pass calls through serial port to the device
+
+
+// The makefile should set the define ENVIRONMENT to one of the following:
+#define ENVIRONMENT_CW 0 // CodeWarrior compiler/linker (IDE or MPW)
+#define ENVIRONMENT_MPW 1 // Apple's MPW compiler/linker
+
+
+// The makefile should set the define PLATFORM_TYPE to one of the following
+// constants:
+#define PLATFORM_VIEWER 0 // PalmPilot Viewer
+#define PLATFORM_SERVER 1 // Server code
+
+
+// The makefile should set the define ERROR_CHECK_LEVEL to one of the
+// following constants:
+#define ERROR_CHECK_NONE 0 // compile no error checking code
+#define ERROR_CHECK_PARTIAL 1 // display for fatal errors only
+#define ERROR_CHECK_FULL 2 // display fatal or non-fatal errors
+
+
+// The makefile should set the define CPU_TYPE to one of the
+// following constants:
+#define CPU_68K 0 // Motorola 68K type
+#define CPU_x86 1 // Intel x86 type
+#ifndef PUBLIC_STUFF_STRIPPED
+#define CPU_PPC 2 // Motorola/IBM PowerPC type
+#define CPU_ARM 3 // ARM type
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// The makefile should set the define CPU_ENDIAN to one of the following:
+// Note: its not just a define because some processors support both.
+// If CPU_ENDIAN is not defined in the makefile then a default is set
+// based on the CPU_TYPE.
+#define CPU_ENDIAN_BIG 0 // Big endian
+#define CPU_ENDIAN_LITTLE 1 // Little endian
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+// The makefile should set the define MODEL to one of the
+// following constants. This equate is currently only use by
+// special purpose applications like Setup that need to install different
+// files for each type of product. Normally, model dependent behavior
+// should be run-time based off of Features using FtrGet().
+#define MODEL_GENERIC 0 // Not one of the specific models that follow
+#define MODEL_ELEVEN 1 // Eleven (Palm Seven)
+#define MODEL_SUMO 2 // EZ product
+
+
+// The makefile should set the define MEMORY_FORCE_LOCK to one of the
+// following.
+#define MEMORY_FORCE_LOCK_OFF 0 // Don't force all handles to be locked
+#define MEMORY_FORCE_LOCK_ON 1 // Force all handles to be locked before usage
+
+
+// The makefile should set the define DEBUG_LEVEL to one of the
+// following. THIS DEFINE IS ONLY USED BY A COUPLE MODULES SO WE
+// DON'T GIVE IT A DEFAULT VALUE BELOW...
+// ANY MODULE THAT USES THIS DEFINE SHOULD VERIFY THAT IT IS DEFINED!!
+#define DEBUG_LEVEL_NONE 1 // None: Does not auto-launch Console or Debugger
+#define DEBUG_LEVEL_PARTIAL 2 // Partial: Auto-Launches Console but skips debugger
+#define DEBUG_LEVEL_FULL 3 // Full: Waits in debugger on reset
+
+
+// The makefile should set the define DEFAULT_DATA to one of the following:
+// Setting this define to USE_DEFAULT_DATA will cause the core apps to include default
+// data in the build.
+#define DO_NOT_USE_DEFAULT_DATA 0
+#define USE_DEFAULT_DATA 1
+
+
+// The makefile should set the define USER_MODE to one of the
+// following constants:
+#define USER_MODE_NORMAL 0 // normal operation
+#define USER_MODE_DEMO 1 // demo mode - Graffiti and pop-up keyboard disabled
+
+
+// The makefile should set the define INTERNAL_COMMANDS to one of the
+// following constants:
+#define INTERNAL_COMMANDS_EXCLUDE 0
+#define INTERNAL_COMMANDS_INCLUDE 1 // Include internal shell commands
+
+
+// The makefile should set the define INCLUDE_DES to one of the
+// following constants:
+#define INCLUDE_DES_OFF 0
+#define INCLUDE_DES_ON 1 // include it
+
+
+// Used by Net Library to link in the CML encoder
+#define CML_ENCODER_OFF 0
+#define CML_ENCODER_ON 1
+
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// The PalmOptLocale.h file defines LOCALE to be one of these.
+// WARNING!!! Use of LOCALE implies non-international code and/or builds,
+// which is a VERY BAD thing. LOCALE should ONLY be used as a last
+// resort!!!!
+#define LOCALE_enUS 0
+#define LOCALE_deDE 1
+#define LOCALE_esES 2
+#define LOCALE_frFR 3
+#define LOCALE_itIT 4
+#define LOCALE_jpJP 5
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+#endif
diff --git a/SrcShared/Palm/Platform/Incs/Core/CoreTraps.h b/SrcShared/Palm/Platform/Incs/Core/CoreTraps.h
new file mode 100644
index 0000000..93139f4
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/CoreTraps.h
@@ -0,0 +1,1505 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-2000 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: CoreTraps.h
+ *
+ * Release:
+ *
+ * Description:
+ * Palm OS core trap numbers
+ *
+ * History:
+ * 06/13/95 Created by Ron Marianetti
+ * 06/13/95 RM Created by Ron Marianetti
+ * ??/??/?? ??? Added Rocky changes
+ * 02/04/98 srj Added Hardware LCD Contrast Trap for Razor
+ * 05/05/98 art Reused sysTrapPsrInit, new name sysTrapIntlDispatch.
+ * 06/17/98 jhl mapped NVPrefs to FlashMgr stuff
+ * 07/03/98 kwk Added WinDrawChar, WinDrawTruncChars, and
+ * FntWidthToOffset for Instant Karma.
+ * 07/07/98 srj Added System LCD Contrast Trap for Razor
+ * 08/05/98 scl Cross-merged Razor's SysTraps with Main's
+ * 09/07/98 kwk Added SysWantEvent, EvtPeekEvent traps for
+ * Instant Karma/Razor.
+ * 09/18/98 scl Cross-merged Razor's SysTraps with Main's
+ * 10/13/98 kwk Removed EvtPeekEvent trap.
+ * 10/28/98 scl Cross-merged Razor's SysTraps with Main's
+ * 10/29/98 Bob Move FtrPtr* traps from 3.2 to 3.1
+ * 05/21/99 kwk Added TsmDispatch and OmDispatch traps.
+ * 06/30/99 CS Added DmOpenDBNoOverlay and ResLoadConstant traps.
+ * 07/01/99 kwk Added DmOpenDBWithLocale trap.
+ * 07/09/99 kwk Added HwrGetSilkscreenIID trap.
+ * 07/12/99 kwk Added SysFatalAlertInit trap.
+ * 07/15/99 kwk Added EvtGetSilkscreenAreaList trap.
+ * 07/15/99 bob Moved macros to PalmTypes.h, moved library stuff to LibTraps.h.
+ * 07/28/99 kwk Added DateTemplateToAscii trap.
+ * 09/14/99 gap Removed EvtGetTrapState.
+ * 09/14/99 jed Renamed NotifyMgr trap constants.
+ * 09/16/99 jmp Noted that old Floating Point traps are maintained for
+ * for backwards compatibility only -- i.e., FloatMgr.h now specifies
+ * the new Floating Point dispatched traps.
+ * 09/22/99 jmp Added MenuEraseMenu trap; we won't be creating any public headers
+ * for this routine in 3.5, but we needed to externalize the routine
+ * to fix 3.5-specific issues.
+ * 11/22/00 bob Added FldSetMaxVisibleLines trap
+ *
+ *****************************************************************************/
+
+ #ifndef __CORETRAPS_H_
+ #define __CORETRAPS_H_
+
+// Include elementary types
+#include <PalmTypes.h>
+
+#if CPU_TYPE == CPU_68K
+#include <M68KHwr.h>
+#endif
+
+// Regular traps start here and go up by 1's
+#define sysTrapBase 0xA000
+
+
+#define sysTrapMemInit 0xA000
+#define sysTrapMemInitHeapTable 0xA001
+#define sysTrapMemStoreInit 0xA002
+#define sysTrapMemCardFormat 0xA003
+#define sysTrapMemCardInfo 0xA004
+#define sysTrapMemStoreInfo 0xA005
+#define sysTrapMemStoreSetInfo 0xA006
+#define sysTrapMemNumHeaps 0xA007
+#define sysTrapMemNumRAMHeaps 0xA008
+#define sysTrapMemHeapID 0xA009
+#define sysTrapMemHeapPtr 0xA00A
+#define sysTrapMemHeapFreeBytes 0xA00B
+#define sysTrapMemHeapSize 0xA00C
+#define sysTrapMemHeapFlags 0xA00D
+#define sysTrapMemHeapCompact 0xA00E
+#define sysTrapMemHeapInit 0xA00F
+#define sysTrapMemHeapFreeByOwnerID 0xA010
+#define sysTrapMemChunkNew 0xA011
+#define sysTrapMemChunkFree 0xA012
+#define sysTrapMemPtrNew 0xA013
+#define sysTrapMemPtrRecoverHandle 0xA014
+#define sysTrapMemPtrFlags 0xA015
+#define sysTrapMemPtrSize 0xA016
+#define sysTrapMemPtrOwner 0xA017
+#define sysTrapMemPtrHeapID 0xA018
+#define sysTrapMemPtrCardNo 0xA019
+#define sysTrapMemPtrToLocalID 0xA01A
+#define sysTrapMemPtrSetOwner 0xA01B
+#define sysTrapMemPtrResize 0xA01C
+#define sysTrapMemPtrResetLock 0xA01D
+#define sysTrapMemHandleNew 0xA01E
+#define sysTrapMemHandleLockCount 0xA01F
+#define sysTrapMemHandleToLocalID 0xA020
+#define sysTrapMemHandleLock 0xA021
+#define sysTrapMemHandleUnlock 0xA022
+#define sysTrapMemLocalIDToGlobal 0xA023
+#define sysTrapMemLocalIDKind 0xA024
+#define sysTrapMemLocalIDToPtr 0xA025
+#define sysTrapMemMove 0xA026
+#define sysTrapMemSet 0xA027
+#define sysTrapMemStoreSearch 0xA028
+#define sysTrapSysReserved10Trap1 0xA029 /* "Reserved" trap in Palm OS 1.0 and later (was sysTrapMemPtrDataStorage) */
+
+#define sysTrapMemKernelInit 0xA02A
+#define sysTrapMemHandleFree 0xA02B
+#define sysTrapMemHandleFlags 0xA02C
+#define sysTrapMemHandleSize 0xA02D
+#define sysTrapMemHandleOwner 0xA02E
+#define sysTrapMemHandleHeapID 0xA02F
+#define sysTrapMemHandleDataStorage 0xA030
+#define sysTrapMemHandleCardNo 0xA031
+#define sysTrapMemHandleSetOwner 0xA032
+#define sysTrapMemHandleResize 0xA033
+#define sysTrapMemHandleResetLock 0xA034
+#define sysTrapMemPtrUnlock 0xA035
+#define sysTrapMemLocalIDToLockedPtr 0xA036
+#define sysTrapMemSetDebugMode 0xA037
+#define sysTrapMemHeapScramble 0xA038
+#define sysTrapMemHeapCheck 0xA039
+#define sysTrapMemNumCards 0xA03A
+#define sysTrapMemDebugMode 0xA03B
+#define sysTrapMemSemaphoreReserve 0xA03C
+#define sysTrapMemSemaphoreRelease 0xA03D
+#define sysTrapMemHeapDynamic 0xA03E
+#define sysTrapMemNVParams 0xA03F
+
+
+#define sysTrapDmInit 0xA040
+#define sysTrapDmCreateDatabase 0xA041
+#define sysTrapDmDeleteDatabase 0xA042
+#define sysTrapDmNumDatabases 0xA043
+#define sysTrapDmGetDatabase 0xA044
+#define sysTrapDmFindDatabase 0xA045
+#define sysTrapDmDatabaseInfo 0xA046
+#define sysTrapDmSetDatabaseInfo 0xA047
+#define sysTrapDmDatabaseSize 0xA048
+#define sysTrapDmOpenDatabase 0xA049
+#define sysTrapDmCloseDatabase 0xA04A
+#define sysTrapDmNextOpenDatabase 0xA04B
+#define sysTrapDmOpenDatabaseInfo 0xA04C
+#define sysTrapDmResetRecordStates 0xA04D
+#define sysTrapDmGetLastErr 0xA04E
+#define sysTrapDmNumRecords 0xA04F
+#define sysTrapDmRecordInfo 0xA050
+#define sysTrapDmSetRecordInfo 0xA051
+#define sysTrapDmAttachRecord 0xA052
+#define sysTrapDmDetachRecord 0xA053
+#define sysTrapDmMoveRecord 0xA054
+#define sysTrapDmNewRecord 0xA055
+#define sysTrapDmRemoveRecord 0xA056
+#define sysTrapDmDeleteRecord 0xA057
+#define sysTrapDmArchiveRecord 0xA058
+#define sysTrapDmNewHandle 0xA059
+#define sysTrapDmRemoveSecretRecords 0xA05A
+#define sysTrapDmQueryRecord 0xA05B
+#define sysTrapDmGetRecord 0xA05C
+#define sysTrapDmResizeRecord 0xA05D
+#define sysTrapDmReleaseRecord 0xA05E
+#define sysTrapDmGetResource 0xA05F
+#define sysTrapDmGet1Resource 0xA060
+#define sysTrapDmReleaseResource 0xA061
+#define sysTrapDmResizeResource 0xA062
+#define sysTrapDmNextOpenResDatabase 0xA063
+#define sysTrapDmFindResourceType 0xA064
+#define sysTrapDmFindResource 0xA065
+#define sysTrapDmSearchResource 0xA066
+#define sysTrapDmNumResources 0xA067
+#define sysTrapDmResourceInfo 0xA068
+#define sysTrapDmSetResourceInfo 0xA069
+#define sysTrapDmAttachResource 0xA06A
+#define sysTrapDmDetachResource 0xA06B
+#define sysTrapDmNewResource 0xA06C
+#define sysTrapDmRemoveResource 0xA06D
+#define sysTrapDmGetResourceIndex 0xA06E
+#define sysTrapDmQuickSort 0xA06F
+#define sysTrapDmQueryNextInCategory 0xA070
+#define sysTrapDmNumRecordsInCategory 0xA071
+#define sysTrapDmPositionInCategory 0xA072
+#define sysTrapDmSeekRecordInCategory 0xA073
+#define sysTrapDmMoveCategory 0xA074
+#define sysTrapDmOpenDatabaseByTypeCreator 0xA075
+#define sysTrapDmWrite 0xA076
+#define sysTrapDmStrCopy 0xA077
+#define sysTrapDmGetNextDatabaseByTypeCreator 0xA078
+#define sysTrapDmWriteCheck 0xA079
+#define sysTrapDmMoveOpenDBContext 0xA07A
+#define sysTrapDmFindRecordByID 0xA07B
+#define sysTrapDmGetAppInfoID 0xA07C
+#define sysTrapDmFindSortPositionV10 0xA07D
+#define sysTrapDmSet 0xA07E
+#define sysTrapDmCreateDatabaseFromImage 0xA07F
+
+
+#define sysTrapDbgSrcMessage 0xA080
+#define sysTrapDbgMessage 0xA081
+#define sysTrapDbgGetMessage 0xA082
+#define sysTrapDbgCommSettings 0xA083
+
+#define sysTrapErrDisplayFileLineMsg 0xA084
+#define sysTrapErrSetJump 0xA085
+#define sysTrapErrLongJump 0xA086
+#define sysTrapErrThrow 0xA087
+#define sysTrapErrExceptionList 0xA088
+
+#define sysTrapSysBroadcastActionCode 0xA089
+#define sysTrapSysUnimplemented 0xA08A
+#define sysTrapSysColdBoot 0xA08B
+#define sysTrapSysReset 0xA08C
+#define sysTrapSysDoze 0xA08D
+#define sysTrapSysAppLaunch 0xA08E
+#define sysTrapSysAppStartup 0xA08F
+#define sysTrapSysAppExit 0xA090
+#define sysTrapSysSetA5 0xA091
+#define sysTrapSysSetTrapAddress 0xA092
+#define sysTrapSysGetTrapAddress 0xA093
+#define sysTrapSysTranslateKernelErr 0xA094
+#define sysTrapSysSemaphoreCreate 0xA095
+#define sysTrapSysSemaphoreDelete 0xA096
+#define sysTrapSysSemaphoreWait 0xA097
+#define sysTrapSysSemaphoreSignal 0xA098
+#define sysTrapSysTimerCreate 0xA099
+#define sysTrapSysTimerWrite 0xA09A
+#define sysTrapSysTaskCreate 0xA09B
+#define sysTrapSysTaskDelete 0xA09C
+#define sysTrapSysTaskTrigger 0xA09D
+#define sysTrapSysTaskID 0xA09E
+#define sysTrapSysTaskUserInfoPtr 0xA09F
+#define sysTrapSysTaskDelay 0xA0A0
+#define sysTrapSysTaskSetTermProc 0xA0A1
+#define sysTrapSysUILaunch 0xA0A2
+#define sysTrapSysNewOwnerID 0xA0A3
+#define sysTrapSysSemaphoreSet 0xA0A4
+#define sysTrapSysDisableInts 0xA0A5
+#define sysTrapSysRestoreStatus 0xA0A6
+#define sysTrapSysUIAppSwitch 0xA0A7
+#define sysTrapSysCurAppInfoPV20 0xA0A8
+#define sysTrapSysHandleEvent 0xA0A9
+#define sysTrapSysInit 0xA0AA
+#define sysTrapSysQSort 0xA0AB
+#define sysTrapSysCurAppDatabase 0xA0AC
+#define sysTrapSysFatalAlert 0xA0AD
+#define sysTrapSysResSemaphoreCreate 0xA0AE
+#define sysTrapSysResSemaphoreDelete 0xA0AF
+#define sysTrapSysResSemaphoreReserve 0xA0B0
+#define sysTrapSysResSemaphoreRelease 0xA0B1
+#define sysTrapSysSleep 0xA0B2
+#define sysTrapSysKeyboardDialogV10 0xA0B3
+#define sysTrapSysAppLauncherDialog 0xA0B4
+#define sysTrapSysSetPerformance 0xA0B5
+#define sysTrapSysBatteryInfoV20 0xA0B6
+#define sysTrapSysLibInstall 0xA0B7
+#define sysTrapSysLibRemove 0xA0B8
+#define sysTrapSysLibTblEntry 0xA0B9
+#define sysTrapSysLibFind 0xA0BA
+#define sysTrapSysBatteryDialog 0xA0BB
+#define sysTrapSysCopyStringResource 0xA0BC
+#define sysTrapSysKernelInfo 0xA0BD
+#define sysTrapSysLaunchConsole 0xA0BE
+#define sysTrapSysTimerDelete 0xA0BF
+#define sysTrapSysSetAutoOffTime 0xA0C0
+#define sysTrapSysFormPointerArrayToStrings 0xA0C1
+#define sysTrapSysRandom 0xA0C2
+#define sysTrapSysTaskSwitching 0xA0C3
+#define sysTrapSysTimerRead 0xA0C4
+
+
+#define sysTrapStrCopy 0xA0C5
+#define sysTrapStrCat 0xA0C6
+#define sysTrapStrLen 0xA0C7
+#define sysTrapStrCompare 0xA0C8
+#define sysTrapStrIToA 0xA0C9
+#define sysTrapStrCaselessCompare 0xA0CA
+#define sysTrapStrIToH 0xA0CB
+#define sysTrapStrChr 0xA0CC
+#define sysTrapStrStr 0xA0CD
+#define sysTrapStrAToI 0xA0CE
+#define sysTrapStrToLower 0xA0CF
+
+#define sysTrapSerReceiveISP 0xA0D0
+
+#define sysTrapSlkOpen 0xA0D1
+#define sysTrapSlkClose 0xA0D2
+#define sysTrapSlkOpenSocket 0xA0D3
+#define sysTrapSlkCloseSocket 0xA0D4
+#define sysTrapSlkSocketRefNum 0xA0D5
+#define sysTrapSlkSocketSetTimeout 0xA0D6
+#define sysTrapSlkFlushSocket 0xA0D7
+#define sysTrapSlkSetSocketListener 0xA0D8
+#define sysTrapSlkSendPacket 0xA0D9
+#define sysTrapSlkReceivePacket 0xA0DA
+#define sysTrapSlkSysPktDefaultResponse 0xA0DB
+#define sysTrapSlkProcessRPC 0xA0DC
+
+
+#define sysTrapConPutS 0xA0DD
+#define sysTrapConGetS 0xA0DE
+
+#define sysTrapFplInit 0xA0DF /* Obsolete, here for compatibilty only! */
+#define sysTrapFplFree 0xA0E0 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplFToA 0xA0E1 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplAToF 0xA0E2 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplBase10Info 0xA0E3 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplLongToFloat 0xA0E4 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplFloatToLong 0xA0E5 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplFloatToULong 0xA0E6 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplMul 0xA0E7 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplAdd 0xA0E8 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplSub 0xA0E9 /* Obsolete, here for compatibilty only! */
+#define sysTrapFplDiv 0xA0EA /* Obsolete, here for compatibilty only! */
+
+#define sysTrapWinScreenInit 0xA0EB /* was sysTrapScrInit */
+#define sysTrapScrCopyRectangle 0xA0EC
+#define sysTrapScrDrawChars 0xA0ED
+#define sysTrapScrLineRoutine 0xA0EE
+#define sysTrapScrRectangleRoutine 0xA0EF
+#define sysTrapScrScreenInfo 0xA0F0
+#define sysTrapScrDrawNotify 0xA0F1
+#define sysTrapScrSendUpdateArea 0xA0F2
+#define sysTrapScrCompressScanLine 0xA0F3
+#define sysTrapScrDeCompressScanLine 0xA0F4
+
+
+#define sysTrapTimGetSeconds 0xA0F5
+#define sysTrapTimSetSeconds 0xA0F6
+#define sysTrapTimGetTicks 0xA0F7
+#define sysTrapTimInit 0xA0F8
+#define sysTrapTimSetAlarm 0xA0F9
+#define sysTrapTimGetAlarm 0xA0FA
+#define sysTrapTimHandleInterrupt 0xA0FB
+#define sysTrapTimSecondsToDateTime 0xA0FC
+#define sysTrapTimDateTimeToSeconds 0xA0FD
+#define sysTrapTimAdjust 0xA0FE
+#define sysTrapTimSleep 0xA0FF
+#define sysTrapTimWake 0xA100
+
+#define sysTrapCategoryCreateListV10 0xA101
+#define sysTrapCategoryFreeListV10 0xA102
+#define sysTrapCategoryFind 0xA103
+#define sysTrapCategoryGetName 0xA104
+#define sysTrapCategoryEditV10 0xA105
+#define sysTrapCategorySelectV10 0xA106
+#define sysTrapCategoryGetNext 0xA107
+#define sysTrapCategorySetTriggerLabel 0xA108
+#define sysTrapCategoryTruncateName 0xA109
+
+#define sysTrapClipboardAddItem 0xA10A
+#define sysTrapClipboardCheckIfItemExist 0xA10B
+#define sysTrapClipboardGetItem 0xA10C
+
+#define sysTrapCtlDrawControl 0xA10D
+#define sysTrapCtlEraseControl 0xA10E
+#define sysTrapCtlHideControl 0xA10F
+#define sysTrapCtlShowControl 0xA110
+#define sysTrapCtlGetValue 0xA111
+#define sysTrapCtlSetValue 0xA112
+#define sysTrapCtlGetLabel 0xA113
+#define sysTrapCtlSetLabel 0xA114
+#define sysTrapCtlHandleEvent 0xA115
+#define sysTrapCtlHitControl 0xA116
+#define sysTrapCtlSetEnabled 0xA117
+#define sysTrapCtlSetUsable 0xA118
+#define sysTrapCtlEnabled 0xA119
+
+
+#define sysTrapEvtInitialize 0xA11A
+#define sysTrapEvtAddEventToQueue 0xA11B
+#define sysTrapEvtCopyEvent 0xA11C
+#define sysTrapEvtGetEvent 0xA11D
+#define sysTrapEvtGetPen 0xA11E
+#define sysTrapEvtSysInit 0xA11F
+#define sysTrapEvtGetSysEvent 0xA120
+#define sysTrapEvtProcessSoftKeyStroke 0xA121
+#define sysTrapEvtGetPenBtnList 0xA122
+#define sysTrapEvtSetPenQueuePtr 0xA123
+#define sysTrapEvtPenQueueSize 0xA124
+#define sysTrapEvtFlushPenQueue 0xA125
+#define sysTrapEvtEnqueuePenPoint 0xA126
+#define sysTrapEvtDequeuePenStrokeInfo 0xA127
+#define sysTrapEvtDequeuePenPoint 0xA128
+#define sysTrapEvtFlushNextPenStroke 0xA129
+#define sysTrapEvtSetKeyQueuePtr 0xA12A
+#define sysTrapEvtKeyQueueSize 0xA12B
+#define sysTrapEvtFlushKeyQueue 0xA12C
+#define sysTrapEvtEnqueueKey 0xA12D
+#define sysTrapEvtDequeueKeyEvent 0xA12E
+#define sysTrapEvtWakeup 0xA12F
+#define sysTrapEvtResetAutoOffTimer 0xA130
+#define sysTrapEvtKeyQueueEmpty 0xA131
+#define sysTrapEvtEnableGraffiti 0xA132
+
+
+#define sysTrapFldCopy 0xA133
+#define sysTrapFldCut 0xA134
+#define sysTrapFldDrawField 0xA135
+#define sysTrapFldEraseField 0xA136
+#define sysTrapFldFreeMemory 0xA137
+#define sysTrapFldGetBounds 0xA138
+#define sysTrapFldGetTextPtr 0xA139
+#define sysTrapFldGetSelection 0xA13A
+#define sysTrapFldHandleEvent 0xA13B
+#define sysTrapFldPaste 0xA13C
+#define sysTrapFldRecalculateField 0xA13D
+#define sysTrapFldSetBounds 0xA13E
+#define sysTrapFldSetText 0xA13F
+#define sysTrapFldGetFont 0xA140
+#define sysTrapFldSetFont 0xA141
+#define sysTrapFldSetSelection 0xA142
+#define sysTrapFldGrabFocus 0xA143
+#define sysTrapFldReleaseFocus 0xA144
+#define sysTrapFldGetInsPtPosition 0xA145
+#define sysTrapFldSetInsPtPosition 0xA146
+#define sysTrapFldSetScrollPosition 0xA147
+#define sysTrapFldGetScrollPosition 0xA148
+#define sysTrapFldGetTextHeight 0xA149
+#define sysTrapFldGetTextAllocatedSize 0xA14A
+#define sysTrapFldGetTextLength 0xA14B
+#define sysTrapFldScrollField 0xA14C
+#define sysTrapFldScrollable 0xA14D
+#define sysTrapFldGetVisibleLines 0xA14E
+#define sysTrapFldGetAttributes 0xA14F
+#define sysTrapFldSetAttributes 0xA150
+#define sysTrapFldSendChangeNotification 0xA151
+#define sysTrapFldCalcFieldHeight 0xA152
+#define sysTrapFldGetTextHandle 0xA153
+#define sysTrapFldCompactText 0xA154
+#define sysTrapFldDirty 0xA155
+#define sysTrapFldWordWrap 0xA156
+#define sysTrapFldSetTextAllocatedSize 0xA157
+#define sysTrapFldSetTextHandle 0xA158
+#define sysTrapFldSetTextPtr 0xA159
+#define sysTrapFldGetMaxChars 0xA15A
+#define sysTrapFldSetMaxChars 0xA15B
+#define sysTrapFldSetUsable 0xA15C
+#define sysTrapFldInsert 0xA15D
+#define sysTrapFldDelete 0xA15E
+#define sysTrapFldUndo 0xA15F
+#define sysTrapFldSetDirty 0xA160
+#define sysTrapFldSendHeightChangeNotification 0xA161
+#define sysTrapFldMakeFullyVisible 0xA162
+
+
+#define sysTrapFntGetFont 0xA163
+#define sysTrapFntSetFont 0xA164
+#define sysTrapFntGetFontPtr 0xA165
+#define sysTrapFntBaseLine 0xA166
+#define sysTrapFntCharHeight 0xA167
+#define sysTrapFntLineHeight 0xA168
+#define sysTrapFntAverageCharWidth 0xA169
+#define sysTrapFntCharWidth 0xA16A
+#define sysTrapFntCharsWidth 0xA16B
+#define sysTrapFntDescenderHeight 0xA16C
+#define sysTrapFntCharsInWidth 0xA16D
+#define sysTrapFntLineWidth 0xA16E
+
+
+#define sysTrapFrmInitForm 0xA16F
+#define sysTrapFrmDeleteForm 0xA170
+#define sysTrapFrmDrawForm 0xA171
+#define sysTrapFrmEraseForm 0xA172
+#define sysTrapFrmGetActiveForm 0xA173
+#define sysTrapFrmSetActiveForm 0xA174
+#define sysTrapFrmGetActiveFormID 0xA175
+#define sysTrapFrmGetUserModifiedState 0xA176
+#define sysTrapFrmSetNotUserModified 0xA177
+#define sysTrapFrmGetFocus 0xA178
+#define sysTrapFrmSetFocus 0xA179
+#define sysTrapFrmHandleEvent 0xA17A
+#define sysTrapFrmGetFormBounds 0xA17B
+#define sysTrapFrmGetWindowHandle 0xA17C
+#define sysTrapFrmGetFormId 0xA17D
+#define sysTrapFrmGetFormPtr 0xA17E
+#define sysTrapFrmGetNumberOfObjects 0xA17F
+#define sysTrapFrmGetObjectIndex 0xA180
+#define sysTrapFrmGetObjectId 0xA181
+#define sysTrapFrmGetObjectType 0xA182
+#define sysTrapFrmGetObjectPtr 0xA183
+#define sysTrapFrmHideObject 0xA184
+#define sysTrapFrmShowObject 0xA185
+#define sysTrapFrmGetObjectPosition 0xA186
+#define sysTrapFrmSetObjectPosition 0xA187
+#define sysTrapFrmGetControlValue 0xA188
+#define sysTrapFrmSetControlValue 0xA189
+#define sysTrapFrmGetControlGroupSelection 0xA18A
+#define sysTrapFrmSetControlGroupSelection 0xA18B
+#define sysTrapFrmCopyLabel 0xA18C
+#define sysTrapFrmSetLabel 0xA18D
+#define sysTrapFrmGetLabel 0xA18E
+#define sysTrapFrmSetCategoryLabel 0xA18F
+#define sysTrapFrmGetTitle 0xA190
+#define sysTrapFrmSetTitle 0xA191
+#define sysTrapFrmAlert 0xA192
+#define sysTrapFrmDoDialog 0xA193
+#define sysTrapFrmCustomAlert 0xA194
+#define sysTrapFrmHelp 0xA195
+#define sysTrapFrmUpdateScrollers 0xA196
+#define sysTrapFrmGetFirstForm 0xA197
+#define sysTrapFrmVisible 0xA198
+#define sysTrapFrmGetObjectBounds 0xA199
+#define sysTrapFrmCopyTitle 0xA19A
+#define sysTrapFrmGotoForm 0xA19B
+#define sysTrapFrmPopupForm 0xA19C
+#define sysTrapFrmUpdateForm 0xA19D
+#define sysTrapFrmReturnToForm 0xA19E
+#define sysTrapFrmSetEventHandler 0xA19F
+#define sysTrapFrmDispatchEvent 0xA1A0
+#define sysTrapFrmCloseAllForms 0xA1A1
+#define sysTrapFrmSaveAllForms 0xA1A2
+#define sysTrapFrmGetGadgetData 0xA1A3
+#define sysTrapFrmSetGadgetData 0xA1A4
+#define sysTrapFrmSetCategoryTrigger 0xA1A5
+
+
+#define sysTrapUIInitialize 0xA1A6
+#define sysTrapUIReset 0xA1A7
+
+#define sysTrapInsPtInitialize 0xA1A8
+#define sysTrapInsPtSetLocation 0xA1A9
+#define sysTrapInsPtGetLocation 0xA1AA
+#define sysTrapInsPtEnable 0xA1AB
+#define sysTrapInsPtEnabled 0xA1AC
+#define sysTrapInsPtSetHeight 0xA1AD
+#define sysTrapInsPtGetHeight 0xA1AE
+#define sysTrapInsPtCheckBlink 0xA1AF
+
+#define sysTrapLstSetDrawFunction 0xA1B0
+#define sysTrapLstDrawList 0xA1B1
+#define sysTrapLstEraseList 0xA1B2
+#define sysTrapLstGetSelection 0xA1B3
+#define sysTrapLstGetSelectionText 0xA1B4
+#define sysTrapLstHandleEvent 0xA1B5
+#define sysTrapLstSetHeight 0xA1B6
+#define sysTrapLstSetSelection 0xA1B7
+#define sysTrapLstSetListChoices 0xA1B8
+#define sysTrapLstMakeItemVisible 0xA1B9
+#define sysTrapLstGetNumberOfItems 0xA1BA
+#define sysTrapLstPopupList 0xA1BB
+#define sysTrapLstSetPosition 0xA1BC
+
+#define sysTrapMenuInit 0xA1BD
+#define sysTrapMenuDispose 0xA1BE
+#define sysTrapMenuHandleEvent 0xA1BF
+#define sysTrapMenuDrawMenu 0xA1C0
+#define sysTrapMenuEraseStatus 0xA1C1
+#define sysTrapMenuGetActiveMenu 0xA1C2
+#define sysTrapMenuSetActiveMenu 0xA1C3
+
+
+#define sysTrapRctSetRectangle 0xA1C4
+#define sysTrapRctCopyRectangle 0xA1C5
+#define sysTrapRctInsetRectangle 0xA1C6
+#define sysTrapRctOffsetRectangle 0xA1C7
+#define sysTrapRctPtInRectangle 0xA1C8
+#define sysTrapRctGetIntersection 0xA1C9
+
+
+#define sysTrapTblDrawTable 0xA1CA
+#define sysTrapTblEraseTable 0xA1CB
+#define sysTrapTblHandleEvent 0xA1CC
+#define sysTrapTblGetItemBounds 0xA1CD
+#define sysTrapTblSelectItem 0xA1CE
+#define sysTrapTblGetItemInt 0xA1CF
+#define sysTrapTblSetItemInt 0xA1D0
+#define sysTrapTblSetItemStyle 0xA1D1
+#define sysTrapTblUnhighlightSelection 0xA1D2
+#define sysTrapTblSetRowUsable 0xA1D3
+#define sysTrapTblGetNumberOfRows 0xA1D4
+#define sysTrapTblSetCustomDrawProcedure 0xA1D5
+#define sysTrapTblSetRowSelectable 0xA1D6
+#define sysTrapTblRowSelectable 0xA1D7
+#define sysTrapTblSetLoadDataProcedure 0xA1D8
+#define sysTrapTblSetSaveDataProcedure 0xA1D9
+#define sysTrapTblGetBounds 0xA1DA
+#define sysTrapTblSetRowHeight 0xA1DB
+#define sysTrapTblGetColumnWidth 0xA1DC
+#define sysTrapTblGetRowID 0xA1DD
+#define sysTrapTblSetRowID 0xA1DE
+#define sysTrapTblMarkRowInvalid 0xA1DF
+#define sysTrapTblMarkTableInvalid 0xA1E0
+#define sysTrapTblGetSelection 0xA1E1
+#define sysTrapTblInsertRow 0xA1E2
+#define sysTrapTblRemoveRow 0xA1E3
+#define sysTrapTblRowInvalid 0xA1E4
+#define sysTrapTblRedrawTable 0xA1E5
+#define sysTrapTblRowUsable 0xA1E6
+#define sysTrapTblReleaseFocus 0xA1E7
+#define sysTrapTblEditing 0xA1E8
+#define sysTrapTblGetCurrentField 0xA1E9
+#define sysTrapTblSetColumnUsable 0xA1EA
+#define sysTrapTblGetRowHeight 0xA1EB
+#define sysTrapTblSetColumnWidth 0xA1EC
+#define sysTrapTblGrabFocus 0xA1ED
+#define sysTrapTblSetItemPtr 0xA1EE
+#define sysTrapTblFindRowID 0xA1EF
+#define sysTrapTblGetLastUsableRow 0xA1F0
+#define sysTrapTblGetColumnSpacing 0xA1F1
+#define sysTrapTblFindRowData 0xA1F2
+#define sysTrapTblGetRowData 0xA1F3
+#define sysTrapTblSetRowData 0xA1F4
+#define sysTrapTblSetColumnSpacing 0xA1F5
+
+
+
+#define sysTrapWinCreateWindow 0xA1F6
+#define sysTrapWinCreateOffscreenWindow 0xA1F7
+#define sysTrapWinDeleteWindow 0xA1F8
+#define sysTrapWinInitializeWindow 0xA1F9
+#define sysTrapWinAddWindow 0xA1FA
+#define sysTrapWinRemoveWindow 0xA1FB
+#define sysTrapWinSetActiveWindow 0xA1FC
+#define sysTrapWinSetDrawWindow 0xA1FD
+#define sysTrapWinGetDrawWindow 0xA1FE
+#define sysTrapWinGetActiveWindow 0xA1FF
+#define sysTrapWinGetDisplayWindow 0xA200
+#define sysTrapWinGetFirstWindow 0xA201
+#define sysTrapWinEnableWindow 0xA202
+#define sysTrapWinDisableWindow 0xA203
+#define sysTrapWinGetWindowFrameRect 0xA204
+#define sysTrapWinDrawWindowFrame 0xA205
+#define sysTrapWinEraseWindow 0xA206
+#define sysTrapWinSaveBits 0xA207
+#define sysTrapWinRestoreBits 0xA208
+#define sysTrapWinCopyRectangle 0xA209
+#define sysTrapWinScrollRectangle 0xA20A
+#define sysTrapWinGetDisplayExtent 0xA20B
+#define sysTrapWinGetWindowExtent 0xA20C
+#define sysTrapWinDisplayToWindowPt 0xA20D
+#define sysTrapWinWindowToDisplayPt 0xA20E
+#define sysTrapWinGetClip 0xA20F
+#define sysTrapWinSetClip 0xA210
+#define sysTrapWinResetClip 0xA211
+#define sysTrapWinClipRectangle 0xA212
+#define sysTrapWinDrawLine 0xA213
+#define sysTrapWinDrawGrayLine 0xA214
+#define sysTrapWinEraseLine 0xA215
+#define sysTrapWinInvertLine 0xA216
+#define sysTrapWinFillLine 0xA217
+#define sysTrapWinDrawRectangle 0xA218
+#define sysTrapWinEraseRectangle 0xA219
+#define sysTrapWinInvertRectangle 0xA21A
+#define sysTrapWinDrawRectangleFrame 0xA21B
+#define sysTrapWinDrawGrayRectangleFrame 0xA21C
+#define sysTrapWinEraseRectangleFrame 0xA21D
+#define sysTrapWinInvertRectangleFrame 0xA21E
+#define sysTrapWinGetFramesRectangle 0xA21F
+#define sysTrapWinDrawChars 0xA220
+#define sysTrapWinEraseChars 0xA221
+#define sysTrapWinInvertChars 0xA222
+#define sysTrapWinGetPattern 0xA223
+#define sysTrapWinSetPattern 0xA224
+#define sysTrapWinSetUnderlineMode 0xA225
+#define sysTrapWinDrawBitmap 0xA226
+#define sysTrapWinModal 0xA227
+#define sysTrapWinGetDrawWindowBounds 0xA228
+#define sysTrapWinFillRectangle 0xA229
+#define sysTrapWinDrawInvertedChars 0xA22A
+
+
+
+#define sysTrapPrefOpenPreferenceDBV10 0xA22B
+#define sysTrapPrefGetPreferences 0xA22C
+#define sysTrapPrefSetPreferences 0xA22D
+#define sysTrapPrefGetAppPreferencesV10 0xA22E
+#define sysTrapPrefSetAppPreferencesV10 0xA22F
+
+
+#define sysTrapSndInit 0xA230
+#define sysTrapSndSetDefaultVolume 0xA231
+#define sysTrapSndGetDefaultVolume 0xA232
+#define sysTrapSndDoCmd 0xA233
+#define sysTrapSndPlaySystemSound 0xA234
+
+
+#define sysTrapAlmInit 0xA235
+#define sysTrapAlmCancelAll 0xA236
+#define sysTrapAlmAlarmCallback 0xA237
+#define sysTrapAlmSetAlarm 0xA238
+#define sysTrapAlmGetAlarm 0xA239
+#define sysTrapAlmDisplayAlarm 0xA23A
+#define sysTrapAlmEnableNotification 0xA23B
+
+
+#define sysTrapHwrGetRAMMapping 0xA23C
+#define sysTrapHwrMemWritable 0xA23D
+#define sysTrapHwrMemReadable 0xA23E
+#define sysTrapHwrDoze 0xA23F
+#define sysTrapHwrSleep 0xA240
+#define sysTrapHwrWake 0xA241
+#define sysTrapHwrSetSystemClock 0xA242
+#define sysTrapHwrSetCPUDutyCycle 0xA243
+#define sysTrapHwrDisplayInit 0xA244 /* Before OS 3.5, this trap a.k.a. sysTrapHwrLCDInit */
+#define sysTrapHwrDisplaySleep 0xA245 /* Before OS 3.5, this trap a.k.a. sysTrapHwrLCDSleep, */
+#define sysTrapHwrTimerInit 0xA246
+#define sysTrapHwrCursorV33 0xA247 /* This trap obsoleted for OS 3.5 and later */
+#define sysTrapHwrBatteryLevel 0xA248
+#define sysTrapHwrDelay 0xA249
+#define sysTrapHwrEnableDataWrites 0xA24A
+#define sysTrapHwrDisableDataWrites 0xA24B
+#define sysTrapHwrLCDBaseAddrV33 0xA24C /* This trap obsoleted for OS 3.5 and later */
+#define sysTrapHwrDisplayDrawBootScreen 0xA24D /* Before OS 3.5, this trap a.k.a. sysTrapHwrLCDDrawBitmap */
+#define sysTrapHwrTimerSleep 0xA24E
+#define sysTrapHwrTimerWake 0xA24F
+#define sysTrapHwrDisplayWake 0xA250 /* Before OS 3.5, this trap a.k.a. sysTrapHwrLCDWake */
+#define sysTrapHwrIRQ1Handler 0xA251
+#define sysTrapHwrIRQ2Handler 0xA252
+#define sysTrapHwrIRQ3Handler 0xA253
+#define sysTrapHwrIRQ4Handler 0xA254
+#define sysTrapHwrIRQ5Handler 0xA255
+#define sysTrapHwrIRQ6Handler 0xA256
+#define sysTrapHwrDockSignals 0xA257
+#define sysTrapHwrPluggedIn 0xA258
+
+
+#define sysTrapCrc16CalcBlock 0xA259
+
+
+#define sysTrapSelectDayV10 0xA25A
+#define sysTrapSelectTimeV33 0xA25B
+
+#define sysTrapDayDrawDaySelector 0xA25C
+#define sysTrapDayHandleEvent 0xA25D
+#define sysTrapDayDrawDays 0xA25E
+#define sysTrapDayOfWeek 0xA25F
+#define sysTrapDaysInMonth 0xA260
+#define sysTrapDayOfMonth 0xA261
+
+#define sysTrapDateDaysToDate 0xA262
+#define sysTrapDateToDays 0xA263
+#define sysTrapDateAdjust 0xA264
+#define sysTrapDateSecondsToDate 0xA265
+#define sysTrapDateToAscii 0xA266
+#define sysTrapDateToDOWDMFormat 0xA267
+#define sysTrapTimeToAscii 0xA268
+
+
+#define sysTrapFind 0xA269
+#define sysTrapFindStrInStr 0xA26A
+#define sysTrapFindSaveMatch 0xA26B
+#define sysTrapFindGetLineBounds 0xA26C
+#define sysTrapFindDrawHeader 0xA26D
+
+#define sysTrapPenOpen 0xA26E
+#define sysTrapPenClose 0xA26F
+#define sysTrapPenGetRawPen 0xA270
+#define sysTrapPenCalibrate 0xA271
+#define sysTrapPenRawToScreen 0xA272
+#define sysTrapPenScreenToRaw 0xA273
+#define sysTrapPenResetCalibration 0xA274
+#define sysTrapPenSleep 0xA275
+#define sysTrapPenWake 0xA276
+
+
+#define sysTrapResLoadForm 0xA277
+#define sysTrapResLoadMenu 0xA278
+
+#define sysTrapFtrInit 0xA279
+#define sysTrapFtrUnregister 0xA27A
+#define sysTrapFtrGet 0xA27B
+#define sysTrapFtrSet 0xA27C
+#define sysTrapFtrGetByIndex 0xA27D
+
+
+
+#define sysTrapGrfInit 0xA27E
+#define sysTrapGrfFree 0xA27F
+#define sysTrapGrfGetState 0xA280
+#define sysTrapGrfSetState 0xA281
+#define sysTrapGrfFlushPoints 0xA282
+#define sysTrapGrfAddPoint 0xA283
+#define sysTrapGrfInitState 0xA284
+#define sysTrapGrfCleanState 0xA285
+#define sysTrapGrfMatch 0xA286
+#define sysTrapGrfGetMacro 0xA287
+#define sysTrapGrfFilterPoints 0xA288
+#define sysTrapGrfGetNumPoints 0xA289
+#define sysTrapGrfGetPoint 0xA28A
+#define sysTrapGrfFindBranch 0xA28B
+#define sysTrapGrfMatchGlyph 0xA28C
+#define sysTrapGrfGetGlyphMapping 0xA28D
+#define sysTrapGrfGetMacroName 0xA28E
+#define sysTrapGrfDeleteMacro 0xA28F
+#define sysTrapGrfAddMacro 0xA290
+#define sysTrapGrfGetAndExpandMacro 0xA291
+#define sysTrapGrfProcessStroke 0xA292
+#define sysTrapGrfFieldChange 0xA293
+
+
+#define sysTrapGetCharSortValue 0xA294
+#define sysTrapGetCharAttr 0xA295
+#define sysTrapGetCharCaselessValue 0xA296
+
+
+#define sysTrapPwdExists 0xA297
+#define sysTrapPwdVerify 0xA298
+#define sysTrapPwdSet 0xA299
+#define sysTrapPwdRemove 0xA29A
+
+#define sysTrapGsiInitialize 0xA29B
+#define sysTrapGsiSetLocation 0xA29C
+#define sysTrapGsiEnable 0xA29D
+#define sysTrapGsiEnabled 0xA29E
+#define sysTrapGsiSetShiftState 0xA29F
+
+#define sysTrapKeyInit 0xA2A0
+#define sysTrapKeyHandleInterrupt 0xA2A1
+#define sysTrapKeyCurrentState 0xA2A2
+#define sysTrapKeyResetDoubleTap 0xA2A3
+#define sysTrapKeyRates 0xA2A4
+#define sysTrapKeySleep 0xA2A5
+#define sysTrapKeyWake 0xA2A6
+
+
+#define sysTrapDlkControl 0xA2A7 /* was sysTrapCmBroadcast */
+
+#define sysTrapDlkStartServer 0xA2A8
+#define sysTrapDlkGetSyncInfo 0xA2A9
+#define sysTrapDlkSetLogEntry 0xA2AA
+
+#define sysTrapIntlDispatch 0xA2AB /* REUSED IN v3.1 (was sysTrapPsrInit in 1.0, removed in 2.0) */
+#define sysTrapSysLibLoad 0xA2AC /* REUSED IN v2.0 (was sysTrapPsrClose) */
+#define sysTrapSndPlaySmf 0xA2AD /* REUSED IN v3.0 (was sysTrapPsrGetCommand in 1.0, removed in 2.0) */
+#define sysTrapSndCreateMidiList 0xA2AE /* REUSED IN v3.0 (was sysTrapPsrSendReply in 1.0, removed in 2.0) */
+
+#define sysTrapAbtShowAbout 0xA2AF
+
+#define sysTrapMdmDial 0xA2B0
+#define sysTrapMdmHangUp 0xA2B1
+
+#define sysTrapDmSearchRecord 0xA2B2
+
+#define sysTrapSysInsertionSort 0xA2B3
+#define sysTrapDmInsertionSort 0xA2B4
+
+#define sysTrapLstSetTopItem 0xA2B5
+
+
+// Palm OS 2.X traps Palm Pilot and 2.0 Upgrade Card
+
+#define sysTrapSclSetScrollBar 0xA2B6
+#define sysTrapSclDrawScrollBar 0xA2B7
+#define sysTrapSclHandleEvent 0xA2B8
+
+#define sysTrapSysMailboxCreate 0xA2B9
+#define sysTrapSysMailboxDelete 0xA2BA
+#define sysTrapSysMailboxFlush 0xA2BB
+#define sysTrapSysMailboxSend 0xA2BC
+#define sysTrapSysMailboxWait 0xA2BD
+
+#define sysTrapSysTaskWait 0xA2BE
+#define sysTrapSysTaskWake 0xA2BF
+#define sysTrapSysTaskWaitClr 0xA2C0
+#define sysTrapSysTaskSuspend 0xA2C1
+#define sysTrapSysTaskResume 0xA2C2
+
+#define sysTrapCategoryCreateList 0xA2C3
+#define sysTrapCategoryFreeList 0xA2C4
+#define sysTrapCategoryEditV20 0xA2C5
+#define sysTrapCategorySelect 0xA2C6
+
+#define sysTrapDmDeleteCategory 0xA2C7
+
+#define sysTrapSysEvGroupCreate 0xA2C8
+#define sysTrapSysEvGroupSignal 0xA2C9
+#define sysTrapSysEvGroupRead 0xA2CA
+#define sysTrapSysEvGroupWait 0xA2CB
+
+#define sysTrapEvtEventAvail 0xA2CC
+#define sysTrapEvtSysEventAvail 0xA2CD
+#define sysTrapStrNCopy 0xA2CE
+
+#define sysTrapKeySetMask 0xA2CF
+
+#define sysTrapSelectDay 0xA2D0
+
+#define sysTrapPrefGetPreference 0xA2D1
+#define sysTrapPrefSetPreference 0xA2D2
+#define sysTrapPrefGetAppPreferences 0xA2D3
+#define sysTrapPrefSetAppPreferences 0xA2D4
+
+#define sysTrapFrmPointInTitle 0xA2D5
+
+#define sysTrapStrNCat 0xA2D6
+
+#define sysTrapMemCmp 0xA2D7
+
+#define sysTrapTblSetColumnEditIndicator 0xA2D8
+
+#define sysTrapFntWordWrap 0xA2D9
+
+#define sysTrapFldGetScrollValues 0xA2DA
+
+#define sysTrapSysCreateDataBaseList 0xA2DB
+#define sysTrapSysCreatePanelList 0xA2DC
+
+#define sysTrapDlkDispatchRequest 0xA2DD
+
+#define sysTrapStrPrintF 0xA2DE
+#define sysTrapStrVPrintF 0xA2DF
+
+#define sysTrapPrefOpenPreferenceDB 0xA2E0
+
+#define sysTrapSysGraffitiReferenceDialog 0xA2E1
+
+#define sysTrapSysKeyboardDialog 0xA2E2
+
+#define sysTrapFntWordWrapReverseNLines 0xA2E3
+#define sysTrapFntGetScrollValues 0xA2E4
+
+#define sysTrapTblSetRowStaticHeight 0xA2E5
+#define sysTrapTblHasScrollBar 0xA2E6
+
+#define sysTrapSclGetScrollBar 0xA2E7
+
+#define sysTrapFldGetNumberOfBlankLines 0xA2E8
+
+#define sysTrapSysTicksPerSecond 0xA2E9
+#define sysTrapHwrBacklightV33 0xA2EA /* This trap obsoleted for OS 3.5 and later */
+#define sysTrapDmDatabaseProtect 0xA2EB
+
+#define sysTrapTblSetBounds 0xA2EC
+
+#define sysTrapStrNCompare 0xA2ED
+#define sysTrapStrNCaselessCompare 0xA2EE
+
+#define sysTrapPhoneNumberLookup 0xA2EF
+
+#define sysTrapFrmSetMenu 0xA2F0
+
+#define sysTrapEncDigestMD5 0xA2F1
+
+#define sysTrapDmFindSortPosition 0xA2F2
+
+#define sysTrapSysBinarySearch 0xA2F3
+#define sysTrapSysErrString 0xA2F4
+#define sysTrapSysStringByIndex 0xA2F5
+
+#define sysTrapEvtAddUniqueEventToQueue 0xA2F6
+
+#define sysTrapStrLocalizeNumber 0xA2F7
+#define sysTrapStrDelocalizeNumber 0xA2F8
+#define sysTrapLocGetNumberSeparators 0xA2F9
+
+#define sysTrapMenuSetActiveMenuRscID 0xA2FA
+
+#define sysTrapLstScrollList 0xA2FB
+
+#define sysTrapCategoryInitialize 0xA2FC
+
+#define sysTrapEncDigestMD4 0xA2FD
+#define sysTrapEncDES 0xA2FE
+
+#define sysTrapLstGetVisibleItems 0xA2FF
+
+#define sysTrapWinSetBounds 0xA300
+
+#define sysTrapCategorySetName 0xA301
+
+#define sysTrapFldSetInsertionPoint 0xA302
+
+#define sysTrapFrmSetObjectBounds 0xA303
+
+#define sysTrapWinSetColors 0xA304
+
+#define sysTrapFlpDispatch 0xA305
+#define sysTrapFlpEmDispatch 0xA306
+
+
+// Palm OS 3.0 traps Palm III and 3.0 Upgrade Card
+
+#define sysTrapExgInit 0xA307
+#define sysTrapExgConnect 0xA308
+#define sysTrapExgPut 0xA309
+#define sysTrapExgGet 0xA30A
+#define sysTrapExgAccept 0xA30B
+#define sysTrapExgDisconnect 0xA30C
+#define sysTrapExgSend 0xA30D
+#define sysTrapExgReceive 0xA30E
+#define sysTrapExgRegisterData 0xA30F
+#define sysTrapExgNotifyReceiveV35 0xA310
+#define sysTrapSysReserved30Trap2 0xA311 /* "Reserved" trap in Palm OS 3.0 and later (was sysTrapExgControl) */
+
+#define sysTrapPrgStartDialogV31 0xA312 /* Updated in v3.2 */
+#define sysTrapPrgStopDialog 0xA313
+#define sysTrapPrgUpdateDialog 0xA314
+#define sysTrapPrgHandleEvent 0xA315
+
+#define sysTrapImcReadFieldNoSemicolon 0xA316
+#define sysTrapImcReadFieldQuotablePrintable 0xA317
+#define sysTrapImcReadPropertyParameter 0xA318
+#define sysTrapImcSkipAllPropertyParameters 0xA319
+#define sysTrapImcReadWhiteSpace 0xA31A
+#define sysTrapImcWriteQuotedPrintable 0xA31B
+#define sysTrapImcWriteNoSemicolon 0xA31C
+#define sysTrapImcStringIsAscii 0xA31D
+
+#define sysTrapTblGetItemFont 0xA31E
+#define sysTrapTblSetItemFont 0xA31F
+
+#define sysTrapFontSelect 0xA320
+#define sysTrapFntDefineFont 0xA321
+
+#define sysTrapCategoryEdit 0xA322
+
+#define sysTrapSysGetOSVersionString 0xA323
+#define sysTrapSysBatteryInfo 0xA324
+#define sysTrapSysUIBusy 0xA325
+
+#define sysTrapWinValidateHandle 0xA326
+#define sysTrapFrmValidatePtr 0xA327
+#define sysTrapCtlValidatePointer 0xA328
+#define sysTrapWinMoveWindowAddr 0xA329
+#define sysTrapFrmAddSpaceForObject 0xA32A
+#define sysTrapFrmNewForm 0xA32B
+#define sysTrapCtlNewControl 0xA32C
+#define sysTrapFldNewField 0xA32D
+#define sysTrapLstNewList 0xA32E
+#define sysTrapFrmNewLabel 0xA32F
+#define sysTrapFrmNewBitmap 0xA330
+#define sysTrapFrmNewGadget 0xA331
+
+#define sysTrapFileOpen 0xA332
+#define sysTrapFileClose 0xA333
+#define sysTrapFileDelete 0xA334
+#define sysTrapFileReadLow 0xA335
+#define sysTrapFileWrite 0xA336
+#define sysTrapFileSeek 0xA337
+#define sysTrapFileTell 0xA338
+#define sysTrapFileTruncate 0xA339
+#define sysTrapFileControl 0xA33A
+
+#define sysTrapFrmActiveState 0xA33B
+
+#define sysTrapSysGetAppInfo 0xA33C
+#define sysTrapSysGetStackInfo 0xA33D
+
+#define sysTrapWinScreenMode 0xA33E /* was sysTrapScrDisplayMode */
+#define sysTrapHwrLCDGetDepthV33 0xA33F /* This trap obsoleted for OS 3.5 and later */
+#define sysTrapHwrGetROMToken 0xA340
+
+#define sysTrapDbgControl 0xA341
+
+#define sysTrapExgDBRead 0xA342
+#define sysTrapExgDBWrite 0xA343
+
+#define sysTrapHostControl 0xA344 /* Renamed from sysTrapSysGremlins, functionality generalized */
+#define sysTrapFrmRemoveObject 0xA345
+
+#define sysTrapSysReserved30Trap1 0xA346 /* "Reserved" trap in Palm OS 3.0 and later (was sysTrapSysReserved1) */
+
+// NOTE: The following two traps are reserved for future mgrs
+// that may or may not be present on any particular device.
+// They are NOT present by default; code must check first!
+#define sysTrapExpansionDispatch 0xA347 /* Reserved for ExpansionMgr (was sysTrapSysReserved2) */
+#define sysTrapFileSystemDispatch 0xA348 /* Reserved for FileSystemMgr (was sysTrapSysReserved3) */
+
+#define sysTrapOEMDispatch 0xA349 /* OEM trap in Palm OS 3.0 and later trap table (formerly sysTrapSysReserved4) */
+
+
+// Palm OS 3.1 traps Palm IIIx and Palm V
+
+#define sysTrapHwrLCDContrastV33 0xA34A /* This trap obsoleted for OS 3.5 and later */
+#define sysTrapSysLCDContrast 0xA34B
+#define sysTrapUIContrastAdjust 0xA34C /* Renamed from sysTrapContrastAdjust */
+#define sysTrapHwrDockStatus 0xA34D
+
+#define sysTrapFntWidthToOffset 0xA34E
+#define sysTrapSelectOneTime 0xA34F
+#define sysTrapWinDrawChar 0xA350
+#define sysTrapWinDrawTruncChars 0xA351
+
+#define sysTrapSysNotifyInit 0xA352 /* Notification Manager traps */
+#define sysTrapSysNotifyRegister 0xA353
+#define sysTrapSysNotifyUnregister 0xA354
+#define sysTrapSysNotifyBroadcast 0xA355
+#define sysTrapSysNotifyBroadcastDeferred 0xA356
+#define sysTrapSysNotifyDatabaseAdded 0xA357
+#define sysTrapSysNotifyDatabaseRemoved 0xA358
+
+#define sysTrapSysWantEvent 0xA359
+
+#define sysTrapFtrPtrNew 0xA35A
+#define sysTrapFtrPtrFree 0xA35B
+#define sysTrapFtrPtrResize 0xA35C
+
+#define sysTrapSysReserved31Trap1 0xA35D /* "Reserved" trap in Palm OS 3.1 and later (was sysTrapSysReserved5) */
+
+
+// Palm OS 3.2 & 3.3 traps Palm VII (3.2) and Fall '99 Palm OS Flash Update (3.3)
+
+#define sysTrapHwrNVPrefSet 0xA35E /* mapped to FlashParmsWrite */
+#define sysTrapHwrNVPrefGet 0xA35F /* mapped to FlashParmsRead */
+#define sysTrapFlashInit 0xA360
+#define sysTrapFlashCompress 0xA361
+#define sysTrapFlashErase 0xA362
+#define sysTrapFlashProgram 0xA363
+
+#define sysTrapAlmTimeChange 0xA364
+#define sysTrapErrAlertCustom 0xA365
+#define sysTrapPrgStartDialog 0xA366 /* New version of sysTrapPrgStartDialogV31 */
+
+#define sysTrapSerialDispatch 0xA367
+#define sysTrapHwrBattery 0xA368
+#define sysTrapDmGetDatabaseLockState 0xA369
+
+#define sysTrapCncGetProfileList 0xA36A
+#define sysTrapCncGetProfileInfo 0xA36B
+#define sysTrapCncAddProfile 0xA36C
+#define sysTrapCncDeleteProfile 0xA36D
+
+#define sysTrapSndPlaySmfResource 0xA36E
+
+#define sysTrapMemPtrDataStorage 0xA36F /* Never actually installed until now. */
+
+#define sysTrapClipboardAppendItem 0xA370
+
+#define sysTrapWiCmdV32 0xA371 /* Code moved to INetLib; trap obsolete */
+
+
+// Palm OS 3.5 traps Palm IIIc and other products
+
+// HAL Display-layer new traps
+#define sysTrapHwrDisplayAttributes 0xA372
+#define sysTrapHwrDisplayDoze 0xA373
+#define sysTrapHwrDisplayPalette 0xA374
+
+// Screen driver new traps
+#define sysTrapBltFindIndexes 0xA375
+#define sysTrapBmpGetBits 0xA376 /* was BltGetBitsAddr */
+#define sysTrapBltCopyRectangle 0xA377
+#define sysTrapBltDrawChars 0xA378
+#define sysTrapBltLineRoutine 0xA379
+#define sysTrapBltRectangleRoutine 0xA37A
+
+// ScrUtils new traps
+#define sysTrapScrCompress 0xA37B
+#define sysTrapScrDecompress 0xA37C
+
+// System Manager new traps
+#define sysTrapSysLCDBrightness 0xA37D
+
+// WindowColor new traps
+#define sysTrapWinPaintChar 0xA37E
+#define sysTrapWinPaintChars 0xA37F
+#define sysTrapWinPaintBitmap 0xA380
+#define sysTrapWinGetPixel 0xA381
+#define sysTrapWinPaintPixel 0xA382
+#define sysTrapWinDrawPixel 0xA383
+#define sysTrapWinErasePixel 0xA384
+#define sysTrapWinInvertPixel 0xA385
+#define sysTrapWinPaintPixels 0xA386
+#define sysTrapWinPaintLines 0xA387
+#define sysTrapWinPaintLine 0xA388
+#define sysTrapWinPaintRectangle 0xA389
+#define sysTrapWinPaintRectangleFrame 0xA38A
+#define sysTrapWinPaintPolygon 0xA38B
+#define sysTrapWinDrawPolygon 0xA38C
+#define sysTrapWinErasePolygon 0xA38D
+#define sysTrapWinInvertPolygon 0xA38E
+#define sysTrapWinFillPolygon 0xA38F
+#define sysTrapWinPaintArc 0xA390
+#define sysTrapWinDrawArc 0xA391
+#define sysTrapWinEraseArc 0xA392
+#define sysTrapWinInvertArc 0xA393
+#define sysTrapWinFillArc 0xA394
+#define sysTrapWinPushDrawState 0xA395
+#define sysTrapWinPopDrawState 0xA396
+#define sysTrapWinSetDrawMode 0xA397
+#define sysTrapWinSetForeColor 0xA398
+#define sysTrapWinSetBackColor 0xA399
+#define sysTrapWinSetTextColor 0xA39A
+#define sysTrapWinGetPatternType 0xA39B
+#define sysTrapWinSetPatternType 0xA39C
+#define sysTrapWinPalette 0xA39D
+#define sysTrapWinRGBToIndex 0xA39E
+#define sysTrapWinIndexToRGB 0xA39F
+#define sysTrapWinScreenLock 0xA3A0
+#define sysTrapWinScreenUnlock 0xA3A1
+#define sysTrapWinGetBitmap 0xA3A2
+
+// UIColor new traps
+#define sysTrapUIColorInit 0xA3A3
+#define sysTrapUIColorGetTableEntryIndex 0xA3A4
+#define sysTrapUIColorGetTableEntryRGB 0xA3A5
+#define sysTrapUIColorSetTableEntry 0xA3A6
+#define sysTrapUIColorPushTable 0xA3A7
+#define sysTrapUIColorPopTable 0xA3A8
+
+// misc cleanup and API additions
+
+#define sysTrapCtlNewGraphicControl 0xA3A9
+
+#define sysTrapTblGetItemPtr 0xA3AA
+
+#define sysTrapUIBrightnessAdjust 0xA3AB
+#define sysTrapUIPickColor 0xA3AC
+
+#define sysTrapEvtSetAutoOffTimer 0xA3AD
+
+// Misc int'l/overlay support.
+#define sysTrapTsmDispatch 0xA3AE
+#define sysTrapOmDispatch 0xA3AF
+#define sysTrapDmOpenDBNoOverlay 0xA3B0
+#define sysTrapDmOpenDBWithLocale 0xA3B1
+#define sysTrapResLoadConstant 0xA3B2
+
+// new boot-time SmallROM HAL additions
+#define sysTrapHwrPreDebugInit 0xA3B3
+#define sysTrapHwrResetNMI 0xA3B4
+#define sysTrapHwrResetPWM 0xA3B5
+
+#define sysTrapKeyBootKeys 0xA3B6
+
+#define sysTrapDbgSerDrvOpen 0xA3B7
+#define sysTrapDbgSerDrvClose 0xA3B8
+#define sysTrapDbgSerDrvControl 0xA3B9
+#define sysTrapDbgSerDrvStatus 0xA3BA
+#define sysTrapDbgSerDrvWriteChar 0xA3BB
+#define sysTrapDbgSerDrvReadChar 0xA3BC
+
+// new boot-time BigROM HAL additions
+#define sysTrapHwrPostDebugInit 0xA3BD
+#define sysTrapHwrIdentifyFeatures 0xA3BE
+#define sysTrapHwrModelSpecificInit 0xA3BF
+#define sysTrapHwrModelInitStage2 0xA3C0
+#define sysTrapHwrInterruptsInit 0xA3C1
+
+#define sysTrapHwrSoundOn 0xA3C2
+#define sysTrapHwrSoundOff 0xA3C3
+
+// Kernel clock tick routine
+#define sysTrapSysKernelClockTick 0xA3C4
+
+// MenuEraseMenu is exposed as of PalmOS 3.5, but there are
+// no public interfaces for it yet. Perhaps in a later release.
+#define sysTrapMenuEraseMenu 0xA3C5
+
+#define sysTrapSelectTime 0xA3C6
+
+// Menu Command Bar traps
+#define sysTrapMenuCmdBarAddButton 0xA3C7
+#define sysTrapMenuCmdBarGetButtonData 0xA3C8
+#define sysTrapMenuCmdBarDisplay 0xA3C9
+
+// Silkscreen info
+#define sysTrapHwrGetSilkscreenID 0xA3CA
+#define sysTrapEvtGetSilkscreenAreaList 0xA3CB
+
+#define sysTrapSysFatalAlertInit 0xA3CC
+#define sysTrapDateTemplateToAscii 0xA3CD
+
+// New traps dealing with masking private records
+#define sysTrapSecVerifyPW 0xA3CE
+#define sysTrapSecSelectViewStatus 0xA3CF
+#define sysTrapTblSetColumnMasked 0xA3D0
+#define sysTrapTblSetRowMasked 0xA3D1
+#define sysTrapTblRowMasked 0xA3D2
+
+// New form trap for dialogs with text entry field
+#define sysTrapFrmCustomResponseAlert 0xA3D3
+#define sysTrapFrmNewGsi 0xA3D4
+
+// New dynamic menu functions
+#define sysTrapMenuShowItem 0xA3D5
+#define sysTrapMenuHideItem 0xA3D6
+#define sysTrapMenuAddItem 0xA3D7
+
+// New form traps for "smart gadgets"
+#define sysTrapFrmSetGadgetHandler 0xA3D8
+
+// More new control functions
+#define sysTrapCtlSetGraphics 0xA3D9
+#define sysTrapCtlGetSliderValues 0xA3DA
+#define sysTrapCtlSetSliderValues 0xA3DB
+#define sysTrapCtlNewSliderControl 0xA3DC
+
+// Bitmap manager functions
+#define sysTrapBmpCreate 0xA3DD
+#define sysTrapBmpDelete 0xA3DE
+#define sysTrapBmpCompress 0xA3DF
+// sysTrapBmpGetBits defined in Screen driver traps
+#define sysTrapBmpGetColortable 0xA3E0
+#define sysTrapBmpSize 0xA3E1
+#define sysTrapBmpBitsSize 0xA3E2
+#define sysTrapBmpColortableSize 0xA3E3
+// extra window namager
+#define sysTrapWinCreateBitmapWindow 0xA3E4
+// Ask for a null event sooner (replaces a macro which Poser hated)
+#define sysTrapEvtSetNullEventTick 0xA3E5
+
+// Exchange manager call to allow apps to select destination categories
+#define sysTrapExgDoDialog 0xA3E6
+
+// this call will remove temporary UI like popup lists
+#define sysTrapSysUICleanup 0xA3E7
+
+// The following 4 traps were "Reserved" traps, present only in SOME post-release builds of Palm OS 3.5
+#define sysTrapWinSetForeColorRGB 0xA3E8
+#define sysTrapWinSetBackColorRGB 0xA3E9
+#define sysTrapWinSetTextColorRGB 0xA3EA
+#define sysTrapWinGetPixelRGB 0xA3EB
+
+// TRAPS ABOVE THIS POINT CAN NOT CHANGE BECAUSE THEY HAVE
+// BEEN RELEASED TO CUSTOMERS IN SHIPPING ROMS AND SDKS.
+// (MOVE THIS COMMENT DOWN WHENEVER THE "NEXT" RELEASE OCCURS.)
+
+// WARNING!! The following are new traps for 4.0. If this file is merged
+// with MAIN sources, new traps that are added for products that precede
+// 4.0 MUST insert their traps BEFORE this section.
+
+#define sysTrapSysReserved40Trap1 0xA3EC
+#define sysTrapSysReserved40Trap2 0xA3ED
+#define sysTrapSysReserved40Trap3 0xA3EE
+#define sysTrapSysReserved40Trap4 0xA3EF
+
+
+// DO NOT CHANGE TRAPS ABOVE THIS LINE
+// THESE TRAPS HAVE BEEN RELEASED IN THE 3.5 SDK
+// NEW TRAPS FOR PALM OS 4.0 CAN BE ADDED AFTER THIS
+// THE ORDER IS NOT IMPORTANT AND CAN BE CHANGED.
+
+// New Trap selector added for New Connection Mgr API
+#define sysTrapCncMgrDispatch 0xA3F0
+
+// new trap for notify from interrupt, implemented in SysEvtMgr.c
+#define sysTrapSysNotifyBroadcastFromInterrupt 0xA3F1
+
+// new trap for waking the UI without generating a null event
+#define sysTrapEvtWakeupWithoutNilEvent 0xA3F2
+
+// new trap for doing stable, fast, 7-bit string compare
+#define sysTrapStrCompareAscii 0xA3F3
+
+// New trap for accessors available thru PalmOS glue
+#define sysTrapAccessorDispatch 0xA3F4
+
+#define sysTrapBltGetPixel 0xA3F5
+#define sysTrapBltPaintPixel 0xA3F6
+#define sysTrapScrScreenInit 0xA3F7
+#define sysTrapScrUpdateScreenBitmap 0xA3F8
+#define sysTrapScrPalette 0xA3F9
+#define sysTrapScrGetColortable 0xA3FA
+#define sysTrapScrGetGrayPat 0xA3FB
+#define sysTrapScrScreenLock 0xA3FC
+#define sysTrapScrScreenUnlock 0xA3FD
+#define sysTrapFntPrvGetFontList 0xA3FE
+
+// Exchange manager functions
+#define sysTrapExgRegisterDatatype 0xA3FF
+#define sysTrapExgNotifyReceive 0xA400
+#define sysTrapExgNotifyGoto 0xA401
+#define sysTrapExgRequest 0xA402
+#define sysTrapExgSetDefaultApplication 0xA403
+#define sysTrapExgGetDefaultApplication 0xA404
+#define sysTrapExgGetTargetApplication 0xA405
+#define sysTrapExgGetRegisteredApplications 0xA406
+#define sysTrapExgGetRegisteredTypes 0xA407
+#define sysTrapExgNotifyPreview 0xA408
+#define sysTrapExgControl 0xA409
+
+// 04/30/00 CS - New Locale Manager handles access to region-specific info like date formats
+#define sysTrapLmDispatch 0xA40A
+
+// 05/10/00 kwk - New Memory Manager trap for retrieving ROM NVParam values (sys use only)
+#define sysTrapMemGetRomNVParams 0xA40B
+
+// 05/12/00 kwk - Safe character width Font Mgr call
+#define sysTrapFntWCharWidth 0xA40C
+
+// 05/17/00 kwk - Faster DmFindDatabase
+#define sysTrapDmFindDatabaseWithTypeCreator 0xA40D
+
+// New Trap selectors added for time zone picker API
+#define sysTrapSelectTimeZone 0xA40E
+#define sysTrapTimeZoneToAscii 0xA40F
+
+// 08/18/00 kwk - trap for doing stable, fast, 7-bit string compare.
+// 08/21/00 kwk - moved here in place of sysTrapSelectDaylightSavingAdjustment.
+#define sysTrapStrNCompareAscii 0xA410
+
+// New Trap selectors added for time zone conversion API
+#define sysTrapTimTimeZoneToUTC 0xA411
+#define sysTrapTimUTCToTimeZone 0xA412
+
+// New trap implemented in PhoneLookup.c
+#define sysTrapPhoneNumberLookupCustom 0xA413
+
+// new trap for selecting debugger path.
+#define sysTrapHwrDebugSelect 0xA414
+
+#define sysTrapBltRoundedRectangle 0xA415
+#define sysTrapBltRoundedRectangleFill 0xA416
+#define sysTrapWinPrvInitCanvas 0xA417
+
+#define sysTrapHwrCalcDynamicHeapSize 0xA418
+#define sysTrapHwrDebuggerEnter 0xA419
+#define sysTrapHwrDebuggerExit 0xA41A
+
+#define sysTrapLstGetTopItem 0xA41B
+
+#define sysTrapHwrModelInitStage3 0xA41C
+
+// 06/21/00 peter - New Attention Manager
+#define sysTrapAttnIndicatorAllow 0xA41D
+#define sysTrapAttnIndicatorAllowed 0xA41E
+#define sysTrapAttnIndicatorEnable 0xA41F
+#define sysTrapAttnIndicatorEnabled 0xA420
+#define sysTrapAttnIndicatorSetBlinkPattern 0xA421
+#define sysTrapAttnIndicatorGetBlinkPattern 0xA422
+#define sysTrapAttnIndicatorTicksTillNextBlink 0xA423
+#define sysTrapAttnIndicatorCheckBlink 0xA424
+#define sysTrapAttnInitialize 0xA425
+#define sysTrapAttnGetAttention 0xA426
+#define sysTrapAttnUpdate 0xA427
+#define sysTrapAttnForgetIt 0xA428
+#define sysTrapAttnGetCounts 0xA429
+#define sysTrapAttnListOpen 0xA42A
+#define sysTrapAttnHandleEvent 0xA42B
+#define sysTrapAttnEffectOfEvent 0xA42C
+#define sysTrapAttnIterate 0xA42D
+#define sysTrapAttnDoSpecialEffects 0xA42E
+#define sysTrapAttnDoEmergencySpecialEffects 0xA42F
+#define sysTrapAttnAllowClose 0xA430
+#define sysTrapAttnReopen 0xA431
+#define sysTrapAttnEnableNotification 0xA432
+#define sysTrapHwrLEDAttributes 0xA433
+#define sysTrapHwrVibrateAttributes 0xA434
+
+// Trap for getting and setting the device password hint.
+#define sysTrapSecGetPwdHint 0xA435
+#define sysTrapSecSetPwdHint 0xA436
+
+#define sysTrapHwrFlashWrite 0xA437
+
+#define sysTrapKeyboardStatusNew 0xA438
+#define sysTrapKeyboardStatusFree 0xA439
+#define sysTrapKbdSetLayout 0xA43A
+#define sysTrapKbdGetLayout 0xA43B
+#define sysTrapKbdSetPosition 0xA43C
+#define sysTrapKbdGetPosition 0xA43D
+#define sysTrapKbdSetShiftState 0xA43E
+#define sysTrapKbdGetShiftState 0xA43F
+#define sysTrapKbdDraw 0xA440
+#define sysTrapKbdErase 0xA441
+#define sysTrapKbdHandleEvent 0xA442
+
+#define sysTrapOEMDispatch2 0xA443
+#define sysTrapHwrCustom 0xA444
+
+// 08/28/00 kwk - Trap for getting form's active field.
+#define sysTrapFrmGetActiveField 0xA445
+
+// 9/18/00 rkr - Added for playing sounds regardless of interruptible flag
+#define sysTrapSndPlaySmfIrregardless 0xA446
+#define sysTrapSndPlaySmfResourceIrregardless 0xA447
+#define sysTrapSndInterruptSmfIrregardless 0xA448
+
+// 10/14/00 ABa: UDA manager
+#define sysTrapUdaMgrDispatch 0xA449
+
+// WK: private traps for PalmOS
+#define sysTrapPalmPrivate1 0xA44A
+#define sysTrapPalmPrivate2 0xA44B
+#define sysTrapPalmPrivate3 0xA44C
+#define sysTrapPalmPrivate4 0xA44D
+
+
+// 11/07/00 tlw: Added accessors
+#define sysTrapBmpGetDimensions 0xA44E
+#define sysTrapBmpGetBitDepth 0xA44F
+#define sysTrapBmpGetNextBitmap 0xA450
+#define sysTrapTblGetNumberOfColumns 0xA451
+#define sysTrapTblGetTopRow 0xA452
+#define sysTrapTblSetSelection 0xA453
+#define sysTrapFrmGetObjectIndexFromPtr 0xA454
+
+// 11/10/00 acs
+#define sysTrapBmpGetSizes 0xA455
+#define sysTrapWinGetBounds 0xA456
+
+
+#define sysTrapBltPaintPixels 0xA457
+
+// 11/22/00 bob
+#define sysTrapFldSetMaxVisibleLines 0xA458
+
+// 01/09/01 acs
+#define sysTrapScrDefaultPaletteState 0xA459
+
+// WARNING!! LEAVE THIS AT THE END AND ALWAYS ADD NEW TRAPS TO
+// THE END OF THE TRAP TABLE BUT RIGHT BEFORE THIS TRAP, AND THEN
+// RENUMBER THIS ONE TO ONE MORE THAN THE ONE RIGHT BEFORE IT!!!!!!!!!
+
+
+
+#define sysTrapLastTrapNumber 0xA45A
+
+
+
+#define sysNumTraps (sysTrapLastTrapNumber - sysTrapBase)
+
+
+
+#endif //__CORETRAPS_H_
diff --git a/SrcShared/Palm/Platform/Incs/Core/Hardware/HAL.h b/SrcShared/Palm/Platform/Incs/Core/Hardware/HAL.h
new file mode 100644
index 0000000..c8e0099
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/Hardware/HAL.h
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HAL.h
+ *
+ * Description:
+ * General HAL Equates. This header file contains function prototypes for
+ * HAL routines, and is used by both Palm OS and the HAL module.
+ *
+ * History:
+ * 5/31/99 SCL Created by Steve Lemke
+ *
+ *****************************************************************************/
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥ Turned this off, because HAL calls *are* portable, right Steve?
+#endif // PUBLIC_STUFF_STRIPPED
+
+// #ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HAL_H__
+#define __HAL_H__
+
+#include <PalmOptErrorCheckLevel.h>
+
+
+/**************************************************************************
+ * HAL routine selectors
+ ***************************************************************************/
+/*
+#define halBootBase 0
+
+typedef enum {
+ halBootHwrPreDebugInit = halBootBase, // 0
+ halBootHwrInit, // 1
+ halBootHwrModelSpecificInit, // 2
+ halBootHwrEnableDataWrites, // 3
+ halBootHwrDisableDataWrites, // 4
+ halBootHwrMemReadable, // 5
+ halBootHwrMemWritable, // 6
+ halBootHwrResetNMI, // 7
+ halBootHwrResetPWM, // 8
+
+ halBootKeyBootKeys, // 9
+
+ halBootHwrDisplayCursor, // 10
+
+ halBootDrvOpen, // 11
+ halBootDrvClose, // 12
+ halBootDrvControl, // 13
+ halBootDrvStatus, // 14
+ halBootDrvWriteChar, // 15
+ halBootDrvReadChar, // 16
+
+ halBootLastSelector
+ } halBootSelector;
+*/
+
+/************************************************************
+ * New HAL function prototypes
+ *************************************************************/
+
+#if DISABLE_HAL_TRAPS
+ #define HAL_CALL(trapNum)
+#else
+ #define HAL_CALL(trapNum) \
+ _HAL_API(_CALL)(_HAL_TABLE, trapNum)
+#endif
+
+// HwrInit is passed as a parameter to InitStage1 in RomBoot.c
+typedef void (*HwrInitProcPtr)(void);
+
+
+/**************************************************************************
+ * Prototypes of functions used only when running on the real hardware
+ ***************************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // These routines are "private" prototypes for the HAL code...
+
+ void HwrPreRAMInit(void);
+
+ void HwrInit(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__HAL_H__
+
+// #endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Incs/Core/Hardware/HwrMiscFlags.h b/SrcShared/Palm/Platform/Incs/Core/Hardware/HwrMiscFlags.h
new file mode 100644
index 0000000..a6f72fc
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/Hardware/HwrMiscFlags.h
@@ -0,0 +1,220 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: HwrMiscFlags.h
+ *
+ * Description:
+ * Bit constants for the hardware MiscFlags
+ *
+ * History:
+ * 10/26/99 JED Created by Jesse Donaldson, extracted from <HwrGlobals.h>
+ *
+ *****************************************************************************/
+
+#ifdef NON_PORTABLE // So app's don't mistakenly include this
+
+#ifndef __HWR_MISCFLAGS_H__
+#define __HWR_MISCFLAGS_H__
+
+
+
+/**************************************************************************
+ * General Equates
+ ***************************************************************************/
+
+// ----------------------------------------------------------------------
+// NOTE: In some ROMs between 3.0 and 3.3 (inclusive), OEMs may have
+// ROM tokens present in the ROM that were detected by the boot code
+// in order to set the various HwrMiscFlags and GHwrMiscFlagsExt
+// settings. That scheme is no longer relevant, since starting with
+// version 3.5 and later, it is now the responsibility of the HAL
+// to set these flags, using whatever means necessary to determine
+// what "features" the device has that the higher level OS may want
+// to know about.
+//
+// These flags are defined in this public header file since both
+// of these low memory globals are published as system features
+// (sysFtrNumHwrMiscFlags and sysFtrNumHwrMiscFlagsExt) in <SystemMgr.h>.
+// These features are for third party software that may (for whatever
+// reason) want to know about certain hardware differences without
+// having to read the low memory globals directly.
+//
+// Palm OS v3.1 was the first OS to publish sysFtrNumHwrMiscFlags as a feature.
+// Call FtrGet first; if the feature doesn't exist, check the OS version:
+// Palm OS v2.0 and 3.0 have GHwrMiscFlags defined as a low memory global.
+// Palm OS v1.0 did not have GHwrMiscFlags, so its contents are unpredictable.
+// Any devices running Palm OS v1.0 devices should assume zero for all flags.
+// ----------------------------------------------------------------------
+
+// Bits in the low memory global GHwrMiscFlags (UInt16)
+#define hwrMiscFlagHasBacklight 0x0001 // set if backlight is present
+#define hwrMiscFlagHasMbdIrDA 0x0002 // set if IrDA is present (on main board)
+#define hwrMiscFlagHasCardIrDA 0x0004 // set if IrDA is present (on memory card)
+#define hwrMiscFlagHasBurrBrown 0x0008 // set if BurrBrown A/D is present
+#define hwrMiscFlagHasJerryHW 0x0010 // set if Jerry Hardware is present
+#define hwrMiscFlagNoRTCBug 0x0020 // set if using rev of DragonBall (3G or later)
+ // that doesn't require the RealTimeClock
+ // bug work-around (see TimeMgr68328.c).
+ // <chg 3-27-98 RM>
+#define hwrMiscFlagHas3vRef 0x0040 // set if switchable 3v reference is present
+#define hwrMiscFlagHasAntennaSw 0x0080 // set if viewer has an antenna raised switch
+#define hwrMiscFlagHasCradleDetect 0x0100 // set if we have an A/D converter on hotsync port used for ID'ing the attached device
+#define hwrMiscFlagHasSWContrast 0x0200 // set if UI should support software contrast
+#define hwrMiscFlagInvertLCDForBL 0x0400 // set if we need to invert LCD w/Backlight
+#define hwrMiscFlagHasMiscFlagExt 0x0800 // set if we have new hwrMiscFlagsExt
+
+ // The following bit flags are set by HwrIdentifyFeatures.
+ // They allow software to read the hardware ID without poking at hardware.
+ // They also provide some isolation from different ID detection schemes
+ // such as if the ID detection mechanism should change with EZ...
+#define hwrMiscFlagID1 0x1000 // set if ID bit keyBitHard1 was set
+#define hwrMiscFlagID2 0x2000 // set if ID bit keyBitHard2 was set
+#define hwrMiscFlagID3 0x4000 // set if ID bit keyBitHard3 was set
+#define hwrMiscFlagID4 0x8000 // set if ID bit keyBitHard4 was set
+#define hwrMiscFlagIDMask 0xF000
+#define hwrMiscFlagIDOffset 12 // Bits to shift to get a numeric ID
+
+
+// NOTE: Currently, the '328 IDs don't overlap with the 'EZ IDs. This is NOT a requirement,
+// but is convenient for the time being as it makes it one step easier to identify a device.
+// If the spaces are forced to overlap, it will be necessary to first check the processor
+// type (328 or EZ) and then parse the product ID code. Fortunately, this scheme is rapidly
+// becoming obsolete since it was based on reading the keyboard I/O pins, and new products
+// are starting to move their keyboard I/O bits to new places. With the introduction of
+// different HAL modules, identifying the actual hardware is now something the HAL code
+// will do when the device boots. The HAL need only do whatever it needs to do to uniquely
+// tell the difference between those devices on which it is capable of operating. Once
+// the hardware is identified, the appropriate hwrMiscFlag and hwrMiscFlagExt bits can be
+// set to tell the OS what features are present, and the appropriate hardware ID information
+// can also be set so higher level software can uniquely identify the OEM/Device/HAL info.
+//
+// Changes
+// 3/16/99 SCL: Documented '328 and 'EZ IDs and how the space could overlap if necessary
+// 3/31/99 SRJ: hwrMiscFlagIDUndetermined created, used specifically during the boot sequence
+// before we have done HwrIdentifyFeatures().
+// 10/29/99 SCL: Renamed hwrMiscFlagIDOther to hwrMiscFlagIDCheckROMToken
+// 10/29/99 SCL: Assigned hwrMiscFlagIDUnused1 to hwrMiscFlagIDUndetermined for Palm OS 3.5
+// 10/29/99 SCL: Assigned hwrMiscFlagIDUnused2 to hwrMiscFlagIDCheckOEMFtrs for Palm OS 3.5
+#ifndef PUBLIC_STUFF_STRIPPED // remove unreleased product codenames for 3.5 SDK
+// 11/ 2/99 SCL: Assigned hwrMiscFlagIDUnused3 to hwrMiscFlagIDCobra2 for Palm OS 3.5
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+// hwrMiscFlagIDCheckROMToken indicates that the actual device ID information
+// should be read from hwrROMTokenHardwareID using SysGetROMToken or HwrGetROMToken.
+// Attached to this token is the OEM ID and the OEM-specific Product ID.
+// This scheme was used in Palm OS releases prior to 3.5. See <HwrROMToken.h> for details.
+// This ID is also reported when booting on PalmPilot devices (aka 2.0 hardware).
+#define hwrMiscFlagIDCheckROMToken (0) // used to be hwrMiscFlagIDOther
+#define hwrMiscFlagIDPalmPilot (0) // since it was never explicitly set
+
+// hwrMiscFlagIDUndetermined is what the OS initializes the ID to when booting.
+// The HAL is responsible for setting the ID to something valid (and meaningful).
+#define hwrMiscFlagIDUndetermined (hwrMiscFlagID1) // used to be hwrMiscFlagIDUnused1
+
+// hwrMiscFlagIDCheckOEMFtrs indicates that the OEM/Device/HAL identification
+// information should be read from the new Palm OS 3.5 System Features
+// (sysFtrNumOEMCompanyID, sysFtrNumOEMDeviceID, and sysFtrNumOEMHALID)
+// or system globals (hwrOEMCompanyID, hwrOEMDeviceID, and hwrOEMHALID).
+// This method of hardware device ID is for HAL-based devices starting with Palm OS
+// 3.5, but some devices may continue to report valid old-style hwrMiscFlagIDxxx tags.
+#define hwrMiscFlagIDCheckOEMFtrs (hwrMiscFlagID2) // used to be hwrMiscFlagIDUnused2
+
+// Old-style Hardware IDs for DragonBall '328 based products
+#define hwrMiscFlagIDThumper (hwrMiscFlagID4 | hwrMiscFlagID2)
+#define hwrMiscFlagIDJerry (hwrMiscFlagID4 | hwrMiscFlagID3)
+#define hwrMiscFlagIDRocky (hwrMiscFlagID4 | hwrMiscFlagID3 | hwrMiscFlagID2)
+#define hwrMiscFlagIDTouchdown (hwrMiscFlagID4 | hwrMiscFlagID3 | hwrMiscFlagID2 | hwrMiscFlagID1)
+
+// Old-style Hardware IDs for DragonBall 'EZ based products
+#define hwrMiscFlagIDJerryEZ (hwrMiscFlagID3 | hwrMiscFlagID2)
+#define hwrMiscFlagIDSumo (hwrMiscFlagID4 | hwrMiscFlagID2 | hwrMiscFlagID1)
+#define hwrMiscFlagIDBrad (hwrMiscFlagID4 | hwrMiscFlagID3 | hwrMiscFlagID1)
+#ifndef PUBLIC_STUFF_STRIPPED // remove unreleased product codenames for 3.5 SDK
+#define hwrMiscFlagIDAustin (hwrMiscFlagID4 | hwrMiscFlagID1)
+#define hwrMiscFlagIDCobra2 (hwrMiscFlagID2 | hwrMiscFlagID1)
+#define hwrMiscFlagIDCalvin (hwrMiscFlagID2 | hwrMiscFlagID1)
+#endif // PUBLIC_STUFF_STRIPPED
+
+// Hardware SubIDs used to detect hardware type early in boot process
+#define hwrMiscFlagExtSubIDBrad 0x0
+#define hwrMiscFlagExtSubIDSumo 0x2
+#define hwrMiscFlagExtSubIDCobra 0x4
+#ifndef PUBLIC_STUFF_STRIPPED // remove unreleased product codenames for 3.5 SDK
+#define hwrMiscFlagExtSubIDCobra2_16 0x6
+#define hwrMiscFlagExtSubIDCobra2_20 0x7
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+// Old-style Hardware IDs still unused
+#define hwrMiscFlagIDUnused4 (hwrMiscFlagID3)
+#define hwrMiscFlagIDUnused5 (hwrMiscFlagID3 | hwrMiscFlagID1)
+#define hwrMiscFlagIDUnused7 (hwrMiscFlagID3 | hwrMiscFlagID2 | hwrMiscFlagID1)
+#define hwrMiscFlagIDUnused8 (hwrMiscFlagID4)
+
+
+// Bits in the low memory global GHwrMiscFlagsExt (UInt32)
+#define hwrMiscFlagExtSubID1 0x00000001 // subtype ID (for feature select in device)
+#define hwrMiscFlagExtSubID2 0x00000002 // subtype ID (for feature select in device)
+#define hwrMiscFlagExtSubID3 0x00000004 // subtype ID (for feature select in device)
+#define hwrMiscFlagExtSubIDMask 0x00000007 // sybtype ID Mask
+
+#define hwrMiscFlagExtHasLiIon 0x00000010 // set if we have Lithium Ion battery rechargable in the cradle
+#define hwrMiscFlagExtHasRailIO 0x00000020 // set if we have Rail I/O hardware
+#define hwrMiscFlagExtHasFlash 0x00000040 // set (by OS or HAL) if we have Flash ROM
+#define hwrMiscFlagExtHasFParms 0x00000080 // set (by OS or HAL) if we have Flash parms area
+
+#define hwrMiscFlagExt115KIrOK 0x00000100 // device supports 115K IR transfers
+#define hwrMiscFlagExtHasExtLCD 0x00000200 // device has external LCD controller
+#define hwrMiscFlagExtHasSWBright 0x00000400 // device has software controlled brightness
+
+
+// Assigned values for hwrOEMCompanyID (aka sysFtrNumOEMCompanyID):
+// Values are assigned by the Palm Computing Platform Engineering group.
+//
+// Note: These values are different from the values that may be found in some
+// OEM devices which used HwrROMTokens on versions of Palm OS prior to 3.5.
+
+#define hwrOEMCompanyIDUnspecified 0x00000000 // hwrOEMCompanyID not specified by HAL
+#define hwrOEMHALIDUnspecified 0x00000000 // hwrOEMHALID not specified by HAL
+#define hwrOEMDeviceIDUnspecified 0x00000000 // hwrOEMDeviceID not specified by HAL
+
+#define hwrOEMCompanyIDPalmPlatform 'psys' // Reference Platforms made by Palm Computing
+#define hwrOEMCompanyIDPalmDevices 'palm' // Devices made by Palm Computing
+
+#define hwrOEMCompanyIDSymbol 'smbl' // Devices made by Symbol Technologies
+#define hwrOEMCompanyIDQualcomm 'qcom' // Devices made by Qualcomm
+#define hwrOEMCompanyIDTRG 'trgp' // Devices made by TRG Products
+#define hwrOEMCompanyIDHandspring 'hspr' // Devices made by Handspring
+
+
+// Note that values for hwrOEMDeviceID (aka sysFtrNumOEMDeviceID) and
+// hwrOEMHALID (aka sysFtrNumOEMHALID) are OEM vendor-specific, and not
+// necessarily tracked by this Palm OS header file, though it may be
+// worthwhile to include "known" values here for third party developers.
+//
+// It is recommended that OEM vendors choose values for these globals that
+// are four-digit human-readable ASCII values, rather than numeric codes,
+// though this is not a requirement.
+
+// HALs that belong to hwrOEMCompanyIDPalmPlatform
+#define hwrOEMHALIDEZRef 'eref' // (Mono) EZ Reference Platform (Palm Computing)
+#define hwrOEMHALIDEZRefColor 'cref' // Color EZ Reference Platform (Palm Computing)
+
+// HALs that belong to hwrOEMCompanyIDPalmDevices
+#define hwrOEMHALID328Jerry 'jery' // Pilot, PalmPilot, Palm III/VII HAL (Palm Computing)
+#define hwrOEMHALIDEZSumo 'sumo' // Palm IIIx/V/Vx HAL (Palm Computing)
+#ifndef PUBLIC_STUFF_STRIPPED // remove unreleased product codenames for 3.5 SDK
+#define hwrOEMHALIDEZAustin 'astn' // Austin HAL (Palm Computing)
+#endif // PUBLIC_STUFF_STRIPPED
+
+#ifndef PUBLIC_STUFF_STRIPPED
+#define hwrOEMHALIDEZCalvin 'clvn' // Calvin HAL (Palm Computing)
+#define hwrOEMHALIDEZBonanza 'bnza' // Bonanza HAL (Palm Computing)
+#endif // PUBLIC_STUFF_STRIPPED
+
+#endif //__HWR_MISCFLAGS_H__
+
+#endif // NON_PORTABLE
diff --git a/SrcShared/Palm/Platform/Incs/Core/Hardware/M68KHwr.h b/SrcShared/Palm/Platform/Incs/Core/Hardware/M68KHwr.h
new file mode 100644
index 0000000..8e27eb8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/Hardware/M68KHwr.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: M68KHwr.h
+ *
+ * Description:
+ * Pilot debugger remote hardware/system info
+ *
+ * History:
+ * 1/18/95 RM - Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifndef __M68KHWR_H
+#define __M68KHWR_H
+
+// Pilot common definitions
+#include <PalmTypes.h>
+
+
+/***********************************************************************
+ * Breakpoint words we use
+ ***********************************************************************/
+#define m68kTrapInstr 0x4E40
+#define m68kTrapVectorMask 0x000F
+
+/***********************************************************************
+ * 68000 Exception Vector table
+ ***********************************************************************/
+typedef struct M68KExcTableType {
+ UInt32 initStack; // initial stack pointer
+ UInt32 initPC; // initial PC
+
+ UInt32 busErr; // 08
+ UInt32 addressErr; // 0C
+ UInt32 illegalInstr; // 10
+ UInt32 divideByZero; // 14
+ UInt32 chk; // 18
+ UInt32 trap; // 1C
+ UInt32 privilege; // 20
+ UInt32 trace; // 24
+ UInt32 aTrap; // 28
+ UInt32 fTrap; // 2C
+ UInt32 reserved12; // 30
+ UInt32 coproc; // 34
+ UInt32 formatErr; // 38
+ UInt32 unitializedInt; // 3C
+
+ UInt32 reserved[8]; // 40-5C
+
+ UInt32 spuriousInt; // 60
+ UInt32 autoVec1; // 64
+ UInt32 autoVec2; // 68
+ UInt32 autoVec3; // 6C
+ UInt32 autoVec4; // 70
+ UInt32 autoVec5; // 74
+ UInt32 autoVec6; // 78
+ UInt32 autoVec7; // 7C
+
+ UInt32 trapN[16]; // 80 - BC
+
+ UInt32 unassigned[16]; // C0 - FC
+ } M68KExcTableType;
+
+
+
+/**************************************************************************************
+ * structure for the Motorolla 68000 processor registers (variables).
+ *
+ * WARNING:
+ * This structure is used as the body of the 'read regs' command response
+ * packet. Any changes to it will require changes in the nub's code.
+ *
+ **************************************************************************************/
+typedef struct M68KRegsType {
+ UInt32 d[8]; /* data registers */
+ UInt32 a[7]; /* address registers */
+ UInt32 usp; /* user stack pointer */
+ UInt32 ssp; /* supervisor stack pointer */
+ UInt32 pc; /* program counter */
+ UInt16 sr; /* status register */
+} M68KRegsType;
+
+
+
+
+/**************************************************************************************
+ * bit masks for testing M68000 status register fields
+ **************************************************************************************/
+
+/* trace mode */
+#define m68kSrTraceMask 0x08000
+#define m68kSrTraceBit 15
+
+/* supervisor state */
+#define m68kSrSupervisorMask 0x02000
+
+/* interrupt mask */
+#define m68kSrInterruptMask 0x00700
+#define m68kSrInterruptOffset 8 /* offset for right-shifting interrupt mask */
+
+/* condition codes */
+#define m68kSrExtendMask 0x00010
+#define m68kSrNegativeMask 0x00008
+#define m68kSrZeroMask 0x00004
+#define m68kSrOverflowMask 0x00002
+#define m68kSrCarryMask 0x00001
+
+
+
+#endif //__M68KHWR_H
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Bitmap.h b/SrcShared/Palm/Platform/Incs/Core/System/Bitmap.h
new file mode 100644
index 0000000..37623d3
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Bitmap.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Bitmap.h
+ *
+ * Description:
+ * This file defines bitmap structures and routines.
+ *
+ * History:
+ * September, 1999 Created by Bertrand Simon
+ * Name Date Description
+ * ---- ---- -----------
+ * BS 9/99 Create
+ * jmp 12/23/99 Fix <> vs. "" problem.
+ *
+ *****************************************************************************/
+
+#ifndef __BITMAP_H__
+#define __BITMAP_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <PalmOptErrorCheckLevel.h> // #define ERROR_CHECK_LEVEL
+
+
+//-----------------------------------------------
+// The Bitmap Structure.
+//-----------------------------------------------
+
+// bitmap version numbers
+#define BitmapVersionZero 0
+#define BitmapVersionOne 1
+#define BitmapVersionTwo 2
+
+// Compression Types for BitMap BitmapVersionTwo.
+typedef enum {
+ BitmapCompressionTypeScanLine = 0,
+ BitmapCompressionTypeRLE,
+
+ BitmapCompressionTypeNone = 0xFF
+} BitmapCompressionType;
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥Ê-- need to add #defines for each bit for endian portableness
+#endif // PUBLIC_STUFF_STRIPPED
+typedef struct BitmapFlagsType {
+ UInt16 compressed:1; // Data format: 0=raw; 1=compressed
+ UInt16 hasColorTable:1; // if true, color table stored before bits[]
+ UInt16 hasTransparency:1; // true if transparency is used
+ UInt16 indirect:1; // true if bits are stored indirectly
+ UInt16 forScreen:1; // system use only
+ UInt16 reserved:11;
+} BitmapFlagsType;
+
+// this definition correspond to the 'Tbmp' and 'tAIB' resource types
+typedef struct BitmapType {
+ Int16 width;
+ Int16 height;
+ UInt16 rowBytes;
+ BitmapFlagsType flags;
+ UInt8 pixelSize; // bits/pixel
+ UInt8 version; // version of bitmap. This is vers 2
+ UInt16 nextDepthOffset; // # of DWords to next BitmapType
+ // from beginnning of this one
+ UInt8 transparentIndex; // v2 only, if flags.hasTransparency is true,
+ // index number of transparent color
+ UInt8 compressionType; // v2 only, if flags.compressed is true, this is
+ // the type, see BitmapCompressionType
+
+ UInt16 reserved; // for future use, must be zero!
+
+ // [colorTableType] pixels | pixels*
+ // If hasColorTable != 0, we have:
+ // ColorTableType followed by pixels.
+ // If hasColorTable == 0:
+ // this is the start of the pixels
+ // if indirect != 0 bits are stored indirectly.
+ // the address of bits is stored here
+ // In some cases the ColorTableType will
+ // have 0 entries and be 2 bytes long.
+} BitmapType;
+
+typedef BitmapType *BitmapPtr;
+
+
+// This is the structure of a color table. It maps pixel values into
+// RGB colors. Each element in the table corresponds to the next
+// index, starting at 0.
+
+typedef struct RGBColorType {
+ UInt8 index; // index of color or best match to cur CLUT or unused.
+ UInt8 r; // amount of red, 0->255
+ UInt8 g; // amount of green, 0->255
+ UInt8 b; // amount of blue, 0->255
+} RGBColorType;
+
+
+typedef struct ColorTableType {
+ // high bits (numEntries > 256) reserved
+ UInt16 numEntries; // number of entries in table
+ // RGBColorType entry[]; // array 0..numEntries-1 of colors
+ // starts immediately after numEntries
+} ColorTableType;
+
+
+// get start of color table entries aray given pointer to ColorTableType
+#define ColorTableEntries(ctP) ((RGBColorType *)((ColorTableType *)(ctP)+1))
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//-----------------------------------------------
+// Routines relating to bitmap management
+//-----------------------------------------------
+
+extern BitmapType *BmpCreate (Coord width, Coord height, UInt8 depth,
+ ColorTableType *colortableP, UInt16 *error)
+ SYS_TRAP(sysTrapBmpCreate);
+
+extern Err BmpDelete (BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpDelete);
+
+extern Err BmpCompress(BitmapType *bitmapP, BitmapCompressionType compType )
+ SYS_TRAP(sysTrapBmpCompress);
+
+extern void *BmpGetBits(BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpGetBits);
+
+extern ColorTableType *BmpGetColortable(BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpGetColortable);
+
+extern UInt16 BmpSize(BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpSize);
+
+extern UInt16 BmpBitsSize(BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpBitsSize);
+
+extern UInt16 BmpColortableSize(BitmapType *bitmapP)
+ SYS_TRAP(sysTrapBmpColortableSize);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif //__BITMAP_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/CharAttr.h b/SrcShared/Palm/Platform/Incs/Core/System/CharAttr.h
new file mode 100644
index 0000000..4797bdb
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/CharAttr.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: CharAttr.h
+ *
+ * Description:
+ * This file defines character classification and character
+ * conversion macros
+ *
+ * History:
+ * April 21, 1995 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __CHARATTR_H__
+#define __CHARATTR_H__
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+
+// Remember that sizeof(0x0D) == 2 because 0x0D is treated like an int. The
+// same is true of sizeof('a'), sizeof('\0'), and sizeof(chrNull). For this
+// reason it's safest to use the sizeOf7BitChar macro to document buffer size
+// and string length calcs. Note that this can only be used with low-ascii
+// characters, as anything else might be the high byte of a double-byte char.
+
+#define sizeOf7BitChar(c) 1
+
+#ifdef NON_INTERNATIONAL
+#define sizeofchar(c) sizeof((char) (c))
+#define lastAsciiChr 0x00FF
+#else
+#define sizeofchar(c) _Obsolete__use_sizeOf7BitChar
+#define lastAsciiChr _Obsolete__lastAsciiChr_does_not_work_for_Japanese
+#endif
+
+// Character attribute code bits.
+
+#define _XA 0x0200 // extra alphabetic
+#define _XS 0x0100 // extra space
+#define _BB 0x0080 // BEL, BS, etc.
+#define _CN 0x0040 // CR, FF, HT, NL, VT
+#define _DI 0x0020 // '0'-'9'
+#define _LO 0x0010 // 'a'-'z' and lowercase extended chars.
+#define _PU 0x0008 // punctuation
+#define _SP 0x0004 // space
+#define _UP 0x0002 // 'A'-'Z' and uppercase extended chars.
+#define _XD 0x0001 // '0'-'9', 'A'-'F', 'a'-'f'
+
+
+// These macros have all been deprecated and replaced by corresponding TxtCharXXXX
+// macros found in TextMgr.h. The main problem is that these all assume 8-bit character
+// codes, and thus won't work with Shift JIS and other multi-byte encodings.
+
+// Character classification macros.
+
+#ifdef NON_INTERNATIONAL
+#define IsAscii(c) (c <= 255)
+#define IsAlNum(attr,c) (attr[(UInt8)(c)] & (_DI|_LO|_UP|_XA))
+#define IsAlpha(attr,c) (attr[(UInt8)(c)] & (_LO|_UP|_XA))
+#define IsCntrl(attr,c) (attr[(UInt8)(c)] & (_BB|_CN))
+#define IsDigit(attr,c) (attr[(UInt8)(c)] & _DI)
+#define IsGraph(attr,c) (attr[(UInt8)(c)] & (_DI|_LO|_PU|_UP|_XA))
+#define IsLower(attr,c) (attr[(UInt8)(c)] & _LO)
+#define IsPrint(attr,c) (attr[(UInt8)(c)] & (_DI|_LO|_PU|_SP|_UP|_XA))
+#define IsPunct(attr,c) (attr[(UInt8)(c)] & _PU)
+#define IsSpace(attr,c) (attr[(UInt8)(c)] & (_CN|_SP|_XS))
+#define IsUpper(attr,c) (attr[(UInt8)(c)] & _UP)
+#define IsHex(attr,c) (attr[(UInt8)(c)] & _XD)
+#define IsDelim(attr,c) (attr[(UInt8)(c)] & _SP|_PU)
+#else
+#define IsAscii(c) _Obsolete__use_TxtCharIsValid
+#define IsAlNum(attr,c) _Obsolete__use_TxtCharIsAlNum
+#define IsAlpha(attr,c) _Obsolete__use_TxtCharIsAlpha
+#define IsCntrl(attr,c) _Obsolete__use_TxtCharIsCntrl
+#define IsDigit(attr,c) _Obsolete__use_TxtCharIsDigit
+#define IsGraph(attr,c) _Obsolete__use_TxtCharIsGraph
+#define IsLower(attr,c) _Obsolete__use_TxtCharIsLower
+#define IsPrint(attr,c) _Obsolete__use_TxtCharIsPrint
+#define IsPunct(attr,c) _Obsolete__use_TxtCharIsPunct
+#define IsSpace(attr,c) _Obsolete__use_TxtCharIsSpace
+#define IsUpper(attr,c) _Obsolete__use_TxtCharIsUpper
+#define IsHex(attr,c) _Obsolete__use_TxtCharIsHex
+#define IsDelim(attr,c) _Obsolete__use_TxtCharIsDelim
+#endif
+
+// This macro is deprecated because it relies on character code ranges, versus checking
+// to ensure that the keydown event has the command bit set in the modifiers field. Use
+// the TxtCharIsHardKey macro found in TextMgr.h.
+
+#ifdef NON_INTERNATIONAL
+#define ChrIsHardKey(c) ((((c) >= hardKeyMin) && ((c) <= hardKeyMax)) || ((c) == calcChr))
+#else
+#define ChrIsHardKey(c) _Obsolete__use_TxtCharIsHardKey
+#endif
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// In 3.1 and later versions of Palm OS, these routines have all been replaced by new
+// Text Manager routines found in TextMgr.h
+
+#ifdef NON_INTERNATIONAL
+const UInt16 *GetCharAttr (void)
+ SYS_TRAP(sysTrapGetCharAttr);
+
+const UInt8 *GetCharSortValue (void)
+ SYS_TRAP(sysTrapGetCharSortValue);
+
+const UInt8 *GetCharCaselessValue (void)
+ SYS_TRAP(sysTrapGetCharCaselessValue);
+#else
+#define GetCharAttr() _Obsolete__use_TxtCharIs_macros
+#define GetCharSortValue() _Obsolete__use_TxtCompare
+#define GetCharCaselessValue() _Obsolete__use_TxtCaselessCompare
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif /* __CHARATTR_H__ */
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Chars.h b/SrcShared/Palm/Platform/Incs/Core/System/Chars.h
new file mode 100644
index 0000000..ada116b
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Chars.h
@@ -0,0 +1,411 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Chars.h
+ *
+ * Description:
+ * This file defines the characters in fonts.
+ *
+ * History:
+ * November 3, 1994 Created by Roger Flores
+ * 11/03/94 rsf Created by Roger Flores.
+ * 04/21/99 JFS Added list of virtual command key ranges reserved
+ * for use by licensees.
+ * 09/13/99 kwk Added vchrTsmMode.
+ * 10/28/99 kwk Defined vchrPageUp and vchrPageDown.
+ *
+ *****************************************************************************/
+
+#ifndef __CHARS_H__
+#define __CHARS_H__
+
+// Standard Unicode 2.0 names for the ascii characters. These exist in
+// all of the text fonts, no matter what character encoding is being
+// used by PalmOS.
+
+#define chrNull 0x0000
+#define chrStartOfHeading 0x0001
+#define chrStartOfText 0x0002
+#define chrEndOfText 0x0003
+#define chrEndOfTransmission 0x0004
+#define chrEnquiry 0x0005
+#define chrAcknowledge 0x0006
+#define chrBell 0x0007
+#define chrBackspace 0x0008
+#define chrHorizontalTabulation 0x0009
+#define chrLineFeed 0x000A
+#define chrVerticalTabulation 0x000B
+#define chrFormFeed 0x000C
+#define chrCarriageReturn 0x000D
+#define chrShiftOut 0x000E
+#define chrShiftIn 0x000F
+#define chrDataLinkEscape 0x0010
+#define chrDeviceControlOne 0x0011
+#define chrDeviceControlTwo 0x0012
+#define chrDeviceControlThree 0x0013
+#define chrDeviceControlFour 0x0014
+#define chrNegativeAcknowledge 0x0015
+#define chrSynchronousIdle 0x0016
+#define chrEndOfTransmissionBlock 0x0017
+#define chrCancel 0x0018
+#define chrEndOfMedium 0x0019
+#define chrSubstitute 0x001A
+#define chrEscape 0x001B
+#define chrFileSeparator 0x001C
+#define chrGroupSeparator 0x001D
+#define chrRecordSeparator 0x001E
+#define chrUnitSeparator 0x001F
+#define chrSpace 0x0020
+#define chrExclamationMark 0x0021
+#define chrQuotationMark 0x0022
+#define chrNumberSign 0x0023
+#define chrDollarSign 0x0024
+#define chrPercentSign 0x0025
+#define chrAmpersand 0x0026
+#define chrApostrophe 0x0027
+#define chrLeftParenthesis 0x0028
+#define chrRightParenthesis 0x0029
+#define chrAsterisk 0x002A
+#define chrPlusSign 0x002B
+#define chrComma 0x002C
+#define chrHyphenMinus 0x002D
+#define chrFullStop 0x002E
+#define chrSolidus 0x002F
+#define chrDigitZero 0x0030
+#define chrDigitOne 0x0031
+#define chrDigitTwo 0x0032
+#define chrDigitThree 0x0033
+#define chrDigitFour 0x0034
+#define chrDigitFive 0x0035
+#define chrDigitSix 0x0036
+#define chrDigitSeven 0x0037
+#define chrDigitEight 0x0038
+#define chrDigitNine 0x0039
+#define chrColon 0x003A
+#define chrSemicolon 0x003B
+#define chrLessThanSign 0x003C
+#define chrEqualsSign 0x003D
+#define chrGreaterThanSign 0x003E
+#define chrQuestionMark 0x003F
+#define chrCommercialAt 0x0040
+#define chrCapital_A 0x0041
+#define chrCapital_B 0x0042
+#define chrCapital_C 0x0043
+#define chrCapital_D 0x0044
+#define chrCapital_E 0x0045
+#define chrCapital_F 0x0046
+#define chrCapital_G 0x0047
+#define chrCapital_H 0x0048
+#define chrCapital_I 0x0049
+#define chrCapital_J 0x004A
+#define chrCapital_K 0x004B
+#define chrCapital_L 0x004C
+#define chrCapital_M 0x004D
+#define chrCapital_N 0x004E
+#define chrCapital_O 0x004F
+#define chrCapital_P 0x0050
+#define chrCapital_Q 0x0051
+#define chrCapital_R 0x0052
+#define chrCapital_S 0x0053
+#define chrCapital_T 0x0054
+#define chrCapital_U 0x0055
+#define chrCapital_V 0x0056
+#define chrCapital_W 0x0057
+#define chrCapital_X 0x0058
+#define chrCapital_Y 0x0059
+#define chrCapital_Z 0x005A
+#define chrLeftSquareBracket 0x005B
+// #define chrReverseSolidus 0x005C (not in Japanese fonts)
+#define chrRightSquareBracket 0x005D
+#define chrCircumflexAccent 0x005E
+#define chrLowLine 0x005F
+#define chrGraveAccent 0x0060
+#define chrSmall_A 0x0061
+#define chrSmall_B 0x0062
+#define chrSmall_C 0x0063
+#define chrSmall_D 0x0064
+#define chrSmall_E 0x0065
+#define chrSmall_F 0x0066
+#define chrSmall_G 0x0067
+#define chrSmall_H 0x0068
+#define chrSmall_I 0x0069
+#define chrSmall_J 0x006A
+#define chrSmall_K 0x006B
+#define chrSmall_L 0x006C
+#define chrSmall_M 0x006D
+#define chrSmall_N 0x006E
+#define chrSmall_O 0x006F
+#define chrSmall_P 0x0070
+#define chrSmall_Q 0x0071
+#define chrSmall_R 0x0072
+#define chrSmall_S 0x0073
+#define chrSmall_T 0x0074
+#define chrSmall_U 0x0075
+#define chrSmall_V 0x0076
+#define chrSmall_W 0x0077
+#define chrSmall_X 0x0078
+#define chrSmall_Y 0x0079
+#define chrSmall_Z 0x007A
+#define chrLeftCurlyBracket 0x007B
+#define chrVerticalLine 0x007C
+#define chrRightCurlyBracket 0x007D
+#define chrTilde 0x007E
+#define chrDelete 0x007F
+
+
+// Special meanings given to characters by the PalmOS
+#define vchrPageUp chrVerticalTabulation // 0x000B
+#define vchrPageDown chrFormFeed // 0x000C
+#define chrOtaSecure chrDeviceControlFour // 0x0014
+#define chrOta chrNegativeAcknowledge // 0x0015
+#define chrCommandStroke chrSynchronousIdle // 0x0016
+#define chrShortcutStroke chrEndOfTransmissionBlock // 0x0017
+#define chrEllipsis chrCancel // 0x0018
+#define chrNumericSpace chrEndOfMedium // 0x0019
+#define chrLeftArrow chrFileSeparator // 0x001C
+#define chrRightArrow chrGroupSeparator // 0x001D
+#define chrUpArrow chrRecordSeparator // 0x001E
+#define chrDownArrow chrUnitSeparator // 0x001F
+
+
+// The following are key codes used for virtual events, like
+// low battery warnings, etc. These keyboard events MUST
+// have the commandKeyMask bit set in the modifiers in order
+// to be recognized.
+#define vchrLowBattery 0x0101 // Display low battery dialog
+#define vchrEnterDebugger 0x0102 // Enter Debugger
+#define vchrNextField 0x0103 // Go to next field in form
+#define vchrStartConsole 0x0104 // Startup console task
+#define vchrMenu 0x0105 // Ctl-A
+#define vchrCommand 0x0106 // Ctl-C
+#define vchrConfirm 0x0107 // Ctl-D
+#define vchrLaunch 0x0108 // Ctl-E
+#define vchrKeyboard 0x0109 // Ctl-F popup the keyboard in appropriate mode
+#define vchrFind 0x010A
+#define vchrCalc 0x010B
+#define vchrPrevField 0x010C
+#define vchrAlarm 0x010D // sent before displaying an alarm
+#define vchrRonamatic 0x010E // stroke from graffiti area to top half of screen
+#define vchrGraffitiReference 0x010F // popup the Graffiti reference
+#define vchrKeyboardAlpha 0x0110 // popup the keyboard in alpha mode
+#define vchrKeyboardNumeric 0x0111 // popup the keyboard in number mode
+#define vchrLock 0x0112 // switch to the Security app and lock the device
+#define vchrBacklight 0x0113 // toggle state of backlight
+#define vchrAutoOff 0x0114 // power off due to inactivity timer
+// Added for PalmOS 3.0
+#define vchrExgTest 0x0115 // put exchange Manager into test mode (&.t)
+#define vchrSendData 0x0116 // Send data if possible
+#define vchrIrReceive 0x0117 // Initiate an Ir receive manually (&.i)
+// Added for PalmOS 3.1
+#define vchrTsm1 0x0118 // Text Services silk-screen button
+#define vchrTsm2 0x0119 // Text Services silk-screen button
+#define vchrTsm3 0x011A // Text Services silk-screen button
+#define vchrTsm4 0x011B // Text Services silk-screen button
+// Added for PalmOS 3.2
+#define vchrRadioCoverageOK 0x011C // Radio coverage check successful
+#define vchrRadioCoverageFail 0x011D // Radio coverage check failure
+#define vchrPowerOff 0x011E // Posted after autoOffChr or hardPowerChr
+ // to put system to sleep with SysSleep.
+// Added for PalmOS 3.5
+#define vchrResumeSleep 0x011F // Posted by NotifyMgr clients after they
+ // have deferred a sleep request in order
+ // to resume it.
+#define vchrLateWakeup 0x0120 // Posted by the system after waking up
+ // to broadcast a late wakeup notification.
+ // FOR SYSTEM USE ONLY
+#define vchrTsmMode 0x0121 // Posted by TSM to trigger mode change.
+#define vchrBrightness 0x0122 // Activates brightness adjust dialog
+#define vchrContrast 0x0123 // Activates contrast adjust dialog
+#define vchrExgIntData 0x01FF // Exchange Manager wakeup event
+
+// The application launching buttons generate the following
+// key codes and will also set the commandKeyMask bit in the
+// modifiers field
+#define vchrHardKeyMin 0x0200
+#define vchrHardKeyMax 0x02FF // 256 hard keys
+
+#define vchrHard1 0x0204
+#define vchrHard2 0x0205
+#define vchrHard3 0x0206
+#define vchrHard4 0x0207
+#define vchrHardPower 0x0208
+#define vchrHardCradle 0x0209 // Button on cradle pressed
+#define vchrHardCradle2 0x020A // Button on cradle pressed and hwrDockInGeneric1
+ // input on dock asserted (low).
+#define vchrHardContrast 0x020B // Sumo's Contrast button
+#define vchrHardAntenna 0x020C // Eleven's Antenna switch
+#define vchrHardBrightness 0x020D // Hypothetical Brightness button
+
+
+
+// The following keycode RANGES are reserved for use by licensees.
+// All have the commandKeyMask bit set in the event's modifiers field.
+// Note that ranges include the Min and Max values themselves (i.e. key
+// codes >= min and <= max are assigned to the following licensees).
+//
+// Qualcomm
+#define vchrThumperMin 0x0300
+#define vchrThumperMax 0x03FF // 256 command keys
+
+// Motorola
+#define vchrCessnaMin 0x14CD
+#define vchrCessnaMax 0x14CD // 1 command key
+
+// TRG
+#define vchrCFlashMin 0x1500
+#define vchrCFlashMax 0x150F // 16 command keys
+
+// Symbol
+#define vchrSPTMin 0x15A0
+#define vchrSPTMax 0x15AF // 16 command keys
+
+// Handspring
+#define vchrSlinkyMin 0x1600
+#define vchrSlinkyMax 0x16FF // 256 command keys
+
+
+
+// Old names for some of the characters.
+#define nullChr chrNull // 0x0000
+#define backspaceChr chrBackspace // 0x0008
+#define tabChr chrHorizontalTabulation // 0x0009
+#define linefeedChr chrLineFeed // 0x000A
+#define pageUpChr vchrPageUp // 0x000B
+#define chrPageUp vchrPageUp // 0x000B
+#define pageDownChr vchrPageDown // 0x000C
+#define chrPageDown vchrPageDown // 0x000C
+#define crChr chrCarriageReturn // 0x000D
+#define returnChr chrCarriageReturn // 0x000D
+#define otaSecureChr chrOtaSecure // 0x0014
+#define otaChr chrOta // 0x0015
+
+#define escapeChr chrEscape // 0x001B
+#define leftArrowChr chrLeftArrow // 0x001C
+#define rightArrowChr chrRightArrow // 0x001D
+#define upArrowChr chrUpArrow // 0x001E
+#define downArrowChr chrDownArrow // 0x001F
+#define spaceChr chrSpace // 0x0020
+#define quoteChr chrQuotationMark // 0x0022 '"'
+#define commaChr chrComma // 0x002C ','
+#define periodChr chrFullStop // 0x002E '.'
+#define colonChr chrColon // 0x003A ':'
+#define lowBatteryChr vchrLowBattery // 0x0101
+#define enterDebuggerChr vchrEnterDebugger // 0x0102
+#define nextFieldChr vchrNextField // 0x0103
+#define startConsoleChr vchrStartConsole // 0x0104
+#define menuChr vchrMenu // 0x0105
+#define commandChr vchrCommand // 0x0106
+#define confirmChr vchrConfirm // 0x0107
+#define launchChr vchrLaunch // 0x0108
+#define keyboardChr vchrKeyboard // 0x0109
+#define findChr vchrFind // 0x010A
+#define calcChr vchrCalc // 0x010B
+#define prevFieldChr vchrPrevField // 0x010C
+#define alarmChr vchrAlarm // 0x010D
+#define ronamaticChr vchrRonamatic // 0x010E
+#define graffitiReferenceChr vchrGraffitiReference // 0x010F
+#define keyboardAlphaChr vchrKeyboardAlpha // 0x0110
+#define keyboardNumericChr vchrKeyboardNumeric // 0x0111
+#define lockChr vchrLock // 0x0112
+#define backlightChr vchrBacklight // 0x0113
+#define autoOffChr vchrAutoOff // 0x0114
+#define exgTestChr vchrExgTest // 0x0115
+#define sendDataChr vchrSendData // 0x0116
+#define irReceiveChr vchrIrReceive // 0x0117
+#define radioCoverageOKChr vchrRadioCoverageOK // 0x011C
+#define radioCoverageFailChr vchrRadioCoverageFail // 0x011D
+#define powerOffChr vchrPowerOff // 0x011E
+#define resumeSleepChr vchrResumeSleep // 0x011F
+#define lateWakeupChr vchrLateWakeup // 0x0120
+#define brightnessChr vchrBrightness // 0x0121
+#define contrastChr vchrContrast // 0x0122
+#define hardKeyMin vchrHardKeyMin // 0x0200
+#define hardKeyMax vchrHardKeyMax // 0x02FF
+#define hard1Chr vchrHard1 // 0x0204
+#define hard2Chr vchrHard2 // 0x0205
+#define hard3Chr vchrHard3 // 0x0206
+#define hard4Chr vchrHard4 // 0x0207
+#define hardPowerChr vchrHardPower // 0x0208
+#define hardCradleChr vchrHardCradle // 0x0209
+#define hardCradle2Chr vchrHardCradle2 // 0x020A
+#define hardContrastChr vchrHardContrast // 0x020B
+#define hardAntennaChr vchrHardAntenna // 0x020C
+#define hardBrightnessChr vchrHardBrightness // 0x020D
+
+// Macros to determine correct character code to use for drawing numeric space
+// and horizontal ellipsis.
+
+#define ChrNumericSpace(chP) \
+ do { \
+ UInt32 attribute; \
+ if ((FtrGet(sysFtrCreator, sysFtrNumROMVersion, &attribute) == 0) \
+ && (attribute >= sysMakeROMVersion(3, 1, 0, 0, 0))) { \
+ *(chP) = chrNumericSpace; \
+ } else { \
+ *(chP) = 0x80; \
+ } \
+ } while (0)
+
+#define ChrHorizEllipsis(chP) \
+ do { \
+ UInt32 attribute; \
+ if ((FtrGet(sysFtrCreator, sysFtrNumROMVersion, &attribute) == 0) \
+ && (attribute >= sysMakeROMVersion(3, 1, 0, 0, 0))) { \
+ *(chP) = chrEllipsis; \
+ } else { \
+ *(chP) = 0x85; \
+ } \
+ } while (0)
+
+// Characters in the 9 point symbol font. Resource ID 9003
+enum symbolChars {
+ symbolLeftArrow = 3,
+ symbolRightArrow,
+ symbolUpArrow,
+ symbolDownArrow,
+ symbolSmallDownArrow,
+ symbolSmallUpArrow,
+ symbolMemo = 9,
+ symbolHelp,
+ symbolNote,
+ symbolNoteSelected,
+ symbolCapsLock,
+ symbolNumLock,
+ symbolShiftUpper,
+ symbolShiftPunc,
+ symbolShiftExt,
+ symbolShiftNone,
+ symbolNoTime,
+ symbolAlarm,
+ symbolRepeat,
+ symbolCheckMark,
+ // These next four characters were moved from the 0x8D..0x90
+ // range in the main fonts to the 9pt Symbol font in PalmOS 3.1
+ symbolDiamondChr,
+ symbolClubChr,
+ symbolHeartChr,
+ symbolSpadeChr
+ };
+
+// Character in the 7 point symbol font. Resource ID 9005
+enum symbol7Chars {
+ symbol7ScrollUp = 1,
+ symbol7ScrollDown,
+ symbol7ScrollUpDisabled,
+ symbol7ScrollDownDisabled
+ };
+
+// Characters in the 11 point symbol font. Resource ID 9004
+enum symbol11Chars {
+ symbolCheckboxOff = 0,
+ symbolCheckboxOn,
+ symbol11LeftArrow,
+ symbol11RightArrow,
+ symbol11LeftArrowDisabled, // New for Palm OS v3.2
+ symbol11RightArrowDisabled // New for Palm OS v3.2
+ };
+
+
+#endif // __CHARS_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Crc.h b/SrcShared/Palm/Platform/Incs/Core/System/Crc.h
new file mode 100644
index 0000000..bd7c3e5
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Crc.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Crc.h
+ *
+ * Description:
+ * This is the header file for the CRC calculation routines for Pilot.
+ *
+ * History:
+ * May 10, 1995 Created by Vitaly Kruglikov
+ * 05/10/95 vmk Created by Vitaly Kruglikov.
+ * 09/10/99 kwk Crc16CalcBlock takes a const void *.
+ *
+ *****************************************************************************/
+
+#ifndef __CRC_H__
+#define __CRC_H__
+
+
+// Include elementary types
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+
+
+
+/********************************************************************
+ * CRC Calculation Routines
+ * These are define as external calls only under emulation mode or
+ * under native mode from the module that actually installs the trap
+ * vectors
+ ********************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+//-------------------------------------------------------------------
+// API
+//-------------------------------------------------------------------
+
+
+// Crc16CalcBlock()
+//
+// Calculate the 16-bit CRC of a data block using the table lookup method.
+//
+UInt16 Crc16CalcBlock(const void *bufP, UInt16 count, UInt16 crc)
+ SYS_TRAP(sysTrapCrc16CalcBlock);
+
+UInt16 Crc16CalcBigBlock(void *bufP, UInt32 count, UInt16 crc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif // __CRC_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/DLCommon.h b/SrcShared/Palm/Platform/Incs/Core/System/DLCommon.h
new file mode 100644
index 0000000..af8a449
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/DLCommon.h
@@ -0,0 +1,2433 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DLCommon.h
+ *
+ * Description:
+ * Desktop Link Protocol(DLP) function id's, parameters, and frame
+ * structures.
+ *
+ * History:
+ * 6/7/95 vmk Created by Vitaly Marty Kruglikov
+ * 6/15/95 vmk Changed dlp/Read/Write/UserID to dlp/Read/Write/UserInfo and
+ * added the last sync PC id field to their arguments at Laura's request.
+ * 6/15/95 vmk Added option to dlpDeleteRecord to delete all records in DB.
+ *
+ *****************************************************************************/
+
+#ifndef __DLCOMMON_H__
+#define __DLCOMMON_H__
+
+#include <PalmTypes.h>
+
+/************************************************************
+ * DesktopLink function codes
+ *************************************************************/
+
+// DlpFuncID -- function id's used in request blocks sent to
+// the DesktopLink application on Pilot. The width of the function
+// id base is 7 bits. The high order bit(the 8th bit) is used to
+// distinguish requests from their responses -- it is cleared in request
+// blocks and is set in response blocks (i.e., the response to a particular
+// command will have the same function code base as the command and the
+// high order bit set). See dlpFuncRespFlag defined below.
+//
+typedef enum DlpFuncID {
+
+ dlpReservedFunc = 0x0F, // range reserved for internal use
+
+ // DLP 1.0 FUNCTIONS START HERE (PalmOS v1.0)
+ dlpReadUserInfo,
+
+ dlpWriteUserInfo,
+
+ dlpReadSysInfo,
+
+ dlpGetSysDateTime,
+
+ dlpSetSysDateTime,
+
+ dlpReadStorageInfo,
+
+ dlpReadDBList,
+
+ dlpOpenDB,
+
+ dlpCreateDB,
+
+ dlpCloseDB,
+
+ dlpDeleteDB,
+
+ dlpReadAppBlock,
+
+ dlpWriteAppBlock,
+
+ dlpReadSortBlock,
+
+ dlpWriteSortBlock,
+
+ dlpReadNextModifiedRec,
+
+ dlpReadRecord,
+
+ dlpWriteRecord,
+
+ dlpDeleteRecord,
+
+ dlpReadResource,
+
+ dlpWriteResource,
+
+ dlpDeleteResource,
+
+ dlpCleanUpDatabase,
+
+ dlpResetSyncFlags,
+
+ dlpCallApplication,
+
+ dlpResetSystem,
+
+ dlpAddSyncLogEntry,
+
+ dlpReadOpenDBInfo,
+
+ dlpMoveCategory,
+
+ dlpProcessRPC, // remote procedure calls interface
+
+ dlpOpenConduit, // this command is sent before each conduit is opened
+
+ dlpEndOfSync, // ends the sync session
+
+ dlpResetRecordIndex, // resets "modified record" index
+
+ dlpReadRecordIDList, // LAST 1.0 FUNCTION
+
+
+ // DLP 1.1 FUNCTIONS ADDED HERE (PalmOS v2.0 Personal, and Professional)
+ dlpReadNextRecInCategory, // iterate through all records in category
+
+ dlpReadNextModifiedRecInCategory, // iterate through modified records in category
+
+ dlpReadAppPreference, // read application preference
+
+ dlpWriteAppPreference, // write application preference
+
+ dlpReadNetSyncInfo, // read Network HotSync settings
+
+ dlpWriteNetSyncInfo, // write Network HotSync settings
+
+ dlpReadFeature, // read a feature from Feature Manager
+
+
+ // DLP 1.2 FUNCTIONS ADDED HERE (PalmOS v3.0)
+ dlpFindDB, // find a database given creator and type, or name, or
+ // get info on currently-open db
+ dlpSetDBInfo, // change database information (name, attributes, version,
+ // creation, modification, backup dates, type and creator
+
+
+
+
+ dlpLastFunc // ***ALWAYS KEEP LAST***
+
+ } DlpFuncID;
+
+#define dlpLastPilotV10FuncID dlpReadRecordIDList
+
+
+// Desktop Link function error codes returned in the response errorCode
+// field.
+typedef enum DlpRespErrorCode {
+ dlpRespErrNone = 0, // reserve 0 for no error
+ dlpRespErrSystem, // general Pilot system error
+ dlpRespErrIllegalReq, // unknown function ID
+ dlpRespErrMemory, // insufficient dynamic heap memory
+ dlpRespErrParam, // invalid parameter
+ dlpRespErrNotFound, // database, record, or resource not found
+ dlpRespErrNoneOpen, // there are no open databases
+ dlpRespErrDatabaseOpen, // database is open by someone else
+ dlpRespErrTooManyOpenDatabases, // there are too many open databases
+ dlpRespErrAlreadyExists, // DB already exists
+ dlpRespErrCantOpen, // couldn't open DB
+ dlpRespErrRecordDeleted, // record is deleted
+ dlpRespErrRecordBusy, // record is in use by someone else
+ dlpRespErrNotSupported, // the requested operation is not supported
+ // on the given database type(record or resource)
+ dlpRespErrUnused1, // was dlpRespErrROMBased
+ dlpRespErrReadOnly, // caller does not have write access(or DB is in ROM)
+ dlpRespErrNotEnoughSpace, // not enough space in data store for record/resource/etc.
+ dlpRespErrLimitExceeded, // size limit exceeded
+ dlpRespErrCancelSync, // cancel the sync
+
+ dlpRespErrBadWrapper, // bad arg wrapper(for debugging)
+ dlpRespErrArgMissing, // required arg not found(for debugging)
+ dlpRespErrArgSize, // invalid argument size
+
+ dlpRespErrLastReserved = 127 // last error code reserved for Palm
+ // *KEEP THIS ENTRY LAST*
+ } DlpRespErrorCode;
+
+
+// Database flags
+// NOTE: THESE *MUST* MATCH THE TOUCHDOWN DB ATTRIBUTES(AT LEAST IN THE FIRST VERSION).
+// ANY CHANGES MUST BE REFLECTED IN "READ DB LIST" AND
+#define dlpDBFlagResDB 0x0001 // resource DB if set; record DB if cleared
+
+#define dlpDBFlagReadOnly 0x0002 // DB is read only if set; read/write if cleared
+
+#define dlpDBFlagAppInfoDirty 0x0004 // Set if Application Info block is dirty
+ // Optionally supported by an App's conduit
+
+#define dlpDBFlagBackup 0x0008 // Set if database should be backed up to PC if
+ // no app-specific synchronization conduit has
+ // been supplied.
+
+#define dlpDBFlagOKToInstallNewer 0x0010 // This tells the backup conduit that it's OK
+ // for it to install a newer version of this database
+ // with a different name if the current database is
+ // open. This mechanism is used to update the
+ // Graffiti Shortcuts database, for example.
+
+#define dlpDBFlagResetAfterInstall 0x0020 // Device requires a reset after this database is
+ // installed.
+
+#define dlpDBFlagCopyPrevention 0x0040 // This database should not be copied to
+ // another deviced.
+
+#define dlpDBFlagOpen 0x8000 // DB is open
+
+
+
+
+// Database record attributes
+#define dlpRecAttrDeleted 0x80 // delete this record next sync
+#define dlpRecAttrDirty 0x40 // archive this record next sync
+#define dlpRecAttrBusy 0x20 // record currently in use
+#define dlpRecAttrSecret 0x10 // "secret" record - password protected
+#define dlpRecAttrArchived 0x08 // archived record
+
+
+// Date/time will be described in the following format
+// yr(2 bytes), mo(1 byte, 1-12), dy(1 byte, 1-31),
+// hr(1 byte, 0-23), min(1 byte, 0-59), sec(1 byte, 0-59),
+// unused(1 byte).
+
+typedef struct DlpDateTimeType { // OFFSET
+ UInt16 year; // 0; year (high, low)
+ UInt8 month; // 2; month: 1-12
+ UInt8 day; // 3; day: 1-31
+ UInt8 hour; // 4; hour: 0-23
+ UInt8 minute; // 5; minute: 0-59
+ UInt8 second; // 6; second: 0-59
+ UInt8 unused; // 7; unused -- set to null!
+ } DlpDateTimeType; // TOTAL: 8 bytes
+
+
+// Version structure
+typedef struct DlpVersionType {
+ // OFFSET
+ UInt16 wMajor; // 0; major version number (0 = ignore)
+ UInt16 wMinor; // 2; minor version number
+ // TOTAL: 4 bytes
+ } DlpVersionType;
+
+
+/************************************************************
+ * Request and Response headers.
+ *
+ * Each DLP request and response data block begins with the
+ * corresponding header structure which identifies the function
+ * id, argument count, and error code(responses only).
+ *************************************************************/
+
+// Request header:
+//
+typedef struct DlpReqHeaderType {
+ // OFFSET
+ UInt8 id; // 0; request function ID
+ UInt8 argc; // 2; count of args that follow this header
+ // TOTAL: 2 bytes
+ } DlpReqHeaderType;
+
+typedef DlpReqHeaderType* DlpReqHeaderPtr;
+
+typedef struct DlpReqType {
+ // OFFSET
+ DlpReqHeaderType header; // 0; request header
+ // FIXED SIZE: 2 bytes
+ UInt8 args[2]; // 2; request arguments -- var size
+ } DlpReqType;
+
+typedef DlpReqType* DlpReqPtr;
+
+// Response header:
+//
+typedef struct DlpRespHeaderType {
+ // OFFSET
+ UInt8 id; // 0; response function ID
+ UInt8 argc; // 1; count of arguments that follow this header
+ UInt16 errorCode; // 2; error code
+ // TOTAL: 4 bytes
+ } DlpRespHeaderType;
+
+typedef DlpRespHeaderType* DlpRespHeaderPtr;
+
+typedef struct DlpRespType {
+ // OFFSET
+ DlpRespHeaderType header; // 0; response header
+ // FIXED SIZE: 4 bytes
+ UInt8 args[2]; // 4; response arguments -- var size
+ } DlpRespType;
+
+typedef DlpRespType* DlpRespPtr;
+
+
+// Generic request/response body type(for utility routines)
+//
+typedef union DlpGenericBodyType {
+ UInt8 id; // request/response id
+ DlpReqType req; // request body
+ DlpRespType resp; // response body
+ } DlpGenericBodyType;
+
+typedef DlpGenericBodyType* DlpGenericBodyPtr;
+
+
+// dlpFuncRespFlag is used to form a function response ID from a
+// function ID by or'ing it with the function ID. For example: if
+// dlpFuncDeleteResource is the request ID, the correct response ID
+// must be (dlpFuncDeleteResource | dlpFuncRespFlag).
+//
+#define dlpFuncRespFlag 0x80
+
+// dlpFuncIDMask is used to mask out the function ID value
+#define dlpFuncIDMask 0x7f
+
+// dlpFirstArgID is the value of the first argument ID to be defined for
+// functions. Values below it are reserved.
+//
+#define dlpFirstArgID 0x20
+
+
+/************************************************************
+ *
+ * Argument headers used to "wrap" request and response arguments
+ *
+ * IMPORTANT: ARGUMENT WRAPPERS IN REQUESTS AND RESPONSES MUST
+ * ALWAYS START ON AN EVEN-BYTE BOUNDARY. The server
+ * implementation expects this to be the case.
+ *
+ *************************************************************/
+
+// dlpSmallArgFlag is used to identify "small" argument wrappers by
+// or'ing it with the argument id in argument header.
+//
+#define dlpSmallArgFlag 0x080
+
+// dlpShortArgIDMask is used to mask out the argument id value
+//
+#define dlpShortArgIDMask 0x7F
+
+
+// dlpLongArgFlag is used to identify "long" argument wrappers by
+// or'ing it with the argument id in argument header.
+//
+#define dlpLongArgFlag 0xC000
+
+// dlpLongArgIDMask is used to mask out the argument id value
+//
+#define dlpLongArgIDMask 0x3FFF
+
+
+//-------------------------------------------------------------------------
+// Int16 argument wrappers (v1.0-compatible)
+//-------------------------------------------------------------------------
+
+// Maximum Int16 argument size which can be "wrapped"
+#define dlpMaxTinyArgSize 0x000000FFL
+#define dlpMaxSmallArgSize 0x0000FFFFL
+#define dlpMaxShortArgSize dlpMaxSmallArgSize
+
+
+
+// Tiny argument header for data sizes up to 255 bytes(optimization)
+//
+typedef struct DlpTinyArgWrapperType {
+ // OFFSET
+ UInt8 bID; // 0; argument ID
+ UInt8 bSize; // 1; argument size (does NOT include this arg header)
+ // TOTAL: 2 bytes
+ } DlpTinyArgWrapperType;
+
+typedef struct DlpTinyArgType {
+ DlpTinyArgWrapperType wrapper; // 0; argument header
+ UInt8 data[2]; // 2; argument data -- var size
+ } DlpTinyArgType;
+
+
+// Small argument header for data sizes above 255 bytes(*may also be used for
+// smaller arguments when convenient*)
+//
+typedef struct DlpSmallArgWrapperType {
+ // OFFSET
+ UInt8 bID; // 0; argument ID
+ UInt8 unused; // 1; unused(for alignment) -- set to null!
+ UInt16 wSize; // 2; argument size (does NOT include this arg header)
+ // TOTAL: 4 bytes
+ } DlpSmallArgWrapperType;
+
+typedef struct DlpSmallArgType {
+ DlpSmallArgWrapperType wrapper; // 0; argument header
+ UInt8 data[2]; // 4; argument data -- var size
+ } DlpSmallArgType;
+
+// Unions of Int16 argument types
+typedef union DlpShortArgWrapperType {
+ UInt8 bID; // arg id
+ DlpTinyArgWrapperType tiny; // "tiny" arg wrapper
+ DlpSmallArgWrapperType small; // "tiny" arg wrapper
+ } DlpShortArgWrapperType;
+typedef DlpShortArgWrapperType* DlpShortArgWrapperPtr;
+
+typedef union DlpShortArgType {
+ UInt8 bID; // arg id
+ DlpTinyArgType tiny; // "tiny" arg
+ DlpSmallArgType small; // "small" arg
+ } DlpShortArgType;
+
+typedef DlpShortArgType* DlpShortArgPtr;
+
+
+
+//-------------------------------------------------------------------------
+// Int32 argument wrapper (v2.0 extension)
+//-------------------------------------------------------------------------
+// NOTE: Pilot v2.0 will implement the capability to parse long arguments
+// but will not originate them. This will assure backwards compatibility with
+// the 1.0 desktop as well as compatibility with the future version of the
+// desktop software which may originate the "long" argument wrappers.
+//
+// Int32 argument wrappers are identified by the dlpLongArgFlag bits set
+// in the argument id field.
+
+// Maximum long argument size which can be "wrapped"
+#define dlpMaxLongArgSize 0xFFFFFFFFL
+
+typedef struct DlpLongArgWrapperType {
+ // OFFSET
+ UInt16 wID; // 0; argument ID
+ UInt32 dwSize; // 2; argument size (does NOT include this arg header)
+ // TOTAL: 6 bytes
+ } DlpLongArgWrapperType;
+typedef DlpLongArgWrapperType* DlpLongArgWrapperPtr;
+
+typedef struct DlpLongArgType {
+ // OFFSET
+ DlpLongArgWrapperType wrapper; // 0; argument header
+ UInt8 data[2]; // 6; argument data -- var size
+ } DlpLongArgType;
+typedef DlpLongArgType* DlpLongArgPtr;
+
+
+//-------------------------------------------------------------------------
+// Unions of all argument and wrapper types
+//-------------------------------------------------------------------------
+
+// Union of all argument wrapper types
+typedef union DlpGenericArgWrapperType {
+ DlpShortArgWrapperType shortWrap; // "Int16" arg wrapper(tiny and small)
+ DlpLongArgWrapperType longWrap; // "long" arg wrapper
+ } DlpGenericArgWrapperType;
+typedef DlpGenericArgWrapperType* DlpGenericArgWrapperPtr;
+
+
+// Union of all argument types
+typedef union DlpGenericArgType {
+ DlpShortArgType shortArg; // "Int16" arg(tiny and small)
+ DlpLongArgType longArg; // "long" arg
+ } DlpGenericArgType;
+typedef DlpGenericArgType* DlpGenericArgPtr;
+
+
+/********************************************************************
+ * Desktop Link Protocol Parameters
+ ********************************************************************/
+
+// dlpCmdTimeoutSec -- this is the number of seconds to wait for a command
+// to begin coming in before timing out
+//
+#define dlpCmdTimeoutSec 30
+
+
+
+/************************************************************
+ * DLP function argument structures
+ *************************************************************/
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadUserInfo
+//////////////////////////////////////////////////////////////////////////
+// Request arguments: none
+//
+// Response arguments:
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory
+
+// Request argument structure:
+//
+// none.
+
+// Response argument structure:
+//
+#define dlpReadUserInfoRespArgID dlpFirstArgID
+
+typedef struct DlpReadUserInfoRespHdrType {
+ // OFFSET
+ UInt32 userID; // 0; user ID number (0 if none)
+ UInt32 viewerID; // 4; id assigned to viewer by the desktop
+ UInt32 lastSyncPC; // 8; last sync PC id (0 if none)
+ DlpDateTimeType succSyncDate; // 12; last successful sync (year = 0 if none)
+ DlpDateTimeType lastSyncDate; // 20; last sync date(year = 0 if none)
+ UInt8 userNameLen; // 28; length of user name field,
+ // including null (0 = no user name)
+ UInt8 passwordLen; // 29; length of encrypted password
+ // (0 = no password set)
+ // TOTAL: 30 bytes
+ } DlpReadUserInfoRespHdrType;
+
+typedef struct DlpReadUserInfoRespType {
+ // OFFSET
+ DlpReadUserInfoRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 30 bytes
+ UInt8 nameAndPassword[2]; // 30; user name -- var size
+ // User name begins at the nameAndPassword field and is null-terminated.
+ // The encrypted password follows the user name and is NOT null-terminated.
+ // The encrypted password may contain any byte values(0-255).
+ } DlpReadUserInfoRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteUserInfo
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+// user id (4 bytes)
+// last sync PC id(4 bytes)
+// user name
+//
+// Response arguments: none
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotEnoughSpace,
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpWriteUserInfoReqArgID dlpFirstArgID
+
+#define dlpMaxUserNameSize 41 // max user name size, including null byte
+
+typedef struct DlpWriteUserInfoReqHdrType {
+ // OFFSET
+ UInt32 userID; // 0; user ID number
+ UInt32 viewerID; // 4; id assigned to viewer by the desktop
+ UInt32 lastSyncPC; // 8; last sync PC id
+ DlpDateTimeType lastSyncDate; // 12; last sync date(year = 0 if none)
+ UInt8 modFlags; // 20; flags indicating which values are being
+ // modified; see the dlpUserInfoMod...
+ // flags defined below
+ UInt8 userNameLen; // 21; user name length, including null
+ // TOTAL: 22 bytes
+ } DlpWriteUserInfoReqHdrType;
+
+// Flags indicating which values are being changed by the dlpWriteUserInfo
+// request. These flags are used in the modFlags field of DlpWriteUserInfoReqHdrType.
+// These flags are additive.
+//
+#define dlpUserInfoModUserID 0x80 // changing the user id
+#define dlpUserInfoModSyncPC 0x40 // changing the last sync PC id
+#define dlpUserInfoModSyncDate 0x20 // changing sync date
+#define dlpUserInfoModName 0x10 // changing user name
+#define dlpUserInfoModViewerID 0x08 // changing the viewer id
+
+typedef struct DlpWriteUserInfoReqType {
+ // OFFSET
+ DlpWriteUserInfoReqHdrType
+ header; // 0; fixed-size header
+ // FIXED SIZE: 22 bytes
+ UInt8 userName[2]; // 22; user name -- var size
+ // User name begins at the userName field and is null-terminated.
+ } DlpWriteUserInfoReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadSysInfo
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem
+//
+
+// Request argument structure:
+//
+// none. DLP v1.0 and v1.1
+
+enum {
+ // NEW FOR DLP v1.2:
+ dlpReadSysInfoReqArgID = dlpFirstArgID
+ };
+
+
+// dlpReadSysInfoReqArgID request arg structure
+//
+typedef struct DlpReadSysInfoReqType {
+ // OFFSET
+ DlpVersionType dlpVer; // 0; DLP version of the caller
+ // TOTAL: 4 bytes
+ } DlpReadSysInfoReqType;
+
+
+// Response argument structure:
+//
+// Both response arguments are returned in one reply
+enum {
+ dlpReadSysInfoRespArgID = dlpFirstArgID,
+
+ // NEW FOR DLP v1.2:
+ dlpReadSysInfoVerRespArgID
+ };
+
+// dlpReadSysInfoRespArgID response arg structure:
+//
+typedef struct DlpReadSysInfoRespType {
+ // OFFSET
+ UInt32 romSWVersion; // 0; ROM-based sys software version
+ UInt32 localizationID;// 4; localization ID
+ UInt8 unused; // 8; unused(for alignment) -- set to null!
+ UInt8 prodIDSize; // 9; size of productID/model field
+ UInt32 prodID; // 10; product id (was variable size)
+ // TOTAL: 14 bytes
+ } DlpReadSysInfoRespType;
+
+
+// dlpReadSysInfoVerRespArgID response arg structure:
+//
+typedef struct DlpReadSysInfoVerRespType {
+ // OFFSET
+ DlpVersionType dlpVer; // 0; DLP version of the device
+ DlpVersionType compVer; // 4; product compatibility version of the device
+ UInt32 dwMaxRecSize; // 8; maximum record/resource size that may be allocated on
+ // the device given that sufficient free memory exists
+ // (0xFFFFFFFF = up to available memory)
+ // TOTAL: 12 bytes
+ } DlpReadSysInfoVerRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpGetSysDateTime
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes: none
+
+// Request argument structure:
+//
+// none.
+
+// Response argument structure:
+//
+#define dlpGetSysDateTimeRespArgID dlpFirstArgID
+
+typedef struct DlpGetSysDateTimeRespType {
+ // OFFSET
+ DlpDateTimeType dateTime; // 0; system date/time
+ // TOTAL: 8 bytes
+ } DlpGetSysDateTimeRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpSetSysDateTime
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+// new system date/time
+//
+// Response arguments: none
+//
+// Possible error codes
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpSetSysDateTimeReqArgID dlpFirstArgID
+
+typedef struct DlpSetSysDateTimeReqType {
+ // OFFSET
+ DlpDateTimeType dateTime; // 0; new system date/time
+ // TOTAL: 8 bytes
+ } DlpSetSysDateTimeReqType;
+
+typedef DlpSetSysDateTimeReqType* DlpSetSysDateTimeReqPtr;
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadStorageInfo
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrNotFound
+
+// Request argument structure:
+//
+enum {
+ dlpReadStorageInfoReqArgID = dlpFirstArgID
+ };
+
+typedef struct DlpReadStorInfoReqType {
+ // OFFSET
+ UInt8 startCardNo; // 0; card number to start at
+ // (0 = first)
+ UInt8 unused; // 1; unused -- set to null!
+ // TOTAL: 2 bytes
+ } DlpReadStorInfoReqType;
+
+
+// Response argument structure:
+//
+enum {
+ dlpReadStorageInfoRespArgID = dlpFirstArgID,
+ dlpReadStorageInfoExRespArgID // v1.1 extension
+ };
+
+//
+// dlpReadStorageInfoRespArgID:
+//
+
+// Card info structure of variable size
+typedef struct DlpCardInfoHdrType {
+ // OFFSET
+ UInt8 totalSize; // 0; total size of this card info
+ // *ROUNDED UP TO EVEN SIZE*
+ UInt8 cardNo; // 1; card number
+ UInt16 cardVersion; // 2; card version
+ DlpDateTimeType crDate; // 4; creation date/time
+ UInt32 romSize; // 12; ROM size
+ UInt32 ramSize; // 16; RAM size
+ UInt32 freeRam; // 20; total free data store RAM - Fixed in DLP v1.2 to exclude
+ // dynamic heap RAM
+ UInt8 cardNameSize; // 24; size of card name string
+ UInt8 manufNameSize; // 25; size of manuf. name string
+ // TOTAL: 26 bytes;
+ } DlpCardInfoHdrType;
+
+typedef struct DlpCardInfoType {
+ // OFFSET
+ DlpCardInfoHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 26 bytes;
+ UInt8 cardNameAndManuf[2];
+ // 26; card name and manuf. text -- var size
+ // Card name is the cardNameSize bytes of text at cardNameAndManuf,
+ // followed immediately by manufNameSize bytes of manufacturer name.
+ } DlpCardInfoType;
+
+
+typedef struct DlpReadStorInfoRespHdrType {
+ // OFFSET
+ UInt8 lastCardNo; // 0; card number of last card retrieved
+ UInt8 more; // 1; non-zero if there are more cards
+ UInt8 unused; // 2; unused -- set to null!
+ UInt8 actCount; // 3; actual count of structures returned
+ // TOTAL: 4 bytes
+ } DlpReadStorInfoRespHdrType;
+
+typedef struct DlpReadStorInfoRespType {
+ // OFFSET
+ DlpReadStorInfoRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 4 bytes
+ DlpCardInfoType cardInfo[1]; // 4; actCount of card info structures -- var size
+ } DlpReadStorInfoRespType;
+
+
+//
+// EXTENDED ARGUMENTS(DL v1.1): dlpReadStorageInfoExRespArgID
+//
+typedef struct DlpReadStorInfoExRespType {
+ // OFFSET
+ UInt16 romDBCount; // 0; ROM database count
+ UInt16 ramDBCount; // 2; RAM database count
+ UInt32 dwReserved1; // 4; RESERVED -- SET TO NULL!
+ UInt32 dwReserved2; // 8; RESERVED -- SET TO NULL!
+ UInt32 dwReserved3; // 12; RESERVED -- SET TO NULL!
+ UInt32 dwReserved4; // 16; RESERVED -- SET TO NULL!
+ // TOTAL: 20 bytes
+ } DlpReadStorInfoExRespType;
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadDBList
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrNotFound
+
+// Request argument structure:
+//
+#define dlpReadDBListReqArgID dlpFirstArgID
+
+typedef struct DlpReadDBListReqType {
+ // OFFSET
+ UInt8 srchFlags; // 0; search flags
+ UInt8 cardNo; // 1; card number -- 0-based
+ UInt16 startIndex; // 2; DB index to start at
+ // (0 = from beginning)
+ // TOTAL: 4 bytes
+ } DlpReadDBListReqType;
+
+#define dlpReadDBListFlagRAM 0x80 // Search for RAM-based
+#define dlpReadDBListFlagROM 0x40 // Search for ROM-based
+#define dlpReadDBListFlagMultiple 0x20 // OK to return multiple entries (DEFINED FOR DLP v1.2)
+
+
+// Response argument structure:
+//
+#define dlpReadDBListRespArgID dlpFirstArgID
+
+// Database info structure of variable size
+typedef struct DlpDBInfoHdrType {
+ // OFFSET
+ UInt8 totalSize; // 0; total size of the DB info (DlpDBInfoHdrType + name)
+ // *ROUNDED UP TO EVEN SIZE*
+ UInt8 miscFlags; // 1; dlpDbInfoMiscFlag... flags(v1.1) -- set all unused bits to null!
+ UInt16 dbFlags; // 2; DB flags: dlpDBFlagReadOnly,
+ // dlpDBFlagResDB, dlpDBFlagAppInfoDirty, dlpDBFlagOpen,
+ // dlpDBFlagBackup, etc;
+ UInt32 type; // 4; database type
+ UInt32 creator; // 8; database creator
+ UInt16 version; // 12; database version
+ UInt32 modNum; // 14; modification number
+ DlpDateTimeType crDate; // 18; creation date
+ DlpDateTimeType modDate; // 26; latest modification date
+ DlpDateTimeType backupDate; // 34; latest backup date
+ UInt16 dbIndex; // 42; DB index (or dlpDbInfoUnknownDbIndex for dlpFindDB)
+ // TOTAL: 44 bytes;
+ } DlpDBInfoHdrType;
+
+// Flags for the miscFlags field of DlpDBInfoHdrType
+#define dlpDbInfoMiscFlagExcludeFromSync 0x80 // DEFINED FOR DLP v1.1
+#define dlpDbInfoMiscFlagRamBased 0x40 // DEFINED FOR DLP v1.2
+
+// Unknown index value for the dbIndex field of DlpDBInfoHdrType
+#define dlpDbInfoUnknownDbIndex 0xFFFF
+
+
+typedef struct DlpDBInfoType {
+ // OFFSET
+ DlpDBInfoHdrType header; // 0; fixed-size header
+ // FIXED SIZE: 44 bytes;
+ UInt8 name[2]; // 44; databse name text -- var size and
+ // null-terminated
+ } DlpDBInfoType;
+
+
+typedef struct DlpReadDBListRespHdrType {
+ // OFFSET
+ UInt16 lastIndex; // 0; DB index of last entry retrieved
+ UInt8 flags; // 2; flags: dlpReadDBListRespFlagMore
+ UInt8 actCount; // 3; actual count of structures returned
+ // TOTAL: 4 bytes
+ } DlpReadDBListRespHdrType;
+
+// dlpReadDBListRespFlagMore flag: if set, indicates that there are more
+// databases to list -- this enables the server to send the listing
+// incrementally, reducing server memory requirements if necessary
+#define dlpReadDBListRespFlagMore 0x80
+
+typedef struct DlpReadDBListRespType {
+ // OFFSET
+ DlpReadDBListRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 4 bytes
+ DlpDBInfoType dbInfo[1]; // 4; actCount of DB info structures -- var size
+ } DlpReadDBListRespType;
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpOpenDB
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrTooManyOpenDatabases
+// dlpRespErrCantOpen
+
+// Request argument structure:
+//
+#define dlpOpenDBReqArgID dlpFirstArgID
+
+typedef struct DlpOpenDBReqHdrType {
+ // OFFSET
+ UInt8 cardNo; // 0; memory module number
+ UInt8 mode; // 1; open mode
+ // TOTAL: 2 bytes;
+ } DlpOpenDBReqHdrType;
+
+#define dlpOpenDBModeRead 0x80
+#define dlpOpenDBModeWrite 0x40
+#define dlpOpenDBModeExclusive 0x20
+#define dlpOpenDBModeShowSecret 0x10
+
+
+typedef struct DlpOpenDBReqType {
+ // OFFSET
+ DlpOpenDBReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 2 bytes;
+ UInt8 name[2]; // 2; databse name text -- var size
+ // zero-terminated
+ } DlpOpenDBReqType;
+
+typedef DlpOpenDBReqType* DlpOpenDBReqPtr;
+
+
+// Response argument structure:
+//
+#define dlpOpenDBRespArgID dlpFirstArgID
+//
+// The response argument is the 1-byte database ID to be passed in
+// subsequent read/write requests.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpCreateDB
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrAlreadyExists,
+// dlpRespErrCantOpen,
+// dlpRespErrNotEnoughSpace,
+// dlpRespErrTooManyOpenDatabases
+
+// Request argument structure:
+//
+#define dlpCreateDBReqArgID dlpFirstArgID
+
+typedef struct DlpCreateDBReqHdrType {
+ // OFFSET
+ UInt32 creator; // 0; DB creator
+ UInt32 type; // 4; DB type
+ UInt8 cardNo; // 8; memory module number
+ UInt8 unused; // 9; unused -- set to null
+ UInt16 dbFlags; // 10; allowed flags: dlpDBFlagResDB,
+ // dlpDBFlagBackup, dlpDBFlagOKToInstallNewer,
+ // dlpDBFlagResetAfterInstall
+ UInt16 version; // 12; DB version #
+ // TOTAL: 14 bytes;
+ } DlpCreateDBReqHdrType;
+
+typedef struct DlpCreateDBReqType {
+ // OFFSET
+ DlpCreateDBReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 12 bytes;
+ UInt8 name[2]; // 14; DB name text -- var size
+ // zero-terminated
+ } DlpCreateDBReqType;
+
+typedef DlpCreateDBReqType* DlpCreateDBReqPtr;
+
+
+// Response argument structure:
+//
+#define dlpCreateDBRespArgID dlpFirstArgID
+
+// The response argument is the 1-byte database ID to be passed in
+// subsequent read/write requests.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpCloseDB
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrParam,
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+typedef enum {
+ dlpCloseDBReqArgID = dlpFirstArgID, // close a specific database
+ dlpCloseDBAllReqArgID, // close all databases
+ dlpCloseDBExReqArgID // close a specific db and update backup
+ // and/or modification dates (PalmOS v3.0)
+ } DlpCloseDBReqArgID;
+
+// Argument structure to close a specific database(dlpCloseDBDBIDReqArgID):
+//
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+typedef UInt8 DlpCloseDBReqType;
+
+// Argument structure to close all databases(dlpCloseDBReqAllArgID):
+//
+// This request argument contains no data
+
+
+// Request type for dlpCloseDBExReqArgID (PalmOS v3.0):
+typedef struct DlpCloseDBExReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id to close
+ UInt8 bOptFlags; // 1; bitfield of dlpCloseDBExOptFlag... flags
+ // TOTAL: 2 bytes
+ } DlpCloseDBExReqType;
+
+// Option flags
+#define dlpCloseDBExOptFlagUpdateBackupDate 0x80 // Update the backup date after closing
+#define dlpCloseDBExOptFlagUpdateModDate 0x40 // Update the modification date after closing
+
+
+#define dlpCloseDBExOptAllFlags (dlpCloseDBExOptFlagUpdateBackupDate | dlpCloseDBExOptFlagUpdateModDate)
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpDeleteDB
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound,
+// dlpRespErrCantOpen,
+// dlpRespErrDatabaseOpen
+
+// Request argument structure:
+//
+#define dlpDeleteDBReqArgID dlpFirstArgID
+
+typedef struct DlpDeleteDBReqHdrType {
+ // OFFSET
+ UInt8 cardNo; // 0; memory module number
+ UInt8 unused; // 1; unused -- set to null!
+ // TOTAL: 2 bytes;
+ } DlpDeleteDBReqHdrType;
+
+
+typedef struct DlpDeleteDBReqType {
+ // OFFSET
+ DlpDeleteDBReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 2 bytes;
+ UInt8 name[2]; // 2; databse name text -- var size
+ // zero-terminated
+ } DlpDeleteDBReqType;
+
+typedef DlpDeleteDBReqType* DlpDeleteDBReqPtr;
+
+
+// Response argument structure:
+//
+// none.
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadOpenDBInfo
+//////////////////////////////////////////////////////////////////////////
+// Get information on an open database
+//
+// Possible error codes
+// dlpRespErrNoneOpen
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpReadOpenDBInfoArgID dlpFirstArgID
+
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+
+
+// Response argument structure:
+//
+#define dlpReadOpenDBInfoRespArgID dlpFirstArgID
+
+
+typedef struct DlpReadOpenDBInfoRespType {
+ // OFFSET
+ UInt16 numRec; // 0; number of records or resources
+ // TOTAL: 2 bytes
+ } DlpReadOpenDBInfoRespType;
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpMoveCategory
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrNoneOpen
+// dlpRespErrParam
+// dlpRespErrNotSupported
+// dlpRespErrReadOnly
+
+// Request argument structure:
+//
+#define dlpMoveCategoryReqArgID dlpFirstArgID
+
+typedef struct DlpMoveCategoryReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 fromCategory; // 1; id of the "from" category
+ UInt8 toCategory; // 2; id of the "to" category
+ UInt8 unused; // 3; unused -- set to null!
+ // TOTAL: 4 bytes;
+ } DlpMoveCategoryReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadAppBlock
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrNotFound
+// dlpRespErrNoneOpen
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpReadBlockReqArgID dlpFirstArgID
+
+typedef struct DlpReadBlockReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt16 offset; // 2; offset into the block
+ UInt16 numBytes; // 4; number of bytes to read starting
+ // at offset(-1 = to the end)
+ // TOTAL: 6 bytes;
+ } DlpReadBlockReqType;
+
+
+// Response argument structure:
+//
+#define dlpReadBlockRespArgID dlpFirstArgID
+
+typedef struct DlpReadBlockRespHdrType {
+ // OFFSET
+ UInt16 blockSize; // 0; actual block size -- may be greater
+ // than the amount of data returned
+ // TOTAL: 2 bytes
+ } DlpReadBlockRespHdrType;
+
+typedef struct DlpReadBlockRespType {
+ // OFFSET
+ DlpReadBlockRespHdrType //
+ header; // 0; fixed size header
+ // FIXED SIZE: 2 bytes
+ UInt8 data[2]; // 2; block data -- var size
+ } DlpReadBlockRespType;
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteAppBlock
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrReadOnly
+// dlpRespErrNotEnoughSpace
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpWriteBlockReqArgID dlpFirstArgID
+
+typedef struct DlpWriteBlockReqHdrType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt16 blockSize; // 2; total block size(0 = free existing block)
+ // TOTAL: 4 bytes;
+ } DlpWriteBlockReqHdrType;
+
+
+typedef struct DlpWriteBlockReqType {
+ // OFFSET
+ DlpWriteBlockReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 4 bytes;
+ UInt8 data[2]; // 4; block data -- var size
+ } DlpWriteBlockReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadSortBlock
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory
+// dlpRespErrNotFound
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+// see dlpReadAppBlock
+
+
+// Response argument structure:
+//
+// see dlpReadAppBlock
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteSortBlock
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+// see dlpWriteAppBlock
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadNextModifiedRec
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// see dlpReadRecord
+//
+
+// Request argument structure:
+//
+#define dlpReadNextModRecReqArgID dlpFirstArgID
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+
+
+// Response argument structure:
+//
+// Response argument id = dlpReadRecordRespArgID
+
+// Response argument structure = DlpReadRecordRespType
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpResetRecordIndex
+//////////////////////////////////////////////////////////////////////////
+// Resets the "next modified record" index to the beginning
+//
+// Possible error codes
+// dlpRespErrParam
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpResetRecordIndexReqArgID dlpFirstArgID
+
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadRecord
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrNotSupported,
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrNotFound,
+// dlpRespErrRecordBusy,
+// dlpRespErrNoneOpen
+
+typedef enum {
+ dlpReadRecordIdArgID = dlpFirstArgID,
+ dlpReadRecordIndexArgID
+ } DlpReadRecordReqArgID;
+
+// dlpReadRecordIdArgID request argument structure:
+//
+typedef struct DlpReadRecordByIDReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt32 recordID; // 2; unique record id
+ UInt16 offset; // 6; offset into the record
+ UInt16 numBytes; // 8; number of bytes to read starting
+ // at the offset(-1 = "to the end")
+ // TOTAL: 10 bytes;
+ } DlpReadRecordByIDReqType;
+
+// dlpReadRecordIndexArgID request argument structure:
+//
+typedef struct DlpReadRecordByIndexReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt16 index; // 2; record index
+ UInt16 offset; // 4; offset into the record
+ UInt16 numBytes; // 6; number of bytes to read starting
+ // at the offset(-1 = "to the end")
+ // TOTAL: 8 bytes;
+ } DlpReadRecordByIndexReqType;
+
+
+// Response argument structure:
+//
+#define dlpReadRecordRespArgID dlpFirstArgID
+
+typedef struct DlpReadRecordRespHdrType {
+ // OFFSET
+ UInt32 recordID; // 0; unique record id
+ UInt16 index; // 4; record index
+ UInt16 recSize; // 6; total record size in bytes
+ UInt8 attributes; // 8; record attributes
+ UInt8 category; // 9; record category index
+ // TOTAL: 10 bytes;
+ } DlpReadRecordRespHdrType;
+
+typedef struct DlpReadRecordRespType {
+ // OFFSET
+ DlpReadRecordRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 8 bytes;
+ UInt8 data[2]; // 8; record data -- var size
+ } DlpReadRecordRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadRecordIDList
+//////////////////////////////////////////////////////////////////////////
+// Returns a list of unique record id's. May need to call more than once
+// to get the entire list. dlpRespErrNotFound is returned when "start"
+// is out of bounds
+//
+// Possible error codes
+// dlpRespErrNotSupported,
+// dlpRespErrParam,
+// dlpRespErrNotFound,
+// dlpRespErrNoneOpen
+
+#define dlpReadRecordIDListReqArgID dlpFirstArgID
+
+// dlpReadRecordIDListReqArgID request argument structure:
+//
+typedef struct DlpReadRecordIDListReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 flags; // 1; request flags
+ UInt16 start; // 2; starting record index (0-based)
+ UInt16 maxEntries; // 4; maximum number of entries, or
+ // 0xFFFF to return as many as possible
+ // TOTAL: 6 bytes;
+ } DlpReadRecordIDListReqType;
+
+// dlpReadRecordIDListFlagSortDB: if set, DL Server will call the creator
+// application to resort the database before returning the list.
+#define dlpReadRecordIDListFlagSortDB 0x80
+
+
+// Response argument structure:
+//
+#define dlpReadRecordIDListRespArgID dlpFirstArgID
+
+typedef struct DlpReadRecordIDListRespHdrType {
+ // OFFSET
+ UInt16 numEntries; // 0; number of entries returned
+ // TOTAL: 2 bytes;
+ } DlpReadRecordIDListRespHdrType;
+
+typedef struct DlpReadRecordIDListRespType {
+ // OFFSET
+ DlpReadRecordIDListRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 2 bytes;
+ UInt32 recID[1]; // 8; list of record id's -- var size
+ } DlpReadRecordIDListRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteRecord
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrNotEnoughSpace
+// dlpRespErrNotSupported
+// dlpRespErrReadOnly
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpWriteRecordReqArgID dlpFirstArgID
+
+// dlpWriteRecordReqArgID -- required
+typedef struct DlpWriteRecordReqHdrType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 flags; // 1; set unused bits to null!
+ UInt32 recordID; // 2; unique record id or null
+ UInt8 attributes; // 6; record attributes -- only
+ // dlpRecAttrSecret is allowed here
+ // v1.1 extension:
+ // dlpRecAttrDeleted, dlpRecAttrArchived and
+ // dlpRecAttrDirty are also allowed.
+ UInt8 category; // 7; record category
+ // TOTAL: 8 bytes;
+ } DlpWriteRecordReqHdrType;
+
+#define dlpWriteRecordReqFlagDataIncluded 0x80 // original implementer of destop software always
+ // set this bit. Define it here for compatibility
+
+typedef struct DlpWriteRecordReqType {
+ // OFFSET
+ DlpWriteRecordReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 8 bytes;
+ UInt8 data[2]; // 8; record data -- var size
+ } DlpWriteRecordReqType;
+
+
+// Response argument structure:
+//
+#define dlpWriteRecordRespArgID dlpFirstArgID
+
+typedef struct DlpWriteRecordRespType {
+ // OFFSET
+ UInt32 recordID; // 0; record ID
+ // TOTAL: 4 bytes
+ } DlpWriteRecordRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpDeleteRecord
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrNotSupported
+// dlpRespErrReadOnly
+// dlpRespErrNoneOpen
+//
+
+// Request argument structure:
+//
+#define dlpDeleteRecordReqArgID dlpFirstArgID
+
+// Argument structure to delete by record ID(dlpDeleteRecordReqIDArgID):
+typedef struct DlpDeleteRecordReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 flags; // 1; flags (dlpDeleteRecFlagDeleteAll)
+ UInt32 recordID; // 2; unique record id (see flags)
+ // TOTAL: 6 bytes;
+ } DlpDeleteRecordReqType;
+
+// dlpDeleteRecFlagDeleteAll: if this flag is set, the reocordID field
+// is ignored and all database records will be deleted
+#define dlpDeleteRecFlagDeleteAll 0x80
+
+// dlpDeleteRecFlagByCategory: if this flag is set, the least significant byte
+// of the reocordID field contains the category id of records to be deleted (PalmOS 2.0)
+#define dlpDeleteRecFlagByCategory 0x40
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadResource
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrNoneOpen
+
+typedef enum {
+ dlpReadResourceIndexArgID = dlpFirstArgID,
+ dlpReadResourceTypeArgID
+ } DlpReadResourceReqArgID;
+
+// dlpReadResourceIndexArgID request argument structure:
+//
+typedef struct DlpReadResourceByIndexReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt16 index; // 2; resource index
+ UInt16 offset; // 4; offset into the resource
+ UInt16 numBytes; // 6; number of bytes to read starting
+ // at the offset(-1 = "to the end")
+ // TOTAL: 8 bytes;
+ } DlpReadResourceByIndexReqType;
+
+// dlpReadResourceTypeArgID request argument structure:
+//
+typedef struct DlpReadResourceByTypeReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; unused -- set to null!
+ UInt32 type; // 2; resource type
+ UInt16 id; // 6; resource id
+ UInt16 offset; // 8; offset into the resource
+ UInt16 numBytes; // 10; number of bytes to read starting
+ // at the offset(-1 = "to the end")
+ // TOTAL: 12 bytes;
+ } DlpReadResourceByTypeReqType;
+
+
+// Response argument structure:
+//
+#define dlpReadResourceRespArgID dlpFirstArgID
+
+typedef struct DlpReadResourceRespHdrType {
+ // OFFSET
+ UInt32 type; // 0; resource type
+ UInt16 id; // 4; resource id
+ UInt16 index; // 6; resource index
+ UInt16 resSize; // 8; total resource size in bytes
+ // TOTAL: 10 bytes;
+ } DlpReadResourceRespHdrType;
+
+typedef struct DlpReadResourceRespType {
+ // OFFSET
+ DlpReadResourceRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 6 bytes;
+ UInt8 resData[2]; // 6; resource data -- var size
+ } DlpReadResourceRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteResource
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotEnoughSpace,
+// dlpRespErrParam,
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpWriteResourceReqArgID dlpFirstArgID
+
+typedef struct DlpWriteResourceReqHdrType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 unused; // 1; inused -- set to null!
+ UInt32 type; // 2; resource type
+ UInt16 id; // 6; resource id
+ UInt16 resSize; // 8; total resource size
+ // TOTAL: 10 bytes;
+ } DlpWriteResourceReqHdrType;
+
+typedef struct DlpWriteResourceReqType {
+ // OFFSET
+ DlpWriteResourceReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 10 bytes;
+ UInt8 data[2]; // 10; resource data -- var size
+ } DlpWriteResourceReqType;
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpDeleteResource
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrNotSupported
+// dlpRespErrReadOnly
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpDeleteResourceReqArgID dlpFirstArgID
+
+typedef struct DlpDeleteResourceReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 flags; // 1; flags (dlpDeleteResFlagDeleteAll)
+ UInt32 type; // 2; resource type
+ UInt16 id; // 6; resource id
+ // TOTAL: 8 bytes;
+ } DlpDeleteResourceReqType;
+
+// dlpDeleteResFlagDeleteAll: if set, all resources in the db will be deleted
+#define dlpDeleteResFlagDeleteAll 0x80
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpCleanUpDatabase
+//////////////////////////////////////////////////////////////////////////
+// Deletes all records which are marked as archived or deleted in the
+// record database
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrReadOnly,
+// dlpRespErrNotSupported
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpCleanUpDatabaseReqArgID dlpFirstArgID
+
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpResetSyncFlags
+//////////////////////////////////////////////////////////////////////////
+// For record databases, reset all dirty flags.
+// For both record and resource databases, set the last sync time to NOW
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam
+// dlpRespErrReadOnly,
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+#define dlpResetSyncFlagsReqArgID dlpFirstArgID
+
+// The request argument is the 1-byte database ID returned in open/create
+// DB responses.
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpCallApplication
+//////////////////////////////////////////////////////////////////////////
+// Call an application entry point via an action code
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+
+// Request argument structure:
+//
+enum {
+ dlpCallApplicationReqArgIDV10 = dlpFirstArgID, // req id for Pilot v1.0
+ dlpCallAppReqArgID // req id for Pilot v2.0 and later
+ };
+
+// dlpCallApplicationReqArgIDV10:
+typedef struct DlpCallApplicationReqHdrTypeV10 {
+ // OFFSET
+ UInt32 creator; // 0; app DB creator id
+ UInt16 action; // 4; action code
+ UInt16 paramSize; // 6; custom param size
+ // TOTAL: 8 bytes
+ } DlpCallApplicationReqHdrTypeV10;
+
+typedef struct DlpCallApplicationReqTypeV10 {
+ // OFFSET
+ DlpCallApplicationReqHdrTypeV10 //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 8 bytes
+ UInt8 paramData[2]; // 8; custom param data -- var size
+ } DlpCallApplicationReqTypeV10;
+
+
+// dlpCallAppReqArgID (Pilot v2.0):
+typedef struct DlpCallAppReqHdrType {
+ // OFFSET
+ UInt32 creator; // 0; DB creator id of target executable
+ UInt32 type; // 4; DB type id of target executable
+ UInt16 action; // 8; action code
+ UInt32 dwParamSize; // 10; custom param size in number of bytes
+ UInt32 dwReserved1; // 14; RESERVED -- set to NULL!!!
+ UInt32 dwReserved2; // 18; RESERVED -- set to NULL!!!
+ // TOTAL: 22 bytes
+ } DlpCallAppReqHdrType;
+
+typedef struct DlpCallAppReqType {
+ // OFFSET
+ DlpCallAppReqHdrType //
+ hdr; // 0; fixed-size header
+ // FIXED SIZE: 22 bytes
+ UInt8 paramData[2]; // 22; custom param data -- var size
+ } DlpCallAppReqType;
+
+
+
+// Response argument structure:
+//
+enum {
+ dlpCallApplicationRespArgIDV10 = dlpFirstArgID, // resp id for Pilot v1.0
+ dlpCallAppRespArgID // resp id for Pilot v2.0 and later
+ };
+
+// dlpCallApplicationRespArgIDV10:
+typedef struct DlpCallApplicationRespHdrTypeV10 {
+ // OFFSET
+ UInt16 action; // 0; action code which was called
+ UInt16 resultCode; // 2; result error code returned by action
+ UInt16 resultSize; // 4; custom result data size
+ // TOTAL: 6 bytes
+ } DlpCallApplicationRespHdrTypeV10;
+
+typedef struct DlpCallApplicationRespTypeV10 {
+ // OFFSET
+ DlpCallApplicationRespHdrTypeV10 //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 6 bytes
+ UInt8 resultData[2]; // 6; custom result data -- var size
+ } DlpCallApplicationRespTypeV10;
+
+// dlpCallAppRespArgID:
+typedef struct DlpCallAppRespHdrType {
+ // OFFSET
+ UInt32 dwResultCode; // 0; result error code returned by handler
+ UInt32 dwResultSize; // 4; custom result data size
+ UInt32 dwReserved1; // 8; RESERVED -- SET TO NULL!!!
+ UInt32 dwReserved2; // 12; RESERVED -- SET TO NULL!!!
+ // TOTAL: 16 bytes
+ } DlpCallAppRespHdrType;
+
+typedef struct DlpCallAppRespType {
+ // OFFSET
+ DlpCallAppRespHdrType //
+ hdr; // 0; fixed-size header
+ // FIXED SIZE: 16 bytes
+ UInt8 resultData[2]; // 16; custom result data -- var size
+ } DlpCallAppRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpResetSystem
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem
+
+// Request argument structure:
+//
+// none.
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpAddSyncLogEntry
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotEnoughSpace,
+// dlpRespErrLimitExceeded,
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpAddSyncLogEntryReqArgID dlpFirstArgID
+
+typedef struct DlpAddSyncLogEntryReqType {
+ // OFFSET
+ UInt8 text[2]; // 0; entry text -- var size and
+ // null-terminated
+ } DlpAddSyncLogEntryReqType;
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpProcessRPC
+//////////////////////////////////////////////////////////////////////////
+// Remote Procedure Call interface
+//
+// Request arguments:
+// RPC command block
+//
+// Response arguments:
+// RPC reply block
+//
+// Possible error codes
+// 0 on success; otherwise error code from the TouchDown
+// RPC executor
+//
+// NOTE: this is a low-level system command which does not use arg wrappers.
+
+// Request argument structure:
+//
+// Block of RPC command data (no arg wrapper)
+
+// Response argument structure:
+//
+// Block of RPC reply data of same length as command block(no arg wrapper)
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpOpenConduit
+//////////////////////////////////////////////////////////////////////////
+// This command is sent before each conduit is opened by the desktop.
+// If the viewer has a cancel pending, it will return dlpRespErrCancelSync
+// in the response header's errorCode field.
+//
+// Request arguments: none.
+//
+// Response arguments: none.
+//
+// Possible error codes
+// dlpRespErrCancelSync
+
+// Request argument structure:
+//
+// none.
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpEndOfSync
+//////////////////////////////////////////////////////////////////////////
+// This command is sent by the desktop to end the sync.
+//
+// Request arguments: termination code: 0 = normal termination;
+// otherwise the client is aborting the sync
+//
+// Possible error codes
+// 0
+
+// Request argument structure:
+//
+#define dlpEndOfSyncReqArgID dlpFirstArgID
+
+typedef enum DlpSyncTermCode {
+ dlpTermCodeNormal = 0, // normal termination
+ dlpTermCodeOutOfMemory, // termination due to low memory on TD
+ dlpTermCodeUserCan, // user cancelled from desktop
+ dlpTermCodeOther, // catch-all abnormal termination code
+ dlpTermCodeIncompatibleProducts // incompatibility between desktop and handheld hotsync products
+ } DlpSyncTermCode;
+
+
+typedef struct DlpEndOfSyncReqType {
+ // OFFSET
+ UInt16 termCode; // 0; termination code
+ // TOTAL: 2 bytes
+ } DlpEndOfSyncReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadNextRecInCategory
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// see dlpReadRecord
+
+#define dlpReadNextRecInCategoryReqArgID dlpFirstArgID
+
+// dlpReadNextRecInCategoryReqArgID request argument structure:
+//
+typedef struct DlpReadNextRecInCategoryReqType {
+ // OFFSET
+ UInt8 dbID; // 0; database id
+ UInt8 category; // 1; category id
+ // TOTAL: 2 bytes;
+ } DlpReadNextRecInCategoryReqType;
+
+
+// Response argument structure:
+//
+// Response argument id = dlpReadRecordRespArgID
+
+// Response argument structure = DlpReadRecordRespType
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadNextModifiedRecInCategory
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// see dlpReadNextRecInCategory
+
+// Request argument structure:
+//
+// same as dlpReadNextRecInCategory
+
+// Response argument structure:
+//
+// same as dlpReadNextRecInCategory
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadAppPreference
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory,
+// dlpRespErrParam,
+// dlpRespErrNotFound,
+
+#define dlpReadAppPreferenceReqArgID dlpFirstArgID
+
+// dlpReadAppPreferenceReqArgID request argument structure:
+//
+typedef struct DlpReadAppPreferenceReqType {
+ // OFFSET
+ UInt32 creator; // 0; application creator type
+ UInt16 id; // 4; preference id
+ UInt16 reqBytes; // 6; max. number of preference bytes requested;
+ // pass 0xFFFF for actual size
+ UInt8 flags; // 8; command flags: dlpAppPrefReqFlagBackedUp - if set, use backed-up pref db
+ UInt8 unused; // 9; reserved/padding -- set to NUL!
+ // TOTAL: 10 bytes;
+ } DlpReadAppPreferenceReqType;
+
+#define dlpReadAppPrefActualSize 0xFFFF
+#define dlpAppPrefReqFlagBackedUp 0x80
+
+// Response argument structure:
+//
+#define dlpReadAppPreferenceRespArgID dlpFirstArgID
+
+typedef struct DlpReadAppPreferenceRespHdrType {
+ // OFFSET
+ UInt16 version; // 0; version number of the application
+ UInt16 actualSize; // 2; actual preference data size
+ UInt16 retBytes; // 4; number of preference bytes returned
+ // TOTAL: 6 bytes
+ } DlpReadAppPreferenceRespHdrType;
+
+typedef struct DlpReadAppPreferenceRespType {
+ // OFFSET
+ DlpReadAppPreferenceRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 6 bytes
+ UInt8 data[2]; // 6; custom result data -- var size
+ } DlpReadAppPreferenceRespType;
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteAppPreference
+//////////////////////////////////////////////////////////////////////////
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotEnoughSpace
+
+// Request argument structure:
+//
+#define dlpWriteAppPreferenceReqArgID dlpFirstArgID
+
+typedef struct DlpWriteAppPreferenceReqHdrType {
+ // OFFSET
+ UInt32 creator; // 0; application creator type
+ UInt16 id; // 4; preference id
+ UInt16 version; // 6; version number of the application
+ UInt16 prefSize; // 8; preference size(in number of bytes)
+ UInt8 flags; // 10; command flags: dlpAppPrefReqFlagBackedUp - if set, use backed-up pref db
+ UInt8 unused; // 11; reserved/padding -- set to NUL!
+ // TOTAL: 12 bytes;
+ } DlpWriteAppPreferenceReqHdrType;
+
+typedef struct DlpWriteAppPreferenceReqType {
+ // OFFSET
+ DlpWriteAppPreferenceReqHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 12 bytes;
+ UInt8 data[2]; // 12; record data -- var size
+ } DlpWriteAppPreferenceReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadNetSyncInfo
+//////////////////////////////////////////////////////////////////////////
+// Request arguments: none
+//
+// Response arguments:
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrMemory
+
+// Request argument structure:
+//
+// none.
+
+// Response argument structure:
+//
+#define dlpReadNetSyncInfoRespArgID dlpFirstArgID
+
+typedef struct DlpReadNetSyncInfoRespHdrType {
+ // OFFSET
+ UInt8 lanSyncOn; // 0; non-zero if Lan Sync is enabled
+ UInt8 bReserved1; // 1; reserved -- SET TO NULL!
+ UInt32 dwReserved1; // 2; reserved -- SET TO NULL!
+ UInt32 dwReserved2; // 6; reserved -- SET TO NULL!
+ UInt32 dwReserved3; // 10; reserved -- SET TO NULL!
+ UInt32 dwReserved4; // 14; reserved -- SET TO NULL!
+ UInt16 syncPCNameSize;// 18; length of sync PC host name,
+ // including null (0 = no host name)
+ UInt16 syncPCAddrSize;// 20; length of sync PC address,
+ // including null (0 = no address)
+ UInt16 syncPCMaskSize;// 22; length of sync PC subnet mask,
+ // including null (0 = no mask)
+ // TOTAL: 24 bytes
+ } DlpReadNetSyncInfoRespHdrType;
+
+typedef struct DlpReadNetSyncInfoRespType {
+ // OFFSET
+ DlpReadNetSyncInfoRespHdrType //
+ hdr; // 0; fixed-size header
+ // FIXED SIZE: 24 bytes
+ UInt8 syncAddr[2]; // 24; sync IP address/host name -- var size,
+ // null-terminated
+ } DlpReadNetSyncInfoRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpWriteNetSyncInfo
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+//
+// Response arguments: none
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotEnoughSpace,
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpWriteNetSyncInfoReqArgID dlpFirstArgID
+
+#define dlpMaxHostAddrLength 255 // maximum PC host name length, not including NULL
+
+typedef struct DlpWriteNetSyncInfoReqHdrType {
+ // OFFSET
+ UInt8 modFlags; // 0; flags indicating which values are being
+ // modified; see the dlpNetSyncInfoMod...
+ // flags defined below
+ UInt8 lanSyncOn; // 1; non-zero if Lan Sync is enabled
+ UInt32 dwReserved1; // 2; reserved -- SET TO NULL!
+ UInt32 dwReserved2; // 6; reserved -- SET TO NULL!
+ UInt32 dwReserved3; // 10; reserved -- SET TO NULL!
+ UInt32 dwReserved4; // 14; reserved -- SET TO NULL!
+ UInt16 syncPCNameSize;// 18; length of sync PC host name,
+ // including null (0 = no address/host name)
+ UInt16 syncPCAddrSize;// 20; length of sync PC address,
+ // including null (0 = no address)
+ UInt16 syncPCMaskSize;// 22; length of sync PC subnet mask,
+ // including null (0 = no mask)
+ // TOTAL: 24 bytes
+ } DlpWriteNetSyncInfoReqHdrType;
+
+// Flags indicating which values are being changed by the dlpWriteNetSyncInfo
+// request. These flags are used in the modFlags field of DlpWriteNetSyncInfoReqHdrType.
+// These flags are additive.
+//
+#define dlpNetSyncInfoModLanSyncOn 0x80 // changing the "lan sync on" setting
+#define dlpNetSyncInfoModSyncPCName 0x40 // changing the sync PC host name
+#define dlpNetSyncInfoModSyncPCAddr 0x20 // changing the sync PC address
+#define dlpNetSyncInfoModSyncPCMask 0x10 // changing the sync PC subnet mask
+
+typedef struct DlpWriteNetSyncInfoReqType {
+ // OFFSET
+ DlpWriteNetSyncInfoReqHdrType
+ hdr; // 0; fixed-size header
+ // FIXED SIZE: 24 bytes
+ UInt8 syncAddr[2]; // 24; sync IP address/host name -- var size,
+ // null-terminated
+ } DlpWriteNetSyncInfoReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpReadFeature
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+//
+// Response arguments:
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotFound,
+// dlpRespErrParam
+
+// Request argument structure:
+//
+#define dlpReadFeatureReqArgID dlpFirstArgID
+
+typedef struct DlpReadFeatureReqType {
+ // OFFSET
+ UInt32 dwFtrCreator; // 0; feature creator
+ UInt16 wFtrNum; // 4; feature number
+ // TOTAL: 6 bytes
+ } DlpReadFeatureReqType;
+
+
+// Response argument structure:
+//
+#define dlpReadFeatureRespArgID dlpFirstArgID
+
+typedef struct DlpReadFeatureRespType {
+ // OFFSET
+ UInt32 dwFeature; // 0; feature value
+ // TOTAL: 4 bytes
+ } DlpReadFeatureRespType;
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpFindDB
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+//
+// Response arguments:
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrNotFound,
+// dlpRespErrParam
+
+// Request argument structure:
+//
+
+// dlpFindDBByNameReqArgID, dlpFindDBByTypeCreatorReqArgID and dlpFindDBByOpenHandleReqArgID
+// are mutually exclusive
+enum {
+ dlpFindDBByNameReqArgID = dlpFirstArgID, // req id for card + name based search
+ dlpFindDBByOpenHandleReqArgID, // req id for search given an open db handle
+ dlpFindDBByTypeCreatorReqArgID // req id for type + creator based iterative search
+ };
+
+// Option flags
+#define dlpFindDBOptFlagGetAttributes 0x80 // get database attributes -- this is
+ // an option to allow find operations to skip
+ // returning this data as a performance optimization
+
+#define dlpFindDBOptFlagGetSize 0x40 // get record count and data size also -- this is
+ // an option because the operation can take a long
+ // time, which we would rather avoid if it is not needed
+
+#define dlpFindDBOptFlagGetMaxRecSize 0x20 // get max rec/resource size -- this is
+ // an option because the operation can take a long
+ // time, which we would rather avoid if it is not needed
+ // (dlpFindDBOptFlagGetMaxRecSize is only supported for
+ // dlpFindDBByOpenHandleReqArgID)
+
+// Request type for dlpdlpFindDBByNameReqArgID:
+typedef struct DlpFindDBByNameReqHdrType {
+ // OFFSET
+ UInt8 bOptFlags; // 0; bitfield of dlpFindDBOptFlag... flags
+ UInt8 bCardNo; // 2; card number to search
+ // TOTAL: 4 bytes
+ } DlpFindDBByNameReqHdrType;
+
+typedef struct DlpFindDBByNameReqType {
+ // OFFSET
+ DlpFindDBByNameReqHdrType //
+ header; // 0; fixed size header
+ // FIXED SIZE: 4 bytes
+ UInt8 name[2]; // variable size -- zero-terminated database name string
+ } DlpFindDBByNameReqType;
+
+
+// Request type for dlpFindDBByOpenHandleReqArgID:
+typedef struct DlpFindDBByOpenHandleReqType {
+ // OFFSET
+ UInt8 bOptFlags; // 0; bitfield of dlpFindDBOptFlag... flags
+ UInt8 bDbID; // 1; database id returned by dlpOpenDB or dlpCreateDB
+ // TOTAL: 2 bytes
+ } DlpFindDBByOpenHandleReqType;
+
+
+// Request type for dlpFindDBByTypeCreatorReqArgID:
+typedef struct DlpFindDBByTypeCreatorReqType {
+ // OFFSET
+ UInt8 bOptFlags; // 0; bitfield of dlpFindDBOptFlag... flags
+ UInt8 bSrchFlags; // 1; bitfield of dlpFindDBSrchFlag... flags
+ UInt32 dwType; // 2; db type id (zero = wildcard)
+ UInt32 dwCreator; // 6; db creator id (zero = wildcard)
+ // TOTAL: 10 bytes
+ } DlpFindDBByTypeCreatorReqType;
+
+#define dlpFindDBSrchFlagNewSearch 0x80 // set to beging a new search
+#define dlpFindDBSrchFlagOnlyLatest 0x40 // set to search for the latest version
+
+
+
+// Response argument structures for dlpFindDBByNameReqArgID, dlpFindDBByOpenHandleReqArgID and
+// dlpFindDBByTypeCreatorReqArgID (if found):
+//
+enum {
+ dlpFindDBBasicRespArgID = dlpFirstArgID, // resp arg id for basic info
+ // (if dlpFindDBOptFlagGetAttributes is set)
+ dlpFindDBSizeRespArgID // resp arg id for size info
+ // (if dlpFindDBOptFlagGetSize or dlpFindDBOptFlagGetMaxRecSize
+ // are set)
+ };
+
+
+// dlpFindDBBasicRespArgID (returned only if dlpFindDBOptFlagGetAttributes is set):
+
+typedef struct DlpFindDBBasicRespHdrType {
+ // OFFSET
+ UInt8 bCardNo; // 0; card number of database
+ UInt8 bReserved; // 1; RESERVED -- SET TO NULL
+ UInt32 dwLocalID; // 2; local id of the database (for internal use)
+ UInt32 dwOpenRef; // 6; db open ref of the database if it is currently opened
+ // by the caller; zero otherwise (for internal use) can
+ // change after read record list
+ DlpDBInfoHdrType info; //10; database info (creator, type, flags, etc.) MUST BE LAST FIELD
+ // TOTAL: 54 bytes
+ } DlpFindDBBasicRespHdrType;
+
+typedef struct DlpFindDBBasicRespType {
+ // OFFSET
+ DlpFindDBBasicRespHdrType //
+ header; // 0; fixed-size header
+ // FIXED SIZE: 54 bytes
+ UInt8 name[2]; // variable size -- zero-terminated database name string
+ } DlpFindDBBasicRespType;
+
+
+
+// dlpFindDBSizeRespArgID (returned only if dlpFindDBOptFlagGetSize or dlpFindDBOptFlagGetMaxRecSize is set):
+
+typedef struct DlpFindDBSizeRespType {
+ // OFFSET
+
+ // Returned if dlpFindDBOptFlagGetSize is set for all queries:
+ // (otherwise, fields are set to zero)
+ UInt32 dwNumRecords; // 0; record/resource count
+ UInt32 dwTotalBytes; // 4; total bytes used by db
+ UInt32 dwDataBytes; // 8; bytes used for data
+
+ // Returned if dlpFindDBOptFlagGetSize is set for dlpFindDBByOpenHandleReqArgID only:
+ // (otherwise, fields are set to zero)
+ UInt32 dwAppBlkSize; //12; size of app info block size (for
+ // dlpFindDBByOpenHandleReqArgID only)
+ UInt32 dwSortBlkSize; //16; size of sort info block size(for
+ // dlpFindDBByOpenHandleReqArgID only)
+ //
+ // Returned if dlpFindDBOptFlagGetMaxRecSize is set for dlpFindDBByOpenHandleReqArgID only:
+ // (otherwise, field is set to zero)
+ UInt32 dwMaxRecSize; //20; size of largest record or resource in the database (for
+ // dlpFindDBByOpenHandleReqArgID + dlpFindDBOptFlagGetMaxRecSize only)
+ // TOTAL: 24 bytes
+ } DlpFindDBSizeRespType;
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// dlpSetDBInfo
+//////////////////////////////////////////////////////////////////////////
+// Request arguments:
+//
+// Response arguments:
+//
+// Possible error codes
+// dlpRespErrSystem,
+// dlpRespErrParam,
+// dlpRespErrNotFound
+// dlpRespErrNotEnoughSpace
+// dlpRespErrNotSupported
+// dlpRespErrReadOnly
+// dlpRespErrNoneOpen
+
+// Request argument structure:
+//
+
+enum {
+ dlpSetDBInfoReqArgID = dlpFirstArgID
+ };
+
+
+typedef struct DlpSetDBInfoReqHdrType {
+ // OFFSET
+ UInt8 dbID; // 0; database id returned by dlpOpenDB or dlpCreateDB
+ UInt8 bReserved; // 1; RESERVED -- SET TO NULL
+ UInt16 wClrDbFlags; // 2; flags to clear; allowed DB flags: dlpDBFlagAppInfoDirty,
+ // dlpDBFlagBackup, dlpDBFlagOKToInstallNewer,
+ // dlpDBFlagResetAfterInstall, dlpDBFlagCopyPrevention;
+ // 0 = don't change
+ UInt16 wSetDbFlags; // 4; flags to set; allowed DB flags: dlpDBFlagAppInfoDirty,
+ // dlpDBFlagBackup, dlpDBFlagOKToInstallNewer,
+ // dlpDBFlagResetAfterInstall, dlpDBFlagCopyPrevention;
+ // 0 = don't change
+ UInt16 wDbVersion; // 6; database version; dlpSetDBInfoNoVerChange = don't change
+ DlpDateTimeType crDate; // 8; creation date; zero year = don't change
+ DlpDateTimeType modDate; //16; modification date; zero year = don't change
+ DlpDateTimeType bckUpDate; //24; backup date; zero year = don't change
+ UInt32 dwType; //32; database type id; zero = don't change
+ UInt32 dwCreator; //36; database creator id; zero = don't change
+ // TOTAL: 40 bytes
+ } DlpSetDBInfoReqHdrType;
+
+#define dlpSetDBInfoNoVerChange 0xFFFF
+
+typedef struct DlpSetDBInfoReqType {
+ // OFFSET
+ DlpSetDBInfoReqHdrType //
+ header; // 0; fixed size header
+ // FIXED SIZE: 40 bytes
+ UInt8 name[2]; // variable size -- zero-terminated database name string
+ } DlpSetDBInfoReqType;
+
+
+// Response argument structure:
+//
+// none.
+
+
+
+/************************************************************
+ * Macros
+ *************************************************************/
+
+
+#endif // __DLCOMMON_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/DLServer.h b/SrcShared/Palm/Platform/Incs/Core/System/DLServer.h
new file mode 100644
index 0000000..7412ea8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/DLServer.h
@@ -0,0 +1,418 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DLServer.h
+ *
+ * Description:
+ * Desktop Link Protocol(DLP) Server implementation definitions.
+ *
+ * History:
+ * vmk 7/12/95 Created by Vitaly Marty Kruglikov
+ * vmk 7/12/96 Converted to HTAL architecture
+ * jmp 12/23/99 Fix <> vs. "" problem.
+ *
+ *****************************************************************************/
+
+#ifndef __DL_SERVER_H__
+#define __DL_SERVER_H__
+
+// Pilot common definitions
+#include <PalmTypes.h>
+#include <DataMgr.h> // for DmOpenRef
+
+#include <PalmOptErrorCheckLevel.h>
+
+
+/************************************************************
+ * DLK result codes
+ * (dlkErrorClass is defined in SystemMgr.h)
+ *************************************************************/
+#pragma mark *Error Codes*
+
+#define dlkErrParam (dlkErrorClass | 1) // invalid parameter
+#define dlkErrMemory (dlkErrorClass | 2) // memory allocation error
+#define dlkErrNoSession (dlkErrorClass | 3) // could not establish a session
+
+#define dlkErrSizeErr (dlkErrorClass | 4) // reply length was too big
+
+#define dlkErrLostConnection (dlkErrorClass | 5) // lost connection
+#define dlkErrInterrupted (dlkErrorClass | 6) // sync was interrupted (see sync state)
+#define dlkErrUserCan (dlkErrorClass | 7) // cancelled by user
+
+
+
+/********************************************************************
+ * Desktop Link system preferences resource for user info
+ * id = sysResIDDlkUserInfo, defined in SystemResources.h
+ ********************************************************************/
+#pragma mark *User Info Preference*
+
+#define dlkMaxUserNameLength 40
+#define dlkUserNameBufSize (dlkMaxUserNameLength + 1)
+
+#if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
+#define dlkMaxLogSize (20 * 1024)
+#else
+#define dlkMaxLogSize (2 * 1024)
+#endif
+
+typedef enum DlkSyncStateType {
+ dlkSyncStateNeverSynced = 0, // never synced
+ dlkSyncStateInProgress, // sync is in progress
+ dlkSyncStateLostConnection, // connection lost during sync
+ dlkSyncStateLocalCan, // cancelled by local user on handheld
+ dlkSyncStateRemoteCan, // cancelled by user from desktop
+ dlkSyncStateLowMemoryOnTD, // sync ended due to low memory on handheld
+ dlkSyncStateAborted, // sync was aborted for some other reason
+ dlkSyncStateCompleted, // sync completed normally
+
+ // Added in PalmOS v3.0:
+ dlkSyncStateIncompatibleProducts // sync ended because desktop HotSync product
+ // is incompatible with this version
+ // of the handheld HotSync
+ } DlkSyncStateType;
+
+#define dlkUserInfoPrefVersion 0x0102 // current user info pref version: 1.2
+
+typedef struct DlkUserInfoHdrType {
+ UInt16 version; // pref version number
+ UInt32 userID; // user id
+ UInt32 viewerID; // id assigned to viewer by the desktop
+ UInt32 lastSyncPC; // last sync PC id
+ UInt32 succSyncDate; // last successful sync date
+ UInt32 lastSyncDate; // last sync date
+ DlkSyncStateType lastSyncState; // last sync status
+ UInt8 reserved1; // Explicitly account for 16-bit alignment padding
+ UInt16 lanSyncEnabled;// if non-zero, LAN Sync is enabled
+ UInt32 hsTcpPortNum; // TCP/IP port number of Desktop HotSync
+ UInt32 dwReserved1; // RESERVED -- set to NULL!
+ UInt32 dwReserved2; // RESERVED -- set to NULL!
+ UInt8 userNameLen; // length of name field(including null)
+ UInt8 reserved2; // Explicitly account for 16-bit alignment padding
+ UInt16 syncLogLen; // length of sync log(including null)
+ } DlkUserInfoHdrType;
+
+typedef struct DlkUserInfoType {
+ DlkUserInfoHdrType header; // fixed size header
+ Char nameAndLog[2]; // user name, followed by sync log;
+ // both null-terminated(for debugging)
+ } DlkUserInfoType;
+
+typedef DlkUserInfoType* DlkUserInfoPtr; // user info pointer
+
+
+/********************************************************************
+ * Desktop Link system preferences resource for the Conduit Filter Table
+ * id = sysResIDDlkCondFilterTab, defined in SystemResources.h
+ ********************************************************************/
+#pragma mark *Conduit Filter Preference*
+
+//
+// Table for specifying conduits to "filter out" during HotSync
+//
+
+// This table consists of DlkCondFilterTableHdrType header followed by a
+// variable number of DlkCondFilterEntryType entries
+
+typedef struct DlkCondFilterTableHdrType {
+ UInt16 entryCount;
+ } DlkCondFilterTableHdrType;
+typedef DlkCondFilterTableHdrType* DlkCondFilterTableHdrPtr;
+
+typedef struct DlkCondFilterEntryType {
+ UInt32 creator;
+ UInt32 type;
+ } DlkCondFilterEntryType;
+typedef DlkCondFilterEntryType* DlkCondFilterEntryPtr;
+
+typedef struct DlkCondFilterTableType {
+ DlkCondFilterTableHdrType
+ hdr; // table header
+ DlkCondFilterEntryType
+ entry[1]; // variable number of entries
+ } DlkCondFilterTableType;
+typedef DlkCondFilterTableType* DlkCondFilterTablePtr;
+
+
+
+/********************************************************************
+ * DLK Session Structures
+ ********************************************************************/
+#pragma mark *Session Structures*
+
+
+// DesktopLink event notification callback. If non-zero is returned,
+// sync will be cancelled as soon as a safe point is reached.
+typedef enum {
+ dlkEventOpeningConduit = 1, // conduit is being opened -- paramP
+ // is null;
+
+ dlkEventDatabaseOpened, // client has opened a database -- paramP
+ // points to DlkEventDatabaseOpenedType;
+
+ dlkEventCleaningUp, // last stage of sync -- cleaning up (notifying apps, etc) --
+ // paramP is null
+
+ dlkEventSystemResetRequested // system reset was requested by the desktop client
+ // (the normal action is to delay the reset until
+ // end of sync) -- paramP is null
+ } DlkEventType;
+
+// Prototype for the event notification callback
+typedef Int16 (*DlkEventProcPtr)(UInt32 eventRef, DlkEventType dlkEvent,
+ void * paramP);
+
+// Parameter structure for dlkEventDatabaseOpened
+// Added new fields for Pilot v2.0 vmk 12/24/96
+typedef struct DlkEventDatabaseOpenedType {
+ DmOpenRef dbR; // open database ref (v2.0)
+ Char * dbNameP; // database name
+ UInt32 dbType; // databse type (v2.0)
+ UInt32 dbCreator; // database creator
+ } DlkEventDatabaseOpenedType;
+
+
+// Prototype for the "user cancel" check callback function
+typedef Int16 (*DlkUserCanProcPtr)(UInt32 canRef);
+
+
+//
+// List of modified database creators maintained by DLP Server
+//
+typedef struct DlkDBCreatorList {
+ UInt16 count; // number of entries in the list
+ MemHandle listH; // chunk MemHandle of the creators list
+ } DlkDBCreatorList;
+
+
+//
+// Desktop Link Server state flags
+//
+#define dlkStateFlagVerExchanged 0x8000
+#define dlkStateFlagSyncDateSet 0x4000
+
+//
+// DLP Server session information
+//
+typedef struct DlkServerSessionType {
+ UInt16 htalLibRefNum; // HTAL library reference number - the library has a live connection
+ UInt32 maxHtalXferSize; // Maximum transfer block size
+
+ // Information supplied by user
+ DlkEventProcPtr eventProcP; // ptr to DesktopLink event notification proc
+ UInt32 eventRef; // user reference value for event proc
+ DlkUserCanProcPtr canProcP; // ptr to user-cancel function
+ UInt32 canRef; // parameter for canProcP()
+ MemHandle condFilterH; // MemHandle of conduit filter table(DlkCondFilterTableHdrPtr) or 0 for none
+
+ // Current database information
+ UInt8 dlkDBID; // Desktop Link database MemHandle of the open database
+ UInt8 reserved1;
+ DmOpenRef dbR; // TouchDown database access pointer -- if null, no current db
+ UInt16 cardNo; // memory module number
+ UInt32 dbCreator; // creator id
+ Char dbName[dmDBNameLength]; // DB name
+ UInt16 dbOpenMode; // database open mode
+ Boolean created; // true if the current db was created
+ Boolean isResDB; // set to true if resource database
+ Boolean ramBased; // true if the db is in RAM storage
+ Boolean readOnly; // true if the db is read-only
+ LocalID dbLocalID; // TouchDown LocalID of the database
+ UInt32 initialModNum; // initial DB modification number
+ UInt32 curRecIndex; // current record index for enumeration functions
+ // (0=beginning)
+
+ // List of modified database creators maintained by DLP Server
+ DlkDBCreatorList creatorList;
+
+ // Session status information
+// DlkSyncStateType syncState; // current sync state;
+ UInt8 syncState; // current sync state;
+
+ Boolean complete; // set to true when completion request
+ // has been received
+
+ Boolean conduitOpened; // set to true after the first coduit
+ // is opened by remote
+
+ Boolean logCleared; // set to true after sync log has been
+ // cleared during the current session;
+ // The log will be cleared before any new entries are added or at
+ // the end of sync in case no new entries were added.
+ // (we do not clear the log at the beginning of sync in case the
+ // user cancels during the "identifying user" phase; in this
+ // event, the spec calls for preserving the original log)
+
+ Boolean resetPending; // set to true if system reset is pending;
+ // the reset will be carried out at end
+ // of sync
+
+ // Current request information
+ Boolean gotCommand; // set to true when got a request
+ UInt8 cmdTID; // current transaction ID
+ UInt8 reserved2;
+ UInt16 cmdLen; // size of data in request buffer
+ void * cmdP; // pointer to command
+ MemHandle cmdH; // MemHandle of command buffer
+
+ // Fields added in PalmOS v3.0
+ UInt16 wStateFlags; // bitfield of dlkStateFlag... bits
+ DmSearchStateType dbSearchState; // database search state for iterative
+ // searches using DmGetNextDatabaseByTypeCreator
+ } DlkServerSessionType;
+
+typedef DlkServerSessionType* DlkServerSessionPtr;
+
+
+/********************************************************************
+ * DLK Function Parameter Structures
+ ********************************************************************/
+#pragma mark *Function Parameter Structures*
+
+//
+// Parameter passed to DlkControl()
+//
+typedef enum DlkCtlEnum {
+ dlkCtlFirst = 0, // reserve 0
+
+ //
+ // Pilot v2.0 control codes:
+ //
+ dlkCtlGetPCHostName, // param1P = ptr to text buffer; (can be null if *(UInt16 *)param2P is 0)
+ // param2P = ptr to buffer size(UInt16);
+ // returns actual length, including null, in *(UInt16 *)param2P which may be bigger than # of bytes copied.
+
+ dlkCtlSetPCHostName, // param1P = ptr to host name(zero-terminated) or NULL if *param2 is 0
+ // param2P = ptr to length(UInt16), including NULL (if length is 0, the current name is deleted)
+
+ dlkCtlGetCondFilterTable, // param1P = ptr to destination buffer for filter table, or NULL if *param2 is 0
+ // param2P = on entry, ptr to size of buffer(UInt16) (the size may be 0)
+ // on return, size, in bytes, of the actual filter table
+
+ dlkCtlSetCondFilterTable, // param1P = ptr to to conduit filter table, or NULL if *param2 is 0
+ // param2P = ptr to size of filter table(UInt16) (if size is 0, the current table will be deleted)
+
+ dlkCtlGetLANSync, // param1P = ptr to store for the LANSync setting(UInt16): 0 = off, otherwise on
+ // param2P = not used, set to NULL
+
+ dlkCtlSetLANSync, // param1P = ptr to the LANSync setting(UInt16): 0 = off, otherwise on
+ // param2P = not used, set to NULL
+
+ dlkCtlGetHSTCPPort, // param1P = ptr to store for the Desktop HotSync TCP/IP port number(UInt32) -- zero if not set
+ // param2P = not used, set to NULL
+
+ dlkCtlSetHSTCPPort, // param1P = ptr to the Desktop HotSync TCP/IP port number(UInt32)
+ // param2P = not used, set to NULL
+
+ dlkCtlSendCallAppReply, // param1P = ptr to DlkCallAppReplyParamType structure
+ // param2P = not used, set to NULL
+ //
+ // RETURNS: send error code; use this error code
+ // as return value from the action code handler
+
+
+ dlkCtlGetPCHostAddr, // param1P = ptr to text buffer; (can be null if *(UInt16 *)param2P is 0)
+ // param2P = ptr to buffer size(UInt16);
+ // returns actual length, including null, in *(UInt16 *)param2P which may be bigger than # of bytes copied.
+
+ dlkCtlSetPCHostAddr, // param1P = ptr to host address string(zero-terminated) or NULL if *param2 is 0
+ // param2P = ptr to length(UInt16), including NULL (if length is 0, the current name is deleted)
+
+
+ dlkCtlGetPCHostMask, // param1P = ptr to text buffer; (can be null if *(UInt16 *)param2P is 0)
+ // param2P = ptr to buffer size(UInt16);
+ // returns actual length, including null, in *(UInt16 *)param2P which may be bigger than # of bytes copied.
+
+ dlkCtlSetPCHostMask, // param1P = ptr to subnet mask string(zero-terminated) or NULL if *param2 is 0
+ // param2P = ptr to length(UInt16), including NULL (if length is 0, the current name is deleted)
+
+
+ dlkCtlLAST // *KEEP THIS ENTRY LAST*
+
+} DlkCtlEnum;
+
+
+//
+// Parameter passed to DlkStartServer()
+//
+typedef struct DlkServerParamType {
+ UInt16 htalLibRefNum; // HTAL library reference number - the library has a live connection
+ DlkEventProcPtr eventProcP; // ptr to DesktopLink event notification proc
+ UInt32 eventRef; // user reference value for event proc
+ UInt32 reserved1; // reserved - set to NULL
+ UInt32 reserved2; // reserved - set to NULL
+ MemHandle condFilterH; // MemHandle of conduit filter table(DlkCondFilterTableHdrPtr) or 0 for none
+ } DlkServerParamType;
+
+typedef DlkServerParamType* DlkServerParamPtr;
+
+
+
+//
+// Parameter passed with DlkControl()'s dlkCtlSendCallAppReply code
+//
+typedef struct DlkCallAppReplyParamType {
+ UInt16 pbSize; // size of this parameter block (set to sizeof(DlkCallAppReplyParamType))
+ UInt32 dwResultCode; // result code to be returned to remote caller
+ void * resultP; // ptr to result data
+ UInt32 dwResultSize; // size of reply data in number of bytes
+ void * dlRefP; // DesktopLink reference pointer from
+ // SysAppLaunchCmdHandleSyncCallAppType
+ UInt32 dwReserved1; // RESERVED -- set to null!!!
+ } DlkCallAppReplyParamType;
+
+
+/********************************************************************
+ * DesktopLink Server Routines
+ ********************************************************************/
+#pragma mark *Function Prototypes*
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// SERVER API
+//
+
+// * RETURNED: 0 if session ended successfully; otherwise: dlkErrParam,
+// * dlkErrNoSession, dlkErrLostConnection, dlkErrMemory,
+// * dlkErrUserCan
+extern Err DlkStartServer(DlkServerParamPtr paramP)
+ SYS_TRAP(sysTrapDlkStartServer);
+
+extern Err DlkGetSyncInfo(UInt32 * succSyncDateP, UInt32 * lastSyncDateP,
+ DlkSyncStateType* syncStateP, Char * nameBufP,
+ Char * logBufP, Int32 * logLenP)
+ SYS_TRAP(sysTrapDlkGetSyncInfo);
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER... this is a temporary function for debugging modem manager.
+// remove it when done.
+#endif // PUBLIC_STUFF_STRIPPED
+extern void DlkSetLogEntry(const Char * textP, Int16 textLen, Boolean append)
+ SYS_TRAP(sysTrapDlkSetLogEntry);
+
+// Dispatch a DesktopLink request (exposed for patching)
+extern Err DlkDispatchRequest(DlkServerSessionPtr sessP)
+ SYS_TRAP(sysTrapDlkDispatchRequest);
+
+extern Err DlkControl(DlkCtlEnum op, void * param1P, void * param2P)
+ SYS_TRAP(sysTrapDlkControl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+/********************************************************************
+ * DLK Macros
+ ********************************************************************/
+
+
+
+#endif // __DL_SERVER_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/DataMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/DataMgr.h
new file mode 100644
index 0000000..0381b29
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/DataMgr.h
@@ -0,0 +1,540 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DataMgr.h
+ *
+ * Description:
+ * Header for the Data Manager
+ *
+ * History:
+ * 11/14/94 RM - Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifndef __DATAMGR_H__
+#define __DATAMGR_H__
+
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+#include <ErrorBase.h> // Error numbers
+
+// Other headers we depend on
+#include <MemoryMgr.h>
+
+
+typedef UInt32 DmResType;
+typedef UInt16 DmResID;
+
+/************************************************************
+ * Category equates
+ *************************************************************/
+#define dmRecAttrCategoryMask 0x0F // mask for category #
+#define dmRecNumCategories 16 // number of categories
+#define dmCategoryLength 16 // 15 chars + 1 null terminator
+
+#define dmAllCategories 0xff
+#define dmUnfiledCategory 0
+
+#define dmMaxRecordIndex 0xffff
+
+
+
+// Record Attributes
+//
+// *** IMPORTANT:
+// ***
+// *** Any changes to record attributes must be reflected in dmAllRecAttrs and dmSysOnlyRecAttrs ***
+// ***
+// *** Only one nibble is available for record attributes
+//
+// *** ANY CHANGES MADE TO THESE ATTRIBUTES MUST BE REFLECTED IN DESKTOP LINK
+// *** SERVER CODE (DLCommon.h, DLServer.c)
+#define dmRecAttrDelete 0x80 // delete this record next sync
+#define dmRecAttrDirty 0x40 // archive this record next sync
+#define dmRecAttrBusy 0x20 // record currently in use
+#define dmRecAttrSecret 0x10 // "secret" record - password protected
+
+
+// All record atributes (for error-checking)
+#define dmAllRecAttrs ( dmRecAttrDelete | \
+ dmRecAttrDirty | \
+ dmRecAttrBusy | \
+ dmRecAttrSecret )
+
+// Record attributes which only the system is allowed to change (for error-checking)
+#define dmSysOnlyRecAttrs ( dmRecAttrBusy )
+
+
+/************************************************************
+ * Database Header equates
+ *************************************************************/
+#define dmDBNameLength 32 // 31 chars + 1 null terminator
+
+// Attributes of a Database
+//
+// *** IMPORTANT:
+// ***
+// *** Any changes to database attributes must be reflected in dmAllHdrAttrs and dmSysOnlyHdrAttrs ***
+// ***
+#define dmHdrAttrResDB 0x0001 // Resource database
+#define dmHdrAttrReadOnly 0x0002 // Read Only database
+#define dmHdrAttrAppInfoDirty 0x0004 // Set if Application Info block is dirty
+ // Optionally supported by an App's conduit
+#define dmHdrAttrBackup 0x0008 // Set if database should be backed up to PC if
+ // no app-specific synchronization conduit has
+ // been supplied.
+#define dmHdrAttrOKToInstallNewer 0x0010 // This tells the backup conduit that it's OK
+ // for it to install a newer version of this database
+ // with a different name if the current database is
+ // open. This mechanism is used to update the
+ // Graffiti Shortcuts database, for example.
+#define dmHdrAttrResetAfterInstall 0x0020 // Device requires a reset after this database is
+ // installed.
+#define dmHdrAttrCopyPrevention 0x0040 // This database should not be copied to
+
+#define dmHdrAttrStream 0x0080 // This database is used for file stream implementation.
+#define dmHdrAttrHidden 0x0100 // This database should generally be hidden from view
+ // used to hide some apps from the main view of the
+ // launcher for example.
+ // For data (non-resource) databases, this hides the record
+ // count within the launcher info screen.
+#define dmHdrAttrLaunchableData 0x0200 // This data database (not applicable for executables)
+ // can be "launched" by passing it's name to it's owner
+ // app ('appl' database with same creator) using
+ // the sysAppLaunchCmdOpenNamedDB action code.
+
+#define dmHdrAttrOpen 0x8000 // Database not closed properly
+
+
+// All database atributes (for error-checking)
+#define dmAllHdrAttrs ( dmHdrAttrResDB | \
+ dmHdrAttrReadOnly | \
+ dmHdrAttrAppInfoDirty | \
+ dmHdrAttrBackup | \
+ dmHdrAttrOKToInstallNewer | \
+ dmHdrAttrResetAfterInstall | \
+ dmHdrAttrCopyPrevention | \
+ dmHdrAttrStream | \
+ dmHdrAttrOpen )
+
+// Database attributes which only the system is allowed to change (for error-checking)
+#define dmSysOnlyHdrAttrs ( dmHdrAttrResDB | \
+ dmHdrAttrOpen )
+
+
+/************************************************************
+ * Unique ID equates
+ *************************************************************/
+#define dmRecordIDReservedRange 1 // The range of upper bits in the database's
+ // uniqueIDSeed from 0 to this number are
+ // reserved and not randomly picked when a
+ // database is created.
+#define dmDefaultRecordsID 0 // Records in a default database are copied
+ // with their uniqueIDSeeds set in this range.
+#define dmUnusedRecordID 0 // Record ID not allowed on the device
+
+
+/************************************************************
+ * Mode flags passed to DmOpenDatabase
+ *************************************************************/
+#define dmModeReadOnly 0x0001 // read access
+#define dmModeWrite 0x0002 // write access
+#define dmModeReadWrite 0x0003 // read & write access
+#define dmModeLeaveOpen 0x0004 // leave open when app quits
+#define dmModeExclusive 0x0008 // don't let anyone else open it
+#define dmModeShowSecret 0x0010 // force show of secret records
+
+// Generic type used to represent an open Database
+typedef void * DmOpenRef;
+
+
+/************************************************************
+ * Structure passed to DmGetNextDatabaseByTypeCreator and used
+ * to cache search information between multiple searches.
+ *************************************************************/
+typedef struct {
+ UInt32 info[8];
+ } DmSearchStateType;
+typedef DmSearchStateType* DmSearchStatePtr;
+
+
+
+/************************************************************
+ * Structures used by the sorting routines
+ *************************************************************/
+typedef struct {
+ UInt8 attributes; // record attributes;
+ UInt8 uniqueID[3]; // unique ID of record
+ } SortRecordInfoType;
+
+typedef SortRecordInfoType *SortRecordInfoPtr;
+
+typedef Int16 DmComparF (void *, void *, Int16 other, SortRecordInfoPtr,
+ SortRecordInfoPtr, MemHandle appInfoH);
+
+
+
+/************************************************************
+ * Database manager error codes
+ * the constant dmErrorClass is defined in ErrorBase.h
+ *************************************************************/
+#define dmErrMemError (dmErrorClass | 1)
+#define dmErrIndexOutOfRange (dmErrorClass | 2)
+#define dmErrInvalidParam (dmErrorClass | 3)
+#define dmErrReadOnly (dmErrorClass | 4)
+#define dmErrDatabaseOpen (dmErrorClass | 5)
+#define dmErrCantOpen (dmErrorClass | 6)
+#define dmErrCantFind (dmErrorClass | 7)
+#define dmErrRecordInWrongCard (dmErrorClass | 8)
+#define dmErrCorruptDatabase (dmErrorClass | 9)
+#define dmErrRecordDeleted (dmErrorClass | 10)
+#define dmErrRecordArchived (dmErrorClass | 11)
+#define dmErrNotRecordDB (dmErrorClass | 12)
+#define dmErrNotResourceDB (dmErrorClass | 13)
+#define dmErrROMBased (dmErrorClass | 14)
+#define dmErrRecordBusy (dmErrorClass | 15)
+#define dmErrResourceNotFound (dmErrorClass | 16)
+#define dmErrNoOpenDatabase (dmErrorClass | 17)
+#define dmErrInvalidCategory (dmErrorClass | 18)
+#define dmErrNotValidRecord (dmErrorClass | 19)
+#define dmErrWriteOutOfBounds (dmErrorClass | 20)
+#define dmErrSeekFailed (dmErrorClass | 21)
+#define dmErrAlreadyOpenForWrites (dmErrorClass | 22)
+#define dmErrOpenedByAnotherTask (dmErrorClass | 23)
+#define dmErrUniqueIDNotFound (dmErrorClass | 24)
+#define dmErrAlreadyExists (dmErrorClass | 25)
+#define dmErrInvalidDatabaseName (dmErrorClass | 26)
+#define dmErrDatabaseProtected (dmErrorClass | 27)
+#define dmErrDatabaseNotProtected (dmErrorClass | 28)
+
+/************************************************************
+ * Values for the direction parameter of DmSeekRecordInCategory
+ *************************************************************/
+#define dmSeekForward 1
+#define dmSeekBackward -1
+
+
+/************************************************************
+ * Data Manager procedures
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Initialization
+Err DmInit(void)
+ SYS_TRAP(sysTrapDmInit);
+
+
+// Directory Lists
+Err DmCreateDatabase(UInt16 cardNo, const Char *nameP,
+ UInt32 creator, UInt32 type, Boolean resDB)
+ SYS_TRAP(sysTrapDmCreateDatabase);
+
+Err DmCreateDatabaseFromImage(MemPtr bufferP)
+ SYS_TRAP(sysTrapDmCreateDatabaseFromImage);
+
+
+Err DmDeleteDatabase(UInt16 cardNo, LocalID dbID)
+ SYS_TRAP(sysTrapDmDeleteDatabase);
+
+UInt16 DmNumDatabases(UInt16 cardNo)
+ SYS_TRAP(sysTrapDmNumDatabases);
+
+LocalID DmGetDatabase(UInt16 cardNo, UInt16 index)
+ SYS_TRAP(sysTrapDmGetDatabase);
+
+LocalID DmFindDatabase(UInt16 cardNo, const Char *nameP)
+ SYS_TRAP(sysTrapDmFindDatabase);
+
+Err DmGetNextDatabaseByTypeCreator(Boolean newSearch, DmSearchStatePtr stateInfoP,
+ UInt32 type, UInt32 creator, Boolean onlyLatestVers,
+ UInt16 *cardNoP, LocalID *dbIDP)
+ SYS_TRAP(sysTrapDmGetNextDatabaseByTypeCreator);
+
+
+// Database info
+Err DmDatabaseInfo(UInt16 cardNo, LocalID dbID, Char *nameP,
+ UInt16 *attributesP, UInt16 *versionP, UInt32 *crDateP,
+ UInt32 * modDateP, UInt32 *bckUpDateP,
+ UInt32 * modNumP, LocalID *appInfoIDP,
+ LocalID *sortInfoIDP, UInt32 *typeP,
+ UInt32 *creatorP)
+ SYS_TRAP(sysTrapDmDatabaseInfo);
+
+Err DmSetDatabaseInfo(UInt16 cardNo, LocalID dbID, const Char *nameP,
+ UInt16 *attributesP, UInt16 *versionP, UInt32 *crDateP,
+ UInt32 * modDateP, UInt32 *bckUpDateP,
+ UInt32 * modNumP, LocalID *appInfoIDP,
+ LocalID *sortInfoIDP, UInt32 *typeP,
+ UInt32 *creatorP)
+ SYS_TRAP(sysTrapDmSetDatabaseInfo);
+
+Err DmDatabaseSize(UInt16 cardNo, LocalID dbID, UInt32 *numRecordsP,
+ UInt32 * totalBytesP, UInt32 *dataBytesP)
+ SYS_TRAP(sysTrapDmDatabaseSize);
+
+
+// This routine can be used to prevent a database from being deleted (by passing
+// true for 'protect'). It will increment the protect count if 'protect' is true
+// and decrement it if 'protect' is false. This is used by code that wants to
+// keep a particular record or resource in a database locked down but doesn't
+// want to keep the database open. This information is keep in the dynamic heap so
+// all databases are "unprotected" at system reset.
+Err DmDatabaseProtect(UInt16 cardNo, LocalID dbID, Boolean protect)
+ SYS_TRAP(sysTrapDmDatabaseProtect);
+
+
+// Open/close Databases
+DmOpenRef DmOpenDatabase(UInt16 cardNo, LocalID dbID, UInt16 mode)
+ SYS_TRAP(sysTrapDmOpenDatabase);
+
+DmOpenRef DmOpenDatabaseByTypeCreator(UInt32 type, UInt32 creator, UInt16 mode)
+ SYS_TRAP(sysTrapDmOpenDatabaseByTypeCreator);
+
+DmOpenRef DmOpenDBNoOverlay(UInt16 cardNo, LocalID dbID, UInt16 mode)
+ SYS_TRAP(sysTrapDmOpenDBNoOverlay);
+
+Err DmCloseDatabase(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmCloseDatabase);
+
+
+// Info on open databases
+DmOpenRef DmNextOpenDatabase(DmOpenRef currentP)
+ SYS_TRAP(sysTrapDmNextOpenDatabase);
+
+Err DmOpenDatabaseInfo(DmOpenRef dbP, LocalID *dbIDP,
+ UInt16 *openCountP, UInt16 *modeP, UInt16 *cardNoP,
+ Boolean *resDBP)
+ SYS_TRAP(sysTrapDmOpenDatabaseInfo);
+
+LocalID DmGetAppInfoID (DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmGetAppInfoID);
+
+void DmGetDatabaseLockState(DmOpenRef dbR, UInt8 *highest, UInt32 *count, UInt32 *busy)
+ SYS_TRAP(sysTrapDmGetDatabaseLockState);
+
+// Utility to unlock all records and clear busy bits
+Err DmResetRecordStates(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmResetRecordStates);
+
+
+// Error Query
+Err DmGetLastErr(void)
+ SYS_TRAP(sysTrapDmGetLastErr);
+
+
+//------------------------------------------------------------
+// Record based access routines
+//------------------------------------------------------------
+
+// Record Info
+UInt16 DmNumRecords(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmNumRecords);
+
+UInt16 DmNumRecordsInCategory(DmOpenRef dbP, UInt16 category)
+ SYS_TRAP(sysTrapDmNumRecordsInCategory);
+
+Err DmRecordInfo(DmOpenRef dbP, UInt16 index,
+ UInt16 *attrP, UInt32 *uniqueIDP, LocalID *chunkIDP)
+ SYS_TRAP(sysTrapDmRecordInfo);
+
+Err DmSetRecordInfo(DmOpenRef dbP, UInt16 index,
+ UInt16 *attrP, UInt32 *uniqueIDP)
+ SYS_TRAP(sysTrapDmSetRecordInfo);
+
+
+
+// Record attaching and detaching
+Err DmAttachRecord(DmOpenRef dbP, UInt16 *atP,
+ MemHandle newH, MemHandle *oldHP)
+ SYS_TRAP(sysTrapDmAttachRecord);
+
+Err DmDetachRecord(DmOpenRef dbP, UInt16 index,
+ MemHandle *oldHP)
+ SYS_TRAP(sysTrapDmDetachRecord);
+
+Err DmMoveRecord(DmOpenRef dbP, UInt16 from, UInt16 to)
+ SYS_TRAP(sysTrapDmMoveRecord);
+
+
+
+// Record creation and deletion
+MemHandle DmNewRecord(DmOpenRef dbP, UInt16 *atP, UInt32 size)
+ SYS_TRAP(sysTrapDmNewRecord);
+
+Err DmRemoveRecord(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmRemoveRecord);
+
+Err DmDeleteRecord(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmDeleteRecord);
+
+Err DmArchiveRecord(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmArchiveRecord);
+
+MemHandle DmNewHandle(DmOpenRef dbP, UInt32 size)
+ SYS_TRAP(sysTrapDmNewHandle);
+
+Err DmRemoveSecretRecords(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmRemoveSecretRecords);
+
+
+// Record viewing manipulation
+Err DmFindRecordByID(DmOpenRef dbP, UInt32 uniqueID, UInt16 *indexP)
+ SYS_TRAP(sysTrapDmFindRecordByID);
+
+MemHandle DmQueryRecord(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmQueryRecord);
+
+MemHandle DmGetRecord(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmGetRecord);
+
+MemHandle DmQueryNextInCategory(DmOpenRef dbP, UInt16 *indexP, UInt16 category)
+ SYS_TRAP(sysTrapDmQueryNextInCategory);
+
+UInt16 DmPositionInCategory (DmOpenRef dbP, UInt16 index, UInt16 category)
+ SYS_TRAP(sysTrapDmPositionInCategory);
+
+Err DmSeekRecordInCategory (DmOpenRef dbP, UInt16 *indexP, UInt16 offset,
+ Int16 direction, UInt16 category)
+ SYS_TRAP(sysTrapDmSeekRecordInCategory);
+
+
+MemHandle DmResizeRecord(DmOpenRef dbP, UInt16 index, UInt32 newSize)
+ SYS_TRAP(sysTrapDmResizeRecord);
+
+Err DmReleaseRecord(DmOpenRef dbP, UInt16 index, Boolean dirty)
+ SYS_TRAP(sysTrapDmReleaseRecord);
+
+UInt16 DmSearchRecord(MemHandle recH, DmOpenRef *dbPP)
+ SYS_TRAP(sysTrapDmSearchRecord);
+
+
+// Category manipulation
+Err DmMoveCategory (DmOpenRef dbP, UInt16 toCategory, UInt16 fromCategory, Boolean dirty)
+ SYS_TRAP(sysTrapDmMoveCategory);
+
+Err DmDeleteCategory (DmOpenRef dbR, UInt16 categoryNum)
+ SYS_TRAP(sysTrapDmDeleteCategory);
+
+
+// Validation for writing
+Err DmWriteCheck(void *recordP, UInt32 offset, UInt32 bytes)
+ SYS_TRAP(sysTrapDmWriteCheck);
+
+// Writing
+Err DmWrite(void *recordP, UInt32 offset, const void *srcP, UInt32 bytes)
+ SYS_TRAP(sysTrapDmWrite);
+
+Err DmStrCopy(void *recordP, UInt32 offset, const Char *srcP)
+ SYS_TRAP(sysTrapDmStrCopy);
+
+Err DmSet(void *recordP, UInt32 offset, UInt32 bytes, UInt8 value)
+ SYS_TRAP(sysTrapDmSet);
+
+
+
+
+//------------------------------------------------------------
+// Resource based access routines
+//------------------------------------------------------------
+
+// High level access routines
+MemHandle DmGetResource(DmResType type, DmResID resID)
+ SYS_TRAP(sysTrapDmGetResource);
+
+MemHandle DmGet1Resource(DmResType type, DmResID resID)
+ SYS_TRAP(sysTrapDmGet1Resource);
+
+Err DmReleaseResource(MemHandle resourceH)
+ SYS_TRAP(sysTrapDmReleaseResource);
+
+MemHandle DmResizeResource(MemHandle resourceH, UInt32 newSize)
+ SYS_TRAP(sysTrapDmResizeResource);
+
+
+// Searching resource databases
+DmOpenRef DmNextOpenResDatabase(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmNextOpenResDatabase);
+
+UInt16 DmFindResourceType(DmOpenRef dbP, DmResType resType, UInt16 typeIndex)
+ SYS_TRAP(sysTrapDmFindResourceType);
+
+UInt16 DmFindResource(DmOpenRef dbP, DmResType resType, DmResID resID,
+ MemHandle resH)
+ SYS_TRAP(sysTrapDmFindResource);
+
+UInt16 DmSearchResource(DmResType resType, DmResID resID,
+ MemHandle resH, DmOpenRef *dbPP)
+ SYS_TRAP(sysTrapDmSearchResource);
+
+
+// Resource Info
+UInt16 DmNumResources(DmOpenRef dbP)
+ SYS_TRAP(sysTrapDmNumResources);
+
+Err DmResourceInfo(DmOpenRef dbP, UInt16 index,
+ DmResType *resTypeP, DmResID *resIDP,
+ LocalID *chunkLocalIDP)
+ SYS_TRAP(sysTrapDmResourceInfo);
+
+Err DmSetResourceInfo(DmOpenRef dbP, UInt16 index,
+ DmResType *resTypeP, DmResID *resIDP)
+ SYS_TRAP(sysTrapDmSetResourceInfo);
+
+
+
+// Resource attaching and detaching
+Err DmAttachResource(DmOpenRef dbP, MemHandle newH,
+ DmResType resType, DmResID resID)
+ SYS_TRAP(sysTrapDmAttachResource);
+
+Err DmDetachResource(DmOpenRef dbP, UInt16 index,
+ MemHandle *oldHP)
+ SYS_TRAP(sysTrapDmDetachResource);
+
+
+
+// Resource creation and deletion
+MemHandle DmNewResource(DmOpenRef dbP, DmResType resType, DmResID resID,
+ UInt32 size)
+ SYS_TRAP(sysTrapDmNewResource);
+
+Err DmRemoveResource(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmRemoveResource);
+
+
+
+// Resource manipulation
+MemHandle DmGetResourceIndex(DmOpenRef dbP, UInt16 index)
+ SYS_TRAP(sysTrapDmGetResourceIndex);
+
+
+
+// Record sorting
+Err DmQuickSort(DmOpenRef dbP, DmComparF *compar, Int16 other)
+ SYS_TRAP(sysTrapDmQuickSort);
+
+Err DmInsertionSort (DmOpenRef dbR, DmComparF *compar, Int16 other)
+ SYS_TRAP(sysTrapDmInsertionSort);
+
+UInt16 DmFindSortPosition(DmOpenRef dbP, void *newRecord,
+ SortRecordInfoPtr newRecordInfo, DmComparF *compar, Int16 other)
+ SYS_TRAP(sysTrapDmFindSortPosition);
+
+UInt16 DmFindSortPositionV10(DmOpenRef dbP, void *newRecord,
+ DmComparF *compar, Int16 other)
+ SYS_TRAP(sysTrapDmFindSortPositionV10);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __DATAMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/DateTime.h b/SrcShared/Palm/Platform/Incs/Core/System/DateTime.h
new file mode 100644
index 0000000..adc44d6
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/DateTime.h
@@ -0,0 +1,283 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: DateTime.h
+ *
+ * Description:
+ * Date and Time calculations
+ *
+ * History:
+ * 1/19/95 rsf - Created by Roger Flores
+ * 7/15/99 rsf - moved some types in from Preferences.h
+ * 12/23/99 jmp - eliminated bogus maxTime definition
+ *
+ *****************************************************************************/
+
+#ifndef __DATETIME_H__
+#define __DATETIME_H__
+
+#include <CoreTraps.h>
+
+typedef enum
+ {
+ tfColon,
+ tfColonAMPM, // 1:00 pm
+ tfColon24h, // 13:00
+ tfDot,
+ tfDotAMPM, // 1.00 pm
+ tfDot24h, // 13.00
+ tfHoursAMPM, // 1 pm
+ tfHours24h, // 13
+ tfComma24h // 13,00
+ } TimeFormatType;
+
+
+typedef enum {
+ dsNone, // Daylight Savings Time not observed
+ dsUSA, // United States Daylight Savings Time
+ dsAustralia, // Australian Daylight Savings Time
+ dsWesternEuropean, // Western European Daylight Savings Time
+ dsMiddleEuropean, // Middle European Daylight Savings Time
+ dsEasternEuropean, // Eastern European Daylight Savings Time
+ dsGreatBritain, // Great Britain and Eire Daylight Savings Time
+ dsRumania, // Rumanian Daylight Savings Time
+ dsTurkey, // Turkish Daylight Savings Time
+ dsAustraliaShifted // Australian Daylight Savings Time with shift in 1986
+ } DaylightSavingsTypes;
+
+
+// pass a TimeFormatType
+#define Use24HourFormat(t) ((t) == tfColon24h || (t) == tfDot24h || (t) == tfHours24h || (t) == tfComma24h)
+#define TimeSeparator(t) ((Char) ( t <= tfColon24h ? ':' : (t <= tfDot24h ? '.' : ',')))
+
+
+typedef enum {
+ dfMDYWithSlashes, // 12/31/95
+ dfDMYWithSlashes, // 31/12/95
+ dfDMYWithDots, // 31.12.95
+ dfDMYWithDashes, // 31-12-95
+ dfYMDWithSlashes, // 95/12/31
+ dfYMDWithDots, // 95.12.31
+ dfYMDWithDashes, // 95-12-31
+
+ dfMDYLongWithComma, // Dec 31, 1995
+ dfDMYLong, // 31 Dec 1995
+ dfDMYLongWithDot, // 31. Dec 1995
+ dfDMYLongNoDay, // Dec 1995
+ dfDMYLongWithComma, // 31 Dec, 1995
+ dfYMDLongWithDot, // 1995.12.31
+ dfYMDLongWithSpace, // 1995 Dec 31
+
+ dfMYMed, // Dec '95
+ dfMYMedNoPost // Dec 95 (added for French 2.0 ROM)
+ } DateFormatType;
+
+typedef struct {
+ Int16 second;
+ Int16 minute;
+ Int16 hour;
+ Int16 day;
+ Int16 month;
+ Int16 year;
+ Int16 weekDay; // Days since Sunday (0 to 6)
+ } DateTimeType;
+
+typedef DateTimeType *DateTimePtr;
+
+
+// This is the time format. Times are treated as words so don't
+// change the order of the members in this structure.
+//
+typedef struct {
+ UInt8 hours;
+ UInt8 minutes;
+} TimeType;
+
+typedef TimeType *TimePtr;
+
+#define noTime -1 // The entire TimeType is -1 if there isn't a time.
+
+
+// This is the date format. Dates are treated as words so don't
+// change the order of the members in this structure.
+//
+typedef struct {
+ UInt16 year :7; // years since 1904 (MAC format)
+ UInt16 month :4;
+ UInt16 day :5;
+} DateType;
+
+typedef DateType *DatePtr;
+
+
+/************************************************************
+ * Date Time Constants
+ *************************************************************/
+
+// Maximum lengths of strings return by the date and time formating
+// routine DateToAscii and TimeToAscii.
+#define timeStringLength 9
+#define dateStringLength 9
+#define longDateStrLength 15
+#define dowDateStringLength 19
+#define dowLongDateStrLength 25
+
+
+#define firstYear 1904
+#define numberOfYears 128
+#define lastYear (firstYear + numberOfYears - 1)
+
+
+
+// Constants for time calculations
+// Could change these from xIny to yPerX
+#define secondsInSeconds 1
+#define minutesInSeconds 60
+#define hoursInMinutes 60
+#define hoursInSeconds (hoursInMinutes * minutesInSeconds)
+#define hoursPerDay 24
+//#define daysInSeconds ((Int32)(hoursPerDay) * ((Int32)hoursInSeconds))
+#define daysInSeconds (0x15180) // cc bug
+
+#define daysInWeek 7
+#define daysInYear 365
+#define daysInLeapYear 366
+#define daysInFourYears (daysInLeapYear + 3 * daysInYear)
+
+#define monthsInYear 12
+
+#define maxDays ((UInt32) numberOfYears / 4 * daysInFourYears - 1)
+#define maxSeconds ((UInt32) maxDays * daysInSeconds)
+
+// Values returned by DayOfWeek routine.
+#define sunday 0
+#define monday 1
+#define tuesday 2
+#define wednesday 3
+#define thursday 4
+#define friday 5
+#define saturday 6
+
+// Months of the year
+#define january 1
+#define february 2
+#define march 3
+#define april 4
+#define may 5
+#define june 6
+#define july 7
+#define august 8
+#define september 9
+#define october 10
+#define november 11
+#define december 12
+
+
+// Values returned by DoyOfMonth routine.
+typedef enum {
+ dom1stSun, dom1stMon, dom1stTue, dom1stWen, dom1stThu, dom1stFri, dom1stSat,
+ dom2ndSun, dom2ndMon, dom2ndTue, dom2ndWen, dom2ndThu, dom2ndFri, dom2ndSat,
+ dom3rdSun, dom3rdMon, dom3rdTue, dom3rdWen, dom3rdThu, dom3rdFri, dom3rdSat,
+ dom4thSun, dom4thMon, dom4thTue, dom4thWen, dom4thThu, dom4thFri, dom4thSat,
+ domLastSun, domLastMon, domLastTue, domLastWen, domLastThu, domLastFri,
+ domLastSat
+ } DayOfWeekType;
+
+// Values used by DateTemplateToAscii routine.
+#define dateTemplateChar chrCircumflexAccent
+
+enum {
+ dateTemplateDayNum = '0',
+ dateTemplateDOWName,
+ dateTemplateMonthName,
+ dateTemplateMonthNum,
+ dateTemplateYearNum
+};
+
+#define dateTemplateShortModifier 's'
+#define dateTemplateRegularModifier 'r'
+#define dateTemplateLongModifier 'l'
+#define dateTemplateLeadZeroModifier 'z'
+
+//************************************************************
+//* Date and Time macros
+//***********************************************************
+
+// Convert a date in a DateType structure to an UInt16.
+ #define DateToInt(date) (*(UInt16 *) &date)
+
+
+// Convert a date in a DateType structure to a signed int.
+ #define TimeToInt(time) (*(Int16 *) &time)
+
+
+
+//************************************************************
+//* Date Time procedures
+//************************************************************
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void TimSecondsToDateTime(UInt32 seconds, DateTimePtr dateTimeP)
+ SYS_TRAP(sysTrapTimSecondsToDateTime);
+
+UInt32 TimDateTimeToSeconds(DateTimePtr dateTimeP)
+ SYS_TRAP(sysTrapTimDateTimeToSeconds);
+
+void TimAdjust(DateTimePtr dateTimeP, Int32 adjustment)
+ SYS_TRAP(sysTrapTimAdjust);
+
+void TimeToAscii(UInt8 hours, UInt8 minutes, TimeFormatType timeFormat,
+ Char *pString)
+ SYS_TRAP(sysTrapTimeToAscii);
+
+
+
+Int16 DaysInMonth(Int16 month, Int16 year)
+ SYS_TRAP(sysTrapDaysInMonth);
+
+Int16 DayOfWeek (Int16 month, Int16 day, Int16 year)
+ SYS_TRAP(sysTrapDayOfWeek);
+
+Int16 DayOfMonth (Int16 month, Int16 day, Int16 year)
+ SYS_TRAP(sysTrapDayOfMonth);
+
+
+
+// Date routines.
+void DateSecondsToDate (UInt32 seconds, DatePtr date)
+ SYS_TRAP(sysTrapDateSecondsToDate);
+
+void DateDaysToDate (UInt32 days, DatePtr date)
+ SYS_TRAP(sysTrapDateDaysToDate);
+
+UInt32 DateToDays (DateType date)
+ SYS_TRAP(sysTrapDateToDays);
+
+void DateAdjust (DatePtr dateP, Int32 adjustment)
+ SYS_TRAP(sysTrapDateAdjust);
+
+void DateToAscii(UInt8 months, UInt8 days, UInt16 years,
+ DateFormatType dateFormat, Char *pString)
+ SYS_TRAP(sysTrapDateToAscii);
+
+void DateToDOWDMFormat(UInt8 months, UInt8 days, UInt16 years,
+ DateFormatType dateFormat, Char *pString)
+ SYS_TRAP(sysTrapDateToDOWDMFormat);
+
+UInt16 DateTemplateToAscii(const Char *templateP, UInt8 months,
+ UInt8 days, UInt16 years, Char *stringP, Int16 stringLen)
+ SYS_TRAP(sysTrapDateTemplateToAscii);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__DATETIME_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/ErrorBase.h b/SrcShared/Palm/Platform/Incs/Core/System/ErrorBase.h
new file mode 100644
index 0000000..9417c42
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/ErrorBase.h
@@ -0,0 +1,294 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: ErrorBase.h
+ *
+ * Description:
+ * Include file for Error Management
+ *
+ * History:
+ * 10/25/94 RM Created by Ron Marianetti
+ * 10/09/98 Bob Fill in all macros, fix defns w/ do{}while(0)
+ * 08/05/99 kwk Added menuErrorClass from Gavin's Menu.c
+ *
+ *-----------------------------------------------------------------------
+ * Exception Handling
+ *
+ * This unit implements an exception handling mechanism that is similar
+ * to "real" C++ Exceptions. Our Exceptions are untyped, and there
+ * must be one and only one Catch block for each Try block.
+ *
+ * Try/Catch Syntax:
+ *
+ * ErrTry {
+ * // Do something which may fail.
+ * // Call ErrThrow() to signal failure and force jump
+ * // to the following Catch block.
+ * }
+ *
+ * ErrCatch(inErr) {
+ * // Recover or cleanup after a failure in the above Try block.
+ * // "inErr" is an ExceptionCode identifying the reason
+ * // for the failure.
+ *
+ * // You may call Throw() if you want to jump out to
+ * // the next Catch block.
+ *
+ * // The code in this Catch block does not execute if
+ * // the above Try block completes without a Throw.
+ *
+ * } ErrEndCatch
+ *
+ * You must structure your code exactly as above. You can't have a
+ * ErrTry { } without a ErrCatch { } ErrEndCatch, or vice versa.
+ *
+ *
+ * ErrThrow
+ *
+ * To signal failure, call ErrThrow() from within a Try block. The
+ * Throw can occur anywhere in the Try block, even within functions
+ * called from the Try block. A ErrThrow() will jump execution to the
+ * start of the nearest Catch block, even across function calls.
+ * Destructors for stack-based objects which go out of scope as
+ * a result of the ErrThrow() are called.
+ *
+ * You can call ErrThrow() from within a Catch block to "rethrow"
+ * the exception to the next nearest Catch block.
+ *
+ *
+ * Exception Codes
+ *
+ * An ExceptionCode is a 32-bit number. You will normally use
+ * Pilot error codes, which are 16-bit numbers. This allows
+ * plently of room for defining codes for your own kinds of errors.
+ *
+ *
+ * Limitations
+ *
+ * Try/Catch and Throw are based on setjmp/longjmp. At the
+ * beginning of a Try block, setjmp saves the machine registers.
+ * Throw calls longjmp, which restores the registers and jumps
+ * to the beginning of the Catch block. Therefore, any changes
+ * in the Try block to variables stored in registers will not
+ * be retained when entering the Catch block.
+ *
+ * The solution is to declare variables that you want to use
+ * in both the Try and Catch blocks as "volatile". For example:
+ *
+ * volatile long x = 1; // Declare volatile local variable
+ * ErrTry {
+ * x = 100; // Set local variable in Try
+ * ErrThrow(-1);
+ * }
+ *
+ * ErrCatch(inErr) {
+ * if (x > 1) { // Use local variable in Catch
+ * SysBeep(1);
+ * }
+ * } ErrEndCatch
+ *
+ *****************************************************************************/
+
+#ifndef __ERRORBASE_H__
+#define __ERRORBASE_H__
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+
+
+#if EMULATION_LEVEL != EMULATION_NONE
+#include <setjmp.h>
+#endif
+
+// Max message length supported by ErrCustomAlert
+#define errMaxMsgLength 511
+
+
+/************************************************************
+ * Error Classes for each manager
+ *************************************************************/
+#define errNone 0x0000 // No error
+
+#define memErrorClass 0x0100 // Memory Manager
+#define dmErrorClass 0x0200 // Data Manager
+#define serErrorClass 0x0300 // Serial Manager
+#define slkErrorClass 0x0400 // Serial Link Manager
+#define sysErrorClass 0x0500 // System Manager
+#define fplErrorClass 0x0600 // Floating Point Library
+#define flpErrorClass 0x0680 // New Floating Point Library
+#define evtErrorClass 0x0700 // System Event Manager
+#define sndErrorClass 0x0800 // Sound Manager
+#define almErrorClass 0x0900 // Alarm Manager
+#define timErrorClass 0x0A00 // Time Manager
+#define penErrorClass 0x0B00 // Pen Manager
+#define ftrErrorClass 0x0C00 // Feature Manager
+#define cmpErrorClass 0x0D00 // Connection Manager (HotSync)
+#define dlkErrorClass 0x0E00 // Desktop Link Manager
+#define padErrorClass 0x0F00 // PAD Manager
+#define grfErrorClass 0x1000 // Graffiti Manager
+#define mdmErrorClass 0x1100 // Modem Manager
+#define netErrorClass 0x1200 // Net Library
+#define htalErrorClass 0x1300 // HTAL Library
+#define inetErrorClass 0x1400 // INet Library
+#define exgErrorClass 0x1500 // Exg Manager
+#define fileErrorClass 0x1600 // File Stream Manager
+#define rfutErrorClass 0x1700 // RFUT Library
+#define txtErrorClass 0x1800 // Text Manager
+#define tsmErrorClass 0x1900 // Text Services Library
+#define webErrorClass 0x1A00 // Web Library
+#define secErrorClass 0x1B00 // Security Library
+#define emuErrorClass 0x1C00 // Emulator Control Manager
+#define flshErrorClass 0x1D00 // Flash Manager
+#define pwrErrorClass 0x1E00 // Power Manager
+#define cncErrorClass 0x1F00 // Connection Manager (Serial Communication)
+#define actvErrorClass 0x2000 // Activation application
+#define radioErrorClass 0x2100 // Radio Manager (Library)
+#define dispErrorClass 0x2200 // Display Driver Errors.
+#define bltErrorClass 0x2300 // Blitter Driver Errors.
+#define winErrorClass 0x2400 // Window manager.
+#define omErrorClass 0x2500 // Overlay Manager
+#define menuErrorClass 0x2600 // Menu Manager
+#define lz77ErrorClass 0x2700 // Lz77 Library
+#define smsErrorClass 0x2800 // Sms Library
+#define expErrorClass 0x2900 // Expansion Manager and Slot Driver Library
+#define vfsErrorClass 0x2A00 // Virtual Filesystem Manager and Filesystem library
+#define lmErrorClass 0x2B00 // Locale Manager
+#define intlErrorClass 0x2C00 // International Manager
+#define pdiErrorClass 0x2D00 // PDI Library
+#define attnErrorClass 0x2E00 // Attention Manager
+#define telErrorClass 0x2F00 // Telephony Manager
+#define hwrErrorClass 0x3000 // Hardware Manager (HAL)
+#define blthErrorClass 0x3100 // Bluetooth Library Error Class
+#define udaErrorClass 0x3200 // UDA Manager Error Class
+
+#define oemErrorClass 0x7000 // OEM/Licensee errors (0x7000-0x7EFF shared among ALL partners)
+#define errInfoClass 0x7F00 // special class shows information w/o error code
+#define appErrorClass 0x8000 // Application-defined errors
+
+
+
+/********************************************************************
+ * Try / Catch / Throw support
+ *
+ * ---------------------------------------------------------------------
+ * Exception Handler structure
+ *
+ * An ErrExceptionType object is created for each ErrTry & ErrCatch block.
+ * At any point in the program, there is a linked list of
+ * ErrExceptionType objects. GErrFirstException points to the
+ * most recently entered block. A ErrExceptionType blocks stores
+ * information about the state of the machine (register values)
+ * at the start of the Try block
+ ********************************************************************/
+
+#if EMULATION_LEVEL != EMULATION_NONE
+ #define ErrJumpBuf jmp_buf
+#else
+ typedef long* ErrJumpBuf[12]; // D3-D7,PC,A2-A7
+#endif
+
+// Structure used to store Try state.
+typedef struct ErrExceptionType {
+ struct ErrExceptionType* nextP; // next exception type
+ ErrJumpBuf state; // setjmp/longjmp storage
+ Int32 err; // Error code
+ } ErrExceptionType;
+typedef ErrExceptionType *ErrExceptionPtr;
+
+
+// Try & Catch macros
+#define ErrTry \
+ { \
+ ErrExceptionType _TryObject; \
+ _TryObject.err = 0; \
+ _TryObject.nextP = (ErrExceptionPtr)*ErrExceptionList(); \
+ *ErrExceptionList() = (MemPtr)&_TryObject; \
+ if (ErrSetJump(_TryObject.state) == 0) {
+
+
+// NOTE: All variables referenced in and after the ErrCatch must
+// be declared volatile. Here's how for variables and pointers:
+// volatile UInt16 oldMode;
+// ShlDBHdrTablePtr volatile hdrTabP = nil;
+// If you have many local variables after the ErrCatch you may
+// opt to put the ErrTry and ErrCatch in a separate enclosing function.
+#define ErrCatch(theErr) \
+ *ErrExceptionList() = (MemPtr)_TryObject.nextP; \
+ } \
+ else { \
+ Int32 theErr = _TryObject.err; \
+ *ErrExceptionList() = (MemPtr)_TryObject.nextP;
+
+
+#define ErrEndCatch \
+ } \
+ }
+
+
+
+/********************************************************************
+ * Error Manager Routines
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if EMULATION_LEVEL != EMULATION_NONE
+ #define ErrSetJump(buf) setjmp(buf)
+ #define ErrLongJump(buf,res) longjmp(buf,res)
+
+#else
+ Int16 ErrSetJump(ErrJumpBuf buf)
+ SYS_TRAP(sysTrapErrSetJump);
+
+ void ErrLongJump(ErrJumpBuf buf, Int16 result)
+ SYS_TRAP(sysTrapErrLongJump);
+#endif
+
+MemPtr* ErrExceptionList(void)
+ SYS_TRAP(sysTrapErrExceptionList);
+
+void ErrThrow(Int32 err)
+ SYS_TRAP(sysTrapErrThrow);
+
+void ErrDisplayFileLineMsg(const Char * const filename, UInt16 lineNo,
+ const Char * const msg)
+ SYS_TRAP(sysTrapErrDisplayFileLineMsg);
+
+
+//---------------------------------------------------------------------
+// 2/25/98 - New routine for PalmOS >3.0 to display a UI alert for
+// run-time errors. This is most likely to be used by network applications
+// that are likely to encounter run-time errors like can't find the server,
+// network down, etc. etc.
+//
+// This routine will lookup the text associated with 'errCode' and display
+// it in an alert. If errMsgP is not NULL, then that text will be used
+// instead of the associated 'errCode' text. If 'preMsgP' or 'postMsgP'
+// is not null, then that text will be pre-pended or post-pended
+// respectively.
+//
+// Apps that don't use the extra parameters may want to just use the
+// macro below 'ErrAlert'
+//---------------------------------------------------------------------
+UInt16 ErrAlertCustom(Err errCode, Char *errMsgP, Char *preMsgP,
+ Char * postMsgP)
+ SYS_TRAP(sysTrapErrAlertCustom);
+
+#define ErrAlert(err) ErrAlertCustom(err, 0, 0, 0)
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
+#endif // __ERRORBASE_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/FeatureMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/FeatureMgr.h
new file mode 100644
index 0000000..ff9b2e5
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/FeatureMgr.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: FeatureMgr.h
+ *
+ * Description:
+ * Header for the Feature Manager
+ *
+ * History:
+ * 11/14/94 RM - Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifndef __FEATUREMGR_H__
+#define __FEATUREMGR_H__
+
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <ErrorBase.h>
+
+
+
+/************************************************************
+ * Feature manager error codes
+ * the constant ftrErrorClass is defined in ErrorBase.h
+ *************************************************************/
+#define ftrErrInvalidParam (ftrErrorClass | 1)
+#define ftrErrNoSuchFeature (ftrErrorClass | 2)
+#define ftrErrAlreadyExists (ftrErrorClass | 3)
+#define ftrErrROMBased (ftrErrorClass | 4)
+#define ftrErrInternalErr (ftrErrorClass | 5)
+
+
+/************************************************************
+ * Feature Manager procedures
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Init the feature Manager
+Err FtrInit(void)
+ SYS_TRAP(sysTrapFtrInit);
+
+
+// Get a feature
+Err FtrGet(UInt32 creator, UInt16 featureNum, UInt32 *valueP)
+ SYS_TRAP(sysTrapFtrGet);
+
+// Set/Create a feature.
+Err FtrSet(UInt32 creator, UInt16 featureNum, UInt32 newValue)
+ SYS_TRAP(sysTrapFtrSet);
+
+// Unregister a feature
+Err FtrUnregister(UInt32 creator, UInt16 featureNum)
+ SYS_TRAP(sysTrapFtrUnregister);
+
+// Get a feature by index
+Err FtrGetByIndex(UInt16 index, Boolean romTable,
+ UInt32 *creatorP, UInt16 *numP, UInt32 *valueP)
+ SYS_TRAP(sysTrapFtrGetByIndex);
+
+// Get temporary space from storage heap
+Err FtrPtrNew(UInt32 creator, UInt16 featureNum, UInt32 size,
+ void **newPtrP)
+ SYS_TRAP(sysTrapFtrPtrNew);
+
+// Release temporary space to storage heap
+Err FtrPtrFree(UInt32 creator, UInt16 featureNum)
+ SYS_TRAP(sysTrapFtrPtrFree);
+
+
+// Resize block of temporary storage
+Err FtrPtrResize(UInt32 creator, UInt16 featureNum, UInt32 newSize,
+ void **newPtrP)
+ SYS_TRAP(sysTrapFtrPtrResize);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __FEATUREMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Font.h b/SrcShared/Palm/Platform/Incs/Core/System/Font.h
new file mode 100644
index 0000000..1312a0a
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Font.h
@@ -0,0 +1,150 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Font.h
+ *
+ * Description:
+ * This file defines font structures and routines.
+ *
+ * History:
+ * September 13, 1994 Created by Art Lamb
+ * 05/05/98 art Add structures for font mapping table.
+ * 07/03/98 kwk Added FntWidthToOffset.
+ * 10/23/98 kwk Changed fontMapTable to 0xC000 (was 0xFFFF).
+ * 10/20/99 kwk Moved private values to FontPrv.h
+ *
+ *****************************************************************************/
+
+#ifndef __FONT_H__
+#define __FONT_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+// Pixel width of tab stops in fields
+#define fntTabChrWidth 20
+
+// Width of character missing from font.
+#define fntMissingChar -1
+
+typedef struct {
+ Int8 offset;
+ Int8 width;
+} FontCharInfoType, * FontCharInfoPtr;
+
+typedef struct {
+ Int16 fontType; // font type
+ Int16 firstChar; // ASCII code of first character
+ Int16 lastChar; // ASCII code of last character
+ Int16 maxWidth; // maximum character width
+ Int16 kernMax; // negative of maximum character kern
+ Int16 nDescent; // negative of descent
+ Int16 fRectWidth; // width of font rectangle
+ Int16 fRectHeight; // height of font rectangle
+ Int16 owTLoc; // offset to offset/width table
+ Int16 ascent; // ascent
+ Int16 descent; // descent
+ Int16 leading; // leading
+ Int16 rowWords; // row width of bit image / 2
+} FontType;
+
+typedef FontType *FontPtr;
+
+typedef FontPtr *FontTablePtr;
+
+enum fontID {
+ stdFont = 0x00, // Small font used for the user's writing. Shows a good amount
+ boldFont, // Small font. Bold for easier reading. Used often for ui.
+ largeFont, // Larger font for easier reading. Shows a lot less.
+ symbolFont, // Various ui images like check boxes and arrows
+ symbol11Font, // Larger various ui images
+ symbol7Font, // Smaller various ui images
+ ledFont, // Calculator specific font
+ largeBoldFont, // A thicker version of the large font. More readable.
+ fntAppFontCustomBase = 0x80 // First available application-defined font ID
+};
+
+typedef enum fontID FontID;
+
+#define checkboxFont symbol11Font
+
+#define FntIsAppDefined(fnt) (fnt >= fntAppFontCustomBase)
+
+
+
+//--------------------------------------------------------------------
+//
+// Font Function
+//
+//--------------------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+FontID FntGetFont (void)
+ SYS_TRAP(sysTrapFntGetFont);
+
+FontID FntSetFont (FontID font)
+ SYS_TRAP(sysTrapFntSetFont);
+
+FontPtr FntGetFontPtr (void)
+ SYS_TRAP(sysTrapFntGetFontPtr);
+
+Int16 FntBaseLine (void)
+ SYS_TRAP(sysTrapFntBaseLine);
+
+Int16 FntCharHeight (void)
+ SYS_TRAP(sysTrapFntCharHeight);
+
+Int16 FntLineHeight (void)
+ SYS_TRAP(sysTrapFntLineHeight);
+
+Int16 FntAverageCharWidth (void)
+ SYS_TRAP(sysTrapFntAverageCharWidth);
+
+Int16 FntCharWidth (Char ch)
+ SYS_TRAP(sysTrapFntCharWidth);
+
+Int16 FntCharsWidth (Char const *chars, Int16 len)
+ SYS_TRAP(sysTrapFntCharsWidth);
+
+Int16 FntWidthToOffset (Char const *pChars, UInt16 length,
+ Int16 pixelWidth, Boolean *leadingEdge, Int16 *truncWidth)
+ SYS_TRAP(sysTrapFntWidthToOffset);
+
+void FntCharsInWidth (Char const *string,
+ Int16 *stringWidthP, Int16 *stringLengthP,
+ Boolean *fitWithinWidth)
+ SYS_TRAP(sysTrapFntCharsInWidth);
+
+Int16 FntDescenderHeight (void)
+ SYS_TRAP(sysTrapFntDescenderHeight);
+
+Int16 FntLineWidth (Char const *pChars, UInt16 length)
+ SYS_TRAP(sysTrapFntLineWidth);
+
+UInt16 FntWordWrap (Char const *chars, UInt16 maxWidth)
+ SYS_TRAP(sysTrapFntWordWrap);
+
+void FntWordWrapReverseNLines (Char const *const chars,
+ UInt16 maxWidth, UInt16 *linesToScrollP, UInt16 *scrollPosP)
+ SYS_TRAP(sysTrapFntWordWrapReverseNLines);
+
+void FntGetScrollValues (Char const *chars, UInt16 width,
+ UInt16 scrollPos, UInt16 *linesP, UInt16 *topLine)
+ SYS_TRAP(sysTrapFntGetScrollValues);
+
+Err FntDefineFont (FontID font, FontPtr fontP)
+ SYS_TRAP(sysTrapFntDefineFont);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif // __FONT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/IntlMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/IntlMgr.h
new file mode 100644
index 0000000..0adaf43
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/IntlMgr.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1998-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: IntlMgr.h
+ *
+ * Description:
+ * This file defines public Int'l Mgr structures and routines.
+ *
+ * History:
+ * 03/21/98 kwk Created by Ken Krugler.
+ * 10/14/98 kwk Added intlIntlGetRoutineAddress selector and
+ * IntlGetRoutineAddress routine declaration.
+ * 08/05/99 kwk Added intlIntlHandleEvent selector and the
+ * IntlHandleEvent routine declaration.
+ * 09/22/99 kwk Added intlTxtParamString selector.
+ * 10/20/99 kwk Moved private stuff to IntlPrv.h
+ *
+ *****************************************************************************/
+
+#ifndef __INTLMGR_H__
+#define __INTLMGR_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+// If nobody has explicitly specified that we should or should not
+// use our international trap dispatcher, set it based on the emulation
+// level.
+
+#ifndef USE_INTL_TRAPS
+ #if EMULATION_LEVEL == EMULATION_NONE
+ #define USE_INTL_TRAPS 1
+ #else
+ #define USE_INTL_TRAPS 0
+ #endif
+#endif
+
+/***********************************************************************
+ * Public constants
+ ***********************************************************************/
+
+// Bits set for the Intl Mgr feature.
+
+#define intlMgrExists 0x00000001
+
+// International Manager trap macros.
+
+#if USE_INTL_TRAPS
+ #define INTL_TRAP(sel) \
+ _SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, sysTrapIntlDispatch, sel)
+#else
+ #define INTL_TRAP(intlSelectorNum)
+#endif
+
+// Selectors for routines found in the international manager. The order
+// of these selectors MUST match the jump table in IntlDispatch.c.
+
+#define intlIntlInit 0
+#define intlTxtByteAttr 1
+#define intlTxtCharAttr 2
+#define intlTxtCharXAttr 3
+#define intlTxtCharSize 4
+#define intlTxtGetPreviousChar 5
+#define intlTxtGetNextChar 6
+#define intlTxtGetChar 7
+#define intlTxtSetNextChar 8
+#define intlTxtCharBounds 9
+#define intlTxtPrepFindString 10
+#define intlTxtFindString 11
+#define intlTxtReplaceStr 12
+#define intlTxtWordBounds 13
+#define intlTxtCharEncoding 14
+#define intlTxtStrEncoding 15
+#define intlTxtEncodingName 16
+#define intlTxtMaxEncoding 17
+#define intlTxtTransliterate 18
+#define intlTxtCharIsValid 19
+#define intlTxtCompare 20
+#define intlTxtCaselessCompare 21
+#define intlTxtCharWidth 22
+#define intlTxtGetTruncationOffset 23
+#define intlIntlGetRoutineAddress 24
+#define intlIntlHandleEvent 25 // New for Palm OS 3.5
+#define intlTxtParamString 26
+#define intlTxtConvertEncodingV35 27 // Patched for Palm OS 3.5.2
+#define intlTxtConvertEncoding 28 // New for Palm OS 4.0
+#define intlIntlSetRoutineAddress 29
+#define intlTxtGetWordWrapOffset 30
+#define intlTxtNameToEncoding 31
+#define intlIntlStrictChecks 32
+
+/***********************************************************************
+ * Public routines
+ ***********************************************************************/
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Return back the address of the routine indicated by <inSelector>. If
+// <inSelector> isn't a valid routine selector, return back NULL.
+void *IntlGetRoutineAddress(IntlSelector inSelector)
+ INTL_TRAP(intlIntlGetRoutineAddress);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
+
+#endif // __INTLMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/KeyMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/KeyMgr.h
new file mode 100644
index 0000000..5a81a6a
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/KeyMgr.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: KeyMgr.h
+ *
+ * Description:
+ * Include file for Key manager
+ *
+ * History:
+ * 9/13/95 Created by Ron Marianetti
+ * 2/04/98 srj- added contrast key defines
+ * 8/23/98 SCL- Cross-merged 3.1 and 3.2
+ *
+ *****************************************************************************/
+
+#ifndef __KEYMGR_H__
+#define __KEYMGR_H__
+
+// Pilot common definitions
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+
+/********************************************************************
+ * Definition of bit field returned from KeyCurrentState
+ ********************************************************************/
+#define keyBitPower 0x0001 // Power key
+#define keyBitPageUp 0x0002 // Page-up
+#define keyBitPageDown 0x0004 // Page-down
+#define keyBitHard1 0x0008 // App #1
+#define keyBitHard2 0x0010 // App #2
+#define keyBitHard3 0x0020 // App #3
+#define keyBitHard4 0x0040 // App #4
+#define keyBitCradle 0x0080 // Button on cradle
+#define keyBitAntenna 0x0100 // Antenna "key" <chg 3-31-98 RM>
+#define keyBitContrast 0x0200 // Contrast key
+
+#define keyBitsAll 0xFFFFFFFF // all keys
+
+
+#define slowestKeyDelayRate 0xff
+#define slowestKeyPeriodRate 0xff
+
+
+/********************************************************************
+ * Key manager Routines
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Set/Get the auto-key repeat rate
+Err KeyRates(Boolean set, UInt16 *initDelayP, UInt16 *periodP,
+ UInt16 *doubleTapDelayP, Boolean *queueAheadP)
+ SYS_TRAP(sysTrapKeyRates);
+
+// Get the current state of the hardware keys
+// This is now updated every tick, even when more than 1 key is held down.
+UInt32 KeyCurrentState(void)
+ SYS_TRAP(sysTrapKeyCurrentState);
+
+// Set the state of the hardware key mask which controls if the key
+// generates a keyDownEvent
+UInt32 KeySetMask(UInt32 keyMask)
+ SYS_TRAP(sysTrapKeySetMask);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__KEYMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/LocaleMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/LocaleMgr.h
new file mode 100644
index 0000000..0351640
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/LocaleMgr.h
@@ -0,0 +1,230 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2000 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: LocaleMgr.h
+ *
+ * Release:
+ *
+ * Description:
+ * Public header for routines that support locales (information specific
+ * to locales and regions).
+ *
+ * History:
+ * 04/28/00 CS Created by Chris Schneider.
+ * 05/16/00 CS LmCountryType/LmLanguageType are now back to
+ * CountryType/LanguageType.
+ * 05/31/00 CS Moved country and language codes to new Locale.h and removed
+ * kLanguageFirst, etc.
+ * 06/06/00 kwk Made _LmLocaleType's language & country fields be UInt16's,
+ * so that it's binary compatible with OmLocaleType.
+ * 07/28/00 CS Replaced lmChoiceMinutesWestOfGMT & lmChoiceDaylightSavings
+ * selectors with lmChoiceTimeZone.
+ * 08/08/00 CS Renamed LmGetLocaleSetting's <iMaxSize> parameter <iValueSize>
+ * to reflect the fact that the routine now checks to make sure
+ * that <oValue> is the correct size for all fixed-size settings.
+ * 09/29/00 CS Made iLocale parm of LmLocaleToIndex const.
+ * 11/17/00 CS Removed support for lmChoiceLanguage & lmChoiceCountry,
+ * since these guys were returning UInt8's, which probably
+ * won't cut it at some point in the future. Callers can use
+ * lmChoiceLocale, which returns an LmLocaleType struct that
+ * places the country and language into UInt16 fields.
+ * CS Defined lmAnyCountry & lmAnyLanguage, which can now be passed
+ * in LmLocaleToIndex's iLocale parameter (as wildcards).
+ *
+ *****************************************************************************/
+
+#ifndef __LOCALEMGR_H__
+#define __LOCALEMGR_H__
+
+/* Supporting lmChoiceLanguageName would add over 3K to the 'locs' resource.
+ DOLATER CS - either do it or punt.
+*/
+#define SUPPORT_LANGUAGE_NAME 0
+
+#include <CoreTraps.h>
+
+/***********************************************************************
+ * Locale Manager errors
+ **********************************************************************/
+
+/* Locale not found in 'locs' resource.
+*/
+#define lmErrUnknownLocale (lmErrorClass | 1)
+
+/* Locale index >= LmGetNumLocales().
+*/
+#define lmErrBadLocaleIndex (lmErrorClass | 2)
+
+/* LmLocaleSettingChoice out of bounds.
+*/
+#define lmErrBadLocaleSettingChoice (lmErrorClass | 3)
+
+/* Data for locale setting too big for destination.
+*/
+#define lmErrSettingDataOverflow (lmErrorClass | 4)
+
+/***********************************************************************
+ * Locale Manager settings (pass to LmGetLocaleSetting)
+ **********************************************************************/
+
+typedef UInt16 LmLocaleSettingChoice;
+
+/* LmLocaleType
+*/
+#define lmChoiceLocale ((LmLocaleSettingChoice)1)
+
+/* Char[kMaxLanguageNameLen+1] - Name of the language spoken there (localized)
+*/
+#if SUPPORT_LANGUAGE_NAME
+ #define lmChoiceLanguageName ((LmLocaleSettingChoice)4)
+#else
+ #define lmChoiceLanguageName #error lmChoiceLanguageName not supported
+#endif
+
+/* Char[kMaxCountryNameLen+1] - Name of the country (localized)
+*/
+#define lmChoiceCountryName ((LmLocaleSettingChoice)5)
+
+/* DateFormatType
+*/
+#define lmChoiceDateFormat ((LmLocaleSettingChoice)6)
+
+/* DateFormatType
+*/
+#define lmChoiceLongDateFormat ((LmLocaleSettingChoice)7)
+
+/* TimeFormatType
+*/
+#define lmChoiceTimeFormat ((LmLocaleSettingChoice)8)
+
+/* UInt16 - Weekday for calendar column 1 (sunday=0, monday=1, etc.)
+*/
+#define lmChoiceWeekStartDay ((LmLocaleSettingChoice)9)
+
+/* Int16 - Default GMT offset minutes, + for east of GMT, - for west
+*/
+#define lmChoiceTimeZone ((LmLocaleSettingChoice)10)
+
+/* NumberFormatType - Specifies decimal and thousands separator characters
+*/
+#define lmChoiceNumberFormat ((LmLocaleSettingChoice)11)
+
+/* Char[kMaxCurrencyNameLen+1] - Name of local currency (e.g., "US Dollar")
+*/
+#define lmChoiceCurrencyName ((LmLocaleSettingChoice)12)
+
+/* Char[kMaxCurrencySymbolLen+1] - Currency symbol (e.g., "$")
+*/
+#define lmChoiceCurrencySymbol ((LmLocaleSettingChoice)13)
+
+/* Char[kMaxCurrencySymbolLen+1] - Unique currency symbol (e.g., "US$")
+*/
+#define lmChoiceUniqueCurrencySymbol ((LmLocaleSettingChoice)14)
+
+/* UInt16 - Number of decimals for currency (e.g., 2 for $10.12)
+*/
+#define lmChoiceCurrencyDecimalPlaces ((LmLocaleSettingChoice)15)
+
+/* MeasurementSystemType - Metric, English, etc.
+*/
+#define lmChoiceMeasurementSystem ((LmLocaleSettingChoice)16)
+
+/***********************************************************************
+ * Locale Manager constants
+ **********************************************************************/
+#define lmAnyCountry 65535U // Pass LmLocaleToIndex's iLocale
+#define lmAnyLanguage 65535U // Pass LmLocaleToIndex's iLocale
+
+#define kMaxCountryNameLen 19
+#if SUPPORT_LANGUAGE_NAME
+ #define kMaxLanguageNameLen 19
+#endif
+#define kMaxCurrencyNameLen 19
+#define kMaxCurrencySymbolLen 5
+
+/***********************************************************************
+ * Selectors & macros used for calling Locale Manager routines
+ **********************************************************************/
+
+#ifndef DIRECT_LOCALE_CALLS
+ #define DIRECT_LOCALE_CALLS 0
+#endif
+#if DIRECT_LOCALE_CALLS
+ #define LMDISPATCH_TRAP(routineSelector)
+#else
+ #define LMDISPATCH_TRAP(routineSelector) \
+ _SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, \
+ sysTrapLmDispatch, \
+ routineSelector)
+#endif
+
+/* Selectors used for getting to the right Locale Manager routine via
+the LmDispatch trap. */
+
+// DOLATER:jwm: remove me after fixing LocaleMgr.c:PrvSelectorError
+typedef UInt16 LmRoutineSelector;
+#define lmInit 0
+#define lmGetNumLocales 1
+#define lmLocaleToIndex 2
+#define lmGetLocaleSetting 3
+
+#define lmMaxRoutineSelector lmGetLocaleSetting
+
+/***********************************************************************
+ * Locale Manager types
+ **********************************************************************/
+
+typedef UInt8 LanguageType;
+typedef UInt8 CountryType;
+
+typedef struct _LmLocaleType LmLocaleType;
+struct _LmLocaleType
+{
+ UInt16 language; // Language spoken in locale (LanguageType)
+ UInt16 country; // Specifies "dialect" of language (CountryType)
+};
+
+/***********************************************************************
+ * Locale Manager routines
+ **********************************************************************/
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Return the number of known locales (maximum locale index + 1).
+*/
+UInt16
+LmGetNumLocales(void)
+ LMDISPATCH_TRAP(lmGetNumLocales);
+
+/* Convert <iLocale> to <oLocaleIndex> by locating it within the set of known
+locales.
+*/
+Err
+LmLocaleToIndex( const
+ LmLocaleType* iLocale,
+ UInt16* oLocaleIndex)
+ LMDISPATCH_TRAP(lmLocaleToIndex);
+
+/* Return in <oValue> the setting identified by <iChoice> which is appropriate for
+the locale identified by <iLocaleIndex>. Return lmErrSettingDataOverflow if the
+data for <iChoice> occupies more than <iValueSize> bytes. Display a non-fatal
+error if <iValueSize> is larger than the data for a fixed-size setting.
+*/
+Err
+LmGetLocaleSetting( UInt16 iLocaleIndex,
+ LmLocaleSettingChoice iChoice,
+ void* oValue,
+ UInt16 iValueSize)
+ LMDISPATCH_TRAP(lmGetLocaleSetting);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
+
+#endif
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Localize.h b/SrcShared/Palm/Platform/Incs/Core/System/Localize.h
new file mode 100644
index 0000000..6bf9e92
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Localize.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1996-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Localize.h
+ *
+ * Description:
+ * Functions to localize data.
+ *
+ * History:
+ * 8/28/96 Roger - Initial version
+ *
+ *****************************************************************************/
+
+#ifndef __LOCALIZE_H__
+#define __LOCALIZE_H__
+
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+
+// The number format (thousands separator and decimal point). This defines
+// how numbers are formatted and not neccessarily currency numbers (i.e. Switzerland).
+typedef enum {
+ nfCommaPeriod,
+ nfPeriodComma,
+ nfSpaceComma,
+ nfApostrophePeriod,
+ nfApostropheComma
+ } NumberFormatType;
+
+
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void LocGetNumberSeparators(NumberFormatType numberFormat,
+ Char *thousandSeparator, Char *decimalSeparator)
+ SYS_TRAP(sysTrapLocGetNumberSeparators);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif // __LOCALIZE_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/MemoryMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/MemoryMgr.h
new file mode 100644
index 0000000..c0b7f6d
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/MemoryMgr.h
@@ -0,0 +1,341 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: MemoryMgr.h
+ *
+ * Description:
+ * Include file for Memory Manager
+ *
+ * History:
+ * 10/25/94 RM Created by Ron Marianetti
+ * 10/28/99 kwk Added memErrROMOnlyCard.
+ *
+ *****************************************************************************/
+
+#ifndef __MEMORYMGR_H__
+#define __MEMORYMGR_H__
+
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+#include <ErrorBase.h>
+
+
+/************************************************************
+ * Memory Manager Types
+ *************************************************************/
+typedef enum { memIDPtr, memIDHandle } LocalIDKind;
+
+
+/************************************************************
+ * Flags accepted as parameter for MemNewChunk.
+ *************************************************************/
+#define memNewChunkFlagPreLock 0x0100
+#define memNewChunkFlagNonMovable 0x0200
+#define memNewChunkFlagAtStart 0x0400 // force allocation at front of heap
+#define memNewChunkFlagAtEnd 0x0800 // force allocation at end of heap
+
+
+/************************************************************
+ * Memory Manager Debug settings for the MemSetDebugMode function
+ *************************************************************/
+#define memDebugModeCheckOnChange 0x0001
+#define memDebugModeCheckOnAll 0x0002
+#define memDebugModeScrambleOnChange 0x0004
+#define memDebugModeScrambleOnAll 0x0008
+#define memDebugModeFillFree 0x0010
+#define memDebugModeAllHeaps 0x0020
+#define memDebugModeRecordMinDynHeapFree 0x0040
+
+
+
+
+/************************************************************
+ * Memory Manager result codes
+ *************************************************************/
+#define memErrChunkLocked (memErrorClass | 1)
+#define memErrNotEnoughSpace (memErrorClass | 2)
+#define memErrInvalidParam (memErrorClass | 3) /* invalid param or requested size is too big */
+#define memErrChunkNotLocked (memErrorClass | 4)
+#define memErrCardNotPresent (memErrorClass | 5)
+#define memErrNoCardHeader (memErrorClass | 6)
+#define memErrInvalidStoreHeader (memErrorClass | 7)
+#define memErrRAMOnlyCard (memErrorClass | 8)
+#define memErrWriteProtect (memErrorClass | 9)
+#define memErrNoRAMOnCard (memErrorClass | 10)
+#define memErrNoStore (memErrorClass | 11)
+#define memErrROMOnlyCard (memErrorClass | 12)
+
+
+/********************************************************************
+ * Memory Manager Routines
+ * These are define as external calls only under emulation mode or
+ * under native mode from the module that actually installs the trap
+ * vectors
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//-------------------------------------------------------------------
+// Initialization
+//-------------------------------------------------------------------
+Err MemInit(void)
+ SYS_TRAP(sysTrapMemInit);
+
+Err MemKernelInit(void)
+ SYS_TRAP(sysTrapMemKernelInit);
+
+Err MemInitHeapTable(UInt16 cardNo)
+ SYS_TRAP(sysTrapMemInitHeapTable);
+
+//-------------------------------------------------------------------
+// Card formatting and Info
+//-------------------------------------------------------------------
+UInt16 MemNumCards(void)
+ SYS_TRAP(sysTrapMemNumCards);
+
+Err MemCardFormat(UInt16 cardNo, Char *cardNameP,
+ Char *manufNameP, Char *ramStoreNameP)
+ SYS_TRAP(sysTrapMemCardFormat);
+
+Err MemCardInfo(UInt16 cardNo,
+ Char *cardNameP, Char *manufNameP,
+ UInt16 *versionP, UInt32 *crDateP,
+ UInt32 *romSizeP, UInt32 *ramSizeP,
+ UInt32 *freeBytesP)
+ SYS_TRAP(sysTrapMemCardInfo);
+
+
+//-------------------------------------------------------------------
+// Store Info
+//-------------------------------------------------------------------
+Err MemStoreInfo(UInt16 cardNo, UInt16 storeNumber,
+ UInt16 *versionP, UInt16 *flagsP, Char *nameP,
+ UInt32 * crDateP, UInt32 *bckUpDateP,
+ UInt32 * heapListOffsetP, UInt32 *initCodeOffset1P,
+ UInt32 *initCodeOffset2P, LocalID* databaseDirIDP)
+ SYS_TRAP(sysTrapMemStoreInfo);
+
+Err MemStoreSetInfo(UInt16 cardNo, UInt16 storeNumber,
+ UInt16 *versionP, UInt16 *flagsP, Char *nameP,
+ UInt32 *crDateP, UInt32 *bckUpDateP,
+ UInt32 *heapListOffsetP, UInt32 *initCodeOffset1P,
+ UInt32 *initCodeOffset2P, LocalID* databaseDirIDP)
+ SYS_TRAP(sysTrapMemStoreSetInfo);
+
+
+//-------------------------------------------------------------------
+// Heap Info & Utilities
+//-------------------------------------------------------------------
+UInt16 MemNumHeaps(UInt16 cardNo)
+ SYS_TRAP(sysTrapMemNumHeaps);
+
+UInt16 MemNumRAMHeaps(UInt16 cardNo)
+ SYS_TRAP(sysTrapMemNumRAMHeaps);
+
+UInt16 MemHeapID(UInt16 cardNo, UInt16 heapIndex)
+ SYS_TRAP(sysTrapMemHeapID);
+
+Boolean MemHeapDynamic(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapDynamic);
+
+Err MemHeapFreeBytes(UInt16 heapID, UInt32 *freeP, UInt32 *maxP)
+ SYS_TRAP(sysTrapMemHeapFreeBytes);
+
+UInt32 MemHeapSize(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapSize);
+
+UInt16 MemHeapFlags(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapFlags);
+
+
+// Heap utilities
+Err MemHeapCompact(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapCompact);
+
+Err MemHeapInit(UInt16 heapID, Int16 numHandles, Boolean initContents)
+ SYS_TRAP(sysTrapMemHeapInit);
+
+Err MemHeapFreeByOwnerID(UInt16 heapID, UInt16 ownerID)
+ SYS_TRAP(sysTrapMemHeapFreeByOwnerID);
+
+
+//-------------------------------------------------------------------
+// Low Level Allocation
+//-------------------------------------------------------------------
+MemPtr MemChunkNew(UInt16 heapID, UInt32 size, UInt16 attr)
+ SYS_TRAP(sysTrapMemChunkNew);
+
+Err MemChunkFree(MemPtr chunkDataP)
+ SYS_TRAP(sysTrapMemChunkFree);
+
+
+
+//-------------------------------------------------------------------
+// Pointer (Non-Movable) based Chunk Routines
+//-------------------------------------------------------------------
+MemPtr MemPtrNew(UInt32 size)
+ SYS_TRAP(sysTrapMemPtrNew);
+
+#define MemPtrFree( p) \
+ MemChunkFree(p)
+
+// Getting Attributes
+MemHandle MemPtrRecoverHandle(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrRecoverHandle);
+
+UInt16 MemPtrFlags(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrFlags);
+
+UInt32 MemPtrSize(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrSize);
+
+UInt16 MemPtrOwner(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrOwner);
+
+UInt16 MemPtrHeapID(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrHeapID);
+
+Boolean MemPtrDataStorage(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrDataStorage);
+
+UInt16 MemPtrCardNo(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrCardNo);
+
+LocalID MemPtrToLocalID(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrToLocalID);
+
+// Setting Attributes
+Err MemPtrSetOwner(MemPtr p, UInt16 owner)
+ SYS_TRAP(sysTrapMemPtrSetOwner);
+
+Err MemPtrResize(MemPtr p, UInt32 newSize)
+ SYS_TRAP(sysTrapMemPtrResize);
+
+Err MemPtrResetLock(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrResetLock);
+
+Err MemPtrUnlock(MemPtr p)
+ SYS_TRAP(sysTrapMemPtrUnlock);
+
+
+//-------------------------------------------------------------------
+// MemHandle (Movable) based Chunk Routines
+//-------------------------------------------------------------------
+MemHandle MemHandleNew(UInt32 size)
+ SYS_TRAP(sysTrapMemHandleNew);
+
+Err MemHandleFree(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleFree);
+
+// Getting Attributes
+UInt16 MemHandleFlags(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleFlags);
+
+UInt32 MemHandleSize(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleSize);
+
+UInt16 MemHandleOwner(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleOwner);
+
+UInt16 MemHandleLockCount(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleLockCount);
+
+UInt16 MemHandleHeapID(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleHeapID);
+
+Boolean MemHandleDataStorage(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleDataStorage);
+
+UInt16 MemHandleCardNo(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleCardNo);
+
+LocalID MemHandleToLocalID(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleToLocalID);
+
+
+// Setting Attributes
+Err MemHandleSetOwner( MemHandle h, UInt16 owner)
+ SYS_TRAP(sysTrapMemHandleSetOwner);
+
+Err MemHandleResize(MemHandle h, UInt32 newSize)
+ SYS_TRAP(sysTrapMemHandleResize);
+
+MemPtr MemHandleLock(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleLock);
+
+Err MemHandleUnlock(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleUnlock);
+
+Err MemHandleResetLock(MemHandle h)
+ SYS_TRAP(sysTrapMemHandleResetLock);
+
+
+
+
+//-------------------------------------------------------------------
+// Local ID based routines
+//-------------------------------------------------------------------
+MemPtr MemLocalIDToGlobal(LocalID local, UInt16 cardNo)
+ SYS_TRAP(sysTrapMemLocalIDToGlobal);
+
+LocalIDKind MemLocalIDKind(LocalID local)
+ SYS_TRAP(sysTrapMemLocalIDKind);
+
+MemPtr MemLocalIDToPtr(LocalID local, UInt16 cardNo)
+ SYS_TRAP(sysTrapMemLocalIDToPtr);
+
+MemPtr MemLocalIDToLockedPtr(LocalID local, UInt16 cardNo)
+ SYS_TRAP(sysTrapMemLocalIDToLockedPtr);
+
+
+//-------------------------------------------------------------------
+// Utilities
+//-------------------------------------------------------------------
+Err MemMove(void *dstP, const void *sP, Int32 numBytes)
+ SYS_TRAP(sysTrapMemMove);
+
+Err MemSet(void *dstP, Int32 numBytes, UInt8 value)
+ SYS_TRAP(sysTrapMemSet);
+
+Int16 MemCmp (const void *s1, const void *s2, Int32 numBytes)
+ SYS_TRAP(sysTrapMemCmp);
+
+Err MemSemaphoreReserve(Boolean writeAccess)
+ SYS_TRAP(sysTrapMemSemaphoreReserve);
+
+Err MemSemaphoreRelease(Boolean writeAccess)
+ SYS_TRAP(sysTrapMemSemaphoreRelease);
+
+//-------------------------------------------------------------------
+// Debugging Support
+//-------------------------------------------------------------------
+UInt16 MemDebugMode(void)
+ SYS_TRAP(sysTrapMemDebugMode);
+
+Err MemSetDebugMode(UInt16 flags)
+ SYS_TRAP(sysTrapMemSetDebugMode);
+
+Err MemHeapScramble(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapScramble);
+
+Err MemHeapCheck(UInt16 heapID)
+ SYS_TRAP(sysTrapMemHeapCheck);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
+
+#endif // __MEMORYMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/NetBitUtils.h b/SrcShared/Palm/Platform/Incs/Core/System/NetBitUtils.h
new file mode 100644
index 0000000..9eb9f15
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/NetBitUtils.h
@@ -0,0 +1,135 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1997-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: NetBitUtils.h
+ *
+ * Description:
+ * Header file for bit manipulation routines used primarily
+ * by wireless network protocols.
+ *
+ * These routines live in the NetLib but are broken out here into
+ * a separate header so that they can be more easily used by source
+ * files that don't need access to the other NetLib functions.
+ *
+ * History:
+ * 6/11/97 Created by Ron Marianetti
+ * Name Date Description
+ * ---- ---- -----------
+ * vmk 8/25/98 Defined bitVarIntMaxBits and bitVarIntMaxBytes
+ *
+ *****************************************************************************/
+
+#ifndef __NETBITUTILS_H__
+#define __NETBITUTILS_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <NetMgr.h>
+
+// # of bits in a byte
+#define bitsInByte 8
+
+
+// Maximum size of variable-size ints in # of bits and bytes. This is based on
+// the largest variable size int, which is encoded as follows: 1111 Bit[32]
+#define bitVarIntMaxBits 36
+#define bitVarIntMaxBytes ((bitVarIntMaxBits + bitsInByte - 1) / bitsInByte)
+
+
+//=====================================================
+// BitXXX Macros
+//
+// The following macros are handy because they don't require that
+// the source code pass in the NetLib library refnum to every
+// call.
+//
+// When building server code or other emulation code where th
+// library trap dispatcher is not used, the libRefNUm is unused
+// and can be 0.
+//
+// When building for the viewer, the libRefNum must be the refNum
+// of the NetLib. For applications, this libRefNum must be put
+// into an application global named 'AppNetRefnum'.
+//
+//====================================================
+#if USE_TRAPS == 0
+ #define netPrvRefnum 0
+#else
+ #define netPrvRefnum AppNetRefnum
+#endif
+
+
+#define BitMove( dstP, dstBitOffsetP, srcP, srcBitOffsetP, numBits) \
+ NetLibBitMove(netPrvRefnum, dstP, dstBitOffsetP, srcP, srcBitOffsetP, numBits)
+
+#define BitPutFixed( dstP, dstBitOffsetP, value, numBits) \
+ NetLibBitPutFixed(netPrvRefnum, dstP, dstBitOffsetP, value, numBits)
+
+#define BitGetFixed(srcP, srcBitOffsetP, numBits) \
+ NetLibBitGetFixed(netPrvRefnum, srcP, srcBitOffsetP, numBits)
+
+#define BitPutUIntV(dstP, dstBitOffsetP, value) \
+ NetLibBitPutUIntV(netPrvRefnum, dstP, dstBitOffsetP, value)
+
+#define BitGetUIntV(srcP, srcBitOffsetP) \
+ NetLibBitGetUIntV(netPrvRefnum, srcP, srcBitOffsetP)
+
+#define BitPutIntV(dstP, dstBitOffsetP, value) \
+ NetLibBitPutIntV(netPrvRefnum, dstP, dstBitOffsetP, value)
+
+#define BitGetIntV(srcP, srcBitOffsetP) \
+ NetLibBitGetIntV(netPrvRefnum, srcP, srcBitOffsetP)
+
+
+
+
+//=====================================================
+// Functions
+//====================================================
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------
+// Bit Moving functions. For "slim" bit packing protocols
+// used over wireless.
+//--------------------------------------------------
+void NetLibBitMove(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP,
+ UInt8 *srcP, UInt32 *srcBitOffsetP,
+ UInt32 numBits)
+ SYS_TRAP(netLibTrapBitMove);
+
+
+void NetLibBitPutFixed(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP,
+ UInt32 value, UInt16 numBits)
+ SYS_TRAP(netLibTrapBitPutFixed);
+
+UInt32 NetLibBitGetFixed(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP,
+ UInt16 numBits)
+ SYS_TRAP(netLibTrapBitGetFixed);
+
+void NetLibBitPutUIntV(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP,
+ UInt32 value)
+ SYS_TRAP(netLibTrapBitPutUIntV);
+
+UInt32 NetLibBitGetUIntV(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP)
+ SYS_TRAP(netLibTrapBitGetUIntV);
+
+void NetLibBitPutIntV(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP,
+ Int32 value)
+ SYS_TRAP(netLibTrapBitPutUIntV);
+
+Int32 NetLibBitGetIntV(UInt16 libRefNum, UInt8 *dstP, UInt32 *dstBitOffsetP)
+ SYS_TRAP(netLibTrapBitGetUIntV);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif // __NETBITUTILS_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/NetMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/NetMgr.h
new file mode 100644
index 0000000..ba0064e
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/NetMgr.h
@@ -0,0 +1,1515 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1996-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: NetMgr.h
+ *
+ * Description:
+ * This module contains the interface definition for the TCP/IP
+ * library on Pilot.
+ *
+ * History:
+ * 2/14/96 Created by Ron Marianetti
+ * Name Date Description
+ * ---- ---- -----------
+ * jrb 3/13/98 Removed NetIFSettings that are Mobitex specific.
+ * Added RadioStateEnum for the setting.
+ * Added NetIFSettingSpecificMobitex
+ * Added what are considered "generic" wirless settings.
+ * jaq 10/1/98 added netMaxIPAddrStrLen constant
+ * scl 3/ 5/99 integrated Eleven's changes into Main
+ *
+ *****************************************************************************/
+
+#ifndef __NETMGR_H__
+#define __NETMGR_H__
+
+#include <PalmTypes.h>
+#include <LibTraps.h>
+#include <SysEvent.h>
+
+// Get rid of warnings about unused pragmas when compiling with
+// Visual C
+#ifdef _MSC_VER
+#pragma warning( disable : 4068)
+#endif
+
+/********************************************************************
+ * Type and creator of Net Library database
+ ********************************************************************/
+
+// Creator. Used for both the database that contains the Net Library and
+// it's preferences database.
+#define netCreator 'netl' // Our Net Library creator
+
+// Feature Creators and numbers, for use with the FtrGet() call. This
+// feature can be obtained to get the current version of the Net Library
+#define netFtrCreator netCreator
+#define netFtrNumVersion 0 // get version of Net Library
+ // 0xMMmfsbbb, where MM is major version, m is minor version
+ // f is bug fix, s is stage: 3-release,2-beta,1-alpha,0-development,
+ // bbb is build number for non-releases
+ // V1.12b3 would be: 0x01122003
+ // V2.00a2 would be: 0x02001002
+ // V1.01 would be: 0x01013000
+
+
+// Types. Used to identify the Net Library from it's prefs.
+#define netLibType 'libr' // Our Net Code Resources Database type
+#define netPrefsType 'rsrc' // Our Net Preferences Database type
+
+
+// All Network interface's have the following type:
+#define netIFFileType 'neti' // The filetype of all Network Interfaces
+
+// Each Network interface has a unique creator:
+#define netIFCreatorLoop 'loop' // Loopback network interface creator.
+#define netIFCreatorSLIP 'slip' // SLIP network interface creator.
+#define netIFCreatorPPP 'ppp_' // PPP network interface creator.
+//<chg 1-28-98 RM>
+#define netIFCreatorRAM 'ram_' // Mobitex network interface creator
+
+
+// Special value for configIndex parameter to NetLibOpenConfig that tells it
+// to use the current settings - even if they are not the defined default settings
+// This is provided for testing purposes
+#define netConfigIndexCurSettings 0xFFFF
+
+// <SCL 3/5/99> Commented out netMaxNetIFs since Tim says it should NOT be here!!
+// Still need to fix (Eleven) code that currently depends on it...
+// Max # of interfaces that can be installed
+//#define netMaxNetIFs 4
+
+
+//-----------------------------------------------------------------------------
+// Misc. constants
+//-----------------------------------------------------------------------------
+#define netDrvrTypeNameLen 8 // Maximum driver type length
+#define netDrvrHWNameLen 16 // Maximum driver hardware name length
+#define netIFNameLen 10 // Maximum interface name (driver type + instance num)
+#define netIFMaxHWAddrLen 14 // Maximum size of a hardware address
+#define netMaxIPAddrStrLen 16 // Max length of an IP address string with null terminator (255.255.255.255)
+
+
+
+//-----------------------------------------------------------------------------
+// Names of built-in configuration aliases available through the
+// NetLibConfigXXX calls
+//-----------------------------------------------------------------------------
+#define netCfgNameDefault ".Default" // The default configuration
+#define netCfgNameDefWireline ".DefWireline" // The default wireline configuration
+#define netCfgNameDefWireless ".DefWireless" // The default wireless configuration
+#define netCfgNameCTPWireline ".CTPWireline" // Wireline through the Jerry Proxy
+#define netCfgNameCTPWireless ".CTPWireless" // Wireless through the Jerry Proxy
+
+
+//-----------------------------------------------------------------------------
+//Flags for the NetUWirelessAppHandleEvent() utility routine
+//-----------------------------------------------------------------------------
+#define netWLAppEventFlagCTPOnly 0x00000001 // using wireless radio for CTP protocol only
+#define netWLAppEventFlagDisplayErrs 0x00000002 // Show error alerts for any errors
+
+//-----------------------------------------------------------------------------
+// Option constants that can be passed to NetSocketOptionSet and NetSocketOptionGet
+// When an option is set or retrieved, both the level of the option and the
+// option number must be specified. The level refers to which layer the option
+// refers to, like the uppermost socket layer, for example.
+//-----------------------------------------------------------------------------
+
+// Socket level options
+typedef enum {
+ // IP Level options
+ netSocketOptIPOptions = 1, // options in IP header (IP_OPTIONS)
+
+ // TCP Level options
+ netSocketOptTCPNoDelay = 1, // don't delay send to coalesce packets
+ netSocketOptTCPMaxSeg = 2, // TCP maximum segment size (TCP_MAXSEG)
+
+ // Socket level options
+ netSocketOptSockDebug = 0x0001, // turn on debugging info recording
+ netSocketOptSockAcceptConn = 0x0002, // socket has had listen
+ netSocketOptSockReuseAddr = 0x0004, // allow local address reuse
+ netSocketOptSockKeepAlive = 0x0008, // keep connections alive
+ netSocketOptSockDontRoute = 0x0010, // just use interface addresses
+ netSocketOptSockBroadcast = 0x0020, // permit sending of broadcast msgs
+ netSocketOptSockUseLoopback = 0x0040, // bypass hardware when possible
+ netSocketOptSockLinger = 0x0080, // linger on close if data present
+ netSocketOptSockOOBInLine = 0x0100, // leave received OutOfBand data in line
+
+ netSocketOptSockSndBufSize = 0x1001, // send buffer size
+ netSocketOptSockRcvBufSize = 0x1002, // receive buffer size
+ netSocketOptSockSndLowWater = 0x1003, // send low-water mark
+ netSocketOptSockRcvLowWater = 0x1004, // receive low-water mark
+ netSocketOptSockSndTimeout = 0x1005, // send timeout
+ netSocketOptSockRcvTimeout = 0x1006, // receive timeout
+ netSocketOptSockErrorStatus= 0x1007, // get error status and clear
+ netSocketOptSockSocketType = 0x1008, // get socket type
+
+ // The following are Pilot specific options
+ netSocketOptSockNonBlocking = 0x2000, // set non-blocking mode on or off
+ netSocketOptSockRequireErrClear = 0x2001, // return error from all further calls to socket
+ // unless netSocketOptSockErrorStatus is cleared.
+ netSocketOptSockMultiPktAddr = 0x2002 // for SOCK_RDM (RMP) sockets. This is the
+ // fixed IP addr (i.e. Mobitex MAN #) to use
+ // for multiple packet requests.
+ } NetSocketOptEnum;
+
+
+
+
+// Option levels for SocketOptionSet and SocketOptionGet
+typedef enum {
+ netSocketOptLevelIP = 0, // IP level options (IPPROTO_IP)
+ netSocketOptLevelTCP = 6, // TCP level options (IPPROTO_TCP)
+ netSocketOptLevelSocket = 0xFFFF // Socket level options (SOL_SOCKET)
+ } NetSocketOptLevelEnum;
+
+
+// Structure used for manipulating the linger option
+typedef struct {
+ Int16 onOff; // option on/off
+ Int16 time; // linger time in seconds
+ } NetSocketLingerType;
+
+//-----------------------------------------------------------------------------
+// Enumeration of Socket domains and types passed to NetSocketOpen
+//-----------------------------------------------------------------------------
+typedef enum {
+ netSocketAddrRaw=0, // (AF_UNSPEC, AF_RAW)
+ netSocketAddrINET=2 // (AF_INET)
+ } NetSocketAddrEnum;
+
+typedef enum {
+ netSocketTypeStream=1, // (SOCK_STREAM)
+ netSocketTypeDatagram=2, // (SOCK_DGRAM)
+ netSocketTypeRaw=3, // (SOCK_RAW)
+ netSocketTypeReliableMsg=4, // (SOCK_RDM)
+ netSocketTypeLicensee=8 // Socket entry reserved for licensees.
+ } NetSocketTypeEnum;
+
+// Protocols, passed in the protocol parameter to NetLibSocketOpen
+#define netSocketProtoIPICMP 1 // IPPROTO_ICMP
+#define netSocketProtoIPTCP 6 // IPPROTO_TCP
+#define netSocketProtoIPUDP 17 // IPPROTO_UDP
+#define netSocketProtoIPRAW 255 // IPPROTO_RAW
+
+
+//-----------------------------------------------------------------------------
+// Enumeration of Socket direction, passed to NetSocketShutdown
+//-----------------------------------------------------------------------------
+typedef enum {
+ netSocketDirInput=0,
+ netSocketDirOutput=1,
+ netSocketDirBoth=2
+ } NetSocketDirEnum;
+
+
+//-----------------------------------------------------------------------------
+// Basic Types
+//-----------------------------------------------------------------------------
+// Socket refnum
+typedef Int16 NetSocketRef;
+
+// Type used to hold internet addresses
+typedef UInt32 NetIPAddr; // a 32-bit IP address.
+
+
+
+//-----------------------------------------------------------------------------
+// Structure used to hold an internet socket address. This includes the internet
+// address and the port number. This structure directly maps to the BSD unix
+// struct sockaddr_in.
+//-----------------------------------------------------------------------------
+typedef struct NetSocketAddrINType {
+ Int16 family; // Address family in HBO (Host UInt8 Order)
+ UInt16 port; // the UDP port in NBO (Network UInt8 Order)
+ NetIPAddr addr; // IP address in NBO (Network UInt8 Order)
+ } NetSocketAddrINType;
+
+// Constant that means "use the local machine's IP address"
+#define netIPAddrLocal 0 // Can be used in NetSockAddrINType.addr
+
+
+// Structure used to hold a generic socket address. This is a generic struct
+// designed to hold any type of address including internet addresses. This
+// structure directly maps to the BSD unix struct sockaddr.
+typedef struct NetSocketAddrType {
+ Int16 family; // Address family
+ UInt8 data[14]; // 14 bytes of address
+ } NetSocketAddrType;
+
+
+// Structure used to hold a raw socket address. When using the netSocketAddrRaw
+// protocol family, the caller must bind() the socket to an interface and
+// specifies the interface using this structure. IMPORTANT: NUMEROUS
+// ROUTINES IN NETLIB RELY ON THE FACT THAT THIS STRUCTURE IS THE SAME
+// SIZE AS A NetSocketAddrINType STRUCTURE.
+typedef struct NetSocketAddrRawType {
+ Int16 family; // Address family in HBO (Host UInt8 Order)
+ UInt16 ifInstance; // the interface instance number
+ UInt32 ifCreator; // the interface creator
+ } NetSocketAddrRawType;
+
+
+
+//-----------------------------------------------------------------------------
+// Structure used to hold information about data to be sent. This structure
+// is passed to NetLibSendMsg and contains the optional address to send to,
+// a scatter-write array of data to be sent, and optional access rights
+//-----------------------------------------------------------------------------
+
+// Scatter/Gather array type. A pointer to an array of these structs is
+// passed to the NetLibSendPB and NetLibRecvPB calls. It specifies where
+// data should go to or come from as a list of buffer addresses and sizes.
+typedef struct NetIOVecType {
+ UInt8 * bufP; // buffer address
+ UInt16 bufLen; // buffer length
+ } NetIOVecType, *NetIOVecPtr;
+
+#define netIOVecMaxLen 16 // max# of NetIOVecTypes in an array
+
+// Read/Write ParamBlock type. Passed directly to the SendPB and RecvPB calls.
+typedef struct {
+ UInt8 * addrP; // address - or 0 for default
+ UInt16 addrLen; // length of address
+ NetIOVecPtr iov; // scatter/gather array
+ UInt16 iovLen; // length of above array
+ UInt8 * accessRights; // access rights
+ UInt16 accessRightsLen; // length of accessrights
+ } NetIOParamType, *NetIOParamPtr;
+
+// Flags values for the NetLibSend, NetLibReceive calls
+#define netIOFlagOutOfBand 0x01 // process out-of-band data
+#define netIOFlagPeek 0x02 // peek at incoming message
+#define netIOFlagDontRoute 0x04 // send without using routing
+
+
+
+//-----------------------------------------------------------------------------
+// Structures used for looking up a host by name or address (NetLibGetHostByName)
+//-----------------------------------------------------------------------------
+
+// Equates for DNS names, from RFC-1035
+#define netDNSMaxDomainName 255
+#define netDNSMaxDomainLabel 63
+
+#define netDNSMaxAliases 1 // max # of aliases for a host
+#define netDNSMaxAddresses 4 // max # of addresses for a host
+
+
+// The actual results of NetLibGetHostByName() are returned in this structure.
+// This structure is designed to match the "struct hostent" structure in Unix.
+typedef struct {
+ Char * nameP; // official name of host
+ Char ** nameAliasesP; // array of alias's for the name
+ UInt16 addrType; // address type of return addresses
+ UInt16 addrLen; // the length, in bytes, of the addresses
+ UInt8 ** addrListP; // array of ptrs to addresses in HBO
+ } NetHostInfoType, *NetHostInfoPtr;
+
+
+// "Buffer" passed to call as a place to store the results
+typedef struct {
+ NetHostInfoType hostInfo; // high level results of call are here
+
+ // The following fields contain the variable length data that
+ // hostInfo points to
+ Char name[netDNSMaxDomainName+1]; // hostInfo->name
+
+ Char *aliasList[netDNSMaxAliases+1]; // +1 for 0 termination.
+ Char aliases[netDNSMaxAliases][netDNSMaxDomainName+1];
+
+ NetIPAddr* addressList[netDNSMaxAddresses];
+ NetIPAddr address[netDNSMaxAddresses];
+
+ } NetHostInfoBufType, *NetHostInfoBufPtr;
+
+
+//-----------------------------------------------------------------------------
+// Structures used for looking up a service (NetLibGetServByName)
+//-----------------------------------------------------------------------------
+
+// Equates for service names
+#define netServMaxName 15 // max # characters in service name
+#define netProtoMaxName 15 // max # characters in protocol name
+#define netServMaxAliases 1 // max # of aliases for a service
+
+
+// The actual results of NetLibGetServByName() are returned in this structure.
+// This structure is designed to match the "struct servent" structure in Unix.
+typedef struct {
+ Char * nameP; // official name of service
+ Char ** nameAliasesP; // array of alias's for the name
+ UInt16 port; // port number for this service
+ Char * protoP; // name of protocol to use
+ } NetServInfoType, *NetServInfoPtr;
+
+// "Buffer" passed to call as a place to store the results
+typedef struct {
+ NetServInfoType servInfo; // high level results of call are here
+
+ // The following fields contain the variable length data that
+ // servInfo points to
+ Char name[netServMaxName+1]; // hostInfo->name
+
+ Char * aliasList[netServMaxAliases+1]; // +1 for 0 termination.
+ Char aliases[netServMaxAliases][netServMaxName];
+ Char protoName[netProtoMaxName+1];
+
+ UInt8 reserved;
+ } NetServInfoBufType, *NetServInfoBufPtr;
+
+
+
+//--------------------------------------------------------------------
+// Structure of a configuration name. Used by NetLibConfigXXX calls
+// <chg 1-28-98 RM> added for the new Config calls.
+//---------------------------------------------------------------------
+#define netConfigNameSize 32
+typedef struct {
+ Char name[netConfigNameSize]; // name of configuration
+ } NetConfigNameType, *NetConfigNamePtr;
+
+
+
+/********************************************************************
+ * Tracing Flags. These flags are ORed together and passed as a UInt32
+ * in the netSettingTraceFlags setting and netIFSettingTraceFlags to
+ * enable/disable various trace options.
+ ********************************************************************/
+#define netTracingErrors 0x00000001 // record errors
+#define netTracingMsgs 0x00000002 // record messages
+#define netTracingPktIP 0x00000004 // record packets sent/received
+ // to/from interfaces at the IP layer
+ // NOTE: netTracingPktData40 & netTracingPktData
+ // will control how much data of each packet is
+ // recorded.
+#define netTracingFuncs 0x00000008 // record function flow
+#define netTracingAppMsgs 0x00000010 // record application messages
+ // (NetLibTracePrintF, NetLibTracePutS)
+#define netTracingPktData40 0x00000020 // record first 40 bytes of packets
+ // when netTracingPktsXX is also on.
+ // NOTE: Mutually exclusive with
+ // netTracingPktData and only applicable if
+ // one of the netTracingPktsXX bits is also set
+#define netTracingPktData 0x00000040 // record all bytes of IP packets
+ // sent/received to/from interfaces
+ // NOTE: Mutually exclusive with
+ // netTracingPkts & netTracingPktData64
+#define netTracingPktIFHi 0x00000080 // record packets sent/received at highest layer
+ // of interface (just below IP layer).
+ // NOTE: netTracingPktData40 & netTracingPktData
+ // will control how much data of each packet is
+ // recorded.
+#define netTracingPktIFMid 0x00000100 // record packets sent/received at mid layer
+ // of interface (just below IFHi layer).
+ // NOTE: netTracingPktData40 & netTracingPktData
+ // will control how much data of each packet is
+ // recorded.
+#define netTracingPktIFLow 0x00000200 // record packets sent/received at low layer
+ // of interface (just below IFMid layer).
+ // NOTE: netTracingPktData40 & netTracingPktData
+ // will control how much data of each packet is
+ // recorded.
+
+
+// OBSOLETE tracing bit, still used by Network Panel
+#define netTracingPkts netTracingPktIP
+
+
+/********************************************************************
+ * Command numbers and parameter blocks for the NetLibMaster() call.
+ * This call is used to put the Net library into certain debugging modes
+ * or for obtaining statistics from the Net Library.
+ *
+ ********************************************************************/
+#pragma mark Master
+typedef enum {
+ // These calls return info
+ netMasterInterfaceInfo,
+ netMasterInterfaceStats,
+ netMasterIPStats,
+ netMasterICMPStats,
+ netMasterUDPStats,
+ netMasterTCPStats,
+
+ // This call used to read the trace buffer.
+ netMasterTraceEventGet // get trace event by index
+
+ } NetMasterEnum;
+
+
+typedef struct NetMasterPBType {
+
+ // These fields are specific to each command
+ union {
+
+ //.............................................................
+ // InterfaceInfo command
+ //.............................................................
+ struct {
+ UInt16 index; // -> index of interface
+ UInt32 creator; // <- creator
+ UInt16 instance; // <- instance
+ void * netIFP; // <- net_if pointer
+
+ // driver level info
+ Char drvrName[netDrvrTypeNameLen]; // <- type of driver (SLIP,PPP, etc)
+ Char hwName[netDrvrHWNameLen]; // <- hardware name (Serial Library, etc)
+ UInt8 localNetHdrLen; // <- local net header length
+ UInt8 localNetTrailerLen; // <- local net trailer length
+ UInt16 localNetMaxFrame; // <- local net maximum frame size
+
+ // media layer info
+ Char ifName[netIFNameLen];// <- interface name w/instance
+ Boolean driverUp; // <- true if interface driver up
+ Boolean ifUp; // <- true if interface is up
+ UInt16 hwAddrLen; // <- length of hardware address
+ UInt8 hwAddr[netIFMaxHWAddrLen]; // <- hardware address
+ UInt16 mtu; // <- maximum transfer unit of interface
+ UInt32 speed; // <- speed in bits/sec.
+ UInt32 lastStateChange; // <- time in milliseconds of last state change
+
+ // Address info
+ NetIPAddr ipAddr; // Address of this interface
+ NetIPAddr subnetMask; // subnet mask of local network
+ NetIPAddr broadcast; // broadcast address of local network
+ } interfaceInfo;
+
+ //.............................................................
+ // InterfaceStats command
+ //.............................................................
+ struct {
+ UInt16 index; // -> index of interface
+ UInt32 inOctets; // <- ....
+ UInt32 inUcastPkts;
+ UInt32 inNUcastPkts;
+ UInt32 inDiscards;
+ UInt32 inErrors;
+ UInt32 inUnknownProtos;
+ UInt32 outOctets;
+ UInt32 outUcastPkts;
+ UInt32 outNUcastPkts;
+ UInt32 outDiscards;
+ UInt32 outErrors;
+ } interfaceStats;
+
+ //.............................................................
+ // IPStats command
+ //.............................................................
+ struct {
+ UInt32 ipInReceives;
+ UInt32 ipInHdrErrors;
+ UInt32 ipInAddrErrors;
+ UInt32 ipForwDatagrams;
+ UInt32 ipInUnknownProtos;
+ UInt32 ipInDiscards;
+ UInt32 ipInDelivers;
+ UInt32 ipOutRequests;
+ UInt32 ipOutDiscards;
+ UInt32 ipOutNoRoutes;
+ UInt32 ipReasmReqds;
+ UInt32 ipReasmOKs;
+ UInt32 ipReasmFails;
+ UInt32 ipFragOKs;
+ UInt32 ipFragFails;
+ UInt32 ipFragCreates;
+ UInt32 ipRoutingDiscards;
+ UInt32 ipDefaultTTL;
+ UInt32 ipReasmTimeout;
+ } ipStats;
+
+ //.............................................................
+ // ICMPStats command
+ //.............................................................
+ struct {
+ UInt32 icmpInMsgs;
+ UInt32 icmpInErrors;
+ UInt32 icmpInDestUnreachs;
+ UInt32 icmpInTimeExcds;
+ UInt32 icmpInParmProbs;
+ UInt32 icmpInSrcQuenchs;
+ UInt32 icmpInRedirects;
+ UInt32 icmpInEchos;
+ UInt32 icmpInEchoReps;
+ UInt32 icmpInTimestamps;
+ UInt32 icmpInTimestampReps;
+ UInt32 icmpInAddrMasks;
+ UInt32 icmpInAddrMaskReps;
+ UInt32 icmpOutMsgs;
+ UInt32 icmpOutErrors;
+ UInt32 icmpOutDestUnreachs;
+ UInt32 icmpOutTimeExcds;
+ UInt32 icmpOutParmProbs;
+ UInt32 icmpOutSrcQuenchs;
+ UInt32 icmpOutRedirects;
+ UInt32 icmpOutEchos;
+ UInt32 icmpOutEchoReps;
+ UInt32 icmpOutTimestamps;
+ UInt32 icmpOutTimestampReps;
+ UInt32 icmpOutAddrMasks;
+ UInt32 icmpOutAddrMaskReps;
+ } icmpStats;
+
+ //.............................................................
+ // UDPStats command
+ //.............................................................
+ struct {
+ UInt32 udpInDatagrams;
+ UInt32 udpNoPorts;
+ UInt32 udpInErrors;
+ UInt32 udpOutDatagrams;
+ } udpStats;
+
+ //.............................................................
+ // TCPStats command
+ //.............................................................
+ struct {
+ UInt32 tcpRtoAlgorithm;
+ UInt32 tcpRtoMin;
+ UInt32 tcpRtoMax;
+ UInt32 tcpMaxConn;
+ UInt32 tcpActiveOpens;
+ UInt32 tcpPassiveOpens;
+ UInt32 tcpAttemptFails;
+ UInt32 tcpEstabResets;
+ UInt32 tcpCurrEstab;
+ UInt32 tcpInSegs;
+ UInt32 tcpOutSegs;
+ UInt32 tcpRetransSegs;
+ UInt32 tcpInErrs;
+ UInt32 tcpOutRsts;
+ } tcpStats;
+
+ //.............................................................
+ // TraceEventGet command
+ //.............................................................
+ struct {
+ UInt16 index; // which event
+ Char * textP; // ptr to text string to return it in
+ } traceEventGet;
+
+ } param;
+
+ } NetMasterPBType, *NetMasterPBPtr;
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Enumeration of Net settings as passed to NetLibSettingGet/Set.
+//-----------------------------------------------------------------------------
+#pragma mark Settings
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+// Global environment settings common to all attached network interfaces,
+// passed to NetLibSettingGet/Set
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+typedef enum {
+ netSettingResetAll, // void, NetLibSettingSet only, resets all settings
+ // to their defaults.
+
+ netSettingPrimaryDNS, // UInt32, IP address of Primary DN Server
+ netSettingSecondaryDNS, // UInt32, IP address of Secondary DN Server
+ netSettingDefaultRouter, // UInt32, IP address of Default router
+ netSettingDefaultIFCreator, // UInt32, Creator type of default interface
+ netSettingDefaultIFInstance, // UInt16, Instance# of default interface
+ netSettingHostName, // Char[64], name of host (not including domain)
+ netSettingDomainName, // Char[256], domain name of hosts's domain
+ netSettingHostTbl, // Char[], host table
+ netSettingCloseWaitTime, // UInt32, time in milliseconds to stay in close-wait state
+ netSettingInitialTCPResendTime, // UInt32, time in milliseconds before TCP resends a packet.
+ // This is just the initial value, the timeout is adjusted
+ // from this initial value depending on history of ACK times.
+ // This is sometimes referred to as the RTO (Roundtrip Time Out)
+ // See RFC-1122 for additional information.
+
+
+ // The following settings are not used for configuration, but rather put the
+ // stack into various modes for debugging, etc.
+ netSettingTraceBits = 0x1000, // UInt32, enable/disable various trace flags (netTraceBitXXXX)
+ netSettingTraceSize, // UInt32, max trace buffer size in bytes. Default 0x800.
+ // Setting this will also clear the trace buffer.
+ netSettingTraceStart, // UInt32, for internal use ONLY!!
+ netSettingTraceRoll, // UInt8, if true, trace buffer will rollover after it fills.
+ // Default is true.
+
+ netSettingRTPrimaryDNS, // used internally by Network interfaces
+ // that dynamically obtain the DNS address
+ netSettingRTSecondaryDNS, // used internally by Network interfaces
+ // that dynamically obtain the DNS address
+
+ netSettingConfigTable // used internally by NetLib - NOT FOR USE BY
+ // APPLICATIONS!!
+
+ } NetSettingEnum;
+
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+// Settings for each Network Interface, passed to NetLibIFSettingGet/Set
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+typedef enum {
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // Reset all settings to defaults
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingResetAll, // void, NetLibIFSettingSet only, resets all settings
+ // to their defaults.
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // Status - read only
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingUp, // UInt8, true if interface is UP.
+ netIFSettingName, // Char[32], name of interface
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // Addressing
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingReqIPAddr, // UInt32, requested IP address of this interface
+ netIFSettingSubnetMask, // UInt32, subnet mask of this interface
+ netIFSettingBroadcast, // UInt32, broadcast address for this interface
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // User Info
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingUsername, // Char[], login script user name
+ // If 0 length, then user will be prompted for it
+ netIFSettingPassword, // Char[], login script user password
+ // If 0 length, then user will be prompted for it
+ netIFSettingDialbackUsername, // Char[], login script dialback user name.
+ // If 0 length, then netIFSettingUsername is used
+ netIFSettingDialbackPassword, // Char[], login script dialback user password.
+ // If 0 length, then user will be prompted for it
+ netIFSettingAuthUsername, // Char[], PAP/CHAP name.
+ // If 0 length, then netIFSettingUsername is used
+ netIFSettingAuthPassword, // Char[], PAP/CHAP password.
+ // If "$", then user will be prompted for it
+ // else If 0 length, then netIFSettingPassword or result
+ // of it's prompt (if it was empty) will be used
+ // else it is used as-is.
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // Connect Settings
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingServiceName, // Char[], name of service
+ netIFSettingLoginScript, // Char[], login script
+ netIFSettingConnectLog, // Char[], connect log
+ netIFSettingInactivityTimeout, // UInt16, # of seconds of inactivity allowed before
+ // interface is brought down. If 0 then
+ // no inactivity timeout enforced.
+ netIFSettingEstablishmentTimeout, // UInt16, max delay in seconds between connection
+ // establishment stages
+
+ // Serial based protocol options
+ netIFSettingDynamicIP, // UInt8, if true, get IP address from server
+ // N/A for SLIP
+ netIFSettingVJCompEnable, // UInt8, if true enable VJ Header compression
+ // Default is on for PPP, off for SLIP
+ netIFSettingVJCompSlots, // UInt8, # of slots to use for VJ compression.
+ // Default is 4 for PPP, 16 for SLIP
+ // (each slot uses 256 bytes of RAM).
+ netIFSettingMTU, // UInt16, maximum transmission unit in bytes
+ // ignored in current PPP and SLIP interfaces
+ netIFSettingAsyncCtlMap, // UInt32, bitmask of characters to escape
+ // ignored in current PPP interfaces
+
+ // Serial settings, used by serial based network interfaces
+ netIFSettingPortNum, // UInt16, port number to use
+ netIFSettingBaudRate, // UInt32, baud rate in bits/sec.
+ netIFSettingFlowControl, // UInt8, flow control setting bits. Set to 0x01 for
+ // hardware flow control, else set to 0x00.
+ netIFSettingStopBits, // UInt8, # of stop bits
+ netIFSettingParityOn, // UInt8, true if parity on
+ netIFSettingParityEven, // UInt8, true if parity even
+
+ // Modem settings, optionally used by serial based network interfaces
+ netIFSettingUseModem, // UInt8, if true dial-up through modem
+ netIFSettingPulseDial, // UInt8, if true use pulse dial, else tone
+ netIFSettingModemInit, // Char[], modem initialization string
+ netIFSettingModemPhone, // Char[], modem phone number string
+ netIFSettingRedialCount, // UInt16, # of times to redial
+
+
+ //---------------------------------------------------------------------------------
+ // New Settings as of PalmOS 3.0
+ // Power control, usually only implemented by wireless interfaces
+ //---------------------------------------------------------------------------------
+ netIFSettingPowerUp, // UInt8, true if this interface is powered up
+ // false if this interface is in power-down mode
+ // interfaces that don't support power modes should
+ // quietly ignore this setting.
+
+ // Wireless or Wireline, read-only, returns true for wireless interfaces. this
+ // setting is used by application level functions to determine which interface(s)
+ // to attach/detach given user preference and/or state of the antenna.
+ netIFSettingWireless, // UInt8, true if this interface is wireless
+
+
+
+ // Option to query server for address of DNS servers
+ netIFSettingDNSQuery, // UInt8, if true PPP queries for DNS address. Default true
+
+
+ //---------------------------------------------------------------------------------
+ // New Settings as of PalmOS 3.2
+ // Power control, usually only implemented by wireless interfaces
+ //---------------------------------------------------------------------------------
+
+ netIFSettingQuitOnTxFail, // BYTE W-only. Power down RF on tx fail
+ netIFSettingQueueSize, // UInt8 R-only. The size of the Tx queue in the RF interface
+ netIFSettingTxInQueue, // BYTE R-only. Packets remaining to be sent
+ netIFSettingTxSent, // BYTE R-only. Packets sent since SocketOpen
+ netIFSettingTxDiscard, // BYTE R-only. Packets discarded on SocketClose
+ netIFSettingRssi, // char R-only. signed value in dBm.
+ netIFSettingRssiAsPercent, // char R-only. signed value in percent, with 0 being no coverage and 100 being excellent.
+ netIFSettingRadioState, // enum R-only. current state of the radio
+ netIFSettingBase, // UInt32 R-only. Interface specific
+ netIFSettingRadioID, // UInt32[2] R-only, two 32-bit. interface specific
+ netIFSettingBattery, // UInt8, R-only. percentage of battery left
+ netIFSettingNetworkLoad, // UInt8, R-only. percent estimate of network loading
+
+ //---------------------------------------------------------------------------------
+ // New Settings as of PalmOS 3.3
+ //---------------------------------------------------------------------------------
+
+ netIFSettingConnectionName, // Char [] Connection Profile Name
+
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // The following settings are not used for configuration, but rather put the
+ // stack into various modes for debugging, etc.
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingTraceBits = 0x1000, // UInt32, enable/disable various trace flags (netTraceBitXXXX)
+ netIFSettingGlobalsPtr, // UInt32, (Read-Only) sinterface's globals ptr
+ netIFSettingActualIPAddr, // UInt32, (Read-Only) the actual IP address that the interface
+ // ends up using. The login script executor stores
+ // the result of the "g" script command here as does
+ // the PPP negotiations.
+ netIFSettingServerIPAddr, // UInt32, (Read-Only) the IP address of the PPP server
+ // we're connected to
+
+
+ // The following setting should be true if this network interface should be
+ // brought down when the Pilot is turned off.
+ netIFSettingBringDownOnPowerDown, // UInt8, if true interface will be brought down when
+ // Pilot is turned off.
+
+ // The following setting is used by the TCP/IP stack ONLY!! It tells the interface
+ // to pass all received packets as-is to the NetIFCallbacksPtr->raw_rcv() routine.
+ // This setting gets setup when an application creates a raw socket in the raw domain
+ netIFSettingRawMode, // UInt32, parameter to pass to raw_rcv() along with
+ // packet pointer.
+
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ // 3rd party settings start here...
+ //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ netIFSettingCustom = 0x8000
+
+ } NetIFSettingEnum;
+
+
+
+//=========================================================================================
+// Enums for the netIFSettingRadioState setting
+//
+// JB added for the radio state setting.
+// <chg 3-17-98 RM> fixed naming conventions.
+//=========================================================================================
+typedef enum {
+ netRadioStateOffNotConnected=0,
+ netRadioStateOnNotConnected, // scanning
+ netRadioStateOnConnected, // have channel
+ netRadioStateOffConnected
+ } NetRadioStateEnum;
+
+
+
+/************************************************************
+ * Net Library Macros
+ *************************************************************/
+// Return current time in milliseconds.
+#define NetNow() (TimGetTicks() * 1000L/sysTicksPerSecond)
+
+
+// File Descriptor macros used for the NetLibSelect() call
+typedef UInt32 NetFDSetType;
+#define netFDSetSize 32
+
+#define netFDSet(n,p) ((*p) |= (1L << n))
+#define netFDClr(n,p) ((*p) &= ~(1L << n))
+#define netFDIsSet(n,p) ((*p) & (1L << n))
+#define netFDZero(p) ((*p) = 0)
+
+
+
+//-----------------------------------------------------------------------------
+// Net error codes
+//-----------------------------------------------------------------------------
+#pragma mark ErrorCodes
+#define netErrAlreadyOpen (netErrorClass | 1)
+#define netErrNotOpen (netErrorClass | 2)
+#define netErrStillOpen (netErrorClass | 3)
+#define netErrParamErr (netErrorClass | 4)
+#define netErrNoMoreSockets (netErrorClass | 5)
+#define netErrOutOfResources (netErrorClass | 6)
+#define netErrOutOfMemory (netErrorClass | 7)
+#define netErrSocketNotOpen (netErrorClass | 8)
+#define netErrSocketBusy (netErrorClass | 9) //EINPROGRESS
+#define netErrMessageTooBig (netErrorClass | 10)
+#define netErrSocketNotConnected (netErrorClass | 11)
+#define netErrNoInterfaces (netErrorClass | 12) //ENETUNREACH
+#define netErrBufTooSmall (netErrorClass | 13)
+#define netErrUnimplemented (netErrorClass | 14)
+#define netErrPortInUse (netErrorClass | 15) //EADDRINUSE
+#define netErrQuietTimeNotElapsed (netErrorClass | 16) //EADDRINUSE
+#define netErrInternal (netErrorClass | 17)
+#define netErrTimeout (netErrorClass | 18) //ETIMEDOUT
+#define netErrSocketAlreadyConnected (netErrorClass | 19) //EISCONN
+#define netErrSocketClosedByRemote (netErrorClass | 20)
+#define netErrOutOfCmdBlocks (netErrorClass | 21)
+#define netErrWrongSocketType (netErrorClass | 22)
+#define netErrSocketNotListening (netErrorClass | 23)
+#define netErrUnknownSetting (netErrorClass | 24)
+#define netErrInvalidSettingSize (netErrorClass | 25)
+#define netErrPrefNotFound (netErrorClass | 26)
+#define netErrInvalidInterface (netErrorClass | 27)
+#define netErrInterfaceNotFound (netErrorClass | 28)
+#define netErrTooManyInterfaces (netErrorClass | 29)
+#define netErrBufWrongSize (netErrorClass | 30)
+#define netErrUserCancel (netErrorClass | 31)
+#define netErrBadScript (netErrorClass | 32)
+#define netErrNoSocket (netErrorClass | 33)
+#define netErrSocketRcvBufFull (netErrorClass | 34)
+#define netErrNoPendingConnect (netErrorClass | 35)
+#define netErrUnexpectedCmd (netErrorClass | 36)
+#define netErrNoTCB (netErrorClass | 37)
+#define netErrNilRemoteWindowSize (netErrorClass | 38)
+#define netErrNoTimerProc (netErrorClass | 39)
+#define netErrSocketInputShutdown (netErrorClass | 40) // EOF to sockets API
+#define netErrCmdBlockNotCheckedOut (netErrorClass | 41)
+#define netErrCmdNotDone (netErrorClass | 42)
+#define netErrUnknownProtocol (netErrorClass | 43)
+#define netErrUnknownService (netErrorClass | 44)
+#define netErrUnreachableDest (netErrorClass | 45)
+#define netErrReadOnlySetting (netErrorClass | 46)
+#define netErrWouldBlock (netErrorClass | 47) //EWOULDBLOCK
+#define netErrAlreadyInProgress (netErrorClass | 48) //EALREADY
+#define netErrPPPTimeout (netErrorClass | 49)
+#define netErrPPPBroughtDown (netErrorClass | 50)
+#define netErrAuthFailure (netErrorClass | 51)
+#define netErrPPPAddressRefused (netErrorClass | 52)
+// The following map into the Epilogue DNS errors declared in DNS.ep.h:
+// and MUST be kept in this order!!
+#define netErrDNSNameTooLong (netErrorClass | 53)
+#define netErrDNSBadName (netErrorClass | 54)
+#define netErrDNSBadArgs (netErrorClass | 55)
+#define netErrDNSLabelTooLong (netErrorClass | 56)
+#define netErrDNSAllocationFailure (netErrorClass | 57)
+#define netErrDNSTimeout (netErrorClass | 58)
+#define netErrDNSUnreachable (netErrorClass | 59)
+#define netErrDNSFormat (netErrorClass | 60)
+#define netErrDNSServerFailure (netErrorClass | 61)
+#define netErrDNSNonexistantName (netErrorClass | 62)
+#define netErrDNSNIY (netErrorClass | 63)
+#define netErrDNSRefused (netErrorClass | 64)
+#define netErrDNSImpossible (netErrorClass | 65)
+#define netErrDNSNoRRS (netErrorClass | 66)
+#define netErrDNSAborted (netErrorClass | 67)
+#define netErrDNSBadProtocol (netErrorClass | 68)
+#define netErrDNSTruncated (netErrorClass | 69)
+#define netErrDNSNoRecursion (netErrorClass | 70)
+#define netErrDNSIrrelevant (netErrorClass | 71)
+#define netErrDNSNotInLocalCache (netErrorClass | 72)
+#define netErrDNSNoPort (netErrorClass | 73)
+// The following map into the Epilogue IP errors declared in IP.ep.h:
+// and MUST be kept in this order!!
+#define netErrIPCantFragment (netErrorClass | 74)
+#define netErrIPNoRoute (netErrorClass | 75)
+#define netErrIPNoSrc (netErrorClass | 76)
+#define netErrIPNoDst (netErrorClass | 77)
+#define netErrIPktOverflow (netErrorClass | 78)
+// End of Epilogue IP errors
+#define netErrTooManyTCPConnections (netErrorClass | 79)
+#define netErrNoDNSServers (netErrorClass | 80)
+#define netErrInterfaceDown (netErrorClass | 81)
+
+// Mobitex network radio interface error code returns
+#define netErrNoChannel (netErrorClass | 82) // The datalink layer cannot acquire a channel
+#define netErrDieState (netErrorClass | 83) // Mobitex network has issued a DIE command.
+#define netErrReturnedInMail (netErrorClass | 84) // The addressed of the transmitted packet was not available, and the message was placed in the network's mailbox.
+#define netErrReturnedNoTransfer (netErrorClass | 85) // This message cannot be transferred or put in the network mailbox.
+#define netErrReturnedIllegal (netErrorClass | 86) // The message could not be switched to the network
+#define netErrReturnedCongest (netErrorClass | 87) // Line, radio channels, or network nodes are congested.
+#define netErrReturnedError (netErrorClass | 88) // Technical error in the network.
+#define netErrReturnedBusy (netErrorClass | 89) // The B-party is busy.
+#define netErrGMANState (netErrorClass | 90) // The modem has not registered with the network.
+#define netErrQuitOnTxFail (netErrorClass | 91) // Couldn't get packet through, shutdown.
+#define netErrFlexListFull (netErrorClass | 92) // raw IF error message: see Mobitex spec.
+#define netErrSenderMAN (netErrorClass | 93) // ditto
+#define netErrIllegalType (netErrorClass | 94) // ditto
+#define netErrIllegalState (netErrorClass | 95) // ditto
+#define netErrIllegalFlags (netErrorClass | 96) // ditto
+#define netErrIllegalSendlist (netErrorClass | 97) // ditto
+#define netErrIllegalMPAKLength (netErrorClass | 98) // ditto
+#define netErrIllegalAddressee (netErrorClass | 99) // ditto
+#define netErrIllegalPacketClass (netErrorClass | 100) // ditto
+#define netErrBufferLength (netErrorClass | 101) // any
+#define netErrNiCdLowBattery (netErrorClass | 102) // any
+#define netErrRFinterfaceFatal (netErrorClass | 103) // any
+#define netErrIllegalLogout (netErrorClass | 104) // raw IF error message
+#define netErrAAARadioLoad (netErrorClass | 105) // 7/20/98 JB. If there is insufficient AAA
+#define netErrAntennaDown (netErrorClass | 106)
+#define netErrNiCdCharging (netErrorClass | 107) // just for charging
+#define netErrAntennaWentDown (netErrorClass | 108)
+#define netErrNotActivated (netErrorClass | 109) // The unit has not been FULLY activated. George and Morty completed.
+#define netErrRadioTemp (netErrorClass | 110) // Radio's temp is too high for FCC compliant TX
+#define netErrNiCdChargeError (netErrorClass | 111) // Charging stopped due to NiCd charging characteristic
+#define netErrNiCdSag (netErrorClass | 112) // the computed sag or actual sag indicates a NiCd with diminished capacity.
+#define netErrNiCdChargeSuspend (netErrorClass | 113) // Charging has been suspended due to low AAA batteries.
+// Left room for more Mobitex errors
+
+// Configuration errors
+#define netErrConfigNotFound (netErrorClass | 115)
+#define netErrConfigCantDelete (netErrorClass | 116)
+#define netErrConfigTooMany (netErrorClass | 117)
+#define netErrConfigBadName (netErrorClass | 118)
+#define netErrConfigNotAlias (netErrorClass | 119)
+#define netErrConfigCantPointToAlias (netErrorClass | 120)
+#define netErrConfigEmpty (netErrorClass | 121)
+#define netErrAlreadyOpenWithOtherConfig (netErrorClass | 122)
+#define netErrConfigAliasErr (netErrorClass | 123)
+#define netErrNoMultiPktAddr (netErrorClass | 124)
+#define netErrOutOfPackets (netErrorClass | 125)
+#define netErrMultiPktAddrReset (netErrorClass | 126)
+#define netErrStaleMultiPktAddr (netErrorClass | 127)
+
+// Login scripting plugin errors
+#define netErrScptPluginMissing (netErrorClass | 128)
+#define netErrScptPluginLaunchFail (netErrorClass | 129)
+#define netErrScptPluginCmdFail (netErrorClass | 130)
+#define netErrScptPluginInvalidCmd (netErrorClass | 131)
+
+#define netErrMobitexStart netErrNoChannel
+#define netErrMobitexEnd netErrNiCdChargeSuspend
+
+//-----------------------------------------------------------------------------
+// Net library call ID's. Each library call gets the trap number:
+// netTrapXXXX which serves as an index into the library's dispatch table.
+// The constant sysLibTrapCustom is the first available trap number after
+// the system predefined library traps Open,Close,Sleep & Wake.
+//
+// WARNING!!! This order of these traps MUST match the order of the dispatch
+// table in NetDispatch.c!!!
+//-----------------------------------------------------------------------------
+#pragma mark Traps
+typedef enum {
+ netLibTrapAddrINToA = sysLibTrapCustom,
+ netLibTrapAddrAToIN,
+
+ netLibTrapSocketOpen,
+ netLibTrapSocketClose,
+ netLibTrapSocketOptionSet,
+ netLibTrapSocketOptionGet,
+ netLibTrapSocketBind,
+ netLibTrapSocketConnect,
+ netLibTrapSocketListen,
+ netLibTrapSocketAccept,
+ netLibTrapSocketShutdown,
+
+ netLibTrapSendPB,
+ netLibTrapSend,
+ netLibTrapReceivePB,
+ netLibTrapReceive,
+ netLibTrapDmReceive,
+ netLibTrapSelect,
+
+ netLibTrapPrefsGet,
+ netLibTrapPrefsSet,
+
+ // The following traps are for internal and Network interface
+ // use only.
+ netLibTrapDrvrWake,
+ netLibTrapInterfacePtr,
+ netLibTrapMaster,
+
+ // New Traps
+ netLibTrapGetHostByName,
+ netLibTrapSettingGet,
+ netLibTrapSettingSet,
+ netLibTrapIFAttach,
+ netLibTrapIFDetach,
+ netLibTrapIFGet,
+ netLibTrapIFSettingGet,
+ netLibTrapIFSettingSet,
+ netLibTrapIFUp,
+ netLibTrapIFDown,
+ netLibTrapIFMediaUp,
+ netLibTrapScriptExecuteV32,
+ netLibTrapGetHostByAddr,
+ netLibTrapGetServByName,
+ netLibTrapSocketAddr,
+ netLibTrapFinishCloseWait,
+ netLibTrapGetMailExchangeByName,
+ netLibTrapPrefsAppend,
+ netLibTrapIFMediaDown,
+ netLibTrapOpenCount,
+
+ netLibTrapTracePrintF,
+ netLibTrapTracePutS,
+
+ netLibTrapOpenIfCloseWait,
+ netLibTrapHandlePowerOff,
+
+ netLibTrapConnectionRefresh,
+
+ // Traps added after 1.0 release of NetLib
+ netLibTrapBitMove,
+ netLibTrapBitPutFixed,
+ netLibTrapBitGetFixed,
+ netLibTrapBitPutUIntV,
+ netLibTrapBitGetUIntV,
+ netLibTrapBitPutIntV,
+ netLibTrapBitGetIntV,
+
+ // Traps added after 2.0 release of NetLib
+ netLibOpenConfig,
+ netLibConfigMakeActive,
+ netLibConfigList,
+ netLibConfigIndexFromName,
+ netLibConfigDelete,
+ netLibConfigSaveAs,
+ netLibConfigRename,
+ netLibConfigAliasSet,
+ netLibConfigAliasGet,
+
+ // Traps added after 3.2 release of NetLib
+ netLibTrapScriptExecute,
+
+ netLibTrapLast
+ } NetLibTrapNumberEnum;
+
+
+
+/************************************************************
+ * Net Library procedures.
+ *************************************************************/
+#pragma mark Functions
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------
+// Library initialization, shutdown, sleep and wake
+//--------------------------------------------------
+Err NetLibOpen (UInt16 libRefnum, UInt16 *netIFErrsP)
+ SYS_TRAP(sysLibTrapOpen);
+
+Err NetLibClose (UInt16 libRefnum, UInt16 immediate)
+ SYS_TRAP(sysLibTrapClose);
+
+Err NetLibSleep (UInt16 libRefnum)
+ SYS_TRAP(sysLibTrapSleep);
+
+Err NetLibWake (UInt16 libRefnum)
+ SYS_TRAP(sysLibTrapWake);
+
+
+// This call forces the library to complete a close if it's
+// currently in the close-wait state. Returns 0 if library is closed,
+// Returns netErrFullyOpen if library is still open by some other task.
+Err NetLibFinishCloseWait(UInt16 libRefnum)
+ SYS_TRAP(netLibTrapFinishCloseWait);
+
+// This call is for use by the Network preference panel only. It
+// causes the NetLib to fully open if it's currently in the close-wait
+// state. If it's not in the close wait state, it returns an error code
+Err NetLibOpenIfCloseWait(UInt16 libRefnum)
+ SYS_TRAP(netLibTrapOpenIfCloseWait);
+
+// Get the open Count of the NetLib
+Err NetLibOpenCount (UInt16 refNum, UInt16 *countP)
+ SYS_TRAP(netLibTrapOpenCount);
+
+// Give NetLib a chance to close the connection down in response
+// to a power off event. Returns non-zero if power should not be
+// turned off. EventP points to the event that initiated the power off
+// which is either a keyDownEvent of the hardPowerChr or the autoOffChr.
+// Don't include unless building for Viewer
+#ifdef __SYSEVENT_H__
+Err NetLibHandlePowerOff (UInt16 refNum, SysEventType *eventP)
+ SYS_TRAP(netLibTrapHandlePowerOff);
+#endif
+
+
+// Check status or try and reconnect any interfaces which have come down.
+// This call can be made by applications when they suspect that an interface
+// has come down (like PPP or SLIP). NOTE: This call can display UI
+// (if 'refresh' is true) so it MUST be called from the UI task.
+Err NetLibConnectionRefresh(UInt16 refNum, Boolean refresh,
+ UInt8 *allInterfacesUpP, UInt16 *netIFErrP)
+ SYS_TRAP(netLibTrapConnectionRefresh);
+
+
+
+//--------------------------------------------------
+// Net address translation and conversion routines.
+//--------------------------------------------------
+
+// convert host Int16 to network Int16
+#define NetHToNS(x) (x)
+
+// convert host long to network long
+#define NetHToNL(x) (x)
+
+// convert network Int16 to host Int16
+#define NetNToHS(x) (x)
+
+// convert network long to host long
+#define NetNToHL(x) (x)
+
+// Convert 32-bit IP address to ascii dotted decimal form. The Sockets glue
+// macro inet_ntoa will pass the address of an application global string in
+// spaceP.
+Char * NetLibAddrINToA(UInt16 libRefnum, NetIPAddr inet, Char *spaceP)
+ SYS_TRAP(netLibTrapAddrINToA);
+
+// Convert a dotted decimal ascii string format of an IP address into
+// a 32-bit value.
+NetIPAddr NetLibAddrAToIN(UInt16 libRefnum, Char *a)
+ SYS_TRAP(netLibTrapAddrAToIN);
+
+
+
+//--------------------------------------------------
+// Socket creation and option setting
+//--------------------------------------------------
+
+// Create a socket and return a refnum to it. Protocol is normally 0.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+NetSocketRef NetLibSocketOpen(UInt16 libRefnum, NetSocketAddrEnum domain,
+ NetSocketTypeEnum type, Int16 protocol, Int32 timeout,
+ Err *errP)
+ SYS_TRAP(netLibTrapSocketOpen);
+
+// Close a socket.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketClose(UInt16 libRefnum, NetSocketRef socket, Int32 timeout,
+ Err *errP)
+ SYS_TRAP(netLibTrapSocketClose);
+
+// Set a socket option. Level is usually netSocketOptLevelSocket. Option is one of
+// netSocketOptXXXXX. OptValueP is a pointer to the new value and optValueLen is
+// the length of the option value.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketOptionSet(UInt16 libRefnum, NetSocketRef socket,
+ UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ void *optValueP, UInt16 optValueLen,
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSocketOptionSet);
+
+// Get a socket option.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketOptionGet(UInt16 libRefnum, NetSocketRef socket,
+ UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ void *optValueP, UInt16 *optValueLenP,
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSocketOptionGet);
+
+
+//--------------------------------------------------
+// Socket Control
+//--------------------------------------------------
+
+// Bind a source address and port number to a socket. This makes the
+// socket accept incoming packets destined for the given socket address.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketBind(UInt16 libRefnum, NetSocketRef socket,
+ NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ Err *errP)
+ SYS_TRAP(netLibTrapSocketBind);
+
+
+// Connect to a remote socket. For a stream based socket (i.e. TCP), this initiates
+// a 3-way handshake with the remote machine to establish a connection. For
+// non-stream based socket, this merely specifies a destination address and port
+// number for future outgoing packets from this socket.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketConnect(UInt16 libRefnum, NetSocketRef socket,
+ NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ Err *errP)
+ SYS_TRAP(netLibTrapSocketConnect);
+
+
+// Makes a socket ready to accept incoming connection requests. The queueLen
+// specifies the max number of pending connection requests that will be enqueued
+// while the server is busy handling other requests.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketListen(UInt16 libRefnum, NetSocketRef socket,
+ UInt16 queueLen, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSocketListen);
+
+
+// Blocks the current process waiting for an incoming connection request. The socket
+// must have previously be put into listen mode through the NetLibSocketListen call.
+// On return, *sockAddrP will have the remote machines address and port number.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketAccept(UInt16 libRefnum, NetSocketRef socket,
+ NetSocketAddrType *sockAddrP, Int16 *addrLenP, Int32 timeout,
+ Err *errP)
+ SYS_TRAP(netLibTrapSocketAccept);
+
+
+// Shutdown a connection in one or both directions.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketShutdown(UInt16 libRefnum, NetSocketRef socket,
+ Int16 /*NetSocketDirEnum*/ direction, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSocketShutdown);
+
+
+
+// Gets the local and remote addresses of a socket. Useful for TCP sockets that
+// get dynamically bound at connect time.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+Int16 NetLibSocketAddr(UInt16 libRefnum, NetSocketRef socketRef,
+ NetSocketAddrType *locAddrP, Int16 *locAddrLenP,
+ NetSocketAddrType *remAddrP, Int16 *remAddrLenP,
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSocketAddr);
+
+
+
+//--------------------------------------------------
+// Sending and Receiving
+//--------------------------------------------------
+// Send data through a socket. The data is specified through the NetIOParamType
+// structure.
+// Flags is one or more of netMsgFlagXXX.
+// Returns # of bytes sent on success, or -1 on error. If error, *errP gets filled
+// in with error code.
+Int16 NetLibSendPB(UInt16 libRefNum, NetSocketRef socket,
+ NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSendPB);
+
+// Send data through a socket. The data to send is passed in a single buffer,
+// unlike NetLibSendPB. If toAddrP is not nil, the data will be sent to
+// address *toAddrP.
+// Flags is one or more of netMsgFlagXXX.
+// Returns # of bytes sent on success, or -1 on error. If error, *errP gets filled
+// in with error code.
+Int16 NetLibSend(UInt16 libRefNum, NetSocketRef socket,
+ void *bufP, UInt16 bufLen, UInt16 flags,
+ void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSend);
+
+// Receive data from a socket. The data is gatthered into buffers specified in the
+// NetIOParamType structure.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+Int16 NetLibReceivePB(UInt16 libRefNum, NetSocketRef socket,
+ NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapReceivePB);
+
+// Receive data from a socket. The data is read into a single buffer, unlike
+// NetLibReceivePB. If fromAddrP is not nil, *fromLenP must be initialized to
+// the size of the buffer that fromAddrP points to and on exit *fromAddrP will
+// have the address of the sender in it.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+Int16 NetLibReceive(UInt16 libRefNum, NetSocketRef socket,
+ void *bufP, UInt16 bufLen, UInt16 flags,
+ void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapReceive);
+
+
+// Receive data from a socket directly into a (write-protected) Data Manager
+// record.
+// If fromAddrP is not nil, *fromLenP must be initialized to
+// the size of the buffer that fromAddrP points to and on exit *fromAddrP will
+// have the address of the sender in it.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+Int16 NetLibDmReceive(UInt16 libRefNum, NetSocketRef socket,
+ void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags,
+ void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapDmReceive);
+
+
+//--------------------------------------------------
+// Name Lookups
+//--------------------------------------------------
+NetHostInfoPtr NetLibGetHostByName(UInt16 libRefNum, Char *nameP,
+ NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapGetHostByName);
+
+
+NetHostInfoPtr NetLibGetHostByAddr(UInt16 libRefNum, UInt8 *addrP, UInt16 len, UInt16 type,
+ NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapGetHostByAddr);
+
+
+NetServInfoPtr NetLibGetServByName(UInt16 libRefNum, const Char *servNameP,
+ const Char *protoNameP, NetServInfoBufPtr bufP,
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapGetServByName);
+
+// Looks up a mail exchange name and returns a list of hostnames for it. Caller
+// must pass space for list of return names (hostNames), space for
+// list of priorities for those hosts (priorities) and max # of names to
+// return (maxEntries).
+// Returns # of entries found, or -1 on error. If error, *errP gets filled in
+// with error code.
+Int16 NetLibGetMailExchangeByName(UInt16 libRefNum, Char *mailNameP,
+ UInt16 maxEntries,
+ Char hostNames[][netDNSMaxDomainName+1], UInt16 priorities[],
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapGetMailExchangeByName);
+
+
+//--------------------------------------------------
+// Interface setup
+//--------------------------------------------------
+Err NetLibIFGet(UInt16 libRefNum, UInt16 index, UInt32 *ifCreatorP,
+ UInt16 *ifInstanceP)
+ SYS_TRAP(netLibTrapIFGet);
+
+Err NetLibIFAttach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ Int32 timeout)
+ SYS_TRAP(netLibTrapIFAttach);
+
+Err NetLibIFDetach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ Int32 timeout)
+ SYS_TRAP(netLibTrapIFDetach);
+
+Err NetLibIFUp(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance)
+ SYS_TRAP(netLibTrapIFUp);
+
+Err NetLibIFDown(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ Int32 timeout)
+ SYS_TRAP(netLibTrapIFDown);
+
+
+
+
+//--------------------------------------------------
+// Settings
+//--------------------------------------------------
+// General settings
+Err NetLibSettingGet(UInt16 libRefNum,
+ UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+ SYS_TRAP(netLibTrapSettingGet);
+
+Err NetLibSettingSet(UInt16 libRefNum,
+ UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+ SYS_TRAP(netLibTrapSettingSet);
+
+// Network interface specific settings.
+Err NetLibIFSettingGet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+ SYS_TRAP(netLibTrapIFSettingGet);
+
+Err NetLibIFSettingSet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+ SYS_TRAP(netLibTrapIFSettingSet);
+
+
+
+//--------------------------------------------------
+// System level
+//--------------------------------------------------
+Int16 NetLibSelect(UInt16 libRefNum, UInt16 width, NetFDSetType *readFDs,
+ NetFDSetType *writeFDs, NetFDSetType *exceptFDs,
+ Int32 timeout, Err *errP)
+ SYS_TRAP(netLibTrapSelect);
+
+
+
+//--------------------------------------------------
+// Debugging support
+//--------------------------------------------------
+Err NetLibMaster(UInt16 libRefNum, UInt16 cmd, NetMasterPBPtr pbP,
+ Int32 timeout)
+ SYS_TRAP(netLibTrapMaster);
+
+Err NetLibTracePrintF(UInt16 libRefNum, Char *formatStr, ...)
+ SYS_TRAP(netLibTrapTracePrintF);
+
+Err NetLibTracePutS(UInt16 libRefNum, Char *strP)
+ SYS_TRAP(netLibTrapTracePutS);
+
+
+
+
+
+//--------------------------------------------------
+// Configuration Calls
+//--------------------------------------------------
+Err NetLibOpenConfig( UInt16 refNum, UInt16 configIndex, UInt32 openFlags,
+ UInt16 *netIFErrP)
+ SYS_TRAP(netLibOpenConfig);
+
+Err NetLibConfigMakeActive( UInt16 refNum, UInt16 configIndex)
+ SYS_TRAP(netLibConfigMakeActive);
+
+Err NetLibConfigList( UInt16 refNum, NetConfigNameType nameArray[],
+ UInt16 *arrayEntriesP)
+ SYS_TRAP(netLibConfigList);
+
+Err NetLibConfigIndexFromName( UInt16 refNum, NetConfigNamePtr nameP,
+ UInt16 *indexP)
+ SYS_TRAP(netLibConfigIndexFromName);
+
+Err NetLibConfigDelete( UInt16 refNum, UInt16 index)
+ SYS_TRAP(netLibConfigDelete);
+
+Err NetLibConfigSaveAs( UInt16 refNum, NetConfigNamePtr nameP)
+ SYS_TRAP(netLibConfigSaveAs);
+
+Err NetLibConfigRename( UInt16 refNum, UInt16 index,
+ NetConfigNamePtr newNameP)
+ SYS_TRAP(netLibConfigRename);
+
+Err NetLibConfigAliasSet( UInt16 refNum, UInt16 configIndex,
+ UInt16 aliasToIndex)
+ SYS_TRAP(netLibConfigAliasSet);
+
+Err NetLibConfigAliasGet( UInt16 refNum, UInt16 aliasIndex,
+ UInt16 *indexP, Boolean *isAnotherAliasP)
+ SYS_TRAP(netLibConfigAliasGet);
+
+
+#ifndef PUBLIC_STUFF_STRIPPED
+//--------------------------------------------------
+// Routines that must be linked in from the :Libraries:PalmOS:Src:NetSocket.c
+// source module.
+//
+// These are general convenience routines for applications that use the
+// NetLib. They are not part of the NetLib itself because they generally
+// need to keep track of state within the application and require the use
+// of application globals that are declared in NetSocket.c
+//--------------------------------------------------
+#ifdef __SYSEVENT_H__
+Boolean NetUWirelessAppHandleEvent(SysEventType *eventP, UInt32 flags, Err *errP);
+#endif
+#endif // PUBLIC_STUFF_STRIPPED
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+// Include the NetMgr Bit Utils
+#include <NetBitUtils.h>
+
+#endif // __NETMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/OverlayMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/OverlayMgr.h
new file mode 100644
index 0000000..7d4f4b9
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/OverlayMgr.h
@@ -0,0 +1,214 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: OverlayMgr.h
+ *
+ * Description:
+ * Public header for routines that support overlays & locales.
+ *
+ * History:
+ * Created by Ken Krugler
+ * 06/24/99 kwk Created by Ken Krugler.
+ * 07/06/99 CS Added omSpecAttrForBase
+ * (and renumbered omSpecAttrStripped).
+ * 07/29/99 CS Added omOverlayKindBase for the entries in the base
+ * DBs 'ovly' resource (they had been set to
+ * omOverlayKindReplace before).
+ * 07/29/99 CS Bumped version to 3, since now we're supposed to
+ * support omOverlayKindAdd.
+ * 09/29/99 kwk Bumped version to 4, since we added the baseChecksum
+ * field to OmOverlaySpecType, as a way of speeding up
+ * overlay validation.
+ * 09/29/99 CS Actually bumped version to 4, which Ken forgot.
+ * 10/08/99 kwk Added OmGetRoutineAddress selector/declaration.
+ * Moved OmDispatch, OmInit, and OmOpenOverlayDatabase
+ * into OverlayPrv.h
+ *
+ *****************************************************************************/
+
+#ifndef __OVERLAYMGR_H__
+#define __OVERLAYMGR_H__
+
+// Include elementary types
+#include <PalmTypes.h>
+#include <DataMgr.h>
+
+#ifdef _WIN32
+ #pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union
+#endif
+
+/***********************************************************************
+ * Overlay Manager constants
+ **********************************************************************/
+
+#define omOverlayVersion 0x0004 // Version of OmOverlaySpecType/OmOverlayRscType
+#define omOverlayDBType 'ovly' // Overlay database type
+#define omOverlayRscType 'ovly' // Overlay desc resource type
+#define omOverlayRscID 1000 // Overlay desc resource ID
+
+#define omFtrCreator 'ovly' // For get/set of Overlay features.
+#define omFtrShowErrorsFlag 0 // Boolean - True => display overlay errors.
+
+// Flags for OmOverlaySpecType.flags field
+#define omSpecAttrForBase 1 // 'ovly' (in base) describes base itself
+#define omSpecAttrStripped 2 // Localized resources stripped (base only)
+
+// OmFindOverlayDatabase called with stripped base, and no appropriate overlay was found.
+#define omErrBaseRequiresOverlay (omErrorClass | 1)
+
+// OmOverlayDBNameToLocale or OmLocaleToOverlayDBName were passed an unknown locale.
+#define omErrUnknownLocale (omErrorClass | 2)
+
+// OmOverlayDBNameToLocale was passed a poorly formed string.
+#define omErrBadOverlayDBName (omErrorClass | 3)
+
+// OmGetIndexedLocale was passed an invalid index.
+#define omErrInvalidLocaleIndex (omErrorClass | 4)
+
+// OmSetSystemLocale was passed an invalid locale (doesn't correspond to available
+// system overlay).
+
+#define omErrInvalidLocale (omErrorClass | 5)
+
+// OmSetSystemLocale was passed a locale that referenced an invalid system overlay
+// (missing one or more required resources)
+
+#define omErrInvalidSystemOverlay (omErrorClass | 6)
+
+// Values for OmOverlayKind
+#define omOverlayKindHide 0 // Hide base resource (not supported in version <= 3)
+#define omOverlayKindAdd 1 // Add new resource (not support in version <= 2)
+#define omOverlayKindReplace 2 // Replace base resource
+#define omOverlayKindBase 3 // Description of base resource itself (not supported in version <= 2)
+
+/***********************************************************************
+ * Selectors & macros used for calling Overlay Manager routines
+ **********************************************************************/
+
+#ifdef DIRECT_OVERLAY_CALLS
+ #define OMDISPATCH_TRAP(omSelectorNum)
+#else
+ #define OMDISPATCH_TRAP(sel) \
+ _SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, sysTrapOmDispatch, sel)
+#endif
+
+// Selectors used for getting to the right Overlay Manager routine via
+// the OmDispatch trap.
+typedef enum {
+ omInit = 0,
+ omOpenOverlayDatabase,
+ omLocaleToOverlayDBName,
+ omOverlayDBNameToLocale,
+ omGetCurrentLocale,
+ omGetIndexedLocale,
+ omGetSystemLocale,
+ omSetSystemLocale,
+ omGetRoutineAddress,
+
+ omMaxSelector = omGetRoutineAddress,
+ omBigSelector = 0x7FFF // Force OmSelector to be 16 bits.
+} OmSelector;
+
+/***********************************************************************
+ * Overlay Manager types
+ **********************************************************************/
+
+typedef UInt16 OmOverlayKind;
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER kwk - figure out exact format for portable struct declaration.
+// We might also want to hide this information in a private header, and
+// just have OmLocaleType in here.
+#endif // PUBLIC_STUFF_STRIPPED
+
+typedef struct {
+ OmOverlayKind overlayType; // Replace, delete, etc.
+ UInt32 rscType; // Resource type to overlay
+ UInt16 rscID; // Resource ID to overlay
+ UInt32 rscLength; // Length of base resource
+ UInt32 rscChecksum; // Checksum of base resource data
+} OmOverlayRscType;
+
+typedef struct {
+ UInt16 language; // Language spoken in locale
+ UInt16 country; // Specifies "dialect" of language
+} OmLocaleType;
+
+// Definition of the Overlay Description Resource ('ovly')
+typedef struct {
+ UInt16 version; // Version of this structure
+ UInt32 flags; // Flags
+ UInt32 baseChecksum; // Checksum of all overlays[].checksum
+ OmLocaleType targetLocale; // Language, & country of overlay resources
+ UInt32 baseDBType; // Type of base DB to overlay
+ UInt32 baseDBCreator; // Creator of base DB to overlay
+ UInt32 baseDBCreateDate; // Date base DB was created
+ UInt32 baseDBModDate; // Date base DB was last modified
+ UInt16 numOverlays; // Number of resources to overlay
+ OmOverlayRscType overlays[0]; // Descriptions of resources to overlay
+} OmOverlaySpecType;
+
+
+/***********************************************************************
+ * Overlay Manager routines
+ **********************************************************************/
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Return in <overlayDBName> an overlay database name that's appropriate
+// for the base name <baseDBName> and the locale <targetLocale>. If the
+// <targetLocale> param in NULL, use the current locale. The <overlayDBName>
+// buffer must be at least dmDBNameLength bytes.
+
+Err OmLocaleToOverlayDBName(const Char *baseDBName, const OmLocaleType *targetLocale,
+ Char *overlayDBName)
+ OMDISPATCH_TRAP(omLocaleToOverlayDBName);
+
+// Given the name of an overlay database in <overlayDBName>, return back
+// the overlay in overlayLocale. If the name isn't an overlay name,
+// return omErrBadOverlayDBName.
+
+Err OmOverlayDBNameToLocale(const Char *overlayDBName, OmLocaleType *overlayLocale)
+ OMDISPATCH_TRAP(omOverlayDBNameToLocale);
+
+// Return the current locale in <currentLocale>. This may not be the same as
+// the system locale, which will take effect after the next reset.
+
+void OmGetCurrentLocale(OmLocaleType *currentLocale)
+ OMDISPATCH_TRAP(omGetCurrentLocale);
+
+// Return the nth available locale in <theLocale>. Indexes are zero-based, and the
+// omErrInvalidLocaleIndex result will be returned if <localeIndex> is out of bounds.
+
+Err OmGetIndexedLocale(UInt16 localeIndex, OmLocaleType *theLocale)
+ OMDISPATCH_TRAP(omGetIndexedLocale);
+
+// Return the system locale in <systemLocale>. This may not be the same as
+// the current locale.
+
+void OmGetSystemLocale(OmLocaleType *systemLocale)
+ OMDISPATCH_TRAP(omGetSystemLocale);
+
+// Set the post-reset system locale to be <systemLocale>. Return omErrInvalidLocale if
+// the passed locale doesnÕt correspond to a valid System.prc overlay.
+
+Err OmSetSystemLocale(const OmLocaleType *systemLocale)
+ OMDISPATCH_TRAP(omSetSystemLocale);
+
+// Return back the address of the routine indicated by <inSelector>. If
+// <inSelector> isn't a valid routine selector, return back NULL.
+
+void *OmGetRoutineAddress(OmSelector inSelector)
+ OMDISPATCH_TRAP(omGetRoutineAddress);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
+
+#endif
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/PalmLocale.h b/SrcShared/Palm/Platform/Incs/Core/System/PalmLocale.h
new file mode 100644
index 0000000..895d5b4
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/PalmLocale.h
@@ -0,0 +1,1258 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: PalmLocale.h
+ *
+ * Release:
+ *
+ * Description:
+ * Public header for simple constants that support locales (information
+ * specific to locales and regions). This file is designed to support
+ * Rez in addition to C/C++.
+ *
+ * History:
+ * 05/31/00 CS Created by Chris Schneider (from LocaleMgr.h).
+ * 06/02/00 CS Moved character encoding constants in here (from TextMgr.h).
+ * 06/05/00 kwk Moved character encoding names in here (from TextMgr.h)
+ * Updated CP1252 charset name to "Windows-1252", as the new
+ * preferred standard. It was "ISO-8859-1-Windows-3.1-Latin-1".
+ * Added encodingNameUCS2. Fixed up some encoding constant names.
+ * 06/05/00 CS Hacked in changes for Rez, which doesn't support macro
+ * parameters in #defines.
+ * 06/06/00 CS Changed name form Locale.h to PalmLocale.h to avoid
+ * name collision with the Metrowerks Standard Library
+ * header Locale.h.
+ * CS Now use PALM_LOCALE_HAS_TYPES to control whether to
+ * use types (rather than just rez).
+ * 06/07/00 kwk Moved encoding name #defines out of conditional sections,
+ * since these don't depend on PALM_LOCALE_HAS_TYPES.
+ * kwk Fixed charEncodingMax - was 76, should be 75.
+ * 06/27/00 kwk Fixed charEncodingMax in the automatically generated section
+ * to also be 75.
+ * kwk Renumbered char encodings so that charEncodingUCS2 stays
+ * at 9 (where it was before I integrated with Michel), since
+ * the Sony version of TxtConvertEncoding relies on this.
+ * Basically swapped charEncodingUCS2 (was 25) with charEncodingEucJp
+ * (was 9).
+ * 07/21/00 kwk Added charEncodingUTF16, charEncodingUTF16BE, and charEncodingUTF16LE.
+ * The UTF16 encoding requires a BOM (byte order mark) in the text
+ * stream to identify big vs. little endian, while the other two
+ * are explicit. Note that for Palm OS, charEncodingUCS2 is the
+ * same as charEncodingUTF16BE without support for surrogates, but
+ * since we currently don't support characters > 16 bits, in reality
+ * charEncodingUTF16BE is more like charEncodingUCS2.
+ * kwk Updated charEncodingMax to be 77 (was 74).
+ * 08/01/00 kwk Changed cNewCalidonia to cNewCaledonia.
+ * 05/12/01 kwk Added charEncodingPalmGSM, and bumped the max encoding value to 78.
+ * kwk Added encodingNamePalmGSM, for when a MIME message is sent with
+ * any of the 10 special Greek characters.
+ * 07/01/01 kwk Changed charset name to be "palmGSM" to match Palm.net's current
+ * character set name.
+ * 07/15/01 kwk Added three additional Big5-based encodings (CP950, Big5Plus, PalmBig5).
+ * kwk Updated charEncodingMax to be 80 (was 77).
+ * kwk Added Big-5 related encoding names.
+ * 08/16/01 MT Added lLanguageNum and cCountryNum so Elaine has a compile warning
+ * when a new Lanaguage or Country (or Charset added with charEncodingMax)
+ * 10/25/01 kwk Merged w/GSM changes. charEncodingMax is now 81 (was 80).
+ * Shifted up the three new Big5-based encodings, since GSM
+ * has the encoding value of 78.
+ * 10/29/01 kwk Changed encodingNameBig5Plus to encodingNameBig5_HKSCS. Got rid
+ * of encodingNameCP950. Changed charEncodingCP950 to charEncodingBig5_HKSCS.
+ * 11/03/01 kwk Added GBK and PalmGB as character encoding values. Bumped max
+ * encoding to 83. Defined charset names for Simplified Chinese encodings.
+ *
+ *****************************************************************************/
+
+#ifndef __PALMLOCALE_H__
+#define __PALMLOCALE_H__
+
+
+// Names of the known encodings.
+#define encodingNameAscii "us-ascii"
+#define encodingNameISO8859_1 "ISO-8859-1"
+#define encodingNameCP1252 "Windows-1252"
+
+#define encodingNameShiftJIS "Shift_JIS"
+#define encodingNameCP932 "Windows-31J"
+
+#define encodingNameUTF8 "UTF-8"
+#define encodingNameUCS2 "ISO-10646-UCS-2"
+
+#define encodingNamePalmGSM "palmGSM"
+
+#define encodingNameBig5 "Big5"
+#define encodingNameBig5_HKSCS "Big5-HKSCS"
+
+// Note that as of 2001-11-03 there are no defined names for GBK/CP936 in the
+// IANA registry. It appears as though software uses GB2312 as the default name.
+#define encodingNameGB2312 "GB2312"
+#define encodingNameHZ "HZ-GB-2312"
+
+// Maximum length of any encoding name.
+#define maxEncodingNameLength 40
+
+/* Rez doesn't even support macros, so for Rez we must simplify all of the #defines.
+Thus, whenever you modify any constants, please do so in the !rez section,
+then execute the following MPW commands (from elsewhere with this file as the target)
+so that the Rez case will be automatically updated:
+
+Find ¥;Find /TAG SOURCE START/!1:/TAG SOURCE END/Á1
+Copy ¤
+Find ¥;Find /TAG DESTINATION START/!1:/TAG DESTINATION END/Á1
+Echo
+Paste ¤
+Find ¥;Find /TAG DESTINATION START/
+Replace -c ° /(#define[ ¶t]+l[a-z0-9_]+[ ¶t]+)¨1LANGUAGE_VALUE¶(([0-9]+)¨2¶)/ "¨1¨2"
+Replace -c ° /(#define[ ¶t]+c[a-z0-9_]+[ ¶t]+)¨1COUNTRY_VALUE¶(([0-9]+)¨2¶)/ "¨1¨2"
+Replace -c ° /(#define[ ¶t]+charEncoding[a-z0-9_]+[ ¶t]+)¨1CHAR_ENCODING_VALUE¶(([0-9]+)¨2¶)/ "¨1¨2"
+*/
+#if rez
+ #define PALM_LOCALE_HAS_TYPES 0
+#endif
+#ifndef PALM_LOCALE_HAS_TYPES
+ #define PALM_LOCALE_HAS_TYPES 1
+#endif
+
+
+#if PALM_LOCALE_HAS_TYPES // Normal (e.g., non-Rez) case
+
+/***********************************************************************
+ * Locale constants
+ **********************************************************************/
+
+/* Language codes (ISO 639). The first 8 preserve the old values for the deprecated
+LanguageType; the rest are sorted by the 2-character language code.
+
+WARNING! Keep in sync with BOTH:
+ 1) LanguageCode array in OverlayMgr.c
+ 2) localeLanguage #define in UIResDefs.r
+*/
+#define LANGUAGE_VALUE(value) ((LanguageType)value)
+
+// Leave the following line unchanged before 1st #define to be copied to rez section:
+// TAG SOURCE START
+
+#define lEnglish LANGUAGE_VALUE(0) // EN
+#define lFrench LANGUAGE_VALUE(1) // FR
+#define lGerman LANGUAGE_VALUE(2) // DE
+#define lItalian LANGUAGE_VALUE(3) // IT
+#define lSpanish LANGUAGE_VALUE(4) // ES
+#define lUnused LANGUAGE_VALUE(5) // Reserved
+
+// New in 3.1
+#define lJapanese LANGUAGE_VALUE(6) // JA (Palm calls this jp)
+#define lDutch LANGUAGE_VALUE(7) // NL
+
+// New in 4.0
+#define lAfar LANGUAGE_VALUE(8) // AA
+#define lAbkhazian LANGUAGE_VALUE(9) // AB
+#define lAfrikaans LANGUAGE_VALUE(10) // AF
+#define lAmharic LANGUAGE_VALUE(11) // AM
+#define lArabic LANGUAGE_VALUE(12) // AR
+#define lAssamese LANGUAGE_VALUE(13) // AS
+#define lAymara LANGUAGE_VALUE(14) // AY
+#define lAzerbaijani LANGUAGE_VALUE(15) // AZ
+#define lBashkir LANGUAGE_VALUE(16) // BA
+#define lByelorussian LANGUAGE_VALUE(17) // BE
+#define lBulgarian LANGUAGE_VALUE(18) // BG
+#define lBihari LANGUAGE_VALUE(19) // BH
+#define lBislama LANGUAGE_VALUE(20) // BI
+#define lBengali LANGUAGE_VALUE(21) // BN (Bangla)
+#define lTibetan LANGUAGE_VALUE(22) // BO
+#define lBreton LANGUAGE_VALUE(23) // BR
+#define lCatalan LANGUAGE_VALUE(24) // CA
+#define lCorsican LANGUAGE_VALUE(25) // CO
+#define lCzech LANGUAGE_VALUE(26) // CS
+#define lWelsh LANGUAGE_VALUE(27) // CY
+#define lDanish LANGUAGE_VALUE(28) // DA
+#define lBhutani LANGUAGE_VALUE(29) // DZ
+#define lGreek LANGUAGE_VALUE(30) // EL
+#define lEsperanto LANGUAGE_VALUE(31) // EO
+#define lEstonian LANGUAGE_VALUE(32) // ET
+#define lBasque LANGUAGE_VALUE(33) // EU
+#define lPersian LANGUAGE_VALUE(34) // FA (Farsi)
+#define lFinnish LANGUAGE_VALUE(35) // FI
+#define lFiji LANGUAGE_VALUE(36) // FJ
+#define lFaroese LANGUAGE_VALUE(37) // FO
+#define lFrisian LANGUAGE_VALUE(38) // FY
+#define lIrish LANGUAGE_VALUE(39) // GA
+#define lScotsGaelic LANGUAGE_VALUE(40) // GD
+#define lGalician LANGUAGE_VALUE(41) // GL
+#define lGuarani LANGUAGE_VALUE(42) // GN
+#define lGujarati LANGUAGE_VALUE(43) // GU
+#define lHausa LANGUAGE_VALUE(44) // HA
+#define lHindi LANGUAGE_VALUE(45) // HI
+#define lCroatian LANGUAGE_VALUE(46) // HR
+#define lHungarian LANGUAGE_VALUE(47) // HU
+#define lArmenian LANGUAGE_VALUE(48) // HY
+#define lInterlingua LANGUAGE_VALUE(49) // IA
+#define lInterlingue LANGUAGE_VALUE(50) // IE
+#define lInupiak LANGUAGE_VALUE(51) // IK
+#define lIndonesian LANGUAGE_VALUE(52) // IN
+#define lIcelandic LANGUAGE_VALUE(53) // IS
+#define lHebrew LANGUAGE_VALUE(54) // IW
+#define lYiddish LANGUAGE_VALUE(55) // JI
+#define lJavanese LANGUAGE_VALUE(56) // JW
+#define lGeorgian LANGUAGE_VALUE(57) // KA
+#define lKazakh LANGUAGE_VALUE(58) // KK
+#define lGreenlandic LANGUAGE_VALUE(59) // KL
+#define lCambodian LANGUAGE_VALUE(60) // KM
+#define lKannada LANGUAGE_VALUE(61) // KN
+#define lKorean LANGUAGE_VALUE(62) // KO
+#define lKashmiri LANGUAGE_VALUE(63) // KS
+#define lKurdish LANGUAGE_VALUE(64) // KU
+#define lKirghiz LANGUAGE_VALUE(65) // KY
+#define lLatin LANGUAGE_VALUE(66) // LA
+#define lLingala LANGUAGE_VALUE(67) // LN
+#define lLaothian LANGUAGE_VALUE(68) // LO
+#define lLithuanian LANGUAGE_VALUE(69) // LT
+#define lLatvian LANGUAGE_VALUE(70) // LV (Lettish)
+#define lMalagasy LANGUAGE_VALUE(71) // MG
+#define lMaori LANGUAGE_VALUE(72) // MI
+#define lMacedonian LANGUAGE_VALUE(73) // MK
+#define lMalayalam LANGUAGE_VALUE(74) // ML
+#define lMongolian LANGUAGE_VALUE(75) // MN
+#define lMoldavian LANGUAGE_VALUE(76) // MO
+#define lMarathi LANGUAGE_VALUE(77) // MR
+#define lMalay LANGUAGE_VALUE(78) // MS
+#define lMaltese LANGUAGE_VALUE(79) // MT
+#define lBurmese LANGUAGE_VALUE(80) // MY
+#define lNauru LANGUAGE_VALUE(81) // NA
+#define lNepali LANGUAGE_VALUE(82) // NE
+#define lNorwegian LANGUAGE_VALUE(83) // NO
+#define lOccitan LANGUAGE_VALUE(84) // OC
+#define lAfan LANGUAGE_VALUE(85) // OM (Oromo)
+#define lOriya LANGUAGE_VALUE(86) // OR
+#define lPunjabi LANGUAGE_VALUE(87) // PA
+#define lPolish LANGUAGE_VALUE(88) // PL
+#define lPashto LANGUAGE_VALUE(89) // PS (Pushto)
+#define lPortuguese LANGUAGE_VALUE(90) // PT
+#define lQuechua LANGUAGE_VALUE(91) // QU
+#define lRhaetoRomance LANGUAGE_VALUE(92) // RM
+#define lKurundi LANGUAGE_VALUE(93) // RN
+#define lRomanian LANGUAGE_VALUE(94) // RO
+#define lRussian LANGUAGE_VALUE(95) // RU
+#define lKinyarwanda LANGUAGE_VALUE(96) // RW
+#define lSanskrit LANGUAGE_VALUE(97) // SA
+#define lSindhi LANGUAGE_VALUE(98) // SD
+#define lSangho LANGUAGE_VALUE(99) // SG
+#define lSerboCroatian LANGUAGE_VALUE(100) // SH
+#define lSinghalese LANGUAGE_VALUE(101) // SI
+#define lSlovak LANGUAGE_VALUE(102) // SK
+#define lSlovenian LANGUAGE_VALUE(103) // SL
+#define lSamoan LANGUAGE_VALUE(104) // SM
+#define lShona LANGUAGE_VALUE(105) // SN
+#define lSomali LANGUAGE_VALUE(106) // SO
+#define lAlbanian LANGUAGE_VALUE(107) // SQ
+#define lSerbian LANGUAGE_VALUE(108) // SR
+#define lSiswati LANGUAGE_VALUE(109) // SS
+#define lSesotho LANGUAGE_VALUE(110) // ST
+#define lSudanese LANGUAGE_VALUE(111) // SU
+#define lSwedish LANGUAGE_VALUE(112) // SV
+#define lSwahili LANGUAGE_VALUE(113) // SW
+#define lTamil LANGUAGE_VALUE(114) // TA
+#define lTelugu LANGUAGE_VALUE(115) // TE
+#define lTajik LANGUAGE_VALUE(116) // TG
+#define lThai LANGUAGE_VALUE(117) // TH
+#define lTigrinya LANGUAGE_VALUE(118) // TI
+#define lTurkmen LANGUAGE_VALUE(119) // TK
+#define lTagalog LANGUAGE_VALUE(120) // TL
+#define lSetswana LANGUAGE_VALUE(121) // TN
+#define lTonga LANGUAGE_VALUE(122) // TO
+#define lTurkish LANGUAGE_VALUE(123) // TR
+#define lTsonga LANGUAGE_VALUE(124) // TS
+#define lTatar LANGUAGE_VALUE(125) // TT
+#define lTwi LANGUAGE_VALUE(126) // TW
+#define lUkrainian LANGUAGE_VALUE(127) // UK
+#define lUrdu LANGUAGE_VALUE(128) // UR
+#define lUzbek LANGUAGE_VALUE(129) // UZ
+#define lVietnamese LANGUAGE_VALUE(130) // VI
+#define lVolapuk LANGUAGE_VALUE(131) // VO
+#define lWolof LANGUAGE_VALUE(132) // WO
+#define lXhosa LANGUAGE_VALUE(133) // XH
+#define lYoruba LANGUAGE_VALUE(134) // YO
+#define lChinese LANGUAGE_VALUE(135) // ZH
+#define lZulu LANGUAGE_VALUE(136) // ZU
+//
+#define lLanguageNum LANGUAGE_VALUE(137) // Number of Languages
+
+/* Country codes (ISO 3166). The first 33 preserve the old values for the
+deprecated CountryType; the rest are sorted by the 2-character country code.
+
+WARNING! Keep in sync with BOTH:
+ 1) CountryCode array in OverlayMgr.c
+ 2) localeCountry #define in UIResDefs.r
+*/
+#define COUNTRY_VALUE(value) ((CountryType)value)
+
+#define cAustralia COUNTRY_VALUE(0) // AU
+#define cAustria COUNTRY_VALUE(1) // AT
+#define cBelgium COUNTRY_VALUE(2) // BE
+#define cBrazil COUNTRY_VALUE(3) // BR
+#define cCanada COUNTRY_VALUE(4) // CA
+#define cDenmark COUNTRY_VALUE(5) // DK
+#define cFinland COUNTRY_VALUE(6) // FI
+#define cFrance COUNTRY_VALUE(7) // FR
+#define cGermany COUNTRY_VALUE(8) // DE
+#define cHongKong COUNTRY_VALUE(9) // HK
+#define cIceland COUNTRY_VALUE(10) // IS
+#define cIreland COUNTRY_VALUE(11) // IE
+#define cItaly COUNTRY_VALUE(12) // IT
+#define cJapan COUNTRY_VALUE(13) // JP
+#define cLuxembourg COUNTRY_VALUE(14) // LU
+#define cMexico COUNTRY_VALUE(15) // MX
+#define cNetherlands COUNTRY_VALUE(16) // NL
+#define cNewZealand COUNTRY_VALUE(17) // NZ
+#define cNorway COUNTRY_VALUE(18) // NO
+#define cSpain COUNTRY_VALUE(19) // ES
+#define cSweden COUNTRY_VALUE(20) // SE
+#define cSwitzerland COUNTRY_VALUE(21) // CH
+#define cUnitedKingdom COUNTRY_VALUE(22) // GB (UK)
+#define cUnitedStates COUNTRY_VALUE(23) // US
+#define cIndia COUNTRY_VALUE(24) // IN
+#define cIndonesia COUNTRY_VALUE(25) // ID
+#define cRepublicOfKorea COUNTRY_VALUE(26) // KR
+#define cMalaysia COUNTRY_VALUE(27) // MY
+#define cChina COUNTRY_VALUE(28) // CN
+#define cPhilippines COUNTRY_VALUE(29) // PH
+#define cSingapore COUNTRY_VALUE(30) // SG
+#define cThailand COUNTRY_VALUE(31) // TH
+#define cTaiwan COUNTRY_VALUE(32) // TW
+
+// New in 4.0
+#define cAndorra COUNTRY_VALUE(33) // AD
+#define cUnitedArabEmirates COUNTRY_VALUE(34) // AE
+#define cAfghanistan COUNTRY_VALUE(35) // AF
+#define cAntiguaAndBarbuda COUNTRY_VALUE(36) // AG
+#define cAnguilla COUNTRY_VALUE(37) // AI
+#define cAlbania COUNTRY_VALUE(38) // AL
+#define cArmenia COUNTRY_VALUE(39) // AM
+#define cNetherlandsAntilles COUNTRY_VALUE(40) // AN
+#define cAngola COUNTRY_VALUE(41) // AO
+#define cAntarctica COUNTRY_VALUE(42) // AQ
+#define cArgentina COUNTRY_VALUE(43) // AR
+#define cAmericanSamoa COUNTRY_VALUE(44) // AS
+#define cAruba COUNTRY_VALUE(45) // AW
+#define cAzerbaijan COUNTRY_VALUE(46) // AZ
+#define cBosniaAndHerzegovina COUNTRY_VALUE(47) // BA
+#define cBarbados COUNTRY_VALUE(48) // BB
+#define cBangladesh COUNTRY_VALUE(49) // BD
+#define cBurkinaFaso COUNTRY_VALUE(50) // BF
+#define cBulgaria COUNTRY_VALUE(51) // BG
+#define cBahrain COUNTRY_VALUE(52) // BH
+#define cBurundi COUNTRY_VALUE(53) // BI
+#define cBenin COUNTRY_VALUE(54) // BJ
+#define cBermuda COUNTRY_VALUE(55) // BM
+#define cBruneiDarussalam COUNTRY_VALUE(56) // BN
+#define cBolivia COUNTRY_VALUE(57) // BO
+#define cBahamas COUNTRY_VALUE(58) // BS
+#define cBhutan COUNTRY_VALUE(59) // BT
+#define cBouvetIsland COUNTRY_VALUE(60) // BV
+#define cBotswana COUNTRY_VALUE(61) // BW
+#define cBelarus COUNTRY_VALUE(62) // BY
+#define cBelize COUNTRY_VALUE(63) // BZ
+#define cCocosIslands COUNTRY_VALUE(64) // CC
+#define cDemocraticRepublicOfTheCongo COUNTRY_VALUE(65) // CD
+#define cCentralAfricanRepublic COUNTRY_VALUE(66) // CF
+#define cCongo COUNTRY_VALUE(67) // CG
+#define cIvoryCoast COUNTRY_VALUE(68) // CI
+#define cCookIslands COUNTRY_VALUE(69) // CK
+#define cChile COUNTRY_VALUE(70) // CL
+#define cCameroon COUNTRY_VALUE(71) // CM
+#define cColumbia COUNTRY_VALUE(72) // CO
+#define cCostaRica COUNTRY_VALUE(73) // CR
+#define cCuba COUNTRY_VALUE(74) // CU
+#define cCapeVerde COUNTRY_VALUE(75) // CV
+#define cChristmasIsland COUNTRY_VALUE(76) // CX
+#define cCyprus COUNTRY_VALUE(77) // CY
+#define cCzechRepublic COUNTRY_VALUE(78) // CZ
+#define cDjibouti COUNTRY_VALUE(79) // DJ
+#define cDominica COUNTRY_VALUE(80) // DM
+#define cDominicanRepublic COUNTRY_VALUE(81) // DO
+#define cAlgeria COUNTRY_VALUE(82) // DZ
+#define cEcuador COUNTRY_VALUE(83) // EC
+#define cEstonia COUNTRY_VALUE(84) // EE
+#define cEgypt COUNTRY_VALUE(85) // EG
+#define cWesternSahara COUNTRY_VALUE(86) // EH
+#define cEritrea COUNTRY_VALUE(87) // ER
+#define cEthiopia COUNTRY_VALUE(88) // ET
+#define cFiji COUNTRY_VALUE(89) // FJ
+#define cFalklandIslands COUNTRY_VALUE(90) // FK
+#define cMicronesia COUNTRY_VALUE(91) // FM
+#define cFaeroeIslands COUNTRY_VALUE(92) // FO
+#define cMetropolitanFrance COUNTRY_VALUE(93) // FX
+#define cGabon COUNTRY_VALUE(94) // GA
+#define cGrenada COUNTRY_VALUE(95) // GD
+#define cGeorgia COUNTRY_VALUE(96) // GE
+#define cFrenchGuiana COUNTRY_VALUE(97) // GF
+#define cGhana COUNTRY_VALUE(98) // GH
+#define cGibraltar COUNTRY_VALUE(99) // GI
+#define cGreenland COUNTRY_VALUE(100) // GL
+#define cGambia COUNTRY_VALUE(101) // GM
+#define cGuinea COUNTRY_VALUE(102) // GN
+#define cGuadeloupe COUNTRY_VALUE(103) // GP
+#define cEquatorialGuinea COUNTRY_VALUE(104) // GQ
+#define cGreece COUNTRY_VALUE(105) // GR
+#define cSouthGeorgiaAndTheSouthSandwichIslands COUNTRY_VALUE(106) // GS
+#define cGuatemala COUNTRY_VALUE(107) // GT
+#define cGuam COUNTRY_VALUE(108) // GU
+#define cGuineaBisseu COUNTRY_VALUE(109) // GW
+#define cGuyana COUNTRY_VALUE(110) // GY
+#define cHeardAndMcDonaldIslands COUNTRY_VALUE(111) // HM
+#define cHonduras COUNTRY_VALUE(112) // HN
+#define cCroatia COUNTRY_VALUE(113) // HR
+#define cHaiti COUNTRY_VALUE(114) // HT
+#define cHungary COUNTRY_VALUE(115) // HU
+#define cIsrael COUNTRY_VALUE(116) // IL
+#define cBritishIndianOceanTerritory COUNTRY_VALUE(117) // IO
+#define cIraq COUNTRY_VALUE(118) // IQ
+#define cIran COUNTRY_VALUE(119) // IR
+#define cJamaica COUNTRY_VALUE(120) // JM
+#define cJordan COUNTRY_VALUE(121) // JO
+#define cKenya COUNTRY_VALUE(122) // KE
+#define cKyrgyzstan COUNTRY_VALUE(123) // KG (Kirgistan)
+#define cCambodia COUNTRY_VALUE(124) // KH
+#define cKiribati COUNTRY_VALUE(125) // KI
+#define cComoros COUNTRY_VALUE(126) // KM
+#define cStKittsAndNevis COUNTRY_VALUE(127) // KN
+#define cDemocraticPeoplesRepublicOfKorea COUNTRY_VALUE(128) // KP
+#define cKuwait COUNTRY_VALUE(129) // KW
+#define cCaymanIslands COUNTRY_VALUE(130) // KY
+#define cKazakhstan COUNTRY_VALUE(131) // KK
+#define cLaos COUNTRY_VALUE(132) // LA
+#define cLebanon COUNTRY_VALUE(133) // LB
+#define cStLucia COUNTRY_VALUE(134) // LC
+#define cLiechtenstein COUNTRY_VALUE(135) // LI
+#define cSriLanka COUNTRY_VALUE(136) // LK
+#define cLiberia COUNTRY_VALUE(137) // LR
+#define cLesotho COUNTRY_VALUE(138) // LS
+#define cLithuania COUNTRY_VALUE(139) // LT
+#define cLatvia COUNTRY_VALUE(140) // LV
+#define cLibya COUNTRY_VALUE(141) // LY
+#define cMorrocco COUNTRY_VALUE(142) // MA
+#define cMonaco COUNTRY_VALUE(143) // MC
+#define cMoldova COUNTRY_VALUE(144) // MD
+#define cMadagascar COUNTRY_VALUE(145) // MG
+#define cMarshallIslands COUNTRY_VALUE(146) // MH
+#define cMacedonia COUNTRY_VALUE(147) // MK
+#define cMali COUNTRY_VALUE(148) // ML
+#define cMyanmar COUNTRY_VALUE(149) // MM
+#define cMongolia COUNTRY_VALUE(150) // MN
+#define cMacau COUNTRY_VALUE(151) // MO
+#define cNorthernMarianaIslands COUNTRY_VALUE(152) // MP
+#define cMartinique COUNTRY_VALUE(153) // MQ
+#define cMauritania COUNTRY_VALUE(154) // MR
+#define cMontserrat COUNTRY_VALUE(155) // MS
+#define cMalta COUNTRY_VALUE(156) // MT
+#define cMauritius COUNTRY_VALUE(157) // MU
+#define cMaldives COUNTRY_VALUE(158) // MV
+#define cMalawi COUNTRY_VALUE(159) // MW
+#define cMozambique COUNTRY_VALUE(160) // MZ
+#define cNamibia COUNTRY_VALUE(161) // NA
+#define cNewCaledonia COUNTRY_VALUE(162) // NC
+#define cNiger COUNTRY_VALUE(163) // NE
+#define cNorfolkIsland COUNTRY_VALUE(164) // NF
+#define cNigeria COUNTRY_VALUE(165) // NG
+#define cNicaragua COUNTRY_VALUE(166) // NI
+#define cNepal COUNTRY_VALUE(167) // NP
+#define cNauru COUNTRY_VALUE(168) // NR
+#define cNiue COUNTRY_VALUE(169) // NU
+#define cOman COUNTRY_VALUE(170) // OM
+#define cPanama COUNTRY_VALUE(171) // PA
+#define cPeru COUNTRY_VALUE(172) // PE
+#define cFrenchPolynesia COUNTRY_VALUE(173) // PF
+#define cPapuaNewGuinea COUNTRY_VALUE(174) // PG
+#define cPakistan COUNTRY_VALUE(175) // PK
+#define cPoland COUNTRY_VALUE(176) // PL
+#define cStPierreAndMiquelon COUNTRY_VALUE(177) // PM
+#define cPitcairn COUNTRY_VALUE(178) // PN
+#define cPuertoRico COUNTRY_VALUE(179) // PR
+#define cPortugal COUNTRY_VALUE(180) // PT
+#define cPalau COUNTRY_VALUE(181) // PW
+#define cParaguay COUNTRY_VALUE(182) // PY
+#define cQatar COUNTRY_VALUE(183) // QA
+#define cReunion COUNTRY_VALUE(184) // RE
+#define cRomania COUNTRY_VALUE(185) // RO
+#define cRussianFederation COUNTRY_VALUE(186) // RU
+#define cRwanda COUNTRY_VALUE(187) // RW
+#define cSaudiArabia COUNTRY_VALUE(188) // SA
+#define cSolomonIslands COUNTRY_VALUE(189) // SB
+#define cSeychelles COUNTRY_VALUE(190) // SC
+#define cSudan COUNTRY_VALUE(191) // SD
+#define cStHelena COUNTRY_VALUE(192) // SH
+#define cSlovenia COUNTRY_VALUE(193) // SI
+#define cSvalbardAndJanMayenIslands COUNTRY_VALUE(194) // SJ
+#define cSlovakia COUNTRY_VALUE(195) // SK
+#define cSierraLeone COUNTRY_VALUE(196) // SL
+#define cSanMarino COUNTRY_VALUE(197) // SM
+#define cSenegal COUNTRY_VALUE(198) // SN
+#define cSomalia COUNTRY_VALUE(199) // SO
+#define cSuriname COUNTRY_VALUE(200) // SR
+#define cSaoTomeAndPrincipe COUNTRY_VALUE(201) // ST
+#define cElSalvador COUNTRY_VALUE(202) // SV
+#define cSyranArabRepublic COUNTRY_VALUE(203) // SY
+#define cSwaziland COUNTRY_VALUE(204) // SZ
+#define cTurksAndCaicosIslands COUNTRY_VALUE(205) // TC
+#define cChad COUNTRY_VALUE(206) // TD
+#define cFrenchSouthernTerritories COUNTRY_VALUE(207) // TF
+#define cTogo COUNTRY_VALUE(208) // TG
+#define cTajikistan COUNTRY_VALUE(209) // TJ
+#define cTokelau COUNTRY_VALUE(210) // TK
+#define cTurkmenistan COUNTRY_VALUE(211) // TM
+#define cTunisia COUNTRY_VALUE(212) // TN
+#define cTonga COUNTRY_VALUE(213) // TO
+#define cEastTimor COUNTRY_VALUE(214) // TP
+#define cTurkey COUNTRY_VALUE(215) // TR
+#define cTrinidadAndTobago COUNTRY_VALUE(216) // TT
+#define cTuvalu COUNTRY_VALUE(217) // TV
+#define cTanzania COUNTRY_VALUE(218) // TZ
+#define cUkraine COUNTRY_VALUE(219) // UA
+#define cUganda COUNTRY_VALUE(220) // UG
+#define cUnitedStatesMinorOutlyingIslands COUNTRY_VALUE(221) // UM
+#define cUruguay COUNTRY_VALUE(222) // UY
+#define cUzbekistan COUNTRY_VALUE(223) // UZ
+#define cHolySee COUNTRY_VALUE(224) // VA
+#define cStVincentAndTheGrenadines COUNTRY_VALUE(225) // VC
+#define cVenezuela COUNTRY_VALUE(226) // VE
+#define cBritishVirginIslands COUNTRY_VALUE(227) // VG
+#define cUSVirginIslands COUNTRY_VALUE(228) // VI
+#define cVietNam COUNTRY_VALUE(229) // VN
+#define cVanuatu COUNTRY_VALUE(230) // VU
+#define cWallisAndFutunaIslands COUNTRY_VALUE(231) // WF
+#define cSamoa COUNTRY_VALUE(232) // WS
+#define cYemen COUNTRY_VALUE(233) // YE
+#define cMayotte COUNTRY_VALUE(234) // YT
+#define cYugoslavia COUNTRY_VALUE(235) // YU
+#define cSouthAfrica COUNTRY_VALUE(236) // ZA
+#define cZambia COUNTRY_VALUE(237) // ZM
+#define cZimbabwe COUNTRY_VALUE(238) // ZW
+//
+#define cCountryNum COUNTRY_VALUE(239) // Number of Countries
+
+/* Various character encodings supported by the PalmOS. Actually these
+are a mixture of character sets (repetoires or coded character sets
+in Internet lingo) and character encodings (CES - character encoding
+standard). Many, however, are some of both (e.g. CP932 is the Shift-JIS
+encoding of the JIS character set + Microsoft's extensions).
+
+The following character set values are used by:
+ a) Palm devices
+ b) Palm wireless servers
+
+WARNING! Be aware that a device supporting a new character set
+ will require some character set definition and maybe
+ some development on the wireless server side.
+*/
+#define CHAR_ENCODING_VALUE(value) ((CharEncodingType)value)
+
+// Unknown to this version of PalmOS.
+#define charEncodingUnknown CHAR_ENCODING_VALUE(0)
+
+// Maximum character encoding _currently_ defined
+#define charEncodingMax CHAR_ENCODING_VALUE(83)
+
+// Latin Palm OS character encoding, and subsets.
+// PalmOS variant of CP1252, with 10 extra Greek characters
+#define charEncodingPalmGSM CHAR_ENCODING_VALUE(78)
+// PalmOS version of CP1252
+#define charEncodingPalmLatin CHAR_ENCODING_VALUE(3)
+// Windows variant of 8859-1
+#define charEncodingCP1252 CHAR_ENCODING_VALUE(7)
+// ISO 8859 Part 1
+#define charEncodingISO8859_1 CHAR_ENCODING_VALUE(2)
+// ISO 646-1991
+#define charEncodingAscii CHAR_ENCODING_VALUE(1)
+
+// Japanese Palm OS character encoding, and subsets.
+// PalmOS version of CP932
+#define charEncodingPalmSJIS CHAR_ENCODING_VALUE(5)
+// Windows variant of ShiftJIS
+#define charEncodingCP932 CHAR_ENCODING_VALUE(8)
+// Encoding for JIS 0208-1990 + 1-byte katakana
+#define charEncodingShiftJIS CHAR_ENCODING_VALUE(4)
+
+// Unicode character encodings
+#define charEncodingUCS2 CHAR_ENCODING_VALUE(9)
+#define charEncodingUTF8 CHAR_ENCODING_VALUE(6)
+#define charEncodingUTF7 CHAR_ENCODING_VALUE(24)
+#define charEncodingUTF16 CHAR_ENCODING_VALUE(75)
+#define charEncodingUTF16BE CHAR_ENCODING_VALUE(76)
+#define charEncodingUTF16LE CHAR_ENCODING_VALUE(77)
+
+// Latin character encodings
+#define charEncodingCP850 CHAR_ENCODING_VALUE(12)
+#define charEncodingCP437 CHAR_ENCODING_VALUE(13)
+#define charEncodingCP865 CHAR_ENCODING_VALUE(14)
+#define charEncodingCP860 CHAR_ENCODING_VALUE(15)
+#define charEncodingCP861 CHAR_ENCODING_VALUE(16)
+#define charEncodingCP863 CHAR_ENCODING_VALUE(17)
+#define charEncodingCP775 CHAR_ENCODING_VALUE(18)
+#define charEncodingMacIslande CHAR_ENCODING_VALUE(19)
+#define charEncodingMacintosh CHAR_ENCODING_VALUE(20)
+#define charEncodingCP1257 CHAR_ENCODING_VALUE(21)
+#define charEncodingISO8859_3 CHAR_ENCODING_VALUE(22)
+#define charEncodingISO8859_4 CHAR_ENCODING_VALUE(23)
+
+// Extended Latin character encodings
+#define charEncodingISO8859_2 CHAR_ENCODING_VALUE(26)
+#define charEncodingCP1250 CHAR_ENCODING_VALUE(27)
+#define charEncodingCP852 CHAR_ENCODING_VALUE(28)
+#define charEncodingXKamenicky CHAR_ENCODING_VALUE(29)
+#define charEncodingMacXCroate CHAR_ENCODING_VALUE(30)
+#define charEncodingMacXLat2 CHAR_ENCODING_VALUE(31)
+#define charEncodingMacXRomania CHAR_ENCODING_VALUE(32)
+
+// Japanese character encodings
+#define charEncodingEucJp CHAR_ENCODING_VALUE(25)
+#define charEncodingISO2022Jp CHAR_ENCODING_VALUE(10)
+#define charEncodingXAutoJp CHAR_ENCODING_VALUE(11)
+
+// Greek character encodings
+#define charEncodingISO8859_7 CHAR_ENCODING_VALUE(33)
+#define charEncodingCP1253 CHAR_ENCODING_VALUE(34)
+#define charEncodingCP869 CHAR_ENCODING_VALUE(35)
+#define charEncodingCP737 CHAR_ENCODING_VALUE(36)
+#define charEncodingMacXGr CHAR_ENCODING_VALUE(37)
+
+// Cyrillic character encodings
+#define charEncodingCP1251 CHAR_ENCODING_VALUE(38)
+#define charEncodingISO8859_5 CHAR_ENCODING_VALUE(39)
+#define charEncodingKoi8R CHAR_ENCODING_VALUE(40)
+#define charEncodingKoi8 CHAR_ENCODING_VALUE(41)
+#define charEncodingCP855 CHAR_ENCODING_VALUE(42)
+#define charEncodingCP866 CHAR_ENCODING_VALUE(43)
+#define charEncodingMacCyr CHAR_ENCODING_VALUE(44)
+#define charEncodingMacUkraine CHAR_ENCODING_VALUE(45)
+
+// Turkish character encodings
+#define charEncodingCP1254 CHAR_ENCODING_VALUE(46)
+#define charEncodingISO8859_9 CHAR_ENCODING_VALUE(47)
+#define charEncodingCP857 CHAR_ENCODING_VALUE(48)
+#define charEncodingMacTurc CHAR_ENCODING_VALUE(49)
+#define charEncodingCP853 CHAR_ENCODING_VALUE(50)
+
+// Arabic character encodings
+#define charEncodingISO8859_6 CHAR_ENCODING_VALUE(51)
+#define charEncodingAsmo708 CHAR_ENCODING_VALUE(52)
+#define charEncodingCP1256 CHAR_ENCODING_VALUE(53)
+#define charEncodingCP864 CHAR_ENCODING_VALUE(54)
+#define charEncodingAsmo708Plus CHAR_ENCODING_VALUE(55)
+#define charEncodingAsmo708Fr CHAR_ENCODING_VALUE(56)
+#define charEncodingMacAra CHAR_ENCODING_VALUE(57)
+
+// Simplified Chinese character encodings
+#define charEncodingGB2312 CHAR_ENCODING_VALUE(58)
+#define charEncodingHZ CHAR_ENCODING_VALUE(59)
+#define charEncodingGBK CHAR_ENCODING_VALUE(82)
+#define charEncodingPalmGB CHAR_ENCODING_VALUE(83)
+
+// Traditional Chinese character encodings
+#define charEncodingBig5 CHAR_ENCODING_VALUE(60)
+#define charEncodingBig5_HKSCS CHAR_ENCODING_VALUE(79)
+#define charEncodingBig5Plus CHAR_ENCODING_VALUE(80)
+#define charEncodingPalmBig5 CHAR_ENCODING_VALUE(81)
+
+// Vietnamese character encodings
+#define charEncodingViscii CHAR_ENCODING_VALUE(61)
+#define charEncodingViqr CHAR_ENCODING_VALUE(62)
+#define charEncodingVncii CHAR_ENCODING_VALUE(63)
+#define charEncodingVietnet CHAR_ENCODING_VALUE(65)
+#define charEncodingCP1258 CHAR_ENCODING_VALUE(66)
+
+// Korean character encodings
+#define charEncodingKsc5601 CHAR_ENCODING_VALUE(67)
+#define charEncodingCP949 CHAR_ENCODING_VALUE(68)
+#define charEncodingISO2022Kr CHAR_ENCODING_VALUE(69)
+
+// Hebrew character encodings
+#define charEncodingISO8859_8I CHAR_ENCODING_VALUE(70)
+#define charEncodingISO8859_8 CHAR_ENCODING_VALUE(71)
+#define charEncodingCP1255 CHAR_ENCODING_VALUE(72)
+#define charEncodingCP1255V CHAR_ENCODING_VALUE(73)
+
+// Thai character encodings
+#define charEncodingTis620 CHAR_ENCODING_VALUE(74)
+#define charEncodingCP874 CHAR_ENCODING_VALUE(64)
+
+
+// Leave the following line unchanged at end of section:
+// TAG SOURCE END
+
+/* Rez doesn't even support macros, so for Rez we simplify all of the #defines.
+
+WARNING! This section is auto-generated (see comment near top of file).
+*/
+#else // !PALM_LOCALE_HAS_TYPES
+
+// Leave the following line unchanged at beginning of rez section
+// TAG DESTINATION START
+
+#define lEnglish 0 // EN
+#define lFrench 1 // FR
+#define lGerman 2 // DE
+#define lItalian 3 // IT
+#define lSpanish 4 // ES
+#define lUnused 5 // Reserved
+
+// New in 3.1
+#define lJapanese 6 // JA (Palm calls this jp)
+#define lDutch 7 // NL
+
+// New in 4.0
+#define lAfar 8 // AA
+#define lAbkhazian 9 // AB
+#define lAfrikaans 10 // AF
+#define lAmharic 11 // AM
+#define lArabic 12 // AR
+#define lAssamese 13 // AS
+#define lAymara 14 // AY
+#define lAzerbaijani 15 // AZ
+#define lBashkir 16 // BA
+#define lByelorussian 17 // BE
+#define lBulgarian 18 // BG
+#define lBihari 19 // BH
+#define lBislama 20 // BI
+#define lBengali 21 // BN (Bangla)
+#define lTibetan 22 // BO
+#define lBreton 23 // BR
+#define lCatalan 24 // CA
+#define lCorsican 25 // CO
+#define lCzech 26 // CS
+#define lWelsh 27 // CY
+#define lDanish 28 // DA
+#define lBhutani 29 // DZ
+#define lGreek 30 // EL
+#define lEsperanto 31 // EO
+#define lEstonian 32 // ET
+#define lBasque 33 // EU
+#define lPersian 34 // FA (Farsi)
+#define lFinnish 35 // FI
+#define lFiji 36 // FJ
+#define lFaroese 37 // FO
+#define lFrisian 38 // FY
+#define lIrish 39 // GA
+#define lScotsGaelic 40 // GD
+#define lGalician 41 // GL
+#define lGuarani 42 // GN
+#define lGujarati 43 // GU
+#define lHausa 44 // HA
+#define lHindi 45 // HI
+#define lCroatian 46 // HR
+#define lHungarian 47 // HU
+#define lArmenian 48 // HY
+#define lInterlingua 49 // IA
+#define lInterlingue 50 // IE
+#define lInupiak 51 // IK
+#define lIndonesian 52 // IN
+#define lIcelandic 53 // IS
+#define lHebrew 54 // IW
+#define lYiddish 55 // JI
+#define lJavanese 56 // JW
+#define lGeorgian 57 // KA
+#define lKazakh 58 // KK
+#define lGreenlandic 59 // KL
+#define lCambodian 60 // KM
+#define lKannada 61 // KN
+#define lKorean 62 // KO
+#define lKashmiri 63 // KS
+#define lKurdish 64 // KU
+#define lKirghiz 65 // KY
+#define lLatin 66 // LA
+#define lLingala 67 // LN
+#define lLaothian 68 // LO
+#define lLithuanian 69 // LT
+#define lLatvian 70 // LV (Lettish)
+#define lMalagasy 71 // MG
+#define lMaori 72 // MI
+#define lMacedonian 73 // MK
+#define lMalayalam 74 // ML
+#define lMongolian 75 // MN
+#define lMoldavian 76 // MO
+#define lMarathi 77 // MR
+#define lMalay 78 // MS
+#define lMaltese 79 // MT
+#define lBurmese 80 // MY
+#define lNauru 81 // NA
+#define lNepali 82 // NE
+#define lNorwegian 83 // NO
+#define lOccitan 84 // OC
+#define lAfan 85 // OM (Oromo)
+#define lOriya 86 // OR
+#define lPunjabi 87 // PA
+#define lPolish 88 // PL
+#define lPashto 89 // PS (Pushto)
+#define lPortuguese 90 // PT
+#define lQuechua 91 // QU
+#define lRhaetoRomance 92 // RM
+#define lKurundi 93 // RN
+#define lRomanian 94 // RO
+#define lRussian 95 // RU
+#define lKinyarwanda 96 // RW
+#define lSanskrit 97 // SA
+#define lSindhi 98 // SD
+#define lSangho 99 // SG
+#define lSerboCroatian 100 // SH
+#define lSinghalese 101 // SI
+#define lSlovak 102 // SK
+#define lSlovenian 103 // SL
+#define lSamoan 104 // SM
+#define lShona 105 // SN
+#define lSomali 106 // SO
+#define lAlbanian 107 // SQ
+#define lSerbian 108 // SR
+#define lSiswati 109 // SS
+#define lSesotho 110 // ST
+#define lSudanese 111 // SU
+#define lSwedish 112 // SV
+#define lSwahili 113 // SW
+#define lTamil 114 // TA
+#define lTelugu 115 // TE
+#define lTajik 116 // TG
+#define lThai 117 // TH
+#define lTigrinya 118 // TI
+#define lTurkmen 119 // TK
+#define lTagalog 120 // TL
+#define lSetswana 121 // TN
+#define lTonga 122 // TO
+#define lTurkish 123 // TR
+#define lTsonga 124 // TS
+#define lTatar 125 // TT
+#define lTwi 126 // TW
+#define lUkrainian 127 // UK
+#define lUrdu 128 // UR
+#define lUzbek 129 // UZ
+#define lVietnamese 130 // VI
+#define lVolapuk 131 // VO
+#define lWolof 132 // WO
+#define lXhosa 133 // XH
+#define lYoruba 134 // YO
+#define lChinese 135 // ZH
+#define lZulu 136 // ZU
+//
+#define lLanguageNum 137 // Number of Languages
+
+/* Country codes (ISO 3166). The first 33 preserve the old values for the
+deprecated CountryType; the rest are sorted by the 2-character country code.
+
+WARNING! Keep in sync with BOTH:
+ 1) CountryCode array in OverlayMgr.c
+ 2) localeCountry #define in UIResDefs.r
+*/
+#define COUNTRY_VALUE(value) ((CountryType)value)
+
+#define cAustralia 0 // AU
+#define cAustria 1 // AT
+#define cBelgium 2 // BE
+#define cBrazil 3 // BR
+#define cCanada 4 // CA
+#define cDenmark 5 // DK
+#define cFinland 6 // FI
+#define cFrance 7 // FR
+#define cGermany 8 // DE
+#define cHongKong 9 // HK
+#define cIceland 10 // IS
+#define cIreland 11 // IE
+#define cItaly 12 // IT
+#define cJapan 13 // JP
+#define cLuxembourg 14 // LU
+#define cMexico 15 // MX
+#define cNetherlands 16 // NL
+#define cNewZealand 17 // NZ
+#define cNorway 18 // NO
+#define cSpain 19 // ES
+#define cSweden 20 // SE
+#define cSwitzerland 21 // CH
+#define cUnitedKingdom 22 // GB (UK)
+#define cUnitedStates 23 // US
+#define cIndia 24 // IN
+#define cIndonesia 25 // ID
+#define cRepublicOfKorea 26 // KR
+#define cMalaysia 27 // MY
+#define cChina 28 // CN
+#define cPhilippines 29 // PH
+#define cSingapore 30 // SG
+#define cThailand 31 // TH
+#define cTaiwan 32 // TW
+
+// New in 4.0
+#define cAndorra 33 // AD
+#define cUnitedArabEmirates 34 // AE
+#define cAfghanistan 35 // AF
+#define cAntiguaAndBarbuda 36 // AG
+#define cAnguilla 37 // AI
+#define cAlbania 38 // AL
+#define cArmenia 39 // AM
+#define cNetherlandsAntilles 40 // AN
+#define cAngola 41 // AO
+#define cAntarctica 42 // AQ
+#define cArgentina 43 // AR
+#define cAmericanSamoa 44 // AS
+#define cAruba 45 // AW
+#define cAzerbaijan 46 // AZ
+#define cBosniaAndHerzegovina 47 // BA
+#define cBarbados 48 // BB
+#define cBangladesh 49 // BD
+#define cBurkinaFaso 50 // BF
+#define cBulgaria 51 // BG
+#define cBahrain 52 // BH
+#define cBurundi 53 // BI
+#define cBenin 54 // BJ
+#define cBermuda 55 // BM
+#define cBruneiDarussalam 56 // BN
+#define cBolivia 57 // BO
+#define cBahamas 58 // BS
+#define cBhutan 59 // BT
+#define cBouvetIsland 60 // BV
+#define cBotswana 61 // BW
+#define cBelarus 62 // BY
+#define cBelize 63 // BZ
+#define cCocosIslands 64 // CC
+#define cDemocraticRepublicOfTheCongo 65 // CD
+#define cCentralAfricanRepublic 66 // CF
+#define cCongo 67 // CG
+#define cIvoryCoast 68 // CI
+#define cCookIslands 69 // CK
+#define cChile 70 // CL
+#define cCameroon 71 // CM
+#define cColumbia 72 // CO
+#define cCostaRica 73 // CR
+#define cCuba 74 // CU
+#define cCapeVerde 75 // CV
+#define cChristmasIsland 76 // CX
+#define cCyprus 77 // CY
+#define cCzechRepublic 78 // CZ
+#define cDjibouti 79 // DJ
+#define cDominica 80 // DM
+#define cDominicanRepublic 81 // DO
+#define cAlgeria 82 // DZ
+#define cEcuador 83 // EC
+#define cEstonia 84 // EE
+#define cEgypt 85 // EG
+#define cWesternSahara 86 // EH
+#define cEritrea 87 // ER
+#define cEthiopia 88 // ET
+#define cFiji 89 // FJ
+#define cFalklandIslands 90 // FK
+#define cMicronesia 91 // FM
+#define cFaeroeIslands 92 // FO
+#define cMetropolitanFrance 93 // FX
+#define cGabon 94 // GA
+#define cGrenada 95 // GD
+#define cGeorgia 96 // GE
+#define cFrenchGuiana 97 // GF
+#define cGhana 98 // GH
+#define cGibraltar 99 // GI
+#define cGreenland 100 // GL
+#define cGambia 101 // GM
+#define cGuinea 102 // GN
+#define cGuadeloupe 103 // GP
+#define cEquatorialGuinea 104 // GQ
+#define cGreece 105 // GR
+#define cSouthGeorgiaAndTheSouthSandwichIslands 106 // GS
+#define cGuatemala 107 // GT
+#define cGuam 108 // GU
+#define cGuineaBisseu 109 // GW
+#define cGuyana 110 // GY
+#define cHeardAndMcDonaldIslands 111 // HM
+#define cHonduras 112 // HN
+#define cCroatia 113 // HR
+#define cHaiti 114 // HT
+#define cHungary 115 // HU
+#define cIsrael 116 // IL
+#define cBritishIndianOceanTerritory 117 // IO
+#define cIraq 118 // IQ
+#define cIran 119 // IR
+#define cJamaica 120 // JM
+#define cJordan 121 // JO
+#define cKenya 122 // KE
+#define cKyrgyzstan 123 // KG (Kirgistan)
+#define cCambodia 124 // KH
+#define cKiribati 125 // KI
+#define cComoros 126 // KM
+#define cStKittsAndNevis 127 // KN
+#define cDemocraticPeoplesRepublicOfKorea 128 // KP
+#define cKuwait 129 // KW
+#define cCaymanIslands 130 // KY
+#define cKazakhstan 131 // KK
+#define cLaos 132 // LA
+#define cLebanon 133 // LB
+#define cStLucia 134 // LC
+#define cLiechtenstein 135 // LI
+#define cSriLanka 136 // LK
+#define cLiberia 137 // LR
+#define cLesotho 138 // LS
+#define cLithuania 139 // LT
+#define cLatvia 140 // LV
+#define cLibya 141 // LY
+#define cMorrocco 142 // MA
+#define cMonaco 143 // MC
+#define cMoldova 144 // MD
+#define cMadagascar 145 // MG
+#define cMarshallIslands 146 // MH
+#define cMacedonia 147 // MK
+#define cMali 148 // ML
+#define cMyanmar 149 // MM
+#define cMongolia 150 // MN
+#define cMacau 151 // MO
+#define cNorthernMarianaIslands 152 // MP
+#define cMartinique 153 // MQ
+#define cMauritania 154 // MR
+#define cMontserrat 155 // MS
+#define cMalta 156 // MT
+#define cMauritius 157 // MU
+#define cMaldives 158 // MV
+#define cMalawi 159 // MW
+#define cMozambique 160 // MZ
+#define cNamibia 161 // NA
+#define cNewCaledonia 162 // NC
+#define cNiger 163 // NE
+#define cNorfolkIsland 164 // NF
+#define cNigeria 165 // NG
+#define cNicaragua 166 // NI
+#define cNepal 167 // NP
+#define cNauru 168 // NR
+#define cNiue 169 // NU
+#define cOman 170 // OM
+#define cPanama 171 // PA
+#define cPeru 172 // PE
+#define cFrenchPolynesia 173 // PF
+#define cPapuaNewGuinea 174 // PG
+#define cPakistan 175 // PK
+#define cPoland 176 // PL
+#define cStPierreAndMiquelon 177 // PM
+#define cPitcairn 178 // PN
+#define cPuertoRico 179 // PR
+#define cPortugal 180 // PT
+#define cPalau 181 // PW
+#define cParaguay 182 // PY
+#define cQatar 183 // QA
+#define cReunion 184 // RE
+#define cRomania 185 // RO
+#define cRussianFederation 186 // RU
+#define cRwanda 187 // RW
+#define cSaudiArabia 188 // SA
+#define cSolomonIslands 189 // SB
+#define cSeychelles 190 // SC
+#define cSudan 191 // SD
+#define cStHelena 192 // SH
+#define cSlovenia 193 // SI
+#define cSvalbardAndJanMayenIslands 194 // SJ
+#define cSlovakia 195 // SK
+#define cSierraLeone 196 // SL
+#define cSanMarino 197 // SM
+#define cSenegal 198 // SN
+#define cSomalia 199 // SO
+#define cSuriname 200 // SR
+#define cSaoTomeAndPrincipe 201 // ST
+#define cElSalvador 202 // SV
+#define cSyranArabRepublic 203 // SY
+#define cSwaziland 204 // SZ
+#define cTurksAndCaicosIslands 205 // TC
+#define cChad 206 // TD
+#define cFrenchSouthernTerritories 207 // TF
+#define cTogo 208 // TG
+#define cTajikistan 209 // TJ
+#define cTokelau 210 // TK
+#define cTurkmenistan 211 // TM
+#define cTunisia 212 // TN
+#define cTonga 213 // TO
+#define cEastTimor 214 // TP
+#define cTurkey 215 // TR
+#define cTrinidadAndTobago 216 // TT
+#define cTuvalu 217 // TV
+#define cTanzania 218 // TZ
+#define cUkraine 219 // UA
+#define cUganda 220 // UG
+#define cUnitedStatesMinorOutlyingIslands 221 // UM
+#define cUruguay 222 // UY
+#define cUzbekistan 223 // UZ
+#define cHolySee 224 // VA
+#define cStVincentAndTheGrenadines 225 // VC
+#define cVenezuela 226 // VE
+#define cBritishVirginIslands 227 // VG
+#define cUSVirginIslands 228 // VI
+#define cVietNam 229 // VN
+#define cVanuatu 230 // VU
+#define cWallisAndFutunaIslands 231 // WF
+#define cSamoa 232 // WS
+#define cYemen 233 // YE
+#define cMayotte 234 // YT
+#define cYugoslavia 235 // YU
+#define cSouthAfrica 236 // ZA
+#define cZambia 237 // ZM
+#define cZimbabwe 238 // ZW
+//
+#define cCountryNum 239 // Number of Countries
+
+/* Various character encodings supported by the PalmOS. Actually these
+are a mixture of character sets (repetoires or coded character sets
+in Internet lingo) and character encodings (CES - character encoding
+standard). Many, however, are some of both (e.g. CP932 is the Shift-JIS
+encoding of the JIS character set + Microsoft's extensions).
+
+The following character set values are used by:
+ a) Palm devices
+ b) Palm wireless servers
+
+WARNING! Be aware that a device supporting a new character set
+ will require some character set definition and maybe
+ some development on the wireless server side.
+*/
+
+
+///////////////////////////////////////////////////////////////////////////
+// Warning: The following files are interdependent and MUST to be modified together:
+//
+// -> Viewer\Incs\Core\System\PalmLocale.h
+// (defines charset IDs)
+//
+// -> Server\apps\Elaine\Src\Core\CharsetInfo.cpp
+// (defines charset attributes like Asian, cp1252 compatible, etc.)
+//
+// -> Server\CstPalmOSCharsets.lst
+// (list the iso names of
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#define CHAR_ENCODING_VALUE(value) ((CharEncodingType)value)
+
+// Unknown to this version of PalmOS.
+#define charEncodingUnknown 0
+
+// Maximum character encoding _currently_ defined
+
+#define charEncodingMax 83
+
+// Latin Palm OS character encoding, and subsets.
+// PalmOS variant of CP1252, with 10 extra Greek characters
+#define charEncodingPalmGSM 78
+// PalmOS version of CP1252
+#define charEncodingPalmLatin 3
+// Windows variant of 8859-1
+#define charEncodingCP1252 7
+// ISO 8859 Part 1
+#define charEncodingISO8859_1 2
+// ISO 646-1991
+#define charEncodingAscii 1
+
+// Japanese Palm OS character encoding, and subsets.
+// PalmOS version of CP932
+#define charEncodingPalmSJIS 5
+// Windows variant of ShiftJIS
+#define charEncodingCP932 8
+// Encoding for JIS 0208-1990 + 1-byte katakana
+#define charEncodingShiftJIS 4
+
+// Unicode character encodings
+#define charEncodingUCS2 9
+#define charEncodingUTF8 6
+#define charEncodingUTF7 24
+#define charEncodingUTF16 75
+#define charEncodingUTF16BE 76
+#define charEncodingUTF16LE 77
+
+// Latin character encodings
+#define charEncodingCP850 12
+#define charEncodingCP437 13
+#define charEncodingCP865 14
+#define charEncodingCP860 15
+#define charEncodingCP861 16
+#define charEncodingCP863 17
+#define charEncodingCP775 18
+#define charEncodingMacIslande 19
+#define charEncodingMacintosh 20
+#define charEncodingCP1257 21
+#define charEncodingISO8859_3 22
+#define charEncodingISO8859_4 23
+
+// Extended Latin character encodings
+#define charEncodingISO8859_2 26
+#define charEncodingCP1250 27
+#define charEncodingCP852 28
+#define charEncodingXKamenicky 29
+#define charEncodingMacXCroate 30
+#define charEncodingMacXLat2 31
+#define charEncodingMacXRomania 32
+
+// Japanese character encodings
+#define charEncodingEucJp 25
+#define charEncodingISO2022Jp 10
+#define charEncodingXAutoJp 11
+
+// Greek character encodings
+#define charEncodingISO8859_7 33
+#define charEncodingCP1253 34
+#define charEncodingCP869 35
+#define charEncodingCP737 36
+#define charEncodingMacXGr 37
+
+// Cyrillic character encodings
+#define charEncodingCP1251 38
+#define charEncodingISO8859_5 39
+#define charEncodingKoi8R 40
+#define charEncodingKoi8 41
+#define charEncodingCP855 42
+#define charEncodingCP866 43
+#define charEncodingMacCyr 44
+#define charEncodingMacUkraine 45
+
+// Turkish character encodings
+#define charEncodingCP1254 46
+#define charEncodingISO8859_9 47
+#define charEncodingCP857 48
+#define charEncodingMacTurc 49
+#define charEncodingCP853 50
+
+// Arabic character encodings
+#define charEncodingISO8859_6 51
+#define charEncodingAsmo708 52
+#define charEncodingCP1256 53
+#define charEncodingCP864 54
+#define charEncodingAsmo708Plus 55
+#define charEncodingAsmo708Fr 56
+#define charEncodingMacAra 57
+
+// Simplified Chinese character encodings
+#define charEncodingGB2312 58
+#define charEncodingHZ 59
+#define charEncodingGBK 82
+#define charEncodingPalmGB 83
+
+// Traditional Chinese character encodings
+#define charEncodingBig5 60
+#define charEncodingBig5_HKSCS 79
+#define charEncodingBig5Plus 80
+#define charEncodingPalmBig5 81
+
+// Vietnamese character encodings
+#define charEncodingViscii 61
+#define charEncodingViqr 62
+#define charEncodingVncii 63
+#define charEncodingVietnet 65
+#define charEncodingCP1258 66
+
+// Korean character encodings
+#define charEncodingKsc5601 67
+#define charEncodingCP949 68
+#define charEncodingISO2022Kr 69
+
+// Hebrew character encodings
+#define charEncodingISO8859_8I 70
+#define charEncodingISO8859_8 71
+#define charEncodingCP1255 72
+#define charEncodingCP1255V 73
+
+// Thai character encodings
+#define charEncodingTis620 74
+#define charEncodingCP874 64
+
+
+// Leave the following line unchanged at end of section
+// TAG DESTINATION END
+
+#endif // !PALM_LOCALE_HAS_TYPES
+
+#endif // __PALMLOCALE_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/PenMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/PenMgr.h
new file mode 100644
index 0000000..538c9ac
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/PenMgr.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: PenMgr.h
+ *
+ * Description:
+ * Include file for Pen manager
+ *
+ * History:
+ * 6/5/96 Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifndef __PEN_MGR_H
+#define __PEN_MGR_H
+
+// Pilot common definitions
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <ErrorBase.h>
+#include <Rect.h>
+
+
+/********************************************************************
+ * Pen Manager Errors
+ * the constant serErrorClass is defined in ErrorBase.h
+ ********************************************************************/
+#define penErrBadParam (penErrorClass | 1)
+#define penErrIgnorePoint (penErrorClass | 2)
+
+
+
+/********************************************************************
+ * Pen manager Routines
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Initializes the Pen Manager
+Err PenOpen(void)
+ SYS_TRAP(sysTrapPenOpen);
+
+// Closes the Pen Manager and frees whatever memory it allocated
+Err PenClose(void)
+ SYS_TRAP(sysTrapPenClose);
+
+
+// Put pen to sleep
+Err PenSleep(void)
+ SYS_TRAP(sysTrapPenSleep);
+
+// Wake pen
+Err PenWake(void)
+ SYS_TRAP(sysTrapPenWake);
+
+
+// Get the raw pen coordinates from the hardware.
+Err PenGetRawPen(PointType *penP)
+ SYS_TRAP(sysTrapPenGetRawPen);
+
+// Reset calibration in preparation for setting it again
+Err PenResetCalibration (void)
+ SYS_TRAP(sysTrapPenResetCalibration);
+
+// Set calibration settings for the pen
+Err PenCalibrate (PointType *digTopLeftP, PointType *digBotRightP,
+ PointType *scrTopLeftP, PointType *scrBotRightP)
+ SYS_TRAP(sysTrapPenCalibrate);
+
+// Scale a raw pen coordinate into screen coordinates
+Err PenRawToScreen(PointType *penP)
+ SYS_TRAP(sysTrapPenRawToScreen);
+
+// Scale a screen pen coordinate back into a raw coordinate
+Err PenScreenToRaw(PointType *penP)
+ SYS_TRAP(sysTrapPenScreenToRaw);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+/************************************************************
+ * Assembly Function Prototypes
+ *************************************************************/
+#define _PenGetRawPen \
+ ASM_SYS_TRAP(sysTrapPenGetRawPen)
+
+
+
+#endif //__PEN_MGR_H
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Preferences.h b/SrcShared/Palm/Platform/Incs/Core/System/Preferences.h
new file mode 100644
index 0000000..726055b
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Preferences.h
@@ -0,0 +1,428 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-2000 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Preferences.h
+ *
+ * Release:
+ *
+ * Description:
+ * Header for the system preferences
+ *
+ * History:
+ * 02/31/95 rsf Created by Roger Flores
+ * 06/26/99 kwk Added LanguageType.
+ * 06/30/99 CS Added MeasurementSystemType, then added it to both
+ * CountryPreferencesType and SystemPreferencesType,
+ * and bumped the version to 7.
+ * CS Added prefMeasurementSystem to select this
+ * preference.
+ * CS Added filler fields to CountryPreferencesType
+ * structure, since this guy gets saved as a
+ * resource.
+ * 09/20/99 gap added additional cXXXX country values.
+ * 09/20/99 gap cPRC -> cRepChina.
+ * 10/4/99 jmp Add support for auto-off duration times in seconds
+ * instead of minutes (the new seconds-based auto-off
+ * duration time is preferred; the minutes-based auto-ff
+ * duration times are maintained for compatibility).
+ * 10/5/99 jmp Make the seconds auto-off duration field a UInt16
+ * instead of a UInt8; also define constants for the
+ * "pegged" auto-off duration values (when the value
+ * is pegged, we no longer automatically shut off).
+ * 12/23/99 jmp Fix <> vs. "" problem.
+ * 04/30/00 CS Use LmCountryType instead of CountryType. Also removed
+ * deprecated countryNameLength, currencyNameLength, and
+ * currencySymbolLength, replacing usage with new
+ * kMaxCountryNameLen, kMaxCurrencyNameLen, and
+ * kMaxCurrencySymbolLen.
+ * 05/16/00 CS LmCountryType/LmLanguageType are now back to
+ * CountryType/LanguageType.
+ * 08/01/00 CS Added prefLanguage & prefLocale to selector set, and
+ * locale to SystemPreferencesType.
+ * 08/01/00 kwk Added timeZoneCountry to SystemPreferencesType, and
+ * prefTimeZoneCountry to SystemPreferencesChoice.
+ * 08/08/00 CS Moved obsolete CountryPreferencesType to RezConvert.cp,
+ * since that's the only code that still needs access to
+ * this private, obsolete resource.
+ * 08/08/00 peter Added attentionFlags to SystemPreferencesType, and
+ * prefAttentionFlags to SystemPreferencesChoice.
+ * 11/07/00 grant Added button default assignment resource type.
+ *
+ *****************************************************************************/
+
+#ifndef __PREFERENCES_H__
+#define __PREFERENCES_H__
+
+#include <DateTime.h>
+#include <Localize.h>
+#include <SystemMgr.h>
+#include <LocaleMgr.h> // CountryType, kMaxCountryNameLen, etc.
+#include <AttentionMgr.h> // AttnFlagsType
+
+/***********************************************************************
+ * Constants
+ ***********************************************************************/
+
+#define noPreferenceFound -1
+
+// Preference version constants
+#define preferenceDataVer2 2 // Palm OS 2.0
+#define preferenceDataVer3 3 // Palm OS 3.0
+#define preferenceDataVer4 4 // Palm OS 3.1
+#define preferenceDataVer5 5 // Palm OS 3.2a
+#define preferenceDataVer6 6 // Palm OS 3.2b/3.3
+#define preferenceDataVer8 8 // Palm OS 3.5
+#define preferenceDataVer9 9 // Palm OS 4.0
+
+// Be SURE to update "preferenceDataVerLatest" when adding a new prefs version...
+#define preferenceDataVerLatest preferenceDataVer9
+
+
+#define defaultAutoOffDuration 2 // minutes
+#define defaultAutoOffDurationSecs (2 * minutesInSeconds) // seconds
+
+#define peggedAutoOffDuration 0xFF // minutes (UInt8)
+#define peggedAutoOffDurationSecs 0xFFFF // seconds (UInt16)
+
+#define defaultAutoLockType never //Never auto lock device
+#define defaultAutoLockTime 0
+#define defaultAutoLockTimeFlag 0
+
+// Obsolete after V20
+#if EMULATION_LEVEL == EMULATION_NONE
+ #define defaultSysSoundLevel slOn
+ #define defaultGameSoundLevel slOn
+ #define defaultAlarmSoundLevel slOn
+#else // EMULATION_LEVEL != EMULATION_NONE
+ #define defaultSysSoundLevel slOff
+ #define defaultGameSoundLevel slOff
+ #define defaultAlarmSoundLevel slOn
+#endif
+
+
+#if EMULATION_LEVEL == EMULATION_NONE
+ #define defaultSysSoundVolume sndMaxAmp
+ #define defaultGameSoundVolume sndMaxAmp
+ #define defaultAlarmSoundVolume sndMaxAmp
+#else // EMULATION_LEVEL != EMULATION_NONE
+ #define defaultSysSoundVolume 0
+ #define defaultGameSoundVolume 0
+ #define defaultAlarmSoundVolume sndMaxAmp
+#endif
+
+typedef enum
+ {
+ unitsEnglish = 0, // Feet, yards, miles, gallons, pounds, slugs, etc.
+ unitsMetric // Meters, liters, grams, newtons, etc.
+ } MeasurementSystemType;
+
+
+// These sound levels must corrospond to positions in the popup lists
+// used by the preferences app. These are made obsolete after V20. The
+// loudness of the sound is now represented as a number from 0 to sndMaxAmp.
+typedef enum {
+ slOn = 0,
+ slOff = 1
+ } SoundLevelTypeV20;
+
+// Device Automatic Locking options.
+typedef enum {
+ never = 0, //Auto-Lock disabled.
+ uponPowerOff, // Auto lock when the device powers off.
+ atPresetTime, //Auto lock at HH:MM every day.
+ afterPresetDelay //Auto lock after x minutes or hours.
+ } SecurityAutoLockType;
+
+
+// The number format (thousands separator and decimal point). This defines
+// how numbers are formatted and not neccessarily currency numbers (i.e. Switzerland).
+typedef enum {
+ alOff, // Never show an animation
+ alEventsOnly, // Show an animation for an event
+ alEventsAndRandom, // Also show random animation
+ alEventsAndMoreRandom // Show random animations more frequently
+ } AnimationLevelType;
+
+
+typedef enum
+ {
+ prefVersion,
+ prefCountry,
+ prefDateFormat,
+ prefLongDateFormat,
+ prefWeekStartDay,
+ prefTimeFormat,
+ prefNumberFormat,
+ prefAutoOffDuration, // prefAutoOffDurationSecs is now preferred (prefAutoOffDuration is in minutes)
+ prefSysSoundLevelV20, // slOn or slOff - error beeps and other non-alarm/game sounds
+ prefGameSoundLevelV20, // slOn or slOff - game sound effects
+ prefAlarmSoundLevelV20, // slOn or slOff - alarm sound effects
+ prefHidePrivateRecordsV33,
+ prefDeviceLocked,
+ prefLocalSyncRequiresPassword,
+ prefRemoteSyncRequiresPassword,
+ prefSysBatteryKind,
+ prefAllowEasterEggs,
+ prefMinutesWestOfGMT, // deprecated old unsigned minutes EAST of GMT
+ prefDaylightSavings, // deprecated old daylight saving time rule
+ prefRonamaticChar,
+ prefHard1CharAppCreator, // App creator for hard key #1
+ prefHard2CharAppCreator, // App creator for hard key #2
+ prefHard3CharAppCreator, // App creator for hard key #3
+ prefHard4CharAppCreator, // App creator for hard key #4
+ prefCalcCharAppCreator, // App creator for calculator soft key
+ prefHardCradleCharAppCreator, // App creator for hard cradle key
+ prefLauncherAppCreator, // App creator for launcher soft key
+ prefSysPrefFlags,
+ prefHardCradle2CharAppCreator, // App creator for 2nd hard cradle key
+ prefAnimationLevel,
+
+ // Additions for PalmOS 3.0:
+ prefSysSoundVolume, // actual amplitude - error beeps and other non-alarm/game sounds
+ prefGameSoundVolume, // actual amplitude - game sound effects
+ prefAlarmSoundVolume, // actual amplitude - alarm sound effects
+ prefBeamReceive, // not used - use ExgLibControl with ir(Get/Set)ScanningMode instead
+ prefCalibrateDigitizerAtReset, // True makes the user calibrate at soft reset time
+ prefSystemKeyboardID, // ID of the preferred keyboard resource
+ prefDefSerialPlugIn, // creator ID of the default serial plug-in
+
+ // Additions for PalmOS 3.1:
+ prefStayOnWhenPluggedIn, // don't sleep after timeout when using line current
+ prefStayLitWhenPluggedIn, // keep backlight on when not sleeping on line current
+
+ // Additions for PalmOS 3.2:
+ prefAntennaCharAppCreator, // App creator for antenna key
+
+ // Additions for PalmOS 3.3:
+ prefMeasurementSystem, // English, Metric, etc.
+
+ // Additions for PalmOS 3.5:
+ prefShowPrivateRecords, // returns privateRecordViewEnum
+ prefAutoOffDurationSecs, // auto-off duration in seconds
+
+ // Additions for PalmOS 4.0:
+ prefTimeZone, // GMT offset in minutes, + for east of GMT, - for west
+ prefDaylightSavingAdjustment, // current DST adjustment in minutes (typically 0 or 60)
+
+ prefAutoLockType, // Never, on poweroff, after preset delay or at preset time.
+ prefAutoLockTime, // Auto lock preset time or delay.
+ prefAutoLockTimeFlag, // For Minutes or Hours.
+
+ prefLanguage, // Language spoken in country selected via Setup app/Formats panel
+ prefLocale, // Locale for country selected via Setup app/Formats panel
+
+ prefTimeZoneCountry, // Country used to specify time zone.
+
+ prefAttentionFlags, // User prefs for getting user's attention
+
+ prefDefaultAppCreator // Default application launched on reset.
+
+ } SystemPreferencesChoice;
+
+
+typedef struct {
+ UInt16 version; // Version of preference info
+
+ // International preferences
+ CountryType country; // Country the device is in
+ DateFormatType dateFormat; // Format to display date in
+ DateFormatType longDateFormat; // Format to display date in
+ UInt8 weekStartDay; // Sunday or Monday
+ TimeFormatType timeFormat; // Format to display time in
+ NumberFormatType numberFormat; // Format to display numbers in
+
+ // system preferences
+ UInt8 autoOffDuration; // Time period before shutting off (in minutes)
+ SoundLevelTypeV20 sysSoundLevel; // slOn or slOff - error beeps and other non-alarm sounds
+ SoundLevelTypeV20 alarmSoundLevel; // slOn or slOff - alarm only
+ Boolean hideSecretRecords; // True to not display records with
+ // their secret bit attribute set
+ Boolean deviceLocked; // Device locked until the system
+ // password is entered
+ UInt8 reserved1;
+ UInt16 sysPrefFlags; // Miscellaneous system pref flags
+ // copied into the global GSysPrefFlags
+ // at boot time.
+ SysBatteryKind sysBatteryKind; // The type of batteries installed. This
+ // is copied into the globals GSysbatteryKind
+ // at boot time.
+ UInt8 reserved2;
+
+ } SystemPreferencesTypeV10;
+
+
+// Any entries added to this structure must be initialized in
+// Prefereces.c:GetPreferenceResource
+//
+// DOLATER CS - We should move SystemPreferencesType, SystemPreferencesTypeV10,
+// PrefGetPreferences, and PrefSetPreferences to a private header
+// file, since any code compiled against an old version of this
+// struct will trash memory when run on a version of the Palm OS
+// that makes the struct longer.
+
+typedef struct
+ {
+ UInt16 version; // Version of preference info
+
+ // International preferences
+ CountryType country; // Country the device is in (see PalmLocale.h)
+ DateFormatType dateFormat; // Format to display date in
+ DateFormatType longDateFormat; // Format to display date in
+ Int8 weekStartDay; // Sunday or Monday
+ TimeFormatType timeFormat; // Format to display time in
+ NumberFormatType numberFormat; // Format to display numbers in
+
+ // system preferences
+ UInt8 autoOffDuration; // Time period in minutes before shutting off (use autoOffDurationSecs instead).
+ SoundLevelTypeV20 sysSoundLevelV20; // slOn or slOff - error beeps and other non-alarm/game sounds
+ SoundLevelTypeV20 gameSoundLevelV20; // slOn or slOff - game sound effects
+ SoundLevelTypeV20 alarmSoundLevelV20; // slOn or slOff - alarm sound effects
+ Boolean hideSecretRecords; // True to not display records with
+ // their secret bit attribute set
+ Boolean deviceLocked; // Device locked until the system
+ // password is entered
+ Boolean localSyncRequiresPassword; // User must enter password on Pilot
+ Boolean remoteSyncRequiresPassword; // User must enter password on Pilot
+ UInt16 sysPrefFlags; // Miscellaneous system pref flags
+ // copied into the global GSysPrefFlags
+ // at boot time. Constants are
+ // sysPrefFlagXXX defined in SystemPrv.h
+ SysBatteryKind sysBatteryKind; // The type of batteries installed. This
+ // is copied into the globals GSysbatteryKind
+ // at boot time.
+ UInt8 reserved1;
+ UInt32 minutesWestOfGMT; // minutes west of Greenwich
+ DaylightSavingsTypes daylightSavings; // Type of daylight savings correction
+ UInt8 reserved2;
+ UInt16 ronamaticChar; // character to generate from ronamatic stroke.
+ // Typically it popups the onscreen keyboard.
+ UInt32 hard1CharAppCreator; // creator of application to launch in response
+ // to the hard button #1. Used by SysHandleEvent.
+ UInt32 hard2CharAppCreator; // creator of application to launch in response
+ // to the hard button #2. Used by SysHandleEvent.
+ UInt32 hard3CharAppCreator; // creator of application to launch in response
+ // to the hard button #3. Used by SysHandleEvent.
+ UInt32 hard4CharAppCreator; // creator of application to launch in response
+ // to the hard button #4. Used by SysHandleEvent.
+ UInt32 calcCharAppCreator; // creator of application to launch in response
+ // to the Calculator icon. Used by SysHandleEvent.
+ UInt32 hardCradleCharAppCreator; // creator of application to launch in response
+ // to the Cradle button. Used by SysHandleEvent.
+ UInt32 launcherCharAppCreator; // creator of application to launch in response
+ // to the launcher button. Used by SysHandleEvent.
+ UInt32 hardCradle2CharAppCreator; // creator of application to launch in response
+ // to the 2nd Cradle button. Used by SysHandleEvent.
+ AnimationLevelType animationLevel; // amount of animation to display
+
+ Boolean maskPrivateRecords; // Only meaningful if hideSecretRecords is true.
+ //true to show a grey placeholder box for secret records.
+ //was reserved3 - added for 3.5
+
+
+ // Additions for PalmOS 3.0:
+ UInt16 sysSoundVolume; // system amplitude (0 - sndMaxAmp) - taps, beeps
+ UInt16 gameSoundVolume; // game amplitude (0 - sndMaxAmp) - explosions
+ UInt16 alarmSoundVolume; // alarm amplitude (0 - sndMaxAmp)
+ Boolean beamReceive; // False turns off IR sniffing, sends still work.
+ Boolean calibrateDigitizerAtReset; // True makes the user calibrate at soft reset time
+ UInt16 systemKeyboardID; // ID of the preferred keyboard resource
+ UInt32 defSerialPlugIn; // creator ID of the default serial plug-in
+
+ // Additions for PalmOS 3.1:
+ Boolean stayOnWhenPluggedIn; // don't sleep after timeout when using line current
+ Boolean stayLitWhenPluggedIn; // keep backlight on when not sleeping on line current
+
+ // Additions for PalmOS 3.2:
+ UInt32 antennaCharAppCreator; // creator of application to launch in response
+ // to the antenna key. Used by SysHandleEvent.
+
+ // Additions for PalmOS 3.5:
+ MeasurementSystemType measurementSystem; // metric, english, etc.
+ UInt8 reserved3;
+ UInt16 autoOffDurationSecs; // Time period in seconds before shutting off.
+
+ // Additions for PalmOS 4.0:
+ Int16 timeZone; // minutes east of Greenwich
+ Int16 daylightSavingAdjustment; // current daylight saving correction in minutes
+ CountryType timeZoneCountry; // country used to specify time zone.
+ SecurityAutoLockType autoLockType; // Never, on power off, after preset delay or at preset time
+ UInt32 autoLockTime; // Auto lock preset time or delay.
+ Boolean autoLockTimeFlag; // For Minutes or Hours.
+ LanguageType language; // Language spoken in country selected via Setup app/Formats panel
+
+ AttnFlagsType attentionFlags; // User prefs for getting user's attention
+
+ UInt32 defaultAppCreator; // Creator of the default "safe" app that is launched
+ // on a reset.
+ } SystemPreferencesType;
+
+
+
+typedef SystemPreferencesType *SystemPreferencesPtr;
+
+
+// structure of the resource that holds hard/soft button defaults
+typedef struct {
+ UInt16 keyCode; // virtual key code of the hard/soft button
+ UInt32 creator; // app creator code
+} ButtonDefaultAppType;
+
+typedef struct {
+ UInt16 numButtons; // number of default button assignments
+ ButtonDefaultAppType button[1]; // array of button assignments
+} ButtonDefaultListType;
+
+
+//-------------------------------------------------------------------
+// Preferences routines
+//-------------------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern DmOpenRef PrefOpenPreferenceDBV10 (void)
+ SYS_TRAP(sysTrapPrefOpenPreferenceDBV10);
+
+extern DmOpenRef PrefOpenPreferenceDB (Boolean saved)
+ SYS_TRAP(sysTrapPrefOpenPreferenceDB);
+
+extern void PrefGetPreferences(SystemPreferencesPtr p)
+ SYS_TRAP(sysTrapPrefGetPreferences);
+
+extern void PrefSetPreferences(SystemPreferencesPtr p)
+ SYS_TRAP(sysTrapPrefSetPreferences);
+
+extern UInt32 PrefGetPreference(SystemPreferencesChoice choice)
+ SYS_TRAP(sysTrapPrefGetPreference);
+
+extern void PrefSetPreference(SystemPreferencesChoice choice, UInt32 value)
+ SYS_TRAP(sysTrapPrefSetPreference);
+
+extern Int16 PrefGetAppPreferences (UInt32 creator, UInt16 id, void *prefs,
+ UInt16 *prefsSize, Boolean saved)
+ SYS_TRAP(sysTrapPrefGetAppPreferences);
+
+extern Boolean PrefGetAppPreferencesV10 (UInt32 type, Int16 version, void *prefs,
+ UInt16 prefsSize)
+ SYS_TRAP(sysTrapPrefGetAppPreferencesV10);
+
+extern void PrefSetAppPreferences (UInt32 creator, UInt16 id, Int16 version,
+ const void *prefs, UInt16 prefsSize, Boolean saved)
+ SYS_TRAP(sysTrapPrefSetAppPreferences);
+
+extern void PrefSetAppPreferencesV10 (UInt32 creator, Int16 version, void *prefs,
+ UInt16 prefsSize)
+ SYS_TRAP(sysTrapPrefSetAppPreferencesV10);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __PREFERENCES_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Rect.h b/SrcShared/Palm/Platform/Incs/Core/System/Rect.h
new file mode 100644
index 0000000..40cd3b7
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Rect.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Rect.h
+ *
+ * Description:
+ * This file defines rectangle structures and routines.
+ *
+ * History:
+ * November 3, 1994 Created by Roger Flores
+ * Name Date Description
+ * ---- ---- -----------
+ * bob 2/9/99 Use Coord abstraction, fix up consts
+ *
+ *****************************************************************************/
+
+#ifndef __RECT_H__
+#define __RECT_H__
+
+// Include elementary types
+#include <PalmTypes.h> // Basic types
+#include <CoreTraps.h> // Trap Numbers.
+
+
+typedef struct AbsRectType {
+ Coord left;
+ Coord top;
+ Coord right;
+ Coord bottom;
+} AbsRectType;
+
+
+typedef struct PointType {
+ Coord x;
+ Coord y;
+} PointType;
+
+
+typedef struct RectangleType {
+ PointType topLeft;
+ PointType extent;
+} RectangleType;
+
+typedef RectangleType *RectanglePtr;
+
+
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void RctSetRectangle (RectangleType *rP,
+ Coord left, Coord top, Coord width, Coord height)
+ SYS_TRAP(sysTrapRctSetRectangle);
+
+extern void RctCopyRectangle (const RectangleType *srcRectP,
+ RectangleType *dstRectP)
+ SYS_TRAP(sysTrapRctCopyRectangle);
+
+extern void RctInsetRectangle (RectangleType *rP, Coord insetAmt)
+ SYS_TRAP(sysTrapRctInsetRectangle);
+
+extern void RctOffsetRectangle (RectangleType *rP, Coord deltaX, Coord deltaY)
+ SYS_TRAP(sysTrapRctOffsetRectangle);
+
+extern Boolean RctPtInRectangle (Coord x, Coord y, const RectangleType *rP)
+ SYS_TRAP(sysTrapRctPtInRectangle);
+
+extern void RctGetIntersection (const RectangleType *r1P, const RectangleType *r2P,
+ RectangleType *r3P)
+ SYS_TRAP(sysTrapRctGetIntersection);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__RECT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SerialLinkMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/SerialLinkMgr.h
new file mode 100644
index 0000000..7142309
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SerialLinkMgr.h
@@ -0,0 +1,437 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SerialLinkMgr.h
+ *
+ * Description:
+ * Source for Serial Link Routines on Pilot
+ *
+ * History:
+ * 2/6/95 replaces DSerial.h from Debugger
+ *
+ *****************************************************************************/
+
+#ifndef __SERIAL_LINK_H
+#define __SERIAL_LINK_H
+
+
+
+// Pilot common definitions
+#include <PalmTypes.h>
+#include <ErrorBase.h>
+
+
+//*************************************************************************
+// Pre-defined, fixxed Socket ID's
+//*************************************************************************
+#define slkSocketDebugger 0 // Debugger Socket
+#define slkSocketConsole 1 // Console Socket
+#define slkSocketRemoteUI 2 // Remote UI Socket
+#define slkSocketDLP 3 // Desktop Link Socket
+#define slkSocketFirstDynamic 4 // first dynamic socket ID
+
+
+//*************************************************************************
+// Packet Types
+//*************************************************************************
+#define slkPktTypeSystem 0 // System packets
+#define slkPktTypeUnused1 1 // used to be: Connection Manager packets
+#define slkPktTypePAD 2 // PAD Protocol packets
+#define slkPktTypeLoopBackTest 3 // Loop-back test packets
+
+
+
+//*************************************************************************
+//
+// Packet structure:
+// header
+// body (0-dbgMaxPacketBodyLength bytes of data)
+// footer
+//
+//*************************************************************************
+
+//----------------------------------------------------------------------
+// packet header
+// Fields marked with -> must be filled in by caller
+// Fields marked with X will be filled in by SlkSendPacket.
+//----------------------------------------------------------------------
+
+typedef UInt8 SlkPktHeaderChecksum;
+
+typedef struct SlkPktHeaderType {
+ UInt16 signature1; // X first 2 bytes of signature
+ UInt8 signature2; // X 3 and final byte of signature
+ UInt8 dest; // -> destination socket Id
+ UInt8 src; // -> src socket Id
+ UInt8 type; // -> packet type
+ UInt16 bodySize; // X size of body
+ UInt8 transId; // -> transaction Id
+ // if 0 specified, it will be replaced
+ SlkPktHeaderChecksum checksum; // X check sum of header
+ } SlkPktHeaderType;
+
+typedef SlkPktHeaderType* SlkPktHeaderPtr;
+
+#define slkPktHeaderSignature1 0xBEEF
+#define slkPktHeaderSignature2 0xED
+
+#define slkPktHeaderSigFirst 0xBE // First byte
+#define slkPktHeaderSigSecond 0xEF // second byte
+#define slkPktHeaderSigThird 0xED // third byte
+
+//----------------------------------------------------------------------
+// packet footer
+//----------------------------------------------------------------------
+typedef struct SlkPktFooterType {
+ UInt16 crc16; // header and body crc
+ } SlkPktFooterType;
+
+typedef SlkPktFooterType* SlkPktFooterPtr;
+
+
+//*************************************************************************
+//
+// Write Data Structure passed to SlkSendPacket. This structure
+// Tells SlkSendPacket where each of the chunks that comprise the body are
+// and the size of each. SlkSendPacket accepts a pointer to an array
+// of SlkWriteDataTypes, the last one has a size field of 0.
+//
+//*************************************************************************
+typedef struct SlkWriteDataType {
+ UInt16 size; // last one has size of 0
+ void* dataP; // pointer to data
+ } SlkWriteDataType;
+typedef SlkWriteDataType* SlkWriteDataPtr;
+
+
+
+
+//*************************************************************************
+//
+// CPU-dependent macros for getting/setting values from/to packets
+//
+//*************************************************************************
+
+//--------------------------------------------------------------------
+// macros to get packet values
+//--------------------------------------------------------------------
+
+#define slkGetPacketByteVal(srcP) (*(UInt8 *)(srcP))
+
+
+#if (CPU_TYPE == CPU_x86)
+#define slkGetPacketWordVal(srcP) \
+ ( (UInt16) \
+ ( \
+ ((UInt16)((UInt8 *)(srcP))[0] << 8) | \
+ ((UInt16)((UInt8 *)(srcP))[1]) \
+ ) \
+ )
+#else
+#define slkGetPacketWordVal(srcP) \
+ ( *((UInt16 *)(srcP)) )
+#endif //CPU_TYPE == CPU_x86
+
+
+#if (CPU_TYPE == CPU_x86)
+#define slkGetPacketDWordVal(srcP) \
+ ( (UInt32) \
+ ( \
+ ((UInt32)((UInt8 *)(srcP))[0] << 24) | \
+ ((UInt32)((UInt8 *)(srcP))[1] << 16) | \
+ ((UInt32)((UInt8 *)(srcP))[2] << 8) | \
+ ((UInt32)((UInt8 *)(srcP))[3]) \
+ ) \
+ )
+#else
+#define slkGetPacketDWordVal(srcP) \
+ ( *((UInt32 *)(srcP)) )
+#endif //CPU_TYPE == CPU_x86
+
+
+#define slkGetPacketSignature1(sigP) \
+ slkGetPacketWordVal(sigP)
+
+#define slkGetPacketSignature2(sigP) \
+ slkGetPacketByteVal(sigP)
+
+
+#define slkGetPacketDest(addressP) \
+ slkGetPacketByteVal(addressP)
+
+#define slkGetPacketSrc(addressP) \
+ slkGetPacketByteVal(addressP)
+
+#define slkGetPacketType(commandP) \
+ slkGetPacketByteVal(commandP)
+
+
+#define slkGetPacketBodySize(lengthP) \
+ slkGetPacketWordVal(lengthP)
+
+#define slkGetPacketTransId(transIDP) \
+ slkGetPacketByteVal(transIDP)
+
+#define slkGetPacketHdrChecksum(checksumP) \
+ slkGetPacketByteVal(checksumP)
+
+
+#define slkGetPacketTotalChecksum(checksumP) \
+ slkGetPacketWordVal(checksumP)
+
+
+
+
+
+
+//--------------------------------------------------------------------
+// macros to set packet values
+//--------------------------------------------------------------------
+
+
+#define slkSetPacketByteVal(srcByteVal, destP) \
+ ( *(UInt8 *)(destP) = (UInt8)(srcByteVal) )
+
+#if (CPU_TYPE == CPU_x86)
+#define slkSetPacketWordVal(srcWordVal, destP) \
+ \
+ do { \
+ UInt16 ___srcVal; \
+ UInt8 * ___srcValP; \
+ \
+ ___srcVal = (UInt16)(srcWordVal); \
+ ___srcValP = (UInt8 *)(&___srcVal); \
+ \
+ ((UInt8 *)(destP))[0] = ___srcValP[1]; \
+ ((UInt8 *)(destP))[1] = ___srcValP[0]; \
+ } while( false )
+#else
+#define slkSetPacketWordVal(srcWordVal, destP) \
+ ( *((UInt16 *)(destP)) = (UInt16)(srcWordVal) )
+#endif //CPU_TYPE == CPU_x86
+
+
+#if (CPU_TYPE == CPU_x86)
+#define slkSetPacketDWordVal(srcDWordVal, destP) \
+ do { \
+ UInt32 ___srcVal; \
+ UInt8 * ___srcValP; \
+ \
+ ___srcVal = (UInt32)(srcDWordVal); \
+ ___srcValP = (UInt8 *)(&___srcVal); \
+ \
+ ((UInt8 *)(destP))[0] = ___srcValP[3]; \
+ ((UInt8 *)(destP))[1] = ___srcValP[2]; \
+ ((UInt8 *)(destP))[2] = ___srcValP[1]; \
+ ((UInt8 *)(destP))[3] = ___srcValP[0]; \
+ } while( false )
+#else
+#define slkSetPacketDWordVal(srcDWordVal, destP) \
+ ( *((UInt32 *)(destP)) = (UInt32)(srcDWordVal) )
+#endif //CPU_TYPE == CPU_x86
+
+
+
+#define slkSetPacketSignature1(magic, destP) \
+ slkSetPacketWordVal(magic, destP)
+
+#define slkSetPacketSignature2(magic, destP) \
+ slkSetPacketByteVal(magic, destP)
+
+
+#define slkSetPacketDest(dest, destP) \
+ slkSetPacketByteVal(dest, destP)
+
+#define slkSetPacketSrc(src, destP) \
+ slkSetPacketByteVal(src, destP)
+
+
+#define slkSetPacketType(type, destP) \
+ slkSetPacketByteVal(type, destP)
+
+
+#define slkSetPacketBodySize(numBytes, destP) \
+ slkSetPacketWordVal(numBytes, destP)
+
+
+#define slkSetPacketTransId(transID, destP) \
+ slkSetPacketByteVal(transID, destP)
+
+#define slkSetPacketHdrChecksum(checksum, destP) \
+ slkSetPacketByteVal(checksum, destP)
+
+#define slkSetPacketTotalChecksum(checksum, destP) \
+ slkSetPacketWordVal(checksum, destP)
+
+
+
+
+
+
+/*******************************************************************
+ * Serial Link Manager Errors
+ * the constant slkErrorClass is defined in SystemMgr.h
+ *******************************************************************/
+#define slkErrChecksum (slkErrorClass | 1)
+#define slkErrFormat (slkErrorClass | 2)
+#define slkErrBuffer (slkErrorClass | 3)
+#define slkErrTimeOut (slkErrorClass | 4)
+#define slkErrHandle (slkErrorClass | 5)
+#define slkErrBodyLimit (slkErrorClass | 6)
+#define slkErrTransId (slkErrorClass | 7)
+#define slkErrResponse (slkErrorClass | 8)
+#define slkErrNoDefaultProc (slkErrorClass | 9)
+#define slkErrWrongPacketType (slkErrorClass | 10)
+#define slkErrBadParam (slkErrorClass | 11)
+#define slkErrAlreadyOpen (slkErrorClass | 12)
+#define slkErrOutOfSockets (slkErrorClass | 13)
+#define slkErrSocketNotOpen (slkErrorClass | 14)
+#define slkErrWrongDestSocket (slkErrorClass | 15)
+#define slkErrWrongPktType (slkErrorClass | 16)
+#define slkErrBusy (slkErrorClass | 17) // called while sending a packet
+ // only returned on single-threaded
+ // emulation implementations
+#define slkErrNotOpen (slkErrorClass | 18)
+
+
+
+/*******************************************************************
+ * Type definition for a Serial Link Socket Listener
+ *
+ *******************************************************************/
+typedef void (*SlkSocketListenerProcPtr)
+ (SlkPktHeaderPtr headerP, void *bodyP);
+
+typedef struct SlkSocketListenType {
+ SlkSocketListenerProcPtr listenerP;
+ SlkPktHeaderPtr headerBufferP; // App allocated buffer for header
+ void* bodyBufferP; // App allocated buffer for body
+ UInt32 bodyBufferSize;
+ } SlkSocketListenType;
+typedef SlkSocketListenType* SlkSocketListenPtr;
+
+
+
+/*******************************************************************
+ * Prototypes
+ *******************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//-------------------------------------------------------------------
+// Initializes the Serial Link Manager
+//-------------------------------------------------------------------
+Err SlkOpen(void)
+ SYS_TRAP(sysTrapSlkOpen);
+
+//-------------------------------------------------------------------
+// Close down the Serial Link Manager
+//-------------------------------------------------------------------
+Err SlkClose(void)
+ SYS_TRAP(sysTrapSlkClose);
+
+
+
+
+//-------------------------------------------------------------------
+// Open up another Serial Link socket. The caller must have already
+// opened the comm library and set it to the right settings.
+//-------------------------------------------------------------------
+
+Err SlkOpenSocket(UInt16 portID, UInt16 *socketP, Boolean staticSocket)
+ SYS_TRAP(sysTrapSlkOpenSocket);
+
+
+//-------------------------------------------------------------------
+// Close up a Serial Link socket.
+// Warning: This routine is assymetrical with SlkOpenSocket because it
+// WILL CLOSE the library for the caller (unless the refNum is the
+// refNum of the debugger comm library).
+//-------------------------------------------------------------------
+Err SlkCloseSocket(UInt16 socket)
+ SYS_TRAP(sysTrapSlkCloseSocket);
+
+
+//-------------------------------------------------------------------
+// Get the library refNum for a particular Socket
+//-------------------------------------------------------------------
+
+
+ Err SlkSocketPortID(UInt16 socket, UInt16 *portIDP)
+ SYS_TRAP(sysTrapSlkSocketRefNum);
+
+ #define SlkSocketRefNum SlkSocketPortID
+
+
+//-------------------------------------------------------------------
+// Set the in-packet timeout for a socket
+//-------------------------------------------------------------------
+Err SlkSocketSetTimeout(UInt16 socket, Int32 timeout)
+ SYS_TRAP(sysTrapSlkSocketSetTimeout);
+
+
+
+
+
+//-------------------------------------------------------------------
+// Flush a Socket
+//-------------------------------------------------------------------
+Err SlkFlushSocket(UInt16 socket, Int32 timeout)
+ SYS_TRAP(sysTrapSlkFlushSocket);
+
+
+//-------------------------------------------------------------------
+// Set up a Socket Listener
+//-------------------------------------------------------------------
+Err SlkSetSocketListener(UInt16 socket, SlkSocketListenPtr socketP)
+ SYS_TRAP(sysTrapSlkSetSocketListener);
+
+
+//-------------------------------------------------------------------
+// Sends a packet's header, body, footer. Stuffs the header's
+// magic number and checksum fields. Expects all other
+// header fields to be filled in by caller.
+// errors returned: dseHandle, dseLine, dseIO, dseParam, dseBodyLimit,
+// dseOther
+//-------------------------------------------------------------------
+Err SlkSendPacket(SlkPktHeaderPtr headerP, SlkWriteDataPtr writeList)
+ SYS_TRAP(sysTrapSlkSendPacket);
+
+
+//-------------------------------------------------------------------
+// Receives and validates an entire packet.
+// errors returned: dseHandle, dseParam, dseLine, dseIO, dseFormat,
+// dseChecksum, dseBuffer, dseBodyLimit, dseTimeOut,
+// dseOther
+//-------------------------------------------------------------------
+Err SlkReceivePacket( UInt16 socket, Boolean andOtherSockets,
+ SlkPktHeaderPtr headerP, void *bodyP, UInt16 bodySize,
+ Int32 timeout)
+ SYS_TRAP(sysTrapSlkReceivePacket);
+
+
+//-------------------------------------------------------------------
+// Do Default processing of a System packet
+//-------------------------------------------------------------------
+Err SlkSysPktDefaultResponse(SlkPktHeaderPtr headerP, void *bodyP)
+ SYS_TRAP(sysTrapSlkSysPktDefaultResponse);
+
+//-------------------------------------------------------------------
+// Do RPC call
+//-------------------------------------------------------------------
+Err SlkProcessRPC(SlkPktHeaderPtr headerP, void *bodyP)
+ SYS_TRAP(sysTrapSlkProcessRPC);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__SERIAL_LINK_H
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SerialMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/SerialMgr.h
new file mode 100644
index 0000000..d59687f
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SerialMgr.h
@@ -0,0 +1,371 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SerialMgr.h
+ *
+ * Description:
+ * Include file for Serial manager
+ *
+ * History:
+ * 1/14/98 SerialMgr.h created by Ben Manuto
+ *
+ *****************************************************************************/
+
+#ifndef __SERIALMGR_H
+#define __SERIALMGR_H
+
+
+// Pilot common definitions
+#include <PalmTypes.h>
+#include <ErrorBase.h>
+
+// New Serial manager feature number
+#define sysFtrNewSerialPresent 1
+
+/********************************************************************
+ * Serial Manager Errors
+ * the constant serErrorClass is defined in SystemMgr.h
+ ********************************************************************/
+
+#define serErrBadParam (serErrorClass | 1)
+#define serErrBadPort (serErrorClass | 2)
+#define serErrNoMem (serErrorClass | 3)
+#define serErrBadConnID (serErrorClass | 4)
+#define serErrTimeOut (serErrorClass | 5)
+#define serErrLineErr (serErrorClass | 6)
+#define serErrAlreadyOpen (serErrorClass | 7)
+#define serErrStillOpen (serErrorClass | 8)
+#define serErrNotOpen (serErrorClass | 9)
+#define serErrNotSupported (serErrorClass | 10) // functionality not supported
+#define serErrNoDevicesAvail (serErrorClass | 11) // No serial devices were loaded or are available.
+
+
+//
+// mask values for the lineErrors from SerGetStatus
+//
+
+#define serLineErrorParity 0x0001 // parity error
+#define serLineErrorHWOverrun 0x0002 // HW overrun
+#define serLineErrorFraming 0x0004 // framing error
+#define serLineErrorBreak 0x0008 // break signal asserted
+#define serLineErrorHShake 0x0010 // line hand-shake error
+#define serLineErrorSWOverrun 0x0020 // HW overrun
+#define serLineErrorCarrierLost 0x0040 // CD dropped
+
+
+/********************************************************************
+ * Serial Port Definitions
+ ********************************************************************/
+
+#define serPortLocalHotSync 0x8000 // Use physical HotSync port
+
+#define serPortCradlePort 0x8000 // Use the RS-232 cradle port.
+#define serPortIrPort 0x8001 // Use available IR port.
+
+
+// This constant is used by the Serial Link Mgr only
+#define serPortIDMask 0xC000
+
+
+/********************************************************************
+ * Serial Settings Descriptor
+ ********************************************************************/
+
+#define srmSettingsFlagStopBitsM 0x00000001 // mask for stop bits field
+#define srmSettingsFlagStopBits1 0x00000000 // 1 stop bits
+#define srmSettingsFlagStopBits2 0x00000001 // 2 stop bits
+#define srmSettingsFlagParityOnM 0x00000002 // mask for parity on
+#define srmSettingsFlagParityEvenM 0x00000004 // mask for parity even
+#define srmSettingsFlagXonXoffM 0x00000008 // (NOT IMPLEMENTED) mask for Xon/Xoff flow control
+#define srmSettingsFlagRTSAutoM 0x00000010 // mask for RTS rcv flow control
+#define srmSettingsFlagCTSAutoM 0x00000020 // mask for CTS xmit flow control
+#define srmSettingsFlagBitsPerCharM 0x000000C0 // mask for bits/char
+#define srmSettingsFlagBitsPerChar5 0x00000000 // 5 bits/char
+#define srmSettingsFlagBitsPerChar6 0x00000040 // 6 bits/char
+#define srmSettingsFlagBitsPerChar7 0x00000080 // 7 bits/char
+#define srmSettingsFlagBitsPerChar8 0x000000C0 // 8 bits/char
+#define srmSettingsFlagFlowControl 0x00000100 // mask for enabling/disabling special flow control feature
+ // for the software receive buffer.
+
+
+// Default settings
+#define srmDefaultSettings (srmSettingsFlagBitsPerChar8 | \
+ srmSettingsFlagStopBits1 | \
+ srmSettingsFlagRTSAutoM)
+
+#define srmDefaultCTSTimeout (5*sysTicksPerSecond)
+
+
+// Status bitfield constants
+
+#define srmStatusCtsOn 0x00000001
+#define srmStatusRtsOn 0x00000002
+#define srmStatusDsrOn 0x00000004
+#define srmStatusBreakSigOn 0x00000008
+
+
+//
+// Info fields describing serial HW capabilities.
+//
+
+#define serDevCradlePort 0x00000001 // Serial HW controls RS-232 serial from cradle connector of Pilot.
+#define serDevRS232Serial 0x00000002 // Serial HW has RS-232 line drivers
+#define serDevIRDACapable 0x00000004 // Serial Device has IR line drivers and generates IRDA mode serial.
+#define serDevModemPort 0x00000008 // Serial deivce drives modem connection.
+#define serDevCncMgrVisible 0x00000010 // Serial device port name string to be displayed in Connection Mgr panel.
+
+
+typedef struct DeviceInfoType {
+ UInt32 serDevCreator; // Four Character creator type for serial driver ('sdrv')
+ UInt32 serDevFtrInfo; // Flags defining features of this serial hardware.
+ UInt32 serDevMaxBaudRate; // Maximum baud rate for this device.
+ UInt32 serDevHandshakeBaud; // HW Handshaking is reccomended for baud rates over this
+ Char *serDevPortInfoStr; // Description of serial HW device or virtual device.
+ UInt8 reserved[8]; // Reserved.
+} DeviceInfoType;
+
+typedef DeviceInfoType *DeviceInfoPtr;
+
+
+/********************************************************************
+ * Type of a wakeup handler procedure which can be installed through the
+ * SerSetWakeupHandler() call.
+ ********************************************************************/
+typedef void (*WakeupHandlerProcPtr)(UInt32 refCon);
+
+/********************************************************************
+ * Type of an emulator-mode only blocking hook routine installed via
+ * SerControl function serCtlEmuSetBlockingHook. This is supported only
+ * under emulation mode. The argument to the function is the value
+ * specified in the SerCallbackEntryType structure. The intention of the
+ * return value is to return false if serial manager should abort the
+ * current blocking action, such as when an app quit event has been received;
+ * otherwise, it should return true. However, in the current implementation,
+ * this return value is ignored. The callback can additionally process
+ * events to enable user interaction with the UI, such as interacting with the
+ * debugger.
+ ********************************************************************/
+typedef Boolean (*BlockingHookProcPtr) (UInt32 userRef);
+
+
+/********************************************************************
+ * Serial Library Control Enumerations (Pilot 2.0)
+ ********************************************************************/
+
+/********************************************************************
+ * Structure for specifying callback routines.
+ ********************************************************************/
+typedef struct SrmCallbackEntryType {
+ BlockingHookProcPtr funcP; // function pointer
+ UInt32 userRef; // ref value to pass to callback
+} SrmCallbackEntryType;
+typedef SrmCallbackEntryType* SrmCallbackEntryPtr;
+
+
+typedef enum SrmCtlEnum {
+ srmCtlFirstReserved = 0, // RESERVE 0
+
+ srmCtlSetBaudRate, // Sets the current baud rate for the HW.
+ // valueP = MemPtr to Int32, valueLenP = MemPtr to sizeof(Int32)
+
+ srmCtlGetBaudRate, // Gets the current baud rate for the HW.
+
+ srmCtlSetFlags, // Sets the current flag settings for the serial HW.
+
+ srmCtlGetFlags, // Gets the current flag settings the serial HW.
+
+ srmCtlSetCtsTimeout, // Sets the current Cts timeout value.
+
+ srmCtlGetCtsTimeout, // Gets the current Cts timeout value.
+
+ srmCtlStartBreak, // turn RS232 break signal on:
+ // users are responsible for ensuring that the break is set
+ // long enough to genearate a valid BREAK!
+ // valueP = 0, valueLenP = 0
+
+ srmCtlStopBreak, // turn RS232 break signal off:
+ // valueP = 0, valueLenP = 0
+
+ srmCtlStartLocalLoopback, // Start local loopback test
+ // valueP = 0, valueLenP = 0
+
+ srmCtlStopLocalLoopback, // Stop local loopback test
+ // valueP = 0, valueLenP = 0
+
+
+ srmCtlIrDAEnable, // Enable IrDA connection on this serial port
+ // valueP = 0, valueLenP = 0
+
+ srmCtlIrDADisable, // Disable IrDA connection on this serial port
+ // valueP = 0, valueLenP = 0
+
+ srmCtlRxEnable, // enable receiver ( for IrDA )
+
+ srmCtlRxDisable, // disable receiver ( for IrDA )
+
+ srmCtlEmuSetBlockingHook, // Set a blocking hook routine FOR EMULATION
+ // MODE ONLY - NOT SUPPORTED ON THE PILOT
+ //PASS:
+ // valueP = MemPtr to SerCallbackEntryType
+ // *valueLenP = sizeof(SerCallbackEntryType)
+ //RETURNS:
+ // the old settings in the first argument
+
+ srmCtlUserDef, // Specifying this opCode passes through a user-defined
+ // function to the DrvControl function. This is for use
+ // specifically by serial driver developers who need info
+ // from the serial driver that may not be available through the
+ // standard SrmMgr interface.
+
+ srmCtlGetOptimalTransmitSize, // This function will ask the port for the most efficient buffer size
+ // for transmitting data packets. This opCode returns serErrNotSupported
+ // if the physical or virtual device does not support this feature.
+ // The device can return a transmit size of 0, if send buffering is
+ // requested, but the actual size is up to the caller to choose.
+ // valueP = MemPtr to UInt32 --> return optimal buf size
+ // ValueLenP = sizeof(UInt32)
+
+ srmCtlSetDTRAsserted, // Enable or disable DTR.
+
+ srmCtlGetDTRAsserted, // Determine if DTR is enabled or disabled.
+
+ srmCtlLAST // ***** ADD NEW ENTRIES BEFORE THIS ONE
+
+} SrmCtlEnum;
+
+
+
+/********************************************************************
+ * Serial Hardware Library Routines
+ ********************************************************************/
+
+#ifdef BUILDING_NEW_SERIAL_MGR
+ #define SERIAL_TRAP(serialSelectorNum)
+#else
+ #define SERIAL_TRAP(serialSelectorNum) \
+ _SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, sysTrapSerialDispatch, \
+ serialSelectorNum)
+#endif
+
+
+// *****************************************************************
+// * New Serial Manager trap selectors
+// *****************************************************************
+
+typedef enum { // The order of this enum *MUST* match the sysSerialSelector in SerialMgr.c
+ sysSerialInstall = 0,
+ sysSerialOpen,
+ sysSerialOpenBkgnd,
+ sysSerialClose,
+ sysSerialSleep,
+ sysSerialWake,
+ sysSerialGetDeviceCount,
+ sysSerialGetDeviceInfo,
+ sysSerialGetStatus,
+ sysSerialClearErr,
+ sysSerialControl,
+ sysSerialSend,
+ sysSerialSendWait,
+ sysSerialSendCheck,
+ sysSerialSendFlush,
+ sysSerialReceive,
+ sysSerialReceiveWait,
+ sysSerialReceiveCheck,
+ sysSerialReceiveFlush,
+ sysSerialSetRcvBuffer,
+ sysSerialRcvWindowOpen,
+ sysSerialRcvWindowClose,
+ sysSerialSetWakeupHandler,
+ sysSerialPrimeWakeupHandler,
+
+ maxSerialSelector = sysSerialPrimeWakeupHandler // Used by SerialMgrDispatch.c
+} sysSerialSelector;
+
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Err SerialMgrInstall(void)
+ SERIAL_TRAP(sysSerialInstall);
+
+Err SrmOpen(UInt32 port, UInt32 baud, UInt16 *newPortIdP)
+ SERIAL_TRAP(sysSerialOpen);
+
+Err SrmOpenBackground(UInt32 port, UInt32 baud, UInt16 *newPortIdP)
+ SERIAL_TRAP(sysSerialOpenBkgnd);
+
+Err SrmClose(UInt16 portId)
+ SERIAL_TRAP(sysSerialClose);
+
+Err SrmSleep()
+ SERIAL_TRAP(sysSerialSleep);
+
+Err SrmWake()
+ SERIAL_TRAP(sysSerialWake);
+
+Err SrmGetDeviceCount(UInt16 *numOfDevicesP)
+ SERIAL_TRAP(sysSerialGetDeviceCount);
+
+Err SrmGetDeviceInfo(UInt32 deviceID, DeviceInfoType *deviceInfoP)
+ SERIAL_TRAP(sysSerialGetDeviceInfo);
+
+Err SrmGetStatus(UInt16 portId, UInt32 *statusFieldP, UInt16 *lineErrsP)
+ SERIAL_TRAP(sysSerialGetStatus);
+
+Err SrmClearErr (UInt16 portId)
+ SERIAL_TRAP(sysSerialClearErr);
+
+Err SrmControl(UInt16 portId, UInt16 op, void *valueP, UInt16 *valueLenP)
+ SERIAL_TRAP(sysSerialControl);
+
+UInt32 SrmSend (UInt16 portId, void *bufP, UInt32 count, Err *errP)
+ SERIAL_TRAP(sysSerialSend);
+
+Err SrmSendWait(UInt16 portId)
+ SERIAL_TRAP(sysSerialSendWait);
+
+Err SrmSendCheck(UInt16 portId, UInt32 *numBytesP)
+ SERIAL_TRAP(sysSerialSendCheck);
+
+Err SrmSendFlush(UInt16 portId)
+ SERIAL_TRAP(sysSerialSendFlush);
+
+UInt32 SrmReceive(UInt16 portId, void *rcvBufP, UInt32 count, Int32 timeout, Err *errP)
+ SERIAL_TRAP(sysSerialReceive);
+
+Err SrmReceiveWait(UInt16 portId, UInt32 bytes, Int32 timeout)
+ SERIAL_TRAP(sysSerialReceiveWait);
+
+Err SrmReceiveCheck(UInt16 portId, UInt32 *numBytesP)
+ SERIAL_TRAP(sysSerialReceiveCheck);
+
+Err SrmReceiveFlush(UInt16 portId, Int32 timeout)
+ SERIAL_TRAP(sysSerialReceiveFlush);
+
+Err SrmSetReceiveBuffer(UInt16 portId, void *bufP, UInt16 bufSize)
+ SERIAL_TRAP(sysSerialSetRcvBuffer);
+
+Err SrmReceiveWindowOpen(UInt16 portId, UInt8 **bufPP, UInt32 *sizeP)
+ SERIAL_TRAP(sysSerialRcvWindowOpen);
+
+Err SrmReceiveWindowClose(UInt16 portId, UInt32 bytesPulled)
+ SERIAL_TRAP(sysSerialRcvWindowClose);
+
+Err SrmSetWakeupHandler(UInt16 portId, WakeupHandlerProcPtr procP, UInt32 refCon)
+ SERIAL_TRAP(sysSerialSetWakeupHandler);
+
+Err SrmPrimeWakeupHandler(UInt16 portId, UInt16 minBytes)
+ SERIAL_TRAP(sysSerialPrimeWakeupHandler);
+
+void SrmSelectorErrPrv (UInt16 serialSelector); // used only by SerialMgrDispatch.c
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __SERIALMGR_H
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SoundMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/SoundMgr.h
new file mode 100644
index 0000000..25a7d15
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SoundMgr.h
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SoundMgr.h
+ *
+ * Description:
+ * Include file for Sound Manager
+ *
+ * History:
+ * 4/11/95 VMK - Created by Vitaly Kruglikov
+ *
+ *****************************************************************************/
+
+#ifndef __SOUNDMGR_H__
+#define __SOUNDMGR_H__
+
+
+// Include elementary types
+#include <PalmTypes.h>
+#include <CoreTraps.h> // Trap Numbers.
+
+#include <Preferences.h>
+
+
+/************************************************************
+ * Sound Manager constants
+ *
+ *************************************************************/
+
+// Sound Manager max and default volume levels
+#define sndMaxAmp 64
+//#define sndVolumeMask 0x0ff
+#define sndDefaultAmp sndMaxAmp
+
+#define sndMidiNameLength 32 // MIDI track name length *including* NULL terminator
+
+
+/************************************************************
+ * Sound Manager data structures
+ *
+ *************************************************************/
+
+//
+// Command numbers for SndCommandType's cmd field
+//
+typedef enum SndCmdIDType {
+
+ sndCmdFreqDurationAmp = 1, // play a sound, blocking for the entire duration (except for zero amplitude)
+ // param1 = frequency in Hz
+ // param2 = duration in milliseconds
+ // param3 = amplitude (0 - sndMaxAmp); if 0, will return immediately
+
+ // Commands added in PilotOS v3.0
+ // ***IMPORTANT***
+ // Please note that SndDoCmd() in PilotOS before v3.0 will Fatal Error on unknown
+ // commands (anything other than sndCmdFreqDurationAmp). For this reason,
+ // applications wishing to take advantage of these new commands while staying
+ // compatible with the earlier version of the OS, _must_ avoid using these commands
+ // when running on OS versions less thatn v3.0 (see sysFtrNumROMVersion in SystemMgr.h).
+ // Beginning with v3.0, SndDoCmd has been fixed to return sndErrBadParam when an
+ // unknown command is passed.
+ //
+ sndCmdNoteOn, // start a sound given its MIDI key index, max duration and velocity;
+ // the call will not wait for the sound to complete, returning imeediately;
+ // any other sound play request made before this one completes will interrupt it.
+ // param1 = MIDI key index (0-127)
+ // param2 = maximum duration in milliseconds
+ // param3 = velocity (0 - 127) (will be interpolated as amplitude)
+
+ sndCmdFrqOn, // start a sound given its frequency in Hz, max duration and amplitude;
+ // the call will not wait for the sound to complete, returning imeediately;
+ // any other sound play request made before this one completes will interrupt it.
+ // param1 = frequency in Hz
+ // param2 = maximum duration in milliseconds
+ // param3 = amplitude (0 - sndMaxAmp)
+
+ sndCmdQuiet // stop current sound
+ // param1 = 0
+ // param2 = 0
+ // param3 = 0
+
+ } SndCmdIDType;
+
+
+
+
+//
+// SndCommandType: used by SndDoCmd()
+//
+
+typedef struct SndCommandType {
+//SndCmdIDType cmd; // command id
+UInt8 cmd; // command id
+UInt8 reserved;
+Int32 param1; // first parameter
+UInt16 param2; // second parameter
+UInt16 param3; // third parameter
+} SndCommandType;
+
+typedef SndCommandType* SndCommandPtr;
+
+
+//
+// Beep numbers used by SndSysBeep()
+//
+
+typedef enum SndSysBeepType {
+ sndInfo = 1,
+ sndWarning,
+ sndError,
+ sndStartUp,
+ sndAlarm,
+ sndConfirmation,
+ sndClick
+ } SndSysBeepType;
+
+
+/************************************************************
+ * Standard MIDI File (SMF) support structures
+ *************************************************************/
+
+
+// Structure of records in the MIDI sound database:
+//
+// Each MIDI record consists of a record header followed immediately by the
+// Standard MIDI File (SMF) data stream. Only SMF format #0 is presently supported.
+// The first byte of the record header is the byte offset from the beginning of the record
+// to the SMF data stream. The name of the record follows the byte offset
+// field. sndMidiNameLength is the limit on name size (including NULL).
+#define sndMidiRecSignature 'PMrc'
+typedef struct SndMidiRecHdrType {
+ UInt32 signature; // set to sndMidiRecSignature
+ UInt8 bDataOffset; // offset from the beginning of the record
+ // to the Standard Midi File data stream
+ UInt8 reserved; // set to zero
+ } SndMidiRecHdrType;
+
+typedef struct SndMidiRecType {
+ SndMidiRecHdrType hdr; // offset from the beginning of the record
+ // to the Standard Midi File data stream
+ Char name[2]; // Track name: 1 or more chars including NULL terminator.
+ // If a track has no name, the NULL character must still
+ // be provided.
+ // Set to 2 to pad the structure out to a word boundary.
+ } SndMidiRecType;
+
+
+// Midi records found by SndCreateMidiList.
+typedef struct SndMidiListItemType
+ {
+ Char name[sndMidiNameLength]; // including NULL terminator
+ UInt32 uniqueRecID;
+ LocalID dbID;
+ UInt16 cardNo;
+ } SndMidiListItemType;
+
+
+// Commands for SndPlaySmf
+typedef enum SndSmfCmdEnum {
+ sndSmfCmdPlay = 1, // play the selection
+ sndSmfCmdDuration // get the duration in milliseconds of the entire track
+ } SndSmfCmdEnum;
+
+typedef void SndComplFuncType(void *chanP, UInt32 dwUserData);
+typedef SndComplFuncType *SndComplFuncPtr;
+
+
+// Return true to continue, false to abort
+typedef Boolean SndBlockingFuncType(void *chanP, UInt32 dwUserData, Int32 sysTicksAvailable);
+typedef SndBlockingFuncType *SndBlockingFuncPtr;
+
+typedef struct SndCallbackInfoType {
+ MemPtr funcP; // pointer to the callback function (NULL = no function)
+ UInt32 dwUserData; // value to be passed in the dwUserData parameter of the callback function
+ } SndCallbackInfoType;
+
+
+typedef struct SndSmfCallbacksType {
+ SndCallbackInfoType completion; // completion callback function (see SndComplFuncType)
+ SndCallbackInfoType blocking; // blocking hook callback function (see SndBlockingFuncType)
+ SndCallbackInfoType reserved; // RESERVED -- SET ALL FIELDS TO ZERO BEFORE PASSING
+ } SndSmfCallbacksType;
+
+
+#define sndSmfPlayAllMilliSec 0xFFFFFFFFUL
+
+typedef struct SndSmfOptionsType {
+ // dwStartMilliSec and dwEndMilliSec are used as inputs to the function for sndSmfCmdPlay and as
+ // outputs for sndSmfCmdDuration
+ UInt32 dwStartMilliSec; // 0 = "start from the beginning"
+ UInt32 dwEndMilliSec; // sndSmfPlayAllMilliSec = "play the entire track";
+ // the default is "play entire track" if this structure
+ // is not passed in
+
+ // The amplitude and interruptible fields are used only for sndSmfCmdPlay
+ UInt16 amplitude; // relative volume: 0 - sndMaxAmp, inclusively; the default is
+ // sndMaxAmp if this structure is not passed in; if 0, the play will
+ // be skipped and the call will return immediately
+
+ Boolean interruptible; // if true, sound play will be interrupted if
+ // user interacts with the controls (digitizer, buttons, etc.);
+ // if false, the paly will not be interrupted; the default behavior
+ // is "interruptible" if this structure is not passed in
+
+ UInt8 reserved1;
+ UInt32 reserved; // RESERVED! -- MUST SET TO ZERO BEFORE PASSING
+ } SndSmfOptionsType;
+
+
+typedef struct SndSmfChanRangeType {
+ UInt8 bFirstChan; // first MIDI channel (0-15 decimal)
+ UInt8 bLastChan; // last MIDI channel (0-15 decimal)
+ } SndSmfChanRangeType;
+
+
+
+
+/************************************************************
+ * Sound Manager result codes
+ * (sndErrorClass is defined in SystemMgr.h)
+ *************************************************************/
+#define sndErrBadParam (sndErrorClass | 1)
+#define sndErrBadChannel (sndErrorClass | 2)
+#define sndErrMemory (sndErrorClass | 3)
+#define sndErrOpen (sndErrorClass | 4)
+#define sndErrQFull (sndErrorClass | 5)
+#define sndErrQEmpty (sndErrorClass | 6) // internal
+#define sndErrFormat (sndErrorClass | 7) // unsupported data format
+#define sndErrBadStream (sndErrorClass | 8) // invalid data stream
+#define sndErrInterrupted (sndErrorClass | 9) // play was interrupted
+
+
+
+/********************************************************************
+ * Sound Manager Routines
+ * These are define as external calls only under emulation mode or
+ * under native mode from the module that actually installs the trap
+ * vectors
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//-------------------------------------------------------------------
+// Initialization
+//-------------------------------------------------------------------
+
+// Initializes the Sound Manager. Should only be called by
+// Pilot initialization code.
+Err SndInit(void) SYS_TRAP(sysTrapSndInit);
+
+// Frees the Sound Manager.
+//void SndFree(void) SYS_TRAP(sysTrapSndFree);
+
+
+//-------------------------------------------------------------------
+// API
+//-------------------------------------------------------------------
+
+// Sets default sound volume levels
+//
+// Any parameter may be passed as NULL
+extern void SndSetDefaultVolume(UInt16 *alarmAmpP, UInt16 *sysAmpP, UInt16 *defAmpP)
+ SYS_TRAP(sysTrapSndSetDefaultVolume);
+
+// Gets default sound volume levels
+//
+// Any parameter may be passed as NULL
+extern void SndGetDefaultVolume(UInt16 *alarmAmpP, UInt16 *sysAmpP, UInt16 *masterAmpP)
+ SYS_TRAP(sysTrapSndGetDefaultVolume);
+
+// Executes a sound command on the given sound channel (pass
+// channelP = 0 to use the shared channel).
+extern Err SndDoCmd(void * /*SndChanPtr*/ channelP, SndCommandPtr cmdP, Boolean noWait)
+ SYS_TRAP(sysTrapSndDoCmd);
+
+// Plays one of several defined system beeps/sounds (see sndSysBeep...
+// constants).
+extern void SndPlaySystemSound(SndSysBeepType beepID)
+ SYS_TRAP(sysTrapSndPlaySystemSound);
+
+
+// NEW FOR v3.0
+// Performs an operation on a Standard MIDI File (SMF) Format #0
+extern Err SndPlaySmf(void *chanP, SndSmfCmdEnum cmd, UInt8 *smfP, SndSmfOptionsType *selP,
+ SndSmfChanRangeType *chanRangeP, SndSmfCallbacksType *callbacksP,
+ Boolean bNoWait)
+ SYS_TRAP(sysTrapSndPlaySmf);
+
+// NEW FOR v3.0
+// Creates a list of all midi records. Useful for displaying in lists.
+// For creator wildcard, pass creator=0;
+extern Boolean SndCreateMidiList(UInt32 creator, Boolean multipleDBs, UInt16 *wCountP, MemHandle *entHP)
+ SYS_TRAP(sysTrapSndCreateMidiList);
+
+// NEW FOR v3.2
+// Plays a MIDI sound which is read out of an open resource database
+extern Err SndPlaySmfResource(UInt32 resType, Int16 resID, SystemPreferencesChoice volumeSelector)
+ SYS_TRAP(sysTrapSndPlaySmfResource);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+/************************************************************
+ * Sound Manager Macros
+ *
+ *************************************************************/
+
+#endif // __SOUND_MGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SysEvent.h b/SrcShared/Palm/Platform/Incs/Core/System/SysEvent.h
new file mode 100644
index 0000000..7f67624
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SysEvent.h
@@ -0,0 +1,204 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SysEvent.h
+ *
+ * Description:
+ * This file defines event structures and routines.
+ *
+ * History:
+ * September 26, 1994 Created by Art Lamb
+ * 05/05/98 art Add Text Services event.
+ * 07/23/98 kwk Changed UInt16 field in keyDown event to WChar.
+ * 08/20/98 kwk Split tsmEvent into tsmConfirmEvent & tsmFepButtonEvent.
+ * 09/07/98 kwk Added EvtPeekEvent routine declaration.
+ * 10/13/98 kwk Removed EvtPeekEvent until API can be finalized.
+ * 03/11/99 grant Fixed types of pointers in SysEventType data fields.
+ * 05/31/99 kwk Added tsmFepModeEvent event.
+ * 07/14/99 jesse Moved UI structures & constants to Event.h
+ * defined ranges for future UI & system events.
+ * 07/30/99 kwk Moved TSM events here from Event.h
+ * 09/12/99 gap Add new multi-tap implementation
+ * 09/14/99 gap Removed EvtGetTrapState.
+ *
+ *****************************************************************************/
+
+#ifndef __SYSEVENT_H__
+#define __SYSEVENT_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <Font.h>
+#include <Rect.h>
+#include <Window.h>
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥ Don't use an enum for this, as convenient as it is, there's namespace
+// pollution, size issues, no way to manage componentization, blah blah blah.
+#endif // PUBLIC_STUFF_STRIPPED
+
+typedef enum {
+ sysEventNilEvent = 0,
+ sysEventPenDownEvent,
+ sysEventPenUpEvent,
+ sysEventPenMoveEvent,
+ sysEventKeyDownEvent,
+ sysEventWinEnterEvent,
+ sysEventWinExitEvent,
+ sysEventAppStopEvent = 22,
+ sysEventTsmConfirmEvent = 35,
+ sysEventTsmFepButtonEvent,
+ sysEventTsmFepModeEvent,
+
+ // add future UI level events in this numeric space
+ // to save room for new system level events
+ sysEventNextUIEvent = 0x0800,
+
+ // <chg 2-25-98 RM> Equates added for library events
+ sysEventFirstINetLibEvent = 0x1000,
+ sysEventFirstWebLibEvent = 0x1100,
+
+ // <chg 10/9/98 SCL> Changed firstUserEvent from 32767 (0x7FFF) to 0x6000
+ // Enums are signed ints, so 32767 technically only allowed for ONE event.
+ sysEventFirstUserEvent = 0x6000
+} SysEventsEnum;
+
+
+
+// keyDownEvent modifers
+#define shiftKeyMask 0x0001
+#define capsLockMask 0x0002
+#define numLockMask 0x0004
+#define commandKeyMask 0x0008
+#define optionKeyMask 0x0010
+#define controlKeyMask 0x0020
+#define autoRepeatKeyMask 0x0040 // True if generated due to auto-repeat
+#define doubleTapKeyMask 0x0080 // True if this is a double-tap event
+#define poweredOnKeyMask 0x0100 // True if this is a double-tap event
+#define appEvtHookKeyMask 0x0200 // True if this is an app hook key
+#define libEvtHookKeyMask 0x0400 // True if this is a library hook key
+
+// define mask for all "virtual" keys
+#define virtualKeyMask (appEvtHookKeyMask | libEvtHookKeyMask | commandKeyMask)
+
+
+// Event timeouts
+#define evtWaitForever -1
+#define evtNoWait 0
+
+struct _GenericEventType {
+ UInt16 datum[8];
+ };
+
+struct _PenUpEventType {
+ PointType start; // display coord. of stroke start
+ PointType end; // display coord. of stroke start
+ };
+
+struct _KeyDownEventType {
+ WChar chr; // ascii code
+ UInt16 keyCode; // virtual key code
+ UInt16 modifiers;
+ };
+
+struct _WinEnterEventType {
+ WinHandle enterWindow;
+ WinHandle exitWindow;
+ };
+
+struct _WinExitEventType {
+ WinHandle enterWindow;
+ WinHandle exitWindow;
+ };
+
+struct _TSMConfirmType {
+ Char * yomiText;
+ UInt16 formID;
+ };
+
+struct _TSMFepButtonType {
+ UInt16 buttonID;
+ };
+
+struct _TSMFepModeEventType {
+ UInt16 mode; // DOLATER kwk - use real type for mode?
+ };
+
+
+// The event record.
+typedef struct SysEventType {
+ SysEventsEnum eType;
+ Boolean penDown;
+ UInt8 tapCount;
+ Coord screenX;
+ Coord screenY;
+ union {
+ struct _GenericEventType generic;
+
+ struct _PenUpEventType penUp;
+ struct _KeyDownEventType keyDown;
+ struct _WinEnterEventType winEnter;
+ struct _WinExitEventType winExit;
+ struct _TSMConfirmType tsmConfirm;
+ struct _TSMFepButtonType tsmFepButton;
+ struct _TSMFepModeEventType tsmFepMode;
+
+ } data;
+
+} SysEventType;
+
+
+// Events are stored in the event queue with some extra fields:
+typedef struct {
+ SysEventType event;
+ UInt32 id; // used to support EvtAddUniqueEvent
+ } SysEventStoreType;
+
+#ifndef PUBLIC_STUFF_STRIPPED // removed header that should be moved into private area
+
+//---------------------------------------------------------------------
+// Event Functions
+//---------------------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DOLATER: jwm: This lot should be in a private header file, no? */
+
+void SysEventInitialize (void)
+ SYS_TRAP(sysTrapEvtInitialize);
+
+void SysEventAddToQueue (const SysEventType *event)
+ SYS_TRAP(sysTrapEvtAddEventToQueue);
+
+void SysEventAddUniqueToQueue(const SysEventType *eventP, UInt32 id,
+ Boolean inPlace)
+ SYS_TRAP(sysTrapEvtAddUniqueEventToQueue);
+
+void SysEventCopy (const SysEventType *source, SysEventType *dest)
+ SYS_TRAP(sysTrapEvtCopyEvent);
+
+void SysEventGet (SysEventType *event, Int32 timeout)
+ SYS_TRAP(sysTrapEvtGetEvent);
+
+Boolean SysEventAvail (void)
+ SYS_TRAP(sysTrapEvtEventAvail);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+// For Compatibility.. DOLATER... source modules should use EvtGetPen instead.
+#endif // PUBLIC_STUFF_STRIPPED
+#define PenGetPoint(a,b,c) EvtGetPen(a,b,c)
+
+
+
+#endif // __SYSEVENT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SysEvtMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/SysEvtMgr.h
new file mode 100644
index 0000000..f9d257f
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SysEvtMgr.h
@@ -0,0 +1,252 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SysEvtMgr.h
+ *
+ * Description:
+ * Header for the System Event Manager
+ *
+ * History:
+ * 03/22/95 RM Created by Ron Marianetti
+ * 07/23/98 kwk Changed UInt16 param in EvtEnqueueKey to WChar.
+ *
+ *****************************************************************************/
+
+#ifndef __SYSEVTMGR_H__
+#define __SYSEVTMGR_H__
+
+#include <PalmTypes.h>
+#include <SysEvent.h>
+
+/************************************************************
+ * System Event Manager Errors
+ *************************************************************/
+#define evtErrParamErr (evtErrorClass | 1)
+#define evtErrQueueFull (evtErrorClass | 2)
+#define evtErrQueueEmpty (evtErrorClass | 3)
+
+
+/************************************************************
+ * Commands for EvtSetAutoOffTimer()
+ *************************************************************/
+typedef enum
+{
+ SetAtLeast, // turn off in at least xxx seconds
+ SetExactly, // turn off in xxx seconds
+ SetAtMost, // turn off in at most xxx seconds
+ SetDefault, // change default auto-off timeout to xxx seconds
+ ResetTimer // reset the timer to the default auto-off timeout
+
+} EvtSetAutoOffCmd;
+
+
+/************************************************************
+ * Pen button info structure. This structure is used
+ * to hold the bounds of each button on the silk screen and
+ * the ascii code and modifiers byte that each will generate
+ * when tapped by the user.
+ *************************************************************/
+typedef struct PenBtnInfoType {
+ RectangleType boundsR; // bounding rectangle of button
+ WChar asciiCode; // ascii code for key event
+ UInt16 keyCode; // virtual key code for key event
+ UInt16 modifiers; // modifiers for key event
+ } PenBtnInfoType;
+typedef PenBtnInfoType* PenBtnInfoPtr;
+
+typedef struct PenBtnListType {
+ UInt16 numButtons; // Count of number of buttons
+ PenBtnInfoType buttons[1]; // Placeholder for one or more buttons
+ } PenBtnListType;
+
+
+/************************************************************
+ * Silkscreen area info structure. An array of these structures
+ * is returned by the EvtGetSilkscreenAreaList function.
+ *************************************************************/
+
+// Different types of rectangles on the display. For new vendor areas,
+// the type should be set to the vendor's creator code, as assigned
+// by 3Com's Partner Engineering group.
+#define silkscreenRectScreen 'scrn'
+#define silkscreenRectGraffiti 'graf'
+
+// Values for SilkscreenAreaType.index if areaType = silkscreenRectGraffiti
+#define alphaGraffitiSilkscreenArea 0
+#define numericGraffitiSilkscreenArea 1
+
+// One silkscreen area. The areaType field tells us which type of
+// area it is, while the index field has different meanings depending
+// on the area type.
+typedef struct SilkscreenAreaType {
+ RectangleType bounds;
+ UInt32 areaType; // four byte creator code.
+ UInt16 index;
+ } SilkscreenAreaType;
+
+
+/************************************************************
+ * System Event Manager procedures
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//-----------------------------------------------------------------
+// High Level Calls
+//------------------------------------------------------------------
+Err EvtSysInit(void)
+ SYS_TRAP(sysTrapEvtSysInit);
+
+// Return next "System" event. This routine will send strokes to Graffiti as necessary
+// and return a key event. Otherwise, it will return a simple pen down or pen
+// up event, or put the processor to sleep for a max time of 'timeout' if
+// no events are available.
+void EvtGetSysEvent(SysEventType *eventP, Int32 timeout)
+ SYS_TRAP(sysTrapEvtGetSysEvent);
+
+
+// Return true if there is a low level system event (pen or key) available
+Boolean EvtSysEventAvail(Boolean ignorePenUps)
+ SYS_TRAP(sysTrapEvtSysEventAvail);
+
+
+
+// Translate a stroke in the silk screen area to a key event
+Err EvtProcessSoftKeyStroke(PointType *startPtP, PointType *endPtP)
+ SYS_TRAP(sysTrapEvtProcessSoftKeyStroke);
+
+
+//-----------------------------------------------------------------
+// Pen Queue Utilties
+//------------------------------------------------------------------
+
+// Replace current pen queue with another of the given size
+Err EvtSetPenQueuePtr(MemPtr penQueueP, UInt32 size)
+ SYS_TRAP(sysTrapEvtSetPenQueuePtr);
+
+// Return size of current pen queue in bytes
+UInt32 EvtPenQueueSize(void)
+ SYS_TRAP(sysTrapEvtPenQueueSize);
+
+// Flush the pen queue
+Err EvtFlushPenQueue(void)
+ SYS_TRAP(sysTrapEvtFlushPenQueue);
+
+
+// Append a point to the pen queue. Passing -1 for x and y means
+// pen-up (terminate the current stroke). Called by digitizer interrupt routine
+Err EvtEnqueuePenPoint(PointType *ptP)
+ SYS_TRAP(sysTrapEvtEnqueuePenPoint);
+
+
+// Return the stroke info for the next stroke in the pen queue. This MUST
+// be the first call when removing a stroke from the queue
+Err EvtDequeuePenStrokeInfo(PointType *startPtP, PointType *endPtP)
+ SYS_TRAP(sysTrapEvtDequeuePenStrokeInfo);
+
+// Dequeue the next point from the pen queue. Returns non-0 if no
+// more points. The point returned will be (-1,-1) at the end
+// of the stroke.
+Err EvtDequeuePenPoint(PointType *retP)
+ SYS_TRAP(sysTrapEvtDequeuePenPoint);
+
+
+// Flush the entire stroke from the pen queue and dispose it
+Err EvtFlushNextPenStroke()
+ SYS_TRAP(sysTrapEvtFlushNextPenStroke);
+
+
+
+
+//-----------------------------------------------------------------
+// Key Queue Utilties
+//------------------------------------------------------------------
+
+// Replace current key queue with another of the given size. This routine will
+// intialize the given key queue before installing it
+Err EvtSetKeyQueuePtr(MemPtr keyQueueP, UInt32 size)
+ SYS_TRAP(sysTrapEvtSetKeyQueuePtr);
+
+// Return size of current key queue in bytes
+UInt32 EvtKeyQueueSize(void)
+ SYS_TRAP(sysTrapEvtKeyQueueSize);
+
+// Flush the key queue
+Err EvtFlushKeyQueue(void)
+ SYS_TRAP(sysTrapEvtFlushKeyQueue);
+
+
+// Append a key to the key queue.
+Err EvtEnqueueKey(WChar ascii, UInt16 keycode, UInt16 modifiers)
+ SYS_TRAP(sysTrapEvtEnqueueKey);
+
+// Return true of key queue empty.
+Boolean EvtKeyQueueEmpty(void)
+ SYS_TRAP(sysTrapEvtKeyQueueEmpty);
+
+
+// Pop off the next key event from the key queue and fill in the given
+// event record structure. Returns non-zero if there aren't any keys in the
+// key queue. If peek is non-zero, key will be left in key queue.
+Err EvtDequeueKeyEvent(SysEventType *eventP, UInt16 peek)
+ SYS_TRAP(sysTrapEvtDequeueKeyEvent);
+
+
+//-----------------------------------------------------------------
+// Silkscreen information calls
+//------------------------------------------------------------------
+
+// Return pointer to the pen based button list
+const PenBtnInfoType* EvtGetPenBtnList(UInt16* numButtons)
+ SYS_TRAP(sysTrapEvtGetPenBtnList);
+
+// Return pointer to the silkscreen area list
+const SilkscreenAreaType* EvtGetSilkscreenAreaList(UInt16* numAreas)
+ SYS_TRAP(sysTrapEvtGetSilkscreenAreaList);
+
+
+//-----------------------------------------------------------------
+// General Utilities
+//------------------------------------------------------------------
+// Force the system to wake-up. This will result in a null event being
+// sent to the current app.
+Err EvtWakeup(void)
+ SYS_TRAP(sysTrapEvtWakeup);
+
+// Reset the auto-off timer. This is called by the SerialLink Manager in order
+// so we don't auto-off while receiving data over the serial port.
+Err EvtResetAutoOffTimer(void)
+ SYS_TRAP(sysTrapEvtResetAutoOffTimer);
+
+Err EvtSetAutoOffTimer(EvtSetAutoOffCmd cmd, UInt16 timeout)
+ SYS_TRAP(sysTrapEvtSetAutoOffTimer);
+
+// Set Graffiti enabled or disabled.
+void EvtEnableGraffiti(Boolean enable)
+ SYS_TRAP(sysTrapEvtEnableGraffiti);
+
+// Force a NullEvent at or before tick
+Boolean EvtSetNullEventTick(UInt32 tick)
+ SYS_TRAP(sysTrapEvtSetNullEventTick);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+/************************************************************
+ * Assembly Function Prototypes
+ *************************************************************/
+#define _EvtEnqueuePenPoint \
+ ASM_SYS_TRAP(sysTrapEvtEnqueuePenPoint)
+
+
+
+#endif //__SYSEVTMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SystemMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/SystemMgr.h
new file mode 100644
index 0000000..a057405
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SystemMgr.h
@@ -0,0 +1,1191 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SystemMgr.h
+ *
+ * Description:
+ * Pilot system equates
+ *
+ * History:
+ * 10/27/94 RM Created by Ron Marianetti
+ * 10/07/96 SCL Added sysAppLaunchFlagDataRelocated flag
+ * 11/13/96 vmk Added sysErrDelayWakened error code
+ * 08/12/98 dia Added sysFtrNumGremlinsSupportGlobals.
+ * 08/18/98 SCL Added sysFtrNumHwrMiscFlags and ...FlagsExt.
+ * Redefined sysFtrNumProcessorID.
+ * 08/23/98 SCL Merged in tsmErrorClass.
+ * 09/07/98 kwk Added SysWantEvent routine declaration.
+ * 10/05/98 jfs Added SysLCDContrast trap descriptor
+ * 04/08/99 kwk Added sysFtrNumVendor (OS 3.3 and later)
+ * 06/28/99 kwk Added omErrorClass.
+ * 08/11/99 kwk Added sysFtrNumCharEncodingFlags.
+ * 11/01/99 kwk Moved SysWantEvent to SystemPrv.h
+ * 12/03/99 SCL Moved SysAppInfoType, SysAppStartup, and SysAppExit
+ * here from SystemPrv.h (for StartupCode/Runtime)
+ *
+ *****************************************************************************/
+
+#ifndef __SYSTEMMGR_H__
+#define __SYSTEMMGR_H__
+
+// Include elementary types
+#include <PalmTypes.h>
+#include <CoreTraps.h> // Trap Numbers.
+
+// Other types
+#include <SystemResources.h> // Resource definitions.
+
+
+// System Headers
+#include <Rect.h>
+#include <Font.h>
+#include <Window.h>
+#include <InsPoint.h>
+#include <Event.h>
+#include <DataMgr.h> // for DmOpenRef
+#include <LibTraps.h>
+
+
+/************************************************************
+ * System Constants
+ *************************************************************/
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER - These #defines should be removed from the public SDK!!!
+// Note that since the SysTicksPerSecond() API still uses these,
+// so they'll need to remain in private headers. There are also
+// several other headers and Palm OS sources that rely on these
+// defines but should be changed to use SysTicksPerSecond().
+#endif // PUBLIC_STUFF_STRIPPED
+// Define the number of ticks/second
+// NOTE: It is strongly recommended that developers avoid using these
+// defines, and use the SysTicksPerSecond() API (below) instead....
+#if EMULATION_LEVEL == EMULATION_MAC
+ #define sysTicksPerSecond 60 // 60/sec on Macintosh
+#elif EMULATION_LEVEL == EMULATION_NONE
+ #define sysTicksPerSecond 100 // 100/sec on Pilot
+#elif EMULATION_LEVEL == EMULATION_WINDOWS
+ #define sysTicksPerSecond 1000 // 1000/sec on Windows PC
+#elif EMULATION_LEVEL == EMULATION_UNIX
+ #define sysTicksPerSecond 1000
+ // 1000/sec on Linux
+#else
+ #error Invalid EMULATION_LEVEL
+#endif
+
+
+
+/************************************************************
+ * Rules for creating and using the Command Parameter Block
+ * passed to SysUIAppSwitch
+ *************************************************************/
+
+// A parameter block containing application-specific information may be passed
+// to an application when launching it via SysUIAppSwitch. To create the
+// parameter block, you allocate a memory block using MemPtrNew and then you must
+// call MemPtrSetOwner to set the block's owner ID to 0. This assigns the block's
+// ownership to the system so that it will not be automatically freed by the system
+// when the calling app exits. The command block must be self contained. It must not
+// have pointers to anything on the stack or in memory blocks owned by an application.
+// The launching and launched applications do not need to worry about freeing the
+// command block since the system will do this after the launched application exits.
+// If no parameter block is being passed, this parameter must be NULL.
+
+
+/************************************************************
+ * Action Codes
+ *
+ * IMPORTANT ACTION CODE CONSIDERATIONS:
+ *
+ * Many action codes are "sent" to apps via a direct function call into the app's
+ * PilotMain() function without launching the app. For these action codes, the
+ * application's global and static variables are *not* available, unless the
+ * application is already running. Some action codes are synchronized with the
+ * currently running UI applcation via the event manager (alarm action codes,
+ * for example), while others, such as HotSync action codes, are sent from a
+ * background thread. To find out if your app is running (is the current UI
+ * app) when an action code is received, test the sysAppLaunchFlagSubCall flag
+ * (defined in SystemMgr.h) which is passed to your PilotMain in the
+ * launchFlags parameter (the third PilotMain parameter). If it is non-zero,
+ * you may assume that your app is currently running and the global variables
+ * are accessible. This information is useful if your app maintains an open
+ * data database (or another similar resource) when it is running. If the app
+ * receives an action code and the sysAppLaunchFlagSubCall is set in
+ * launchFlags, the handler may access global variables and use the open
+ * database handle while handling the call. On the other hand, if the
+ * sysAppLaunchFlagSubCall flag is not set (ie., zero), the handler will need
+ * to open and close the database itself and is not allowed to access global
+ * or static variables.
+ *
+ *************************************************************/
+
+// NOTE: for defining custom action codes, see sysAppLaunchCmdCustomBase below.
+
+// System SysAppLaunch Commands
+#define sysAppLaunchCmdNormalLaunch 0 // Normal Launch
+
+#define sysAppLaunchCmdFind 1 // Find string
+
+#define sysAppLaunchCmdGoTo 2 // Launch and go to a particular record
+
+#define sysAppLaunchCmdSyncNotify 3 // Sent to apps whose databases changed during
+ // HotSync after the sync has been completed,
+ // including when the app itself has been installed
+ // by HotSync. The data database(s) must have the
+ // same creator ID as the application for this
+ // mechanism to function correctly. This is a
+ // good opportunity to update/initialize/validate
+ // the app's data, such as resorting records,
+ // setting alarms, etc.
+ //
+ // Parameter block: None.
+ // Restrictions: No accessing of global or
+ // static variables; no User Interface calls.
+ // Notes: This action code is sent via a
+ // direct function call into the app's
+ // PilotMain function from the background
+ // thread of the HotSync application.
+
+
+#define sysAppLaunchCmdTimeChange 4 // Sent to all applications and preference
+ // panels when the system time is changed.
+ // This notification is the right place to
+ // update alarms and other time-related
+ // activities and resources.
+ //
+ // Parameter block: None.
+ // Restrictions: No accessing of global or
+ // static variables; no User Interface calls.
+ // Notes: This action code is sent via a direct
+ // function call into the app's PilotMain
+ // function without "launching" the app.
+
+#define sysAppLaunchCmdSystemReset 5 // Sent to all applications and preference
+ // panels when the system is either soft-reset
+ // or hard-reset. This notification is the
+ // right place to initialize and/or validate
+ // your application's preferences/features/
+ // database(s) as well as to update alarms and
+ // other time-related activities and resources.
+ //
+ // Parameter block: SysAppLaunchCmdSystemResetType
+ // Restrictions: No accessing of global or
+ // static variables; no User Interface calls.
+ // Notes: This action code is sent via a direct
+ // function call into the app's PilotMain
+ // function without "launching" the app.
+
+#define sysAppLaunchCmdAlarmTriggered 6 // Sent to an application at the time its
+ // alarm time expires (even when another app
+ // is already displaying its alarm dialog box).
+ // This call is intended to allow the app to
+ // perform some very quick activity, such as
+ // scheduling the next alarm or performing a
+ // quick maintenance task. The handler for
+ // sysAppLaunchCmdAlarmTriggered must take as
+ // little time as possible and is *not* allowed
+ // to block (this would delay notification for
+ // alarms set by other applications).
+ //
+ // Parameter block: SysAlarmTriggeredParamType
+ // (defined in AlarmMgr.h)
+ // Restrictions: No accessing of global or
+ // static variables unless sysAppLaunchFlagSubCall
+ // flag is set, as discussed above.
+ // Notes: This action code is sent via a direct
+ // function call into the app's PilotMain
+ // function without "launching" the app.
+
+#define sysAppLaunchCmdDisplayAlarm 7 // Sent to an application when it is time
+ // to display the alarm UI. The application
+ // is responsible for making any alarm sounds
+ // and for displaying the alarm UI.
+ // sysAppLaunchCmdDisplayAlarm calls are ordered
+ // chronoligically and are not overlapped.
+ // This means that your app will receive
+ // sysAppLaunchCmdDisplayAlarm only after
+ // all earlier alarms have been displayed.
+ //
+ // Parameter block: SysDisplayAlarmParamType
+ // (defined in AlarmMgr.h)
+ // Restrictions: No accessing of global or
+ // static variables unless sysAppLaunchFlagSubCall
+ // flag is set, as discussed above. UI calls are
+ // allowed to display the app's alarm dialog.
+ // Notes: This action code is sent via a direct
+ // function call into the app's PilotMain
+ // function without "launching" the app.
+
+#define sysAppLaunchCmdCountryChange 8 // The country has changed
+
+#define sysAppLaunchCmdSyncRequestLocal 9 // Sent to the HotSync application to request a
+ // local HotSync. ("HotSync" button was pressed.)
+
+#define sysAppLaunchCmdSyncRequest sysAppLaunchCmdSyncRequestLocal // for backward compatibility
+
+#define sysAppLaunchCmdSaveData 10 // Sent to running app before sysAppLaunchCmdFind
+ // or other action codes that will cause data
+ // searches or manipulation.
+
+#define sysAppLaunchCmdInitDatabase 11 // Sent to an application when a database with
+ // a matching Creator ID is created during
+ // HotSync (in response to a "create db"
+ // request). This allows the application to
+ // initialize a newly-created database during
+ // HotSync. This might include creating some
+ // default records, setting up the database's
+ // application and sort info blocks, etc.
+ //
+ // Parameter block: SysAppLaunchCmdInitDatabaseType
+ // Restrictions: No accessing of global or
+ // static variables; no User Interface calls.
+ // Notes: This action code is sent via a
+ // direct function call into the app's
+ // PilotMain function from the background
+ // thread of the HotSync application.
+
+#define sysAppLaunchCmdSyncCallApplicationV10 12 // Used by DesktopLink Server command "call application";
+ // Pilot v1.0 only!!!
+
+//------------------------------------------------------------------------
+// New launch codes defined for PalmOS 2.0
+//------------------------------------------------------------------------
+
+#define sysAppLaunchCmdPanelCalledFromApp 13 // The panel should display a done
+ // button instead of the pick list.
+ // The Done button will return the user
+ // to the last app.
+
+#define sysAppLaunchCmdReturnFromPanel 14 // A panel returned to this app
+
+#define sysAppLaunchCmdLookup 15 // Lookup info managed by an app
+
+#define sysAppLaunchCmdSystemLock 16 // Lock the system until a password is entered.
+
+#define sysAppLaunchCmdSyncRequestRemote 17 // Sent to the HotSync application to request
+ // a remote HotSync. ("Remote HotSync" button
+ // was pressed.)
+
+#define sysAppLaunchCmdHandleSyncCallApp 18 // Pilot v2.0 and greater. Sent by DesktopLink Server to an application to handle
+ // the "call application" command; use DlkControl with
+ // control code dlkCtlSendCallAppReply to send the reply(see DLServer.h).
+ // This action code replaces the v1.0 code sysAppLaunchCmdSyncCallApplication.
+ // vmk 11/26/96
+
+#define sysAppLaunchCmdAddRecord 19 // Add a record to an applications's database.
+
+
+//------------------------------------------------------------------------
+// Standard Service Panel launch codes (used by network panel, dialer panel, etc.)
+#ifndef PUBLIC_STUFF_STRIPPED
+// (DOLATER... document parameter block structures)
+#endif // PUBLIC_STUFF_STRIPPED
+//------------------------------------------------------------------------
+#define sysSvcLaunchCmdSetServiceID 20
+#define sysSvcLaunchCmdGetServiceID 21
+#define sysSvcLaunchCmdGetServiceList 22
+#define sysSvcLaunchCmdGetServiceInfo 23
+
+
+#define sysAppLaunchCmdFailedAppNotify 24 // An app just switched to failed.
+#define sysAppLaunchCmdEventHook 25 // Application event hook callback
+#define sysAppLaunchCmdExgReceiveData 26 // Exg command for app to receive data.
+#define sysAppLaunchCmdExgAskUser 27 // Exg command sent before asking user.
+
+
+//------------------------------------------------------------------------
+// Standard Dialer Service launch codes (30 - 39 reserved)
+#ifndef PUBLIC_STUFF_STRIPPED
+// (DOLATER... document parameter block structures)
+#endif // PUBLIC_STUFF_STRIPPED
+//------------------------------------------------------------------------
+
+// sysDialLaunchCmdDial: dials the modem(optionally displays dial progress UI), given service id
+// and serial library reference number
+#define sysDialLaunchCmdDial 30
+// sysDialLaunchCmdHangUp: hangs up the modem(optionally displays disconnect progress UI), given service id
+// and serial library reference number
+#define sysDialLaunchCmdHangUp 31
+#define sysDialLaunchCmdLast 39
+
+
+//------------------------------------------------------------------------
+// Additional standard Service Panel launch codes (used by network panel, dialer panel, etc)
+// (40-49 reserved)
+//------------------------------------------------------------------------
+
+#define sysSvcLaunchCmdGetQuickEditLabel 40 // SvcQuickEditLabelInfoType
+#define sysSvcLaunchCmdLast 49
+
+
+//------------------------------------------------------------------------
+// New launch codes defined for PalmOS 3.x where x >= 1
+//------------------------------------------------------------------------
+
+#define sysAppLaunchCmdURLParams 50 // Sent from the Web Clipper application.
+ // This launch code gets used to satisfy
+ // URLs like the following:
+ // palm:memo.appl?param1=value1&param2=value2
+ // Everything in the URL past the '?' is passed
+ // to the app as the cmdPBP parameter of PilotMain().
+
+#define sysAppLaunchCmdNotify 51 // This is a NotifyMgr notification sent
+ // via SysNotifyBroadcast. The cmdPBP parameter
+ // points to a SysNotifyParamType structure
+ // containing more specific information
+ // about the notification (e.g., what it's for).
+
+#define sysAppLaunchCmdOpenDB 52 // Sent to switch to an application and have it
+ // "open" up the given data file. The cmdPBP
+ // pointer is a pointer to a SysAppLaunchCmdOpenDBType
+ // structure that has the cardNo and localID of the database
+ // to open. This action code is used by the Launcher
+ // to launch data files, like Eleven PQA files that
+ // have the dmHdrAttrLaunchableData bit set in their
+ // database attributes.
+
+#define sysAppLaunchCmdAntennaUp 53 // Sent to switch only to the launcher when
+ // the antenna is raised and the launcher
+ // is the application in the buttons preferences
+ // that is to be run when the antenna is raised is
+ // the launcher.
+
+#define sysAppLaunchCmdGoToURL 54 // Sent to Clipper to have it launch and display
+ // a given URL. cmdPBP points to the URL string.
+
+
+// ***ADD NEW SYSTEM ACTION CODES BEFORE THIS COMMENT***
+
+//------------------------------------------------------------------------
+// Custom action code base (custom action codes begin at this value)
+//------------------------------------------------------------------------
+#define sysAppLaunchCmdCustomBase 0x8000
+
+// Your custom launch codes can be defined like this:
+//
+// typedef enum {
+// myAppCmdDoSomething = sysAppLaunchCmdCustomBase,
+// myAppCmdDoSomethingElse,
+// myAppCmdEtcetera
+//
+// } MyAppCustomActionCodes;
+
+
+
+//------------------------------------------------------------------------
+// SysAppLaunch flags (passed to PilotMain)
+//------------------------------------------------------------------------
+
+#define sysAppLaunchFlagNewThread 0x01 // create a new thread for application
+ // - implies sysAppLaunchFlagNewStack
+#define sysAppLaunchFlagNewStack 0x02 // create separate stack for application
+#define sysAppLaunchFlagNewGlobals 0x04 // create new globals world for application
+ // - implies new owner ID for Memory chunks
+#define sysAppLaunchFlagUIApp 0x08 // notifies launch routine that this is a UI app being
+ // launched.
+#define sysAppLaunchFlagSubCall 0x10 // notifies launch routine that the app is calling it's
+ // entry point as a subroutine call. This tells the launch
+ // code that it's OK to keep the A5 (globals) pointer valid
+ // through the call.
+ // IMPORTANT: This flag is for internal use by
+ // SysAppLaunch only!!! It should NEVER be set
+ // by the caller.
+#define sysAppLaunchFlagDataRelocated 0x80 // global data (static ptrs) have been "relocated"
+ // by either SysAppStartup or StartupCode.c
+ // IMPORTANT: This flag is for internal use by
+ // SysAppLaunch only!!! It should NEVER be set
+ // by the caller.
+
+// The set of private, internal flags that should never be set by the caller
+#define sysAppLaunchFlagPrivateSet (sysAppLaunchFlagSubCall | sysAppLaunchFlagDataRelocated)
+
+
+
+//-------------------------------------------------------------------
+// Parameter blocks for action codes
+// NOTE: The parameter block for the sysAppLaunchCmdFind and sysAppLaunchCmdGoTo
+// action codes are defined in "Find.h";
+//---------------------------------------------------------------------------
+
+// For sysAppLaunchCmdSaveData
+typedef struct {
+ Boolean uiComing; // true if system dialog will be put up
+ // before coming action code arrives.
+ UInt8 reserved1;
+ } SysAppLaunchCmdSaveDataType;
+
+// For sysAppLaunchCmdSystemReset
+typedef struct {
+ Boolean hardReset; // true if system was hardReset, false if soft-reset.
+ Boolean createDefaultDB; // true if app should create default database.
+ } SysAppLaunchCmdSystemResetType;
+
+
+// For sysAppLaunchCmdInitDatabase
+typedef struct SysAppLaunchCmdInitDatabaseType {
+ DmOpenRef dbP; // Handle of the newly-created database,
+ // already open for read/write access.
+ // IMPORTANT: The handler *MUST* leave
+ // this database handle open on return.
+ UInt32 creator; // Creator ID of the newly-created database
+ UInt32 type; // Type ID of the newly-created database
+ UInt16 version; // Version number of the newly-created database
+ } SysAppLaunchCmdInitDatabaseType;
+
+
+// For sysAppLaunchCmdSyncCallApplicationV10
+// This structure used on Pilot v1.0 only. See sysAppLaunchCmdHandleSyncCallApp
+// for later platforms.
+typedef struct SysAppLaunchCmdSyncCallApplicationTypeV10 {
+ UInt16 action; // call action id (app-specific)
+ UInt16 paramSize; // parameter size
+ void * paramP; // ptr to parameter
+ UInt8 remoteSocket; // remote socket id
+ UInt8 tid; // command transaction id
+ Boolean handled; // if handled, MUST be set true by the app
+ UInt8 reserved1;
+ } SysAppLaunchCmdSyncCallApplicationTypeV10;
+
+
+// For sysAppLaunchCmdHandleSyncCallApp (Pilot v2.0 and greater).
+// This structure replaces SysAppLaunchCmdSyncCallApplicationType
+// which was used in Pilot v1.0
+typedef struct SysAppLaunchCmdHandleSyncCallAppType {
+ UInt16 pbSize; // this parameter block size (set to sizeof SysAppLaunchCmdHandleSyncCallAppType)
+ UInt16 action; // call action id (app-specific)
+ void * paramP; // ptr to parameter
+ UInt32 dwParamSize; // parameter size
+ void * dlRefP; // DesktopLink reference pointer for passing
+ // to DlkControl()'s dlkCtlSendCallAppReply code
+
+ Boolean handled; // initialized to FALSE by DLServer; if
+ // handled, MUST be set TRUE by the app(the
+ // handler MUST call DlkControl with
+ // control code dlkCtlSendCallAppReply);
+ // if the handler is not going to send a reply,
+ // it should leave this field set to FALSE, in which
+ // case DesktopLink Server will send the default
+ // "unknown request" reply.
+
+ UInt8 reserved1;
+
+ Err replyErr; // error from dlkCtlSendCallAppReply
+
+ // RESERVED FOR FUTURE EXTENSIONS
+ UInt32 dwReserved1; // RESERVED -- set to null!!!
+ UInt32 dwReserved2; // RESERVED -- set to null!!!
+
+ // Target executable creator and type for testing the mechanism
+ // in EMULATION MODE ONLY!!!
+ #if EMULATION_LEVEL != EMULATION_NONE
+ UInt32 creator;
+ UInt32 type;
+ #endif
+
+ } SysAppLaunchCmdHandleSyncCallAppType;
+
+// For sysAppLaunchCmdFailedAppNotify
+typedef struct
+ {
+ UInt32 creator;
+ UInt32 type;
+ Err result;
+ } SysAppLaunchCmdFailedAppNotifyType;
+
+
+// For sysAppLaunchCmdOpenDB
+typedef struct
+ {
+ UInt16 cardNo;
+ LocalID dbID;
+ } SysAppLaunchCmdOpenDBType;
+
+
+/************************************************************
+ * Structure of Application info for an application. Applications
+ * do not necessarily have to be on their own thread - there
+ * can be more than 1 app on the same AMX task. Each application
+ * has an assocated SysAppInfoType structure which holds the
+ * application specific information like the database MemHandle of the
+ * app, the code MemHandle, the stack chunk pointer, the owner ID, etc.
+ *
+ * As of PalmOS 3.X, one of these structures is created for each
+ * app running as an action code.
+ *
+ ****
+ ****IMPORTANT: ADD NEW FIELDS AT THE END OF THE STRUCTURE FOR
+ **** BACKWARD COMPATIBILITY
+ ****
+ *************************************************************/
+typedef struct SysAppInfoType {
+ Int16 cmd; // command code for app
+ MemPtr cmdPBP; // cmd ParamBlock
+ UInt16 launchFlags; // launch flags
+
+ UInt32 taskID; // AMX task ID of task that app runs in
+ MemHandle codeH; // code MemHandle of the main code segment
+ DmOpenRef dbP; // Application database access MemPtr of App
+ UInt8 *stackP; // stack chunk for the App
+ UInt8 *globalsChunkP; // globals chunk for the App
+
+ UInt16 memOwnerID; // owner ID for Memory Manager chunks
+ MemPtr dmAccessP; // pointer to linked list of opened DB's
+ Err dmLastErr; // Last error from Data Manager
+ MemPtr errExceptionP; // ErrTry,Catch exception list
+
+ // PalmOS v3.0 fields begin here
+ UInt8 *a5Ptr; // A5 MemPtr for this app
+ UInt8 *stackEndP; // stack chunk end for the App (last byte)
+ UInt8 *globalEndP; // global chunk end for the App (last byte)
+ struct SysAppInfoType *rootP; // Points to the SysAppInfoType first
+ // allocated for this thread.
+ MemPtr extraP; // unused MemPtr for the App.
+ } SysAppInfoType;
+typedef SysAppInfoType *SysAppInfoPtr;
+
+
+/************************************************************
+ * Function prototype for libraries
+ *************************************************************/
+
+// ***IMPORTANT***
+// ***IMPORTANT***
+// ***IMPORTANT***
+//
+// The assembly level TrapDispatcher() function uses a hard-coded value for
+// the size of the structure SysLibTblEntryType to obtain a pointer to a
+// library entry in the library table. Therefore, any changes to this structure,
+// require corresponding changes in TrapDispatcher() in ROMBoot.c. Furthermore,
+// it is advantageous to keep the size of the structure a power of 2 as this
+// improves performance by allowing the entry offset to be calculated by shifting
+// left instead of using the multiply instruction. vmk 8/27/96 (yes, I fell into
+// this trap myself)
+typedef struct SysLibTblEntryType {
+ MemPtr *dispatchTblP; // pointer to library dispatch table
+ void *globalsP; // Library globals
+
+ // New INTERNAL fields for v2.0 (vmk 8/27/96):
+ LocalID dbID; // database id of the library
+ void *codeRscH; // library code resource handle for RAM-based libraries
+ } SysLibTblEntryType;
+typedef SysLibTblEntryType* SysLibTblEntryPtr;
+
+// Emulated versions of libraries have a slightly different dispatch table
+// Enough for the offset to the library name and the name itself.
+#if EMULATION_LEVEL != EMULATION_NONE
+typedef struct SimDispatchTableType {
+ UInt32 numEntries; // number of library entries
+ void *entries[1]; // dispatch routine entries
+ // followed by pointer to name
+ } SimDispatchTableType;
+typedef SimDispatchTableType* SimDispatchTablePtr;
+#endif
+
+
+// Library entry point procedure
+typedef Err (*SysLibEntryProcPtr)(UInt16 refNum, SysLibTblEntryPtr entryP);
+
+// This library refNum is reserved for the Debugger comm library
+#define sysDbgCommLibraryRefNum 0
+
+// This portID is reserved for identifying the debugger's port
+#define sysDbgCommPortID 0xC0FF
+
+// This refNum signals an invalid refNum
+#define sysInvalidRefNum 0xFFFF
+
+
+/************************************************************
+ * Function prototype for Kernel
+ *************************************************************/
+// Task termination procedure prototype for use with SysTaskSetTermProc
+typedef void (*SysTermProcPtr)(UInt32 taskID, Int32 reason);
+
+// Timer procedure for use with SysTimerCreate
+typedef void (*SysTimerProcPtr)(Int32 timerID, Int32 param);
+
+
+
+
+/************************************************************
+ * System Errors
+ *************************************************************/
+#define sysErrTimeout (sysErrorClass | 1)
+#define sysErrParamErr (sysErrorClass | 2)
+#define sysErrNoFreeResource (sysErrorClass | 3)
+#define sysErrNoFreeRAM (sysErrorClass | 4)
+#define sysErrNotAllowed (sysErrorClass | 5)
+#define sysErrSemInUse (sysErrorClass | 6)
+#define sysErrInvalidID (sysErrorClass | 7)
+#define sysErrOutOfOwnerIDs (sysErrorClass | 8)
+#define sysErrNoFreeLibSlots (sysErrorClass | 9)
+#define sysErrLibNotFound (sysErrorClass | 10)
+#define sysErrDelayWakened (sysErrorClass | 11) // SysTaskDelay wakened by SysTaskWake before delay completed.
+#define sysErrRomIncompatible (sysErrorClass | 12)
+#define sysErrBufTooSmall (sysErrorClass | 13)
+#define sysErrPrefNotFound (sysErrorClass | 14)
+
+// NotifyMgr error codes:
+#define sysNotifyErrEntryNotFound (sysErrorClass | 16) // could not find registration entry in the list
+#define sysNotifyErrDuplicateEntry (sysErrorClass | 17) // identical entry already exists
+#define sysNotifyErrBroadcastBusy (sysErrorClass | 19) // a broadcast is already in progress - try again later.
+#define sysNotifyErrBroadcastCancelled (sysErrorClass | 20) // a handler cancelled the broadcast
+
+// AMX error codes continued - jb 10/20/98
+#define sysErrMbId (sysErrorClass | 21)
+#define sysErrMbNone (sysErrorClass | 22)
+#define sysErrMbBusy (sysErrorClass | 23)
+#define sysErrMbFull (sysErrorClass | 24)
+#define sysErrMbDepth (sysErrorClass | 25)
+#define sysErrMbEnv (sysErrorClass | 26)
+
+// NotifyMgr Phase #2 Error Codes:
+#define sysNotifyErrQueueFull (sysErrorClass | 27) // deferred queue is full.
+#define sysNotifyErrQueueEmpty (sysErrorClass | 28) // deferred queue is empty.
+#define sysNotifyErrNoStackSpace (sysErrorClass | 29) // not enough stack space for a broadcast
+#define sysErrNotInitialized (sysErrorClass | 30) // manager is not initialized
+
+// AMX error/warning codes continued - jed 9/10/99
+#define sysErrNotAsleep (sysErrorClass | 31) // Task woken by SysTaskWake was not asleep, 1 wake pending
+#define sysErrNotAsleepN (sysErrorClass | 32) // Task woken by SysTaskWake was not asleep, >1 wake pending
+
+
+// Power Manager error codes - should these be located elsewhere? -soe-
+#define pwrErrNone (pwrErrorClass | 0)
+#define pwrErrBacklight (pwrErrorClass | 1)
+#define pwrErrRadio (pwrErrorClass | 2)
+#define pwrErrBeam (pwrErrorClass | 3)
+
+
+
+/************************************************************
+ * System Features
+ *************************************************************/
+#define sysFtrCreator sysFileCSystem // Feature Creator
+
+#define sysFtrNumROMVersion 1 // ROM Version
+ // 0xMMmfsbbb, where MM is major version, m is minor version
+ // f is bug fix, s is stage: 3-release,2-beta,1-alpha,0-development,
+ // bbb is build number for non-releases
+ // V1.12b3 would be: 0x01122003
+ // V2.00a2 would be: 0x02001002
+ // V1.01 would be: 0x01013000
+
+#define sysFtrNumProcessorID 2 // Product id
+ // 0xMMMMRRRR, where MMMM is the processor model and RRRR is the revision.
+#define sysFtrNumProcessorMask 0xFFFF0000 // Mask to obtain processor model
+#define sysFtrNumProcessor328 0x00010000 // Motorola 68328 (Dragonball)
+#define sysFtrNumProcessorEZ 0x00020000 // Motorola 68EZ328 (Dragonball EZ)
+#define sysFtrNumProductID sysFtrNumProcessorID // old (obsolete) define
+
+#define sysFtrNumBacklight 3 // Backlight
+ // bit 0: 1 if present. 0 if Feature does not exist or backlight is not present
+
+#define sysFtrNumEncryption 4 // Which encryption schemes are present
+#define sysFtrNumEncryptionMaskDES 0x00000001 // bit 0: 1 if DES is present
+
+#define sysFtrNumCountry 5 // International ROM identifier
+ // Result is of type CountryType as defined in Preferences.h.
+ // Result is essentially the "default" country for this ROM.
+ // Assume cUnitedStates if sysFtrNumROMVersion >= 02000000
+ // and feature does not exist. Result is in low sixteen bits.
+
+#define sysFtrNumLanguage 6 // Language identifier
+ // Result is of untyped; values are defined in Incs:BuildRules.h
+ // Result is essentially the "default" language for this ROM.
+ // This is new for the WorkPad (v2.0.2) and did NOT exist for any of the
+ // following: GermanPersonal, GermanPro, FrenchPersonal, FrenchPro
+ // Thus we can't really assume anything if the feature doesn't exist,
+ // though the actual language MAY be determined from sysFtrNumCountry,
+ // above. Result is in low sixteen bits.
+
+#define sysFtrNumDisplayDepth 7 // Display depth
+ // Result is the "default" display depth for the screen. (PalmOS 3.0)
+ // This value is used by ScrDisplayMode when setting the default display depth.
+
+#define sysFtrNumHwrMiscFlags 8 // GHwrMiscFlags value (PalmOS 3.1)
+#define sysFtrNumHwrMiscFlagsExt 9 // GHwrMiscFlagsExt value (PalmOS 3.1)
+
+#define sysFtrNumIntlMgr 10
+ // Result is a set of flags that define functionality supported
+ // by the Int'l Manager. (PalmOS 3.1)
+
+#define sysFtrNumEncoding 11
+ // Result is the character encoding (defined in TextMgr.h) supported
+ // by this ROM. If this feature doesn't exist then the assumed encoding
+ // is latin (Windows code page 1252). (PalmOS 3.1)
+
+#define sysFtrDefaultFont 12
+ // Default font ID used for displaying text. (PalmOS 3.1)
+
+#define sysFtrDefaultBoldFont 13
+ // Default font ID used for displaying bold text. (PalmOS 3.1)
+
+#define sysFtrNumGremlinsSupportGlobals 14 // Globals for supporting gremlins.
+ // This value is a pointer to a memory location that stores global variables needed
+ // for intelligently supporting gremlins. Currently, it is only used in Progress.c.
+ // It is only initialized on first use (gremlins and progress bar in combination)
+ // when ERROR_CHECK_LEVEL == ERROR_CHECK_FULL. (PalmOS 3.2)
+
+#define sysFtrNumVendor 15
+ // Result is the vendor id, in the low sixteen bits. (PalmOS 3.3)
+#ifndef PUBLIC_STUFF_STRIPPED
+ // DOLATER: Need more information about what to expect in this feature.
+#endif // PUBLIC_STUFF_STRIPPED
+
+#define sysFtrNumCharEncodingFlags 16
+ // Flags for a given character encoding, specified in TextMgr.h (PalmOS 3.5)
+
+#define sysFtrNumNotifyMgrVersion 17 // version of the NotifyMgr, if any (PalmOS 3.5)
+
+#define sysFtrNumOEMROMVersion 18 // Supplemental ROM version, provided by OEM
+ // This value may be present in OEM devices, and is in the same format
+ // as sysFtrNumROMVersion. (PalmOS 3.5)
+
+#define sysFtrNumErrorCheckLevel 19 // ROM build setting of ERROR_CHECK_LEVEL
+ // May be set to ERROR_CHECK_NONE, ERROR_CHECK_PARTIAL, or ERROR_CHECK_FULL
+ // as defined in <BuildDefines.h>. (PalmOS 3.5)
+
+#define sysFtrNumOEMCompanyID 20 // GHwrOEMCompanyID value (PalmOS 3.5)
+#define sysFtrNumOEMDeviceID 21 // GHwrOEMDeviceID value (PalmOS 3.5)
+#define sysFtrNumOEMHALID 22 // GHwrOEMHALID value (PalmOS 3.5)
+
+
+/************************************************************
+ * ROM token information (for SysGetROMToken, below)
+ *************************************************************/
+// Additional tokens and token information is located in <Hardware.h>
+#define sysROMTokenSnum 'snum' // Memory Card Flash ID (serial number)
+
+
+/************************************************************
+ * Macros for extracting and combining ROM/OS version components
+ *************************************************************/
+
+// ROM/OS stage numbers
+#define sysROMStageDevelopment (0)
+#define sysROMStageAlpha (1)
+#define sysROMStageBeta (2)
+#define sysROMStageRelease (3)
+
+
+// MACRO: sysMakeROMVersion
+//
+// Builds a ROM version value from the major, minor, fix, stage, and build numbers
+//
+#define sysMakeROMVersion(major, minor, fix, stage, buildNum) \
+ ( \
+ (((UInt32)((UInt8)(major) & 0x0FF)) << 24) | \
+ (((UInt32)((UInt8)(minor) & 0x00F)) << 20) | \
+ (((UInt32)((UInt8)(fix) & 0x00F)) << 16) | \
+ (((UInt32)((UInt8)(stage) & 0x00F)) << 12) | \
+ (((UInt32)((UInt16)(buildNum) & 0x0FFF))) \
+ )
+
+
+// Macros for parsing the ROM version number
+// (the system OS version is obtained by calling
+// FtrGet(sysFtrCreator, sysFtrNumROMVersion, dwOSVerP), where dwOSVerP is
+// a pointer to to a UInt32 variable that is to receive the OS version number)
+#define sysGetROMVerMajor(dwROMVer) (((UInt16)((dwROMVer) >> 24)) & 0x00FF)
+#define sysGetROMVerMinor(dwROMVer) (((UInt16)((dwROMVer) >> 20)) & 0x000F)
+#define sysGetROMVerFix(dwROMVer) (((UInt16)((dwROMVer) >> 16)) & 0x000F)
+#define sysGetROMVerStage(dwROMVer) (((UInt16)((dwROMVer) >> 12)) & 0x000F)
+#define sysGetROMVerBuild(dwROMVer) (((UInt16)(dwROMVer)) & 0x0FFF)
+
+
+
+
+/************************************************************
+ * System Types
+ *************************************************************/
+
+// Types of batteries installed.
+typedef enum {
+ sysBatteryKindAlkaline=0,
+ sysBatteryKindNiCad,
+ sysBatteryKindLiIon,
+ sysBatteryKindRechAlk,
+ sysBatteryKindNiMH,
+ sysBatteryKindLiIon1400,
+ sysBatteryKindLast=0xFF // insert new battery types BEFORE this one
+ } SysBatteryKind;
+
+// Different battery states (output of hwrBattery)
+typedef enum {
+ sysBatteryStateNormal=0,
+ sysBatteryStateLowBattery,
+ sysBatteryStateCritBattery,
+ sysBatteryStateShutdown
+ } SysBatteryState;
+
+
+// SysCreateDataBaseList can generate a list of database.
+typedef struct
+ {
+ Char name[dmDBNameLength];
+ UInt32 creator;
+ UInt32 type;
+ UInt16 version;
+ LocalID dbID;
+ UInt16 cardNo;
+ BitmapPtr iconP;
+ } SysDBListItemType;
+
+
+// Structure of a generic message that can be send to a mailbox
+// through the SysMailboxSend call. Note, this structure MUST
+// be CJ_MAXMSZ bytes large, where CJ_MAXMSZ is defined in
+// the AMX includes.
+typedef struct {
+ UInt32 data[3];
+ } SysMailboxMsgType;
+
+
+// Constants used by the SysEvGroupSignal call
+#define sysEvGroupSignalConstant 0
+#define sysEvGroupSignalPulse 1
+
+// Constants used by the SysEvGroupWait call
+#define sysEvGroupWaitOR 0
+#define sysEvGroupWaitAND 1
+
+
+
+/************************************************************
+ * System Pre-defined "file descriptors"
+ * These are used by applications that use the Net Library's
+ * NetLibSelect() call
+ *************************************************************/
+#define sysFileDescStdIn 0
+
+
+/************************************************************
+ * Function Prototypes
+ *************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Prototype for Pilot applications entry point
+UInt32 PilotMain(UInt16 cmd, void *cmdPBP, UInt16 launchFlags);
+
+
+// SystemMgr routines
+void SysUnimplemented(void)
+ SYS_TRAP(sysTrapSysUnimplemented);
+
+void SysColdBoot(void *card0P, UInt32 card0Size,
+ void *card1P, UInt32 card1Size,
+ UInt32 sysCardHeaderOffset)
+ SYS_TRAP(sysTrapSysColdBoot);
+
+void SysInit(void)
+ SYS_TRAP(sysTrapSysInit);
+
+void SysReset(void)
+ SYS_TRAP(sysTrapSysReset);
+
+void SysPowerOn(void *card0P, UInt32 card0Size,
+ void *card1P, UInt32 card1Size,
+ UInt32 sysCardHeaderOffset, Boolean reFormat);
+
+
+void SysDoze(Boolean onlyNMI)
+ SYS_TRAP(sysTrapSysDoze);
+
+Err SysSetPerformance(UInt32 *sysClockP, UInt16 *cpuDutyP)
+ SYS_TRAP(sysTrapSysSetPerformance);
+
+void SysSleep(Boolean untilReset, Boolean emergency)
+ SYS_TRAP(sysTrapSysSleep);
+
+UInt16 SysSetAutoOffTime(UInt16 seconds)
+ SYS_TRAP(sysTrapSysSetAutoOffTime);
+
+UInt16 SysTicksPerSecond(void)
+ SYS_TRAP(sysTrapSysTicksPerSecond);
+
+Err SysLaunchConsole(void)
+ SYS_TRAP(sysTrapSysLaunchConsole);
+
+Boolean SysHandleEvent(EventPtr eventP)
+ SYS_TRAP(sysTrapSysHandleEvent);
+
+void SysUILaunch(void)
+ SYS_TRAP(sysTrapSysUILaunch);
+
+Err SysUIAppSwitch(UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP)
+ SYS_TRAP(sysTrapSysUIAppSwitch);
+
+Err SysCurAppDatabase(UInt16 *cardNoP, LocalID *dbIDP)
+ SYS_TRAP(sysTrapSysCurAppDatabase);
+
+Err SysBroadcastActionCode(UInt16 cmd, MemPtr cmdPBP)
+ SYS_TRAP(sysTrapSysBroadcastActionCode);
+
+Err SysAppLaunch(UInt16 cardNo, LocalID dbID, UInt16 launchFlags,
+ UInt16 cmd, MemPtr cmdPBP, UInt32 *resultP)
+ SYS_TRAP(sysTrapSysAppLaunch);
+
+UInt16 SysNewOwnerID(void)
+ SYS_TRAP(sysTrapSysNewOwnerID);
+
+UInt32 SysSetA5(UInt32 newValue)
+ SYS_TRAP(sysTrapSysSetA5);
+
+// Routines used by startup code
+Err SysAppStartup(SysAppInfoPtr *appInfoPP, MemPtr *prevGlobalsP,
+ MemPtr *globalsPtrP)
+ SYS_TRAP(sysTrapSysAppStartup);
+
+Err SysAppExit(SysAppInfoPtr appInfoP, MemPtr prevGlobalsP, MemPtr globalsP)
+ SYS_TRAP(sysTrapSysAppExit);
+
+
+#if EMULATION_LEVEL != EMULATION_NONE
+// Simulator-specific routines
+MemPtr SysCardImageInfo(UInt16 cardNo, UInt32 *sizeP);
+
+void SysCardImageDeleted(UInt16 cardNo);
+#endif // EMULATION_LEVEL != EMULATION_NONE
+
+UInt16 SysUIBusy(Boolean set, Boolean value)
+ SYS_TRAP(sysTrapSysUIBusy);
+
+UInt8 SysLCDContrast(Boolean set, UInt8 newContrastLevel)
+ SYS_TRAP(sysTrapSysLCDContrast);
+
+UInt8 SysLCDBrightness(Boolean set, UInt8 newBrightnessLevel)
+ SYS_TRAP(sysTrapSysLCDBrightness);
+
+
+// System Dialogs
+void SysBatteryDialog(void)
+ SYS_TRAP(sysTrapSysBatteryDialog);
+
+// Utilities
+Err SysSetTrapAddress(UInt16 trapNum, void *procP)
+ SYS_TRAP(sysTrapSysSetTrapAddress);
+
+void * SysGetTrapAddress(UInt16 trapNum)
+ SYS_TRAP(sysTrapSysGetTrapAddress);
+
+UInt16 SysDisableInts(void)
+ SYS_TRAP(sysTrapSysDisableInts);
+
+void SysRestoreStatus(UInt16 status)
+ SYS_TRAP(sysTrapSysRestoreStatus);
+
+extern Char * SysGetOSVersionString()
+ SYS_TRAP(sysTrapSysGetOSVersionString);
+
+// The following trap is a public definition of HwrGetROMToken from <Hardware.h>
+// See token definitions (like sysROMTokenSerial) above...
+Err SysGetROMToken(UInt16 cardNo, UInt32 token, UInt8 **dataP, UInt16 *sizeP )
+ SYS_TRAP(sysTrapHwrGetROMToken);
+
+
+// Library Management
+Err SysLibInstall(SysLibEntryProcPtr libraryP, UInt16 *refNumP)
+ SYS_TRAP(sysTrapSysLibInstall);
+
+Err SysLibLoad(UInt32 libType, UInt32 libCreator, UInt16 *refNumP)
+ SYS_TRAP(sysTrapSysLibLoad);
+
+
+Err SysLibRemove(UInt16 refNum)
+ SYS_TRAP(sysTrapSysLibRemove);
+
+Err SysLibFind(const Char *nameP, UInt16 *refNumP)
+ SYS_TRAP(sysTrapSysLibFind);
+
+SysLibTblEntryPtr SysLibTblEntry(UInt16 refNum)
+ SYS_TRAP(sysTrapSysLibTblEntry);
+
+// Generic Library calls
+Err SysLibOpen(UInt16 refNum)
+ SYS_TRAP(sysLibTrapOpen);
+Err SysLibClose(UInt16 refNum)
+ SYS_TRAP(sysLibTrapClose);
+Err SysLibSleep(UInt16 refNum)
+ SYS_TRAP(sysLibTrapSleep);
+Err SysLibWake(UInt16 refNum)
+ SYS_TRAP(sysLibTrapWake);
+
+
+//-----------------------------------------------------
+// Kernel Prototypes
+//-----------------------------------------------------
+// Task Creation and deleation
+Err SysTranslateKernelErr(Err err)
+ SYS_TRAP(sysTrapSysTranslateKernelErr);
+
+Err SysTaskCreate(UInt32 *taskIDP, UInt32 *creator, ProcPtr codeP,
+ MemPtr stackP, UInt32 stackSize, UInt32 attr, UInt32 priority,
+ UInt32 tSlice)
+ SYS_TRAP(sysTrapSysTaskCreate);
+
+Err SysTaskDelete(UInt32 taskID, UInt32 priority)
+ SYS_TRAP(sysTrapSysTaskDelete);
+
+Err SysTaskTrigger(UInt32 taskID)
+ SYS_TRAP(sysTrapSysTaskTrigger);
+
+UInt32 SysTaskID()
+ SYS_TRAP(sysTrapSysTaskID);
+
+Err SysTaskDelay(Int32 delay)
+ SYS_TRAP(sysTrapSysTaskDelay);
+
+Err SysTaskSetTermProc(UInt32 taskID, SysTermProcPtr termProcP)
+ SYS_TRAP(sysTrapSysTaskSetTermProc);
+
+Err SysTaskSwitching(Boolean enable)
+ SYS_TRAP(sysTrapSysTaskSwitching);
+
+Err SysTaskWait(Int32 timeout)
+ SYS_TRAP(sysTrapSysTaskWait);
+
+Err SysTaskWake(UInt32 taskID)
+ SYS_TRAP(sysTrapSysTaskWake);
+
+void SysTaskWaitClr(void)
+ SYS_TRAP(sysTrapSysTaskWaitClr);
+
+Err SysTaskSuspend(UInt32 taskID)
+ SYS_TRAP(sysTrapSysTaskSuspend);
+
+Err SysTaskResume(UInt32 taskID)
+ SYS_TRAP(sysTrapSysTaskResume);
+
+
+// Counting Semaphores
+Err SysSemaphoreCreate(UInt32 *smIDP, UInt32 *tagP, Int32 initValue)
+ SYS_TRAP(sysTrapSysSemaphoreCreate);
+
+Err SysSemaphoreDelete(UInt32 smID)
+ SYS_TRAP(sysTrapSysSemaphoreDelete);
+
+Err SysSemaphoreWait(UInt32 smID, UInt32 priority, Int32 timeout)
+ SYS_TRAP(sysTrapSysSemaphoreWait);
+
+Err SysSemaphoreSignal(UInt32 smID)
+ SYS_TRAP(sysTrapSysSemaphoreSignal);
+
+Err SysSemaphoreSet(UInt32 smID)
+ SYS_TRAP(sysTrapSysSemaphoreSet);
+
+
+// Resource Semaphores
+Err SysResSemaphoreCreate(UInt32 *smIDP, UInt32 *tagP)
+ SYS_TRAP(sysTrapSysResSemaphoreCreate);
+
+Err SysResSemaphoreDelete(UInt32 smID)
+ SYS_TRAP(sysTrapSysResSemaphoreDelete);
+
+Err SysResSemaphoreReserve(UInt32 smID, UInt32 priority, Int32 timeout)
+ SYS_TRAP(sysTrapSysResSemaphoreReserve);
+
+Err SysResSemaphoreRelease(UInt32 smID)
+ SYS_TRAP(sysTrapSysResSemaphoreRelease);
+
+
+
+// Timers
+Err SysTimerCreate(UInt32 *timerIDP, UInt32 *tagP,
+ SysTimerProcPtr timerProc, UInt32 periodicDelay,
+ UInt32 param)
+ SYS_TRAP(sysTrapSysTimerCreate);
+
+Err SysTimerDelete(UInt32 timerID)
+ SYS_TRAP(sysTrapSysTimerDelete);
+
+Err SysTimerWrite(UInt32 timerID, UInt32 value)
+ SYS_TRAP(sysTrapSysTimerWrite);
+
+Err SysTimerRead(UInt32 timerID, UInt32 *valueP)
+ SYS_TRAP(sysTrapSysTimerRead);
+
+
+// Information
+Err SysKernelInfo(void *paramP)
+ SYS_TRAP(sysTrapSysKernelInfo);
+
+Boolean SysCreateDataBaseList(UInt32 type, UInt32 creator, UInt16 *dbCount,
+ MemHandle *dbIDs, Boolean lookupName)
+ SYS_TRAP(sysTrapSysCreateDataBaseList);
+
+Boolean SysCreatePanelList(UInt16 *panelCount, MemHandle *panelIDs)
+ SYS_TRAP(sysTrapSysCreatePanelList);
+
+UInt16 SysBatteryInfo(Boolean set, UInt16 *warnThresholdP, UInt16 *criticalThresholdP,
+ Int16 *maxTicksP, SysBatteryKind* kindP, Boolean *pluggedIn, UInt8 *percentP)
+ SYS_TRAP(sysTrapSysBatteryInfo);
+
+UInt16 SysBatteryInfoV20(Boolean set, UInt16 *warnThresholdP, UInt16 *criticalThresholdP,
+ Int16 *maxTicksP, SysBatteryKind* kindP, Boolean *pluggedIn)
+ SYS_TRAP(sysTrapSysBatteryInfoV20);
+
+Boolean SysGetStackInfo(MemPtr *startPP, MemPtr *endPP)
+ SYS_TRAP(sysTrapSysGetStackInfo);
+
+
+
+// Mailboxes
+Err SysMailboxCreate(UInt32 *mbIDP, UInt32 *tagP, UInt32 depth)
+ SYS_TRAP(sysTrapSysMailboxCreate);
+
+Err SysMailboxDelete(UInt32 mbID)
+ SYS_TRAP(sysTrapSysMailboxDelete);
+
+Err SysMailboxFlush(UInt32 mbID)
+ SYS_TRAP(sysTrapSysMailboxFlush);
+
+Err SysMailboxSend(UInt32 mbID, void *msgP, UInt32 wAck)
+ SYS_TRAP(sysTrapSysMailboxSend);
+
+Err SysMailboxWait(UInt32 mbID, void *msgP, UInt32 priority,
+ Int32 timeout)
+ SYS_TRAP(sysTrapSysMailboxWait);
+
+// Event Groups
+Err SysEvGroupCreate(UInt32 *evIDP, UInt32 *tagP, UInt32 init)
+ SYS_TRAP(sysTrapSysEvGroupCreate);
+
+//Err SysEvGroupDelete(UInt32 evID) // save trap table space - don't need
+ //SYS_TRAP(sysTrapSysEvGroupDelete);
+
+Err SysEvGroupSignal(UInt32 evID, UInt32 mask, UInt32 value, Int32 type)
+ SYS_TRAP(sysTrapSysEvGroupSignal);
+
+Err SysEvGroupRead(UInt32 evID, UInt32 *valueP)
+ SYS_TRAP(sysTrapSysEvGroupRead);
+
+Err SysEvGroupWait(UInt32 evID, UInt32 mask, UInt32 value, Int32 matchType,
+ Int32 timeout)
+ SYS_TRAP(sysTrapSysEvGroupWait);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+/************************************************************
+ * Assembly Function Prototypes
+ *************************************************************/
+#define _SysSemaphoreSignal \
+ ASM_SYS_TRAP(sysTrapSysSemaphoreSignal)
+
+#define _SysSemaphoreSet \
+ ASM_SYS_TRAP(sysTrapSysSemaphoreSet)
+
+#define _SysDoze \
+ ASM_SYS_TRAP(sysTrapSysDoze)
+
+
+#endif //__SYSTEMMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SystemPkt.h b/SrcShared/Palm/Platform/Incs/Core/System/SystemPkt.h
new file mode 100644
index 0000000..80c562b
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SystemPkt.h
@@ -0,0 +1,430 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SystemPkt.h
+ *
+ * Description:
+ * Structure of System Packets for the Serial Link Manager. These
+ * packets are used by the Debugger, Console, and Remote UI modules
+ * for communication with the host computer.
+ *
+ * History:
+ * 6/26/95 RM - Created by Ron Marianetti
+ *
+ *****************************************************************************/
+
+#ifndef __SYSTEM_PKT_H__
+#define __SYSTEM_PKT_H__
+
+#include <SerialLinkMgr.h>
+
+
+//*************************************************************************
+// Constants for System Packets
+//
+//*************************************************************************
+
+// Max # of bytes we can read/write at a time with the ReadMem and WriteMem
+// commands;
+#define sysPktMaxMemChunk 256
+
+// Maximum body size for System Packets. This is big enough to have
+// 256 bytes of data for the Read and Write Mem command plus whatever other
+// parameters are in the body for these commands.
+#define sysPktMaxBodySize (sysPktMaxMemChunk+16)
+
+
+// Default nitial timeout value for packet receive routines in ticks
+#define sysPktInitialTimeout (sysTicksPerSecond*10)
+
+
+
+//*************************************************************************
+// Packet Body Structure
+//*************************************************************************
+
+// Common fields at the start of every body
+#define _sysPktBodyCommon \
+ UInt8 command; \
+ UInt8 _filler
+
+
+// Generic System Packet Body
+typedef struct SysPktBodyType {
+ _sysPktBodyCommon;
+ UInt8 data[sysPktMaxBodySize-2];
+ } SysPktBodyType;
+typedef SysPktBodyType* SysPktBodyPtr;
+
+
+
+//*************************************************************************
+// The max size of the array of SlkWriteDataTypes used by System Packet
+// assembly routines in order to minimize stack usage.
+//*************************************************************************
+#define sysPktMaxBodyChunks 3
+
+
+
+//*************************************************************************
+// packet commands
+//*************************************************************************
+
+//--------------------------------------------------------------------
+// get state command
+//--------------------------------------------------------------------
+#define sysPktStateCmd 0x00
+#define sysPktStateRsp 0x80
+
+//--------------------------------------------------------------------
+// read memory command
+//--------------------------------------------------------------------
+#define sysPktReadMemCmd 0x01
+#define sysPktReadMemRsp 0x81
+
+typedef struct SysPktReadMemCmdType {
+ _sysPktBodyCommon; // Common Body header
+ void* address; // Address to read
+ UInt16 numBytes; // # of bytes to read
+ } SysPktReadMemCmdType;
+typedef SysPktReadMemCmdType* SysPktReadMemCmdPtr;
+
+typedef struct SysPktReadMemRspType {
+ _sysPktBodyCommon; // Common Body header
+ // UInt8 data[?]; // variable size
+ } SysPktReadMemRspType;
+typedef SysPktReadMemRspType* SysPktReadMemRspPtr;
+
+
+//--------------------------------------------------------------------
+// write memory command
+//--------------------------------------------------------------------
+#define sysPktWriteMemCmd 0x02
+#define sysPktWriteMemRsp 0x82
+
+typedef struct SysPktWriteMemCmdType {
+ _sysPktBodyCommon; // Common Body header
+ void* address; // Address to write
+ UInt16 numBytes; // # of bytes to write
+ // UInt8 data[?]; // variable size data
+ } SysPktWriteMemCmdType;
+typedef SysPktWriteMemCmdType* SysPktWriteMemCmdPtr;
+
+typedef struct SysPktWriteMemRspType {
+ _sysPktBodyCommon; // Common Body header
+ } SysPktWriteMemRspType;
+typedef SysPktWriteMemRspType* SysPktWriteMemRspPtr;
+
+
+//--------------------------------------------------------------------
+// single-step command
+//--------------------------------------------------------------------
+#define sysPktSingleStepCmd 0x03
+// no response
+
+//--------------------------------------------------------------------
+// get routine name command
+//--------------------------------------------------------------------
+#define sysPktGetRtnNameCmd 0x04
+#define sysPktGetRtnNameRsp 0x84
+
+//--------------------------------------------------------------------
+// read registers command
+//--------------------------------------------------------------------
+#define sysPktReadRegsCmd 0x05
+#define sysPktReadRegsRsp 0x85
+
+
+//--------------------------------------------------------------------
+// write registers command
+//--------------------------------------------------------------------
+#define sysPktWriteRegsCmd 0x06
+#define sysPktWriteRegsRsp 0x86
+
+//--------------------------------------------------------------------
+// continue command
+//--------------------------------------------------------------------
+#define sysPktContinueCmd 0x07
+// no response
+
+
+//--------------------------------------------------------------------
+// Remote Procedure call
+//--------------------------------------------------------------------
+#define sysPktRPCCmd 0x0A
+#define sysPktRPCRsp 0x8A
+
+typedef struct SysPktRPCParamInfo {
+ UInt8 byRef; // true if param is by reference
+ UInt8 size; // # of Bytes of paramData (must be even)
+ UInt16 data[1]; // variable length array of paramData
+ } SysPktRPCParamType;
+
+typedef struct SysPktRPCType {
+ _sysPktBodyCommon; // Common Body header
+ UInt16 trapWord; // which trap to execute
+ UInt32 resultD0; // result from D0 placed here
+ UInt32 resultA0; // result from A0 placed here
+ UInt16 numParams; // how many parameters follow
+ // Following is a variable length array ofSlkRPCParamInfo's
+ SysPktRPCParamType param[1];
+ } SysPktRPCType;
+
+
+//--------------------------------------------------------------------
+// Set/Get breakpoints
+//--------------------------------------------------------------------
+#define sysPktGetBreakpointsCmd 0x0B
+#define sysPktGetBreakpointsRsp 0x8B
+#define sysPktSetBreakpointsCmd 0x0C
+#define sysPktSetBreakpointsRsp 0x8C
+
+
+//--------------------------------------------------------------------
+// Remote UI Support - These packets are used by the screen driver
+// and event manager to support remote viewing and control of a Pilot
+// over the serial port.
+//--------------------------------------------------------------------
+#define sysPktRemoteUIUpdCmd 0x0C
+
+typedef struct SysPktRemoteUIUpdCmdType {
+ _sysPktBodyCommon; // Common Body header
+
+ // These parameters are sent from traget to host after drawing operations
+ UInt16 rowBytes; // rowbytes of update area
+ UInt16 fromY; // top of update rect
+ UInt16 fromX; // left of update rect
+ UInt16 toY; // top of screen rect
+ UInt16 toX; // left of screen rect
+ UInt16 height; // bottom of update rect
+ UInt16 width; // right of update rect
+
+ // The actual pixels of the update area follow
+ UInt16 pixels; // variable length...
+
+ } SysPktRemoteUIUpdCmdType;
+
+
+#define sysPktRemoteEvtCmd 0x0D
+
+typedef struct SysPktRemoteEvtCmdType {
+ _sysPktBodyCommon; // Common Body header
+
+ // These parameters are sent from host to target to feed pen and keyboard
+ // events. They do not require a response.
+ Boolean penDown; // true if pen down
+ UInt8 padding1;
+ Int16 penX; // X location of pen
+ Int16 penY; // Y location of pen
+
+ Boolean keyPress; // true if key event follows
+ UInt8 padding2;
+ UInt16 keyModifiers; // keyboard modifiers
+ WChar keyAscii; // key ascii code
+ UInt16 keyCode; // key virtual code
+
+ } SysPktRemoteEvtCmdType;
+
+
+//--------------------------------------------------------------------
+// Enable/Disable DbgBreak's command
+//--------------------------------------------------------------------
+#define sysPktDbgBreakToggleCmd 0x0D
+#define sysPktDbgBreakToggleRsp 0x8D
+
+
+//--------------------------------------------------------------------
+// Program Flash command - programs one sector of the FLASH ram
+// If numBytes is 0, this routine returns info on the flash in:
+// manuf - manufacturer code
+// device - device code
+//--------------------------------------------------------------------
+#define sysPktFlashCmd 0x0E // OBSOLETE AS OF 3.0! SEE BELOW!
+#define sysPktFlashRsp 0x8E // OSBOLETE AS OF 3.0! SEE BELOW!
+
+
+//--------------------------------------------------------------------
+// Get/Set communication parameters
+//--------------------------------------------------------------------
+#define sysPktCommCmd 0x0F
+#define sysPktCommRsp 0x8F
+
+typedef struct SysPktCommCmdType {
+ _sysPktBodyCommon; // Common Body header
+ Boolean set; // true to change parameters
+ UInt8 padding;
+ UInt32 baudRate; // new baud rate
+ UInt32 flags; // new flags
+ } SysPktCommCmdType;
+typedef SysPktCommCmdType *SysPktCommCmdPtr;
+
+typedef struct SysPktCommRspType {
+ _sysPktBodyCommon; // Common Body header
+ UInt32 baudRate; // current baud rate
+ UInt32 flags; // current flags
+ } SysPktCommRspType;
+typedef SysPktCommRspType *SysPktCommRspPtr;
+
+
+//--------------------------------------------------------------------
+// Get/Set Trap Breaks
+//--------------------------------------------------------------------
+#define sysPktGetTrapBreaksCmd 0x10
+#define sysPktGetTrapBreaksRsp 0x90
+#define sysPktSetTrapBreaksCmd 0x11
+#define sysPktSetTrapBreaksRsp 0x91
+
+
+//--------------------------------------------------------------------
+// Gremlins Support - These packets are used by the screen driver
+// and event manager to support remote viewing and control of a Pilot
+// over the serial port.
+//--------------------------------------------------------------------
+#define sysPktGremlinsCmd 0x12
+
+typedef struct SysPktGremlinsCmdType {
+ _sysPktBodyCommon; // Common Body header
+
+ // These parameters are sent from target to host to send Gremlins stuff
+ UInt16 action;
+ UInt8 data[32];
+
+ } SysPktGremlinsCmdType;
+
+// Gremlins action codes
+#define sysPktGremlinsIdle 1
+#define sysPktGremlinsEvent 2
+
+
+//--------------------------------------------------------------------
+// Find data - searches a range of addresses for data
+//--------------------------------------------------------------------
+#define sysPktFindCmd 0x13
+#define sysPktFindRsp (sysPktFindCmd | 0x80)
+
+typedef struct SysPktFindCmdType {
+ _sysPktBodyCommon; // Common Body header
+
+ UInt32 firstAddr; // first address to search
+ UInt32 lastAddr; // last address to begin searching
+ UInt16 numBytes; // number of data bytes to match
+ Boolean caseInsensitive; // if true, perform a case-insensitive search
+ UInt8 padding;
+ } SysPktFindCmdType;
+typedef SysPktFindCmdType* SysPktFindCmdPtr;
+
+typedef struct SysPktFindRspType {
+ _sysPktBodyCommon; // Common Body header
+
+ UInt32 addr; // address where data was found
+ Boolean found; // true if data was found
+ UInt8 padding;
+
+ } SysPktFindRspType;
+typedef SysPktFindRspType* SysPktFindRspPtr;
+
+
+//--------------------------------------------------------------------
+// Get/Set Trap Conditionals. These are used to tell the debugger
+// to conditionally break on a trap depending on the value of the
+// first word on the stack. They are used when setting a-traps on
+// library calls. This is a 3.0 feature.
+//--------------------------------------------------------------------
+#define sysPktGetTrapConditionsCmd 0x14
+#define sysPktGetTrapConditionsRsp 0x94
+#define sysPktSetTrapConditionsCmd 0x15
+#define sysPktSetTrapConditionsRsp 0x95
+
+
+//--------------------------------------------------------------------
+// Checksum data - checksums a range of memory.
+// This is a (late) 3.0 feature.
+//--------------------------------------------------------------------
+#define sysPktChecksumCmd 0x16
+#define sysPktChecksumRsp (sysPktChecksumCmd | 0x80)
+
+typedef struct SysPktChecksumType {
+ _sysPktBodyCommon; // Common Body header
+
+ UInt32 firstAddr; // -> first address to checksum
+ UInt16 numBytes; // -> number of bytes to checksum
+ UInt16 seed; // -> initial checksum value
+ UInt16 checksum; // <- checksum result
+ } SysPktChecksumType;
+typedef SysPktChecksumType* SysPktChecksumPtr;
+
+
+//--------------------------------------------------------------------
+// NEW Program Flash command - programs one sector of the FLASH ram
+// If numBytes is 0, this routine returns address to store flash code.
+// Supercedes Obsolete 1.0 and 2.0 sysPktFlashCmd call above in the 3.0 ROM
+//--------------------------------------------------------------------
+#define sysPktExecFlashCmd 0x17
+#define sysPktExecFlashRsp (sysPktExecFlashCmd | 0x80)
+
+
+//--------------------------------------------------------------------
+// message from remote unit
+//--------------------------------------------------------------------
+#define sysPktRemoteMsgCmd 0x7f
+
+
+//--------------------------------------------------------------------
+// sysPktRemoteMsg
+// Send a text message
+//--------------------------------------------------------------------
+typedef struct SysPktRemoteMsgCmdType {
+ _sysPktBodyCommon; // Common Body header
+ //UInt8 text; // variable length text goes here
+ } SysPktRemoteMsgCmdType;
+typedef SysPktRemoteMsgCmdType *SysPktRemoteMsgCmdPtr;
+
+
+
+
+
+/*******************************************************************
+ * Prototypes
+ *******************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//================================================================
+//
+// Host Only Routines.
+//
+//================================================================
+#if (EMULATION_LEVEL != EMULATION_NONE)
+
+
+ //-------------------------------------------------------------------
+ // RPC
+ //------------------------------------------------------------------
+ // Init preparate on an RPC packet header and body.
+ Err SlkRPCInitPacket(SlkPktHeaderType *headerP, UInt16 dstSocket,
+ SysPktRPCType *bodyP, UInt16 trapWord);
+
+
+ // Stuff a parameter into an RPC packet body
+ void * SlkRPCStuffParam(SysPktRPCType *bodyP, const void *dataP,
+ Int16 dataSize, Boolean byRef);
+
+ // Send RPC packet and wait for response.
+ Err SlkRPCExecute(SlkPktHeaderPtr headerP, SysPktRPCType *bodyP,
+ Boolean async);
+
+#endif // (EMULATION_LEVEL != EMULATION_NONE)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+#endif //__SYSTEM_PKT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/SystemResources.h b/SrcShared/Palm/Platform/Incs/Core/System/SystemResources.h
new file mode 100644
index 0000000..39b4e92
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/SystemResources.h
@@ -0,0 +1,346 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: SystemResources.h
+ *
+ * Description:
+ * Include file for both PalmRez and the C Compiler. This file contains
+ * equates used by both tools. When compiling using the C compiler
+ * the variable RESOURCE_COMPILER must be defined.
+ *
+ * History:
+ * 02/27/95 ron Created by Ron Marianetti
+ * 08/04/95 vmk Added system resource id for Desktop Link user info
+ * 02/03/98 tlw Changed sysFileCDefaultApp from sysFileCMemory which
+ * no longer exists to sysFileCPreferences.
+ * 6/23/98 jhl Added FlashMgr resource
+ * 06/23/98 jhl Added FlashMgr resource
+ * 05/05/99 kwk Added simulator creator/file types, also the
+ * Japanese user dict panel creator and the TSM
+ * library creator.
+ * 05/06/99 lyl Added OEM System File type
+ * 06/25/99 kwk Added sysResIDAppPrefs & sysResIDOverlayFeatures.
+ * 07/14/99 kwk Added sysResTSilkscreen.
+ * 08/08/99 kwk Added sysFileCJEDict.
+ * 09/20/99 kwk Added keyboard feature for reentrancy check.
+ *
+ *****************************************************************************/
+
+#ifndef __SYSTEMRESOURCES_H__
+#define __SYSTEMRESOURCES_H__
+
+//-----------------------------------------------------------
+// This section is common to both the C and Resource Compiler
+//-----------------------------------------------------------
+
+//................................................................
+// File types and creators
+//
+// Each database shall have a creator ID and a type.
+//
+// The creator ID shall establish which application, patch, or extension
+// a particular database is associated with. The creator ID should identify
+// the application/patch/extension, NOT who created it.
+//
+// The type will determine which part of an application,
+// patch, or extension a particular database is.
+//
+// There can be only one database per application, patch, or extension
+// which has type 'application', 'patch', or 'extension'.
+//
+// Creators:
+//
+// ROM-based applications created by Palm Computing have all-lower case
+// creator ID's. Third-party applications have creator ID's which
+// are either all caps, or mixed case. The same requirements go for
+// system patches and extensions.
+//
+// All applications, system patches and extensions shall have unique creator
+// ID's.
+//
+// Types:
+//
+// 'Application', 'Extension', and 'Patch' file/database types for ROM-based
+// apps shall be all-lower case (they are defined below). Other
+// file/database types must be mixed-case,
+// or all caps. These other types are internal to the applications, and
+// therefore the system is unconcerned with their exact values.
+//................................................................
+#define sysFileCSystem 'psys' // Creator type for System files
+#define sysFileCOEMSystem 'poem' // Creator type for OEM System files
+#define sysFileCGraffiti 'graf' // Creator type for Graffiti databases
+#define sysFileCSystemPatch 'ptch' // Creator for System resource file patches
+
+#define sysFileCCalculator 'calc' // Creator type for Calculator App
+#define sysFileCSecurity 'secr' // Creator type for Security App
+#define sysFileCPreferences 'pref' // Creator type for Preferences App
+#define sysFileCAddress 'addr' // Creator type for Address App
+#define sysFileCToDo 'todo' // Creator type for To Do App
+#define sysFileCDatebook 'date' // Creator type for Datebook App
+#define sysFileCMemo 'memo' // Creator type for MemoPad App
+#define sysFileCSync 'sync' // Creator type for HotSync App
+#define sysFileCMemory 'memr' // Creator type for Memory App
+#define sysFileCMail 'mail' // Creator type for Mail App
+#define sysFileCExpense 'exps' // Creator type for Expense App
+#define sysFileCLauncher 'lnch' // Creator type for Launcher App
+#define sysFileCClipper 'clpr' // Creator type for clipper app.
+#define sysFileCSetup 'setp' // Creator type for setup app.
+#define sysFileCActivate 'actv' // Creator type for activation app.
+#define sysFileCFlashInstaller 'fins' // Creator type for FlashInstaller app.
+#define sysFileCRFDiag 'rfdg' // Creator type for RF diagnostics app.
+#define sysFileCMessaging 'msgs' // Creator type for Messaging App
+#define sysFileCModemFlashTool 'gsmf' // Creator type for Palm V modem flash app.
+#define sysFileCJEDict 'dict' // Creator type for JEDict app.
+#define sysFileHotSyncServer 'srvr' // Creator type for HotSync(R) Server app.
+#define sysFileHotSyncServerUpdate 'hssu' // Creator type for HotSync(R) Server update app.
+
+// The following two apps are manufacturing, calibration and maintenance related
+#define sysFileCMACUtilScreen 'mcut' // Creator type for screen oriented MACUtil app.
+#define sysFileCMACUtilSerial 'mcus' // Creator type for serial line driven MACUtil app.
+#define sysResIDMACUtilAutostart 10000 // Autostart serial MACUtil
+
+// Demo Apps
+#define sysFileCGraffitiDemo 'gdem' // Creator type for Graffiti Demo
+#define sysFileCMailDemo 'mdem' // Creator type for Mail Demo
+
+#define sysFileCFirstApp sysFileCPreferences // Creator type for First App after reset
+#define sysFileCAltFirstApp sysFileCSetup // Creator type for First alternate App after reset (with hard key pressed)
+#define sysFileCDefaultApp sysFileCPreferences // Creator type for Default app
+#define sysFileCDefaultButton1App sysFileCDatebook // Creator type for dflt hard button 1 app
+#define sysFileCDefaultButton2App sysFileCAddress // Creator type for dflt hard button 2 app
+#define sysFileCDefaultButton3App sysFileCToDo // Creator type for dflt hard button 3 app
+#define sysFileCDefaultButton4App sysFileCMemo // Creator type for dflt hard button 4 app
+#define sysFileCDefaultCalcButtonApp sysFileCCalculator // Creator type for dflt calc button app
+#define sysFileCDefaultCradleApp sysFileCSync // Creator type for dflt hot sync button app
+#define sysFileCDefaultModemApp sysFileCSync // Creator type for dflt modem button app
+#define sysFileCDefaultAntennaButtonApp sysFileCLauncher // Creator type for dflt antenna up button app
+#define sysFileCNullApp '0000' // Creator type for non-existing app
+#define sysFileCSimulator '\?\?\?\?' // Creator type for Simulator files (app.tres, sys.tres)
+ // '????' does not compile with VC++ (Elaine Server)
+
+#define sysFileCDigitizer 'digi' // Creator type for Digitizer Panel
+#define sysFileCGeneral 'gnrl' // Creator type for General Panel
+#define sysFileCFormats 'frmt' // Creator type for Formats Panel
+#define sysFileCShortCuts 'shct' // Creator type for ShortCuts Panel
+#define sysFileCButtons 'bttn' // Creator type for Buttons Panel
+#define sysFileCOwner 'ownr' // Creator type for Owner Panel
+#define sysFileCModemPanel 'modm' // Creator type for Modem Panel
+#define sysFileCDialPanel 'dial' // Creator type for Dial Panel
+#define sysFileCNetworkPanel 'netw' // Creator type for Network Panel
+#define sysFileCWirelessPanel 'wrls' // Creator type for the wireless Panel.
+#define sysFileCUserDict 'udic' // Creator type for the UserDict panel.
+#define sysFileCPADHtal 'hpad' // Creator type for PAD HTAL lirary
+#define sysFileCTCPHtal 'htcp' // Creator type for TCP HTAL lirary
+#define sysFileCMineHunt 'mine' // Creator type for MineHunt App
+#define sysFileCPuzzle15 'puzl' // Creator type for Puzzle "15" App
+#define sysFileCOpenLibInfo 'olbi' // Creator type for Feature Manager features
+ // used for saving open library info under PalmOS v1.x
+#define sysFileCHwrFlashMgr 'flsh' // Creator type for HwrFlashMgr features
+
+// Libraries. If the resource used by these are expected to be treated as part of
+// the system's usage then the Memory app must be changed.
+#define sysFileTLibrary 'libr' // File type of Shared Libraries
+#define sysFileTLibraryExtension 'libx' // File type of library extensions
+
+#define sysFileCNet 'netl' // Creator type for Net (TCP/IP) Library
+#define sysFileCRmpLib 'netp' // Creator type for RMP Library (NetLib plug-in)
+#define sysFileCINetLib 'inet' // Creator type for INet Library
+#define sysFileCSecLib 'secl' // Creator type for Ir Library
+#define sysFileCWebLib 'webl' // Creator type for Web Library
+#define sysFileCIrLib 'irda' // Creator type for Ir Library
+
+#define sysFileCSerialMgr 'smgr' // Creator for SerialMgrNew used for features.
+#define sysFileCSerialWrapper 'swrp' // Creator type for Serial Wrapper Library.
+#define sysFileCIrSerialWrapper 'iwrp' // Creator type for Ir Serial Wrapper Library.
+#define sysFileCTextServices 'tsml' // Creator type for Text Services Library.
+
+#define sysFileTUartPlugIn 'sdrv' // File type for SerialMgrNew physical port plug-in.
+#define sysFileTVirtPlugin 'vdrv' // Flir type for SerialMgrNew virtual port plug-in.
+#define sysFileCUart328 'u328' // Creator type for '328 UART plug-in
+#define sysFileCUart328EZ 'u8EZ' // Creator type for '328EZ UART plug-in
+#define sysFileCUart650 'u650' // Creator type for '650 UART plug-in
+#define sysFileCVirtIrComm 'ircm' // Creator type for IrComm virtual port plug-in.
+
+#define sysFileTSystem 'rsrc' // File type for Main System File
+#define sysFileTSystemPatch 'ptch' // File type for System resource file patches
+#define sysFileTKernel 'krnl' // File type for System Kernel (AMX)
+#define sysFileTBoot 'boot' // File type for SmallROM System File
+#define sysFileTSmallHal 'shal' // File type for SmallROM HAL File
+#define sysFileTBigHal 'bhal' // File type for Main ROM HAL File
+#define sysFileTSplash 'spls' // File type for Main ROM Splash File
+#define sysFileTUIAppShell 'uish' // File type for UI Application Shell
+#define sysFileTOverlay 'ovly' // File type for UI overlay database
+#define sysFileTExtension 'extn' // File type for System Extensions
+#define sysFileTApplication 'appl' // File type for applications
+#define sysFileTPanel 'panl' // File type for preference panels
+#define sysFileTSavedPreferences 'sprf' // File type for saved preferences
+#define sysFileTPreferences 'pref' // File type for preferences
+#define sysFileTMidi 'smfr' // File type for Standard MIDI File record databases
+#define sysFileTpqa 'pqa ' // File type for the PQA files.
+
+#define sysFileTUserDictionary 'dict' // File type for input method user dictionary.
+#define sysFileTLearningData 'lean' // File type for input method learning data.
+
+#define sysFileTGraffitiMacros 'macr' // Graffiti Macros database
+
+#define sysFileTHtalLib 'htal' // HTAL library
+
+#define sysFileTExgLib 'exgl' // Type of Exchange libraries
+
+#define sysFileTFileStream 'strm' // Default File Stream database type
+
+#define sysFileTTemp 'temp' // Temporary database type; in future versions
+ // of PalmOS (although likely not before 3.3), the
+ // system may automatically delete any db's of
+ // this type at reset time (however, apps are still
+ // responsible for deleting the ones they create
+ // before exiting to protect valuable storage space)
+
+#define sysFileTScriptPlugin 'scpt' // File type for plugin to the Network Panel to
+ //extend scripting capabilities.
+
+#define sysFileTSimulator '\?\?\?\?' // File type for Simulator files (app.tres, sys.tres)
+ // '????' does not compile with VC++ (Elaine Server)
+
+//................................................................
+// Resource types and IDs
+//................................................................
+#define sysResTBootCode 'boot' // Resource type of boot resources
+#define sysResIDBootReset 10000 // Reset code
+#define sysResIDBootInitCode 10001 // Init code
+#define sysResIDBootSysCodeStart 10100 // System code resources start here
+#define sysResIDBootSysCodeMin 10102 // IDs 'Start' to this must exist!!
+#define sysResIDBootUICodeStart 10200 // UI code resources start here
+#define sysResIDBootUICodeMin 10203 // IDs 'Start' to this must exist!!
+
+#define sysResIDBootHAL 19000 // HAL code resource (from HAL.prc)
+
+#define sysResIDBitmapSplash 19000 // ID of (boot) splash screen bitmap
+#define sysResIDBitmapConfirm 19001 // ID of hard reset confirmation bitmap
+
+#define sysResTAppPrefs 'pref' // Resource type of App preferences resources
+#define sysResIDAppPrefs 0 // Application preference
+
+#define sysResTExtPrefs 'xprf' // Resource type of extended preferences
+#define sysResIDExtPrefs 0 // Extended preferences
+
+#define sysResTAppCode 'code' // Resource type of App code resources
+#define sysResTAppGData 'data' // Resource type of App global data resources
+
+#define sysResTExtensionCode 'extn' // Resource type of Extensions code
+#define sysResTExtensionOEMCode 'exte' // Resource type of OEM Extensions code
+
+#define sysResTFeatures 'feat' // Resource type of System features table
+#define sysResIDFeatures 10000 // Resource ID of System features table
+#define sysResIDOverlayFeatures 10001 // Resource ID of system overlay feature table.
+
+#define sysResTCountries 'cnty' // Resource type of System countries table
+#define sysResIDCountries 10000 // Resource ID of System countries table
+
+#define sysResTLibrary 'libr' // Resource type of System Libraries
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER - obsolete, should be removed:
+#endif // PUBLIC_STUFF_STRIPPED
+//#define sysResIDLibrarySerMgr328 10000 // Dragonball (68328) UART
+//#define sysResIDLibrarySerMgr681 10001 // 68681 UART
+//#define sysResIDLibraryRMPPlugIn 10002 // Reliable Message Protocol NetLib Plug-in
+
+#define sysResTSilkscreen 'silk' // Resource type of silkscreen info.
+
+#define sysResTGrfTemplate 'tmpl' // Graffiti templates "file"
+#define sysResIDGrfTemplate 10000 // Graffiti templates "file" ID
+#define sysResTGrfDictionary 'dict' // Graffiti dictionary "file"
+#define sysResIDGrfDictionary 10000 // Graffiti dictionary "file" ID
+#define sysResIDGrfDefaultMacros 10000 // sysResTDefaultDB resource with Graffiti Macros database
+
+#define sysResTDefaultDB 'dflt' // Default database resource type
+#define sysResIDDefaultDB 1 // resource ID of sysResTDefaultDB in each app
+
+#define sysResTErrStrings 'tSTL' // list of error strings
+#define sysResIDErrStrings 10000 // resource ID is (errno>>8)+sysResIDErrStrings
+
+#define sysResIDOEMDBVersion 20001 // resource ID of "tver" and "tint" versions in OEM stamped databases
+
+// System Preferences
+#define sysResTSysPref sysFileCSystem
+#define sysResIDSysPrefMain 0 // Main preferences
+#define sysResIDSysPrefPassword 1 // Password
+#define sysResIDSysPrefFindStr 2 // Find string
+#define sysResIDSysPrefCalibration 3 // Digitizer calibration.
+#define sysResIDDlkUserInfo 4 // Desktop Link user information.
+#define sysResIDDlkLocalPC 5 // Desktop Link local PC host name
+#define sysResIDDlkCondFilterTab 6 // Desktop Link conduit filter table
+#define sysResIDModemMgrPref 7 // Modem Manager preferences
+#define sysResIDDlkLocalPCAddr 8 // Desktop Link local PC host address
+#define sysResIDDlkLocalPCMask 9 // Desktop Link local PC host subnet mask
+
+// These prefs store parameters to pass to an app when launched with a button
+#define sysResIDButton1Param 10 // Parameter for hard button 1 app
+#define sysResIDButton2Param 11 // Parameter for hard button 2 app
+#define sysResIDButton3Param 12 // Parameter for hard button 3 app
+#define sysResIDButton4Param 13 // Parameter for hard button 4 app
+#define sysResIDCalcButtonParam 14 // Parameter for calc button app
+#define sysResIDCradleParam 15 // Parameter for hot sync button app
+#define sysResIDModemParam 16 // Parameter for modem button app
+#define sysResIDAntennaButtonParam 17 // Parameter for antenna up button app
+
+// New for Color, user's color preferences
+#define sysResIDPrefUIColorTableBase 17 // base + depth = ID of actual pref
+#define sysResIDPrefUIColorTable1 18 // User's UI colors for 1bpp displays
+#define sysResIDPrefUIColorTable2 19 // User's UI colors for 2bpp displays
+#define sysResIDPrefUIColorTable4 21 // User's UI colors for 4bpp displays
+#define sysResIDPrefUIColorTable8 25 // User's UI colors for 8bpp displays
+
+// FlashMgr Resources - old
+#define sysResTFlashMgr 'flsh'
+#define sysResIDFlashMgrWorkspace 1 // RAM workspace during flash activity
+
+// FlashMgr Resources - new
+#define sysResTHwrFlashIdent 'flid' // Flash identification code resource
+#define sysResIDHwrFlashIdent 10000 // Flash identification code resource
+
+#define sysResTHwrFlashCode 'flcd' // Flash programming code resource
+ // (resource ID determined by device type)
+
+// OEM Feature type and id.
+#define sysFtrTOEMSys sysFileCOEMSystem
+#define sysFtrIDOEMSysHideBatteryGauge 1
+
+// Onscreen keyboard features
+#define sysFtrTKeyboard 'keyb'
+#define sysFtrIDKeyboardActive 1 // Boolean value, true => keyboard is active.
+ // Currently only used for Japanese.
+
+// Activation status values.
+#define sysActivateStatusFeatureIndex 1
+#define sysActivateNeedGeorgeQuery 0
+#define sysActivateNeedMortyQuery 1
+#define sysActivateFullyActivated 2
+
+#define sysMaxUserDomainNameLength 64
+
+// Current clipper feature indeces
+#define sysClipperPQACardNoIndex 1
+#define sysClipperPQADbIDIndex 2
+
+//-----------------------------------------------------------
+// This section is only valid when running the resource compiler
+//
+// Actually, this section is obsolete. Instear, .r files should
+// inlude SysResTypes.rh to get these definitions.
+//
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥ leaving this here for now just in case.
+#endif // PUBLIC_STUFF_STRIPPED
+//-----------------------------------------------------------
+
+#ifdef RESOURCE_COMPILER
+
+#include <SysResTypes.rh>
+
+#endif
+
+
+#endif // __SYSTEMRESOURCES_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/TextMgr.h b/SrcShared/Palm/Platform/Incs/Core/System/TextMgr.h
new file mode 100644
index 0000000..baed10f
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/TextMgr.h
@@ -0,0 +1,411 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1998-2000 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: TextMgr.h
+ *
+ * Release:
+ *
+ * Description:
+ * Header file for Text Manager.
+ *
+ * History:
+ * 03/05/98 kwk Created by Ken Krugler.
+ * 02/02/99 kwk Added charEncodingPalmLatin & charEncodingPalmSJIS,
+ * since we've extended the CP1252 & CP932 encodings.
+ * Added TxtUpperStr, TxtLowerStr, TxtUpperChar, and
+ * TxtLowerChar macros.
+ * 03/11/99 kwk Changed TxtTruncate to TxtGetTruncationOffset.
+ * 04/24/99 kwk Moved string & character upper/lower casing macros
+ * to IntlGlue library.
+ * 04/28/99 kwk Changed kMaxCharSize to maxCharBytes, as per Roger's request.
+ * 05/15/99 kwk Changed TxtIsValidChar to TxtCharIsValid.
+ * 05/29/99 kwk Removed include of CharAttr.h.
+ * 07/13/99 kwk Moved TxtPrepFindString into TextPrv.h
+ * 09/22/99 kwk Added TxtParamString (OS 3.5).
+ * 10/28/99 kwk Added the TxtCharIsVirtual macro.
+ * 03/01/00 kwk Added the TxtConvertEncoding routine (OS 4.0), and the
+ * txtErrUnknownEncoding and txtErrConvertOverflow errors.
+ * 05/12/00 kwk Deprecated the TxtCharWidth routine.
+ * 05/26/00 kwk Added TxtGetWordWrapOffset (OS 4.0). Convert CharEncodingType
+ * to #define format versus enums. Re-ordered into logical
+ * groups, and fixed up names to match existing convention.
+ * 05/30/00 kwk Added txtErrTranslitUnderflow.
+ * 06/02/00 CS Moved character encoding constants to PalmLocale.h so that
+ * Rez has access to them.
+ * 07/13/00 kwk Added TxtNameToEncoding (OS 4.0).
+ * 07/23/00 kwk Updated TxtConvertEncoding to match new API.
+ * 10/05/00 kwk Added charAttr_<whatever> as substitutes for the old
+ * character attribute flags in CharAttr.h (e.g. _XA, _LO).
+ * kwk Moved sizeOf7BitChar here from CharAttr.h
+ * 11/21/00 kwk Undeprecated TxtCharWidth, in anticipation of future,
+ * proper deprecation.
+ * 11/24/00 kwk Reverted maxCharBytes to 3 (was 4). You only need more than
+ * three bytes for surrogate Unicode characters, which we don't
+ * support, as this would require a 32 bit WChar variable to
+ * hold the result (potentially 21 bits of data). Since we
+ * never use more than 3 bytes, it's OK to shrink this back down.
+ *
+ *****************************************************************************/
+
+#ifndef __TEXTMGR_H__
+#define __TEXTMGR_H__
+
+#include <IntlMgr.h>
+#include <Chars.h>
+
+/***********************************************************************
+ * Public types & constants
+ ***********************************************************************/
+
+// See PalmLocale.h for encoding constants of type CharEncodingType, and
+// character encoding names.
+typedef UInt8 CharEncodingType;
+
+// Transliteration operations for the TxtTransliterate call. We don't use
+// an enum, since each character encoding contains its own set of special
+// transliteration operations (which begin at translitOpCustomBase).
+typedef UInt16 TranslitOpType;
+
+// Standard transliteration operations.
+#define translitOpStandardBase 0 // Beginning of standard operations.
+
+#define translitOpUpperCase 0
+#define translitOpLowerCase 1
+#define translitOpReserved2 2
+#define translitOpReserved3 3
+
+// Custom transliteration operations (defined in CharXXXX.h encoding-specific
+// header files.
+#define translitOpCustomBase 1000 // Beginning of char-encoding specific ops.
+
+#define translitOpPreprocess 0x8000 // Mask for pre-process option, where
+ // no transliteration actually is done.
+
+// Structure used to maintain state across calls to TxtConvertEncoding, for
+// proper handling of source or destination encodings with have modes.
+#define kTxtConvertStateSize 32
+
+typedef struct {
+ UInt8 ioSrcState[kTxtConvertStateSize];
+ UInt8 ioDstState[kTxtConvertStateSize];
+} TxtConvertStateType;
+
+// Flags available in the sysFtrNumCharEncodingFlags feature attribute.
+#define charEncodingOnlySingleByte 0x00000001
+#define charEncodingHasDoubleByte 0x00000002
+#define charEncodingHasLigatures 0x00000004
+#define charEncodingLeftToRight 0x00000008
+
+// Various byte attribute flags. Note that multiple flags can be
+// set, thus a byte could be both a single-byte character, or the first
+// byte of a multi-byte character.
+#define byteAttrFirst 0x80 // First byte of multi-byte char.
+#define byteAttrLast 0x40 // Last byte of multi-byte char.
+#define byteAttrMiddle 0x20 // Middle byte of muli-byte char.
+#define byteAttrSingle 0x01 // Single byte.
+
+// Character attribute flags. These replace the old flags defined in
+// CharAttr.h, but are bit-compatible.
+#define charAttr_XA 0x0200 // extra alphabetic
+#define charAttr_XS 0x0100 // extra space
+#define charAttr_BB 0x0080 // BEL, BS, etc.
+#define charAttr_CN 0x0040 // CR, FF, HT, NL, VT
+#define charAttr_DI 0x0020 // '0'-'9'
+#define charAttr_LO 0x0010 // 'a'-'z' and lowercase extended chars.
+#define charAttr_PU 0x0008 // punctuation
+#define charAttr_SP 0x0004 // space
+#define charAttr_UP 0x0002 // 'A'-'Z' and uppercase extended chars.
+#define charAttr_XD 0x0001 // '0'-'9', 'A'-'F', 'a'-'f'
+
+// Various sets of character attribute flags.
+#define charAttrPrint (charAttr_DI|charAttr_LO|charAttr_PU|charAttr_SP|charAttr_UP|charAttr_XA)
+#define charAttrSpace (charAttr_CN|charAttr_SP|charAttr_XS)
+#define charAttrAlNum (charAttr_DI|charAttr_LO|charAttr_UP|charAttr_XA)
+#define charAttrAlpha (charAttr_LO|charAttr_UP|charAttr_XA)
+#define charAttrCntrl (charAttr_BB|charAttr_CN)
+#define charAttrGraph (charAttr_DI|charAttr_LO|charAttr_PU|charAttr_UP|charAttr_XA)
+#define charAttrDelim (charAttr_SP|charAttr_PU)
+
+// Remember that sizeof(0x0D) == 2 because 0x0D is treated like an int. The
+// same is true of sizeof('a'), sizeof('\0'), and sizeof(chrNull). For this
+// reason it's safest to use the sizeOf7BitChar macro to document buffer size
+// and string length calcs. Note that this can only be used with low-ascii
+// characters, as anything else might be the high byte of a double-byte char.
+#define sizeOf7BitChar(c) 1
+
+// Maximum size a single WChar character will occupy in a text string.
+#define maxCharBytes 3
+
+// Text manager error codes.
+#define txtErrUknownTranslitOp (txtErrorClass | 1)
+#define txtErrTranslitOverrun (txtErrorClass | 2)
+#define txtErrTranslitOverflow (txtErrorClass | 3)
+#define txtErrConvertOverflow (txtErrorClass | 4)
+#define txtErrConvertUnderflow (txtErrorClass | 5)
+#define txtErrUnknownEncoding (txtErrorClass | 6)
+#define txtErrNoCharMapping (txtErrorClass | 7)
+#define txtErrTranslitUnderflow (txtErrorClass | 8)
+
+/***********************************************************************
+ * Public macros
+ ***********************************************************************/
+
+#define TxtCharIsSpace(ch) ((TxtCharAttr(ch) & charAttrSpace) != 0)
+#define TxtCharIsPrint(ch) ((TxtCharAttr(ch) & charAttrPrint) != 0)
+#define TxtCharIsDigit(ch) ((TxtCharAttr(ch) & charAttr_DI) != 0)
+#define TxtCharIsAlNum(ch) ((TxtCharAttr(ch) & charAttrAlNum) != 0)
+#define TxtCharIsAlpha(ch) ((TxtCharAttr(ch) & charAttrAlpha) != 0)
+#define TxtCharIsCntrl(ch) ((TxtCharAttr(ch) & charAttrCntrl) != 0)
+#define TxtCharIsGraph(ch) ((TxtCharAttr(ch) & charAttrGraph) != 0)
+#define TxtCharIsLower(ch) ((TxtCharAttr(ch) & charAttr_LO) != 0)
+#define TxtCharIsPunct(ch) ((TxtCharAttr(ch) & charAttr_PU) != 0)
+#define TxtCharIsUpper(ch) ((TxtCharAttr(ch) & charAttr_UP) != 0)
+#define TxtCharIsHex(ch) ((TxtCharAttr(ch) & charAttr_XD) != 0)
+#define TxtCharIsDelim(ch) ((TxtCharAttr(ch) & charAttrDelim) != 0)
+
+// <c> is a hard key if the event modifier <m> has the command bit set
+// and <c> is either in the proper range or is the calculator character.
+#define TxtCharIsHardKey(m, c) ((((m) & commandKeyMask) != 0) && \
+ ((((c) >= hardKeyMin) && ((c) <= hardKeyMax)) || ((c) == calcChr)))
+
+// <c> is a virtual character if the event modifier <m> has the command
+// bit set. WARNING!!! This macro is only safe to use on Palm OS 3.5 or
+// later. With earlier versions of the OS, use TxtGlueCharIsVirtual()
+// in PalmOSGlue.lib
+#define TxtCharIsVirtual(m, c) (((m) & commandKeyMask) != 0)
+
+#define TxtPreviousCharSize(inText, inOffset) TxtGetPreviousChar((inText), (inOffset), NULL)
+#define TxtNextCharSize(inText, inOffset) TxtGetNextChar((inText), (inOffset), NULL)
+
+
+/***********************************************************************
+ * Public routines
+ ***********************************************************************/
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Return back byte attribute (first, last, single, middle) for <inByte>.
+
+UInt8 TxtByteAttr(UInt8 inByte)
+ INTL_TRAP(intlTxtByteAttr);
+
+// Return back the standard attribute bits for <inChar>.
+
+UInt16 TxtCharAttr(WChar inChar)
+ INTL_TRAP(intlTxtCharAttr);
+
+// Return back the extended attribute bits for <inChar>.
+
+UInt16 TxtCharXAttr(WChar inChar)
+ INTL_TRAP(intlTxtCharXAttr);
+
+// Return the size (in bytes) of the character <inChar>. This represents
+// how many bytes would be required to store the character in a string.
+
+UInt16 TxtCharSize(WChar inChar)
+ INTL_TRAP(intlTxtCharSize);
+
+// Return the width (in pixels) of the character <inChar>. You should
+// use FntWCharWidth or FntGlueWCharWidth instead of this routine.
+
+Int16 TxtCharWidth(WChar inChar)
+ INTL_TRAP(intlTxtCharWidth);
+
+// Load the character before offset <inOffset> in the <inText> text. Return
+// back the size of the character.
+
+UInt16 TxtGetPreviousChar(const Char *inText, UInt32 inOffset, WChar *outChar)
+ INTL_TRAP(intlTxtGetPreviousChar);
+
+// Load the character at offset <inOffset> in the <inText> text. Return
+// back the size of the character.
+
+UInt16 TxtGetNextChar(const Char *inText, UInt32 inOffset, WChar *outChar)
+ INTL_TRAP(intlTxtGetNextChar);
+
+// Return the character at offset <inOffset> in the <inText> text.
+
+WChar TxtGetChar(const Char *inText, UInt32 inOffset)
+ INTL_TRAP(intlTxtGetChar);
+
+// Set the character at offset <inOffset> in the <inText> text, and
+// return back the size of the character.
+
+UInt16 TxtSetNextChar(Char *ioText, UInt32 inOffset, WChar inChar)
+ INTL_TRAP(intlTxtSetNextChar);
+
+// Replace the substring "^X" (where X is 0..9, as specified by <inParamNum>)
+// with the string <inParamStr>. If <inParamStr> is NULL then don't modify <ioStr>.
+// Make sure the resulting string doesn't contain more than <inMaxLen> bytes,
+// excluding the terminating null. Return back the number of occurances of
+// the substring found in <ioStr>.
+
+UInt16 TxtReplaceStr(Char *ioStr, UInt16 inMaxLen, const Char *inParamStr, UInt16 inParamNum)
+ INTL_TRAP(intlTxtReplaceStr);
+
+// Allocate a handle containing the result of substituting param0...param3
+// for ^0...^3 in <inTemplate>, and return the locked result. If a parameter
+// is NULL, replace the corresponding substring in the template with "".
+
+Char *TxtParamString(const Char *inTemplate, const Char *param0,
+ const Char *param1, const Char *param2, const Char *param3)
+ INTL_TRAP(intlTxtParamString);
+
+// Return the bounds of the character at <inOffset> in the <inText>
+// text, via the <outStart> & <outEnd> offsets, and also return the
+// actual value of character at or following <inOffset>.
+
+WChar TxtCharBounds(const Char *inText, UInt32 inOffset, UInt32 *outStart, UInt32 *outEnd)
+ INTL_TRAP(intlTxtCharBounds);
+
+// Return the appropriate byte position for truncating <inText> such that it is
+// at most <inOffset> bytes long.
+
+UInt32 TxtGetTruncationOffset(const Char *inText, UInt32 inOffset)
+ INTL_TRAP(intlTxtGetTruncationOffset);
+
+// Search for <inTargetStr> in <inSourceStr>. If found return true and pass back
+// the found position (byte offset) in <outPos>, and the length of the matched
+// text in <outLength>.
+
+Boolean TxtFindString(const Char *inSourceStr, const Char *inTargetStr,
+ UInt32 *outPos, UInt16 *outLength)
+ INTL_TRAP(intlTxtFindString);
+
+// Find the bounds of the word that contains the character at <inOffset>.
+// Return the offsets in <*outStart> and <*outEnd>. Return true if the
+// word we found was not empty & not a delimiter (attribute of first char
+// in word not equal to space or punct).
+
+Boolean TxtWordBounds(const Char *inText, UInt32 inLength, UInt32 inOffset,
+ UInt32 *outStart, UInt32 *outEnd)
+ INTL_TRAP(intlTxtWordBounds);
+
+// Return the offset of the first break position (for text wrapping) that
+// occurs at or before <iOffset> in <iTextP>. Note that this routine will
+// also add trailing spaces and a trailing linefeed to the break position,
+// thus the result could be greater than <iOffset>.
+
+UInt32 TxtGetWordWrapOffset(const Char *iTextP, UInt32 iOffset)
+ INTL_TRAP(intlTxtGetWordWrapOffset);
+
+// Return the minimum (lowest) encoding required for <inChar>. If we
+// don't know about the character, return encoding_Unknown.
+
+CharEncodingType TxtCharEncoding(WChar inChar)
+ INTL_TRAP(intlTxtCharEncoding);
+
+// Return the minimum (lowest) encoding required to represent <inStr>.
+// This is the maximum encoding of any character in the string, where
+// highest is unknown, and lowest is ascii.
+
+CharEncodingType TxtStrEncoding(const Char *inStr)
+ INTL_TRAP(intlTxtStrEncoding);
+
+// Return the higher (max) encoding of <a> and <b>.
+
+CharEncodingType TxtMaxEncoding(CharEncodingType a, CharEncodingType b)
+ INTL_TRAP(intlTxtMaxEncoding);
+
+// Return a pointer to the 'standard' name for <inEncoding>. If the
+// encoding is unknown, return a pointer to an empty string.
+
+const Char *TxtEncodingName(CharEncodingType inEncoding)
+ INTL_TRAP(intlTxtEncodingName);
+
+// Map from a character set name <iEncodingName> to a CharEncodingType.
+// If the character set name is unknown, return charEncodingUnknown.
+
+CharEncodingType TxtNameToEncoding(const Char* iEncodingName)
+ INTL_TRAP(intlTxtNameToEncoding);
+
+// Transliterate <inSrcLength> bytes of text found in <inSrcText>, based
+// on the requested <inOp> operation. Place the results in <outDstText>,
+// and set the resulting length in <ioDstLength>. On entry <ioDstLength>
+// must contain the maximum size of the <outDstText> buffer. If the
+// buffer isn't large enough, return an error (note that outDestText
+// might have been modified during the operation). Note that if <inOp>
+// has the preprocess bit set, then <outDstText> is not modified, and
+// <ioDstLength> will contain the total space required in the destination
+// buffer in order to perform the operation.
+
+Err TxtTransliterate(const Char *inSrcText, UInt16 inSrcLength, Char *outDstText,
+ UInt16 *ioDstLength, TranslitOpType inOp)
+ INTL_TRAP(intlTxtTransliterate);
+
+// Convert <*ioSrcBytes> of text from <srcTextP> between the <srcEncoding>
+// and <dstEncoding> character encodings. If <dstTextP> is not NULL, write
+// the resulting bytes to the buffer, and always return the number of
+// resulting bytes in <*ioDstBytes>. Update <*srcBytes> with the number of
+// bytes from the beginning of <*srcTextP> that were successfully converted.
+// When the routine is called with <srcTextP> pointing to the beginning of
+// a string or text buffer, <newConversion> should be true; if the text is
+// processed in multiple chunks, either because errors occurred or due to
+// source/destination buffer size constraints, then subsequent calls to
+// this routine should pass false for <newConversion>. The TxtConvertStateType
+// record maintains state information so that if the source or destination
+// character encodings have state or modes (e.g. JIS), processing a single
+// sequence of text with multiple calls will work correctly.
+
+// When an error occurs due to an unconvertable character, the behavior of
+// the routine will depend on the <substitutionStr> parameter. If it is NULL,
+// then <*ioSrcBytes> will be set to the offset of the unconvertable character,
+// <ioDstBytes> will be set to the number of successfully converted resulting
+// bytes, and <dstTextP>, in not NULL, will contain conversion results up to
+// the point of the error. The routine will return an appropriate error code,
+// and it is up to the caller to either terminate conversion or skip over the
+// unconvertable character and continue the conversion process (passing false
+// for the <newConversion> parameter in subsequent calls to TxtConvertEncoding).
+// If <substitutionStr> is not NULL, then this string is written to the
+// destination buffer when an unconvertable character is encountered in the
+// source text, and the source character is skipped. Processing continues, though
+// the error code will still be returned when the routine terminates. Note that
+// if a more serious error occurs during processing (e.g. buffer overflow) then
+// that error will be returned even if there was an earlier unconvertable character.
+// Note that the substitution string must use the destination character encoding.
+
+Err TxtConvertEncoding(Boolean newConversion, TxtConvertStateType* ioStateP,
+ const Char* srcTextP, UInt16* ioSrcBytes, CharEncodingType srcEncoding,
+ Char* dstTextP, UInt16* ioDstBytes, CharEncodingType dstEncoding,
+ const Char* substitutionStr, UInt16 substitutionLen)
+ INTL_TRAP(intlTxtConvertEncoding);
+
+// Return true if <inChar> is a valid (drawable) character. Note that we'll
+// return false if it is a virtual character code.
+
+Boolean TxtCharIsValid(WChar inChar)
+ INTL_TRAP(intlTxtCharIsValid);
+
+// Compare the first <s1Len> bytes of <s1> with the first <s2Len> bytes
+// of <s2>. Return the results of the comparison: < 0 if <s1> sorts before
+// <s2>, > 0 if <s1> sorts after <s2>, and 0 if they are equal. Also return
+// the number of bytes that matched in <s1MatchLen> and <s2MatchLen>
+// (either one of which can be NULL if the match length is not needed).
+// This comparison is "caseless", in the same manner as a find operation,
+// thus case, character size, etc. don't matter.
+
+Int16 TxtCaselessCompare(const Char *s1, UInt16 s1Len, UInt16 *s1MatchLen,
+ const Char *s2, UInt16 s2Len, UInt16 *s2MatchLen)
+ INTL_TRAP(intlTxtCaselessCompare);
+
+// Compare the first <s1Len> bytes of <s1> with the first <s2Len> bytes
+// of <s2>. Return the results of the comparison: < 0 if <s1> sorts before
+// <s2>, > 0 if <s1> sorts after <s2>, and 0 if they are equal. Also return
+// the number of bytes that matched in <s1MatchLen> and <s2MatchLen>
+// (either one of which can be NULL if the match length is not needed).
+
+Int16 TxtCompare(const Char *s1, UInt16 s1Len, UInt16 *s1MatchLen,
+ const Char *s2, UInt16 s2Len, UInt16 *s2MatchLen)
+ INTL_TRAP(intlTxtCompare);
+
+#ifdef __cplusplus
+ }
+#endif
+#endif
+
+#endif // __TEXTMGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/System/Window.h b/SrcShared/Palm/Platform/Incs/Core/System/Window.h
new file mode 100644
index 0000000..50aec23
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/System/Window.h
@@ -0,0 +1,559 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Window.h
+ *
+ * Description:
+ * This file defines window structures and routines that support color.
+ *
+ * History:
+ * January 20, 1999 Created by Bob Ebert
+ * Name Date Description
+ * ---- ---- -----------
+ * bob 1/20/99 Branch off WindowNew.h
+ * BS 4/20/99 Re-design of the screen driver
+ * bob 5/26/99 Cleanup/reorg
+ * jmp 12/23/99 Fix <> vs. "" problem.
+ *
+ *****************************************************************************/
+
+#ifndef __WINDOW_H__
+#define __WINDOW_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <Font.h>
+#include <Rect.h>
+#include <Bitmap.h>
+
+#include <PalmOptErrorCheckLevel.h> // #define ERROR_CHECK_LEVEL
+
+#ifdef _WIN32
+ #pragma warning(disable: 4214) // nonstandard extension used : bit field types other than int
+#endif
+
+// enum for WinScrollRectangle
+typedef enum { winUp = 0, winDown, winLeft, winRight } WinDirectionType;
+
+
+// enum for WinCreateOffscreenWindow
+typedef enum { screenFormat = 0, genericFormat } WindowFormatType;
+
+
+// enum for WinLockScreen
+typedef enum {winLockCopy, winLockErase, winLockDontCare} WinLockInitType;
+
+
+// operations for the WinScreenMode function
+typedef enum {
+ winScreenModeGetDefaults,
+ winScreenModeGet,
+ winScreenModeSetToDefaults,
+ winScreenModeSet,
+ winScreenModeGetSupportedDepths,
+ winScreenModeGetSupportsColor
+} WinScreenModeOperation;
+
+// Operations for the WinPalette function
+#define winPaletteGet 0
+#define winPaletteSet 1
+#define winPaletteSetToDefault 2
+
+// transfer modes for color drawing
+typedef enum {winPaint, winErase, winMask, winInvert, winOverlay, winPaintInverse, winSwap} WinDrawOperation;
+
+
+typedef enum { blackPattern, whitePattern, grayPattern, customPattern } PatternType;
+#define noPattern blackPattern
+#define grayHLinePattern 0xAA
+#define grayHLinePatternOdd 0x55
+
+
+// grayUnderline means dotted current foreground color
+// solidUnderline means solid current foreground color
+// colorUnderline redundant, use solidUnderline instead
+typedef enum { noUnderline, grayUnderline, solidUnderline, colorUnderline } UnderlineModeType;
+
+#define WinMaxSupportedDepth 8
+#define WinNumSupportedColors 4
+
+typedef UInt8 IndexedColorType; // 1-, 2-, 4-, or 8-bit index
+
+typedef UInt8 CustomPatternType [8]; // 8x8 1-bit deep pattern
+
+// for WinPalette startIndex value, respect indexes in passed table
+#define WinUseTableIndexes -1
+
+//-----------------------------------------------
+// Draw state structures.
+//-----------------------------------------------
+
+
+typedef struct DrawStateType {
+ WinDrawOperation transferMode;
+ PatternType pattern;
+ UnderlineModeType underlineMode;
+ FontID fontId;
+ FontPtr font;
+ CustomPatternType patternData;
+ IndexedColorType foreColor;
+ IndexedColorType backColor;
+ IndexedColorType textColor;
+ UInt8 reserved;
+} DrawStateType;
+
+
+#define DrawStateStackSize 5 // enough for a control in a field in a window
+
+
+
+
+//-----------------------------------------------
+// The Window Structures.
+//-----------------------------------------------
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥Ê-- need to add #defines for each bit for endian portableness
+#endif // PUBLIC_STUFF_STRIPPED
+typedef union FrameBitsType {
+ struct {
+ UInt16 cornerDiam : 8; // corner diameter, max 38
+ UInt16 reserved_3 : 3;
+ UInt16 threeD : 1; // Draw 3D button
+ UInt16 shadowWidth : 2; // Width of shadow
+ UInt16 width : 2; // Width frame
+ } bits;
+ UInt16 word; // IMPORTANT: INITIALIZE word to zero before setting bits!
+} FrameBitsType;
+
+typedef UInt16 FrameType;
+
+// Standard Frame Types
+#define noFrame 0
+#define simpleFrame 1
+#define rectangleFrame 1
+#define simple3DFrame 0x0012 // 3d, frame = 2
+#define roundFrame 0x0401 // corner = 7, frame = 1
+#define boldRoundFrame 0x0702 // corner = 7, frame = 2
+#define popupFrame 0x0205 // corner = 2, frame = 1, shadow = 1
+#define dialogFrame 0x0302 // corner = 3, frame = 2
+#define menuFrame popupFrame
+
+
+#define winDefaultDepthFlag 0xFF
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER ¥¥¥Ê-- need to add #defines for each bit for endian portableness
+#endif // PUBLIC_STUFF_STRIPPED
+typedef struct WindowFlagsType {
+ UInt16 format:1; // window format: 0=screen mode; 1=generic mode
+ UInt16 offscreen:1; // offscreen flag: 0=onscreen ; 1=offscreen
+ UInt16 modal:1; // modal flag: 0=modeless window; 1=modal window
+ UInt16 focusable:1; // focusable flag: 0=non-focusable; 1=focusable
+ UInt16 enabled:1; // enabled flag: 0=disabled; 1=enabled
+ UInt16 visible:1; // visible flag: 0-invisible; 1=visible
+ UInt16 dialog:1; // dialog flag: 0=non-dialog; 1=dialog
+ UInt16 freeBitmap:1; // free bitmap w/window: 0=don't free, 1=free
+ UInt16 reserved :8;
+} WindowFlagsType;
+
+typedef struct WindowType {
+ Coord displayWidthV20; // use WinGetDisplayExtent instead
+ Coord displayHeightV20; // use WinGetDisplayExtent instead
+ void * displayAddrV20; // use the drawing functions instead
+ WindowFlagsType windowFlags;
+ RectangleType windowBounds;
+ AbsRectType clippingBounds;
+ BitmapPtr bitmapP;
+ FrameBitsType frameType;
+ DrawStateType * drawStateP; // was GraphicStatePtr
+ struct WindowType * nextWindow;
+} WindowType;
+
+typedef WindowType *WinPtr;
+typedef WindowType *WinHandle;
+
+
+//-----------------------------------------------
+// More graphics shapes
+//-----------------------------------------------
+typedef struct WinLineType {
+ Coord x1;
+ Coord y1;
+ Coord x2;
+ Coord y2;
+} WinLineType;
+
+// Rectangles, Points defined in Rect.h
+
+
+
+//-----------------------------------------------
+// Low Memory Globals
+//-----------------------------------------------
+
+// This is the structure of a low memory global reserved for the Window Manager
+// In GRAPHIC_VERSION_2, it held a single drawing state. In this version, it
+// holds stack information for structures that are allocated from the dynamic heap
+typedef struct GraphicStateType {
+ DrawStateType * drawStateP;
+ DrawStateType * drawStateStackP;
+ Int16 drawStateIndex;
+ UInt16 screenLockCount;
+} GraphicStateType;
+
+// ----------------------
+// Window manager errors
+// ----------------------
+#define winErrPalette (winErrorClass | 1)
+
+
+
+//-----------------------------------------------
+// Macros
+//-----------------------------------------------
+
+// For now, the window handle is a pointer to a window structure,
+// this however may change, so use the following macros.
+
+#define WinGetWindowPointer(winHandle) ((WindowType *) winHandle)
+
+#define WinGetWindowHandle(winPtr) ((WinHandle) winPtr)
+
+#if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
+#define ECWinValidateHandle(winHandle) WinValidateHandle(winHandle)
+#else
+#define ECWinValidateHandle(winHandle)
+#endif
+
+
+
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//-----------------------------------------------
+// Routines relating to windows management
+//-----------------------------------------------
+
+extern Boolean WinValidateHandle (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinValidateHandle);
+
+extern WinHandle WinCreateWindow (const RectangleType *bounds, FrameType frame,
+ Boolean modal, Boolean focusable, UInt16 *error)
+ SYS_TRAP(sysTrapWinCreateWindow);
+
+extern WinHandle WinCreateOffscreenWindow (Coord width, Coord height,
+ WindowFormatType format, UInt16 *error)
+ SYS_TRAP(sysTrapWinCreateOffscreenWindow);
+
+extern WinHandle WinCreateBitmapWindow (BitmapType *bitmapP, UInt16 *error)
+ SYS_TRAP(sysTrapWinCreateBitmapWindow);
+
+extern void WinDeleteWindow (WinHandle winHandle, Boolean eraseIt)
+ SYS_TRAP(sysTrapWinDeleteWindow);
+
+extern void WinInitializeWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinInitializeWindow);
+
+extern void WinAddWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinAddWindow);
+
+extern void WinRemoveWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinRemoveWindow);
+
+extern void WinMoveWindowAddr (WindowType *oldLocationP, WindowType *newLocationP)
+ SYS_TRAP(sysTrapWinMoveWindowAddr);
+
+extern void WinSetActiveWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinSetActiveWindow);
+
+extern WinHandle WinSetDrawWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinSetDrawWindow);
+
+extern WinHandle WinGetDrawWindow (void)
+ SYS_TRAP(sysTrapWinGetDrawWindow);
+
+extern WinHandle WinGetActiveWindow (void)
+ SYS_TRAP(sysTrapWinGetActiveWindow);
+
+extern WinHandle WinGetDisplayWindow (void)
+ SYS_TRAP(sysTrapWinGetDisplayWindow);
+
+extern WinHandle WinGetFirstWindow (void)
+ SYS_TRAP(sysTrapWinGetFirstWindow);
+
+extern void WinEnableWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinEnableWindow);
+
+extern void WinDisableWindow (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinDisableWindow);
+
+extern void WinGetWindowFrameRect (WinHandle winHandle, RectangleType *r)
+ SYS_TRAP(sysTrapWinGetWindowFrameRect);
+
+extern void WinDrawWindowFrame (void)
+ SYS_TRAP(sysTrapWinDrawWindowFrame);
+
+extern void WinEraseWindow (void)
+ SYS_TRAP(sysTrapWinEraseWindow);
+
+extern WinHandle WinSaveBits (const RectangleType *source, UInt16 *error)
+ SYS_TRAP(sysTrapWinSaveBits);
+
+extern void WinRestoreBits (WinHandle winHandle, Coord destX, Coord destY)
+ SYS_TRAP(sysTrapWinRestoreBits);
+
+extern void WinCopyRectangle (WinHandle srcWin, WinHandle dstWin,
+ const RectangleType *srcRect, Coord destX, Coord destY, WinDrawOperation mode)
+ SYS_TRAP(sysTrapWinCopyRectangle);
+
+extern void WinScrollRectangle (const RectangleType *rP, WinDirectionType direction,
+ Coord distance, RectangleType *vacatedP)
+ SYS_TRAP(sysTrapWinScrollRectangle);
+
+extern void WinGetDisplayExtent (Coord *extentX, Coord *extentY)
+ SYS_TRAP(sysTrapWinGetDisplayExtent);
+
+extern void WinGetWindowBounds (RectangleType *rP)
+ SYS_TRAP(sysTrapWinGetWindowBounds);
+
+extern void WinSetWindowBounds (WinHandle winHandle, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinSetWindowBounds);
+
+extern void WinGetWindowExtent (Coord *extentX, Coord *extentY)
+ SYS_TRAP(sysTrapWinGetWindowExtent);
+
+extern void WinDisplayToWindowPt (Coord *extentX, Coord *extentY)
+ SYS_TRAP(sysTrapWinDisplayToWindowPt);
+
+extern void WinWindowToDisplayPt (Coord *extentX, Coord *extentY)
+ SYS_TRAP(sysTrapWinWindowToDisplayPt);
+
+extern BitmapType *WinGetBitmap (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinGetBitmap);
+
+extern void WinGetClip (RectangleType *rP)
+ SYS_TRAP(sysTrapWinGetClip);
+
+extern void WinSetClip (const RectangleType *rP)
+ SYS_TRAP(sysTrapWinSetClip);
+
+extern void WinResetClip (void)
+ SYS_TRAP(sysTrapWinResetClip);
+
+extern void WinClipRectangle (RectangleType *rP)
+ SYS_TRAP(sysTrapWinClipRectangle);
+
+extern Boolean WinModal (WinHandle winHandle)
+ SYS_TRAP(sysTrapWinModal);
+
+//-----------------------------------------------
+// Routines to draw shapes or frames shapes
+//-----------------------------------------------
+
+// Pixel(s)
+extern IndexedColorType WinGetPixel (Coord x, Coord y)
+ SYS_TRAP(sysTrapWinGetPixel);
+
+extern void WinPaintPixel (Coord x, Coord y) // uses drawing mode
+ SYS_TRAP(sysTrapWinPaintPixel);
+
+extern void WinDrawPixel (Coord x, Coord y)
+ SYS_TRAP(sysTrapWinDrawPixel);
+
+extern void WinErasePixel (Coord x, Coord y)
+ SYS_TRAP(sysTrapWinErasePixel);
+
+extern void WinInvertPixel (Coord x, Coord y)
+ SYS_TRAP(sysTrapWinInvertPixel);
+
+extern void WinPaintPixels (UInt16 numPoints, PointType pts[])
+ SYS_TRAP(sysTrapWinPaintPixels);
+
+// Line(s)
+extern void WinPaintLines (UInt16 numLines, WinLineType lines[])
+ SYS_TRAP(sysTrapWinPaintLines);
+
+extern void WinPaintLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinPaintLine);
+
+extern void WinDrawLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinDrawLine);
+
+extern void WinDrawGrayLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinDrawGrayLine);
+
+extern void WinEraseLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinEraseLine);
+
+extern void WinInvertLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinInvertLine);
+
+extern void WinFillLine (Coord x1, Coord y1, Coord x2, Coord y2)
+ SYS_TRAP(sysTrapWinFillLine);
+
+
+// Rectangle
+extern void WinPaintRectangle (const RectangleType *rP, UInt16 cornerDiam)
+ SYS_TRAP(sysTrapWinPaintRectangle);
+
+extern void WinDrawRectangle (const RectangleType *rP, UInt16 cornerDiam)
+ SYS_TRAP(sysTrapWinDrawRectangle);
+
+extern void WinEraseRectangle (const RectangleType *rP, UInt16 cornerDiam)
+ SYS_TRAP(sysTrapWinEraseRectangle);
+
+extern void WinInvertRectangle (const RectangleType *rP, UInt16 cornerDiam)
+ SYS_TRAP(sysTrapWinInvertRectangle);
+
+extern void WinFillRectangle (const RectangleType *rP, UInt16 cornerDiam)
+ SYS_TRAP(sysTrapWinFillRectangle);
+
+// Rectangle frames
+extern void WinPaintRectangleFrame (FrameType frame, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinPaintRectangleFrame);
+
+extern void WinDrawRectangleFrame (FrameType frame, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinDrawRectangleFrame);
+
+extern void WinDrawGrayRectangleFrame (FrameType frame, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinDrawGrayRectangleFrame);
+
+extern void WinEraseRectangleFrame (FrameType frame, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinEraseRectangleFrame);
+
+extern void WinInvertRectangleFrame (FrameType frame, const RectangleType *rP)
+ SYS_TRAP(sysTrapWinInvertRectangleFrame);
+
+extern void WinGetFramesRectangle (FrameType frame, const RectangleType *rP,
+ RectangleType *obscuredRect)
+ SYS_TRAP(sysTrapWinGetFramesRectangle);
+
+
+// Bitmap
+extern void WinDrawBitmap (BitmapPtr bitmapP, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinDrawBitmap);
+
+extern void WinPaintBitmap (BitmapType *bitmapP, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinPaintBitmap);
+
+
+// Characters
+extern void WinDrawChar (WChar theChar, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinDrawChar);
+
+extern void WinDrawChars (const Char *chars, Int16 len, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinDrawChars);
+
+extern void WinPaintChar (WChar theChar, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinPaintChar);
+
+extern void WinPaintChars (const Char *chars, Int16 len, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinPaintChars);
+
+extern void WinDrawInvertedChars (const Char *chars, Int16 len, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinDrawInvertedChars);
+
+extern void WinDrawTruncChars(const Char *chars, Int16 len, Coord x, Coord y, Coord maxWidth)
+ SYS_TRAP(sysTrapWinDrawTruncChars);
+
+extern void WinEraseChars (const Char *chars, Int16 len, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinEraseChars);
+
+extern void WinInvertChars (const Char *chars, Int16 len, Coord x, Coord y)
+ SYS_TRAP(sysTrapWinInvertChars);
+
+extern UnderlineModeType WinSetUnderlineMode (UnderlineModeType mode)
+ SYS_TRAP(sysTrapWinSetUnderlineMode);
+
+
+
+//-----------------------------------------------
+// Routines for patterns and colors
+//-----------------------------------------------
+
+extern void WinPushDrawState (void) // "save" fore, back, text color, pattern, underline mode, font
+ SYS_TRAP(sysTrapWinPushDrawState);
+
+extern void WinPopDrawState (void) // "restore" saved drawing variables
+ SYS_TRAP(sysTrapWinPopDrawState);
+
+
+extern WinDrawOperation WinSetDrawMode (WinDrawOperation newMode)
+ SYS_TRAP(sysTrapWinSetDrawMode);
+
+
+extern IndexedColorType WinSetForeColor (IndexedColorType foreColor)
+ SYS_TRAP(sysTrapWinSetForeColor);
+
+extern IndexedColorType WinSetBackColor (IndexedColorType backColor)
+ SYS_TRAP(sysTrapWinSetBackColor);
+
+extern IndexedColorType WinSetTextColor (IndexedColorType textColor)
+ SYS_TRAP(sysTrapWinSetTextColor);
+
+// "obsolete" color call, supported for backwards compatibility
+extern void WinSetColors(const RGBColorType *newForeColorP, RGBColorType *oldForeColorP,
+ const RGBColorType *newBackColorP, RGBColorType *oldBackColorP)
+ SYS_TRAP(sysTrapWinSetColors);
+
+extern void WinGetPattern (CustomPatternType *patternP)
+ SYS_TRAP(sysTrapWinGetPattern);
+
+extern PatternType WinGetPatternType (void)
+ SYS_TRAP(sysTrapWinGetPatternType);
+
+extern void WinSetPattern (const CustomPatternType *patternP)
+ SYS_TRAP(sysTrapWinSetPattern);
+
+extern void WinSetPatternType (PatternType newPattern)
+ SYS_TRAP(sysTrapWinSetPatternType);
+
+extern Err WinPalette(UInt8 operation, Int16 startIndex,
+ UInt16 paletteEntries, RGBColorType *tableP)
+ SYS_TRAP(sysTrapWinPalette);
+
+extern IndexedColorType WinRGBToIndex(const RGBColorType *rgbP)
+ SYS_TRAP(sysTrapWinRGBToIndex);
+
+extern void WinIndexToRGB(IndexedColorType i, RGBColorType *rgbP)
+ SYS_TRAP(sysTrapWinIndexToRGB);
+
+
+
+//-----------------------------------------------
+// New WinScreen functions
+//-----------------------------------------------
+
+extern void WinScreenInit(void)
+ SYS_TRAP(sysTrapWinScreenInit);
+
+extern Err WinScreenMode(WinScreenModeOperation operation,
+ UInt32 *widthP,
+ UInt32 *heightP,
+ UInt32 *depthP,
+ Boolean *enableColorP)
+ SYS_TRAP(sysTrapWinScreenMode);
+
+
+//-----------------------------------------------
+// Screen tracking (double buffering) support
+//-----------------------------------------------
+extern UInt8 *WinScreenLock(WinLockInitType initMode)
+ SYS_TRAP(sysTrapWinScreenLock);
+
+extern void WinScreenUnlock(void)
+ SYS_TRAP(sysTrapWinScreenUnlock);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__WINDOW_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/AttentionMgr.h b/SrcShared/Palm/Platform/Incs/Core/UI/AttentionMgr.h
new file mode 100644
index 0000000..c466a1f
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/AttentionMgr.h
@@ -0,0 +1,209 @@
+/******************************************************************************
+ *
+ * Copyright (c) 2000 Palm, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: AttentionMgr.h
+ *
+ * Release:
+ *
+ * Description:
+ * Include file for Attention Manager
+ *
+ * History:
+ * Name Date Description
+ * ---- ---- -----------
+ * peter 06/12/00 Initial Revision
+ * gap 07/21/00 Change parameter list and data structures to support
+ * specification of card number as well as dbID.
+ *
+ *****************************************************************************/
+
+#ifndef __ATTENTION_MGR_H__
+#define __ATTENTION_MGR_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <Rect.h>
+#include <SysEvent.h>
+#include <Event.h>
+
+/************************************************************
+ * Attention Manager result codes
+ * (attnErrorClass is defined in ErrorBase)
+ *************************************************************/
+#define attnErrMemory (attnErrorClass | 1) // ran out of memory
+
+
+/************************************************************
+ * Attention Indicator bounds
+ *************************************************************/
+#define kAttnIndicatorLeft 0
+#define kAttnIndicatorTop 0
+#define kAttnIndicatorWidth 16
+#define kAttnIndicatorHeight 15
+
+
+/************************************************************
+ * Constants used for list view drawing.
+ *
+ * Applications should use the following constants to format
+ * the display of information in attention manager list view.
+ *
+ * The application's small icon should be drawn centered within
+ * the first kAttnListMaxIconWidth pixels of the drawing bounds.
+ *
+ * Two lines of text information describing the attention should
+ * then be drawn left justified starting at kAttnListTextOffset
+ * from the left edge of the drawing bounds.
+ *************************************************************/
+#define kAttnListMaxIconWidth 15
+#define kAttnListTextOffset 17
+
+
+/********************************************************************
+ * Attention Manager Structures
+ ********************************************************************/
+
+typedef UInt32 AttnFlagsType;
+
+#define kAttnFlagsSoundBit ((AttnFlagsType)0x0001)
+#define kAttnFlagsLEDBit ((AttnFlagsType)0x0002)
+#define kAttnFlagsVibrateBit ((AttnFlagsType)0x0004)
+#define kAttnFlagsCustomEffectBit ((AttnFlagsType)0x0008)
+ // Note: More bits can be defined if/when hardware capability increases
+
+#define kAttnFlagsAllBits ((AttnFlagsType)0xFFFF)
+
+
+// The following are passed to AttnGetAttention() and AttnUpdate to specify
+// overrides from the user settings for an attention request.
+#define kAttnFlagsUseUserSettings ((AttnFlagsType)0x00000000)
+
+#define kAttnFlagsAlwaysSound (kAttnFlagsSoundBit)
+#define kAttnFlagsAlwaysLED (kAttnFlagsLEDBit)
+#define kAttnFlagsAlwaysVibrate (kAttnFlagsVibrateBit)
+#define kAttnFlagsAlwaysCustomEffect (kAttnFlagsCustomEffectBit)
+#define kAttnFlagsEverything (kAttnFlagsAllBits)
+
+#define kAttnFlagsNoSound (kAttnFlagsSoundBit<<16)
+#define kAttnFlagsNoLED (kAttnFlagsLEDBit<<16)
+#define kAttnFlagsNoVibrate (kAttnFlagsVibrateBit<<16)
+#define kAttnFlagsNoCustomEffect (kAttnFlagsCustomEffectBit<<16)
+#define kAttnFlagsNothing (kAttnFlagsAllBits<<16)
+
+
+// The following are used to interpret the feature.
+#define kAttnFtrCreator 'attn'
+#define kAttnFtrCapabilities 0 // Read to determine device capabilities and user settings.
+
+#define kAttnFlagsUserWantsSound (kAttnFlagsSoundBit)
+#define kAttnFlagsUserWantsLED (kAttnFlagsLEDBit)
+#define kAttnFlagsUserWantsVibrate (kAttnFlagsVibrateBit)
+#define kAttnFlagsUserWantsCustomEffect (kAttnFlagsCustomEffectBit) // Always false
+#define kAttnFlagsUserSettingsMask (kAttnFlagsAllBits)
+
+#define kAttnFlagsHasSound (kAttnFlagsSoundBit<<16)
+#define kAttnFlagsHasLED (kAttnFlagsLEDBit<<16)
+#define kAttnFlagsHasVibrate (kAttnFlagsVibrateBit<<16)
+#define kAttnFlagsHasCustomEffect (kAttnFlagsCustomEffectBit<<16) // Always true
+#define kAttnFlagsCapabilitiesMask (kAttnFlagsAllBits<<16)
+
+
+typedef UInt16 AttnLevelType;
+ #define kAttnLevelInsistent ((AttnLevelType)0)
+ #define kAttnLevelSubtle ((AttnLevelType)1)
+
+typedef UInt16 AttnCommandType;
+ #define kAttnCommandDrawDetail ((AttnCommandType)1)
+ #define kAttnCommandDrawList ((AttnCommandType)2)
+ #define kAttnCommandPlaySound ((AttnCommandType)3)
+ #define kAttnCommandCustomEffect ((AttnCommandType)4)
+ #define kAttnCommandGoThere ((AttnCommandType)5)
+ #define kAttnCommandGotIt ((AttnCommandType)6)
+ #define kAttnCommandSnooze ((AttnCommandType)7)
+ #define kAttnCommandIterate ((AttnCommandType)8)
+
+typedef union AttnCommandArgsTag {
+ struct AttnCommandArgsDrawDetailTag{
+ RectangleType bounds;
+ Boolean firstTime;
+ AttnFlagsType flags;
+ } drawDetail;
+
+ struct AttnCommandArgsDrawListTag {
+ RectangleType bounds;
+ Boolean firstTime;
+ AttnFlagsType flags;
+ Boolean selected;
+ } drawList;
+
+ struct AttnCommandArgsGotItTag {
+ Boolean dismissedByUser;
+ } gotIt;
+
+ struct AttnCommandArgsIterateTag {
+ UInt32 iterationData;
+ } iterate;
+} AttnCommandArgsType;
+
+typedef struct {
+ AttnCommandType command;
+ UInt32 userData;
+ AttnCommandArgsType *commandArgsP;
+} AttnLaunchCodeArgsType;
+
+typedef Err AttnCallbackProc (AttnCommandType command, UInt32 userData, AttnCommandArgsType *commandArgsP);
+
+// These details go with the sysNotifyGotUsersAttention notification.
+typedef struct {
+ AttnFlagsType flags;
+} AttnNotifyDetailsType;
+
+
+/********************************************************************
+ * Public Attention Manager Routines
+ ********************************************************************/
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Err AttnGetAttention (UInt16 cardNo, LocalID dbID, UInt32 userData,
+ AttnCallbackProc *callbackFnP, AttnLevelType level, AttnFlagsType flags,
+ UInt16 nagRateInSeconds, UInt16 nagRepeatLimit)
+ SYS_TRAP(sysTrapAttnGetAttention);
+
+Boolean AttnUpdate (UInt16 cardNo, LocalID dbID, UInt32 userData,
+ AttnCallbackProc *callbackFnP, AttnFlagsType *flagsP,
+ UInt16 *nagRateInSecondsP, UInt16 *nagRepeatLimitP)
+ SYS_TRAP(sysTrapAttnUpdate);
+
+Boolean AttnForgetIt (UInt16 cardNo, LocalID dbID, UInt32 userData)
+ SYS_TRAP(sysTrapAttnForgetIt);
+
+UInt16 AttnGetCounts (UInt16 cardNo, LocalID dbID, UInt16 *insistentCountP, UInt16 *subtleCountP)
+ SYS_TRAP(sysTrapAttnGetCounts);
+
+void AttnListOpen (void)
+ SYS_TRAP(sysTrapAttnListOpen);
+
+void AttnIterate (UInt16 cardNo, LocalID dbID, UInt32 iterationData)
+ SYS_TRAP(sysTrapAttnIterate);
+
+Err AttnDoSpecialEffects(AttnFlagsType flags)
+ SYS_TRAP(sysTrapAttnDoSpecialEffects);
+
+void AttnIndicatorEnable(Boolean enableIt)
+ SYS_TRAP(sysTrapAttnIndicatorEnable);
+
+Boolean AttnIndicatorEnabled(void)
+ SYS_TRAP(sysTrapAttnIndicatorEnabled);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __ATTENTION_MGR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Control.h b/SrcShared/Palm/Platform/Incs/Core/UI/Control.h
new file mode 100644
index 0000000..bd23d96
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Control.h
@@ -0,0 +1,188 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Control.h
+ *
+ * Description:
+ * This file defines check box structures and routines.
+ *
+ * History:
+ * August 29, 1994 Created by Art Lamb
+ * Name Date Description
+ * ---- ---- -----------
+ * bob 2/9/99 Fix up const stuff
+ * bob 4/16/99 add GraphicControlType
+ *
+ *****************************************************************************/
+
+#ifndef __CONTROL_H__
+#define __CONTROL_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <DataMgr.h>
+#include <Event.h>
+
+typedef struct {
+ UInt8 usable :1; // set if part of ui
+ UInt8 enabled :1; // set if interactable (not grayed out)
+ UInt8 visible :1; // set if drawn (set internally)
+ UInt8 on :1; // set if on (checked)
+ UInt8 leftAnchor :1; // set if bounds expand to the right
+ // clear if bounds expand to the left
+ UInt8 frame :3;
+ UInt8 drawnAsSelected :1; // support for old-style graphic controls
+ // where control overlaps a bitmap
+ UInt8 graphical :1; // set if images are used instead of text
+ UInt8 vertical :1; // true for vertical sliders
+ UInt8 reserved :5;
+} ControlAttrType;
+
+
+enum controlStyles {buttonCtl, pushButtonCtl, checkboxCtl, popupTriggerCtl,
+ selectorTriggerCtl, repeatingButtonCtl, sliderCtl,
+ feedbackSliderCtl };
+typedef enum controlStyles ControlStyleType;
+
+enum buttonFrames {noButtonFrame, standardButtonFrame, boldButtonFrame,
+ rectangleButtonFrame};
+typedef enum buttonFrames ButtonFrameType;
+
+
+typedef struct ControlType {
+ UInt16 id;
+ RectangleType bounds;
+ Char * text;
+ ControlAttrType attr;
+ ControlStyleType style;
+ FontID font;
+ UInt8 group;
+ UInt8 reserved;
+} ControlType;
+
+typedef ControlType *ControlPtr; // deprecated, use ControlType *
+
+
+// GraphicControlType *'s can be cast to ControlType *'s and passed to all
+// Control API functions (as long as the 'graphical' bit in the attrs is set)
+
+typedef struct GraphicControlType {
+ UInt16 id;
+ RectangleType bounds;
+ DmResID bitmapID; // overlays text in ControlType
+ DmResID selectedBitmapID; // overlays text in ControlType
+ ControlAttrType attr;
+ ControlStyleType style;
+ FontID unused;
+ UInt8 group;
+ UInt8 reserved;
+} GraphicControlType;
+
+
+// SliderControlType *'s can be cast to ControlType *'s and passed to all
+// Control API functions (as long as the control style is a slider)
+
+typedef struct SliderControlType {
+ UInt16 id;
+ RectangleType bounds;
+ DmResID thumbID; // overlays text in ControlType
+ DmResID backgroundID; // overlays text in ControlType
+ ControlAttrType attr; // graphical *is* set
+ ControlStyleType style; // must be sliderCtl or repeatingSliderCtl
+ UInt8 reserved;
+ Int16 minValue;
+ Int16 maxValue;
+ Int16 pageSize;
+ Int16 value;
+ MemPtr activeSliderP;
+} SliderControlType;
+
+
+//----------------------------------------------------------
+// Control Functions
+//----------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void CtlDrawControl (ControlType *controlP)
+ SYS_TRAP(sysTrapCtlDrawControl);
+
+extern void CtlEraseControl (ControlType *controlP)
+ SYS_TRAP(sysTrapCtlEraseControl);
+
+extern void CtlHideControl (ControlType *controlP)
+ SYS_TRAP(sysTrapCtlHideControl);
+
+extern void CtlShowControl (ControlType *controlP)
+ SYS_TRAP(sysTrapCtlShowControl);
+
+extern Boolean CtlEnabled (const ControlType *controlP)
+ SYS_TRAP(sysTrapCtlEnabled);
+
+extern void CtlSetEnabled (ControlType *controlP, Boolean usable)
+ SYS_TRAP(sysTrapCtlSetEnabled);
+
+extern void CtlSetUsable (ControlType *controlP, Boolean usable)
+ SYS_TRAP(sysTrapCtlSetUsable);
+
+extern Int16 CtlGetValue (const ControlType *controlP)
+ SYS_TRAP(sysTrapCtlGetValue);
+
+extern void CtlSetValue (ControlType *controlP, Int16 newValue)
+ SYS_TRAP(sysTrapCtlSetValue);
+
+extern const Char *CtlGetLabel (const ControlType *controlP)
+ SYS_TRAP(sysTrapCtlGetLabel);
+
+extern void CtlSetLabel (ControlType *controlP, const Char *newLabel)
+ SYS_TRAP(sysTrapCtlSetLabel);
+
+extern void CtlSetGraphics (ControlType *ctlP,
+ DmResID newBitmapID, DmResID newSelectedBitmapID)
+ SYS_TRAP(sysTrapCtlSetGraphics);
+
+extern void CtlSetSliderValues(ControlType *ctlP, const UInt16 *minValueP, const UInt16 *maxValueP,
+ const UInt16 *pageSizeP, const UInt16 *valueP)
+ SYS_TRAP(sysTrapCtlSetSliderValues);
+
+extern void CtlGetSliderValues(const ControlType *ctlP, UInt16 *minValueP, UInt16 *maxValueP,
+ UInt16 *pageSizeP, UInt16 *valueP)
+ SYS_TRAP(sysTrapCtlGetSliderValues);
+
+extern void CtlHitControl (const ControlType *controlP)
+ SYS_TRAP(sysTrapCtlHitControl);
+
+extern Boolean CtlHandleEvent (ControlType *controlP, EventType *pEvent)
+ SYS_TRAP(sysTrapCtlHandleEvent);
+
+extern Boolean CtlValidatePointer (const ControlType *controlP)
+ SYS_TRAP(sysTrapCtlValidatePointer);
+
+extern ControlType *CtlNewControl (void **formPP, UInt16 ID,
+ ControlStyleType style, const Char *textP,
+ Coord x, Coord y, Coord width, Coord height,
+ FontID font, UInt8 group, Boolean leftAnchor)
+ SYS_TRAP(sysTrapCtlNewControl);
+
+extern GraphicControlType *CtlNewGraphicControl (void **formPP, UInt16 ID,
+ ControlStyleType style, DmResID bitmapID, DmResID selectedBitmapID,
+ Coord x, Coord y, Coord width, Coord height,
+ UInt8 group, Boolean leftAnchor)
+ SYS_TRAP(sysTrapCtlNewGraphicControl);
+
+extern SliderControlType *CtlNewSliderControl (void **formPP, UInt16 ID,
+ ControlStyleType style, DmResID thumbID, DmResID backgroundID,
+ Coord x, Coord y, Coord width, Coord height, UInt16 minValue, UInt16 maxValue,
+ UInt16 pageSize, UInt16 value)
+ SYS_TRAP(sysTrapCtlNewSliderControl);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //__CONTROL_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Event.h b/SrcShared/Palm/Platform/Incs/Core/UI/Event.h
new file mode 100644
index 0000000..521d1f8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Event.h
@@ -0,0 +1,347 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Event.h
+ *
+ * Description:
+ * This file defines UI event structures and routines.
+ *
+ * History:
+ * September 26, 1994 Created by Art Lamb
+ * 07/14/99 jesse Separated from Event.h
+ * 09/12/99 gap Add for new multi-tap implementation
+ * 09/14/99 gap Removed EvtGetTrapState.
+ * 10/28/99 kwk Added EvtKeydownIsVirtual macro.
+ *
+ *****************************************************************************/
+
+#ifndef __EVENT_H__
+#define __EVENT_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <Font.h>
+#include <Rect.h>
+#include <SysEvent.h>
+#include <Window.h>
+
+
+typedef enum {
+ nilEvent = 0, // system level
+ penDownEvent, // system level
+ penUpEvent, // system level
+ penMoveEvent, // system level
+ keyDownEvent, // system level
+ winEnterEvent, // system level
+ winExitEvent, // system level
+ ctlEnterEvent,
+ ctlExitEvent,
+ ctlSelectEvent,
+ ctlRepeatEvent,
+ lstEnterEvent,
+ lstSelectEvent,
+ lstExitEvent,
+ popSelectEvent,
+ fldEnterEvent,
+ fldHeightChangedEvent,
+ fldChangedEvent,
+ tblEnterEvent,
+ tblSelectEvent,
+ daySelectEvent,
+ menuEvent,
+ appStopEvent = 22, // system level
+ frmLoadEvent,
+ frmOpenEvent,
+ frmGotoEvent,
+ frmUpdateEvent,
+ frmSaveEvent,
+ frmCloseEvent,
+ frmTitleEnterEvent,
+ frmTitleSelectEvent,
+ tblExitEvent,
+ sclEnterEvent,
+ sclExitEvent,
+ sclRepeatEvent,
+ tsmConfirmEvent = 35, // system level
+ tsmFepButtonEvent, // system level
+ tsmFepModeEvent, // system level
+//DOLATER - peter: remove this: frmTitleChangedEvent, // system level
+ attnIndicatorEnterEvent, // for attention manager's indicator
+ attnIndicatorSelectEvent, // for attention manager's indicator
+
+ // add future UI level events in this numeric space
+ // to save room for new system level events
+ menuCmdBarOpenEvent = 0x0800,
+ menuOpenEvent,
+ menuCloseEvent,
+ frmGadgetEnterEvent,
+ frmGadgetMiscEvent,
+
+ // <chg 2-25-98 RM> Equates added for library events
+ firstINetLibEvent = 0x1000,
+ firstWebLibEvent = 0x1100,
+
+ // <chg 10/9/98 SCL> Changed firstUserEvent from 32767 (0x7FFF) to 0x6000
+ // Enums are signed ints, so 32767 technically only allowed for ONE event.
+ firstUserEvent = 0x6000
+} eventsEnum;
+
+
+// The event record.
+typedef struct EventType {
+// eventsEnum eType;
+ Int16 eType;
+ Boolean penDown;
+ UInt8 tapCount;
+ Int16 screenX;
+ Int16 screenY;
+ union {
+ struct _GenericEventType generic;
+ struct _PenUpEventType penUp;
+ struct _KeyDownEventType keyDown;
+ struct _WinEnterEventType winEnter;
+ struct _WinExitEventType winExit;
+ struct _TSMConfirmType tsmConfirm;
+ struct _TSMFepButtonType tsmFepButton;
+ struct _TSMFepModeEventType tsmFepMode;
+
+ struct ctlEnter {
+ UInt16 controlID;
+ struct ControlType *pControl;
+ } ctlEnter;
+
+ struct ctlSelect {
+ UInt16 controlID;
+ struct ControlType *pControl;
+ Boolean on;
+ UInt8 reserved1;
+ UInt16 value; // used for slider controls only
+ } ctlSelect;
+
+ struct ctlRepeat {
+ UInt16 controlID;
+ struct ControlType *pControl;
+ UInt32 time;
+ UInt16 value; // used for slider controls only
+ } ctlRepeat;
+
+ struct ctlExit {
+ UInt16 controlID;
+ struct ControlType *pControl;
+ } ctlExit;
+
+ struct fldEnter {
+ UInt16 fieldID;
+ struct FieldType *pField;
+ } fldEnter;
+
+ struct fldHeightChanged {
+ UInt16 fieldID;
+ struct FieldType *pField;
+ Int16 newHeight;
+ UInt16 currentPos;
+ } fldHeightChanged;
+
+ struct fldChanged {
+ UInt16 fieldID;
+ struct FieldType *pField;
+ } fldChanged;
+
+ struct fldExit {
+ UInt16 fieldID;
+ struct FieldType *pField;
+ } fldExit;
+
+ struct lstEnter {
+ UInt16 listID;
+ struct ListType *pList;
+ Int16 selection;
+ } lstEnter;
+
+ struct lstExit {
+ UInt16 listID;
+ struct ListType *pList;
+ } lstExit;
+
+ struct lstSelect {
+ UInt16 listID;
+ struct ListType *pList;
+ Int16 selection;
+ } lstSelect;
+
+ struct tblEnter {
+ UInt16 tableID;
+ struct TableType *pTable;
+ Int16 row;
+ Int16 column;
+ } tblEnter;
+
+ struct tblExit {
+ UInt16 tableID;
+ struct TableType *pTable;
+ Int16 row;
+ Int16 column;
+ } tblExit;
+
+ struct tblSelect {
+ UInt16 tableID;
+ struct TableType *pTable;
+ Int16 row;
+ Int16 column;
+ } tblSelect;
+
+ struct frmLoad {
+ UInt16 formID;
+ } frmLoad;
+
+ struct frmOpen {
+ UInt16 formID;
+ } frmOpen;
+
+ struct frmGoto {
+ UInt16 formID;
+ UInt16 recordNum; // index of record that contain a match
+ UInt16 matchPos; // postion in record of the match.
+ UInt16 matchLen; // length of match.
+ UInt16 matchFieldNum; // field number string was found int
+ UInt32 matchCustom; // application specific info
+ } frmGoto;
+
+ struct frmClose {
+ UInt16 formID;
+ } frmClose;
+
+ struct frmUpdate {
+ UInt16 formID;
+ UInt16 updateCode; // Application specific
+ } frmUpdate;
+
+ struct frmTitleEnter {
+ UInt16 formID;
+ } frmTitleEnter;
+
+ struct frmTitleSelect {
+ UInt16 formID;
+ } frmTitleSelect;
+
+ struct attnIndicatorEnter {
+ UInt16 formID;
+ } attnIndicatorEnter;
+
+ struct attnIndicatorSelect {
+ UInt16 formID;
+ } attnIndicatorSelect;
+
+ struct daySelect {
+ struct DaySelectorType *pSelector;
+ Int16 selection;
+ Boolean useThisDate;
+ UInt8 reserved1;
+ } daySelect;
+
+ struct menu {
+ UInt16 itemID;
+ } menu;
+
+ struct popSelect {
+ UInt16 controlID;
+ struct ControlType *controlP;
+ UInt16 listID;
+ struct ListType *listP;
+ Int16 selection;
+ Int16 priorSelection;
+ } popSelect;
+
+ struct sclEnter {
+ UInt16 scrollBarID;
+ struct ScrollBarType *pScrollBar;
+ } sclEnter;
+
+ struct sclExit {
+ UInt16 scrollBarID;
+ struct ScrollBarType *pScrollBar;
+ Int16 value;
+ Int16 newValue;
+ } sclExit;
+
+ struct sclRepeat {
+ UInt16 scrollBarID;
+ struct ScrollBarType *pScrollBar;
+ Int16 value;
+ Int16 newValue;
+ Int32 time;
+ } sclRepeat;
+
+ struct menuCmdBarOpen {
+ Boolean preventFieldButtons; // set to stop the field from automatically adding cut/copy/paste
+ UInt8 reserved; // alignment padding
+ } menuCmdBarOpen;
+
+ struct menuOpen {
+ UInt16 menuRscID;
+ //struct MenuBarType *pMenu;
+ Int16 cause;
+ } menuOpen;
+
+ struct gadgetEnter {
+ UInt16 gadgetID; // must be same as gadgetMisc
+ struct FormGadgetType * gadgetP; // must be same as gadgetMisc
+ } gadgetEnter;
+
+ struct gadgetMisc {
+ UInt16 gadgetID; // must be same as gadgetEnter
+ struct FormGadgetType * gadgetP; // must be same as gadgetEnter
+ UInt16 selector;
+ void * dataP;
+ } gadgetMisc;
+
+ } data;
+
+} EventType;
+
+typedef EventType *EventPtr;
+
+// Evaluate to true if <eventP> is a pointer to a virtual character key-
+// down event. We assume that the caller has already determined the event
+// is a keydown. WARNING!!! This macro is only safe to use on Palm OS 3.5
+// or later. With earlier versions of the OS, use TxtGlueCharIsVirtual()
+// in PalmOSGlue.lib
+#define EvtKeydownIsVirtual(eventP) (((eventP)->data.keyDown.modifiers & virtualKeyMask) != 0)
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//---------------------------------------------------------------------
+// Event Functions
+//---------------------------------------------------------------------
+
+void EvtAddEventToQueue (const EventType *event)
+ SYS_TRAP(sysTrapEvtAddEventToQueue);
+
+void EvtAddUniqueEventToQueue(const EventType *eventP, UInt32 id,
+ Boolean inPlace)
+ SYS_TRAP(sysTrapEvtAddUniqueEventToQueue);
+
+void EvtCopyEvent (const EventType *source, EventType *dest)
+ SYS_TRAP(sysTrapEvtCopyEvent);
+
+void EvtGetEvent (EventType *event, Int32 timeout)
+ SYS_TRAP(sysTrapEvtGetEvent);
+
+Boolean EvtEventAvail (void)
+ SYS_TRAP(sysTrapEvtEventAvail);
+
+void EvtGetPen(Int16 *pScreenX, Int16 *pScreenY, Boolean *pPenDown)
+ SYS_TRAP(sysTrapEvtGetPen);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif // __EVENT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/FatalAlert.h b/SrcShared/Palm/Platform/Incs/Core/UI/FatalAlert.h
new file mode 100644
index 0000000..d550c5c
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/FatalAlert.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: FatalAlert.h
+ *
+ * Description:
+ * This file defines the system Fatal Alert support.
+ *
+ * History:
+ * September 12, 1994 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __FATALALERT_H__
+#define __FATALALERT_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+// Value returned by SysFatalAlert
+#define fatalReset 0
+#define fatalEnterDebugger 1
+#define fatalDoNothing 0xFFFFU
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UInt16 SysFatalAlert (const Char *msg)
+ SYS_TRAP(sysTrapSysFatalAlert);
+
+void SysFatalAlertInit (void)
+ SYS_TRAP(sysTrapSysFatalAlertInit);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __FATALALERT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Field.h b/SrcShared/Palm/Platform/Incs/Core/UI/Field.h
new file mode 100644
index 0000000..c31084c
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Field.h
@@ -0,0 +1,275 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Field.h
+ *
+ * Description:
+ * This file defines field structures and routines.
+ *
+ * History:
+ * August 29, 1994 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __FIELD_H__
+#define __FIELD_H__
+
+#include <PalmTypes.h>
+
+#include <Font.h>
+#include <Event.h>
+#include <Window.h>
+
+#define maxFieldTextLen 0x7fff
+
+// Maximun number of line the a dynamicly sizing field will expand to.
+#define maxFieldLines 11
+
+
+// kind alignment values
+enum justifications {leftAlign, centerAlign, rightAlign};
+typedef enum justifications JustificationType;
+
+
+#define undoBufferSize 100
+
+typedef enum { undoNone, undoTyping, undoBackspace, undoDelete,
+ undoPaste, undoCut, undoInput } UndoMode;
+
+typedef struct {
+ UndoMode mode;
+ UInt8 reserved;
+ UInt16 start;
+ UInt16 end;
+ UInt16 bufferLen;
+ Char *buffer;
+ } FieldUndoType;
+
+
+typedef struct {
+ UInt16 usable :1; // Set if part of ui
+ UInt16 visible :1; // Set if drawn, used internally
+ UInt16 editable :1; // Set if editable
+ UInt16 singleLine :1; // Set if only a single line is displayed
+ UInt16 hasFocus :1; // Set if the field has the focus
+ UInt16 dynamicSize :1; // Set if height expands as text is entered
+ UInt16 insPtVisible :1; // Set if the ins pt is scolled into view
+ UInt16 dirty :1; // Set if user modified
+ UInt16 underlined :2; // text underlined mode
+ UInt16 justification :2; // text alignment
+ UInt16 autoShift :1; // Set if auto case shift
+ UInt16 hasScrollBar :1; // Set if the field has a scroll bar
+ UInt16 numeric :1; // Set if numeric, digits and secimal separator only
+} FieldAttrType;
+
+typedef FieldAttrType *FieldAttrPtr;
+
+typedef struct {
+ UInt16 start; // position in text string of first char.
+ UInt16 length; // number of character in the line
+} LineInfoType;
+
+typedef LineInfoType *LineInfoPtr;
+
+
+typedef struct FieldType {
+ UInt16 id;
+ RectangleType rect;
+ FieldAttrType attr;
+ Char *text; // pointer to the start of text string
+ MemHandle textHandle; // block the contains the text string
+ LineInfoPtr lines;
+ UInt16 textLen;
+ UInt16 textBlockSize;
+ UInt16 maxChars;
+ UInt16 selFirstPos;
+ UInt16 selLastPos;
+ UInt16 insPtXPos;
+ UInt16 insPtYPos;
+ FontID fontID;
+ UInt8 reserved;
+} FieldType;
+
+
+typedef FieldType *FieldPtr; // deprecated, use FieldType *
+
+
+//---------------------------------------------------------------------
+// Field Functions
+//---------------------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void FldCopy (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldCopy);
+
+extern void FldCut (FieldType *fldP)
+ SYS_TRAP(sysTrapFldCut);
+
+extern void FldDrawField (FieldType *fldP)
+ SYS_TRAP(sysTrapFldDrawField);
+
+extern void FldEraseField (FieldType *fldP)
+ SYS_TRAP(sysTrapFldEraseField);
+
+extern void FldFreeMemory (FieldType *fldP)
+ SYS_TRAP(sysTrapFldFreeMemory);
+
+extern void FldGetBounds (const FieldType *fldP, RectanglePtr rect)
+ SYS_TRAP(sysTrapFldGetBounds);
+
+extern FontID FldGetFont (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetFont);
+
+extern void FldGetSelection (const FieldType *fldP, UInt16 *startPosition, UInt16 *endPosition)
+ SYS_TRAP(sysTrapFldGetSelection);
+
+extern MemHandle FldGetTextHandle (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetTextHandle);
+
+extern Char * FldGetTextPtr (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetTextPtr);
+
+extern Boolean FldHandleEvent (FieldType *fldP, EventType *eventP)
+ SYS_TRAP(sysTrapFldHandleEvent);
+
+extern void FldPaste (FieldType *fldP)
+ SYS_TRAP(sysTrapFldPaste);
+
+extern void FldRecalculateField (FieldType *fldP, Boolean redraw)
+ SYS_TRAP(sysTrapFldRecalculateField);
+
+extern void FldSetBounds (FieldType *fldP, const RectangleType *rP)
+ SYS_TRAP(sysTrapFldSetBounds);
+
+extern void FldSetFont (FieldType *fldP, FontID fontID)
+ SYS_TRAP(sysTrapFldSetFont);
+
+extern void FldSetText (FieldType *fldP, MemHandle textHandle, UInt16 offset, UInt16 size)
+ SYS_TRAP(sysTrapFldSetText);
+
+extern void FldSetTextHandle (FieldType *fldP, MemHandle textHandle)
+ SYS_TRAP(sysTrapFldSetTextHandle);
+
+extern void FldSetTextPtr (FieldType *fldP, Char *textP)
+ SYS_TRAP(sysTrapFldSetTextPtr);
+
+extern void FldSetUsable (FieldType *fldP, Boolean usable)
+ SYS_TRAP(sysTrapFldSetUsable);
+
+extern void FldSetSelection (FieldType *fldP, UInt16 startPosition, UInt16 endPosition)
+ SYS_TRAP(sysTrapFldSetSelection);
+
+extern void FldGrabFocus (FieldType *fldP)
+ SYS_TRAP(sysTrapFldGrabFocus);
+
+extern void FldReleaseFocus (FieldType *fldP)
+ SYS_TRAP(sysTrapFldReleaseFocus);
+
+extern UInt16 FldGetInsPtPosition (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetInsPtPosition);
+
+extern void FldSetInsPtPosition (FieldType *fldP, UInt16 pos)
+ SYS_TRAP(sysTrapFldSetInsPtPosition);
+
+extern void FldSetInsertionPoint (FieldType *fldP, UInt16 pos)
+ SYS_TRAP(sysTrapFldSetInsertionPoint);
+
+extern UInt16 FldGetScrollPosition (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetScrollPosition);
+
+extern void FldSetScrollPosition (FieldType *fldP, UInt16 pos)
+ SYS_TRAP(sysTrapFldSetScrollPosition);
+
+extern void FldGetScrollValues (const FieldType *fldP, UInt16 *scrollPosP,
+ UInt16 *textHeightP, UInt16 *fieldHeightP)
+ SYS_TRAP(sysTrapFldGetScrollValues);
+
+extern UInt16 FldGetTextLength (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetTextLength);
+
+extern void FldScrollField (FieldType *fldP, UInt16 linesToScroll, WinDirectionType direction)
+ SYS_TRAP(sysTrapFldScrollField);
+
+extern Boolean FldScrollable (const FieldType *fldP, WinDirectionType direction)
+ SYS_TRAP(sysTrapFldScrollable);
+
+extern UInt16 FldGetVisibleLines (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetVisibleLines);
+
+extern UInt16 FldGetTextHeight (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetTextHeight);
+
+extern UInt16 FldCalcFieldHeight (const Char *chars, UInt16 maxWidth)
+ SYS_TRAP(sysTrapFldCalcFieldHeight);
+
+extern UInt16 FldWordWrap (const Char *chars, Int16 maxWidth)
+ SYS_TRAP(sysTrapFldWordWrap);
+
+extern void FldCompactText (FieldType *fldP)
+ SYS_TRAP(sysTrapFldCompactText);
+
+extern Boolean FldDirty (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldDirty);
+
+extern void FldSetDirty (FieldType *fldP, Boolean dirty)
+ SYS_TRAP(sysTrapFldSetDirty);
+
+extern UInt16 FldGetMaxChars (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetMaxChars);
+
+extern void FldSetMaxChars (FieldType *fldP, UInt16 maxChars)
+ SYS_TRAP(sysTrapFldSetMaxChars);
+
+extern Boolean FldInsert (FieldType *fldP, const Char *insertChars, UInt16 insertLen)
+ SYS_TRAP(sysTrapFldInsert);
+
+extern void FldDelete (FieldType *fldP, UInt16 start, UInt16 end)
+ SYS_TRAP(sysTrapFldDelete);
+
+extern void FldUndo (FieldType *fldP)
+ SYS_TRAP(sysTrapFldUndo);
+
+extern UInt16 FldGetTextAllocatedSize (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetTextAllocatedSize);
+
+extern void FldSetTextAllocatedSize (FieldType *fldP, UInt16 allocatedSize)
+ SYS_TRAP(sysTrapFldSetTextAllocatedSize);
+
+extern void FldGetAttributes (const FieldType *fldP, FieldAttrPtr attrP)
+ SYS_TRAP(sysTrapFldGetAttributes);
+
+extern void FldSetAttributes (FieldType *fldP, const FieldAttrType *attrP)
+ SYS_TRAP(sysTrapFldSetAttributes);
+
+extern void FldSendChangeNotification (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldSendChangeNotification);
+
+extern void FldSendHeightChangeNotification (const FieldType *fldP, UInt16 pos, Int16 numLines)
+ SYS_TRAP(sysTrapFldSendHeightChangeNotification);
+
+extern Boolean FldMakeFullyVisible (FieldType *fldP)
+ SYS_TRAP(sysTrapFldMakeFullyVisible);
+
+extern UInt16 FldGetNumberOfBlankLines (const FieldType *fldP)
+ SYS_TRAP(sysTrapFldGetNumberOfBlankLines);
+
+extern FieldType *FldNewField (void **formPP, UInt16 id,
+ Coord x, Coord y, Coord width, Coord height,
+ FontID font, UInt32 maxChars, Boolean editable, Boolean underlined,
+ Boolean singleLine, Boolean dynamicSize, JustificationType justification,
+ Boolean autoShift, Boolean hasScrollBar, Boolean numeric)
+ SYS_TRAP(sysTrapFldNewField);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __FIELD_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Find.h b/SrcShared/Palm/Platform/Incs/Core/UI/Find.h
new file mode 100644
index 0000000..5e3c891
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Find.h
@@ -0,0 +1,124 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Find.h
+ *
+ * Description:
+ * This file defines field structures and routines.
+ *
+ * History:
+ * August 29, 1994 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __FIND_H__
+#define __FIND_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <DataMgr.h>
+#include <Rect.h>
+
+#define maxFinds 9
+#define maxFindStrLen 16
+
+typedef struct {
+ UInt16 appCardNo; // card number of the application
+ LocalID appDbID; // LocalID of the application
+ Boolean foundInCaller; // true if found in app that called Find
+ UInt8 reserved;
+
+ UInt16 dbCardNo; // card number of the database record was found in
+ LocalID dbID; // LocalID of the database record was found in
+ UInt16 recordNum; // index of record that contain a match
+ UInt16 matchPos; // postion in record of the match.
+ UInt16 matchFieldNum; // field number
+ UInt32 matchCustom; // app specific data
+ } FindMatchType;
+
+typedef FindMatchType *FindMatchPtr;
+
+typedef struct {
+
+ // These fields are used by the applications.
+ UInt16 dbAccesMode; // read mode and maybe show secret
+ UInt16 recordNum; // index of last record that contained a match
+ Boolean more; // true of more matches to display
+ Char strAsTyped [maxFindStrLen+1]; // search string as entered
+ Char strToFind [maxFindStrLen+1]; // search string is lower case
+ UInt8 reserved1;
+
+
+ // The lineNumber field can be modified by the app. The continuation field can
+ // be tested by the app. All other fields are private to the Find routine and
+ // should NOT be accessed by applications.
+ UInt16 numMatches; // # of matches
+ UInt16 lineNumber; // next line in the results tabel
+ Boolean continuation; // true if contining search of same app
+ Boolean searchedCaller; // true after we've searched app that initiated the find
+
+ LocalID callerAppDbID; // dbID of app that initiated search
+ UInt16 callerAppCardNo; // cardNo of app that initiated search
+
+ LocalID appDbID; // dbID of app that we're currently searching
+ UInt16 appCardNo; // card number of app that we're currently searching
+
+ Boolean newSearch; // true for first search
+ UInt8 reserved2;
+ DmSearchStateType searchState; // search state
+ FindMatchType match [maxFinds];
+} FindParamsType;
+
+typedef FindParamsType *FindParamsPtr;
+
+
+// Param Block passsed with the sysAppLaunchCmdGoto Command
+typedef struct {
+ Int16 searchStrLen; // length of search string.
+ UInt16 dbCardNo; // card number of the database
+ LocalID dbID; // LocalID of the database
+ UInt16 recordNum; // index of record that contain a match
+ UInt16 matchPos; // postion in record of the match.
+ UInt16 matchFieldNum; // field number string was found int
+ UInt32 matchCustom; // application specific info
+ } GoToParamsType;
+
+typedef GoToParamsType *GoToParamsPtr;
+
+
+//----------------------------------------------------------
+// Find Functions
+//----------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void Find (GoToParamsPtr goToP)
+ SYS_TRAP(sysTrapFind);
+
+
+Boolean FindStrInStr (Char const *strToSearch, Char const *strToFind,
+ UInt16 *posP)
+ SYS_TRAP(sysTrapFindStrInStr);
+
+Boolean FindSaveMatch (FindParamsPtr findParams, UInt16 recordNum,
+ UInt16 pos, UInt16 fieldNum, UInt32 appCustom, UInt16 cardNo, LocalID dbID)
+ SYS_TRAP(sysTrapFindSaveMatch);
+
+void FindGetLineBounds (const FindParamsType *findParams, RectanglePtr r)
+ SYS_TRAP(sysTrapFindGetLineBounds);
+
+Boolean FindDrawHeader (FindParamsPtr findParams, Char const *title)
+ SYS_TRAP(sysTrapFindDrawHeader);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif //__FIND_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Form.h b/SrcShared/Palm/Platform/Incs/Core/UI/Form.h
new file mode 100644
index 0000000..0245029
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Form.h
@@ -0,0 +1,510 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Form.h
+ *
+ * Description:
+ * This file defines dialog box structures and routines.
+ *
+ * History:
+ * September 6, 1994 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __FORM_H__
+#define __FORM_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+#include <Preferences.h>
+
+#include <Field.h>
+#include <Control.h>
+#include <List.h>
+#include <ScrollBar.h>
+#include <Table.h>
+
+#define noFocus 0xffff
+
+#define frmInvalidObjectId 0xffff
+#define frmNoSelectedControl 0xff
+
+// Update code send as part of a frmUpdate event.
+#define frmRedrawUpdateCode 0x8000
+
+// Magic button IDs used by FrmCustomResponseAlert callbacks
+#define frmResponseCreate 1974
+#define frmResponseQuit ((Int16) 0xBEEF)
+
+
+// Alert constants and structures
+enum alertTypes {
+ informationAlert,
+ confirmationAlert,
+ warningAlert,
+ errorAlert };
+typedef enum alertTypes AlertType;
+
+typedef struct {
+ UInt16 alertType;
+ UInt16 helpRscID;
+ UInt16 numButtons;
+ UInt16 defaultButton;
+} AlertTemplateType;
+
+
+// Types of object in a dialog box
+enum formObjects {
+ frmFieldObj,
+ frmControlObj,
+ frmListObj,
+ frmTableObj,
+ frmBitmapObj,
+ frmLineObj,
+ frmFrameObj,
+ frmRectangleObj,
+ frmLabelObj,
+ frmTitleObj,
+ frmPopupObj,
+ frmGraffitiStateObj,
+ frmGadgetObj,
+ frmScrollBarObj };
+typedef enum formObjects FormObjectKind;
+
+
+typedef struct {
+ UInt16 usable :1; // Set if part of ui
+ UInt16 reserved :15; // pad it out
+} FormObjAttrType;
+
+
+// Gadget support:
+#define formGadgetDrawCmd 0 // paramP is unspecified
+#define formGadgetEraseCmd 1 // paramP is unspecified
+#define formGadgetHandleEventCmd 2 // paramP is an EventType *for the relevant event.
+#define formGadgetDeleteCmd 3 // paramP is unspecified.
+
+
+typedef struct {
+ UInt16 usable :1; // Set if part of ui - "should be drawn"
+ UInt16 extended :1; // Set if the structure is an "Extended" gadget (i.e., the 'handler' field is present)
+ UInt16 visible :1; // Set if drawn - "has been drawn" or "must do work to erase"
+ UInt16 reserved :13; // pad it out
+} FormGadgetAttrType;
+
+struct FormType; // forward reference to FormType so we can declare the handler type:
+typedef Boolean (FormGadgetHandlerType) (struct FormGadgetType *gadgetP, UInt16 cmd, void *paramP);
+
+struct FormGadgetType {
+ UInt16 id;
+ FormGadgetAttrType attr;
+ RectangleType rect;
+ const void * data;
+ FormGadgetHandlerType *handler;
+};
+typedef struct FormGadgetType FormGadgetType;
+
+
+// All of the smaller form objects:
+
+typedef struct {
+ FormObjAttrType attr;
+ PointType pos;
+ UInt16 rscID;
+} FormBitmapType;
+
+
+typedef struct {
+ FormObjAttrType attr;
+ PointType point1;
+ PointType point2;
+} FormLineType;
+
+
+typedef struct {
+ UInt16 id;
+ FormObjAttrType attr;
+ RectangleType rect;
+ UInt16 frameType;
+} FormFrameType;
+
+
+typedef struct {
+ FormObjAttrType attr;
+ RectangleType rect;
+} FormRectangleType;
+
+
+typedef struct {
+ UInt16 id;
+ PointType pos;
+ FormObjAttrType attr;
+ FontID fontID;
+ UInt8 reserved;
+ Char * text;
+} FormLabelType;
+
+
+typedef struct {
+ RectangleType rect;
+ Char * text;
+} FormTitleType;
+
+
+typedef struct {
+ UInt16 controlID;
+ UInt16 listID;
+} FormPopupType;
+
+
+typedef struct {
+ PointType pos;
+} FrmGraffitiStateType;
+
+
+typedef union {
+ void * ptr;
+ FieldType * field;
+ ControlType * control;
+ GraphicControlType * graphicControl;
+ SliderControlType * sliderControl;
+ ListType * list;
+ TableType * table;
+ FormBitmapType * bitmap;
+// FormLineType * line;
+// FormFrameType * frame;
+// FormRectangleType * rectangle;
+ FormLabelType * label;
+ FormTitleType * title;
+ FormPopupType * popup;
+ FrmGraffitiStateType * grfState;
+ FormGadgetType * gadget;
+ ScrollBarType * scrollBar;
+} FormObjectType;
+
+// typedef FormObjectType *FormObjectPtr;
+
+
+typedef struct {
+ FormObjectKind objectType;
+ UInt8 reserved;
+ FormObjectType object;
+} FormObjListType;
+
+
+typedef struct {
+ UInt16 usable :1; // Set if part of ui
+ UInt16 enabled :1; // Set if interactable (not grayed out)
+ UInt16 visible :1; // Set if drawn, used internally
+ UInt16 dirty :1; // Set if dialog has been modified
+ UInt16 saveBehind :1; // Set if bits behind form are save when form ids drawn
+ UInt16 graffitiShift :1; // Set if graffiti shift indicator is supported
+ UInt16 globalsAvailable:1; // Set by Palm OS if globals are available for the
+ // form event handler
+ UInt16 doingDialog :1; // FrmDoDialog is using for nested event loop
+ UInt16 exitDialog :1; // tells FrmDoDialog to bail out and stop using this form
+ UInt16 reserved :7; // pad to 16
+ UInt16 reserved2; // FormAttrType now explicitly 32-bits wide.
+} FormAttrType;
+
+
+typedef Boolean FormEventHandlerType (EventType *eventP);
+
+typedef FormEventHandlerType *FormEventHandlerPtr;
+
+struct FormType {
+ WindowType window;
+ UInt16 formId;
+ FormAttrType attr;
+ WinHandle bitsBehindForm;
+ FormEventHandlerType * handler;
+ UInt16 focus;
+ UInt16 defaultButton;
+ UInt16 helpRscId;
+ UInt16 menuRscId;
+ UInt16 numObjects;
+ FormObjListType * objects;
+};
+
+typedef struct FormType FormType;
+typedef FormType *FormPtr;
+
+
+// FormActiveStateType: this structure is passed to FrmActiveState for
+// saving and restoring active form/window state; this structure's
+// contents are abstracted because the contents will differ significantly
+// as PalmOS evolves
+// Added for PalmOS 3.0
+typedef struct FormActiveStateType {
+ UInt16 data[11];
+ } FormActiveStateType;
+
+
+// FrmCustomResponseAlert callback routine prototype
+typedef Boolean FormCheckResponseFuncType
+ (Int16 button, Char * attempt);
+
+typedef FormCheckResponseFuncType *FormCheckResponseFuncPtr;
+
+
+//-----------------------------------------------
+// Macros
+//-----------------------------------------------
+
+#if ERROR_CHECK_LEVEL == ERROR_CHECK_FULL
+#define ECFrmValidatePtr(formP) FrmValidatePtr(formP)
+#else
+#define ECFrmValidatePtr(formP)
+#endif
+
+//--------------------------------------------------------------------
+//
+// Form Function
+//
+//--------------------------------------------------------------------
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern FormType * FrmInitForm (UInt16 rscID)
+ SYS_TRAP(sysTrapFrmInitForm);
+
+extern void FrmDeleteForm (FormType *formP)
+ SYS_TRAP(sysTrapFrmDeleteForm);
+
+extern void FrmDrawForm (FormType *formP)
+ SYS_TRAP(sysTrapFrmDrawForm);
+
+extern void FrmEraseForm (FormType *formP)
+ SYS_TRAP(sysTrapFrmEraseForm);
+
+extern FormType * FrmGetActiveForm (void)
+ SYS_TRAP(sysTrapFrmGetActiveForm);
+
+extern void FrmSetActiveForm (FormType *formP)
+ SYS_TRAP(sysTrapFrmSetActiveForm);
+
+extern UInt16 FrmGetActiveFormID (void)
+ SYS_TRAP(sysTrapFrmGetActiveFormID);
+
+extern Boolean FrmGetUserModifiedState (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetUserModifiedState);
+
+extern void FrmSetNotUserModified (FormType *formP)
+ SYS_TRAP(sysTrapFrmSetNotUserModified);
+
+extern UInt16 FrmGetFocus (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetFocus);
+
+extern void FrmSetFocus (FormType *formP, UInt16 fieldIndex)
+ SYS_TRAP(sysTrapFrmSetFocus);
+
+extern Boolean FrmHandleEvent (FormType *formP, EventType *eventP)
+ SYS_TRAP(sysTrapFrmHandleEvent);
+
+extern void FrmGetFormBounds (const FormType *formP, RectangleType *rP)
+ SYS_TRAP(sysTrapFrmGetFormBounds);
+
+extern WinHandle FrmGetWindowHandle (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetWindowHandle);
+
+extern UInt16 FrmGetFormId (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetFormId);
+
+extern FormType *FrmGetFormPtr (UInt16 formId)
+ SYS_TRAP(sysTrapFrmGetFormPtr);
+
+extern FormType *FrmGetFirstForm (void)
+ SYS_TRAP(sysTrapFrmGetFirstForm);
+
+extern UInt16 FrmGetNumberOfObjects (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetNumberOfObjects);
+
+extern UInt16 FrmGetObjectIndex (const FormType *formP, UInt16 objID)
+ SYS_TRAP(sysTrapFrmGetObjectIndex);
+
+extern UInt16 FrmGetObjectId (const FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmGetObjectId);
+
+extern FormObjectKind FrmGetObjectType (const FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmGetObjectType);
+
+extern void *FrmGetObjectPtr (const FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmGetObjectPtr);
+
+extern void FrmGetObjectBounds (const FormType *formP, UInt16 objIndex,
+ RectangleType *rP)
+ SYS_TRAP(sysTrapFrmGetObjectBounds);
+
+extern void FrmHideObject (FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmHideObject);
+
+extern void FrmShowObject (FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmShowObject);
+
+extern void FrmGetObjectPosition (const FormType *formP, UInt16 objIndex,
+ Coord *x, Coord *y)
+ SYS_TRAP(sysTrapFrmGetObjectPosition);
+
+extern void FrmSetObjectPosition (FormType *formP, UInt16 objIndex,
+ Coord x, Coord y)
+ SYS_TRAP(sysTrapFrmSetObjectPosition);
+
+extern void FrmSetObjectBounds (FormType *formP, UInt16 objIndex,
+ const RectangleType *bounds)
+ SYS_TRAP(sysTrapFrmSetObjectBounds);
+
+extern Int16 FrmGetControlValue (const FormType *formP, UInt16 controlID)
+ SYS_TRAP(sysTrapFrmGetControlValue);
+
+extern void FrmSetControlValue (const FormType *formP, UInt16 controlID,
+ Int16 newValue)
+ SYS_TRAP(sysTrapFrmSetControlValue);
+
+extern UInt16 FrmGetControlGroupSelection (const FormType *formP,
+ UInt8 groupNum)
+ SYS_TRAP(sysTrapFrmGetControlGroupSelection);
+
+extern void FrmSetControlGroupSelection (const FormType *formP,
+ UInt8 groupNum, UInt16 controlID)
+ SYS_TRAP(sysTrapFrmSetControlGroupSelection);
+
+extern void FrmCopyLabel (FormType *formP, UInt16 labelID,
+ const Char *newLabel)
+ SYS_TRAP(sysTrapFrmCopyLabel);
+
+extern const Char *FrmGetLabel (const FormType *formP, UInt16 labelID)
+ SYS_TRAP(sysTrapFrmGetLabel);
+
+extern void FrmSetCategoryLabel (const FormType *formP, UInt16 objIndex,
+ Char *newLabel)
+ SYS_TRAP(sysTrapFrmSetCategoryLabel);
+
+extern const Char *FrmGetTitle (const FormType *formP)
+ SYS_TRAP(sysTrapFrmGetTitle);
+
+extern void FrmSetTitle (FormType *formP, Char *newTitle)
+ SYS_TRAP(sysTrapFrmSetTitle);
+
+extern void FrmCopyTitle (FormType *formP, const Char *newTitle)
+ SYS_TRAP(sysTrapFrmCopyTitle);
+
+extern void *FrmGetGadgetData (const FormType *formP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmGetGadgetData);
+
+extern void FrmSetGadgetData (FormType *formP, UInt16 objIndex,
+ const void *data)
+ SYS_TRAP(sysTrapFrmSetGadgetData);
+
+extern void FrmSetGadgetHandler (FormType *formP, UInt16 objIndex,
+ FormGadgetHandlerType *attrP)
+ SYS_TRAP(sysTrapFrmSetGadgetHandler);
+
+extern UInt16 FrmDoDialog (FormType *formP)
+ SYS_TRAP(sysTrapFrmDoDialog);
+
+extern UInt16 FrmAlert (UInt16 alertId)
+ SYS_TRAP(sysTrapFrmAlert);
+
+extern UInt16 FrmCustomAlert (UInt16 alertId, const Char *s1,
+ const Char *s2, const Char *s3)
+ SYS_TRAP(sysTrapFrmCustomAlert);
+
+extern void FrmHelp (UInt16 helpMsgId)
+ SYS_TRAP(sysTrapFrmHelp);
+
+extern void FrmUpdateScrollers (FormType *formP, UInt16 upIndex,
+ UInt16 downIndex, Boolean scrollableUp, Boolean scrollableDown)
+ SYS_TRAP(sysTrapFrmUpdateScrollers);
+
+extern Boolean FrmVisible (const FormType *formP)
+ SYS_TRAP(sysTrapFrmVisible);
+
+extern void FrmSetEventHandler (FormType *formP, FormEventHandlerType *handler)
+ SYS_TRAP(sysTrapFrmSetEventHandler);
+
+extern Boolean FrmDispatchEvent (EventType *eventP)
+ SYS_TRAP(sysTrapFrmDispatchEvent);
+
+
+
+
+extern void FrmPopupForm (UInt16 formId)
+ SYS_TRAP(sysTrapFrmPopupForm);
+
+extern void FrmGotoForm (UInt16 formId)
+ SYS_TRAP(sysTrapFrmGotoForm);
+
+extern void FrmUpdateForm (UInt16 formId, UInt16 updateCode)
+ SYS_TRAP(sysTrapFrmUpdateForm);
+
+extern void FrmReturnToForm (UInt16 formId)
+ SYS_TRAP(sysTrapFrmReturnToForm);
+
+extern void FrmCloseAllForms (void)
+ SYS_TRAP(sysTrapFrmCloseAllForms);
+
+extern void FrmSaveAllForms (void)
+ SYS_TRAP(sysTrapFrmSaveAllForms);
+
+
+
+extern Boolean FrmPointInTitle (const FormType *formP, Coord x, Coord y)
+ SYS_TRAP(sysTrapFrmPointInTitle);
+
+extern void FrmSetMenu (FormType *formP, UInt16 menuRscID)
+ SYS_TRAP(sysTrapFrmSetMenu);
+
+extern Boolean FrmValidatePtr (const FormType *formP)
+ SYS_TRAP(sysTrapFrmValidatePtr);
+
+extern Err FrmAddSpaceForObject (FormType **formPP, MemPtr *objectPP,
+ FormObjectKind objectKind, UInt16 objectSize)
+ SYS_TRAP(sysTrapFrmAddSpaceForObject);
+
+extern Err FrmRemoveObject (FormType **formPP, UInt16 objIndex)
+ SYS_TRAP(sysTrapFrmRemoveObject);
+
+extern FormType *FrmNewForm (UInt16 formID, const Char *titleStrP,
+ Coord x, Coord y, Coord width, Coord height, Boolean modal,
+ UInt16 defaultButton, UInt16 helpRscID, UInt16 menuRscID)
+ SYS_TRAP(sysTrapFrmNewForm);
+
+extern FormLabelType *FrmNewLabel (FormType **formPP, UInt16 ID, const Char *textP,
+ Coord x, Coord y, FontID font)
+ SYS_TRAP(sysTrapFrmNewLabel);
+
+extern FormBitmapType *FrmNewBitmap (FormType **formPP, UInt16 ID,
+ UInt16 rscID, Coord x, Coord y)
+ SYS_TRAP(sysTrapFrmNewBitmap);
+
+extern FormGadgetType *FrmNewGadget (FormType **formPP, UInt16 id,
+ Coord x, Coord y, Coord width, Coord height)
+ SYS_TRAP(sysTrapFrmNewGadget);
+
+extern Err FrmActiveState (FormActiveStateType *stateP, Boolean save)
+ SYS_TRAP(sysTrapFrmActiveState);
+
+extern UInt16 FrmCustomResponseAlert (UInt16 alertId, const Char *s1, const Char *s2,
+ const Char *s3, Char *entryStringBuf, Int16 entryStringBufLength,
+ FormCheckResponseFuncPtr callback)
+ SYS_TRAP(sysTrapFrmCustomResponseAlert);
+
+extern FrmGraffitiStateType *FrmNewGsi (FormType **formPP, Coord x, Coord y)
+ SYS_TRAP(sysTrapFrmNewGsi);
+
+#define FrmSaveActiveState(stateP) FrmActiveState(stateP, true)
+#define FrmRestoreActiveState(stateP) FrmActiveState(stateP, false)
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __FORM_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/InsPoint.h b/SrcShared/Palm/Platform/Incs/Core/UI/InsPoint.h
new file mode 100644
index 0000000..f29efc8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/InsPoint.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: InsPoint.h
+ *
+ * Description:
+ * This file defines insertion point routines.
+ *
+ * History:
+ * Jan 25, 1995 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __INSPOINT_H__
+#define __INSPOINT_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+// Blink interval is half of a second
+#define insPtBlinkInterval (sysTicksPerSecond / 2)
+#define insPtWidth 2
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void InsPtInitialize (void)
+ SYS_TRAP(sysTrapInsPtInitialize);
+
+extern void InsPtSetLocation (const Int16 x, const Int16 y)
+ SYS_TRAP(sysTrapInsPtSetLocation);
+
+extern void InsPtGetLocation (Int16 *x, Int16 *y)
+ SYS_TRAP(sysTrapInsPtGetLocation);
+
+extern void InsPtEnable (Boolean enableIt)
+ SYS_TRAP(sysTrapInsPtEnable);
+
+extern Boolean InsPtEnabled (void)
+ SYS_TRAP(sysTrapInsPtEnabled);
+
+extern void InsPtSetHeight (const Int16 height)
+ SYS_TRAP(sysTrapInsPtSetHeight);
+
+extern Int16 InsPtGetHeight (void)
+ SYS_TRAP(sysTrapInsPtGetHeight);
+
+extern void InsPtCheckBlink (void)
+ SYS_TRAP(sysTrapInsPtCheckBlink);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif //__INSPOINT_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/List.h b/SrcShared/Palm/Platform/Incs/Core/UI/List.h
new file mode 100644
index 0000000..60a6e16
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/List.h
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: List.h
+ *
+ * Description:
+ * This file defines list structures and routines.
+ *
+ * History:
+ * November 3, 1994 Created by Roger Flores
+ * Name Date Description
+ * ---- ---- -----------
+ * bob 2/9/99 fixed const stuff
+ *
+ *****************************************************************************/
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <Event.h>
+
+#define noListSelection -1
+
+//-------------------------------------------------------------------
+// List structures
+//-------------------------------------------------------------------
+
+typedef struct {
+ UInt16 usable :1; // set if part of ui
+ UInt16 enabled :1; // set if interactable (not grayed out)
+ UInt16 visible :1; // set if drawn
+ UInt16 poppedUp :1; // set if choices displayed in popup win.
+ UInt16 hasScrollBar :1; // set if the list has a scroll bar
+ UInt16 search :1; // set if incremental search is enabled
+ UInt16 reserved :2;
+} ListAttrType;
+
+
+// Load data callback routine prototype
+typedef void ListDrawDataFuncType (Int16 itemNum, RectangleType *bounds,
+ Char **itemsText);
+
+typedef ListDrawDataFuncType *ListDrawDataFuncPtr;
+
+
+typedef struct ListType {
+ UInt16 id;
+ RectangleType bounds;
+ ListAttrType attr;
+ Char * *itemsText;
+ Int16 numItems; // number of choices in the list
+ Int16 currentItem; // currently display choice
+ Int16 topItem; // top item visible when poped up
+ FontID font; // font used to draw list
+ UInt8 reserved;
+ WinHandle popupWin; // used only by popup lists
+ ListDrawDataFuncPtr drawItemsCallback; // 0 indicates no function
+} ListType;
+
+typedef ListType *ListPtr;
+
+
+//-------------------------------------------------------------------
+// List routines
+//-------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void LstDrawList (ListType *listP)
+ SYS_TRAP(sysTrapLstDrawList);
+
+extern void LstEraseList (ListType *listP)
+ SYS_TRAP(sysTrapLstEraseList);
+
+extern Int16 LstGetSelection (const ListType *listP)
+ SYS_TRAP(sysTrapLstGetSelection);
+
+extern Char * LstGetSelectionText (const ListType *listP, Int16 itemNum)
+ SYS_TRAP(sysTrapLstGetSelectionText);
+
+extern Boolean LstHandleEvent (ListType *listP, const EventType *eventP)
+ SYS_TRAP(sysTrapLstHandleEvent);
+
+extern void LstSetHeight (ListType *listP, Int16 visibleItems)
+ SYS_TRAP(sysTrapLstSetHeight);
+
+extern void LstSetPosition (ListType *listP, Coord x, Coord y)
+ SYS_TRAP(sysTrapLstSetPosition);
+
+extern void LstSetSelection (ListType *listP, Int16 itemNum)
+ SYS_TRAP(sysTrapLstSetSelection);
+
+extern void LstSetListChoices (ListType *listP, Char **itemsText, Int16 numItems)
+ SYS_TRAP(sysTrapLstSetListChoices);
+
+extern void LstSetDrawFunction (ListType *listP, ListDrawDataFuncPtr func)
+ SYS_TRAP(sysTrapLstSetDrawFunction);
+
+extern void LstSetTopItem (ListType *listP, Int16 itemNum)
+ SYS_TRAP(sysTrapLstSetTopItem);
+
+extern void LstMakeItemVisible (ListType *listP, Int16 itemNum)
+ SYS_TRAP(sysTrapLstMakeItemVisible);
+
+extern Int16 LstGetNumberOfItems (const ListType *listP)
+ SYS_TRAP(sysTrapLstGetNumberOfItems);
+
+extern Int16 LstPopupList (ListType *listP)
+ SYS_TRAP(sysTrapLstPopupList);
+
+extern Boolean LstScrollList(ListType *listP, WinDirectionType direction, Int16 itemCount)
+ SYS_TRAP(sysTrapLstScrollList);
+
+extern Int16 LstGetVisibleItems (const ListType *listP)
+ SYS_TRAP(sysTrapLstGetVisibleItems);
+
+extern Err LstNewList (void **formPP, UInt16 id,
+ Coord x, Coord y, Coord width, Coord height,
+ FontID font, Int16 visibleItems, Int16 triggerId)
+ SYS_TRAP(sysTrapLstNewList);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LIST_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/ScrollBar.h b/SrcShared/Palm/Platform/Incs/Core/UI/ScrollBar.h
new file mode 100644
index 0000000..a7163bb
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/ScrollBar.h
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1996-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: ScrollBar.h
+ *
+ * Description:
+ * This file defines scroll bar structures and routines.
+ *
+ * History:
+ * Feb 6, 1996 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __SCROLLBAR_H__
+#define __SCROLLBAR_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <Rect.h>
+#include <Event.h>
+
+typedef enum { sclUpArrow, sclDownArrow, sclUpPage, sclDownPage, sclCar }
+ ScrollBarRegionType;
+
+
+typedef struct {
+ UInt16 usable :1; // Set if part of ui
+ UInt16 visible :1; // Set if drawn, used internally
+ UInt16 hilighted :1; // Set if region is hilighted
+ UInt16 shown :1; // Set if drawn and maxValue > minValue
+ UInt16 activeRegion :4; // ScrollBarRegionType
+} ScrollBarAttrType;
+
+
+typedef struct ScrollBarType {
+ RectangleType bounds;
+ UInt16 id;
+ ScrollBarAttrType attr;
+ Int16 value;
+ Int16 minValue;
+ Int16 maxValue;
+ Int16 pageSize;
+ Int16 penPosInCar;
+ Int16 savePos;
+} ScrollBarType;
+
+typedef ScrollBarType *ScrollBarPtr;
+
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void SclGetScrollBar (const ScrollBarPtr bar, Int16 *valueP,
+ Int16 *minP, Int16 *maxP, Int16 *pageSizeP)
+ SYS_TRAP(sysTrapSclGetScrollBar);
+
+extern void SclSetScrollBar (const ScrollBarPtr bar, Int16 value,
+ const Int16 min, const Int16 max, const Int16 pageSize)
+ SYS_TRAP(sysTrapSclSetScrollBar);
+
+extern void SclDrawScrollBar (const ScrollBarPtr bar)
+ SYS_TRAP(sysTrapSclDrawScrollBar);
+
+extern Boolean SclHandleEvent (const ScrollBarPtr bar, const EventType *event)
+ SYS_TRAP(sysTrapSclHandleEvent);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+#endif //__SCROLLBAR_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/Table.h b/SrcShared/Palm/Platform/Incs/Core/UI/Table.h
new file mode 100644
index 0000000..1c67ce8
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/Table.h
@@ -0,0 +1,319 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: Table.h
+ *
+ * Description:
+ * This file defines table structures and routines.
+ *
+ * History:
+ * September 1, 1994 Created by Art Lamb
+ *
+ *****************************************************************************/
+
+#ifndef __TABLE_H__
+#define __TABLE_H__
+
+#include <PalmTypes.h>
+#include <CoreTraps.h>
+
+#include <Field.h>
+
+//-------------------------------------------------------------------
+// Table structures
+//-------------------------------------------------------------------
+
+#define tableDefaultColumnSpacing 1
+#define tableNoteIndicatorWidth 7
+#define tableNoteIndicatorHeight 11
+#define tableMaxTextItemSize 255 // does not incude terminating null
+
+#define tblUnusableRow 0xffff
+
+// Display style of a table item
+//
+enum tableItemStyles { checkboxTableItem,
+ customTableItem,
+ dateTableItem,
+ labelTableItem,
+ numericTableItem,
+ popupTriggerTableItem,
+ textTableItem,
+ textWithNoteTableItem,
+ timeTableItem,
+ narrowTextTableItem
+ };
+typedef enum tableItemStyles TableItemStyleType;
+
+
+typedef struct {
+ TableItemStyleType itemType;
+ FontID fontID; // font for drawing text
+ Int16 intValue;
+ Char * ptr;
+} TableItemType;
+typedef TableItemType *TableItemPtr;
+
+
+// Draw item callback routine prototype, used only by customTableItem.
+typedef void TableDrawItemFuncType
+ (void *tableP, Int16 row, Int16 column, RectangleType *bounds);
+
+typedef TableDrawItemFuncType *TableDrawItemFuncPtr;
+
+
+// Load data callback routine prototype
+typedef Err TableLoadDataFuncType
+ (void *tableP, Int16 row, Int16 column, Boolean editable,
+ MemHandle * dataH, Int16 *dataOffset, Int16 *dataSize, FieldPtr fld);
+
+typedef TableLoadDataFuncType *TableLoadDataFuncPtr;
+
+
+// Save data callback routine prototype
+typedef Boolean TableSaveDataFuncType
+ (void *tableP, Int16 row, Int16 column);
+
+typedef TableSaveDataFuncType *TableSaveDataFuncPtr;
+
+typedef struct {
+ Coord width; // width in pixels
+ UInt16 reserved1 : 5;
+ UInt16 masked : 1; // if both row + column masked, draw only grey box
+ UInt16 editIndicator : 1;
+ UInt16 usable : 1;
+ UInt16 reserved2 : 8;
+ Coord spacing; // space after column
+ TableDrawItemFuncPtr drawCallback;
+ TableLoadDataFuncPtr loadDataCallback;
+ TableSaveDataFuncPtr saveDataCallback;
+
+} TableColumnAttrType;
+
+
+typedef struct {
+ UInt16 id;
+ Coord height; // row height in pixels
+ UInt32 data;
+
+ UInt16 reserved1 : 7;
+ UInt16 usable : 1;
+ UInt16 reserved2 : 4;
+ UInt16 masked : 1; // if both row + column masked, draw only grey box
+ UInt16 invalid : 1; // true if redraw needed
+ UInt16 staticHeight : 1; // Set if height does not expands as text is entered
+ UInt16 selectable : 1;
+
+ UInt16 reserved3;
+
+} TableRowAttrType;
+
+
+typedef struct {
+ UInt16 visible:1; // Set if drawn, used internally
+ UInt16 editable:1; // Set if editable
+ UInt16 editing:1; // Set if in edit mode
+ UInt16 selected:1; // Set if the current item is selected
+ UInt16 hasScrollBar:1; // Set if the table has a scroll bar
+ UInt16 reserved:11;
+} TableAttrType;
+
+
+typedef struct TableType {
+ UInt16 id;
+ RectangleType bounds;
+ TableAttrType attr;
+ Int16 numColumns;
+ Int16 numRows;
+ Int16 currentRow;
+ Int16 currentColumn;
+ Int16 topRow;
+ TableColumnAttrType * columnAttrs;
+ TableRowAttrType * rowAttrs;
+ TableItemPtr items;
+ FieldType currentField;
+} TableType;
+
+typedef TableType *TablePtr;
+
+
+//-------------------------------------------------------------------
+// Table routines
+//-------------------------------------------------------------------
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void TblDrawTable (TableType *tableP)
+ SYS_TRAP(sysTrapTblDrawTable);
+
+extern void TblRedrawTable (TableType *tableP)
+ SYS_TRAP(sysTrapTblRedrawTable);
+
+extern void TblEraseTable (TableType *tableP)
+ SYS_TRAP(sysTrapTblEraseTable);
+
+extern Boolean TblHandleEvent (TableType *tableP, EventType *event)
+ SYS_TRAP(sysTrapTblHandleEvent);
+
+extern void TblGetItemBounds (const TableType *tableP, Int16 row, Int16 column, RectangleType *rP)
+ SYS_TRAP(sysTrapTblGetItemBounds);
+
+extern void TblSelectItem (TableType *tableP, Int16 row, Int16 column)
+ SYS_TRAP(sysTrapTblSelectItem);
+
+extern Int16 TblGetItemInt (const TableType *tableP, Int16 row, Int16 column)
+ SYS_TRAP(sysTrapTblGetItemInt);
+
+extern void TblSetItemInt (TableType *tableP, Int16 row, Int16 column, Int16 value)
+ SYS_TRAP(sysTrapTblSetItemInt);
+
+extern void TblSetItemPtr (TableType *tableP, Int16 row, Int16 column, void *value)
+ SYS_TRAP(sysTrapTblSetItemPtr);
+
+extern void TblSetItemStyle (TableType *tableP, Int16 row, Int16 column, TableItemStyleType type)
+ SYS_TRAP(sysTrapTblSetItemStyle);
+
+extern void TblUnhighlightSelection (TableType *tableP)
+ SYS_TRAP(sysTrapTblUnhighlightSelection);
+
+extern Boolean TblRowUsable (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblRowUsable);
+
+extern void TblSetRowUsable (TableType *tableP, Int16 row, Boolean usable)
+ SYS_TRAP(sysTrapTblSetRowUsable);
+
+extern Int16 TblGetLastUsableRow (const TableType *tableP)
+ SYS_TRAP(sysTrapTblGetLastUsableRow);
+
+extern void TblSetColumnUsable (TableType *tableP, Int16 column, Boolean usable)
+ SYS_TRAP(sysTrapTblSetColumnUsable);
+
+extern void TblSetRowSelectable (TableType *tableP, Int16 row, Boolean selectable)
+ SYS_TRAP(sysTrapTblSetRowSelectable);
+
+extern Boolean TblRowSelectable (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblRowSelectable);
+
+extern Int16 TblGetNumberOfRows (const TableType *tableP)
+ SYS_TRAP(sysTrapTblGetNumberOfRows);
+
+extern void TblSetCustomDrawProcedure (TableType *tableP, Int16 column,
+ TableDrawItemFuncPtr drawCallback)
+ SYS_TRAP(sysTrapTblSetCustomDrawProcedure);
+
+extern void TblSetLoadDataProcedure (TableType *tableP, Int16 column,
+ TableLoadDataFuncPtr loadDataCallback)
+ SYS_TRAP(sysTrapTblSetLoadDataProcedure);
+
+extern void TblSetSaveDataProcedure (TableType *tableP, Int16 column,
+ TableSaveDataFuncPtr saveDataCallback)
+ SYS_TRAP(sysTrapTblSetSaveDataProcedure);
+
+extern void TblGetBounds (const TableType *tableP, RectangleType *rP)
+ SYS_TRAP(sysTrapTblGetBounds);
+
+extern void TblSetBounds (TableType *tableP, const RectangleType *rP)
+ SYS_TRAP(sysTrapTblSetBounds);
+
+extern Coord TblGetRowHeight (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblGetRowHeight);
+
+extern void TblSetRowHeight (TableType *tableP, Int16 row, Coord height)
+ SYS_TRAP(sysTrapTblSetRowHeight);
+
+extern Coord TblGetColumnWidth (const TableType *tableP, Int16 column)
+ SYS_TRAP(sysTrapTblGetColumnWidth);
+
+extern void TblSetColumnWidth (TableType *tableP, Int16 column, Coord width)
+ SYS_TRAP(sysTrapTblSetColumnWidth);
+
+extern Coord TblGetColumnSpacing (const TableType *tableP, Int16 column)
+ SYS_TRAP(sysTrapTblGetColumnSpacing);
+
+extern void TblSetColumnSpacing (TableType *tableP, Int16 column, Coord spacing)
+ SYS_TRAP(sysTrapTblSetColumnSpacing);
+
+extern Boolean TblFindRowID (const TableType *tableP, UInt16 id, Int16 *rowP)
+ SYS_TRAP(sysTrapTblFindRowID);
+
+extern Boolean TblFindRowData (const TableType *tableP, UInt32 data, Int16 *rowP)
+ SYS_TRAP(sysTrapTblFindRowData);
+
+extern UInt16 TblGetRowID (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblGetRowID);
+
+extern void TblSetRowID (TableType *tableP, Int16 row, UInt16 id)
+ SYS_TRAP(sysTrapTblSetRowID);
+
+extern UInt32 TblGetRowData (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblGetRowData);
+
+extern void TblSetRowData (TableType *tableP, Int16 row, UInt32 data)
+ SYS_TRAP(sysTrapTblSetRowData);
+
+extern Boolean TblRowInvalid (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblRowInvalid);
+
+extern void TblMarkRowInvalid (TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblMarkRowInvalid);
+
+extern void TblMarkTableInvalid (TableType *tableP)
+ SYS_TRAP(sysTrapTblMarkTableInvalid);
+
+extern Boolean TblGetSelection (const TableType *tableP, Int16 *rowP, Int16 *columnP)
+ SYS_TRAP(sysTrapTblGetSelection);
+
+extern void TblInsertRow (TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblInsertRow);
+
+extern void TblRemoveRow (TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblRemoveRow);
+
+extern void TblReleaseFocus (TableType *tableP)
+ SYS_TRAP(sysTrapTblReleaseFocus);
+
+extern Boolean TblEditing (const TableType *tableP)
+ SYS_TRAP(sysTrapTblEditing);
+
+extern FieldPtr TblGetCurrentField (const TableType *tableP)
+ SYS_TRAP(sysTrapTblGetCurrentField);
+
+extern void TblGrabFocus (TableType *tableP, Int16 row, Int16 column)
+ SYS_TRAP(sysTrapTblGrabFocus);
+
+extern void TblSetColumnEditIndicator (TableType *tableP, Int16 column, Boolean editIndicator)
+ SYS_TRAP(sysTrapTblSetColumnEditIndicator);
+
+extern void TblSetRowStaticHeight (TableType *tableP, Int16 row, Boolean staticHeight)
+ SYS_TRAP(sysTrapTblSetRowStaticHeight);
+
+extern void TblHasScrollBar (TableType *tableP, Boolean hasScrollBar)
+ SYS_TRAP(sysTrapTblHasScrollBar);
+
+extern FontID TblGetItemFont (const TableType *tableP, Int16 row, Int16 column)
+ SYS_TRAP(sysTrapTblGetItemFont);
+
+extern void TblSetItemFont (TableType *tableP, Int16 row, Int16 column, FontID fontID)
+ SYS_TRAP(sysTrapTblSetItemFont);
+
+extern void *TblGetItemPtr (const TableType *tableP, Int16 row, Int16 column)
+ SYS_TRAP(sysTrapTblGetItemPtr);
+
+extern Boolean TblRowMasked (const TableType *tableP, Int16 row)
+ SYS_TRAP(sysTrapTblRowMasked);
+
+extern void TblSetRowMasked (TableType *tableP, Int16 row, Boolean masked)
+ SYS_TRAP(sysTrapTblSetRowMasked);
+
+extern void TblSetColumnMasked (TableType *tableP, Int16 column, Boolean masked)
+ SYS_TRAP(sysTrapTblSetColumnMasked);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif //__TABLE_H__
diff --git a/SrcShared/Palm/Platform/Incs/Core/UI/UIResources.h b/SrcShared/Palm/Platform/Incs/Core/UI/UIResources.h
new file mode 100644
index 0000000..56d2d93
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Core/UI/UIResources.h
@@ -0,0 +1,322 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1995-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: UIResources.h
+ *
+ * Description:
+ * This file defines UI resource types & ids.
+ *
+ * History:
+ * ??/??/?? ??? Created.
+ * 06/29/99 CS Added constantRscType & ResLoadConstant().
+ * 07/07/99 kwk Added fepFieldExtraBytesID, maxCategoryWidthID,
+ * extraStackSpaceID.
+ * 07/09/99 kwk Added silkscreenRscType & formRscType.
+ * 07/12/99 kwk Added sysFatalAlert.
+ * 07/18/99 kwk Added strListRscType, system string list resources.
+ * 08/08/99 kwk Added sysEditMenuJapAddWord/LookupWord.
+ * 09/07/99 kwk Added StrippedBase/GenericLaunchErrAlert
+ * 09/17/99 jmp Added a new NoteView form and menu to eliminate the goto
+ * top/bottom menu items and other extraneous UI elements
+ * that we no longer use in the built-in apps. We need to keep
+ * the old NoteView form and menu around for backwards
+ * compatibility.
+ * 12/10/99 kwk Deleted silkscreenRscType, use sysResTSilkscreen instead.
+ *
+ *****************************************************************************/
+
+#ifndef __UIRESOURCES_H__
+#define __UIRESOURCES_H__
+
+#include <CoreTraps.h>
+
+// System Default app icon (for apps missing a tAIB)
+#define defaultAppIconBitmap 10000
+#define defaultAppSmallIconBitmap 10001
+
+// System version string ID - this is hidden in
+// the SystemVersion.rsrc resource, because the 'system' resources
+// don't have ResEdit formats.
+#define systemVersionID 10000
+
+
+//------------------------------------------------------------
+// Resource Type Constants
+//------------------------------------------------------------
+
+#define strRsc 'tSTR'
+#define ainRsc 'tAIN'
+#define iconType 'tAIB'
+#define bitmapRsc 'Tbmp'
+#define bsBitmapRsc 'Tbsb'
+#define alertRscType 'Talt'
+#define kbdRscType 'tkbd'
+#define MenuRscType 'MBAR'
+#define fontRscType 'NFNT'
+#define verRsc 'tver'
+#define appInfoStringsRsc 'tAIS'
+#define fontIndexType 'fnti'
+#define midiRsc 'MIDI'
+#define colorTableRsc 'tclt'
+#define MenuCtlRsc 'tcbr'
+#define constantRscType 'tint'
+#define formRscType 'tFRM'
+#define strListRscType 'tSTL'
+#define wrdListRscType 'wrdl'
+#define defaultCategoryRscType 'taic'
+
+
+//------------------------------------------------------------
+// App Version Constants
+//------------------------------------------------------------
+
+#define appVersionID 1 // our apps use tver 1 resource
+#define appVersionAlternateID 1000 // CW Constructor uses tver 1000 resource
+ // so we'll look for ours first, then try theirs
+#define ainID 1000
+
+#define oemVersionID 10001 // Per-DB version provided by OEMs
+
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER kwk - should resource ids >= 10000 be in a private header file, so that
+#endif // PUBLIC_STUFF_STRIPPED
+// developers know they're not guaranteed to be around (or in the same format)?
+
+//------------------------------------------------------------
+// System Information Constants
+//------------------------------------------------------------
+
+#define fepFieldExtraBytesID 10000 // Extra bytes for expanded field if FEP is active.
+#define maxCategoryWidthID 10001 // Max pixel width for category trigger.
+#define extraStackSpaceID 10002 // Extra stack space for non-English locales
+
+//------------------------------------------------------------
+// System Alerts
+//------------------------------------------------------------
+
+#define SelectACategoryAlert 10000
+
+// This alert broke 1.0 applications and is now disabled until later.
+// It is redefined below (10015).
+//#define RemoveCategoryAlert 10001
+//#define RemoveCategoryRecordsButton 0
+//#define RemoveCategoryNameButton 1
+//#define RemoveCategoryCancelButton 2
+
+#define LowBatteryAlert 10002
+#define VeryLowBatteryAlert 10003
+#define UndoAlert 10004
+#define UndoCancelButton 1
+
+#define MergeCategoryAlert 10005
+#define MergeCategoryYes 0
+#define MergeCategoryNo 1
+
+#define privateRecordInfoAlert 10006
+
+#define ClipboardLimitAlert 10007
+
+#define CategoryExistsAlert 10012
+
+#define DeviceFullAlert 10013
+
+#define categoryAllUsedAlert 10014
+
+#define RemoveCategoryAlert 10015 // See alert 10001
+#define RemoveCategoryYes 0
+#define RemoveCategoryNo 1
+
+#define DemoUnitAlert 10016
+
+#define NoDataToBeamAlert 10017
+
+// New for PalmOS 3.1
+#define LowCradleChargedBatteryAlert 10018 // (Not present in Palm VII)
+#define VeryLowCradleChargedBatteryAlert 10019 // (Not present in Palm VII)
+
+// New for PalmOS 3.1 (Instant Karma only)
+#define CategoryTooLongAlert 10020 // (Not present in Palm VII)
+
+// New for PalmOS 3.2 - Alerts used by the ErrAlertCustom() call.
+#define ErrOKAlert 10021 // Error Alert with just an OK button
+#define ErrOKCancelAlert 10022 // Error Alert with an OK & Cancel button
+#define ErrCancelAlert 10023 // Error Alert with just Cancel button. Special case for antenna down alert.
+#define InfoOKAlert 10024 // Info alert with just an OK button
+#define InfoOKCancelAlert 10025 // Info alert with an OK & Cancel button
+#define InfoCancelAlert 10026 // Info alert with just a Cancel button
+#define PrivacyWarningAlert 10027 // Privacy warning for weblib
+#define ConfirmationOKAlert 10028 // Confirmation alert with just an OK button
+#define ConfirmationOKCancelAlert 10029 // Confirmation alert with an OK & Cancel button
+#define ConfirmationCancelAlert 10030 // Confirmation alert with just a Cancel button
+#define WarningOKAlert 10031 // Warning Alert with just an OK button
+#define WarningOKCancelAlert 10032 // Warning Alert with an OK & Cancel button
+#define WarningCancelAlert 10033 // Warning Alert with just Cancel button. Special case for antenna down alert.
+
+// New for PalmOS 3.5 - Launch error alerts
+#define StrippedBaseLaunchErrAlert 10034 // Launch error because of stripped base.
+#define GenericLaunchErrAlert 10035 // Generic launch error.
+
+// New for PalmOS 3.5 - Fatal Alert template
+#define sysFatalAlert 10100 // Template for fatal alert
+
+// New for PalmOS 3.5 - Alerts used by new security traps
+#define secInvalidPasswordAlert 13250
+#define secGotoInvalidRecordAlert 13251
+#define secShowPrivatePermanentPassEntryAlert 13261
+#define secShowMaskedPrivatePermanentPassEntryAlert 13265
+#define secHideRecordsAlert 13268
+#define secMaskRecordsAlert 13269
+#define secHideMaskRecordsOK 0
+#define secHideMaskRecordsCancel 1
+
+// command-bar bitmaps
+#define BarCutBitmap 10030
+#define BarCopyBitmap 10031
+#define BarPasteBitmap 10032
+#define BarUndoBitmap 10033
+#define BarBeamBitmap 10034
+#define BarSecureBitmap 10035
+#define BarDeleteBitmap 10036
+#define BarInfoBitmap 10037
+
+//Masking bitmaps
+#define SecLockBitmap 10050
+#define SecLockWidth 6
+#define SecLockHeight 8
+
+// System Menu Bar and Menus
+#define sysEditMenuID 10000
+#define sysEditMenuUndoCmd 10000
+#define sysEditMenuCutCmd 10001
+#define sysEditMenuCopyCmd 10002
+#define sysEditMenuPasteCmd 10003
+#define sysEditMenuSelectAllCmd 10004
+#define sysEditMenuSeparator 10005
+#define sysEditMenuKeyboardCmd 10006
+#define sysEditMenuGraffitiCmd 10007
+
+// Dynamically added to System Edit menu at runtime
+#define sysEditMenuJapAddWord 10100
+#define sysEditMenuJapLookupWord 10101
+
+// Note View Menu Bar and Menus
+#define noteMenuID 10200 // Old NoteView MenuBar
+#define noteUndoCmd sysEditMenuUndoCmd
+#define noteCutCmd sysEditMenuCutCmd
+#define noteCopyCmd sysEditMenuCopyCmd
+#define notePasteCmd sysEditMenuPasteCmd
+#define noteSelectAllCmd sysEditMenuSelectAllCmd
+#define noteSeparator sysEditMenuSeparator
+#define noteKeyboardCmd sysEditMenuKeyboardCmd
+#define noteGraffitiCmd sysEditMenuKeyboardCmd
+
+#define noteFontCmd 10200 // These are here for backwards
+#define noteTopOfPageCmd 10201 // compatibility. The built-in
+#define noteBottomOfPageCmd 10202 // apps no longer use them.
+#define notePhoneLookupCmd 10203
+
+#define newNoteMenuID 10300 // The Edit Menu for the new NoteView.
+#define newNoteFontCmd 10300 // MenuBar is the same as it is for
+#define newNotePhoneLookupCmd 10301 // the old NoteView MenuBar.
+
+// Note View (used by Datebook, To Do, Address, and Expense apps)
+#define NoteView 10900 // The new NoteView is "new" as of Palm OS 3.5.
+#define NewNoteView 10950 // Same as old NoteView, but points to newNoteMenuID and doesn't ref UI objects listed below.
+#define NoteField 10901
+#define NoteDoneButton 10902
+#define NoteSmallFontButton 10903 // Not in NewNoteView, use FontCmd instead.
+#define NoteLargeFontButton 10904 // Not in NewNoteView, use FontCmd instead.
+#define NoteDeleteButton 10905
+#define NoteUpButton 10906 // Not in NewNoteView, use scrollbars now.
+#define NoteDownButton 10907 // Not in NewNoteView, use scrollbars now.
+#define NoteScrollBar 10908
+#define NoteFontGroup 1
+#define noteViewMaxLength 4096 // not including null, tied to tFLD rsrc 10901
+
+
+// About Box - used by Datebook, Memo, Address, To Do, & others
+#define aboutDialog 11000
+#define aboutNameLabel 11001
+#define aboutVersionLabel 11002
+#define aboutErrorStr 11003
+
+
+// Category New Name Dialog (used for new and renamed categories)
+#define categoryNewNameDialog 11100
+#define categoryNewNameField 11103
+#define categoryNewNameOKButton 11104
+
+
+// Categories Edit Dialog
+#define CategoriesEditForm 10000
+#define CategoriesEditList 10002
+#define CategoriesEditOKButton 10003
+#define CategoriesEditNewButton 10004
+#define CategoriesEditRenameButton 10005
+#define CategoriesEditDeleteButton 10006
+
+
+// Graffiti Reference Dialog
+#define graffitiReferenceDialog 11200
+#define graffitiReferenceDoneButton 11202
+#define graffitiReferenceUpButton 11203
+#define graffitiReferenceDownButton 11204
+#define graffitiReferenceFirstBitmap 11205
+
+
+// System string resources
+#define daysOfWeekStrID 10000 // OBSOLETE - use daysOfWeekStdStrListID
+#define dayFullNamesStrID 10001 // OBSOLETE - use daysOfWeekLongStrListID
+#define monthNamesStrID 10002 // OBSOLETE - use monthNamesStdStrListID
+#define monthFullNamesStrID 10003 // OBSOLETE - use monthNamesLongStrListID
+#define categoryAllStrID 10004
+#define categoryEditStrID 10005
+#define menuCommandStrID 10006
+#define launcherBatteryStrID 10007
+#define systemNameStrID 10008
+#define phoneLookupTitleStrID 10009
+#define phoneLookupAddStrID 10010
+#define phoneLookupFormatStrID 10011
+
+// System string list resources
+#ifndef PUBLIC_STUFF_STRIPPED
+// DOLATER kwk - put in error string defines here (range)
+#endif // PUBLIC_STUFF_STRIPPED
+#define daysOfWeekShortStrListID 10200
+#define daysOfWeekStdStrListID 10201
+#define daysOfWeekLongStrListID 10202
+#define monthNamesShortStrListID 10203
+#define monthNamesStdStrListID 10204
+#define monthNamesLongStrListID 10205
+#define prefDateFormatsStrListID 10206
+#define prefDOWDateFormatsStrListID 10207
+
+
+//------------------------------------------------------------
+// Misc. resource routines
+//------------------------------------------------------------
+#ifdef REMOVE_FOR_EMULATOR
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void * ResLoadForm (UInt16 rscID)
+ SYS_TRAP(sysTrapResLoadForm);
+
+void * ResLoadMenu (UInt16 rscID)
+ SYS_TRAP(sysTrapResLoadMenu);
+
+
+Char * ResLoadString (UInt16 rscID);
+
+UInt32 ResLoadConstant (UInt16 rscID)
+ SYS_TRAP(sysTrapResLoadConstant);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#endif // __UIRESOURCES_H__
diff --git a/SrcShared/Palm/Platform/Incs/Libraries/LibTraps.h b/SrcShared/Palm/Platform/Incs/Libraries/LibTraps.h
new file mode 100644
index 0000000..cd0b63b
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/Libraries/LibTraps.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: LibTraps.h
+ *
+ * Description:
+ * Palm OS Shared Library 'default' traps.
+ *
+ * History:
+ * 7/15/99 Created by Bob Ebert
+ * mm/dd/yy initials - brief revision comment
+ *
+ *****************************************************************************/
+
+ #ifndef __LIBTRAPS_H_
+ #define __LIBTRAPS_H_
+
+// Include elementary types
+#include <PalmTypes.h>
+
+#if CPU_TYPE == CPU_68K
+#include <M68KHwr.h>
+#endif
+
+//--------------------------------------------------------------------
+// Define Library Trap Numbers
+//--------------------------------------------------------------------
+// Library traps start here and go up by 1's
+#define sysLibTrapBase 0xA800
+typedef enum {
+ sysLibTrapName = sysLibTrapBase,
+ sysLibTrapOpen,
+ sysLibTrapClose,
+ sysLibTrapSleep,
+ sysLibTrapWake,
+ sysLibTrapCustom
+ } SysLibTrapNumber;
+
+
+
+#endif //__LIBTRAPS_H_
diff --git a/SrcShared/Palm/Platform/Incs/PalmTypes.h b/SrcShared/Palm/Platform/Incs/PalmTypes.h
new file mode 100644
index 0000000..4eac7ee
--- /dev/null
+++ b/SrcShared/Palm/Platform/Incs/PalmTypes.h
@@ -0,0 +1,303 @@
+/******************************************************************************
+ *
+ * Copyright (c) 1994-1999 Palm Computing, Inc. or its subsidiaries.
+ * All rights reserved.
+ *
+ * File: PalmTypes.h
+ *
+ * Description:
+ * Common header file for all Palm OS components.
+ * Contains elementary data types
+ *
+ * History:
+ * 10/19/94 Created by Ron Marianetti
+ * 04/24/97 SCL Changes for PalmOS 2.0 SDK
+ * 08/21/98 SCL Merged WChar & WCharPtr typedefs from Sumo.
+ * 07/13/99 bob Created from Common.h, lots of cleanup of types
+ *
+ *****************************************************************************/
+
+#ifndef __PALMTYPES_H__
+#define __PALMTYPES_H__
+
+
+/************************************************************
+ * Environment configuration
+ *************************************************************/
+// <BuildDefaults.h> must be included here, rather than in <PalmOS.h>
+// because they must be included for ALL builds.
+// Not every build includes <PalmOS.h>.
+
+// To override build options in a local component, include <BuildDefines.h>
+// first, then define switches as need, and THEN include <PalmTypes.h>.
+// This new mechanism supercedes the old "AppBuildRules.h" approach.
+// More details available in <BuildDefaults.h>.
+#include <BuildDefaults.h>
+
+
+/************************************************************
+ * Useful Macros
+ *************************************************************/
+#if defined(__GNUC__) && defined(__UNIX__) // used to be in <BuildRules.h>
+ // Ensure that structure elements are 16-bit aligned
+ // Other [host] development platforms may need this as well...
+#ifndef PUBLIC_STUFF_STRIPPED
+ // DOLATER - Do NOT remove without talking to TLW first!!
+#endif // PUBLIC_STUFF_STRIPPED
+ #pragma pack(2)
+#endif
+
+
+/********************************************************************
+ * Elementary data types
+ ********************************************************************/
+// Determine if we need to define our basic types or not
+#ifndef __TYPES__ // (Already defined in CW11)
+#ifndef __MACTYPES__ // (Already defined in CWPro3)
+#define __DEFINE_TYPES_ 1
+#endif
+#endif
+
+
+// Fixed size data types
+typedef signed char Int8;
+typedef signed short Int16;
+typedef signed long Int32;
+
+#if __DEFINE_TYPES_
+typedef unsigned char UInt8;
+typedef unsigned short UInt16;
+typedef unsigned long UInt32;
+#endif
+
+
+// Logical data types
+#if __DEFINE_TYPES_
+typedef unsigned char Boolean;
+#endif
+
+typedef char Char;
+typedef UInt16 WChar; // 'wide' int'l character type.
+
+typedef UInt16 Err;
+
+typedef UInt32 LocalID; // local (card relative) chunk ID
+
+typedef Int16 Coord; // screen/window coordinate
+
+
+typedef void * MemPtr; // global pointer
+typedef struct _opaque *MemHandle; // global handle
+
+
+#if __DEFINE_TYPES_
+typedef Int32 (*ProcPtr)();
+#endif
+
+
+/************************************************************
+ * Useful Macros
+ *************************************************************/
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+#define OffsetOf(type, member) ((UInt32) &(((type *) 0)->member))
+
+
+
+
+/************************************************************
+ * Common constants
+ *************************************************************/
+#ifndef NULL
+#define NULL 0
+#endif // NULL
+
+#ifndef bitsInByte
+#define bitsInByte 8
+#endif // bitsInByte
+
+
+// Include the following typedefs if types.h wasn't read.
+#if __DEFINE_TYPES_
+ #ifdef __MWERKS__
+ #if !__option(bool)
+ #ifndef true
+ #define true 1
+ #endif
+ #ifndef false
+ #define false 0
+ #endif
+ #endif
+ #else
+ #ifndef __cplusplus
+ #ifndef true
+ enum {false, true};
+ #endif
+ #endif
+ #endif
+#endif /* __TYPES__ */
+
+
+
+
+/************************************************************
+ * Misc
+ *************************************************************/
+
+// Standardized infinite loop notation
+// Use in place of while(1), while(true), while(!0), ...
+#define loop_forever for (;;)
+
+
+// Include M68KHwr.h:
+#if EMULATION_LEVEL == EMULATION_NONE
+#if CPU_TYPE == CPU_68K
+#include <M68KHwr.h>
+//#pragma warn_no_side_effect on
+#endif
+#endif
+
+/************************************************************
+ * Metrowerks will substitute strlen and strcpy with inline
+ * 68K assembly code. Prevent this.
+ *************************************************************/
+
+#ifdef __MC68K__
+#define _NO_FAST_STRING_INLINES_ 0
+#endif
+
+
+/************************************************************
+ * Define whether or not we are direct linking, or going through
+ * traps.
+ *
+ * When eumulating we use directy linking.
+ * When running under native mode, we use traps EXCEPT for the
+ * modules that actually install the routines into the trap table.
+ * These modules will set the DIRECT_LINK define to 1
+ *************************************************************/
+#ifndef EMULATION_LEVEL
+#error "This should not happen!"
+#endif
+
+#ifndef USE_TRAPS
+ #if EMULATION_LEVEL == EMULATION_NONE
+ #define USE_TRAPS 1 // use Pilot traps
+ #else
+ #define USE_TRAPS 0 // direct link (Simulator)
+ #endif
+#endif
+
+
+/********************************************************************
+ * Palm OS System and Library trap macro definitions:
+ ********************************************************************/
+
+#define _DIRECT_CALL(table, vector)
+#define _DIRECT_CALL_WITH_SELECTOR(table, vector, selector)
+#define _DIRECT_CALL_WITH_16BIT_SELECTOR(table, vector, selector)
+
+#ifndef _STRUCTURE_PICTURES
+
+#define _SYSTEM_TABLE 15
+#define _HAL_TABLE 15
+
+#ifdef __GNUC__
+
+ #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+
+ #ifndef _Str
+ #define _Str(X) #X
+ #endif
+
+ #define _OS_CALL(table, vector) \
+ __attribute__ ((__callseq__ ( \
+ "trap #" _Str(table) "; dc.w " _Str(vector))))
+
+ #define _OS_CALL_WITH_SELECTOR(table, vector, selector) \
+ __attribute__ ((__callseq__ ( \
+ "moveq #" _Str(selector) ",%%d2; " \
+ "trap #" _Str(table) "; dc.w " _Str(vector))))
+
+ #define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector) \
+ __attribute__ ((__callseq__ ( \
+ "move.w #" _Str(selector) ",-(%%sp); " \
+ "trap #" _Str(table) "; dc.w " _Str(vector) "; " \
+ "addq.w #2,%%sp")))
+
+ #else
+
+ #define _OS_CALL(table, vector) __attribute__ ((systrap (vector)))
+ #define _OS_CALL_WITH_SELECTOR(table, vector, selector)
+ #define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector)
+
+ #endif
+
+#elif defined (__MWERKS__) /* The equivalent in CodeWarrior syntax */
+
+ #define _OS_CALL(table, vector) \
+ = { 0x4E40 + table, vector }
+
+ #define _OS_CALL_WITH_SELECTOR(table, vector, selector) \
+ = { 0x7400 + selector, 0x4E40 + table, vector }
+
+ #define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector) \
+ = { 0x3F3C, selector, 0x4E40 + table, vector, 0x544F }
+
+#endif
+
+#else
+
+#define _SYSTEM_TABLE "systrap"
+#define _HAL_TABLE "hal"
+
+#define _OS_CALL(table, vector) \
+ __SPIC__("simple", table, vector, 0)
+
+#define _OS_CALL_WITH_SELECTOR(table, vector, selector) \
+ __SPIC__("selector", table, vector, selector)
+
+#define _OS_CALL_WITH_16BIT_SELECTOR(table, vector, selector) \
+ __SPIC__("16bit_selector", table, vector, selector)
+
+#endif
+
+
+#if EMULATION_LEVEL != EMULATION_NONE
+
+#define _HAL_API(kind) _DIRECT##kind
+#define _SYSTEM_API(kind) _DIRECT##kind
+
+#elif USE_TRAPS == 0
+
+#define _HAL_API(kind) _OS##kind
+#define _SYSTEM_API(kind) _DIRECT##kind
+
+#else
+
+#define _HAL_API(kind) _OS##kind
+#define _SYSTEM_API(kind) _OS##kind
+
+#endif
+
+
+/************************************************************
+ * Palm specific TRAP instruction numbers
+ *************************************************************/
+#define sysDbgBreakpointTrapNum 0 // For soft breakpoints
+#define sysDbgTrapNum 8 // For compiled breakpoints
+#define sysDispatchTrapNum 15 // Trap dispatcher
+
+#ifndef PUBLIC_STUFF_STRIPPED
+/* DOLATER:jwm: @@@ move us to CoreTraps.h */
+#endif // PUBLIC_STUFF_STRIPPED
+
+#define SYS_TRAP(trapNum) _SYSTEM_API(_CALL)(_SYSTEM_TABLE, trapNum)
+
+#define ASM_SYS_TRAP(trapNum) \
+ DC.W m68kTrapInstr+sysDispatchTrapNum; \
+ DC.W trapNum
+
+
+#endif //__PALMTYPES_H__
diff --git a/SrcShared/PalmOptErrorCheckLevel.h b/SrcShared/PalmOptErrorCheckLevel.h
new file mode 100644
index 0000000..eb03796
--- /dev/null
+++ b/SrcShared/PalmOptErrorCheckLevel.h
@@ -0,0 +1,28 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef __PALMOPTERRORCHECKLEVEL_H__
+#define __PALMOPTERRORCHECKLEVEL_H__
+
+#include <BuildDefines.h>
+
+ #ifdef ERROR_CHECK_LEVEL_OK_TO_REDEFINE
+ #undef ERROR_CHECK_LEVEL_OK_TO_REDEFINE
+ #undef ERROR_CHECK_LEVEL
+ #endif
+
+ #ifndef ERROR_CHECK_LEVEL
+ #define ERROR_CHECK_LEVEL ERROR_CHECK_FULL
+ #endif
+
+#endif
diff --git a/SrcShared/PalmPack.h b/SrcShared/PalmPack.h
new file mode 100644
index 0000000..466f92a
--- /dev/null
+++ b/SrcShared/PalmPack.h
@@ -0,0 +1,25 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+
+#if defined (_MSC_VER)
+#pragma warning (disable: 4103) // used #pragma pack to change alignment
+#pragma pack (push, 2)
+#endif
+
+#if defined(__GNUC__)
+#pragma pack(2)
+#endif
diff --git a/SrcShared/PalmPackPop.h b/SrcShared/PalmPackPop.h
new file mode 100644
index 0000000..218899b
--- /dev/null
+++ b/SrcShared/PalmPackPop.h
@@ -0,0 +1,24 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#if defined(__GNUC__)
+#pragma pack()
+#endif
+
+#if defined (_MSC_VER)
+#pragma pack (pop)
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
diff --git a/SrcShared/Patches/EmPatchIf.h b/SrcShared/Patches/EmPatchIf.h
new file mode 100644
index 0000000..e6e1d41
--- /dev/null
+++ b/SrcShared/Patches/EmPatchIf.h
@@ -0,0 +1,150 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ 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.
+\* ===================================================================== */
+
+
+#ifndef EmPatchIf_h
+#define EmPatchIf_h
+
+#include "EcmIf.h"
+
+
+enum
+{
+ kPatchErrNone,
+ kPatchErrNotImplemented,
+ kPatchErrInvalidIndex
+};
+
+
+enum CallROMType
+{
+ kExecuteROM,
+ kSkipROM
+};
+
+
+// Function types for head- and Tailpatch functions.
+
+typedef CallROMType (*HeadpatchProc)(void);
+typedef void (*TailpatchProc)(void);
+
+
+// ==============================================================================
+// * BEGIN IEmPatchLoader
+// ==============================================================================
+
+const EcmIfName kEmPatchLoaderIfn = "loader.patchmodule.i.ecm";
+
+ecm_interface IEmPatchLoader : ecm_extends IEcmComponent
+{
+ virtual Err InitializePL (void) = 0;
+ virtual Err ResetPL (void) = 0;
+ virtual Err DisposePL (void) = 0;
+
+ virtual Err ClearPL (void) = 0;
+ virtual Err LoadPL (void) = 0;
+
+ virtual Err LoadAllModules (void) = 0;
+ virtual Err LoadModule (const string& url) = 0;
+};
+
+// ==============================================================================
+// * END IEmPatchLoader
+// ==============================================================================
+
+
+
+// ==============================================================================
+// * BEGIN IEmPatchContainer
+// ==============================================================================
+
+const EcmIfName kEmPatchContainerIfn = "container.patchmodule.i.ecm";
+
+ecm_interface IEmPatchContainer : ecm_extends IEcmContainer
+{
+};
+
+
+// ==============================================================================
+// * END IEmPatchContainer
+// ==============================================================================
+
+
+
+// ==============================================================================
+// * BEGIN IEmPatchDllTempHacks
+// ==============================================================================
+
+const EcmIfName kEmPatchDllTempHacksIfn = "hacks.dll.patchmodule.i.ecm";
+
+ecm_interface IEmPatchDllTempHacks : ecm_extends IEcmComponent
+{
+ virtual Err GetGlobalMemBanks(void** membanksPP)=0;
+ virtual Err GetGlobalRegs(void** regsPP)=0;
+};
+
+// ==============================================================================
+// * END IEmPatchDllTempHacks
+// ==============================================================================
+
+
+
+
+// ===========================================================================
+// IEmPatchModule interface exposed by all patch modules.
+// this is how all patch modules appear to the patching sub-system
+// ===========================================================================
+
+const EcmIfName kEmPatchModuleIfn = "patchmodule.i.ecm";
+
+ecm_interface IEmPatchModule : ecm_extends IEcmComponent
+{
+ virtual Err Initialize(IEmPatchContainer &containerIP) = 0;
+ virtual Err Reset() = 0;
+ virtual Err Dispose() = 0;
+
+ virtual Err Clear () = 0;
+ virtual Err Load () = 0;
+
+ virtual const string &GetName() = 0;
+
+ virtual Err GetHeadpatch (uint16 index, HeadpatchProc &procP) = 0;
+ virtual Err GetTailpatch (uint16 index, TailpatchProc &procP) = 0;
+};
+
+
+
+
+// ===========================================================================
+// IEmPatchModuleMap interface supporting a collection of PatchModules
+// Basically there is one component which maintains the list of all
+// installed patch modules, and it is accessed using IEmPatchModuleMap
+// ===========================================================================
+
+const EcmIfName kEmPatchModuleMapIfn = "map.patchmodule.i.ecm";
+
+ecm_interface IEmPatchModuleMap : ecm_extends IEcmComponent
+{
+ virtual Err InitializeAll(IEmPatchContainer &containerI) = 0;
+ virtual Err ResetAll() = 0;
+ virtual Err DisposeAll() = 0;
+
+ virtual Err ClearAll () = 0;
+ virtual Err LoadAll () = 0;
+
+ virtual Err AddModule (IEmPatchModule *moduleIP) = 0;
+
+ virtual Err GetModuleByName (const string &nameStr, IEmPatchModule *& moduleIP) = 0;
+};
+
+#endif // EmPatchIf_h
diff --git a/SrcShared/Patches/EmPatchLoader.cpp b/SrcShared/Patches/EmPatchLoader.cpp
new file mode 100644
index 0000000..01c6f2d
--- /dev/null
+++ b/SrcShared/Patches/EmPatchLoader.cpp
@@ -0,0 +1,129 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ 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 "EmPatchLoader.h"
+
+#include "EmPatchMgr.h"
+#include "EmPatchModule.h"
+#include "EmPatchModuleHtal.h"
+#include "EmPatchModuleMap.h"
+#include "EmPatchModuleNetLib.h"
+#include "EmPatchModuleSys.h"
+#include "EmPatchState.h"
+
+
+// ======================================================================
+// This is where you might say all the good stuff actually happens...
+//
+// we create the instances of all the relevant objects
+// we create the instances of all the statically linked patch modules
+// we add the statically linked patch modules to the PatchMap
+//
+// NOTE:
+// If USE_HOST_SPECIFIC_LOADER is defined no EmPatchLoader object is
+// created here, a derived object will be created for the Host specific
+// implementation.
+//
+// Either way the EmPatchLoader will be exposed globally through the
+// global public interface pointer "gTheLoaderIP"
+// ======================================================================
+
+
+// ======================================================================
+// Private Object instances
+// ======================================================================
+//
+static EmPatchMgr gPatchManager;
+static EmPatchModuleMap gPatchMap;
+
+#ifndef USE_HOST_SPECIFIC_LOADER
+static EmPatchLoader gLoader;
+#endif //USE_HOST_SPECIFIC_LOADER
+
+
+// ======================================================================
+// Static linked PatchModule instances
+// ======================================================================
+
+static EmPatchModuleHtal gPatchModuleHtal;
+static EmPatchModuleSys gPatchModuleSys;
+static EmPatchModuleNetLib gPatchModuleNetLib;
+
+
+// ======================================================================
+// Global Public interfaces
+// ======================================================================
+
+IEmPatchModuleMap* gPatchMapIP = &gPatchMap;
+IEmPatchContainer* gPatchContainerIP = &gPatchManager;
+
+#ifndef USE_HOST_SPECIFIC_LOADER
+
+IEmPatchLoader* gTheLoaderIP = &gLoader;
+
+#endif //USE_HOST_SPECIFIC_LOADER
+
+
+
+
+// ==============================================================================
+// * BEGIN IEmPatchLoader
+// ==============================================================================
+
+Err EmPatchLoader::InitializePL (void)
+{
+ return kPatchErrNone;
+}
+
+Err EmPatchLoader::ResetPL (void)
+{
+ return kPatchErrNone;
+}
+
+Err EmPatchLoader::DisposePL (void)
+{
+ return kPatchErrNone;
+}
+
+Err EmPatchLoader::ClearPL (void)
+{
+ return kPatchErrNone;
+}
+
+Err EmPatchLoader::LoadPL (void)
+{
+ return kPatchErrNone;
+}
+
+
+Err EmPatchLoader::LoadAllModules(void)
+{
+ gPatchMap.AddModule (&gPatchModuleSys);
+ gPatchMap.AddModule (&gPatchModuleNetLib);
+ gPatchMap.AddModule (&gPatchModuleHtal);
+
+ gPatchMap.InitializeAll (*gPatchContainerIP);
+
+ return kPatchErrNone;
+}
+
+
+Err EmPatchLoader::LoadModule (const string& /*url*/)
+{
+ return kPatchErrNotImplemented;
+}
+
+// ==============================================================================
+// * END IEmPatchLoader
+// ==============================================================================
diff --git a/SrcShared/Patches/EmPatchLoader.h b/SrcShared/Patches/EmPatchLoader.h
new file mode 100644
index 0000000..05a1ad8
--- /dev/null
+++ b/SrcShared/Patches/EmPatchLoader.h
@@ -0,0 +1,74 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ 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.
+\* ===================================================================== */
+
+
+#ifndef EmPatchLoader_h
+#define EmPatchLoader_h
+
+#include "EcmObject.h"
+#include "EmPatchIf.h"
+
+
+// ===========================================================================
+// EmPatchLoader
+// ===========================================================================
+
+class EmPatchLoader : public EcmObject,
+ ecm_implements IEmPatchLoader
+{
+ public:
+
+// ==============================================================================
+// * constructors
+// ==============================================================================
+
+ EmPatchLoader()
+ {
+ }
+
+
+// ==============================================================================
+// * interface implementations
+// ==============================================================================
+// ==============================================================================
+// * BEGIN IEmPatchLoader
+// ==============================================================================
+
+ virtual Err InitializePL();
+ virtual Err ResetPL();
+ virtual Err DisposePL();
+ virtual Err ClearPL();
+ virtual Err LoadPL();
+
+ virtual Err LoadAllModules();
+ virtual Err LoadModule(const string &url);
+
+// ==============================================================================
+// * END IEmPatchLoader
+// ==============================================================================
+
+
+// ==============================================================================
+// * BEGIN IEmPatchContainer
+// ==============================================================================
+
+
+// ==============================================================================
+// * END IEmPatchContainer
+// ==============================================================================
+
+ private:
+};
+
+
+#endif // EmPatchLoader_h
diff --git a/SrcShared/Patches/EmPatchMgr.cpp b/SrcShared/Patches/EmPatchMgr.cpp
new file mode 100644
index 0000000..4a8f844
--- /dev/null
+++ b/SrcShared/Patches/EmPatchMgr.cpp
@@ -0,0 +1,1203 @@
+/* -*- 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 "EmPatchMgr.h"
+
+#include "EmPatchModule.h"
+#include "EmPatchModuleMap.h"
+#include "EmPatchState.h"
+#include "EmPatchLoader.h"
+
+#include "CGremlinsStubs.h" // StubAppEnqueueKey
+#include "DebugMgr.h" // Debug::ConnectedToTCPDebugger
+#include "EmEventPlayback.h" // EmEventPlayback::ReplayingEvents
+#include "EmHAL.h" // EmHAL::GetLineDriverState
+#include "EmLowMem.h" // EmLowMem::GetEvtMgrIdle, EmLowMem::TrapExists, EmLowMem_SetGlobal, EmLowMem_GetGlobal
+#include "EmPalmFunction.h" // IsSystemTrap
+#include "EmRPC.h" // RPC::SignalWaiters
+#include "EmSession.h" // GetDevice
+#include "Hordes.h" // Hordes::IsOn, Hordes::PostFakeEvent, Hordes::CanSwitchToApp
+#include "Logging.h" // LogEvtAddEventToQueue, etc.
+#include "MetaMemory.h" // MetaMemory mark functions
+#include "PreferenceMgr.h" // Preference (kPrefKeyUserName)
+#include "Profiling.h" // StDisableAllProfiling
+#include "ROMStubs.h" // FtrSet, FtrUnregister, EvtWakeup, ...
+#include "SessionFile.h" // SessionFile
+#include "UAE.h" // gRegs, m68k_dreg, etc.
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ EmPatchMgr
+// ===========================================================================
+
+// ======================================================================
+// Global Interfaces
+// ======================================================================
+
+
+//Interface to THE collection of all patch modules:
+
+extern IEmPatchModuleMap* gPatchMapIP;
+extern IEmPatchLoader* gTheLoaderIP;
+
+
+// ======================================================================
+// Private globals and constants
+// ======================================================================
+
+//Table of currently Patched shared libraries
+//
+static PatchedLibIndex gPatchedLibs;
+
+//Table of currently installed tail patches
+//
+static TailPatchIndex gInstalledTailpatches;
+
+
+// Magic number used to identify Htal patch
+// See comments in HtalLibSendReply.
+//
+const UInt16 kMagicRefNum = 0x666;
+
+
+
+// ======================================================================
+// Private functions
+// ======================================================================
+
+void PrvAutoload (void);
+void PrvSetCurrentDate (void);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::Initialize (void)
+{
+ EmAssert (gSession);
+
+ gTheLoaderIP->InitializePL ();
+ gTheLoaderIP->LoadAllModules ();
+
+ gSession->AddInstructionBreakHandlers (
+ InstallInstructionBreaks,
+ RemoveInstructionBreaks,
+ HandleInstructionBreak);
+
+ if (gPatchMapIP != NULL)
+ {
+ gPatchMapIP->ClearAll ();
+ gPatchMapIP->LoadAll ();
+ }
+
+ EmPatchState::Initialize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::Reset (void)
+{
+ gInstalledTailpatches.clear ();
+
+ // Clear the installed lib patches (for "loaded" libraries)
+ //
+ gPatchedLibs.clear ();
+
+ EmPatchState::Reset ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::Save (SessionFile& f)
+{
+ const long kCurrentVersion = 5;
+
+ Chunk chunk;
+ EmStreamChunk s (chunk);
+
+ s << kCurrentVersion;
+
+ EmPatchState::Save (s, kCurrentVersion, EmPatchState::PSPersistStep1);
+
+// s << gSysPatchModule;
+// s << gNetLibPatchModule;
+// s << gPatchedLibs;
+
+ s << (long) gInstalledTailpatches.size ();
+
+ TailPatchIndex::iterator iter2;
+ for (iter2 = gInstalledTailpatches.begin (); iter2 != gInstalledTailpatches.end (); ++iter2)
+ {
+ s << iter2->fContext.fDestPC1; // !!! Need to support fDestPC2, too. But since only fNextPC seems to be used, it doesn't really matter.
+ s << iter2->fContext.fExtra;
+ s << iter2->fContext.fNextPC;
+ s << iter2->fContext.fPC;
+ s << iter2->fContext.fTrapIndex;
+ s << iter2->fContext.fTrapWord;
+ s << iter2->fCount;
+// s << iter2->fTailpatch; // Patched up in ::Load
+ }
+
+ EmPatchState::Save (s, kCurrentVersion, EmPatchState::PSPersistStep2);
+
+ f.WritePatchInfo (chunk);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::Load (SessionFile& f)
+{
+ Chunk chunk;
+ if (f.ReadPatchInfo (chunk))
+ {
+ long version;
+ EmStreamChunk s (chunk);
+
+ s >> version;
+
+ if (version >= 1)
+ {
+ EmPatchState::Load (s, version, EmPatchState::PSPersistStep1);
+
+ gPatchedLibs.clear ();
+ gInstalledTailpatches.clear ();
+
+
+ long numTailpatches;
+ s >> numTailpatches;
+
+ int ii;
+ for (ii = 0; ii < numTailpatches; ++ii)
+ {
+ TailpatchType patch;
+
+ s >> patch.fContext.fDestPC1; // !!! Need to support fDestPC2, too. But since only fNextPC seems to be used, it doesn't really matter.
+ patch.fContext.fDestPC2 = patch.fContext.fDestPC1;
+ s >> patch.fContext.fExtra;
+ s >> patch.fContext.fNextPC;
+ s >> patch.fContext.fPC;
+ s >> patch.fContext.fTrapIndex;
+ s >> patch.fContext.fTrapWord;
+ s >> patch.fCount;
+
+ // Patch up the tailpatch proc.
+
+ HeadpatchProc dummy;
+ GetPatches (patch.fContext, dummy, patch.fTailpatch);
+
+ gInstalledTailpatches.push_back (patch);
+ }
+ }
+
+ EmPatchState::Load (s, version, EmPatchState::PSPersistStep2);
+ }
+ else
+ {
+ f.SetCanReload (false);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::Dispose (void)
+{
+ gInstalledTailpatches.clear ();
+ gPatchedLibs.clear ();
+
+ EmPatchState::Dispose ();
+
+ if (gPatchMapIP != NULL)
+ {
+ gPatchMapIP->ClearAll ();
+ }
+
+ if (gTheLoaderIP)
+ {
+ gTheLoaderIP->ClearPL ();
+ }
+}
+
+
+Err EmPatchMgr::GetGlobalMemBanks (void** membanksPP)
+{
+ if (membanksPP != NULL)
+ *membanksPP = gEmMemBanks;
+
+ return 0;
+}
+
+Err EmPatchMgr::GetGlobalRegs (void** regsPP)
+{
+ if (regsPP != NULL)
+ *regsPP = &gRegs;
+
+ return 0;
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::PostLoad
+ *
+ * DESCRIPTION: Do some stuff that is normally taken care of during the
+ * process of resetting the device (autoloading
+ * applications, setting the device date, installing the
+ * HotSync user-name, and setting the 'gdbS' feature).
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::PostLoad (void)
+{
+ if (EmPatchState::UIInitialized ())
+ {
+ // 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);
+ }
+ else
+ {
+ FtrUnregister ('gdbS', 0);
+ }
+
+ // 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);
+
+ // Install the HotSync user-name.
+
+ // Actually, let's not do that. From Scott Maxwell:
+ //
+ // Would it be possible to save the HotSync user name with each session? This
+ // would be very convenient for working on multiple projects because each
+ // session could have a different user name.
+ //
+ // To which I said:
+ // I think that what you're seeing is Poser (re-)establishing the user preference
+ // from the Properties/Preferences dialog box after the session is reloaded. I
+ // could see this way of working as being valuable, too, so I'm not sure which way
+ // to go: keep things the way they are or change them.
+ //
+ // To which he said:
+ //
+ // How about having the preferences dialog grab the name from the Palm RAM?
+ // That way you could easily maintain it per session.
+ //
+ // Sounds good to me...
+
+// Preference<string> userNamePref (kPrefKeyUserName);
+// ::SetHotSyncUserName (userNamePref->c_str ());
+
+ CEnableFullAccess munge;
+
+ if (EmLowMem::TrapExists (sysTrapDlkGetSyncInfo))
+ {
+ char userName[dlkUserNameBufSize];
+ Err err = ::DlkGetSyncInfo (NULL, NULL, NULL, userName, NULL, NULL);
+ if (!err)
+ {
+ Preference<string> userNamePref (kPrefKeyUserName);
+ userNamePref = string (userName);
+ }
+ }
+
+ // Auto-load any files in the Autoload[Foo] directories.
+
+ ::PrvAutoload ();
+
+ // Install the current date.
+
+ ::PrvSetCurrentDate ();
+
+ // Wake up any current application so that they can respond
+ // to events we pump in at EvtGetEvent time.
+
+ ::EvtWakeup ();
+ }
+
+ // Re-open any needed transports. This could probably be done
+ // at the time the session file is loaded, but we put it here
+ // with the rest of the (deferred) post-load activities for
+ // consistancy.
+
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ if (EmHAL::GetLineDriverState (ii))
+ {
+ EmTransport* transport = gEmuPrefs->GetTransportForDevice (ii);
+
+ if (transport)
+ {
+ transport->Open ();
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::GetLibPatchTable
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+IEmPatchModule* EmPatchMgr::GetLibPatchTable (uint16 refNum)
+{
+ if (refNum >= gPatchedLibs.size ())
+ {
+ gPatchedLibs.resize (refNum + 1);
+ }
+
+ InstalledLibPatchEntry &libPtchEntry = gPatchedLibs[refNum];
+
+ if (libPtchEntry.IsDirty () == true)
+ {
+ string libName = ::GetLibraryName (refNum);
+
+ IEmPatchModule *patchModuleIP = NULL;
+
+ if (gPatchMapIP != NULL)
+ {
+ gPatchMapIP->GetModuleByName (libName, patchModuleIP);
+ }
+
+
+ libPtchEntry.SetPatchTableP (patchModuleIP);
+ libPtchEntry.SetDirty (false);
+ }
+
+ return libPtchEntry.GetPatchTableP ();
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::HandleSystemCall
+ *
+ * DESCRIPTION: If this is a trap we could possibly have head- or
+ * tail-patched, handle those cases.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType EmPatchMgr::HandleSystemCall (const SystemCallContext& context)
+{
+ EmAssert (gSession);
+ if (gSession->GetNeedPostLoad ())
+ {
+ gSession->SetNeedPostLoad (false);
+ EmPatchMgr::PostLoad ();
+ }
+
+ HeadpatchProc hp;
+ TailpatchProc tp;
+ EmPatchMgr::GetPatches (context, hp, tp);
+
+ CallROMType handled = EmPatchMgr::HandlePatches (context, hp, tp);
+
+ return handled;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::GetPatches
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::GetPatches ( const SystemCallContext& context,
+ HeadpatchProc& hp,
+ TailpatchProc& tp)
+{
+ IEmPatchModule* patchModuleIP = NULL;
+
+ // If this is in the system function range, check our table of
+ // system function patches.
+
+ if (::IsSystemTrap (context.fTrapWord))
+ {
+ static IEmPatchModule *sysPatchModuleIP = NULL;
+
+ if (sysPatchModuleIP == NULL && gPatchMapIP != NULL)
+ {
+ gPatchMapIP->GetModuleByName (string ("~system"), sysPatchModuleIP);
+ }
+
+ patchModuleIP = sysPatchModuleIP;
+ }
+
+ else if (context.fExtra == kMagicRefNum) // See comments in HtalLibSendReply.
+ {
+ static IEmPatchModule *htalPatchModuleIP = NULL;
+
+ if (htalPatchModuleIP == NULL && gPatchMapIP != NULL)
+ {
+ gPatchMapIP->GetModuleByName (string ("~Htal"), htalPatchModuleIP);
+ }
+
+ patchModuleIP = htalPatchModuleIP;
+ }
+
+ // Otherwise, see if this is a call to a patched library
+ else
+ {
+ patchModuleIP = GetLibPatchTable (context.fExtra);
+ }
+
+ // Now that we've got the right patch table for this module, see if
+ // that patch table has head- or tailpatches for this function.
+
+ if (patchModuleIP != NULL)
+ {
+ patchModuleIP->GetHeadpatch (context.fTrapIndex, hp);
+ patchModuleIP->GetTailpatch (context.fTrapIndex, tp);
+ }
+ else
+ {
+ hp = NULL;
+ tp = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::HandlePatches
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType EmPatchMgr::HandlePatches (const SystemCallContext& context,
+ HeadpatchProc hp,
+ TailpatchProc tp)
+{
+ CallROMType handled = kExecuteROM;
+
+ // First, see if we have a SysHeadpatch for this function. If so, call
+ // it. If it returns true, then that means that the head patch
+ // completely handled the function.
+
+ // !!! May have to mess with PC here in case patches do something
+ // to enter the debugger.
+
+ if (hp)
+ {
+ handled = CallHeadpatch (hp);
+ }
+
+ // Next, see if there's a SysTailpatch function for this trap. If
+ // so, install the TRAP that will cause us to regain control
+ // after the trap function has executed.
+
+ if (tp)
+ {
+ if (handled == kExecuteROM)
+ {
+ SetupForTailpatch (tp, context);
+ }
+ else
+ {
+ CallTailpatch (tp);
+ }
+ }
+
+ return handled;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::HandleInstructionBreak
+ *
+ * DESCRIPTION: Handle a tail patch, if any is registered for this
+ * memory location.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::HandleInstructionBreak (void)
+{
+ // Get the address of the tailpatch to call. May return NULL if
+ // there is no tailpatch for this memory location.
+
+ TailpatchProc tp = RecoverFromTailpatch (gCPU->GetPC ());
+
+ // Call the tailpatch handler for the trap that just returned.
+
+ CallTailpatch (tp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::InstallInstructionBreaks
+ *
+ * DESCRIPTION: Set the MetaMemory bit that tells the CPU loop to stop
+ * when we get to the desired locations.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::InstallInstructionBreaks (void)
+{
+ TailPatchIndex::iterator iter = gInstalledTailpatches.begin ();
+
+ while (iter != gInstalledTailpatches.end ())
+ {
+ MetaMemory::MarkInstructionBreak (iter->fContext.fNextPC);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::RemoveInstructionBreaks
+ *
+ * DESCRIPTION: Clear the MetaMemory bit that tells the CPU loop to stop
+ * when we get to the desired locations.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::RemoveInstructionBreaks (void)
+{
+ TailPatchIndex::iterator iter = gInstalledTailpatches.begin ();
+
+ while (iter != gInstalledTailpatches.end ())
+ {
+ MetaMemory::UnmarkInstructionBreak (iter->fContext.fNextPC);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::SetupForTailpatch
+ *
+ * DESCRIPTION: Set up the pending TRAP $F call to be tailpatched.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::SetupForTailpatch (TailpatchProc tp, const SystemCallContext& context)
+{
+ // See if this function is already tailpatched. If so, merely increment
+ // the use-count field.
+
+ TailPatchIndex::iterator iter = gInstalledTailpatches.begin ();
+
+ while (iter != gInstalledTailpatches.end ())
+ {
+ if (iter->fContext.fNextPC == context.fNextPC)
+ {
+ ++(iter->fCount);
+ return;
+ }
+
+ ++iter;
+ }
+
+ // This function is not already tailpatched, so add a new entry
+ // for the the PC/opcode we want to save.
+
+ EmAssert (gSession);
+ gSession->RemoveInstructionBreaks ();
+
+ TailpatchType newTailpatch;
+
+ newTailpatch.fContext = context;
+ newTailpatch.fCount = 1;
+ newTailpatch.fTailpatch = tp;
+
+ gInstalledTailpatches.push_back (newTailpatch);
+
+ gSession->InstallInstructionBreaks ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::RecoverFromTailpatch
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+TailpatchProc EmPatchMgr::RecoverFromTailpatch (emuptr startPC)
+{
+ // Get the current PC so that we can find the record for this tailpatch.
+
+ emuptr patchPC = startPC;
+
+ // Find the PC.
+
+ TailPatchIndex::iterator iter = gInstalledTailpatches.begin ();
+
+ while (iter != gInstalledTailpatches.end ())
+ {
+ if (iter->fContext.fNextPC == patchPC)
+ {
+ TailpatchProc result = iter->fTailpatch;
+
+ // Decrement the use-count. If it reaches zero, remove the
+ // patch from our list.
+
+ if (--(iter->fCount) == 0)
+ {
+ EmAssert (gSession);
+ gSession->RemoveInstructionBreaks ();
+
+ gInstalledTailpatches.erase (iter);
+
+ gSession->InstallInstructionBreaks ();
+ }
+
+ return result;
+ }
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::CallHeadpatch
+ *
+ * DESCRIPTION: If the given system function is head patched, then call
+ * the headpatch. Return "handled" (which means whether
+ * or not to call the ROM function after this one).
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType EmPatchMgr::CallHeadpatch (HeadpatchProc hp, bool /* noProfiling */)
+{
+ CallROMType handled = kExecuteROM;
+
+ if (hp)
+ {
+ // If (noProfiling == true) then stop all profiling activities.
+ // Stop cycle counting and stop the recording of function entries
+ // and exits. We want our trap patches to be as transparent as possible.
+
+ StDisableAllProfiling stopper (/*noProfiling*/);
+
+ handled = hp ();
+ }
+
+ return handled;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::CallTailpatch
+ *
+ * DESCRIPTION: If the given function is tail patched, then call the
+ * tailpatch.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchMgr::CallTailpatch (TailpatchProc tp, bool /* noProfiling */)
+{
+ if (tp)
+ {
+ // Stop all profiling activities. Stop cycle counting and stop the
+ // recording of function entries and exits. We want our trap patches
+ // to be as transparent as possible.
+
+ StDisableAllProfiling stopper (/*noProfiling*/);
+
+ tp ();
+ }
+}
+
+
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::PuppetString
+ *
+ * DESCRIPTION: Puppet stringing function for inserting events into
+ * the system. We want to insert events when:
+ *
+ * - Gremlins is running
+ * - The user types characters
+ * - The user clicks with the mouse
+ * - We need to trigger a switch another application
+ *
+ * This function is called from headpatches to
+ * SysEvGroupWait and SysSemaphoreWait. When the Palm OS
+ * needs an event, it calls EvtGetEvent. EvtGetEvent
+ * looks in all the usual places for events to return. If
+ * it doesn't find any, it puts the system to sleep by
+ * calling SysEvGroupWait (or SysSemaphoreWait on 1.0
+ * systems). SysEvGroupWait will wake up and return when
+ * an event is posted via something like EvtEnqueuePenPoint,
+ * EvtEnqueueKey, or KeyHandleInterrupt.
+ *
+ * To puppet-string Palm OS, we therefore patch those
+ * functions and post events, preventing them from actually
+ * going to sleep.
+ *
+ * PARAMETERS: callROM - return here whether or not the original ROM
+ * function still needs to be called. Normally, the
+ * answer is "yes".
+ *
+ * clearTimeout - set to true if the "timeout" parameter
+ * of the function we've patched needs to be prevented
+ * from being "infinite".
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+static void PrvForceNilEvent (void)
+{
+ // No event was posted. What we'd like right now is to force
+ // EvtGetEvent to return a nil event. We can do that by returning
+ // a non-zero result code from SysEvGroupWait. EvtGetEvent doesn't
+ // look too closely at the result, but let's try to be as close to
+ // reality as possible. SysEvGroupWait currently returns "4"
+ // (CJ_WRTMOUT) to indicate a timeout condition. It should
+ // probably get turned into sysErrTimeout somewhere along the way,
+ // but that translation doesn't seem to occur.
+
+ m68k_dreg (gRegs, 0) = 4;
+}
+
+void EmPatchMgr::PuppetString (CallROMType& callROM, Bool& clearTimeout)
+{
+ callROM = kExecuteROM;
+ clearTimeout = false;
+
+ // Set the return value (Err) to zero in case we return
+ // "true" (saying that we handled the trap).
+
+ m68k_dreg (gRegs, 0) = 0;
+
+ // If the low-memory global "idle" is true, then we're being
+ // called from EvtGetEvent or EvtGetPen, in which case we
+ // need to check if we need to post some events.
+
+ if (EmLowMem::GetEvtMgrIdle ())
+ {
+ // If there's an RPC request waiting for a nilEvent,
+ // let it know that it happened.
+
+ if (EmPatchState::GetLastEvtTrap () == sysTrapEvtGetEvent)
+ {
+ RPC::SignalWaiters (hostSignalIdle);
+ }
+
+ // If we're in the middle of calling a Palm OS function ourself,
+ // and we are somehow at the point where the system is about to
+ // doze, then just return now. Don't let it doze! Interrupts are
+ // off, and HwrDoze will never return!
+
+ if (gSession->IsNested ())
+ {
+ ::PrvForceNilEvent ();
+ callROM = kSkipROM;
+ return;
+ }
+
+ EmAssert (gSession);
+
+ // Check if Minimization is going on.
+
+ if (EmEventPlayback::ReplayingEvents ())
+ {
+ if (EmPatchState::GetLastEvtTrap () == sysTrapEvtGetEvent)
+ {
+ if (!EmEventPlayback::ReplayGetEvent ())
+ {
+ ::PrvForceNilEvent ();
+ callROM = kSkipROM;
+ return;
+ }
+ }
+ else if (EmPatchState::GetLastEvtTrap () == sysTrapEvtGetPen)
+ {
+ EmEventPlayback::ReplayGetPen ();
+ }
+
+ // Never let the timeout be infinite. If the above event-posting
+ // attempts failed (which could happen, for instance, if we attempted
+ // to post a pen event with the same coordinates as the previous
+ // pen event), we'd end up waiting forever.
+
+ clearTimeout = true;
+ }
+
+ // Check if Hords is going on.
+
+ else if (Hordes::IsOn ())
+ {
+ if (EmPatchState::GetLastEvtTrap () == sysTrapEvtGetEvent)
+ {
+ if (!Hordes::PostFakeEvent ())
+ {
+ if (LogEnqueuedEvents ())
+ {
+ LogAppendMsg ("Hordes::PostFakeEvent did not post an event.");
+ }
+
+ ::PrvForceNilEvent ();
+ callROM = kSkipROM;
+ return;
+ }
+ }
+ else if (EmPatchState::GetLastEvtTrap () == sysTrapEvtGetPen)
+ {
+ Hordes::PostFakePenEvent ();
+ }
+ else
+ {
+ if (LogEnqueuedEvents ())
+ {
+ LogAppendMsg ("Last event was 0x%04X, so not posting event.", EmPatchState::GetLastEvtTrap ());
+ }
+ }
+
+ // Never let the timeout be infinite. If the above event-posting
+ // attempts failed (which could happen, for instance, if we attempted
+ // to post a pen event with the same coordinates as the previous
+ // pen event), we'd end up waiting forever.
+
+ clearTimeout = true;
+ }
+
+ // Gremlins aren't on; let's see if the user has typed some
+ // keys that we need to pass on to the Palm device.
+
+ else if (gSession->HasKeyEvent ())
+ {
+ EmKeyEvent event = gSession->GetKeyEvent ();
+
+ UInt16 modifiers = 0;
+
+ if (event.fShiftDown)
+ modifiers |= shiftKeyMask;
+
+ if (event.fCapsLockDown)
+ modifiers |= capsLockMask;
+
+ if (event.fNumLockDown)
+ modifiers |= numLockMask;
+
+ // We don't really want to set this one. commandKeyMask
+ // means something special in Palm OS
+// if (event.fCommandDown)
+// modifiers |= commandKeyMask;
+
+ if (event.fOptionDown)
+ modifiers |= optionKeyMask;
+
+ if (event.fControlDown)
+ modifiers |= controlKeyMask;
+
+ if (event.fAltDown)
+ modifiers |= 0; // no bit defined for this
+
+ if (event.fWindowsDown)
+ modifiers |= 0; // no bit defined for this
+
+ ::StubAppEnqueueKey (event.fKey, 0, modifiers);
+ }
+
+ // No key events, let's see if there are pen events.
+
+ else if (gSession->HasPenEvent ())
+ {
+ EmPoint pen (-1, -1);
+ EmPenEvent event = gSession->GetPenEvent ();
+ if (event.fPenIsDown)
+ {
+ pen = event.fPenPoint;
+ }
+
+ PointType palmPen = pen;
+ StubAppEnqueuePt (&palmPen);
+ }
+
+ // E. None of the above. Let's see if there's an app
+ // we're itching to switch to.
+
+ else if (EmPatchState::GetNextAppDbID () != 0)
+ {
+ /*Err err =*/ SwitchToApp (EmPatchState::GetNextAppCardNo (), EmPatchState::GetNextAppDbID ());
+
+ EmPatchState::SetNextAppCardNo (0);
+ EmPatchState::SetNextAppDbID (0);
+
+ clearTimeout = true;
+ }
+ }
+ else
+ {
+ if (Hordes::IsOn () && LogEnqueuedEvents ())
+ {
+ LogAppendMsg ("Event Manager not idle, so not posting an event.");
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::IntlMgrAvailable
+ *
+ * DESCRIPTION: Indicates whether the international manager is available.
+ *
+ * PARAMETERS:
+ *
+ * RETURNED: True if it is (OS > 4.0), false otherwise.
+ *
+ ***********************************************************************/
+
+Bool EmPatchMgr::IntlMgrAvailable (void)
+{
+ UInt32 romVersionData;
+ FtrGet (sysFileCSystem, sysFtrNumROMVersion, &romVersionData);
+ UInt32 romVersionMajor = sysGetROMVerMajor (romVersionData);
+
+ return (romVersionMajor >= 4);
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchMgr::SwitchToApp
+ *
+ * DESCRIPTION: Switches to the given application or launchable document.
+ *
+ * PARAMETERS: cardNo - the card number of the app to switch to.
+ *
+ * dbID - the database id of the app to switch to.
+ *
+ * RETURNED: Err number of any errors that occur
+ *
+ ***********************************************************************/
+
+Err EmPatchMgr::SwitchToApp (UInt16 cardNo, LocalID dbID)
+{
+ UInt16 dbAttrs;
+ UInt32 type, creator;
+
+ Err err = ::DmDatabaseInfo (
+ cardNo,
+ dbID,
+ NULL, /*name*/
+ &dbAttrs,
+ NULL, /*version*/
+ NULL, /*create date*/
+ NULL, /*modDate*/
+ NULL, /*backup date*/
+ NULL, /*modNum*/
+ NULL, /*appInfoID*/
+ NULL, /*sortInfoID*/
+ &type,
+ &creator);
+
+ if (err)
+ return err;
+
+ //---------------------------------------------------------------------
+ // If this is an executable, call SysUIAppSwitch
+ //---------------------------------------------------------------------
+ if (::IsExecutable (type, creator, dbAttrs))
+ {
+ err = ::SysUIAppSwitch (cardNo, dbID,
+ sysAppLaunchCmdNormalLaunch, NULL);
+
+ if (err)
+ return err;
+ }
+
+ //---------------------------------------------------------------------
+ // else, this must be a launchable data database. Find it's owner app
+ // and launch it with a pointer to the data database name.
+ //---------------------------------------------------------------------
+ else
+ {
+ DmSearchStateType searchState;
+ UInt16 appCardNo;
+ LocalID appDbID;
+
+ err = ::DmGetNextDatabaseByTypeCreator (true, &searchState,
+ sysFileTApplication, creator,
+ true, &appCardNo, &appDbID);
+ if (err)
+ return err;
+
+ // Create the param block
+
+ emuptr cmdPBP = (emuptr) ::MemPtrNew (sizeof (SysAppLaunchCmdOpenDBType));
+ if (cmdPBP == EmMemNULL)
+ return memErrNotEnoughSpace;
+
+ // Fill it in
+
+ ::MemPtrSetOwner ((MemPtr) cmdPBP, 0);
+ EmMemPut16 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, cardNo), cardNo);
+ EmMemPut32 (cmdPBP + offsetof (SysAppLaunchCmdOpenDBType, dbID), dbID);
+
+ // Switch now
+
+ err = ::SysUIAppSwitch (appCardNo, appDbID, sysAppLaunchCmdOpenDB, (MemPtr) cmdPBP);
+ if (err)
+ return err;
+ }
+
+ return errNone;
+}
diff --git a/SrcShared/Patches/EmPatchMgr.h b/SrcShared/Patches/EmPatchMgr.h
new file mode 100644
index 0000000..d2d0155
--- /dev/null
+++ b/SrcShared/Patches/EmPatchMgr.h
@@ -0,0 +1,103 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchMgr_h
+#define EmPatchMgr_h
+
+#include "EcmObject.h"
+#include "EmPatchIf.h"
+#include "PreferenceMgr.h" // PrefKeyType
+
+#include <vector>
+
+class SessionFile;
+struct SystemCallContext;
+
+struct IEmPatchModule;
+
+
+class EmPatchMgr : public EcmObject,
+ ecm_implements IEmPatchContainer,
+ ecm_implements IEmPatchDllTempHacks
+{
+ public:
+
+ ECM_CLASS_IF_LIST_BEGIN(EmPatchMgr, EcmObject)
+ ECM_CLASS_IF(kEmPatchContainerIfn, IEmPatchContainer)
+ ECM_CLASS_IF(kEmPatchDllTempHacksIfn, IEmPatchDllTempHacks)
+ ECM_CLASS_IF_LIST_END(EmPatchMgr, EcmObject)
+
+
+
+// ==============================================================================
+// * BEGIN IEmPatchContainer
+// ==============================================================================
+
+// ==============================================================================
+// * END IEmPatchContainer
+// ==============================================================================
+
+// ==============================================================================
+// * BEGIN IEmPatchDllTempHacks
+// ==============================================================================
+
+ virtual Err GetGlobalMemBanks(void** membanksPP);
+ virtual Err GetGlobalRegs(void** regsPP);
+
+// ==============================================================================
+// * END IEmPatchDllTempHacks
+// ==============================================================================
+
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void PostLoad (void);
+
+ static CallROMType HandleSystemCall (const SystemCallContext&);
+
+ static void HandleInstructionBreak (void);
+ static void InstallInstructionBreaks(void);
+ static void RemoveInstructionBreaks (void);
+
+ static void GetPatches (const SystemCallContext&,
+ HeadpatchProc& hp,
+ TailpatchProc& tp);
+
+ static CallROMType HandlePatches (const SystemCallContext&,
+ HeadpatchProc hp,
+ TailpatchProc tp);
+
+ static IEmPatchModule* GetLibPatchTable (uint16 refNum);
+
+ static CallROMType CallHeadpatch (HeadpatchProc, bool noProfiling = true);
+ static void CallTailpatch (TailpatchProc, bool noProfiling = true);
+
+ static Err SwitchToApp (UInt16 cardNo, LocalID dbID);
+
+ static void PuppetString (CallROMType& callROM,
+ Bool& clearTimeout);
+
+ static Bool IntlMgrAvailable (void);
+
+ private:
+ static void SetupForTailpatch (TailpatchProc tp,
+ const SystemCallContext&);
+ static TailpatchProc RecoverFromTailpatch (emuptr oldpc);
+};
+
+#endif /* EmPatchMgr_h */
+
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
+// ==============================================================================
diff --git a/SrcShared/Patches/EmPatchModule.h b/SrcShared/Patches/EmPatchModule.h
new file mode 100644
index 0000000..c867489
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModule.h
@@ -0,0 +1,118 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModule_h
+#define EmPatchModule_h
+
+#include "EcmObject.h"
+#include "EmPatchModuleTypes.h"
+#include "ChunkFile.h"
+#include "Miscellaneous.h"
+#include "SystemMgr.h"
+
+#include <string>
+#include <map>
+
+
+
+// ===========================================================================
+// EmPatchModule
+// ===========================================================================
+
+
+const uint16 kMaxProtoTables = 5;
+
+class EmPatchModule : public EcmObject,
+ ecm_implements IEmPatchModule
+{
+ private:
+// ==============================================================================
+// * illegal constructors
+// ==============================================================================
+ //don't let EmPatchModule be created using default constructor... must have a unique name.
+ //
+ EmPatchModule(){}
+
+ public:
+
+// ==============================================================================
+// * constructors
+// ==============================================================================
+
+ EmPatchModule(const char *nameCSP, ProtoPatchTableEntry *protoTable1P = NULL, ProtoPatchTableEntry *protoTable2P = NULL);
+ virtual ~EmPatchModule (void) {};
+
+// ==============================================================================
+// * interface implementations
+// ==============================================================================
+// ==============================================================================
+// * BEGIN IEmPatchModule
+// ==============================================================================
+
+ virtual Err Initialize(IEmPatchContainer &containerIP);
+
+ virtual Err Reset();
+
+ virtual Err Dispose();
+
+ virtual Err Clear ();
+
+ virtual Err Load();
+
+ virtual const string &GetName();
+
+ virtual Err GetHeadpatch (uint16 index, HeadpatchProc& procP);
+ virtual Err GetTailpatch (uint16 index, TailpatchProc& procP);
+
+// ==============================================================================
+// * END IEmPatchModule
+// ==============================================================================
+
+
+ void AddProtoPatchTable (ProtoPatchTableEntry protoPatchTable[], bool loadTable = false)
+ {
+ fProtoTables[fProtoTableCount++] = protoPatchTable;
+
+ if (loadTable)
+ Load();
+ }
+
+
+ void PrvLoadProtoPatchTable (uint16 index);
+
+ bool operator == (const char *nameCSP) const
+ {
+ return (fName == nameCSP);
+ }
+
+ bool operator == (const string &nameStr) const
+ {
+ return (fName == nameStr);
+ }
+
+ private:
+ string fName;
+
+ vector<HeadpatchProc> fHeadpatches;
+ vector<TailpatchProc> fTailpatches;
+
+ uint16 fProtoTableCount;
+ uint16 fLoadedTableCount;
+
+ IEmPatchContainer* fContainerIP;
+
+ ProtoPatchTableEntry* fProtoTables[kMaxProtoTables];
+};
+
+#endif // EmPatchModule_h
diff --git a/SrcShared/Patches/EmPatchModuleHtal.cpp b/SrcShared/Patches/EmPatchModuleHtal.cpp
new file mode 100644
index 0000000..f22c760
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleHtal.cpp
@@ -0,0 +1,89 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ Copyright (c) 2001 PocketPyro, Inc.
+ All rights reserved.
+
+ Portions Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+
+ 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 "EmPatchModuleHtal.h"
+
+#include "EmSubroutine.h"
+#include "Marshal.h"
+
+
+class HtalLibHeadpatch
+{
+ public:
+ static CallROMType HtalLibSendReply (void);
+};
+
+
+EmPatchModuleHtal::EmPatchModuleHtal (void) :
+ EmPatchModule ("~Htal")
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleHtal::GetHeadpatch
+ *
+ * DESCRIPTION: Special overide of GetHeadpatch to return the same function for any
+ * index.
+ *
+ * PARAMETERS: index trap index to locate patch for
+ * procP patch procedure returned.
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+
+Err EmPatchModuleHtal::GetHeadpatch (uint16 /* index */, HeadpatchProc& procP)
+{
+ procP = HtalLibHeadpatch::HtalLibSendReply;
+
+ return kPatchErrNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HtalLibHeadpatch::HtalLibSendReply
+ *
+ * DESCRIPTION: Ohhh...I'm going to Programmer Hell for this one...
+ * We call DlkDispatchRequest to install the user name in
+ * our UIInitialize patch. DlkDispatchRequest will
+ * eventually call HtalLibSendReply to return a result
+ * code. Well, we haven't fired up the Htal library, and
+ * wouldn't want it to send a response even if we had.
+ * Therefore, I'll subvert the whole process by setting
+ * the HTAL library refNum passed in to the Desktop Link
+ * Manager to an invalid value. I'll look for this
+ * value in the SysTrap handling code and no-op the call
+ * by calling this stub.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType HtalLibHeadpatch::HtalLibSendReply (void)
+{
+ CALLED_SETUP ("Err", "void");
+
+ PUT_RESULT_VAL (Err, errNone);
+
+ return kSkipROM;
+}
diff --git a/SrcShared/Patches/EmPatchModuleHtal.h b/SrcShared/Patches/EmPatchModuleHtal.h
new file mode 100644
index 0000000..7147fca
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleHtal.h
@@ -0,0 +1,30 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModuleHtal_h
+#define EmPatchModuleHtal_h
+
+#include "EmPatchModule.h"
+
+class EmPatchModuleHtal : public EmPatchModule
+{
+ public:
+ EmPatchModuleHtal (void);
+ virtual ~EmPatchModuleHtal (void) {}
+
+ virtual Err GetHeadpatch (uint16 index, HeadpatchProc& proc);
+};
+
+
+#endif // EmPatchModuleHtal_h
diff --git a/SrcShared/Patches/EmPatchModuleMap.cpp b/SrcShared/Patches/EmPatchModuleMap.cpp
new file mode 100644
index 0000000..5124004
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleMap.cpp
@@ -0,0 +1,146 @@
+/* -*- 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 "EmPatchModuleMap.h"
+
+#include "EmStructs.h"
+#include "Miscellaneous.h"
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleMap::EmPatchModuleMap
+ *
+ * DESCRIPTION: EmPatchModuleMap constructor
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmPatchModuleMap::EmPatchModuleMap()
+{
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleMap::DoAll
+ *
+ * DESCRIPTION: Repeat the given operation for all modules in the PatchMap
+ *
+ * PARAMETERS: todo the operation to be performed
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModuleMap::DoAll(EPmOperation todo, IEmPatchContainer *conainerIP)
+{
+ Err ret = kPatchErrNone;
+
+ SimplePatchModuleMap::iterator iter;
+ for (iter = fModMap.begin(); iter != fModMap.end(); ++iter)
+ {
+ switch (todo)
+ {
+ case EPMOpInitializeAll:
+ iter->second->Initialize(*conainerIP);
+ break;
+ case EPMOpResetAll:
+ iter->second->Reset();
+ break;
+ case EPMOpDisposeAll:
+ iter->second->Dispose();
+ break;
+ case EPMOpClearAll:
+ iter->second->Clear();
+ break;
+ case EPMOpLoadAll:
+ iter->second->Load();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+// ==============================================================================
+// * interface implementations
+// ==============================================================================
+// ==============================================================================
+// * BEGIN IEmAllPatchModules
+// ==============================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleMap::GetModuleByName
+ *
+ * DESCRIPTION: Locates a PatchModule in the collection, based on the given
+ * unique PatchModule name.
+ *
+ * PARAMETERS: nameStr name of the PatchModule to be located
+ * moduleIP IEmPatchModule interface for the given PatchModule
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModuleMap::GetModuleByName (const string &nameStr, IEmPatchModule *& moduleIP)
+{
+ moduleIP = NULL;
+ SimplePatchModuleMap::iterator iter = fModMap.find(nameStr);
+
+ if (iter != fModMap.end())
+ moduleIP = iter->second;
+
+ return kPatchErrNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleMap::AddModule
+ *
+ * DESCRIPTION: Add a PatchModule to the EmPatchModuleMap collection
+ *
+ * PARAMETERS: moduleIP address of the IEmPatchModule interface for
+ * the PatchModule to be added.
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModuleMap::AddModule (IEmPatchModule *moduleIP)
+{
+ if (moduleIP != NULL)
+ {
+ fModMap.insert(SimplePatchModuleMap::value_type(moduleIP->GetName(), moduleIP));
+ }
+
+ return kPatchErrNone;
+}
+
+// ==============================================================================
+// * END IEmPatchModuleMap
+// ==============================================================================
diff --git a/SrcShared/Patches/EmPatchModuleMap.h b/SrcShared/Patches/EmPatchModuleMap.h
new file mode 100644
index 0000000..0e242a9
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleMap.h
@@ -0,0 +1,100 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModuleMap_h
+#define EmPatchModuleMap_h
+
+#include "EmPatchIf.h" // IEmPatchModuleMap
+#include "EmPatchModule.h" // IEmPatchModule
+
+
+typedef map<string, IEmPatchModule*> SimplePatchModuleMap;
+
+
+// EmPatchModuleMap defines a mapped list of Patch Modules created
+
+class EmPatchModuleMap : public EcmObject,
+ ecm_implements IEmPatchModuleMap
+{
+ public:
+// ==============================================================================
+// * constructors
+// ==============================================================================
+ EmPatchModuleMap();
+ virtual ~EmPatchModuleMap() {}
+
+
+// ==============================================================================
+// * Helper functions
+// ==============================================================================
+ enum EPmOperation
+ {
+ EPMOpInitializeAll,
+ EPMOpResetAll,
+ EPMOpDisposeAll,
+ EPMOpClearAll,
+ EPMOpLoadAll
+ };
+
+ Err DoAll(EPmOperation todo, IEmPatchContainer *IP = NULL);
+
+
+// ==============================================================================
+// * interface implementations
+// ==============================================================================
+// ==============================================================================
+// * BEGIN IEmPatchModuleMap
+// ==============================================================================
+ Err InitializeAll(IEmPatchContainer &containerI)
+ {
+ return DoAll(EPMOpInitializeAll, &containerI);
+ }
+
+ Err ResetAll()
+ {
+ return DoAll(EPMOpResetAll);
+ }
+
+ Err DisposeAll()
+ {
+ return DoAll(EPMOpDisposeAll);
+ }
+
+ Err ClearAll()
+ {
+ return DoAll(EPMOpClearAll);
+ }
+
+ Err LoadAll()
+ {
+ return DoAll(EPMOpLoadAll);
+ }
+
+ Err AddModule (IEmPatchModule *moduleIP);
+
+ Err GetModuleByName (const string &nameStr, IEmPatchModule *& moduleIP);
+
+// ==============================================================================
+// * BEGIN IEmPatchModuleMap
+// ==============================================================================
+
+ private:
+ SimplePatchModuleMap fModMap;
+};
+
+
+Err AddStaticPatchModules();
+
+
+#endif // EmPatchModuleMap_h
diff --git a/SrcShared/Patches/EmPatchModuleMemMgr.cpp b/SrcShared/Patches/EmPatchModuleMemMgr.cpp
new file mode 100644
index 0000000..92a3df8
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleMemMgr.cpp
@@ -0,0 +1,1902 @@
+/* -*- 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 "EmLowMem.h" // EmLowMem_GetGlobal
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmPalmOS.h" // ForgetStacksIn
+#include "EmPalmFunction.h" // FindFunctionName
+#include "EmPalmHeap.h" // EmPalmHeap::MemMgrInit, etc.
+#include "EmPatchState.h" // EnterMemMgr, ExitMemMgr,etc.
+#include "EmSession.h" // ScheduleDeferredError
+#include "EmSubroutine.h"
+#include "Hordes.h" // gWarningHappened (!!! There's gotta be a better place for this!)
+#include "Logging.h" // LogAppendMsg
+#include "Marshal.h" // CALLED_SETUP
+#include "MetaMemory.h" // MetaMemory mark functions
+#include "PreferenceMgr.h" // ShouldContinue
+#include "ROMStubs.h" // MemHandleLock, MemHandleUnlock
+
+
+// ======================================================================
+// Proto patch table for the system functions. This array will be used
+// to create a sparse array at runtime.
+// ======================================================================
+
+ProtoPatchTableEntry gProtoMemMgrPatchTable[] =
+{
+ #undef INSTALL_PATCH
+ #define INSTALL_PATCH(fn) {sysTrap##fn, MemMgrHeadpatch::fn, MemMgrTailpatch::fn},
+
+ FOR_EACH_MEMMGR_FUNCTION(INSTALL_PATCH)
+
+ {0, NULL, NULL}
+};
+
+
+#ifdef FILL_BLOCKS
+const int kChunkNewValue = 0x31;
+const int kChunkResizeValue = 0x33;
+const int kChunkFreeValue = 0x35;
+const int kHandleNewValue = 0x71;
+const int kHandleResizeValue = 0x73;
+const int kHandleFreeValue = 0x75;
+const int kPtrNewValue = 0x91;
+const int kPtrResizeValue = 0x93;
+const int kPtrFreeValue = 0x95;
+#endif
+
+static void PrvRememberHeapAndPtr (EmPalmHeap* h, emuptr p);
+static EmPalmHeap* PrvGetRememberedHeap (emuptr p);
+
+static void PrvRememberChunk (emuptr);
+static void PrvRememberHandle (emuptr);
+static void PrvForgetChunk (emuptr);
+static void PrvForgetHandle (emuptr);
+static void PrvForgetAll (UInt16 heapID, UInt16 ownerID);
+static int PrvCountLeaks (UInt16 ownerID);
+static void PrvReportMemoryLeaks (UInt16 ownerID);
+static void PrvReportLeakedChunk (const EmTrackedChunk& tracked,
+ const EmPalmChunk& chunk);
+static Bool PrvLeakException (const EmPalmChunk& chunk);
+
+
+// Define a bunch of wrapper head- and tailpatches.
+// These are defined via macros for those functions that don't have a
+// complex implementation.
+
+#define DEFINE_HEAD_PATCH(fn) CallROMType MemMgrHeadpatch::fn (void) { EmPatchState::EnterMemMgr (#fn); return kExecuteROM; }
+#define DEFINE_TAIL_PATCH(fn) void MemMgrTailpatch::fn (void) { EmPatchState::ExitMemMgr (#fn); }
+
+FOR_EACH_STUB_HEADPATCH_FUNCTION(DEFINE_HEAD_PATCH)
+FOR_EACH_STUB_BOTHPATCH_FUNCTION(DEFINE_HEAD_PATCH)
+
+FOR_EACH_STUB_TAILPATCH_FUNCTION(DEFINE_TAIL_PATCH)
+FOR_EACH_STUB_BOTHPATCH_FUNCTION(DEFINE_TAIL_PATCH)
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemChunkFree
+ *
+ * DESCRIPTION: If the user wants disposed blocks to be filled with a
+ * special value, handle that here.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemChunkFree (void)
+{
+ // Err MemChunkFree(MemPtr chunkDataP)
+
+ EmPatchState::EnterMemMgr ("MemChunkFree");
+
+ CALLED_SETUP ("Err", "MemPtr p");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+#ifdef FILL_BLOCKS
+
+ gHeapID = ::MemPtrHeapID (p);
+
+ if (p && gPrefs->FillDisposedBlocks ())
+ {
+ UInt32 size = ::MemPtrSize (p);
+
+ CEnableFullAccess munge;
+ uae_memset (p, kChunkFreeValue, size);
+ }
+
+#endif
+
+ ::PrvForgetChunk ((emuptr) (MemPtr) p);
+
+ // Remember what heap the chunk was in for later when
+ // we need to resync with that heap.
+
+ EmPalmHeap* heap = const_cast<EmPalmHeap*>(EmPalmHeap::GetHeapByPtr (p));
+ ::PrvRememberHeapAndPtr (heap, (emuptr) (MemPtr) p);
+
+ // In case this chunk contained a stack, forget all references
+ // to that stack (or those stacks).
+
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkBodyContaining ((emuptr) (MemPtr) p);
+ if (chunk)
+ {
+ EmPalmOS::ForgetStacksIn (chunk->BodyStart (), chunk->BodySize ());
+ }
+ }
+
+ return kExecuteROM;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemHandleFree
+ *
+ * DESCRIPTION: If the user wants disposed blocks to be filled with a
+ * special value, handle that here.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemHandleFree (void)
+{
+ // Err MemHandleFree(MemHandle h)
+
+ EmPatchState::EnterMemMgr ("MemHandleFree");
+
+ CALLED_SETUP ("Err", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+#ifdef FILL_BLOCKS
+
+ gHeapID = ::MemHandleHeapID (h);
+
+ if (h && gPrefs->FillDisposedBlocks ())
+ {
+ UInt32 size = ::MemHandleSize (h);
+ if (p)
+ {
+ {
+ CEnableFullAccess munge;
+ uae_memset (p, kHandleFreeValue, size);
+ }
+ }
+ }
+
+#endif
+
+ ::PrvForgetHandle ((emuptr) (MemHandle) h);
+
+ // Remember what heap the chunk was in for later when
+ // we need to resync with that heap.
+
+ EmPalmHeap* heap = const_cast<EmPalmHeap*>(EmPalmHeap::GetHeapByHdl (h));
+ ::PrvRememberHeapAndPtr (heap, (emuptr) (MemHandle) h);
+
+ // In case this chunk contained a stack, forget all references
+ // to that stack (or those stacks).
+
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkReferencedBy (h);
+ if (chunk)
+ {
+ EmPalmOS::ForgetStacksIn (chunk->BodyStart (), chunk->BodySize ());
+ }
+ }
+
+ if (h)
+ {
+ // In case this chunk contained system code, invalid our cache
+ // of valid system code chunks.
+
+ emuptr p = (emuptr) EmPalmHeap::DerefHandle (h);
+ MetaMemory::ChunkUnlocked (p);
+
+ // In case this chunk held a bitmap, drop it from our list of
+ // registered bitmaps.
+
+ MetaMemory::UnregisterBitmapHandle (h);
+ }
+
+ return kExecuteROM;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemHandleUnlock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemHandleUnlock (void)
+{
+ // Err MemHandleUnlock(MemHandle h)
+
+ EmPatchState::EnterMemMgr ("MemHandleUnlock");
+
+ CALLED_SETUP ("Err", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+ // If this handle was for a bitmap resource, forget the pointer
+ // we registered earlier.
+
+ if (MetaMemory::IsBitmapHandle (h))
+ {
+ EmPalmHeap* heap = const_cast<EmPalmHeap*>(EmPalmHeap::GetHeapByHdl (h));
+
+ if (heap)
+ {
+ emuptr p = (emuptr) EmPalmHeap::DerefHandle (h) - heap->ChunkHeaderSize ();
+
+ EmPalmChunk chunk (*heap, p);
+
+ if (chunk.LockCount () == 1)
+ {
+ MetaMemory::UnregisterBitmapPointer ((MemPtr) p);
+ }
+ }
+ }
+
+ return kExecuteROM;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemPtrUnlock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemPtrUnlock (void)
+{
+ // Err MemPtrUnlock(MemPtr p)
+
+ EmPatchState::EnterMemMgr ("MemPtrUnlock");
+
+ CALLED_SETUP ("Err", "MemPtr p");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+ // If this handle was for a bitmap resource, forget the pointer
+ // we registered earlier.
+
+ if (MetaMemory::IsBitmapPointer (p))
+ {
+ MetaMemory::UnregisterBitmapPointer (p);
+ }
+
+ return kExecuteROM;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemSemaphoreRelease
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemSemaphoreRelease (void)
+{
+ // Err MemSemaphoreRelease (Boolean writeAccess)
+
+ EmPatchState::EnterMemMgr ("MemSemaphoreRelease");
+
+ CALLED_SETUP ("Err", "Boolean writeAccess");
+
+ CALLED_GET_PARAM_VAL (Boolean, writeAccess);
+
+ if (writeAccess
+ && --EmPatchState::fgData.fMemSemaphoreCount == 0
+ && EmPatchState::HasWellBehavedMemSemaphoreUsage ())
+ {
+ // Amount of time to allow before warning that the memory manager
+ // semaphore has been held too long. Note that this used to be
+ // 60 seconds. However, at current emulation speeds and the rate
+ // at which the tickcount is incremented, it seems that the
+ // Memory Manager itself can hold onto the semaphore longer than
+ // this threshold (in really, really full heaps when calling
+ // MemChunkNew, for example). So let's double it.
+
+ const unsigned long kMaxElapsedSeconds = 120 /* seconds */ * 100 /* ticks per second */;
+
+ CEnableFullAccess munge;
+
+ unsigned long curCount = EmLowMem_GetGlobal (hwrCurTicks);
+ unsigned long elapsedTicks = curCount - EmPatchState::fgData.fMemSemaphoreReserveTime;
+
+ if (elapsedTicks > kMaxElapsedSeconds)
+ {
+ EmAssert (gSession);
+ gSession->ScheduleDeferredError (new EmDeferredErrMemMgrSemaphore);
+ }
+ }
+
+ return kExecuteROM;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrHeadpatch::MemSemaphoreReserve
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType MemMgrHeadpatch::MemSemaphoreReserve (void)
+{
+ // Err MemSemaphoreReserve (Boolean writeAccess)
+
+ EmPatchState::EnterMemMgr ("MemSemaphoreReserve");
+
+ CALLED_SETUP ("Err", "Boolean writeAccess");
+
+ CALLED_GET_PARAM_VAL (Boolean, writeAccess);
+
+ if (writeAccess
+ && EmPatchState::fgData.fMemSemaphoreCount++ == 0
+ && EmPatchState::HasWellBehavedMemSemaphoreUsage ())
+ {
+ CEnableFullAccess munge;
+ EmPatchState::fgData.fMemSemaphoreReserveTime = EmLowMem_GetGlobal (hwrCurTicks);
+ }
+
+ return kExecuteROM;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemChunkFree
+ *
+ * DESCRIPTION: If the user wants disposed blocks to be filled with a
+ * special value, handle that here.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemChunkFree (void)
+{
+ // Err MemChunkFree(MemPtr chunkDataP)
+
+ CALLED_SETUP ("Err", "MemPtr p");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+ EmPalmHeap* heap = ::PrvGetRememberedHeap ((emuptr) (MemPtr) p);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemChunkFree (heap, &delta);
+ MetaMemory::Resync (delta);
+
+ {
+ CEnableFullAccess munge;
+
+ emuptr w = EmLowMem_GetGlobal (uiGlobals.firstWindow);
+ if (w == (emuptr) (MemPtr) p)
+ {
+ EmPatchState::SetUIReset (false);
+ }
+ }
+
+ EmPatchState::ExitMemMgr ("MemChunkFree");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemChunkNew
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemChunkNew (void)
+{
+ // MemPtr MemChunkNew(UInt16 heapID, UInt32 size, UInt16 attr)
+
+ CALLED_SETUP ("MemPtr", "UInt16 heapID, UInt32 size, UInt16 attr");
+
+ CALLED_GET_PARAM_VAL (UInt16, heapID);
+// CALLED_GET_PARAM_VAL (UInt32, size);
+ CALLED_GET_PARAM_VAL (UInt16, attr);
+ GET_RESULT_PTR ();
+
+#ifdef FILL_BLOCKS
+
+ if (gPrefs->FillNewBlocks ())
+ {
+ if (c)
+ {
+
+ if (attr & memNewChunkFlagNonMovable)
+ {
+ CEnableFullAccess munge;
+ uae_memset (c, kChunkNewValue, size);
+ }
+ else
+ {
+ emuptr p = (emuptr) ::MemHandleLock ((MemHandle) c);
+ if (p)
+ {
+ {
+ CEnableFullAccess munge;
+ uae_memset (p, kChunkNewValue, size);
+ }
+
+ ::MemHandleUnlock ((MemHandle) c);
+ }
+ }
+ }
+ }
+
+#endif
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemChunkNew (heapID, (MemPtr) result, attr, &delta);
+ MetaMemory::Resync (delta);
+
+#define TRACK_BOOT_ALLOCATION 0
+#if TRACK_BOOT_ALLOCATION
+ if (attr & memNewChunkFlagNonMovable)
+ {
+ c = EmPalmHeap::DerefHandle (c);
+ }
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr ((MemPtr) result);
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkContaining (result);
+ if (chunk)
+ {
+ LogAppendMsg ("Chunk allocated, loc = 0x%08X, size = 0x%08X",
+ (int) chunk->Start (), (int) chunk->Size ());
+ }
+ }
+#endif
+
+ if (attr & memNewChunkFlagNonMovable)
+ {
+ ::PrvRememberChunk (result);
+ }
+
+ else if (attr & memNewChunkFlagPreLock)
+ {
+ MemHandle h = EmPalmHeap::RecoverHandle ((MemPtr) result);
+ ::PrvRememberHandle ((emuptr) h);
+ }
+ else
+ {
+ ::PrvRememberHandle (result);
+ }
+
+ EmPatchState::ExitMemMgr ("MemChunkNew");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleFree
+ *
+ * DESCRIPTION: If the user wants disposed blocks to be filled with a
+ * special value, handle that here.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleFree (void)
+{
+ // Err MemHandleFree(MemHandle h)
+
+ CALLED_SETUP ("Err", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+ EmPalmHeap* heap = ::PrvGetRememberedHeap ((emuptr) (MemHandle) h);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleFree (heap, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHandleFree");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleNew
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleNew (void)
+{
+ // MemHandle MemHandleNew(UInt32 size)
+
+ CALLED_SETUP ("MemHandle", "UInt32 size");
+
+ GET_RESULT_PTR ();
+
+
+#ifdef FILL_BLOCKS
+
+ if (result)
+ {
+ if (size && gPrefs->FillNewBlocks ())
+ {
+ emuptr p = (emuptr) ::MemHandleLock ((MemHandle) result);
+ if (p)
+ {
+ {
+ CEnableFullAccess munge;
+ uae_memset (p, kHandleNewValue, size);
+ }
+
+ ::MemHandleUnlock ((MemHandle) result);
+ }
+ }
+ }
+
+#endif
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleNew ((MemHandle) result, &delta);
+ MetaMemory::Resync (delta);
+
+#if TRACK_BOOT_ALLOCATION
+ emuptr c;
+
+ if (1)
+ {
+ c = EmPalmHeap::DerefHandle (result);
+ }
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr ((MemPtr) c);
+ if (heap)
+ {
+ const EmPalmChunk* chunk = heap->GetChunkContaining (c);
+ if (chunk)
+ {
+ LogAppendMsg ("Handle allocated, loc = 0x%08X, size = 0x%08X",
+ (int) chunk->Start (), (int) chunk->Size ());
+ }
+ }
+#endif
+
+ ::PrvRememberHandle (result);
+
+ EmPatchState::ExitMemMgr ("MemHandleNew");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleLock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleLock (void)
+{
+ // MemPtr MemHandleLock(MemHandle h)
+
+ CALLED_SETUP ("MemPtr", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleLock ((MemHandle) h, &delta);
+ MetaMemory::Resync (delta);
+
+ // If this handle was for a bitmap resource, remember the pointer
+ // for fast checking later.
+
+ if (MetaMemory::IsBitmapHandle (h))
+ {
+ GET_RESULT_PTR ();
+ MetaMemory::RegisterBitmapPointer ((MemPtr) result);
+ }
+
+ EmPatchState::ExitMemMgr ("MemHandleLock");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleResetLock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleResetLock (void)
+{
+ // Err MemHandleResetLock(MemHandle h)
+
+ CALLED_SETUP ("Err", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleResetLock ((MemHandle) h, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHandleResetLock");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleResize
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleResize (void)
+{
+ // Err MemHandleResize(MemHandle h, UInt32 newSize)
+
+ CALLED_SETUP ("Err", "MemHandle h, UInt32 newSize");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+#ifdef FILL_BLOCKS
+
+ if (h)
+ {
+ if (newSize > gResizeOrigSize && gPrefs->FillResizedBlocks ())
+ {
+ emuptr p = (emuptr) ::MemHandleLock ((MemHandle) h);
+ if (p)
+ {
+ {
+ CEnableFullAccess munge;
+ uae_memset (p + gResizeOrigSize, kHandleResizeValue, newSize - gResizeOrigSize);
+ }
+
+ ::MemHandleUnlock ((MemHandle) h);
+ }
+ }
+ }
+
+#endif
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleResize ((MemHandle) h, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHandleResize");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHandleUnlock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHandleUnlock (void)
+{
+ // Err MemHandleUnlock(MemHandle h)
+
+ CALLED_SETUP ("Err", "MemHandle h");
+
+ CALLED_GET_PARAM_VAL (MemHandle, h);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHandleUnlock ((MemHandle) h, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHandleUnlock");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHeapCompact
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHeapCompact (void)
+{
+ // Err MemHeapCompact(UInt16 heapID)
+
+ CALLED_SETUP ("Err", "UInt16 heapID");
+
+ CALLED_GET_PARAM_VAL (UInt16, heapID);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHeapCompact (heapID, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHeapCompact");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHeapFreeByOwnerID
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+// !!! This should probably walk the heap itself so that it can just mark
+// the chunks that are about to be freed.
+
+void MemMgrTailpatch::MemHeapFreeByOwnerID (void)
+{
+ // Err MemHeapFreeByOwnerID(UInt16 heapID, UInt16 ownerID)
+
+ CALLED_SETUP ("Err", "UInt16 heapID, UInt16 ownerID");
+
+ CALLED_GET_PARAM_VAL (UInt16, heapID);
+ CALLED_GET_PARAM_VAL (UInt16, ownerID);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHeapFreeByOwnerID (heapID, ownerID, &delta);
+ MetaMemory::Resync (delta);
+
+ ::PrvForgetAll (heapID, ownerID);
+
+ EmPatchState::ExitMemMgr ("MemHeapFreeByOwnerID");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemInitHeapTable
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemInitHeapTable (void)
+{
+ // Err MemInitHeapTable(UInt16 cardNo)
+
+ CALLED_SETUP ("Err", "UInt16 cardNo");
+
+ CALLED_GET_PARAM_VAL (UInt16, cardNo);
+
+ EmPalmHeap::MemInitHeapTable (cardNo);
+
+ EmPatchState::ExitMemMgr ("MemInitHeapTable");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHeapInit
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHeapInit (void)
+{
+ // Err MemHeapInit(UInt16 heapID, Int16 numHandles, Boolean initContents)
+
+ CALLED_SETUP ("Err", "UInt16 heapID, Int16 numHandles, Boolean initContents");
+
+ CALLED_GET_PARAM_VAL (UInt16, heapID);
+ CALLED_GET_PARAM_VAL (Int16, numHandles);
+ CALLED_GET_PARAM_VAL (Boolean, initContents);
+
+ EmPalmHeap::MemHeapInit (heapID, numHandles, initContents);
+
+ EmPatchState::ExitMemMgr ("MemHeapInit");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemHeapScramble
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemHeapScramble (void)
+{
+ // Err MemHeapScramble(UInt16 heapID)
+
+ CALLED_SETUP ("Err", "UInt16 heapID");
+
+ CALLED_GET_PARAM_VAL (UInt16, heapID);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemHeapScramble (heapID, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemHeapScramble");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemKernelInit
+ *
+ * DESCRIPTION: MemKernelInit is called just after AMXDriversInit, which
+ * is where the exception vectors are set up. After those
+ * vectors are installed, there really shouldn't be any
+ * more memory accesses to that range of memory. Thus,
+ * memory access there is flagged as invalid.
+ *
+ * While we're here, let's mark some other memory
+ * locations, too.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemKernelInit (void)
+{
+ MetaMemory::MarkLowMemory ( MetaMemory::GetLowMemoryBegin (),
+ MetaMemory::GetLowMemoryEnd ());
+ MetaMemory::MarkSystemGlobals ( MetaMemory::GetSysGlobalsBegin (),
+ MetaMemory::GetSysGlobalsEnd ());
+ MetaMemory::MarkHeapHeader ( MetaMemory::GetHeapHdrBegin (0),
+ MetaMemory::GetHeapHdrEnd (0));
+
+ // On the Visor, these are fair game.
+ MetaMemory::MarkSystemGlobals (offsetof (M68KExcTableType, unassigned[12]),
+ offsetof (M68KExcTableType, unassigned[16]));
+
+ EmPatchState::ExitMemMgr ("MemKernelInit");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemLocalIDToLockedPtr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemLocalIDToLockedPtr (void)
+{
+ // MemPtr MemLocalIDToLockedPtr(LocalID local, UInt16 cardNo)
+
+ CALLED_SETUP ("MemPtr", "LocalID local, UInt16 cardNo");
+
+ GET_RESULT_PTR ();
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemLocalIDToLockedPtr ((MemPtr) result, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemLocalIDToLockedPtr");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemPtrNew
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemPtrNew (void)
+{
+ // MemPtr MemPtrNew(UInt32 size)
+
+ CALLED_SETUP ("MemPtr", "UInt32 size");
+
+ GET_RESULT_PTR ();
+
+#ifdef FILL_BLOCKS
+
+ if (result)
+ {
+ if (gPrefs->FillNewBlocks ())
+ {
+ CEnableFullAccess munge;
+ uae_memset (result, kPtrNewValue, size);
+ }
+ }
+
+#endif
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemPtrNew ((MemPtr) result, &delta);
+ MetaMemory::Resync (delta);
+
+ ::PrvRememberChunk (result);
+
+ EmPatchState::ExitMemMgr ("MemPtrNew");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemPtrResetLock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemPtrResetLock (void)
+{
+ // Err MemPtrResetLock(MemPtr p)
+
+ CALLED_SETUP ("Err", "MemPtr p");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemPtrResetLock (p, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemPtrResetLock");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemPtrResize
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemPtrSetOwner (void)
+{
+ // Err MemPtrSetOwner(MemPtr chunkDataP, UInt8 owner)
+
+ CALLED_SETUP ("Err", "MemPtr p, UInt16 owner");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+// CALLED_GET_PARAM_VAL (UInt16, owner);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemPtrSetOwner (p, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemPtrSetOwner");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemPtrResize
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemPtrResize (void)
+{
+ // Err MemPtrResize(MemPtr p, UInt32 newSize)
+
+ CALLED_SETUP ("Err", "MemPtr p, UInt32 newSize");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+#ifdef FILL_BLOCKS
+
+ if (p)
+ {
+ if (newSize > gResizeOrigSize && gPrefs->FillResizedBlocks ())
+ {
+ CEnableFullAccess munge;
+ uae_memset (p + gResizeOrigSize, kPtrResizeValue, newSize - gResizeOrigSize);
+ }
+ }
+
+#endif
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemPtrResize (p, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemPtrResize");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MemMgrTailpatch::MemPtrUnlock
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void MemMgrTailpatch::MemPtrUnlock (void)
+{
+ // Err MemPtrUnlock(MemPtr p)
+
+ CALLED_SETUP ("Err", "MemPtr p");
+
+ CALLED_GET_PARAM_VAL (MemPtr, p);
+
+ EmPalmChunkList delta;
+ EmPalmHeap::MemPtrUnlock (p, &delta);
+ MetaMemory::Resync (delta);
+
+ EmPatchState::ExitMemMgr ("MemPtrUnlock");
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvRememberHeapAndPtr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void PrvRememberHeapAndPtr (EmPalmHeap* h, emuptr p)
+{
+ EmAssert (EmPatchState::fgData.fRememberedHeaps.find (p) == EmPatchState::fgData.fRememberedHeaps.end ());
+
+ EmPatchState::fgData.fRememberedHeaps[p] = h;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetRememberedHeap
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmPalmHeap* PrvGetRememberedHeap (emuptr p)
+{
+ EmPalmHeap* result = NULL;
+
+ map<emuptr, EmPalmHeap*>::iterator iter = EmPatchState::fgData.fRememberedHeaps.find (p);
+ if (iter != EmPatchState::fgData.fRememberedHeaps.end ())
+ {
+ result = iter->second;
+ EmPatchState::fgData.fRememberedHeaps.erase (iter);
+ }
+
+ EmAssert (result);
+
+ return result;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvRememberChunk
+ *
+ * DESCRIPTION: Remember the context in which the given pointer was
+ * allocated. Called after MemPtrNew or MemChunkNew
+ * completes.
+ *
+ * PARAMETERS: p - pointer returned from MemPtrNew or MemChunkNew.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvRememberChunk (emuptr p)
+{
+ //
+ // Track only allocations in the dynamic heap.
+ //
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByPtr (p);
+
+ if (!heap || heap->HeapID () != 0)
+ return;
+
+#ifdef _DEBUG
+
+ //
+ // Make sure that this pointer is not a handle in disguise.
+ //
+
+ MemHandle h = EmPalmHeap::RecoverHandle ((MemPtr) p);
+
+ if (h)
+ {
+ EmAssert (false);
+ }
+
+ //
+ // Ensure this pointer is not already on our list.
+ //
+
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ //
+ // If we have recorded a handle, make sure that our handle
+ // does not reference this newly allocated chunk. That would
+ // indicate that we have a stale handle in our list.
+ //
+
+ if (iter->isHandle)
+ {
+ emuptr hDereffed = (emuptr) EmPalmHeap::DerefHandle ((MemHandle) iter->ptr);
+ if (hDereffed == p)
+ {
+ EmAssert (false);
+ }
+ }
+
+ //
+ // If we have recorded a pointer, make sure that it doesn't
+ // also point to the newly allocated chunk. That would indicate
+ // that we have a stale pointer in our list.
+ //
+
+ else
+ {
+ if (iter->ptr == p)
+ {
+ EmAssert (false);
+ }
+ }
+
+ ++iter;
+ }
+#endif
+
+ //
+ // Push an empty record onto our list. We'll update it after
+ // it's on the list in order to reduce any performance impact
+ // due to copying the stack crawl. Push the chunk at the front
+ // of the list; the theory here is that recently added chunks
+ // will be the ones most likely to be removed later, so adding
+ // them to the front will speed up the removal process when
+ // performing a forward traversal.
+ //
+
+ EmTrackedChunk chunk;
+ EmPatchState::fgData.fTrackedChunks.push_front (chunk);
+
+ //
+ // Get the pointer to the newly-added record.
+ //
+
+ EmTrackedChunkList::reference newChunk = EmPatchState::fgData.fTrackedChunks.front ();
+
+ //
+ // Fill in the newly added record.
+ //
+
+ newChunk.ptr = p;
+ newChunk.isHandle = false;
+
+ EmPalmOS::GenerateStackCrawl (newChunk.stackCrawl);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvRememberHandle
+ *
+ * DESCRIPTION: Remember the context in which the given handle was
+ * allocated. Called after MemHandleNew or MemChunkNew
+ * completes.
+ *
+ * PARAMETERS: h - handle returned from MemHandleNew or MemChunkNew.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvRememberHandle (emuptr h)
+{
+ //
+ // Track only allocations in the dynamic heap.
+ //
+
+ const EmPalmHeap* heap = EmPalmHeap::GetHeapByHdl ((MemHandle) h);
+
+ if (!heap || heap->HeapID () != 0)
+ return;
+
+#ifdef _DEBUG
+ //
+ // Ensure this handle is not already on our list.
+ //
+
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ //
+ // If we have recorded a handle, make sure it does not
+ // match the newly allocated handle. That would indicate
+ // that we have a stale handle in our list.
+ //
+
+ if (iter->isHandle)
+ {
+ if (iter->ptr == h)
+ {
+ EmAssert (false);
+ }
+ }
+
+ //
+ // If we have recorded a pointer, make sure it is not
+ // pointed to by the newly allocate handle. That would
+ // indicate that we have a stale pointer in our list.
+ //
+
+ else
+ {
+ emuptr hDereffed = (emuptr) EmPalmHeap::DerefHandle ((MemHandle) h);
+
+ if (iter->ptr == hDereffed)
+ {
+ EmAssert (false);
+ }
+ }
+
+ ++iter;
+ }
+#endif
+
+ //
+ // Push an empty record onto our list. We'll update it after
+ // it's on the list in order to reduce any performance impact
+ // due to copying the stack crawl. Push the handle at the front
+ // of the list; the theory here is that recently added chunks
+ // will be the ones most likely to be removed later, so adding
+ // them to the front will speed up the removal process when
+ // performing a forward traversal.
+ //
+
+ EmTrackedChunk chunk;
+ EmPatchState::fgData.fTrackedChunks.push_front (chunk);
+
+ //
+ // Get the pointer to the newly-added record.
+ //
+
+ EmTrackedChunkList::reference newChunk = EmPatchState::fgData.fTrackedChunks.front ();
+
+ //
+ // Fill in the newly added record.
+ //
+
+ newChunk.ptr = h;
+ newChunk.isHandle = true;
+
+ EmPalmOS::GenerateStackCrawl (newChunk.stackCrawl);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvForgetChunk
+ *
+ * DESCRIPTION: Forget about the given chunk. Also checks for pointers
+ * to relocatable blocks and calls PrvForgetHandle instead
+ * if appropriate. Called in response to MemChunkFree.
+ *
+ * PARAMETERS: p - handle passed to MemChunkFree.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvForgetChunk (emuptr p)
+{
+ //
+ // Deal with the goofwads who allocate by handle but
+ // dispose by pointer.
+ //
+
+ MemHandle h = EmPalmHeap::RecoverHandle ((MemPtr) p);
+
+ if (h)
+ {
+ ::PrvForgetHandle ((emuptr) h);
+ return;
+ }
+
+ //
+ // Look for the given chunk in our records.
+ //
+
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ if (!iter->isHandle && iter->ptr == p)
+ {
+ //
+ // If we've found it, erase it from our list and return.
+ //
+
+ EmPatchState::fgData.fTrackedChunks.erase (iter);
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvForgetHandle
+ *
+ * DESCRIPTION: Forget about the given handle. Called in response to
+ * MemHandleFree.
+ *
+ * PARAMETERS: h - handle passed to MemHandleFree.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvForgetHandle (emuptr h)
+{
+ //
+ // Look for the given handle in our records.
+ //
+
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ if (iter->isHandle && iter->ptr == h)
+ {
+ //
+ // If we've found it, erase it from our list and return.
+ //
+
+ EmPatchState::fgData.fTrackedChunks.erase (iter);
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvForgetAll
+ *
+ * DESCRIPTION: Forget about all allocated chunks in the given heap
+ * with the given owner ID. Called in response to
+ * MemHeapFreeByOwnerID.
+ *
+ * PARAMETERS: heapID - heap ID passed to MemHeapFreeByOwnerID.
+ *
+ * ownerID - owner ID passed to MemHeapFreeByOwnerID.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvForgetAll (UInt16 heapID, UInt16 ownerID)
+{
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ const EmPalmHeap* heap = NULL;
+ const EmPalmChunk* chunk = NULL;
+
+ if (iter->isHandle)
+ {
+ heap = EmPalmHeap::GetHeapByHdl ((MemHandle) iter->ptr);
+
+ if (heap && heap->HeapID () == heapID)
+ {
+ chunk = heap->GetChunkReferencedBy ((MemHandle) iter->ptr);
+ }
+ }
+ else
+ {
+ heap = EmPalmHeap::GetHeapByPtr (iter->ptr);
+
+ if (heap && heap->HeapID () == heapID)
+ {
+ chunk = heap->GetChunkBodyContaining (iter->ptr);
+ }
+ }
+
+ if (chunk && chunk->Owner () == ownerID)
+ {
+ iter = EmPatchState::fgData.fTrackedChunks.erase (iter);
+ }
+ else
+ {
+ if (chunk)
+ EmAssert (!chunk->Free ());
+
+ ++iter;
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvCountLeaks
+ *
+ * DESCRIPTION: Find and report memory leaks. Iterates over the
+ * allocated chunks, looking for ones with the given
+ * owner ID.
+ *
+ * PARAMETERS: ownerID - owner ID of the application quitting.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+int PrvCountLeaks (UInt16 ownerID)
+{
+ int leaks = 0;
+
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ const EmPalmHeap* heap = NULL;
+ const EmPalmChunk* chunk = NULL;
+
+ if (iter->isHandle)
+ {
+ heap = EmPalmHeap::GetHeapByHdl ((MemHandle) iter->ptr);
+
+ if (heap)
+ {
+ chunk = heap->GetChunkReferencedBy ((MemHandle) iter->ptr);
+ }
+ }
+ else
+ {
+ heap = EmPalmHeap::GetHeapByPtr (iter->ptr);
+
+ if (heap)
+ {
+ chunk = heap->GetChunkBodyContaining (iter->ptr);
+ }
+ }
+
+ if (chunk && chunk->Owner () == ownerID)
+ {
+ //
+ // If this "leak" is not caused by the OS, count it.
+ //
+
+ if (!::PrvLeakException (*chunk))
+ {
+ ++leaks;
+ }
+ }
+
+ ++iter;
+ }
+
+ return leaks;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvReportMemoryLeaks
+ *
+ * DESCRIPTION: Find and report memory leaks. Iterates over the
+ * allocated chunks, looking for ones with the given
+ * owner ID.
+ *
+ * PARAMETERS: ownerID - owner ID of the application quitting.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvReportMemoryLeaks (UInt16 ownerID)
+{
+ EmTrackedChunkList::iterator iter = EmPatchState::fgData.fTrackedChunks.begin ();
+ while (iter != EmPatchState::fgData.fTrackedChunks.end ())
+ {
+ const EmPalmHeap* heap = NULL;
+ const EmPalmChunk* chunk = NULL;
+
+ if (iter->isHandle)
+ {
+ heap = EmPalmHeap::GetHeapByHdl ((MemHandle) iter->ptr);
+
+ if (heap)
+ {
+ chunk = heap->GetChunkReferencedBy ((MemHandle) iter->ptr);
+ }
+ }
+ else
+ {
+ heap = EmPalmHeap::GetHeapByPtr (iter->ptr);
+
+ if (heap)
+ {
+ chunk = heap->GetChunkBodyContaining (iter->ptr);
+ }
+ }
+
+ if (chunk && chunk->Owner () == ownerID)
+ {
+ //
+ // If this "leak" is not caused by the OS, report it.
+ //
+
+ if (!::PrvLeakException (*chunk))
+ {
+ if (iter != EmPatchState::fgData.fTrackedChunks.begin ())
+ {
+ LogAppendMsg ("--------------------------------------------------------");
+ }
+
+ ::PrvReportLeakedChunk (*iter, *chunk);
+ }
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvReportLeakedChunk
+ *
+ * DESCRIPTION: Report information on the leaked chunk:
+ *
+ * * Chunk address and size
+ * * Stack crawl of the context allocating the chunk
+ * * Contents of the chunk (truncated to 256 bytes).
+ *
+ * PARAMETERS: tracked - context information about the chunk.
+ *
+ * chunk - information on the leaked chunk.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void PrvReportLeakedChunk (const EmTrackedChunk& tracked, const EmPalmChunk& chunk)
+{
+ //
+ // Generate a full stack crawl.
+ //
+
+ StringList stackCrawlFunctions;
+
+ EmStackFrameList::const_iterator iter = tracked.stackCrawl.begin ();
+ while (iter != tracked.stackCrawl.end ())
+ {
+ // Get the function name.
+
+ char funcName[256] = {0};
+ ::FindFunctionName (iter->fAddressInFunction, funcName, NULL, NULL, 255);
+
+ // If we can't find the name, dummy one up.
+
+ if (strlen (funcName) == 0)
+ {
+ sprintf (funcName, "<Unknown @ 0x%08lX>", iter->fAddressInFunction);
+ }
+
+ stackCrawlFunctions.push_back (string (funcName));
+
+ ++iter;
+ }
+
+ //
+ // Get some data to dump
+ //
+
+ uint8 buffer[256];
+ uint32 len = chunk.BodySize ();
+
+ if (len > countof (buffer))
+ {
+ len = countof (buffer);
+ }
+
+ EmMem_memcpy ((void*) buffer, chunk.BodyStart (), len);
+
+ //
+ // Print the message.
+ //
+ // * Chunk address and size
+ // * Stack crawl of the context allocating the chunk
+ // * Contents of the chunk (truncated to 256 bytes).
+ //
+
+ LogAppendMsg ("%s chunk leaked at 0x%08X, size = %ld",
+ tracked.isHandle ? "Relocatable" : "Non-relocatable",
+ chunk.BodyStart (), chunk.BodySize ());
+
+ LogAppendMsg ("Chunk allocated by:");
+
+ StringList::iterator iter2 = stackCrawlFunctions.begin ();
+ while (iter2 != stackCrawlFunctions.end ())
+ {
+ LogAppendMsg ("\t%s", iter2->c_str ());
+
+ ++iter2;
+ }
+
+ if (chunk.BodySize () <= countof (buffer))
+ LogAppendData (buffer, len, "Chunk contents:");
+ else
+ LogAppendData (buffer, len, "Chunk contents (first %d bytes only):", countof (buffer));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvLeakException
+ *
+ * DESCRIPTION: Return whether or not the given memory chunk should be
+ * quietly allowed as a leak.
+ *
+ * PARAMETERS: chunk - information on the chunk to be tested.
+ *
+ * RETURNED: TRUE if the chunk -- even though leaked -- should not
+ * be reported as a leak. FALSE otherwise.
+ *
+ ***********************************************************************/
+
+Bool PrvLeakException (const EmPalmChunk& chunk)
+{
+ // Up to Palm OS 3.2, UIReset (called from the application's
+ // startup code) allocated the event queue and undo buffers
+ // using the application's chunk ID. In Palm OS 3.2, this
+ // allocation was moved to UIInitialize, causing the blocks
+ // to be marked with the system's chunk ID.
+ //
+ // At the same time, the call to InitWindowVariables (which
+ // allocated the RootWindow) was moved from UIReset to
+ // UIInitialize.
+
+ if (EmPatchState::OSMajorMinorVersion () >= 32)
+ {
+ // Nothing
+ }
+ else if (EmPatchState::OSMajorMinorVersion () >= 31)
+ {
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV31.displayWindow))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV31.eventQ))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV31.undoGlobals.buffer))
+ return true;
+ }
+ else if (EmPatchState::OSMajorMinorVersion () >= 30)
+ {
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV3.displayWindow))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV3.eventQ))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV3.undoGlobals.buffer))
+ return true;
+ }
+ else if (EmPatchState::OSMajorMinorVersion () >= 20)
+ {
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV2.displayWindow))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV2.eventQ))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV2.undoGlobals.buffer))
+ return true;
+ }
+ else // OSMajorMinorVersion < 20
+ {
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV1.displayWindow))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV1.eventQ))
+ return true;
+
+ if (chunk.BodyStart () == EmLowMem_GetGlobal (uiGlobalsV1.undoGlobals.buffer))
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CheckForMemoryLeaks
+ *
+ * DESCRIPTION: Entry point for checking for and reporting memory leaks.
+ * Called from SysAppExit patch.
+ *
+ * PARAMETERS: memOwnerID - memory owner ID of the function quitting.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void CheckForMemoryLeaks (UInt32 memOwnerID)
+{
+ if (!EmPatchState::fgData.fMemMgrLeaks)
+ return;
+
+ CEnableFullAccess munge;
+
+ int leaks = ::PrvCountLeaks (memOwnerID);
+
+ if (!leaks)
+ return;
+
+ //
+ // Found some leaks, so report them.
+ //
+
+ LogAppendMsg ("WARNING: ========================================================");
+ LogAppendMsg ("WARNING: Memory Leaks");
+ LogAppendMsg ("WARNING: ========================================================");
+ LogAppendMsg ("WARNING: Begin Memory Leak Dump");
+ LogAppendMsg ("WARNING: ========================================================");
+
+ ::PrvReportMemoryLeaks (memOwnerID);
+
+ LogAppendMsg ("WARNING: ========================================================");
+ LogAppendMsg ("WARNING: End Memory Leak Dump");
+ LogAppendMsg ("WARNING: ========================================================");
+
+ LogDump ();
+
+ // Now tell the user about them.
+
+ Errors::ReportErrMemMgrLeaks (leaks);
+}
diff --git a/SrcShared/Patches/EmPatchModuleNetLib.cpp b/SrcShared/Patches/EmPatchModuleNetLib.cpp
new file mode 100644
index 0000000..60c0d4b
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleNetLib.cpp
@@ -0,0 +1,4100 @@
+/* -*- 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 "EmPatchModuleNetLib.h"
+
+#include "EmMemory.h" // CEnableFullAccess
+#include "EmSubroutine.h"
+#include "Logging.h" // LogAppendMsg
+#include "Marshal.h" // PARAM_VAL, etc.
+#include "Platform_NetLib.h" // Platform_NetLib
+
+#if PLATFORM_UNIX || PLATFORM_MAC
+#include <netinet/in.h> // ntohs, ntohs
+#endif
+
+
+// ======================================================================
+// Patches for NetLib functions
+// ======================================================================
+
+class NetLibHeadpatch
+{
+ public:
+ static CallROMType NetLibOpen (void);
+ static CallROMType NetLibClose (void);
+ static CallROMType NetLibSleep (void);
+ static CallROMType NetLibWake (void);
+ static CallROMType NetLibAddrINToA (void);
+ static CallROMType NetLibAddrAToIN (void);
+ static CallROMType NetLibSocketOpen (void);
+ static CallROMType NetLibSocketClose (void);
+ static CallROMType NetLibSocketOptionSet (void);
+ static CallROMType NetLibSocketOptionGet (void);
+ static CallROMType NetLibSocketBind (void);
+ static CallROMType NetLibSocketConnect (void);
+ static CallROMType NetLibSocketListen (void);
+ static CallROMType NetLibSocketAccept (void);
+ static CallROMType NetLibSocketShutdown (void);
+ static CallROMType NetLibSendPB (void);
+ static CallROMType NetLibSend (void);
+ static CallROMType NetLibReceivePB (void);
+ static CallROMType NetLibReceive (void);
+ static CallROMType NetLibDmReceive (void);
+ static CallROMType NetLibSelect (void);
+ static CallROMType NetLibMaster (void);
+ static CallROMType NetLibGetHostByName (void);
+ static CallROMType NetLibSettingGet (void);
+ static CallROMType NetLibSettingSet (void);
+ static CallROMType NetLibIFAttach (void);
+ static CallROMType NetLibIFDetach (void);
+ static CallROMType NetLibIFGet (void);
+ static CallROMType NetLibIFSettingGet (void);
+ static CallROMType NetLibIFSettingSet (void);
+ static CallROMType NetLibIFUp (void);
+ static CallROMType NetLibIFDown (void);
+ static CallROMType NetLibGetHostByAddr (void);
+ static CallROMType NetLibGetServByName (void);
+ static CallROMType NetLibSocketAddr (void);
+ static CallROMType NetLibFinishCloseWait (void);
+ static CallROMType NetLibGetMailExchangeByName (void);
+ static CallROMType NetLibOpenCount (void);
+ static CallROMType NetLibTracePrintF (void);
+ static CallROMType NetLibTracePutS (void);
+ static CallROMType NetLibOpenIfCloseWait (void);
+ static CallROMType NetLibHandlePowerOff (void);
+ static CallROMType NetLibConnectionRefresh (void);
+ static CallROMType NetLibOpenConfig (void);
+ static CallROMType NetLibConfigMakeActive (void);
+ static CallROMType NetLibConfigList (void);
+ static CallROMType NetLibConfigIndexFromName (void);
+ static CallROMType NetLibConfigDelete (void);
+ static CallROMType NetLibConfigSaveAs (void);
+ static CallROMType NetLibConfigRename (void);
+ static CallROMType NetLibConfigAliasSet (void);
+ static CallROMType NetLibConfigAliasGet (void);
+};
+
+
+class NetLibTailpatch
+{
+ public:
+ static void NetLibOpen (void);
+ static void NetLibClose (void);
+ static void NetLibSleep (void);
+ static void NetLibWake (void);
+ static void NetLibAddrINToA (void);
+ static void NetLibAddrAToIN (void);
+ static void NetLibSocketOpen (void);
+ static void NetLibSocketClose (void);
+ static void NetLibSocketOptionSet (void);
+ static void NetLibSocketOptionGet (void);
+ static void NetLibSocketBind (void);
+ static void NetLibSocketConnect (void);
+ static void NetLibSocketListen (void);
+ static void NetLibSocketAccept (void);
+ static void NetLibSocketShutdown (void);
+ static void NetLibSendPB (void);
+ static void NetLibSend (void);
+ static void NetLibReceivePB (void);
+ static void NetLibReceive (void);
+ static void NetLibDmReceive (void);
+ static void NetLibSelect (void);
+ static void NetLibMaster (void);
+ static void NetLibGetHostByName (void);
+ static void NetLibSettingGet (void);
+ static void NetLibSettingSet (void);
+ static void NetLibIFAttach (void);
+ static void NetLibIFDetach (void);
+ static void NetLibIFGet (void);
+ static void NetLibIFSettingGet (void);
+ static void NetLibIFSettingSet (void);
+ static void NetLibIFUp (void);
+ static void NetLibIFDown (void);
+ static void NetLibGetHostByAddr (void);
+ static void NetLibGetServByName (void);
+ static void NetLibSocketAddr (void);
+ static void NetLibFinishCloseWait (void);
+ static void NetLibGetMailExchangeByName (void);
+ static void NetLibOpenCount (void);
+ static void NetLibTracePrintF (void);
+ static void NetLibTracePutS (void);
+ static void NetLibOpenIfCloseWait (void);
+ static void NetLibHandlePowerOff (void);
+ static void NetLibConnectionRefresh (void);
+ static void NetLibOpenConfig (void);
+ static void NetLibConfigMakeActive (void);
+ static void NetLibConfigList (void);
+ static void NetLibConfigIndexFromName (void);
+ static void NetLibConfigDelete (void);
+ static void NetLibConfigSaveAs (void);
+ static void NetLibConfigRename (void);
+ static void NetLibConfigAliasSet (void);
+ static void NetLibConfigAliasGet (void);
+};
+
+
+// ======================================================================
+// Proto patch table for NetLib functions. This array will be used
+// to create a sparse array at runtime.
+// ======================================================================
+
+static ProtoPatchTableEntry gProtoNetLibPatchTable[] =
+{
+ {sysLibTrapOpen, NetLibHeadpatch::NetLibOpen, NetLibTailpatch::NetLibOpen},
+ {sysLibTrapClose, NetLibHeadpatch::NetLibClose, NetLibTailpatch::NetLibClose},
+ {sysLibTrapSleep, NetLibHeadpatch::NetLibSleep, NetLibTailpatch::NetLibSleep},
+ {sysLibTrapWake, NetLibHeadpatch::NetLibWake, NetLibTailpatch::NetLibWake},
+ {netLibTrapAddrINToA, NetLibHeadpatch::NetLibAddrINToA, NetLibTailpatch::NetLibAddrINToA},
+ {netLibTrapAddrAToIN, NetLibHeadpatch::NetLibAddrAToIN, NetLibTailpatch::NetLibAddrAToIN},
+ {netLibTrapSocketOpen, NetLibHeadpatch::NetLibSocketOpen, NetLibTailpatch::NetLibSocketOpen},
+ {netLibTrapSocketClose, NetLibHeadpatch::NetLibSocketClose, NetLibTailpatch::NetLibSocketClose},
+ {netLibTrapSocketOptionSet, NetLibHeadpatch::NetLibSocketOptionSet, NetLibTailpatch::NetLibSocketOptionSet},
+ {netLibTrapSocketOptionGet, NetLibHeadpatch::NetLibSocketOptionGet, NetLibTailpatch::NetLibSocketOptionGet},
+ {netLibTrapSocketBind, NetLibHeadpatch::NetLibSocketBind, NetLibTailpatch::NetLibSocketBind},
+ {netLibTrapSocketConnect, NetLibHeadpatch::NetLibSocketConnect, NetLibTailpatch::NetLibSocketConnect},
+ {netLibTrapSocketListen, NetLibHeadpatch::NetLibSocketListen, NetLibTailpatch::NetLibSocketListen},
+ {netLibTrapSocketAccept, NetLibHeadpatch::NetLibSocketAccept, NetLibTailpatch::NetLibSocketAccept},
+ {netLibTrapSocketShutdown, NetLibHeadpatch::NetLibSocketShutdown, NetLibTailpatch::NetLibSocketShutdown},
+ {netLibTrapSendPB, NetLibHeadpatch::NetLibSendPB, NetLibTailpatch::NetLibSendPB},
+ {netLibTrapSend, NetLibHeadpatch::NetLibSend, NetLibTailpatch::NetLibSend},
+ {netLibTrapReceivePB, NetLibHeadpatch::NetLibReceivePB, NetLibTailpatch::NetLibReceivePB},
+ {netLibTrapReceive, NetLibHeadpatch::NetLibReceive, NetLibTailpatch::NetLibReceive},
+ {netLibTrapDmReceive, NetLibHeadpatch::NetLibDmReceive, NetLibTailpatch::NetLibDmReceive},
+ {netLibTrapSelect, NetLibHeadpatch::NetLibSelect, NetLibTailpatch::NetLibSelect},
+// {netLibTrapPrefsGet, NULL, NULL},
+// {netLibTrapPrefsSet, NULL, NULL},
+// {netLibTrapDrvrWake, NULL, NULL},
+// {netLibTrapInterfacePtr, NULL, NULL},
+ {netLibTrapMaster, NetLibHeadpatch::NetLibMaster, NetLibTailpatch::NetLibMaster},
+ {netLibTrapGetHostByName, NetLibHeadpatch::NetLibGetHostByName, NetLibTailpatch::NetLibGetHostByName},
+ {netLibTrapSettingGet, NetLibHeadpatch::NetLibSettingGet, NetLibTailpatch::NetLibSettingGet},
+ {netLibTrapSettingSet, NetLibHeadpatch::NetLibSettingSet, NetLibTailpatch::NetLibSettingSet},
+ {netLibTrapIFAttach, NetLibHeadpatch::NetLibIFAttach, NetLibTailpatch::NetLibIFAttach},
+ {netLibTrapIFDetach, NetLibHeadpatch::NetLibIFDetach, NetLibTailpatch::NetLibIFDetach},
+ {netLibTrapIFGet, NetLibHeadpatch::NetLibIFGet, NetLibTailpatch::NetLibIFGet},
+ {netLibTrapIFSettingGet, NetLibHeadpatch::NetLibIFSettingGet, NetLibTailpatch::NetLibIFSettingGet},
+ {netLibTrapIFSettingSet, NetLibHeadpatch::NetLibIFSettingSet, NetLibTailpatch::NetLibIFSettingSet},
+ {netLibTrapIFUp, NetLibHeadpatch::NetLibIFUp, NetLibTailpatch::NetLibIFUp},
+ {netLibTrapIFDown, NetLibHeadpatch::NetLibIFDown, NetLibTailpatch::NetLibIFDown},
+// {netLibTrapIFMediaUp, NULL, NULL},
+// {netLibTrapScriptExecute, NULL, NULL},
+ {netLibTrapGetHostByAddr, NetLibHeadpatch::NetLibGetHostByAddr, NetLibTailpatch::NetLibGetHostByAddr},
+ {netLibTrapGetServByName, NetLibHeadpatch::NetLibGetServByName, NetLibTailpatch::NetLibGetServByName},
+ {netLibTrapSocketAddr, NetLibHeadpatch::NetLibSocketAddr, NetLibTailpatch::NetLibSocketAddr},
+ {netLibTrapFinishCloseWait, NetLibHeadpatch::NetLibFinishCloseWait, NetLibTailpatch::NetLibFinishCloseWait},
+ {netLibTrapGetMailExchangeByName,NetLibHeadpatch::NetLibGetMailExchangeByName, NetLibTailpatch::NetLibGetMailExchangeByName},
+// {netLibTrapPrefsAppend, NULL, NULL},
+// {netLibTrapIFMediaDown, NULL, NULL},
+ {netLibTrapOpenCount, NetLibHeadpatch::NetLibOpenCount, NetLibTailpatch::NetLibOpenCount},
+ {netLibTrapTracePrintF, NetLibHeadpatch::NetLibTracePrintF, NetLibTailpatch::NetLibTracePrintF},
+ {netLibTrapTracePutS, NetLibHeadpatch::NetLibTracePutS, NetLibTailpatch::NetLibTracePutS},
+ {netLibTrapOpenIfCloseWait, NetLibHeadpatch::NetLibOpenIfCloseWait, NetLibTailpatch::NetLibOpenIfCloseWait},
+ {netLibTrapHandlePowerOff, NetLibHeadpatch::NetLibHandlePowerOff, NetLibTailpatch::NetLibHandlePowerOff},
+ {netLibTrapConnectionRefresh, NetLibHeadpatch::NetLibConnectionRefresh, NetLibTailpatch::NetLibConnectionRefresh},
+// {netLibTrapBitMove, NULL, NULL},
+// {netLibTrapBitPutFixed, NULL, NULL},
+// {netLibTrapBitGetFixed, NULL, NULL},
+// {netLibTrapBitPutUIntV, NULL, NULL},
+// {netLibTrapBitGetUIntV, NULL, NULL},
+// {netLibTrapBitPutIntV, NULL, NULL},
+// {netLibTrapBitGetIntV, NULL, NULL},
+ {netLibOpenConfig, NetLibHeadpatch::NetLibOpenConfig, NetLibTailpatch::NetLibOpenConfig},
+ {netLibConfigMakeActive, NetLibHeadpatch::NetLibConfigMakeActive, NetLibTailpatch::NetLibConfigMakeActive},
+ {netLibConfigList, NetLibHeadpatch::NetLibConfigList, NetLibTailpatch::NetLibConfigList},
+ {netLibConfigIndexFromName, NetLibHeadpatch::NetLibConfigIndexFromName, NetLibTailpatch::NetLibConfigIndexFromName},
+ {netLibConfigDelete, NetLibHeadpatch::NetLibConfigDelete, NetLibTailpatch::NetLibConfigDelete},
+ {netLibConfigSaveAs, NetLibHeadpatch::NetLibConfigSaveAs, NetLibTailpatch::NetLibConfigSaveAs},
+ {netLibConfigRename, NetLibHeadpatch::NetLibConfigRename, NetLibTailpatch::NetLibConfigRename},
+ {netLibConfigAliasSet, NetLibHeadpatch::NetLibConfigAliasSet, NetLibTailpatch::NetLibConfigAliasSet},
+ {netLibConfigAliasGet, NetLibHeadpatch::NetLibConfigAliasGet, NetLibTailpatch::NetLibConfigAliasGet},
+
+ {0, NULL, NULL}
+};
+
+
+
+
+// ======================================================================
+// Private functions
+// ======================================================================
+
+static const char* PrvGetOptLevelString (NetSocketOptLevelEnum);
+static const char* PrvGetOptString (NetSocketOptLevelEnum, NetSocketOptEnum);
+static const char* PrvGetDottedIPString (const NetSocketAddrType& ipAddr);
+static const char* PrvGetPortString (const NetSocketAddrType& ipAddr);
+static const char* PrvGetErrorString (Err err);
+
+
+#define PRINTF if (!LogNetLib ()) ; else LogAppendMsg
+
+
+#pragma mark -
+
+// ===========================================================================
+// ¥ EmPatchModuleNetLib
+// ===========================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModuleNetLib::EmPatchModuleNetLib
+ *
+ * DESCRIPTION: Constructor
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmPatchModuleNetLib::EmPatchModuleNetLib() :
+ EmPatchModule ("Net.lib", gProtoNetLibPatchTable)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibOpen
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibOpen (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibOpen");
+
+ // Err NetLibOpen (UInt16 libRefNum, UInt16 *netIFErrsP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 *netIFErrsP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrsP, Marshal::kOutput);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::Open (libRefNum, netIFErrsP);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (netIFErrsP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibOpen (void)
+{
+ // Err NetLibOpen (UInt16 libRefNum, UInt16 *netIFErrsP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 *netIFErrsP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrsP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*netIFErrsP = %s (0x%04X)", PrvGetErrorString (*netIFErrsP), (long) *netIFErrsP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibClose
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibClose (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibClose");
+
+ // Err NetLibClose (UInt16 libRefNum, UInt16 immediate)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 immediate");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, immediate);
+
+ // Examine the parameters
+ PRINTF ("\timmediate = 0x%08X", (long) immediate);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::Close (libRefNum, immediate);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibClose (void)
+{
+ // Err NetLibClose (UInt16 libRefNum, UInt16 immediate)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 immediate");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (UInt16, immediate);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSleep
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSleep (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSleep");
+
+ // Err NetLibSleep (UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::Sleep (libRefNum);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+
+void NetLibTailpatch::NetLibSleep (void)
+{
+ // Err NetLibSleep (UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibWake
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibWake (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibWake");
+
+ // Err NetLibWake (UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::Wake (libRefNum);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibWake (void)
+{
+ // Err NetLibWake (UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibAddrINToA
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibAddrINToA (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibAddrINToA");
+
+ // Char * NetLibAddrINToA(UInt16 libRefNum, NetIPAddr inet, Char *spaceP)
+
+ CALLED_SETUP ("Char*", "UInt16 libRefNum, NetIPAddr inet, Char *spaceP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibAddrINToA (void)
+{
+ // Char * NetLibAddrINToA(UInt16 libRefNum, NetIPAddr inet, Char *spaceP)
+
+ CALLED_SETUP ("Char*", "UInt16 libRefNum, NetIPAddr inet, Char *spaceP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_PTR ();
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibAddrAToIN
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibAddrAToIN (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibAddrAToIN");
+
+ // NetIPAddr NetLibAddrAToIN(UInt16 libRefNum, Char *a)
+
+ CALLED_SETUP ("NetIPAddr", "UInt16 libRefNum, Char *a");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibAddrAToIN (void)
+{
+ // NetIPAddr NetLibAddrAToIN(UInt16 libRefNum, Char *a)
+
+ CALLED_SETUP ("NetIPAddr", "UInt16 libRefNum, Char *a");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (NetIPAddr);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketOpen
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketOpen (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketOpen");
+
+ // NetSocketRef NetLibSocketOpen(UInt16 libRefNum, NetSocketAddrEnum domain,
+ // NetSocketTypeEnum type, Int16 protocol, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("NetSocketRef", "UInt16 libRefNum, NetSocketAddrEnum domain, "
+ "NetSocketTypeEnum type, Int16 protocol, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketAddrEnum, domain);
+ CALLED_GET_PARAM_VAL (NetSocketTypeEnum, type);
+ CALLED_GET_PARAM_VAL (Int16, protocol);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tdomain = 0x%08X", (long) domain);
+ PRINTF ("\ttype = 0x%08X", (long) type);
+ PRINTF ("\tprotocol = 0x%08X", (long) protocol);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ NetSocketRef result = Platform_NetLib::SocketOpen (libRefNum,
+ (NetSocketAddrEnum) (UInt8) domain, (NetSocketTypeEnum) (UInt8) type,
+ protocol, timeout, errP);
+ PUT_RESULT_VAL (NetSocketRef, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketOpen (void)
+{
+ CALLED_SETUP ("NetSocketRef", "UInt16 libRefNum, NetSocketAddrEnum domain, "
+ "NetSocketTypeEnum type, Int16 protocol, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketAddrEnum, domain);
+// CALLED_GET_PARAM_VAL (NetSocketTypeEnum, type);
+// CALLED_GET_PARAM_VAL (Int16, protocol);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (NetSocketRef);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketClose
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketClose (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketClose");
+
+ // Int16 NetLibSocketClose(UInt16 libRefNum, NetSocketRef socket, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketClose (libRefNum,
+ socket, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketClose (void)
+{
+ // Int16 NetLibSocketClose(UInt16 libRefNum, NetSocketRef socket, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketOptionSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketOptionSet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketOptionSet");
+
+ // Int16 NetLibSocketOptionSet(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ // void *optValueP, UInt16 optValueLen,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 level, UInt16 option, "
+ "void *optValueP, UInt16 optValueLen,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, level);
+ CALLED_GET_PARAM_VAL (UInt16, option);
+ CALLED_GET_PARAM_VAL (UInt16, optValueLen);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ CALLED_GET_PARAM_PTR (void, optValueP, optValueLen, Marshal::kInput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tlevel = %s (0x%08X)", PrvGetOptLevelString ((NetSocketOptLevelEnum) (UInt16) level), (long) (UInt16) level);
+ PRINTF ("\toption = %s (0x%08X)", PrvGetOptString ((NetSocketOptLevelEnum) (UInt16) level, (NetSocketOptEnum) (UInt16) option), (long) (UInt16) option);
+ PRINTF ("\toptValueP = 0x%08X", (long) (void*) optValueP);
+ PRINTF ("\toptValueLen = 0x%08X", (long) optValueLen);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketOptionSet (libRefNum,
+ socket, (NetSocketOptLevelEnum) (UInt16) level,
+ (NetSocketOptEnum) (UInt16) option, optValueP,
+ optValueLen, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (optValueP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketOptionSet (void)
+{
+ // Int16 NetLibSocketOptionSet(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ // void *optValueP, UInt16 optValueLen,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 level, UInt16 option, "
+ "void *optValueP, UInt16 optValueLen,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_VAL (UInt16, level);
+// CALLED_GET_PARAM_VAL (UInt16, option);
+ CALLED_GET_PARAM_VAL (UInt16, optValueLen);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ CALLED_GET_PARAM_PTR (void, optValueP, optValueLen, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketOptionGet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketOptionGet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketOptionGet");
+
+ // Int16 NetLibSocketOptionGet(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ // void *optValueP, UInt16 *optValueLenP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 level, UInt16 option,"
+ "void *optValueP, UInt16 *optValueLenP,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, level);
+ CALLED_GET_PARAM_VAL (UInt16, option);
+ CALLED_GET_PARAM_REF (UInt16, optValueLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ CALLED_GET_PARAM_PTR (void, optValueP, *optValueLenP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tlevel = 0x%08X", (long) level);
+ PRINTF ("\toption = 0x%08X", (long) option);
+ PRINTF ("\toptValueP = 0x%08X", (long) (void*) optValueP);
+ PRINTF ("\toptValueLenP = 0x%08X", (long) *optValueLenP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketOptionGet (libRefNum,
+ socket, (NetSocketOptLevelEnum) (UInt16) level,
+ (NetSocketOptEnum) (UInt16) option, optValueP,
+ optValueLenP, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (optValueP);
+ CALLED_PUT_PARAM_REF (optValueLenP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketOptionGet (void)
+{
+ // Int16 NetLibSocketOptionGet(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 /*NetSocketOptLevelEnum*/ level, UInt16 /*NetSocketOptEnum*/ option,
+ // void *optValueP, UInt16 *optValueLenP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 level, UInt16 option,"
+ "void *optValueP, UInt16 *optValueLenP,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_VAL (UInt16, level);
+// CALLED_GET_PARAM_VAL (UInt16, option);
+ CALLED_GET_PARAM_REF (UInt16, optValueLenP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ CALLED_GET_PARAM_PTR (void, optValueP, *optValueLenP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+ PRINTF ("\t*optValueLenP = 0x%08X", (long) *optValueLenP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketBind
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketBind (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketBind");
+
+ // Int16 NetLibSocketBind(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_VAL (Int16, addrLen);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tsockAddr.family = 0x%04X", (uint16) (*sockAddrP).family);
+ PRINTF ("\tsockAddr.port = %s", PrvGetPortString (*sockAddrP));
+ PRINTF ("\tsockAddr.address = %s", PrvGetDottedIPString (*sockAddrP));
+ PRINTF ("\taddrLen = 0x%08X", (long) addrLen);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketBind (libRefNum, socket,
+ sockAddrP, addrLen, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ if (result == 0)
+ {
+ CALLED_PUT_PARAM_REF (sockAddrP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketBind (void)
+{
+ // Int16 NetLibSocketBind(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int16, addrLen);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketConnect
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketConnect (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketConnect");
+
+ // Int16 NetLibSocketConnect(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_VAL (Int16, addrLen);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tsockAddr.family = 0x%04X", (uint16) (*sockAddrP).family);
+ PRINTF ("\tsockAddr.port = %s", PrvGetPortString (*sockAddrP));
+ PRINTF ("\tsockAddr.address = %s", PrvGetDottedIPString (*sockAddrP));
+ PRINTF ("\taddrLen = 0x%08X", (long) addrLen);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketConnect (libRefNum,
+ socket, sockAddrP, addrLen, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ if (result == 0)
+ {
+ CALLED_PUT_PARAM_REF (sockAddrP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketConnect (void)
+{
+ // Int16 NetLibSocketConnect(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 addrLen, Int32 timeout, "
+ "Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int16, addrLen);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketListen
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketListen (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketListen");
+
+ // Int16 NetLibSocketListen(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 queueLen, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 queueLen, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, queueLen);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tqueueLen = 0x%08X", (long) queueLen);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketListen (libRefNum,
+ socket, queueLen, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketListen (void)
+{
+ // Int16 NetLibSocketListen(UInt16 libRefNum, NetSocketRef socket,
+ // UInt16 queueLen, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "UInt16 queueLen, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_VAL (UInt16, queueLen);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketAccept
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketAccept (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketAccept");
+
+ // Int16 NetLibSocketAccept(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 *addrLenP, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 *addrLenP, Int32 timeout,"
+ "Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (Int16, addrLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\taddrLen = 0x%08X", (long) *addrLenP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketAccept (libRefNum,
+ socket, sockAddrP, addrLenP, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ if (result >= 0)
+ {
+ CALLED_PUT_PARAM_REF (sockAddrP);
+ CALLED_PUT_PARAM_REF (addrLenP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketAccept (void)
+{
+ // Int16 NetLibSocketAccept(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *sockAddrP, Int16 *addrLenP, Int32 timeout,
+ // Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *sockAddrP, Int16 *addrLenP, Int32 timeout,"
+ "Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, sockAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_REF (Int16, addrLenP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+ PRINTF ("\tsockAddr.family = 0x%04X", (uint16) (*sockAddrP).family);
+ PRINTF ("\tsockAddr.port = %s", PrvGetPortString (*sockAddrP));
+ PRINTF ("\tsockAddr.address = %s", PrvGetDottedIPString (*sockAddrP));
+ PRINTF ("\taddrLen = 0x%08X", (long) *addrLenP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketShutdown
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketShutdown (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketShutdown");
+
+ // Int16 NetLibSocketShutdown(UInt16 libRefNum, NetSocketRef socket,
+ // Int16 /*NetSocketDirEnum*/ direction, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket, "
+ "Int16 direction, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (Int16, direction);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tdirection = 0x%08X", (long) direction);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketShutdown (libRefNum,
+ socket, direction, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketShutdown (void)
+{
+ // Int16 NetLibSocketShutdown(UInt16 libRefNum, NetSocketRef socket,
+ // Int16 /*NetSocketDirEnum*/ direction, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket, "
+ "Int16 direction, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_VAL (Int16, direction);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSendPB
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSendPB (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSendPB");
+
+ // Int16 NetLibSendPB(UInt16 libRefNum, NetSocketRef socket,
+ // NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetIOParamType, pbP, Marshal::kInput);
+ CALLED_GET_PARAM_VAL (UInt16, flags);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tflags = 0x%08X", (long) flags);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SendPB (libRefNum,
+ socket, pbP, flags, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (pbP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSendPB (void)
+{
+ // Int16 NetLibSendPB(UInt16 libRefNum, NetSocketRef socket,
+ // NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_REF (NetIOParamType, pbP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (UInt16, flags);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSend
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSend (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSend");
+
+ // Int16 NetLibSend(UInt16 libRefNum, NetSocketRef socket,
+ // void *bufP, UInt16 bufLen, UInt16 flags,
+ // void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *bufP, UInt16 bufLen, UInt16 flags,"
+ "void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, bufLen);
+ CALLED_GET_PARAM_VAL (UInt16, flags);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, toAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_VAL (UInt16, toLen);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+// PRINTF ("\tbufP = 0x%08X", (long) bufP);
+ PRINTF ("\tbufLen = 0x%08X", (long) bufLen);
+ PRINTF ("\tflags = 0x%08X", (long) flags);
+// PRINTF ("\ttoAddrP = 0x%08X", (long) toAddrP);
+ PRINTF ("\ttoLen = 0x%08X", (long) toLen);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::Send (libRefNum, socket,
+ bufP, bufLen, flags, toAddrP, toLen, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (bufP);
+ CALLED_PUT_PARAM_REF (toAddrP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSend (void)
+{
+ // Int16 NetLibSend(UInt16 libRefNum, NetSocketRef socket,
+ // void *bufP, UInt16 bufLen, UInt16 flags,
+ // void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *bufP, UInt16 bufLen, UInt16 flags,"
+ "void *toAddrP, UInt16 toLen, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, bufLen);
+// CALLED_GET_PARAM_VAL (UInt16, flags);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, toAddrP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (UInt16, toLen);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibReceivePB
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibReceivePB (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibReceivePB");
+
+ // Int16 NetLibReceivePB(UInt16 libRefNum, NetSocketRef socket,
+ // NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetIOParamType, pbP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (UInt16, flags);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+// PRINTF ("\tpbP = 0x%08X", (long) pbP);
+ PRINTF ("\tflags = 0x%08X", (long) flags);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::ReceivePB (libRefNum,
+ socket, pbP, flags, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (pbP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibReceivePB (void)
+{
+ // Int16 NetLibReceivePB(UInt16 libRefNum, NetSocketRef socket,
+ // NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetIOParamType *pbP, UInt16 flags, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+// CALLED_GET_PARAM_REF (NetIOParamType, pbP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (UInt16, flags);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibReceive
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibReceive (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibReceive");
+
+ // Int16 NetLibReceive(UInt16 libRefNum, NetSocketRef socket,
+ // void *bufP, UInt16 bufLen, UInt16 flags,
+ // void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *bufP, UInt16 bufLen, UInt16 flags, "
+ "void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, bufLen);
+ CALLED_GET_PARAM_VAL (UInt16, flags);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, fromAddrP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (UInt16, fromLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInOut);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+// PRINTF ("\tbufP = 0x%08X", (long) bufP);
+ PRINTF ("\tbufLen = 0x%08X", (long) bufLen);
+ PRINTF ("\tflags = 0x%08X", (long) flags);
+// PRINTF ("\tfromAddrP = 0x%08X", (long) fromAddrP);
+ PRINTF ("\tfromLen = 0x%08X", (long) *fromLenP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::Receive (libRefNum,
+ socket, bufP, bufLen, flags, fromAddrP, fromLenP, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (bufP);
+ CALLED_PUT_PARAM_REF (fromAddrP);
+ CALLED_PUT_PARAM_REF (fromLenP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibReceive (void)
+{
+ // Int16 NetLibReceive(UInt16 libRefNum, NetSocketRef socket,
+ // void *bufP, UInt16 bufLen, UInt16 flags,
+ // void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *bufP, UInt16 bufLen, UInt16 flags, "
+ "void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt16, bufLen);
+// CALLED_GET_PARAM_VAL (UInt16, flags);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, fromAddrP, Marshal::kInput);
+// CALLED_GET_PARAM_REF (UInt16, fromLenP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+
+ if (LogNetLibData () && (((long) *errP) == 0) && (result > 0))
+ {
+ LogAppendData (bufP, result, "Received Data");
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibDmReceive
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibDmReceive (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibDmReceive");
+
+ // Int16 NetLibDmReceive(UInt16 libRefNum, NetSocketRef socket,
+ // void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags,
+ // void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags, "
+ "void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt32, recordOffset);
+ CALLED_GET_PARAM_VAL (UInt16, rcvLen);
+ CALLED_GET_PARAM_VAL (UInt16, flags);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, fromAddrP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (UInt16, fromLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ CALLED_GET_PARAM_PTR (void, recordP, rcvLen + recordOffset, Marshal::kInOut);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::DmReceive (libRefNum,
+ socket, recordP, recordOffset, rcvLen, flags,
+ fromAddrP, fromLenP, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (recordP);
+ CALLED_PUT_PARAM_REF (fromAddrP);
+ CALLED_PUT_PARAM_REF (fromLenP);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibDmReceive (void)
+{
+ // Int16 NetLibDmReceive(UInt16 libRefNum, NetSocketRef socket,
+ // void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags,
+ // void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "void *recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags, "
+ "void *fromAddrP, UInt16 *fromLenP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_VAL (UInt32, recordOffset);
+ CALLED_GET_PARAM_VAL (UInt16, rcvLen);
+// CALLED_GET_PARAM_VAL (UInt16, flags);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, fromAddrP, Marshal::kInput);
+// CALLED_GET_PARAM_REF (UInt16, fromLenP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ CALLED_GET_PARAM_PTR (void, recordP, recordOffset + rcvLen, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSelect
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSelect (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSelect");
+
+ // Int16 NetLibSelect(UInt16 libRefNum, UInt16 width, NetFDSetType *readFDs,
+ // NetFDSetType *writeFDs, NetFDSetType *exceptFDs,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, UInt16 width, NetFDSetType *readFDs, "
+ "NetFDSetType *writeFDs, NetFDSetType *exceptFDs,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, width);
+ CALLED_GET_PARAM_REF (NetFDSetType, readFDs, Marshal::kInOut);
+ CALLED_GET_PARAM_REF (NetFDSetType, writeFDs, Marshal::kInOut);
+ CALLED_GET_PARAM_REF (NetFDSetType, exceptFDs, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\twidth = 0x%08X", (long) width);
+ PRINTF ("\treadFDs = 0x%08X", (long) *readFDs);
+ PRINTF ("\twriteFDs = 0x%08X", (long) *writeFDs);
+ PRINTF ("\texceptFDs = 0x%08X", (long) *exceptFDs);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::Select (libRefNum,
+ width, readFDs, writeFDs, exceptFDs, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (readFDs);
+ CALLED_PUT_PARAM_REF (writeFDs);
+ CALLED_PUT_PARAM_REF (exceptFDs);
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSelect (void)
+{
+ // Int16 NetLibSelect(UInt16 libRefNum, UInt16 width, NetFDSetType *readFDs,
+ // NetFDSetType *writeFDs, NetFDSetType *exceptFDs,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, UInt16 width, NetFDSetType *readFDs, "
+ "NetFDSetType *writeFDs, NetFDSetType *exceptFDs,"
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (UInt16, width);
+ CALLED_GET_PARAM_REF (NetFDSetType, readFDs, Marshal::kInput);
+ CALLED_GET_PARAM_REF (NetFDSetType, writeFDs, Marshal::kInput);
+ CALLED_GET_PARAM_REF (NetFDSetType, exceptFDs, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+ PRINTF ("\treadFDs = 0x%08X", (long) *readFDs);
+ PRINTF ("\twriteFDs = 0x%08X", (long) *writeFDs);
+ PRINTF ("\texceptFDs = 0x%08X", (long) *exceptFDs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibMaster
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibMaster (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibMaster");
+
+ // Err NetLibMaster(UInt16 libRefNum, UInt16 cmd, NetMasterPBPtr pbP,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 cmd, NetMasterPBPtr pbP,"
+ "Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibMaster (void)
+{
+ // Err NetLibMaster(UInt16 libRefNum, UInt16 cmd, NetMasterPBPtr pbP,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 cmd, NetMasterPBPtr pbP,"
+ "Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibGetHostByName
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibGetHostByName (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibGetHostByName");
+
+ // NetHostInfoPtr NetLibGetHostByName(UInt16 libRefNum, Char *nameP,
+ // NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetHostInfoPtr", "UInt16 libRefNum, Char *nameP, "
+ "NetHostInfoBufPtr bufP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_STR (Char, nameP);
+ CALLED_GET_PARAM_REF (NetHostInfoBufType, bufP, Marshal::kOutput);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tnameP = %s", (Char*) nameP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ NetHostInfoPtr p = Platform_NetLib::GetHostByName (libRefNum,
+ nameP, bufP, timeout, errP);
+ emuptr result = p ? (emuptr) bufP + offsetof (NetHostInfoBufType, hostInfo) : EmMemNULL;
+ PUT_RESULT_VAL (emuptr, result);
+
+ // Return any pass-by-reference values.
+ // bufP is a complex type with internal pointers and such. We
+ // *can't* copy the contents back into emulated memory if they
+ // are uninitialized. Check for errors before attempting that.
+ if (result != EmMemNULL)
+ {
+ CALLED_PUT_PARAM_REF (nameP);
+ CALLED_PUT_PARAM_REF (bufP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibGetHostByName (void)
+{
+ // NetHostInfoPtr NetLibGetHostByName(UInt16 libRefNum, Char *nameP,
+ // NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetHostInfoPtr", "UInt16 libRefNum, Char *nameP, "
+ "NetHostInfoBufPtr bufP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_STR (Char, nameP);
+// CALLED_GET_PARAM_REF (NetHostInfoBufType, bufP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_PTR ();
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+
+ NetHostInfoBufType hostInfo;
+ Marshal::GetNetHostInfoBufType (result, hostInfo);
+// PRINTF ("\t\tname = %s", hostInfo.name);
+// PRINTF ("\t\taddress = 0x%08X", hostInfo.address[0]);
+
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSettingGet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSettingGet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSettingGet");
+
+ // Err NetLibSettingGet(UInt16 libRefNum,
+ // UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 setting, void *valueP, UInt16 *valueLenP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSettingGet (void)
+{
+ // Err NetLibSettingGet(UInt16 libRefNum,
+ // UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 setting, void *valueP, UInt16 *valueLenP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSettingSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSettingSet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSettingSet");
+
+ // Err NetLibSettingSet(UInt16 libRefNum,
+ // UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 setting, void *valueP, UInt16 valueLen");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSettingSet (void)
+{
+ // Err NetLibSettingSet(UInt16 libRefNum,
+ // UInt16 /*NetSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 setting, void *valueP, UInt16 valueLen");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFAttach
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFAttach (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFAttach");
+
+ // Err NetLibIFAttach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance, Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFAttach (void)
+{
+ // Err NetLibIFAttach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance, Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFDetach
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFDetach (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFDetach");
+
+ // Err NetLibIFDetach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFDetach (void)
+{
+ // Err NetLibIFDetach(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFGet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFGet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFGet");
+
+ // Err NetLibIFGet(UInt16 libRefNum, UInt16 index, UInt32 *ifCreatorP,
+ // UInt16 *ifInstanceP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index, UInt32 *ifCreatorP, "
+ "UInt16 *ifInstanceP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFGet (void)
+{
+ // Err NetLibIFGet(UInt16 libRefNum, UInt16 index, UInt32 *ifCreatorP,
+ // UInt16 *ifInstanceP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index, UInt32 *ifCreatorP, "
+ "UInt16 *ifInstanceP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFSettingGet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFSettingGet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFSettingGet");
+
+ // Err NetLibIFSettingGet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "UInt16 setting, void *valueP, UInt16 *valueLenP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFSettingGet (void)
+{
+ // Err NetLibIFSettingGet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 *valueLenP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "UInt16 setting, void *valueP, UInt16 *valueLenP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFSettingSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFSettingSet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFSettingSet");
+
+ // Err NetLibIFSettingSet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "UInt16 setting, void *valueP, UInt16 valueLen");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFSettingSet (void)
+{
+ // Err NetLibIFSettingSet(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // UInt16 /*NetIFSettingEnum*/ setting, void *valueP, UInt16 valueLen)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,"
+ "UInt16 setting, void *valueP, UInt16 valueLen");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFUp
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFUp (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFUp");
+
+ // Err NetLibIFUp(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFUp (void)
+{
+ // Err NetLibIFUp(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibIFDown
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibIFDown (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibIFDown");
+
+ // Err NetLibIFDown(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance, Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibIFDown (void)
+{
+ // Err NetLibIFDown(UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance,
+ // Int32 timeout)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt32 ifCreator, UInt16 ifInstance, Int32 timeout");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibGetHostByAddr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibGetHostByAddr (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibGetHostByAddr");
+
+ // NetHostInfoPtr NetLibGetHostByAddr(UInt16 libRefNum, UInt8 *addrP, UInt16 len, UInt16 type,
+ // NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetHostInfoPtr", "UInt16 libRefNum, UInt8 *addrP, UInt16 len, UInt16 type,"
+ "NetHostInfoBufPtr bufP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, len);
+ CALLED_GET_PARAM_PTR (UInt8, addrP, len, Marshal::kInput);
+ CALLED_GET_PARAM_VAL (UInt16, type);
+ CALLED_GET_PARAM_REF (NetHostInfoBufType, bufP, Marshal::kOutput);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ NetHostInfoPtr p = Platform_NetLib::GetHostByAddr (libRefNum,
+ (UInt8*) addrP, len, type, bufP, timeout, errP);
+ emuptr result = p ? (emuptr) bufP + offsetof (NetHostInfoBufType, hostInfo) : EmMemNULL;
+ PUT_RESULT_VAL (emuptr, result);
+
+ // Return any pass-by-reference values.
+ // bufP is a complex type with internal pointers and such. We
+ // *can't* copy the contents back into emulated memory if they
+ // are uninitialized. Check for errors before attempting that.
+ if (result != EmMemNULL)
+ {
+ CALLED_PUT_PARAM_REF (addrP);
+ CALLED_PUT_PARAM_REF (bufP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibGetHostByAddr (void)
+{
+ // NetHostInfoPtr NetLibGetHostByAddr(UInt16 libRefNum, UInt8 *addrP, UInt16 len, UInt16 type,
+ // NetHostInfoBufPtr bufP, Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetHostInfoPtr", "UInt16 libRefNum, UInt8 *addrP, UInt16 len, UInt16 type,"
+ "NetHostInfoBufPtr bufP, Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_REF (NetSocketAddrType, addrP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (UInt16, len);
+// CALLED_GET_PARAM_VAL (UInt16, type);
+// CALLED_GET_PARAM_REF (NetHostInfoBufType, bufP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_PTR ();
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibGetServByName
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibGetServByName (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibGetServByName");
+
+ // NetServInfoPtr NetLibGetServByName(UInt16 libRefNum, const Char *servNameP,
+ // const Char *protoNameP, NetServInfoBufPtr bufP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetServInfoPtr", "UInt16 libRefNum, const Char *servNameP, "
+ "const Char *protoNameP, NetServInfoBufPtr bufP, "
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_STR (Char, servNameP);
+ CALLED_GET_PARAM_STR (Char, protoNameP);
+ CALLED_GET_PARAM_REF (NetServInfoBufType, bufP, Marshal::kOutput);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tservNameP = %s", (Char*) servNameP);
+ PRINTF ("\tprotoNameP = %s", (Char*) protoNameP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ NetServInfoPtr p = Platform_NetLib::GetServByName (libRefNum,
+ servNameP, protoNameP, bufP, timeout, errP);
+ emuptr result = p ? (emuptr) bufP + offsetof (NetServInfoBufType, servInfo) : EmMemNULL;
+ PUT_RESULT_VAL (emuptr, result);
+
+ // Return any pass-by-reference values.
+ // bufP is a complex type with internal pointers and such. We
+ // *can't* copy the contents back into emulated memory if they
+ // are uninitialized. Check for errors before attempting that.
+ if (result != EmMemNULL)
+ {
+ CALLED_PUT_PARAM_REF (servNameP);
+ CALLED_PUT_PARAM_REF (protoNameP);
+ CALLED_PUT_PARAM_REF (bufP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibGetServByName (void)
+{
+ // NetServInfoPtr NetLibGetServByName(UInt16 libRefNum, const Char *servNameP,
+ // const Char *protoNameP, NetServInfoBufPtr bufP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("NetServInfoPtr", "UInt16 libRefNum, const Char *servNameP, "
+ "const Char *protoNameP, NetServInfoBufPtr bufP, "
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_STR (Char, servNameP);
+ CALLED_GET_PARAM_STR (Char, protoNameP);
+// CALLED_GET_PARAM_REF (NetServInfoBufType, bufP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_PTR ();
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+
+ NetServInfoBufType servInfo;
+ Marshal::GetNetServInfoBufType (result, servInfo);
+// PRINTF ("\t\tname = %s", servInfo.name);
+// PRINTF ("\t\tport = 0x%04X", (UInt16) servInfo.servInfo.port);
+// PRINTF ("\t\tprotoName = %s", servInfo.protoName);
+
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibSocketAddr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibSocketAddr (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibSocketAddr");
+
+ // Int16 NetLibSocketAddr(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *locAddrP, Int16 *locAddrLenP,
+ // NetSocketAddrType *remAddrP, Int16 *remAddrLenP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *locAddrP, Int16 *locAddrLenP, "
+ "NetSocketAddrType *remAddrP, Int16 *remAddrLenP, "
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, locAddrP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (Int16, locAddrLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, remAddrP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (Int16, remAddrLenP, Marshal::kInOut);
+ CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tsocket = 0x%08X", (long) socket);
+ PRINTF ("\tlocAddrLen = 0x%08X", (long) *locAddrLenP);
+ PRINTF ("\tremAddrLen = 0x%08X", (long) *remAddrLenP);
+ PRINTF ("\ttimeout = 0x%08X", (long) timeout);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Int16 result = Platform_NetLib::SocketAddr (libRefNum,
+ socket, locAddrP, locAddrLenP, remAddrP, remAddrLenP, timeout, errP);
+ PUT_RESULT_VAL (Int16, result);
+
+ // Return any pass-by-reference values.
+ if (result == 0)
+ {
+ CALLED_PUT_PARAM_REF (locAddrP);
+ CALLED_PUT_PARAM_REF (locAddrLenP);
+ CALLED_PUT_PARAM_REF (remAddrP);
+ CALLED_PUT_PARAM_REF (remAddrLenP);
+ }
+ CALLED_PUT_PARAM_REF (errP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibSocketAddr (void)
+{
+ // Int16 NetLibSocketAddr(UInt16 libRefNum, NetSocketRef socket,
+ // NetSocketAddrType *locAddrP, Int16 *locAddrLenP,
+ // NetSocketAddrType *remAddrP, Int16 *remAddrLenP,
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, NetSocketRef socket,"
+ "NetSocketAddrType *locAddrP, Int16 *locAddrLenP, "
+ "NetSocketAddrType *remAddrP, Int16 *remAddrLenP, "
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (NetSocketRef, socket);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, locAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_REF (Int16, locAddrLenP, Marshal::kInput);
+ CALLED_GET_PARAM_REF (NetSocketAddrType, remAddrP, Marshal::kInput);
+ CALLED_GET_PARAM_REF (Int16, remAddrLenP, Marshal::kInput);
+// CALLED_GET_PARAM_VAL (Int32, timeout);
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+ PRINTF ("\tlocAddr.family = 0x%04X", (uint16) (*locAddrP).family);
+ PRINTF ("\tlocAddr.port = %s", PrvGetPortString (*locAddrP));
+ PRINTF ("\tlocAddr.address = %s", PrvGetDottedIPString (*locAddrP));
+ PRINTF ("\tlocAddrLen = 0x%08X", (long) *locAddrLenP);
+ PRINTF ("\tremAddr.family = 0x%04X", (uint16) (*remAddrP).family);
+ PRINTF ("\tremAddr.port = %s", PrvGetPortString (*remAddrP));
+ PRINTF ("\tremAddr.address = %s", PrvGetDottedIPString (*remAddrP));
+ PRINTF ("\tremAddrLen = 0x%08X", (long) *remAddrLenP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibFinishCloseWait
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibFinishCloseWait (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibFinishCloseWait");
+
+ // Err NetLibFinishCloseWait(UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::FinishCloseWait (libRefNum);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibFinishCloseWait (void)
+{
+ // Err NetLibFinishCloseWait(UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibGetMailExchangeByName
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibGetMailExchangeByName (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibGetMailExchangeByName");
+
+ // Int16 NetLibGetMailExchangeByName(UInt16 libRefNum, Char *mailNameP,
+ // UInt16 maxEntries,
+ // Char hostNames[][netDNSMaxDomainName+1], UInt16 priorities[],
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, Char *mailNameP, "
+ "UInt16 maxEntries, "
+ "Char** hostNames, UInt16* priorities, "
+ "Int32 timeout, Err *errP");
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibGetMailExchangeByName (void)
+{
+ // Int16 NetLibGetMailExchangeByName(UInt16 libRefNum, Char *mailNameP,
+ // UInt16 maxEntries,
+ // Char hostNames[][netDNSMaxDomainName+1], UInt16 priorities[],
+ // Int32 timeout, Err *errP)
+
+ CALLED_SETUP ("Int16", "UInt16 libRefNum, Char *mailNameP, "
+ "UInt16 maxEntries, "
+ "Char** hostNames, UInt16* priorities, "
+ "Int32 timeout, Err *errP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Int16);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*errP = %s (0x%04X)", PrvGetErrorString (*errP), (long) *errP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibOpenCount
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibOpenCount (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibOpenCount");
+
+ // Err NetLibOpenCount (UInt16 libRefNum, UInt16 *countP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 *countP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_REF (UInt16, countP, Marshal::kOutput);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::OpenCount (libRefNum, countP);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (countP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibOpenCount (void)
+{
+ // Err NetLibOpenCount (UInt16 libRefNum, UInt16 *countP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 *countP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_REF (UInt16, countP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\tcount = 0x%08X", (long) *countP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibTracePrintF
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibTracePrintF (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibTracePrintF");
+
+ // Err NetLibTracePrintF(UInt16 libRefNum, Char *formatStr, ...)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Char *formatStr");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibTracePrintF (void)
+{
+ // Err NetLibTracePrintF(UInt16 libRefNum, Char *formatStr, ...)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Char *formatStr");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibTracePutS
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibTracePutS (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibTracePutS");
+
+ // Err NetLibTracePutS(UInt16 libRefNum, Char *strP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Char *strP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibTracePutS (void)
+{
+ // Err NetLibTracePutS(UInt16 libRefNum, Char *strP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Char *strP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibOpenIfCloseWait
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibOpenIfCloseWait (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibOpenIfCloseWait");
+
+ // Err NetLibOpenIfCloseWait(UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::OpenIfCloseWait (libRefNum);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibOpenIfCloseWait (void)
+{
+ // Err NetLibOpenIfCloseWait(UInt16 libRefNum)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibHandlePowerOff
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibHandlePowerOff (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibHandlePowerOff");
+
+ // Err NetLibHandlePowerOff (UInt16 libRefNum, SysEventType *eventP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, SysEventType *eventP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_REF (EventType, eventP, Marshal::kInput);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::HandlePowerOff (libRefNum, eventP);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (eventP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibHandlePowerOff (void)
+{
+ // Err NetLibHandlePowerOff (UInt16 libRefNum, SysEventType *eventP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, SysEventType *eventP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_REF (EventType, eventP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConnectionRefresh
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConnectionRefresh (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConnectionRefresh");
+
+ // Err NetLibConnectionRefresh(UInt16 libRefNum, Boolean refresh,
+ // UInt8 *allInterfacesUpP, UInt16 *netIFErrP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Boolean refresh, "
+ "UInt8 *allInterfacesUpP, UInt16 *netIFErrP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (Boolean, refresh);
+ CALLED_GET_PARAM_REF (Boolean, allInterfacesUpP, Marshal::kOutput);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\trefresh = 0x%08X", (long) refresh);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::ConnectionRefresh (libRefNum,
+ refresh, allInterfacesUpP, netIFErrP);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (allInterfacesUpP);
+ CALLED_PUT_PARAM_REF (netIFErrP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConnectionRefresh (void)
+{
+ // Err NetLibConnectionRefresh(UInt16 libRefNum, Boolean refresh,
+ // UInt8 *allInterfacesUpP, UInt16 *netIFErrP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, Boolean refresh, "
+ "UInt8 *allInterfacesUpP, UInt16 *netIFErrP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (Boolean, refresh);
+ CALLED_GET_PARAM_REF (Boolean, allInterfacesUpP, Marshal::kInput);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*netIFErrP = %s (0x%04X)", PrvGetErrorString (*netIFErrP), (long) *netIFErrP);
+ PRINTF ("\t*allInterfacesUpP = 0x%08X", (long) *allInterfacesUpP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibOpenConfig
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibOpenConfig (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibOpenConfig");
+
+ // Err NetLibOpenConfig( UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags,
+ // UInt16 *netIFErrP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags,"
+ "UInt16 *netIFErrP");
+
+ // Get the stack-based parameters.
+ CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+ CALLED_GET_PARAM_VAL (UInt16, configIndex);
+ CALLED_GET_PARAM_VAL (UInt32, openFlags);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrP, Marshal::kOutput);
+
+ // Examine the parameters
+ PRINTF ("\tconfigIndex = 0x%08X", (long) configIndex);
+ PRINTF ("\topenFlags = 0x%08X", (long) openFlags);
+
+ if (Platform_NetLib::Redirecting ())
+ {
+ PRINTF ("\t-->Executing host version");
+
+ // Call the host function.
+ Err result = Platform_NetLib::OpenConfig (libRefNum,
+ configIndex, openFlags, netIFErrP);
+ PUT_RESULT_VAL (Err, result);
+
+ // Return any pass-by-reference values.
+ CALLED_PUT_PARAM_REF (netIFErrP);
+
+ return kSkipROM;
+ }
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibOpenConfig (void)
+{
+ // Err NetLibOpenConfig( UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags,
+ // UInt16 *netIFErrP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags,"
+ "UInt16 *netIFErrP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+// CALLED_GET_PARAM_VAL (UInt16, configIndex);
+// CALLED_GET_PARAM_VAL (UInt16, openFlags);
+ CALLED_GET_PARAM_REF (UInt16, netIFErrP, Marshal::kInput);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+ PRINTF ("\t*netIFErrP = %s (0x%04X)", PrvGetErrorString (*netIFErrP), (long) *netIFErrP);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigMakeActive
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigMakeActive (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigMakeActive");
+
+ // Err NetLibConfigMakeActive( UInt16 libRefNum, UInt16 configIndex)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigMakeActive (void)
+{
+ // Err NetLibConfigMakeActive( UInt16 libRefNum, UInt16 configIndex)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigList
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigList (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigList");
+
+ // Err NetLibConfigList( UInt16 libRefNum, NetConfigNameType nameArray[],
+ // UInt16 *arrayEntriesP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNameType* nameArray,"
+ "UInt16 *arrayEntriesP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigList (void)
+{
+ // Err NetLibConfigList( UInt16 libRefNum, NetConfigNameType nameArray[],
+ // UInt16 *arrayEntriesP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNameType* nameArray,"
+ "UInt16 *arrayEntriesP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigIndexFromName
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigIndexFromName (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigIndexFromName");
+
+ // Err NetLibConfigIndexFromName( UInt16 libRefNum, NetConfigNamePtr nameP,
+ // UInt16 *indexP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNamePtr nameP, UInt16 *indexP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigIndexFromName (void)
+{
+ // Err NetLibConfigIndexFromName( UInt16 libRefNum, NetConfigNamePtr nameP,
+ // UInt16 *indexP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNamePtr nameP, UInt16 *indexP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigDelete
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigDelete (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigDelete");
+
+ // Err NetLibConfigDelete( UInt16 libRefNum, UInt16 index)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigDelete (void)
+{
+ // Err NetLibConfigDelete( UInt16 libRefNum, UInt16 index)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigSaveAs
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigSaveAs (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigSaveAs");
+
+ // Err NetLibConfigSaveAs( UInt16 libRefNum, NetConfigNamePtr nameP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNamePtr nameP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigSaveAs (void)
+{
+ // Err NetLibConfigSaveAs( UInt16 libRefNum, NetConfigNamePtr nameP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, NetConfigNamePtr nameP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigRename
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigRename (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigRename");
+
+ // Err NetLibConfigRename( UInt16 libRefNum, UInt16 index,
+ // NetConfigNamePtr newNameP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index, NetConfigNamePtr newNameP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigRename (void)
+{
+ // Err NetLibConfigRename( UInt16 libRefNum, UInt16 index,
+ // NetConfigNamePtr newNameP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 index, NetConfigNamePtr newNameP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigAliasSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigAliasSet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigAliasSet");
+
+ // Err NetLibConfigAliasSet( UInt16 libRefNum, UInt16 configIndex,
+ // UInt16 aliasToIndex)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex, UInt16 aliasToIndex");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigAliasSet (void)
+{
+ // Err NetLibConfigAliasSet( UInt16 libRefNum, UInt16 configIndex,
+ // UInt16 aliasToIndex)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 configIndex, UInt16 aliasToIndex");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibHeadpatch::NetLibConfigAliasGet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+CallROMType NetLibHeadpatch::NetLibConfigAliasGet (void)
+{
+ PRINTF ("----------------------------------------");
+ PRINTF ("NetLibConfigAliasGet");
+
+ // Err NetLibConfigAliasGet( UInt16 libRefNum, UInt16 aliasIndex,
+ // UInt16 *indexP, Boolean *isAnotherAliasP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 aliasIndex, UInt16 *indexP, Boolean *isAnotherAliasP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Examine the parameters
+
+ PRINTF ("\t-->Executing ROM version");
+ return kExecuteROM;
+}
+
+void NetLibTailpatch::NetLibConfigAliasGet (void)
+{
+ // Err NetLibConfigAliasGet( UInt16 libRefNum, UInt16 aliasIndex,
+ // UInt16 *indexP, Boolean *isAnotherAliasP)
+
+ CALLED_SETUP ("Err", "UInt16 libRefNum, UInt16 aliasIndex, UInt16 *indexP, Boolean *isAnotherAliasP");
+
+ // Get the stack-based parameters.
+// CALLED_GET_PARAM_VAL (UInt16, libRefNum);
+
+ // Get the result.
+ GET_RESULT_VAL (Err);
+
+ // Examine the results.
+ PRINTF ("\tResult = 0x%08X", result);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetOptLevelString
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+#define DOCASE(name) case name: return #name;
+
+const char* PrvGetOptLevelString (NetSocketOptLevelEnum level)
+{
+ switch (level)
+ {
+ DOCASE (netSocketOptLevelIP)
+ DOCASE (netSocketOptLevelTCP)
+ DOCASE (netSocketOptLevelSocket)
+ }
+
+ return "Unknown NetSocketOptLevelEnum";
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetOptString
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+const char* PrvGetOptString (NetSocketOptLevelEnum level, NetSocketOptEnum opt)
+{
+ switch (level)
+ {
+ case netSocketOptLevelIP:
+ switch (opt)
+ {
+ DOCASE (netSocketOptIPOptions)
+
+// case netSocketOptTCPNoDelay: == 1 (netSocketOptIPOptions)
+ case netSocketOptTCPMaxSeg:
+
+// case netSocketOptSockDebug: == 1 (netSocketOptIPOptions)
+// case netSocketOptSockAcceptConn: == 2 (netSocketOptTCPMaxSeg)
+ case netSocketOptSockReuseAddr:
+ case netSocketOptSockKeepAlive:
+ case netSocketOptSockDontRoute:
+ case netSocketOptSockBroadcast:
+ case netSocketOptSockUseLoopback:
+ case netSocketOptSockLinger:
+ case netSocketOptSockOOBInLine:
+ case netSocketOptSockSndBufSize:
+ case netSocketOptSockRcvBufSize:
+ case netSocketOptSockSndLowWater:
+ case netSocketOptSockRcvLowWater:
+ case netSocketOptSockSndTimeout:
+ case netSocketOptSockRcvTimeout:
+ case netSocketOptSockErrorStatus:
+ case netSocketOptSockSocketType:
+ case netSocketOptSockNonBlocking:
+ case netSocketOptSockRequireErrClear:
+ case netSocketOptSockMultiPktAddr:
+ break;
+ }
+ break;
+
+ case netSocketOptLevelTCP:
+ switch (opt)
+ {
+// case netSocketOptIPOptions: == 1 (netSocketOptTCPNoDelay)
+// break;
+
+ DOCASE (netSocketOptTCPNoDelay)
+ DOCASE (netSocketOptTCPMaxSeg)
+
+// case netSocketOptSockDebug: == 1 (netSocketOptTCPNoDelay)
+// case netSocketOptSockAcceptConn: == 2 (netSocketOptTCPMaxSeg)
+ case netSocketOptSockReuseAddr:
+ case netSocketOptSockKeepAlive:
+ case netSocketOptSockDontRoute:
+ case netSocketOptSockBroadcast:
+ case netSocketOptSockUseLoopback:
+ case netSocketOptSockLinger:
+ case netSocketOptSockOOBInLine:
+ case netSocketOptSockSndBufSize:
+ case netSocketOptSockRcvBufSize:
+ case netSocketOptSockSndLowWater:
+ case netSocketOptSockRcvLowWater:
+ case netSocketOptSockSndTimeout:
+ case netSocketOptSockRcvTimeout:
+ case netSocketOptSockErrorStatus:
+ case netSocketOptSockSocketType:
+ case netSocketOptSockNonBlocking:
+ case netSocketOptSockRequireErrClear:
+ case netSocketOptSockMultiPktAddr:
+ break;
+ }
+ break;
+
+ case netSocketOptLevelSocket:
+ switch (opt)
+ {
+// case netSocketOptIPOptions:
+// case netSocketTCPNoDelay:
+// case netSocketTCPMaxSeg:
+// break;
+
+ DOCASE (netSocketOptSockDebug)
+ DOCASE (netSocketOptSockAcceptConn)
+ DOCASE (netSocketOptSockReuseAddr)
+ DOCASE (netSocketOptSockKeepAlive)
+ DOCASE (netSocketOptSockDontRoute)
+ DOCASE (netSocketOptSockBroadcast)
+ DOCASE (netSocketOptSockUseLoopback)
+ DOCASE (netSocketOptSockLinger)
+ DOCASE (netSocketOptSockOOBInLine)
+
+ DOCASE (netSocketOptSockSndBufSize)
+ DOCASE (netSocketOptSockRcvBufSize)
+ DOCASE (netSocketOptSockSndLowWater)
+ DOCASE (netSocketOptSockRcvLowWater)
+ DOCASE (netSocketOptSockSndTimeout)
+ DOCASE (netSocketOptSockRcvTimeout)
+ DOCASE (netSocketOptSockErrorStatus)
+ DOCASE (netSocketOptSockSocketType)
+
+ DOCASE (netSocketOptSockNonBlocking)
+ DOCASE (netSocketOptSockRequireErrClear)
+ DOCASE (netSocketOptSockMultiPktAddr)
+ }
+ break;
+ }
+
+ return "Unknown NetSocketOptEnum";
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetDottedIPString
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+const char* PrvGetDottedIPString (const NetSocketAddrType& addr)
+{
+ NetSocketAddrINType ipAddr = (const NetSocketAddrINType&) addr;
+ long tempIP = ntohl (ipAddr.addr);
+
+ static char dottedIPStr[20];
+
+ sprintf (dottedIPStr, "%ld.%ld.%ld.%ld",
+ ((tempIP >> 24) & 0xFF),
+ ((tempIP >> 16) & 0xFF),
+ ((tempIP >> 8) & 0xFF),
+ ((tempIP) & 0xFF));
+
+ return dottedIPStr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetPortString
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+const char* PrvGetPortString (const NetSocketAddrType& addr)
+{
+ NetSocketAddrINType ipAddr = (const NetSocketAddrINType&) addr;
+ UInt16 port = ntohs (ipAddr.port);
+
+ static char portStr[10];
+
+ sprintf (portStr, "0x%04X", port);
+
+ return portStr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetErrorString
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+const char* PrvGetErrorString (Err err)
+{
+ switch (err)
+ {
+ DOCASE (errNone)
+ DOCASE (netErrAlreadyOpen)
+ DOCASE (netErrNotOpen)
+ DOCASE (netErrStillOpen)
+ DOCASE (netErrParamErr)
+ DOCASE (netErrNoMoreSockets)
+ DOCASE (netErrOutOfResources)
+ DOCASE (netErrOutOfMemory)
+ DOCASE (netErrSocketNotOpen)
+ DOCASE (netErrSocketBusy)
+ DOCASE (netErrMessageTooBig)
+ DOCASE (netErrSocketNotConnected)
+ DOCASE (netErrNoInterfaces)
+ DOCASE (netErrBufTooSmall)
+ DOCASE (netErrUnimplemented)
+ DOCASE (netErrPortInUse)
+ DOCASE (netErrQuietTimeNotElapsed)
+ DOCASE (netErrInternal)
+ DOCASE (netErrTimeout)
+ DOCASE (netErrSocketAlreadyConnected)
+ DOCASE (netErrSocketClosedByRemote)
+ DOCASE (netErrOutOfCmdBlocks)
+ DOCASE (netErrWrongSocketType)
+ DOCASE (netErrSocketNotListening)
+ DOCASE (netErrUnknownSetting)
+ DOCASE (netErrInvalidSettingSize)
+ DOCASE (netErrPrefNotFound)
+ DOCASE (netErrInvalidInterface)
+ DOCASE (netErrInterfaceNotFound)
+ DOCASE (netErrTooManyInterfaces)
+ DOCASE (netErrBufWrongSize)
+ DOCASE (netErrUserCancel)
+ DOCASE (netErrBadScript)
+ DOCASE (netErrNoSocket)
+ DOCASE (netErrSocketRcvBufFull)
+ DOCASE (netErrNoPendingConnect)
+ DOCASE (netErrUnexpectedCmd)
+ DOCASE (netErrNoTCB)
+ DOCASE (netErrNilRemoteWindowSize)
+ DOCASE (netErrNoTimerProc)
+ DOCASE (netErrSocketInputShutdown)
+ DOCASE (netErrCmdBlockNotCheckedOut)
+ DOCASE (netErrCmdNotDone)
+ DOCASE (netErrUnknownProtocol)
+ DOCASE (netErrUnknownService)
+ DOCASE (netErrUnreachableDest)
+ DOCASE (netErrReadOnlySetting)
+ DOCASE (netErrWouldBlock)
+ DOCASE (netErrAlreadyInProgress)
+ DOCASE (netErrPPPTimeout)
+ DOCASE (netErrPPPBroughtDown)
+ DOCASE (netErrAuthFailure)
+ DOCASE (netErrPPPAddressRefused)
+ DOCASE (netErrDNSNameTooLong)
+ DOCASE (netErrDNSBadName)
+ DOCASE (netErrDNSBadArgs)
+ DOCASE (netErrDNSLabelTooLong)
+ DOCASE (netErrDNSAllocationFailure)
+ DOCASE (netErrDNSTimeout)
+ DOCASE (netErrDNSUnreachable)
+ DOCASE (netErrDNSFormat)
+ DOCASE (netErrDNSServerFailure)
+ DOCASE (netErrDNSNonexistantName)
+ DOCASE (netErrDNSNIY)
+ DOCASE (netErrDNSRefused)
+ DOCASE (netErrDNSImpossible)
+ DOCASE (netErrDNSNoRRS)
+ DOCASE (netErrDNSAborted)
+ DOCASE (netErrDNSBadProtocol)
+ DOCASE (netErrDNSTruncated)
+ DOCASE (netErrDNSNoRecursion)
+ DOCASE (netErrDNSIrrelevant)
+ DOCASE (netErrDNSNotInLocalCache)
+ DOCASE (netErrDNSNoPort)
+ DOCASE (netErrIPCantFragment)
+ DOCASE (netErrIPNoRoute)
+ DOCASE (netErrIPNoSrc)
+ DOCASE (netErrIPNoDst)
+ DOCASE (netErrIPktOverflow)
+ DOCASE (netErrTooManyTCPConnections)
+ DOCASE (netErrNoDNSServers)
+ DOCASE (netErrInterfaceDown)
+ DOCASE (netErrNoChannel)
+ DOCASE (netErrDieState)
+ DOCASE (netErrReturnedInMail)
+ DOCASE (netErrReturnedNoTransfer)
+ DOCASE (netErrReturnedIllegal)
+ DOCASE (netErrReturnedCongest)
+ DOCASE (netErrReturnedError)
+ DOCASE (netErrReturnedBusy)
+ DOCASE (netErrGMANState)
+ DOCASE (netErrQuitOnTxFail)
+ DOCASE (netErrFlexListFull)
+ DOCASE (netErrSenderMAN)
+ DOCASE (netErrIllegalType)
+ DOCASE (netErrIllegalState)
+ DOCASE (netErrIllegalFlags)
+ DOCASE (netErrIllegalSendlist)
+ DOCASE (netErrIllegalMPAKLength)
+ DOCASE (netErrIllegalAddressee)
+ DOCASE (netErrIllegalPacketClass)
+ DOCASE (netErrBufferLength)
+ DOCASE (netErrNiCdLowBattery)
+ DOCASE (netErrRFinterfaceFatal)
+ DOCASE (netErrIllegalLogout)
+ DOCASE (netErrAAARadioLoad)
+ DOCASE (netErrAntennaDown)
+ DOCASE (netErrNiCdCharging)
+ DOCASE (netErrAntennaWentDown)
+ DOCASE (netErrNotActivated)
+ DOCASE (netErrRadioTemp)
+ DOCASE (netErrConfigNotFound)
+ DOCASE (netErrConfigCantDelete)
+ DOCASE (netErrConfigTooMany)
+ DOCASE (netErrConfigBadName)
+ DOCASE (netErrConfigNotAlias)
+ DOCASE (netErrConfigCantPointToAlias)
+ DOCASE (netErrConfigEmpty)
+ DOCASE (netErrAlreadyOpenWithOtherConfig)
+ DOCASE (netErrConfigAliasErr)
+ DOCASE (netErrNoMultiPktAddr)
+ DOCASE (netErrOutOfPackets)
+ DOCASE (netErrMultiPktAddrReset)
+ DOCASE (netErrStaleMultiPktAddr)
+ }
+
+ return "Unknown Error Code";
+}
diff --git a/SrcShared/Patches/EmPatchModuleNetLib.h b/SrcShared/Patches/EmPatchModuleNetLib.h
new file mode 100644
index 0000000..72e09d0
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleNetLib.h
@@ -0,0 +1,27 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModuleNetLib_h
+#define EmPatchModuleNetLib_h
+
+#include "EmPatchModule.h"
+
+class EmPatchModuleNetLib : public EmPatchModule
+{
+ public:
+ EmPatchModuleNetLib (void);
+ virtual ~EmPatchModuleNetLib (void) {}
+};
+
+#endif // EmPatchModuleNetLib_h
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 (&currentCardNo, &currentDbID);
+
+ // 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;
+}
diff --git a/SrcShared/Patches/EmPatchModuleSys.h b/SrcShared/Patches/EmPatchModuleSys.h
new file mode 100644
index 0000000..dc59a03
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleSys.h
@@ -0,0 +1,271 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModuleSys_h
+#define EmPatchModuleSys_h
+
+#include "EmPatchModule.h"
+
+class EmPatchModuleSys : public EmPatchModule
+{
+ public:
+ EmPatchModuleSys();
+ virtual ~EmPatchModuleSys() {}
+};
+
+
+// ======================================================================
+// PatchModule for system functions.
+// ======================================================================
+
+class SysHeadpatch
+{
+ public:
+ static CallROMType UnmarkUIObjects (void); // CtlNewControl, FldNewField, FrmInitForm, FrmNewBitmap, FrmNewGadget, FrmNewGsi, FrmNewLabel, LstNewList, WinAddWindow, WinRemoveWindow
+ static CallROMType RecordTrapNumber (void); // EvtGetEvent & EvtGetPen
+
+ static CallROMType ClipboardGetItem (void);
+ static CallROMType DbgMessage (void);
+ static CallROMType DmCloseDatabase (void);
+ static CallROMType DmInit (void);
+ static CallROMType ErrDisplayFileLineMsg (void);
+ static CallROMType EvtAddEventToQueue (void);
+ static CallROMType EvtAddUniqueEventToQueue(void);
+ static CallROMType EvtEnqueueKey (void);
+ static CallROMType EvtEnqueuePenPoint (void);
+ static CallROMType ExgDoDialog (void);
+ static CallROMType FrmCustomAlert (void);
+ static CallROMType FrmDrawForm (void);
+ static CallROMType FrmPopupForm (void);
+ static CallROMType HostControl (void);
+ static CallROMType HwrBatteryLevel (void);
+ static CallROMType HwrBattery (void);
+ static CallROMType HwrDockStatus (void);
+ static CallROMType HwrGetROMToken (void);
+ static CallROMType HwrSleep (void);
+ static CallROMType PenOpen (void);
+ static CallROMType PrefSetAppPreferences (void);
+ static CallROMType SndDoCmd (void);
+ static CallROMType SysAppExit (void);
+ static CallROMType SysAppLaunch (void);
+ static CallROMType SysBinarySearch (void);
+ static CallROMType SysEvGroupWait (void);
+ static CallROMType SysFatalAlert (void);
+ static CallROMType SysLaunchConsole (void);
+ static CallROMType SysSemaphoreWait (void);
+ static CallROMType SysUIAppSwitch (void);
+ static CallROMType TblHandleEvent (void);
+};
+
+class SysTailpatch
+{
+ public:
+ static void MarkUIObjects (void); // CtlNewControl, FldNewField, FrmInitForm, FrmNewBitmap, FrmNewGadget, FrmNewGsi, FrmNewLabel, LstNewList, WinAddWindow, WinRemoveWindow
+
+ static void BmpCreate (void);
+ static void BmpDelete (void);
+ static void ClipboardAddItem (void);
+ static void ClipboardAppendItem (void);
+ static void DmGet1Resource (void);
+ static void DmGetResource (void);
+ static void EvtGetEvent (void);
+ static void EvtGetPen (void);
+ static void EvtGetSysEvent (void);
+ static void EvtSysEventAvail (void);
+ static void ExgReceive (void);
+ static void ExgSend (void);
+ static void FtrInit (void);
+ static void FtrSet (void);
+ static void HwrMemReadable (void);
+ static void HwrSleep (void);
+ static void SysAppStartup (void);
+ static void SysBinarySearch (void);
+ static void SysTaskCreate (void);
+ static void TblHandleEvent (void);
+ static void TimInit (void);
+ static void UIInitialize (void);
+ static void UIReset (void);
+};
+
+
+
+
+
+/* ===========================================================================
+ The following macros are used to help us generate patches to all the
+ Memory Manager functions. We patch the entire Memory Manager in order
+ to track when we are "in" the Memory Manager. We want to know this so
+ that we can extend special privileges to the Memory Manager when it
+ accesses memory; the Memory Manager can touch more of RAM than any other
+ executing code.
+
+ Since our patches mostly just increment and decrement a counter, most of
+ them are generated automatically with macros. I call these "simple"
+ head- and tailpatches. However, we patch a few other the other Memory
+ Manager functions for other reasons. We can't let the macros generate
+ simple patches for these functions and instead have to write them
+ ourselves, making sure to perform the same incrementing and decrementing
+ the simple functions would do. I call these patches "complex" head- and
+ tailpatches.
+
+ Therefore, there are four "categories" of patchings: functions for which
+ we want simple head- and tailpatches, functions for which we have a
+ complex headpatch but need a simple tailpatch, functions for which we
+ have a complex tailpatch but need a simple headpatch, and functions for
+ which we already have complex head- and tailpatches and don't need
+ simple patches.
+
+ (Actually, there is a fifth category: Memory Manager functions that we
+ don't want to treat as Memory Manager functions. The functions in this
+ category are MemSet, MemMove, and MemCmp. We don't want to extend to
+ these functions the same privileges that other Memory Manager functions
+ get.)
+
+ (And there's kind of a sixth category as well: non-Memory Manager
+ functions that we want to treat as Memory Manager functions. For
+ instance, DmWriteCheck grovels over Memory Manager data structures, so
+ we have to give it Memory Manager function privileges.
+ PrvFindMemoryLeaks is also a function like this, but since it's not in
+ the trap table, we can't patch it, and have to handle it differently.
+ See MetaMemory.cpp for this.)
+
+ The macros below divide the set of Memory Manager functions into the
+ four categories. Any function on any of the four lists will
+ automatically have generated for it declarations for head- and
+ tailpatches. Additionally, depending on which list it's on, it will
+ optionally have simple head- and tailpatch functions generated for it.
+=========================================================================== */
+
+// List of functions for which we want to automatically generate simple
+// head- and tailpatches.
+//
+// DmWriteCheck is on this list because it grovels over memory, making sure
+// everything is OK before it writes to the storage heap. ScrInit is on
+// this list because it calls MemMove to move the contents of the temporary
+// LCD buffer to the real one after it's been allocated; the source of this
+// move is a faux buffer out in the middle of an unallocated block.
+
+#define FOR_EACH_STUB_BOTHPATCH_FUNCTION(DO_TO_FUNCTION) \
+ DO_TO_FUNCTION(MemInit) \
+ DO_TO_FUNCTION(MemNumCards) \
+ DO_TO_FUNCTION(MemCardFormat) \
+ DO_TO_FUNCTION(MemCardInfo) \
+ DO_TO_FUNCTION(MemStoreInfo) \
+ DO_TO_FUNCTION(MemStoreSetInfo) \
+ DO_TO_FUNCTION(MemNumHeaps) \
+ DO_TO_FUNCTION(MemNumRAMHeaps) \
+ DO_TO_FUNCTION(MemHeapID) \
+ DO_TO_FUNCTION(MemHeapDynamic) \
+ DO_TO_FUNCTION(MemHeapFreeBytes) \
+ DO_TO_FUNCTION(MemHeapSize) \
+ DO_TO_FUNCTION(MemHeapFlags) \
+ DO_TO_FUNCTION(MemPtrRecoverHandle) \
+ DO_TO_FUNCTION(MemPtrFlags) \
+ DO_TO_FUNCTION(MemPtrSize) \
+ DO_TO_FUNCTION(MemPtrOwner) \
+ DO_TO_FUNCTION(MemPtrHeapID) \
+ DO_TO_FUNCTION(MemPtrDataStorage) \
+ DO_TO_FUNCTION(MemPtrCardNo) \
+ DO_TO_FUNCTION(MemPtrToLocalID) \
+ DO_TO_FUNCTION(MemHandleFlags) \
+ DO_TO_FUNCTION(MemHandleSize) \
+ DO_TO_FUNCTION(MemHandleOwner) \
+ DO_TO_FUNCTION(MemHandleLockCount) \
+ DO_TO_FUNCTION(MemHandleHeapID) \
+ DO_TO_FUNCTION(MemHandleDataStorage) \
+ DO_TO_FUNCTION(MemHandleCardNo) \
+ DO_TO_FUNCTION(MemHandleToLocalID) \
+ DO_TO_FUNCTION(MemHandleSetOwner) \
+ DO_TO_FUNCTION(MemLocalIDToGlobal) \
+ DO_TO_FUNCTION(MemLocalIDKind) \
+ DO_TO_FUNCTION(MemLocalIDToPtr) \
+ DO_TO_FUNCTION(MemDebugMode) \
+ DO_TO_FUNCTION(MemSetDebugMode) \
+ DO_TO_FUNCTION(MemHeapCheck) \
+ DO_TO_FUNCTION(MemHeapPtr) \
+ DO_TO_FUNCTION(MemStoreSearch) \
+ DO_TO_FUNCTION(MemStoreInit) \
+ DO_TO_FUNCTION(MemNVParams) \
+ DO_TO_FUNCTION(DmWriteCheck) \
+ DO_TO_FUNCTION(WinScreenInit)
+
+// List of functions for which we want to automatically
+// generate simple headpatches only.
+
+#define FOR_EACH_STUB_HEADPATCH_FUNCTION(DO_TO_FUNCTION) \
+ DO_TO_FUNCTION(MemKernelInit) \
+ DO_TO_FUNCTION(MemInitHeapTable) \
+ DO_TO_FUNCTION(MemHeapInit) \
+ DO_TO_FUNCTION(MemHeapCompact) \
+ DO_TO_FUNCTION(MemHeapFreeByOwnerID) \
+ DO_TO_FUNCTION(MemChunkNew) \
+ DO_TO_FUNCTION(MemPtrNew) \
+ DO_TO_FUNCTION(MemPtrSetOwner) \
+ DO_TO_FUNCTION(MemPtrResize) \
+ DO_TO_FUNCTION(MemPtrResetLock) \
+ DO_TO_FUNCTION(MemHandleNew) \
+ DO_TO_FUNCTION(MemHandleResize) \
+ DO_TO_FUNCTION(MemHandleLock) \
+ DO_TO_FUNCTION(MemHandleResetLock) \
+ DO_TO_FUNCTION(MemLocalIDToLockedPtr) \
+ DO_TO_FUNCTION(MemHeapScramble)
+
+// List of functions for which we want to automatically
+// generate simple tailpatches only.
+
+#define FOR_EACH_STUB_TAILPATCH_FUNCTION(DO_TO_FUNCTION) \
+ DO_TO_FUNCTION(MemSemaphoreReserve) \
+ DO_TO_FUNCTION(MemSemaphoreRelease)
+
+// List of functions for which we have compex head- and tailpatches.
+
+#define FOR_EACH_STUB_NOPATCH_FUNCTION(DO_TO_FUNCTION) \
+ DO_TO_FUNCTION(MemChunkFree) \
+ DO_TO_FUNCTION(MemHandleFree) \
+ DO_TO_FUNCTION(MemHandleUnlock) \
+ DO_TO_FUNCTION(MemPtrUnlock) \
+
+// This macro contains _all_ memory manager functions.
+
+#define FOR_EACH_MEMMGR_FUNCTION(DO_TO_FUNCTION) \
+ FOR_EACH_STUB_BOTHPATCH_FUNCTION(DO_TO_FUNCTION) \
+ FOR_EACH_STUB_HEADPATCH_FUNCTION(DO_TO_FUNCTION) \
+ FOR_EACH_STUB_TAILPATCH_FUNCTION(DO_TO_FUNCTION) \
+ FOR_EACH_STUB_NOPATCH_FUNCTION(DO_TO_FUNCTION)
+
+
+class MemMgrHeadpatch
+{
+ public:
+ // Declare headpatches for all the memory manager functions.
+
+ #define DECLARE_HEAD_PATCH(fn) static CallROMType fn (void);
+ FOR_EACH_MEMMGR_FUNCTION(DECLARE_HEAD_PATCH)
+};
+
+
+class MemMgrTailpatch
+{
+ public:
+ // Declare tailpatches for all the memory manager functions.
+
+ #define DECLARE_TAIL_PATCH(fn) static void fn (void);
+ FOR_EACH_MEMMGR_FUNCTION(DECLARE_TAIL_PATCH)
+};
+
+
+void CheckForMemoryLeaks (UInt32 memOwnerID);
+
+
+#endif // EmPatchModuleSys_h
diff --git a/SrcShared/Patches/EmPatchModuleTypes.h b/SrcShared/Patches/EmPatchModuleTypes.h
new file mode 100644
index 0000000..6ffb475
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModuleTypes.h
@@ -0,0 +1,94 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 PocketPyro, Inc.
+ Portions Copyright (c) Palm, 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.
+\* ===================================================================== */
+
+#ifndef EmPatchModuleTypes_h
+#define EmPatchModuleTypes_h
+
+#include "EmPatchIf.h" // HeadpatchProc, TailpatchProc, IEmPatchModule
+#include "EmStructs.h" // SystemCallContext
+
+
+// ======================================================================
+// At compile time, the list of functions we want to head- and tailpatch
+// are stored in an array of ProtoPatchTableEntries. At runtime, these
+// compact arrays are expanded by PatchModule into a sparse array
+// so that the function dispatch number can be used to look up the
+// patch function.
+// ======================================================================
+
+struct ProtoPatchTableEntry
+{
+ uint16 fTrapWord;
+ HeadpatchProc fHeadpatch;
+ TailpatchProc fTailpatch;
+};
+
+
+// ===========================================================================
+// InstalledLibPatchEntry
+// ===========================================================================
+// Structure used to hold tail-patch information.
+
+class InstalledLibPatchEntry
+{
+ public:
+ InstalledLibPatchEntry (void) :
+ fIsDirty (true),
+ fTableP (NULL)
+ {
+ }
+
+ bool IsDirty (void) const
+ {
+ return fIsDirty;
+ }
+
+ void SetDirty (bool dirty = true)
+ {
+ fIsDirty = dirty;
+ }
+
+ IEmPatchModule* GetPatchTableP (void) const
+ {
+ return fTableP;
+ }
+
+ void SetPatchTableP (IEmPatchModule* tableP)
+ {
+ fTableP = tableP;
+ }
+
+ private:
+ bool fIsDirty;
+ IEmPatchModule* fTableP;
+};
+
+typedef vector<InstalledLibPatchEntry> PatchedLibIndex;
+
+
+// ===========================================================================
+// ¥ TailpatchType
+// ===========================================================================
+// Structure used to hold tail-patch information.
+
+struct TailpatchType
+{
+ SystemCallContext fContext;
+ int32 fCount;
+ TailpatchProc fTailpatch;
+};
+
+typedef vector<TailpatchType> TailPatchIndex;
+
+#endif // EmPatchModuleTypes_h
diff --git a/SrcShared/Patches/EmPatchState.cpp b/SrcShared/Patches/EmPatchState.cpp
new file mode 100644
index 0000000..d5acc50
--- /dev/null
+++ b/SrcShared/Patches/EmPatchState.cpp
@@ -0,0 +1,1034 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ Copyright (c) 2001 PocketPyro, Inc.
+
+ Portions Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPatchState.h"
+
+#include "EmApplication.h" // ScheduleQuit
+#include "EmMemory.h" // EmMem_strcpy
+#include "Miscellaneous.h" // SysTrapIndex, SystemCallContext
+#include "PreferenceMgr.h" // Preference, kPrefKeyReportMemMgrLeaks
+#include "ROMStubs.h"
+
+
+EmStream& operator >> (EmStream& inStream, EmStackFrame& outInfo);
+EmStream& operator << (EmStream& inStream, const EmStackFrame& inInfo);
+EmStream& operator >> (EmStream& inStream, EmTrackedChunk& outInfo);
+EmStream& operator << (EmStream& inStream, const EmTrackedChunk& inInfo);
+
+
+// STATIC class data:
+
+EmPatchStateData EmPatchState::fgData;
+
+
+Err EmPatchState::Initialize (void)
+{
+ // Add a notification for MemMgrLeaks
+
+ gPrefs->AddNotification (&EmPatchState::MemMgrLeaksPrefsChanged, kPrefKeyReportMemMgrLeaks);
+
+ return errNone;
+}
+
+
+Err EmPatchState::Dispose (void)
+{
+ fgData.fUIInitialized = false;
+ fgData.fUIReset = false;
+ fgData.fHeapInitialized = false;
+ fgData.fEvtGetEventCalled = false;
+ fgData.fEncoding = charEncodingUnknown;
+
+ return errNone;
+}
+
+
+Err EmPatchState::Reset (void)
+{
+ fgData.fMemMgrCount = 0;
+ fgData.fMemSemaphoreCount = 0;
+ fgData.fMemSemaphoreReserveTime = 0;
+ fgData.fResizeOrigSize = 0;
+ fgData.fHeapID = 0;
+
+ fgData.fRememberedHeaps.clear ();
+ fgData.fTrackedChunks.clear ();
+
+ fgData.fLastEvtTrap = 0;
+ fgData.fOSVersion = kOSUndeterminedVersion;
+
+ fgData.fEvtGetEventCalled = false;
+ fgData.fEncoding = charEncodingUnknown;
+ fgData.fSysBinarySearchCount = 0;
+
+ fgData.fUIInitialized = false;
+ fgData.fUIReset = false;
+ fgData.fHeapInitialized = false;
+
+
+ SetQuitApp (0, 0);
+ SetSwitchApp (0, 0);
+
+ // Clear out everything we know about the current applications.
+
+ fgData.fCurAppInfo.clear ();
+
+ // Cache the preference about checking for memory manager leaks.
+
+ Preference<Bool> pref (kPrefKeyReportMemMgrLeaks);
+ fgData.fMemMgrLeaks = pref.Loaded () && *pref;
+
+ return errNone;
+}
+
+
+
+Err EmPatchState::Save (EmStreamChunk &s, long streamFmtVer, PersistencePhase pass)
+{
+ UNUSED_PARAM (streamFmtVer);
+
+ if (pass == PSPersistAll || pass == PSPersistStep1)
+ {
+ s << fgData.fUIInitialized;
+ s << fgData.fHeapInitialized;
+ s << fgData.fSysBinarySearchCount;
+
+ s << fgData.fMemMgrCount;
+ s << fgData.fMemSemaphoreCount;
+ s << fgData.fMemSemaphoreReserveTime;
+ s << fgData.fResizeOrigSize;
+ s << fgData.fHeapID;
+
+ s << fgData.fNextAppCardNo;
+ s << fgData.fNextAppDbID;
+ s << (long) 0; // was gQuitStage;
+
+ SaveCurAppInfo (s);
+ }
+
+ if (pass == PSPersistAll || pass == PSPersistStep2)
+ {
+ s << fgData.fLastEvtTrap;
+ s << fgData.fOSVersion;
+
+ // Added in version 2.
+
+ s << false; // was: gJapanese
+
+ // Added in version 3.
+
+ s << fgData.fEncoding;
+
+ // Added in version 4.
+
+ s << fgData.fUIReset;
+
+ // Added in version 5
+
+ s << fgData.fTrackedChunks;
+ }
+
+ return errNone;
+}
+
+
+Err EmPatchState::Load (EmStreamChunk &s, long streamFmtVer, PersistencePhase pass)
+{
+ if (pass == PSPersistAll || pass == PSPersistStep1)
+ {
+ long unused;
+
+ s >> fgData.fUIInitialized;
+ s >> fgData.fHeapInitialized;
+
+ SetEvtGetEventCalled (false);
+
+
+ s >> fgData.fSysBinarySearchCount;
+
+ s >> fgData.fMemMgrCount;
+ s >> fgData.fMemSemaphoreCount;
+ s >> fgData.fMemSemaphoreReserveTime;
+ s >> fgData.fResizeOrigSize;
+ s >> fgData.fHeapID;
+
+ s >> fgData.fNextAppCardNo;
+ s >> fgData.fNextAppDbID;
+ s >> unused; // was gQuitStage;
+
+ EmPatchState::LoadCurAppInfo (s);
+ }
+
+ if (pass == PSPersistAll || pass == PSPersistStep2)
+ {
+ if (streamFmtVer >= 1)
+ {
+ s >> fgData.fLastEvtTrap;
+ s >> fgData.fOSVersion;
+ }
+
+ if (streamFmtVer >= 2)
+ {
+ bool dummy;
+ s >> dummy; // was: gJapanese
+ }
+
+ if (streamFmtVer >= 3)
+ {
+ s >> fgData.fEncoding;
+ }
+ else
+ {
+ fgData.fEncoding = charEncodingUnknown;
+ }
+
+ if (streamFmtVer >= 4)
+ {
+ s >> fgData.fUIReset;
+ }
+
+ if (streamFmtVer >= 5)
+ {
+ s >> fgData.fTrackedChunks;
+ }
+ }
+
+ // Cache the preference about checking for memory manager leaks.
+
+ Preference<Bool> pref (kPrefKeyReportMemMgrLeaks);
+ fgData.fMemMgrLeaks = pref.Loaded () && *pref;
+
+ return errNone;
+}
+
+
+
+
+Err EmPatchState::SaveCurAppInfo (EmStreamChunk &s)
+{
+ s << (long) fgData.fCurAppInfo.size ();
+
+ EmuAppInfoList::iterator iter;
+ for (iter = fgData.fCurAppInfo.begin (); iter != fgData.fCurAppInfo.end (); ++iter)
+ {
+ s << iter->fCmd;
+ s << (long) iter->fDB;
+ s << iter->fCardNo;
+ s << iter->fDBID;
+ s << iter->fMemOwnerID;
+ s << iter->fStackP;
+ s << iter->fStackEndP;
+ s << iter->fStackSize;
+ s << iter->fName;
+ s << iter->fVersion;
+ }
+
+ return errNone;
+}
+
+Err EmPatchState::LoadCurAppInfo (EmStreamChunk &s)
+{
+ fgData.fCurAppInfo.clear ();
+
+ long numApps;
+
+ s >> numApps;
+
+ long ii;
+
+ for (ii = 0; ii < numApps; ++ii)
+ {
+ EmuAppInfo info;
+
+ s >> info.fCmd;
+
+ long temp;
+
+ s >> temp;
+ info.fDB = (DmOpenRef) temp;
+
+
+ s >> info.fCardNo;
+ s >> info.fDBID;
+ s >> info.fMemOwnerID;
+ s >> info.fStackP;
+ s >> info.fStackEndP;
+ s >> info.fStackSize;
+ s >> info.fName;
+ s >> info.fVersion;
+
+ fgData.fCurAppInfo.push_back (info);
+ }
+
+ return errNone;
+}
+
+Err EmPatchState::AddAppInfo (EmuAppInfo &newAppInfo)
+{
+ fgData.fCurAppInfo.push_back (newAppInfo);
+ return errNone;
+}
+
+Err EmPatchState::RemoveCurAppInfo (void)
+{
+ fgData.fCurAppInfo.pop_back ();
+ return errNone;
+}
+
+
+
+Err EmPatchState::SetLastEvtTrap (uint16 lastEvtTrap)
+{
+ fgData.fLastEvtTrap = lastEvtTrap;
+
+ return errNone;
+}
+
+uint16 EmPatchState::GetLastEvtTrap (void)
+{
+ return fgData.fLastEvtTrap;
+}
+
+Err EmPatchState::SetEvtGetEventCalled (bool wasCalled)
+{
+ fgData.fEvtGetEventCalled = wasCalled;
+
+ return errNone;
+}
+
+Err EmPatchState::SetQuitApp (UInt16 cardNo, LocalID dbID)
+{
+ fgData.fTimeToQuit = false;
+ fgData.fQuitAppCardNo = cardNo;
+ fgData.fQuitAppDbID = dbID;
+
+ return errNone;
+}
+
+void EmPatchState::SetTimeToQuit (void)
+{
+ gApplication->ScheduleQuit ();
+}
+
+
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmPatchState::MemMgrLeaksPrefsChanged
+// ---------------------------------------------------------------------------
+// Respond to a preference change.
+
+void EmPatchState::MemMgrLeaksPrefsChanged (PrefKeyType, void*)
+{
+ Preference<Bool> pref (kPrefKeyReportMemMgrLeaks, false);
+ fgData.fMemMgrLeaks = *pref;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::OSVersion
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+UInt32 EmPatchState::OSVersion (void)
+{
+ EmAssert (fgData.fOSVersion != kOSUndeterminedVersion);
+
+ return fgData.fOSVersion;
+}
+
+void EmPatchState::SetOSVersion (UInt32 version)
+{
+ fgData.fOSVersion = version;
+}
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::OSMajorMinorVersion
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+UInt32 EmPatchState::OSMajorMinorVersion (void)
+{
+ return OSMajorVersion () * 10 + OSMinorVersion ();
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::OSMajorVersion
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+UInt32 EmPatchState::OSMajorVersion (void)
+{
+ EmAssert (fgData.fOSVersion != kOSUndeterminedVersion);
+
+ return sysGetROMVerMajor (fgData.fOSVersion);
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::OSMinorVersion
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+UInt32 EmPatchState::OSMinorVersion (void)
+{
+ EmAssert (fgData.fOSVersion != kOSUndeterminedVersion);
+
+ return sysGetROMVerMinor (fgData.fOSVersion);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SetSwitchApp
+ *
+ * DESCRIPTION: Sets an application or launchable document to switch to
+ * the next time the system can manage it.
+ *
+ * PARAMETERS: cardNo - the card number of the app to switch to.
+ *
+ * dbID - the database id of the app to switch to.
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchState::SetSwitchApp (UInt16 cardNo, LocalID dbID)
+{
+ fgData.fNextAppCardNo = cardNo;
+ fgData.fNextAppDbID = dbID;
+}
+
+
+Bool EmPatchState::DatabaseInfoHasStackInfo (void)
+{
+ return OSMajorVersion () <= 2;
+} // Changed in 3.0
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::HasWellBehavedMemSemaphoreUsage
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+Bool EmPatchState::HasWellBehavedMemSemaphoreUsage (void)
+{
+ // Palm OS 3.0 and later should not be holding the memory manager
+ // semaphore for longer than 1 minute. I imagine that older ROMs
+ // don't hold the semaphore for longer than this, but Roger still
+ // suggested testing for 3.0.
+
+ return fgData.fOSVersion != kOSUndeterminedVersion && OSMajorMinorVersion () >= 30;
+}
+
+
+// Bugs fixed in 3.0.
+Bool EmPatchState::HasFindShowResultsBug (void)
+{
+ return OSMajorVersion () <= 2;
+}
+
+Bool EmPatchState::HasSysBinarySearchBug (void)
+{
+ return OSMajorVersion () <= 2;
+}
+
+// Bugs fixed in 3.1
+Bool EmPatchState::HasGrfProcessStrokeBug (void)
+{
+ return OSMajorMinorVersion () <= 30;
+}
+
+Bool EmPatchState::HasMenuHandleEventBug (void)
+{
+ return OSMajorMinorVersion () <= 30;
+}
+
+// Bugs fixed in 3.2
+Bool EmPatchState::HasBackspaceCharBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasDeletedStackBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasFindSaveFindStrBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasFldDeleteBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasFntDefineFontBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasNetPrvTaskMainBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+Bool EmPatchState::HasNetPrvSettingSetBug (void)
+{
+ return OSMajorMinorVersion () <= 31;
+}
+
+// Bugs fixed in 3.3
+Bool EmPatchState::HasECValidateFieldBug (void)
+{
+ return OSMajorMinorVersion () <= 32;
+}
+
+// Bugs fixed in 3.5
+Bool EmPatchState::HasConvertDepth1To2BWBug (void)
+{
+ return OSMajorMinorVersion () <= 33;
+}
+
+// Bugs fixed in 4.0
+Bool EmPatchState::HasSelectItemBug (void)
+{
+ return OSMajorMinorVersion () == 35;
+}
+
+Bool EmPatchState::HasSyncNotifyBug (void)
+{
+ return OSMajorVersion () <= 3;
+}
+
+// Bugs fixed in ???
+Bool EmPatchState::HasPrvDrawSliderControlBug (void)
+{
+ return OSMajorMinorVersion () <= 40;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::GetAutoAcceptBeamDialogs
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+Bool EmPatchState::GetAutoAcceptBeamDialogs (void)
+{
+ return fgData.fAutoAcceptBeamDialogs;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::AutoAcceptBeamDialogs
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+Bool EmPatchState::AutoAcceptBeamDialogs (Bool newState)
+{
+ bool oldState = fgData.fAutoAcceptBeamDialogs;
+ fgData.fAutoAcceptBeamDialogs = newState != 0;
+ return oldState;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::GetROMCharEncoding (was TurningJapanese)
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: Palm OS character encoding used by ROM.
+*
+***********************************************************************/
+
+UInt16 EmPatchState::GetROMCharEncoding (void)
+{
+ return fgData.fEncoding;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::EvtGetEventCalled
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+Bool EmPatchState::EvtGetEventCalled (void)
+{
+ return fgData.fEvtGetEventCalled;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::IsInSysBinarySearch
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+Bool EmPatchState::IsInSysBinarySearch (void)
+{
+ return fgData.fSysBinarySearchCount > 0;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::EnterSysBinarySearch
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+void EmPatchState::EnterSysBinarySearch (void)
+{
+ EmAssert (fgData.fSysBinarySearchCount < 10);
+ ++fgData.fSysBinarySearchCount;
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::ExitSysBinarySearch
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+void EmPatchState::ExitSysBinarySearch (void)
+{
+ --fgData.fSysBinarySearchCount;
+ EmAssert (fgData.fSysBinarySearchCount >= 0);
+}
+
+
+
+uint16 EmPatchState::GetQuitAppCardNo (void)
+{
+ return fgData.fQuitAppCardNo;
+}
+
+
+LocalID EmPatchState::GetQuitAppDbID (void)
+{
+ return fgData.fQuitAppDbID;
+}
+
+void EmPatchState::SetEncoding (uint32 encoding)
+{
+ fgData.fEncoding = encoding;
+}
+
+Bool EmPatchState::IsPCInMemMgr (void)
+{
+ return fgData.fMemMgrCount > 0;
+}
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::EnterMemMgr
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+void EmPatchState::EnterMemMgr (const char* fnName)
+{
+ UNUSED_PARAM (fnName)
+
+ ++fgData.fMemMgrCount;
+ EmAssert (fgData.fMemMgrCount < 10);
+}
+
+
+/***********************************************************************
+*
+* FUNCTION: EmPatchState::ExitMemMgr
+*
+* DESCRIPTION:
+*
+* PARAMETERS: none
+*
+* RETURNED: nothing
+*
+***********************************************************************/
+
+void EmPatchState::ExitMemMgr (const char* fnName)
+{
+ UNUSED_PARAM (fnName)
+
+ --fgData.fMemMgrCount;
+ EmAssert (fgData.fMemMgrCount >= 0);
+
+ #if 0 // _DEBUG
+ if (fgData.fMemMgrCount == 0)
+ {
+ EmPalmHeap::ValidateAllHeaps ();
+ }
+ #endif
+}
+
+Bool EmPatchState::UIInitialized (void)
+{
+ return fgData.fUIInitialized;
+}
+
+void EmPatchState::SetUIInitialized (Bool value)
+{
+ fgData.fUIInitialized = value != 0;
+}
+
+Bool EmPatchState::UIReset (void)
+{
+ return fgData.fUIReset;
+}
+
+void EmPatchState::SetUIReset (Bool value)
+{
+ fgData.fUIReset = value != 0;
+}
+
+Bool EmPatchState::HeapInitialized (void)
+{
+ return fgData.fHeapInitialized;
+}
+
+void EmPatchState::SetHeapInitialized (Bool value)
+{
+ fgData.fHeapInitialized = value != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchState::CollectCurrentAppInfo
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Err EmPatchState::CollectCurrentAppInfo (emuptr appInfoP, EmuAppInfo &newAppInfo)
+{
+ memset (&newAppInfo, 0, sizeof (newAppInfo));
+
+ // Scarf some information out of the app info block.
+
+ newAppInfo.fDB = (DmOpenRef) EmMemGet32 (appInfoP + offsetof (SysAppInfoType, dbP));
+ newAppInfo.fStackP = EmMemGet32 (appInfoP + offsetof (SysAppInfoType, stackP));
+ newAppInfo.fMemOwnerID = EmMemGet16 (appInfoP + offsetof (SysAppInfoType, memOwnerID));
+
+ // Determine the current stack range. Under Palm OS 3.0 and later, this information
+ // is in the DatabaseInfo block. Under earlier OSes, we only get the low-end of the stack
+ // (that is, the address that was returned by MemPtrNew). To get the high-end of
+ // the stack, assume that stackP pointed to a chunk of memory allocated by MemPtrNew
+ // and call MemPtrSize.
+
+ if (DatabaseInfoHasStackInfo ())
+ {
+ if (newAppInfo.fStackP)
+ {
+ UInt32 stackSize = ::MemPtrSize ((MemPtr) newAppInfo.fStackP);
+ if (stackSize)
+ {
+ newAppInfo.fStackEndP = newAppInfo.fStackP + stackSize;
+ }
+ else
+ {
+ newAppInfo.fStackEndP = EmMemNULL;
+ }
+ }
+ }
+ else
+ {
+ newAppInfo.fStackEndP = EmMemGet32 (appInfoP + offsetof (SysAppInfoType, stackEndP));
+ }
+
+ newAppInfo.fStackSize = newAppInfo.fStackEndP - newAppInfo.fStackP;
+
+ // Remember the current application name and version information. We use
+ // this information when telling users that something has gone haywire. Collect
+ // this information now instead of later (on demand) as we can't be sure that
+ // we can make the necessary DataMgr calls after an error occurs.
+ //
+ // If the database has a 'tAIN' resource, get the name from there.
+ // Otherwise, use the database name.
+ //
+ // (Write the name into a temporary local variable. The local variable is
+ // on the stack, which will get "mapped" into the emulated address space so
+ // that the emulated DmDatabaseInfo can get to it.)
+
+ UInt16 cardNo;
+ LocalID dbID;
+
+ Err err = ::DmOpenDatabaseInfo (newAppInfo.fDB, &dbID, NULL, NULL, &cardNo, NULL);
+ if (err)
+ return err;
+
+ newAppInfo.fCardNo = cardNo;
+ newAppInfo.fDBID = dbID;
+
+ char appName[dmDBNameLength] = {0};
+ char appVersion[256] = {0}; // <gulp> I hope this is big enough...
+
+// DmOpenRef dbP = DmOpenDatabase (cardNo, dbID, dmModeReadOnly);
+
+// if (dbP)
+ {
+ MemHandle strH;
+
+ // Get the app name from the 'tAIN' resource.
+
+ strH = ::DmGet1Resource (ainRsc, ainID);
+ if (strH)
+ {
+ emuptr strP = (emuptr) ::MemHandleLock (strH);
+ EmMem_strcpy (appName, strP);
+ ::MemHandleUnlock (strH);
+ ::DmReleaseResource (strH);
+ }
+
+ // Get the version from the 'tver' resource, using ID's 1 and 1000
+
+ strH = ::DmGet1Resource (verRsc, appVersionID);
+ if (strH == NULL)
+ strH = ::DmGet1Resource (verRsc, appVersionAlternateID);
+ if (strH)
+ {
+ emuptr strP = (emuptr) ::MemHandleLock (strH);
+ EmMem_strcpy (appVersion, strP);
+ ::MemHandleUnlock (strH);
+ ::DmReleaseResource (strH);
+ }
+
+// ::DmCloseDatabase (dbP);
+ }
+
+ if (appName[0] == 0) // No 'tAIN' resource, so use database name
+ {
+ ::DmDatabaseInfo (cardNo, dbID,
+ appName,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ }
+
+ // Copy the strings from the stack to their permanent homes.
+
+ strcpy (newAppInfo.fName, appName);
+ strcpy (newAppInfo.fVersion, appVersion);
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchState::GetCurrentAppInfo
+ *
+ * DESCRIPTION: Return information on the last application launched
+ * with SysAppLaunch (and that hasn't exited yet).
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+
+EmuAppInfo EmPatchState::GetCurrentAppInfo (void)
+{
+ EmuAppInfo result;
+ memset (&result, 0, sizeof (result));
+
+ if (fgData.fCurAppInfo.size () > 0)
+ {
+ result = *(fgData.fCurAppInfo.rbegin ());
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchState::GetRootAppInfo
+ *
+ * DESCRIPTION: Return information on the last application launched
+ * with SysAppLaunch and with the launch code of
+ * sysAppLaunchCmdNormalLaunch (and that hasn't exited yet).
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmuAppInfo EmPatchState::GetRootAppInfo (void)
+{
+ EmuAppInfo result;
+ memset (&result, 0, sizeof (result));
+
+ EmuAppInfoList::reverse_iterator iter = fgData.fCurAppInfo.rbegin ();
+
+ while (iter != fgData.fCurAppInfo.rend ())
+ {
+ if ((*iter).fCmd == sysAppLaunchCmdNormalLaunch)
+ {
+ result = *iter;
+ break;
+ }
+
+ ++iter;
+ }
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, EmStackFrame&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& inStream, EmStackFrame& outInfo)
+{
+ inStream >> outInfo.fAddressInFunction;
+ inStream >> outInfo.fA6;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, const EmStackFrame&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& inStream, const EmStackFrame& inInfo)
+{
+ inStream << inInfo.fAddressInFunction;
+ inStream << inInfo.fA6;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator >> (EmStream&, EmTrackedChunk&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator >> (EmStream& inStream, EmTrackedChunk& outInfo)
+{
+ inStream >> outInfo.ptr;
+ inStream >> outInfo.isHandle;
+ inStream >> outInfo.stackCrawl;
+
+ return inStream;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ operator << (EmStream&, const EmTrackedChunk&)
+// ---------------------------------------------------------------------------
+
+EmStream& operator << (EmStream& inStream, const EmTrackedChunk& inInfo)
+{
+ inStream << inInfo.ptr;
+ inStream << inInfo.isHandle;
+ inStream << inInfo.stackCrawl;
+
+ return inStream;
+}
diff --git a/SrcShared/Patches/EmPatchState.h b/SrcShared/Patches/EmPatchState.h
new file mode 100644
index 0000000..1c8fa2d
--- /dev/null
+++ b/SrcShared/Patches/EmPatchState.h
@@ -0,0 +1,264 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmPatchState_h
+#define EmPatchState_h
+
+#include "ChunkFile.h"
+#include "EmPalmHeap.h"
+#include "EmPatchModuleTypes.h"
+#include "PreferenceMgr.h" // PrefKeyType
+
+#include <vector>
+#include <map>
+
+
+const UInt32 kOSUndeterminedVersion = ~0;
+
+
+typedef map<emuptr, EmPalmHeap*> EmHeapMap;
+
+
+
+// Structure used to hold information about the currently
+// running Palm OS application (as recorded when SysAppStartup
+// is called).
+
+struct EmuAppInfo
+{
+ Int16 fCmd; // launch code
+ DmOpenRef fDB;
+ UInt16 fCardNo;
+ LocalID fDBID;
+ UInt16 fMemOwnerID;
+ emuptr fStackP;
+ emuptr fStackEndP;
+ long fStackSize;
+ char fName[dmDBNameLength];
+ char fVersion[256]; // <gulp> I hope this is big enough...
+};
+
+typedef vector<EmuAppInfo> EmuAppInfoList;
+
+
+// Structure used to keep track of the context in which
+// memory chunks were allocated.
+
+struct EmTrackedChunk
+{
+ emuptr ptr;
+ bool isHandle;
+ EmStackFrameList stackCrawl;
+};
+
+typedef list<EmTrackedChunk> EmTrackedChunkList;
+
+
+struct EmPatchStateData
+{
+ public:
+ EmPatchStateData () :
+ fUIInitialized (false),
+ fUIReset (false),
+
+ fEvtGetEventCalled (false),
+ fAutoAcceptBeamDialogs (false),
+ fTimeToQuit (false),
+
+ fLastEvtTrap (0),
+ fOSVersion (0),
+ fEncoding (0),
+
+ fSysBinarySearchCount (0),
+
+ fQuitAppCardNo (0),
+ fQuitAppDbID (0),
+ fNextAppCardNo (0),
+ fNextAppDbID (0),
+
+ fHeapInitialized (false),
+ fMemMgrCount (0),
+ fMemSemaphoreCount (0),
+ fMemSemaphoreReserveTime (0),
+ fResizeOrigSize (0),
+ fHeapID (0)
+ {
+ }
+
+ bool fUIInitialized;
+ bool fUIReset;
+ bool fEvtGetEventCalled;
+ bool fAutoAcceptBeamDialogs;
+ bool fTimeToQuit;
+
+ uint16 fLastEvtTrap;
+ uint32 fOSVersion;
+ uint32 fEncoding;
+
+ long fSysBinarySearchCount;
+
+ uint16 fQuitAppCardNo;
+ LocalID fQuitAppDbID;
+ uint16 fNextAppCardNo;
+ LocalID fNextAppDbID;
+
+ EmuAppInfoList fCurAppInfo;
+
+ bool fHeapInitialized;
+
+ long fMemMgrCount;
+ Bool fMemMgrLeaks;
+ long fMemSemaphoreCount;
+ unsigned long fMemSemaphoreReserveTime;
+
+ uint32 fResizeOrigSize;
+ uint16 fHeapID;
+
+ EmHeapMap fRememberedHeaps;
+
+ EmTrackedChunkList fTrackedChunks;
+};
+
+
+
+class EmPatchState
+{
+ public:
+ static Err Initialize (void);
+ static Err Dispose (void);
+ static Err Reset (void);
+
+ enum PersistencePhase
+ {
+ PSPersistAll, // save/load all
+ PSPersistStep1, // Backward compatability step 1
+ PSPersistStep2 // Backward compatability step 2
+ };
+
+ static Err Save (EmStreamChunk &s, long version = 1, PersistencePhase pass = PSPersistAll);
+ static Err Load (EmStreamChunk &s, long version = 1, PersistencePhase pass = PSPersistAll);
+
+ static Err SaveCurAppInfo (EmStreamChunk &s);
+ static Err LoadCurAppInfo (EmStreamChunk &s);
+
+ static uint16 GetLastEvtTrap (void);
+ static EmuAppInfo GetCurrentAppInfo (void);
+ static EmuAppInfo GetRootAppInfo (void);
+
+
+ static Err AddAppInfo (EmuAppInfo &newAppInfo);
+ static Err RemoveCurAppInfo (void);
+
+ static Err SetLastEvtTrap (uint16 lastEvtTrap);
+ static Err SetEvtGetEventCalled (bool wasCalled);
+
+ static Err SetQuitApp (UInt16 cardNo, LocalID dbID);
+ static void SetTimeToQuit (void);
+
+ static void MemMgrLeaksPrefsChanged (PrefKeyType, void*);
+
+ static Err CollectCurrentAppInfo (emuptr appInfoP, EmuAppInfo &newAppInfo);
+
+
+ static UInt32 OSVersion (void);
+ static void SetOSVersion (UInt32 version);
+ static UInt32 OSMajorMinorVersion (void);
+ static UInt32 OSMajorVersion (void);
+ static UInt32 OSMinorVersion (void);
+ static void SetSwitchApp (UInt16 cardNo, LocalID dbID);
+ static Bool DatabaseInfoHasStackInfo(void);
+ static Bool HasWellBehavedMemSemaphoreUsage (void);
+
+
+ // Bugs fixed in 3.0.
+ static Bool HasFindShowResultsBug (void);
+ static Bool HasSysBinarySearchBug (void);
+
+ // Bugs fixed in 3.1
+ static Bool HasGrfProcessStrokeBug (void);
+ static Bool HasMenuHandleEventBug (void);
+
+ // Bugs fixed in 3.2
+ static Bool HasBackspaceCharBug (void);
+ static Bool HasDeletedStackBug (void);
+ static Bool HasFindSaveFindStrBug (void);
+ static Bool HasFldDeleteBug (void);
+ static Bool HasFntDefineFontBug (void);
+ static Bool HasNetPrvTaskMainBug (void);
+ static Bool HasNetPrvSettingSetBug (void);
+
+ // Bugs fixed in 3.3
+ static Bool HasECValidateFieldBug (void);
+
+ // Bugs fixed in 3.5
+ static Bool HasConvertDepth1To2BWBug(void);
+
+ // Bugs fixed in 4.0
+ static Bool HasSelectItemBug (void);
+ static Bool HasSyncNotifyBug (void);
+
+ // Bugs fixed in ???
+ static Bool HasPrvDrawSliderControlBug (void);
+
+
+ static Bool GetAutoAcceptBeamDialogs (void);
+ static Bool AutoAcceptBeamDialogs (Bool newState);
+ static UInt16 GetROMCharEncoding (void);
+ static Bool EvtGetEventCalled (void);
+ static Bool IsInSysBinarySearch (void);
+ static void EnterSysBinarySearch (void);
+ static void ExitSysBinarySearch (void);
+ static uint16 GetQuitAppCardNo (void);
+ static LocalID GetQuitAppDbID (void);
+ static void SetEncoding (uint32 encoding);
+
+ static Bool IsPCInMemMgr (void);
+ static void EnterMemMgr (const char* fnName);
+ static void ExitMemMgr (const char* fnName);
+ static Bool UIInitialized (void);
+
+ static void SetUIInitialized (Bool value = true);
+ static void SetUIReset (Bool value = true);
+ static void SetHeapInitialized (Bool value = true);
+
+ static Bool UIReset (void);
+ static Bool HeapInitialized (void);
+
+ // inline functions
+
+ static uint16 GetNextAppCardNo (void)
+ {
+ return fgData.fNextAppCardNo;
+ }
+
+ static LocalID GetNextAppDbID (void)
+ {
+ return fgData.fNextAppDbID;
+ }
+
+ static void SetNextAppCardNo (uint16 cardno)
+ {
+ fgData.fNextAppCardNo = cardno;
+ }
+
+ static void SetNextAppDbID (LocalID id)
+ {
+ fgData.fNextAppDbID = id;
+ }
+
+ public:
+ static EmPatchStateData fgData;
+};
+
+#endif // EmPatchState_h
diff --git a/SrcShared/Platform.h b/SrcShared/Platform.h
new file mode 100644
index 0000000..5fe9fdb
--- /dev/null
+++ b/SrcShared/Platform.h
@@ -0,0 +1,218 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _PLATFORM_H_
+#define _PLATFORM_H_
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ // Define these wrapper functions for C modules.
+
+void* Platform_AllocateMemory (size_t size);
+void* Platform_ReallocMemory (void* p, size_t size);
+void Platform_DisposeMemory (void* p);
+
+#ifdef __cplusplus
+} // extern "C"
+
+ // Do all the rest of this for C++ studs.
+
+#include "EmStructs.h" // ByteList
+#include "EmTypes.h" // StrCode
+#include "EmPatchIf.h" // CallROMType
+
+class ChunkFile;
+class CSocket;
+class EmFileRef;
+class EmRect;
+class SessionFile;
+class StMemory;
+
+// Globals
+
+int _stricmp(const char *s1, const char *s2);
+int _strnicmp(const char *s1, const char *s2, int n);
+char* _strdup (const char* s);
+char* _strlwr (char* s);
+
+// Function prototypes.
+
+class Platform
+{
+ public:
+
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ // Resource-related functions
+
+ static string GetString (StrCode id);
+ static int GetIDForError (ErrCode error);
+ static int GetIDForRecovery (ErrCode error);
+
+ static string GetShortVersionString (void);
+
+ // Clipboard-related functions
+
+ static void CopyToClipboard (const ByteList& palmChars,
+ const ByteList& hostChars);
+ static void CopyFromClipboard (ByteList& palmChars,
+ ByteList& hostChars);
+
+ static uint16 RemapHostChar (uint8 hostEncoding, uint8 deviceEncoding, uint16 hostChar);
+
+ static void RemapHostToPalmChars (const ByteList& hostChars,
+ ByteList& palmChars);
+ static void RemapPalmToHostChars (const ByteList& palmChars,
+ ByteList& hostChars);
+
+ // Time-related functions
+
+ static uint32 GetMilliseconds (void);
+
+ // External debugger-related functions
+
+ static CSocket* CreateDebuggerSocket (void);
+ static void ExitDebugger (void);
+
+ // Graphics-related functions
+
+ static void ViewDrawLine (int xStart, int yStart, int xEnd, int yEnd);
+ static void ViewDrawPixel (int xPos, int yPos);
+
+ // Sound functions
+
+ static CallROMType SndDoCmd (SndCommandType&);
+ static void StopSound (void);
+ static void Beep (void);
+
+ // Whatever....
+
+ static Bool PinToScreen (EmRect&);
+
+ static void ToHostEOL (StMemory& dest, long& destLen,
+ const char* src, long srcLen);
+
+
+ static Bool ReadROMFileReference (ChunkFile& docFile,
+ EmFileRef& f);
+ static void WriteROMFileReference (ChunkFile& docFile,
+ const EmFileRef& f);
+
+ static void Delay (void);
+ static void CycleSlowly (void);
+
+ static void* RealAllocateMemory (size_t size, Bool clear, const char* file, int line);
+ static void* RealReallocMemory (void* p, size_t size, const char* file, int line);
+ template <class T>
+ static void DisposeMemory (T*& p)
+ {
+ // Normally, I don't put functions inline like
+ // this. However, if I try defining this function
+ // in a separate body, VC++ complains that DisposeMemory
+ // doesn't take one parameter. Go figure...
+
+ if (p)
+ {
+ RealDisposeMemory ((void*) p);
+ p = NULL;
+ }
+ }
+ static void RealDisposeMemory (void* p);
+
+ // Aliases for DisposeMemory, because I can never remember
+ // what the real name is...
+ template <class T>
+ static void DeleteMemory (T*& p) { DisposeMemory(p); }
+
+ template <class T>
+ static void FreeMemory (T*& p) { DisposeMemory(p); }
+
+ static Bool ForceStartupScreen (void);
+ static Bool StopOnResetKeyDown (void);
+
+ // Parse up the command line in a platform-specific fashion. In particular,
+ // FLTK likes to take over the iteration so that it can scarf up any
+ // standard X options. We have to let *it* do the iteration in order to
+ // get everything to work out right. If we were to iterate over the
+ // options and call the low-level FLTK "consume one option" function for
+ // the options we don't know about, then when we later call fl::show to
+ // show our main window (using the geometry, display, etc., information
+ // from the command line), fl::show will try to parse the command line
+ // again, fumbling on the options it doesn't know. If we try to fool
+ // fl::show by NULL-ing out the command line options it doesn't know about,
+ // it will later crash when trying to call strlen(NULL).
+
+ static Bool CollectOptions (int argc, char** argv, int& i, int (*cb)(int, char**, int&));
+ static void PrintHelp (void);
+
+ static void Debugger (const char* = NULL);
+};
+
+#define AllocateMemory(size) \
+ RealAllocateMemory(size, false, __FILE__, __LINE__)
+
+#define AllocateMemoryClear(size) \
+ RealAllocateMemory(size, true, __FILE__, __LINE__)
+
+#define ReallocMemory(p, size) \
+ RealReallocMemory(p, size, __FILE__, __LINE__)
+
+
+#if PLATFORM_MAC
+
+ inline void Platform::Debugger (const char* text)
+ {
+ if (text)
+ {
+ LStr255 str (text);
+ ::DebugStr (str);
+ }
+ else
+ {
+ ::Debugger ();
+ }
+ }
+
+#endif
+
+#if PLATFORM_WINDOWS
+
+ inline void Platform::Debugger (const char*)
+ {
+ ::DebugBreak ();
+ }
+
+#endif
+
+#if PLATFORM_UNIX
+
+#include <signal.h>
+
+ inline void Platform::Debugger (const char*)
+ {
+ raise (SIGTRAP);
+ }
+
+#endif
+
+#endif // extern "C"
+
+#endif /* _PLATFORM_H_ */
diff --git a/SrcShared/Platform_NetLib.h b/SrcShared/Platform_NetLib.h
new file mode 100644
index 0000000..03f0a80
--- /dev/null
+++ b/SrcShared/Platform_NetLib.h
@@ -0,0 +1,100 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _PLATFORM_NETLIB_H_
+#define _PLATFORM_NETLIB_H_
+
+#include "SessionFile.h" // SessionFile
+
+class Platform_NetLib
+{
+ public:
+ static void Initialize (void);
+ static void Reset (void);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static Bool Redirecting (void);
+
+ static Err Open (UInt16 libRefNum, UInt16* netIFErrsP);
+ static Err OpenConfig (UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags, UInt16* netIFErrsP);
+ static Err Close (UInt16 libRefNum, UInt16 immediate);
+ static Err Sleep (UInt16 libRefNum);
+ static Err Wake (UInt16 libRefNum);
+ static Err FinishCloseWait(UInt16 libRefNum);
+ static Err OpenIfCloseWait(UInt16 libRefNum);
+ static Err OpenCount (UInt16 refNum, UInt16* countP);
+ static Err HandlePowerOff (UInt16 refNum, EventPtr eventP);
+ static Err ConnectionRefresh(UInt16 refNum, Boolean refresh,
+ Boolean* allInterfacesUpP, UInt16* netIFErrP);
+ static NetSocketRef SocketOpen(UInt16 libRefNum, NetSocketAddrEnum domain,
+ NetSocketTypeEnum type, Int16 protocol, Int32 timeout,
+ Err* errP);
+ static Int16 SocketClose(UInt16 libRefNum, NetSocketRef socket, Int32 timeout,
+ Err* errP);
+ static Int16 SocketOptionSet(UInt16 libRefNum, NetSocketRef socket,
+ NetSocketOptLevelEnum level, NetSocketOptEnum option,
+ MemPtr optValueP, UInt16 optValueLen,
+ Int32 timeout, Err* errP);
+ static Int16 SocketOptionGet(UInt16 libRefNum, NetSocketRef socket,
+ NetSocketOptLevelEnum level, NetSocketOptEnum option,
+ MemPtr optValueP, UInt16* optValueLenP,
+ Int32 timeout, Err* errP);
+ static Int16 SocketBind(UInt16 libRefNum, NetSocketRef socket,
+ NetSocketAddrType* sockAddrP, Int16 addrLen, Int32 timeout,
+ Err* errP);
+ static Int16 SocketConnect(UInt16 libRefNum, NetSocketRef socket,
+ NetSocketAddrType* sockAddrP, Int16 addrLen, Int32 timeout,
+ Err* errP);
+ static Int16 SocketListen(UInt16 libRefNum, NetSocketRef socket,
+ UInt16 queueLen, Int32 timeout, Err* errP);
+ static Int16 SocketAccept(UInt16 libRefNum, NetSocketRef socket,
+ NetSocketAddrType* sockAddrP, Int16* addrLenP, Int32 timeout,
+ Err* errP);
+ static Int16 SocketShutdown(UInt16 libRefNum, NetSocketRef socket,
+ Int16 /*NetSocketDirEnum*/ direction, Int32 timeout, Err* errP);
+ static Int16 SocketAddr(UInt16 libRefNum, NetSocketRef socketRef,
+ NetSocketAddrType* locAddrP, Int16* locAddrLenP,
+ NetSocketAddrType* remAddrP, Int16* remAddrLenP,
+ Int32 timeout, Err* errP);
+ static Int16 SendPB(UInt16 libRefNum, NetSocketRef socket,
+ NetIOParamType* pbP, UInt16 flags, Int32 timeout, Err* errP);
+ static Int16 Send(UInt16 libRefNum, NetSocketRef socket,
+ const MemPtr bufP, UInt16 bufLen, UInt16 flags,
+ MemPtr toAddrP, UInt16 toLen, Int32 timeout, Err* errP);
+ static Int16 ReceivePB(UInt16 libRefNum, NetSocketRef socket,
+ NetIOParamType* pbP, UInt16 flags, Int32 timeout, Err* errP);
+ static Int16 Receive(UInt16 libRefNum, NetSocketRef socket,
+ MemPtr bufP, UInt16 bufLen, UInt16 flags,
+ MemPtr fromAddrP, UInt16* fromLenP, Int32 timeout, Err* errP);
+ static Int16 DmReceive(UInt16 libRefNum, NetSocketRef socket,
+ MemPtr recordP, UInt32 recordOffset, UInt16 rcvLen, UInt16 flags,
+ MemPtr fromAddrP, UInt16* fromLenP, Int32 timeout, Err* errP);
+ static NetHostInfoPtr GetHostByName(UInt16 libRefNum, Char* nameP,
+ NetHostInfoBufPtr bufP, Int32 timeout, Err* errP);
+ static NetHostInfoPtr GetHostByAddr(UInt16 libRefNum, UInt8* addrP, UInt16 len, UInt16 type,
+ NetHostInfoBufPtr bufP, Int32 timeout, Err* errP);
+ static NetServInfoPtr GetServByName(UInt16 libRefNum, Char* servNameP,
+ Char* protoNameP, NetServInfoBufPtr bufP,
+ Int32 timeout, Err* errP);
+ static Int16 GetMailExchangeByName(UInt16 libRefNum, Char* mailNameP,
+ UInt16 maxEntries,
+ Char hostNames[][netDNSMaxDomainName+1], UInt16 priorities[],
+ Int32 timeout, Err* errP);
+ static Int16 Select(UInt16 libRefNum, UInt16 width, NetFDSetType* readFDs,
+ NetFDSetType* writeFDs, NetFDSetType* exceptFDs,
+ Int32 timeout, Err* errP);
+};
+
+#endif // _PLATFORM_NETLIB_H_
diff --git a/SrcShared/Platform_NetLib_Sck.cpp b/SrcShared/Platform_NetLib_Sck.cpp
new file mode 100644
index 0000000..c97265d
--- /dev/null
+++ b/SrcShared/Platform_NetLib_Sck.cpp
@@ -0,0 +1,3436 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Platform_NetLib.h"
+
+#include "PreferenceMgr.h" // Preference
+#include "Byteswapping.h" // Canonical
+#include "Logging.h" // LogAppendMsg
+#include "Miscellaneous.h" // StMemory
+#include "Platform.h" // AllocateMemory
+#include "ROMStubs.h" // NetLibConfigMakeActive
+
+
+#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
+#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
+#endif
+
+#if defined(__svr4__)
+#include <sys/filio.h> // FIONBIO
+#endif
+
+#define PRINTF if (!LogNetLib ()) ; else LogAppendMsg
+
+// ===== COPIED FROM NETPRV.H =====
+
+// Max # of open built-in sockets at one time.
+#define netMaxNumSockets 4 // Max # of sockets
+#define netMinSocketRefNum (sysFileDescNet) // lowest libRefNum
+#define netMaxSocketRefNum (sysFileDescNet+netMaxNumSockets-1) // highest libRefNum
+
+// The sockets maintained by NetLib plug-ins are numbered above the built-in
+// sockets.
+#define netMaxNumPISockets 4 // Max # of Plug-In sockets
+#define netMinPISocketRefNum (netMaxSocketRefNum+1) // lowest libRefNum
+#define netMaxPISocketRefNum (netMinPISocketRefNum+netMaxNumPISockets-1)
+
+
+// A NetSocketRef is the index into an array holding the pointers to
+// socket data. Because NetSocketRefs should not be zero, the refNums
+// actually start at sysFileDescNet (which happens to be 1).
+//
+// The NetLib headers are sensitive to this numbering. In particular,
+// netFDSet, et al, assume a certain number range in order to set bits
+// in the NetFDSetType object.
+//
+// Therefore, we can't just return the results of the socket() function as
+// the result of NetLibSocketOpen(). Though an opaque type, the range of
+// values returned by socket() is outside the range allowed by netFDSet.
+// So, we have to map the SOCKET returned by socket() to something allowed
+// by NetLib. We store the SOCKETs in the array below, and return the
+// index of the SOCKET, just as NetLib would.
+
+SOCKET gSockets[netMaxNumSockets] = { INVALID_SOCKET, INVALID_SOCKET, INVALID_SOCKET, INVALID_SOCKET };
+
+
+// The following are copied from WinSock2.h. We don't include that file
+// here because it can't be included in the same scope as WinSock.h, which
+// Windows.h pulls in.
+
+#define SD_RECEIVE 0x00
+#define SD_SEND 0x01
+#define SD_BOTH 0x02
+
+#if PLATFORM_WINDOWS
+extern WORD gWinSockVersion;
+#endif
+
+static long gOpenCount;
+static UInt16 gCurConfigIndex;
+
+static Bool NetLibToSocketsRef (const NetSocketRef inSocket,
+ SOCKET& outSocket);
+
+static Bool RememberSocketsRef (const SOCKET inSocket,
+ NetSocketRef& outSocket);
+static Bool ForgetSocketsRef (NetSocketRef sRef);
+
+static Bool NetLibToSocketsDomain (const NetSocketAddrEnum inDomain,
+ u_short& outDomain);
+
+static Bool NetLibToSocketsType (const NetSocketTypeEnum inType,
+ int& outType);
+static Bool NetLibToSocketsProtocol (const Int16 inProtocol,
+ int& outProtocol);
+static Bool NetLibToSocketsDirection (const Int16 inDirection,
+ int& outDirection);
+static Bool NetLibToSocketsFlags (const UInt16 inFlags,
+ int& outFlags);
+
+static Bool NetLibToSocketsOptions (const NetSocketOptLevelEnum inOptLevel,
+ const NetSocketOptEnum inOptName,
+ const MemPtr inOptVal,
+ const UInt16 inOptValLen,
+ int& outOptLevel,
+ int& outOptName,
+ char*& outOptVal,
+ socklen_t& outOptValLen);
+static Bool SocketsToNetLibOptions (const int inOptLevel,
+ const int inOptName,
+ /*const*/ char*& inOptVal,
+ const int inOptValLen,
+ NetSocketOptLevelEnum outOptLevel,
+ NetSocketOptEnum outOptName,
+ MemPtr outOptVal,
+ UInt16 outOptValLen);
+
+static Bool NetLibToSocketsAddr (const NetSocketAddrType& inAddr,
+ const Int16 inAddrLen,
+ sockaddr& outAddr,
+ int outAddrLen);
+static Bool SocketsToNetLibAddr (const sockaddr& inAddr,
+ int inAddrLen,
+ NetSocketAddrType& outAddr,
+ Int16 outAddrLen);
+
+static Bool SocketsToNetLibHostEnt (const hostent& inHostEnt,
+ NetHostInfoBufType& outHostEnt);
+static Bool SocketsToNetLibServEnt (const servent& inServEnt,
+ NetServInfoBufType& outServEnt);
+
+static Bool NetLibToSocketsFDSet (const NetFDSetType* inFDSet,
+ UInt16 inWidth,
+ fd_set*& outFSSet,
+ int& outWidth);
+static Bool SocketsToNetLibFDSet (const fd_set* inFDSet,
+ int inWidth,
+ NetFDSetType* outFSSet,
+ UInt16& outWidth);
+
+static Bool NetLibToSocketsScalarOption (const MemPtr inOptVal,
+ const UInt16 inOptValLen,
+ char*& outOptVal,
+ socklen_t& outOptValLen);
+
+static Bool SocketsToNetLibScalarOption (/*const*/ char*& inOptVal,
+ const int inOptValLen,
+ MemPtr outOptVal,
+ UInt16 outOptValLen);
+
+static uint32 PrvGetError (void);
+static Err PrvGetTranslatedError (void);
+#if PLATFORM_MAC
+static Err PrvGetTranslatedHError (void);
+#endif
+static Err PrvTranslateError (uint32 err);
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform_NetLib::Initialize
+ *
+ * DESCRIPTION: NetLib redirection subsystem initialization routine
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void Platform_NetLib::Initialize (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform_NetLib::Reset
+ *
+ * DESCRIPTION: NetLib redirection subsystem reset routine
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void Platform_NetLib::Reset (void)
+{
+ Dispose();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform_NetLib::Save
+ *
+ * DESCRIPTION: NetLib redirection subsystem state saving routine
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void Platform_NetLib::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform_NetLib::Load
+ *
+ * DESCRIPTION: NetLib redirection subsystem state loading routine
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void Platform_NetLib::Load (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform_NetLib::Dispose
+ *
+ * DESCRIPTION: NetLib redirection subsystem cleanup routine
+ *
+ * PARAMETERS:
+ *
+ * RETURNED:
+ *
+ ***********************************************************************/
+
+void Platform_NetLib::Dispose (void)
+{
+ for (int ii = 0; ii < netMaxNumSockets; ++ii)
+ {
+ if (gSockets[ii] != INVALID_SOCKET)
+ {
+ closesocket (gSockets[ii]);
+ gSockets[ii] = INVALID_SOCKET;
+ }
+ }
+
+ gOpenCount = 0;
+}
+
+
+Bool Platform_NetLib::Redirecting (void)
+{
+ Preference<bool> pref (kPrefKeyRedirectNetLib);
+ return *pref;
+}
+
+
+//--------------------------------------------------
+// Library initialization, shutdown, sleep and wake
+//--------------------------------------------------
+
+Err Platform_NetLib::Open(UInt16 libRefNum, UInt16* netIFErrsP)
+{
+ UNUSED_PARAM(libRefNum)
+
+ // Init return error
+ *netIFErrsP = 0;
+
+#if PLATFORM_WINDOWS
+ if (gWinSockVersion == 0)
+ {
+ return netErrInternal;
+ }
+#endif
+
+ if (gOpenCount > 0)
+ {
+ ++gOpenCount;
+ return netErrAlreadyOpen;
+ }
+
+ ++gOpenCount;
+ return errNone;
+}
+
+Err Platform_NetLib::OpenConfig(UInt16 libRefNum, UInt16 configIndex, UInt32 openFlags,
+ UInt16* netIFErrP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(openFlags)
+
+ Err err = errNone;
+ Boolean needRefresh = false;
+
+ // Init return error
+ *netIFErrP = errNone;
+
+ //-----------------------------------------------------------------
+ // We now have a "lock" on the globals and have prevented all other tasks
+ // from initiating an open or close until we release the lock.
+ // Now, see what the current state of the library is and take the
+ // appropriate action
+ // If it's already open make sure it's a compatible configuration,
+ // if not, it's an error
+ // If we're in the closeWait state see if it's
+ // a compatible configuration, if it is just bump it's open
+ // count and return. If it's not, finish the close before we
+ // change the configuration
+ //-----------------------------------------------------------------
+ if (gOpenCount > 0)
+ {
+ // If we can use the current state...
+ if (configIndex == netConfigIndexCurSettings || configIndex == gCurConfigIndex)
+ {
+ gOpenCount++;
+ if (gOpenCount > 1)
+ err = netErrAlreadyOpen;
+
+ // Refresh connections if necessary
+ needRefresh = true;
+ goto Exit;
+ }
+
+ err = netErrAlreadyOpenWithOtherConfig;
+ goto Exit;
+ }
+
+
+ //-----------------------------------------------------------------
+ // Activate the new configuration. This routine will initialize
+ // the config if it's one of our pre-defined ones that we
+ // know how to initialize and it's the first time we've used it.
+ //
+ // It will also save the current configuration, update the
+ // curConfigIndex field of the config table with the new config
+ // index, and set the restoreConfig index to the old index
+ // so that PrvClose() in the protocol task can restore the
+ // current configuration when it closes the NetLib.
+ //-----------------------------------------------------------------
+ if (configIndex != netConfigIndexCurSettings)
+ {
+ err = NetLibConfigMakeActive (libRefNum, configIndex);
+ // !!! Doesn't do the restoreOldConfigOnClose stuff...
+ if (err)
+ goto Exit;
+
+ gCurConfigIndex = configIndex;
+ }
+
+
+ //-----------------------------------------------------------------
+ // Do the guts of the open. This routine will leave the globals
+ // locked. If it's successful, it will return the new "realGlobals"
+ // ptr. If not, it will leave the shadow globals
+ //-----------------------------------------------------------------
+ err = Platform_NetLib::Open (libRefNum, netIFErrP);
+
+
+ //-----------------------------------------------------------------
+ // Exit now..
+ //-----------------------------------------------------------------
+Exit:
+
+ // See if we should refresh any connections
+ if (!err && needRefresh)
+ {
+ Boolean allIFsUp;
+ err = Platform_NetLib::ConnectionRefresh (libRefNum, true, &allIFsUp, netIFErrP);
+ }
+
+ return err;
+}
+
+Err Platform_NetLib::Close(UInt16 libRefNum, UInt16 immediate)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(immediate)
+
+ if (gOpenCount <= 0)
+ {
+ return netErrNotOpen;
+ }
+
+ --gOpenCount;
+
+ return errNone;
+}
+
+
+Err Platform_NetLib::Sleep(UInt16 libRefNum)
+{
+ UNUSED_PARAM(libRefNum)
+
+ // stub. Do Nothing
+ return errNone;
+}
+
+
+Err Platform_NetLib::Wake(UInt16 libRefNum)
+{
+ UNUSED_PARAM(libRefNum)
+
+ // stub. Do Nothing
+ return errNone;
+}
+
+
+// This call forces the library to complete a close if it's
+// currently in the close-wait state. Returns 0 if library is closed,
+// Returns netErrFullyOpen if library is still open by some other task.
+
+Err Platform_NetLib::FinishCloseWait(UInt16 libRefNum)
+{
+ UNUSED_PARAM(libRefNum)
+
+ // stub. Do Nothing
+ return errNone;
+}
+
+
+// This call is for use by the Network preference panel only. It
+// causes the NetLib to fully open if it's currently in the close-wait
+// state. If it's not in the close wait state, it returns an error code
+
+Err Platform_NetLib::OpenIfCloseWait(UInt16 libRefNum)
+{
+ UNUSED_PARAM(libRefNum)
+
+ return netErrNotOpen;
+}
+
+
+// Get the open Count of the NetLib
+
+Err Platform_NetLib::OpenCount(UInt16 libRefNum, UInt16* countP)
+{
+ UNUSED_PARAM(libRefNum)
+
+ *countP = gOpenCount;
+ return errNone;
+}
+
+
+// Give NetLib a chance to close the connection down in response
+// to a power off event. Returns non-zero if power should not be
+// turned off. EventP points to the event that initiated the power off
+// which is either a keyDownEvent of the hardPowerChr or the autoOffChr.
+// Don't include unless building for Viewer
+
+Err Platform_NetLib::HandlePowerOff (UInt16 libRefNum, EventPtr eventP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(eventP)
+
+ Err err = Platform_NetLib::Close (libRefNum, true);
+
+ // Don't let the fact that we're not open prevent us from powering off.
+ if (err == netErrNotOpen)
+ err = errNone;
+
+ return err;
+}
+
+
+// Check status or try and reconnect any interfaces which have come down.
+// This call can be made by applications when they suspect that an interface
+// has come down (like PPP or SLIP). NOTE: This call can display UI
+// (if 'refresh' is true) so it MUST be called from the UI task.
+
+Err Platform_NetLib::ConnectionRefresh(UInt16 libRefNum,
+ Boolean refresh,
+ Boolean* allInterfacesUpP,
+ UInt16* netIFErrP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(refresh)
+
+ *allInterfacesUpP = true;
+ *netIFErrP =0;
+ return errNone;
+}
+
+
+//--------------------------------------------------
+// Socket creation and option setting
+//--------------------------------------------------
+
+// Create a socket and return a refnum to it. Protocol is normally 0.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+NetSocketRef Platform_NetLib::SocketOpen(UInt16 libRefNum,
+ NetSocketAddrEnum socketDomain,
+ NetSocketTypeEnum socketType,
+ Int16 socketProtocol,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ u_short af;
+ int type;
+ int protocol;
+
+ if (!NetLibToSocketsDomain (socketDomain, af) ||
+ !NetLibToSocketsType (socketType, type) ||
+ !NetLibToSocketsProtocol (socketProtocol, protocol))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ SOCKET s = socket (af, type, protocol);
+
+ if (s == INVALID_SOCKET)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ NetSocketRef result;
+ if (!RememberSocketsRef (s, result))
+ {
+ // !!! Need to close the socket. But we should never
+ // really get here...we allow as many sockets at NetLib
+ // does. I guess if NetLib raised the number of sockets
+ // and we don't, then we'd get here, though...
+ *errP = netErrNoMoreSockets;
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Close a socket.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketClose(UInt16 libRefNum,
+ NetSocketRef sRef,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ if (!NetLibToSocketsRef (sRef, s))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = closesocket (s);
+
+ // Drop our reference to this socket.
+ // !!! Do this even if closesocket fails?
+
+ ForgetSocketsRef (sRef);
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Set a socket option. Level is usually netSocketOptLevelSocket. Option is one of
+// netSocketOptXXXXX. OptValueP is a pointer to the new value and optValueLen is
+// the length of the option value.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketOptionSet(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketOptLevelEnum optLevel,
+ NetSocketOptEnum opt,
+ MemPtr optValueP,
+ UInt16 optValueLen,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ int result;
+
+ if (optLevel == netSocketOptLevelSocket &&
+ opt == netSocketOptSockNonBlocking)
+ {
+ SOCKET s;
+ if (!NetLibToSocketsRef (sRef, s))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+#if PLATFORM_WINDOWS
+ unsigned long param;
+#else
+ long param;
+#endif
+
+ if (optValueLen == 1)
+ param = *(char*) optValueP;
+ else if (optValueLen == 2)
+ param = *(short*) optValueP;
+ else if (optValueLen == 4)
+ param = *(long*) optValueP;
+ else
+ param = 1;
+
+ result = ioctlsocket (s, FIONBIO, &param);
+ }
+ else
+ {
+ SOCKET s;
+ int level;
+ int optName;
+ char* optVal;
+ socklen_t optLen;
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsOptions (optLevel, opt, optValueP, optValueLen, level, optName, optVal, optLen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ result = setsockopt (s, level, optName, optVal, optLen);
+
+ Platform::DisposeMemory (optVal);
+ }
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Get a socket option.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketOptionGet(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketOptLevelEnum optLevel,
+ NetSocketOptEnum opt,
+ MemPtr optValueP,
+ UInt16* optValueLenP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ int level;
+ int optName;
+ char* optVal;
+ socklen_t optLen = *optValueLenP;
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsOptions (optLevel, opt, optValueP, *optValueLenP, level, optName, optVal, optLen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = getsockopt (s, level, optName, optVal, &optLen);
+
+ if (result)
+ {
+ Platform::DisposeMemory (optVal);
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ if (!SocketsToNetLibOptions (level, optName, optVal, optLen, optLevel, opt, optValueP, *optValueLenP))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+//--------------------------------------------------
+// Socket Control
+//--------------------------------------------------
+
+// Bind a source address and port number to a socket. This makes the
+// socket accept incoming packets destined for the given socket address.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketBind(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketAddrType* sockAddrP,
+ Int16 addrLen,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ sockaddr name;
+ int namelen = sizeof (name);
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsAddr (*sockAddrP, addrLen, name, namelen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = bind (s, &name, namelen);
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Connect to a remote socket. For a stream based socket (i.e. TCP), this initiates
+// a 3-way handshake with the remote machine to establish a connection. For
+// non-stream based socket, this merely specifies a destination address and port
+// number for future outgoing packets from this socket.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketConnect(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketAddrType* sockAddrP,
+ Int16 addrLen,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ sockaddr name;
+ int namelen = sizeof (name);
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsAddr (*sockAddrP, addrLen, name, namelen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = connect (s, &name, namelen);
+
+ if (result)
+ {
+ // Work around Windows 2000 bug. According to Mark Baysinger
+ // (<mbaysing@qualcomm.com>):
+ //
+ // Windows 2000 seems to return the wrong error code from connect() with
+ // non-blocking IO when the connection is already in progress. (It returns
+ // WSAEINVAL instead of WSAEALREADY.) This results in NetLibSocketConnect
+ // returning netErrParamErr instead of netErrSocketAlreadyConnected."
+ //
+ // However, according to the connect() documentation on MSDN:
+ //
+ // Until the connection attempt completes on a nonblocking socket, all
+ // subsequent calls to connect on the same socket will fail with the error
+ // value WSAEALREADY, and WSAEISCONN when the connection completes
+ // successfully. Due to ambiguities the Windows Sockets Specification 1.1,
+ // error values returned from connect while a connection is already pending
+ // may vary among implementations. As a result, it is not recommended that
+ // applications use multiple calls to connect to detect connection
+ // completion. If they do, they must be prepared to handle WSAEINVAL and
+ // WSAEWOULDBLOCK error values the same way that they handle WSAEALREADY,
+ // to assure robust execution.
+ //
+ // So it looks like (a) there are other result codes to look for, and (b)
+ // we shouldn't consider only Windows 2000.
+ //
+ // Further Notes:
+ //
+ // In the connect documentation, it says:
+ //
+ // With a nonblocking socket, the connection attempt cannot be completed
+ // immediately. In this case, connect will return SOCKET_ERROR, and
+ // WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are
+ // three possible scenarios: <snip>
+ //
+ // This means that WSAEWOULDBLOCK should not be translated to WSAEALREADY.
+
+
+#if PLATFORM_WINDOWS
+ uint32 err = ::PrvGetError ();
+
+ if (err == WSAEINVAL /*|| err == WSAEWOULDBLOCK*/)
+ {
+ err = WSAEALREADY;
+ }
+
+ *errP = PrvTranslateError (err);
+#else
+ *errP = PrvGetTranslatedError ();
+#endif
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+// Makes a socket ready to accept incoming connection requests. The queueLen
+// specifies the max number of pending connection requests that will be enqueued
+// while the server is busy handling other requests.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketListen(UInt16 libRefNum,
+ NetSocketRef sRef,
+ UInt16 queueLen,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ if (!NetLibToSocketsRef (sRef, s))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = listen (s, queueLen);
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+// Blocks the current process waiting for an incoming connection request. The socket
+// must have previously be put into listen mode through the NetLibSocketListen call.
+// On return, *sockAddrP will have the remote machines address and port number.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketAccept(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketAddrType* sockAddrP,
+ Int16* addrLenP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+
+ if (!NetLibToSocketsRef (sRef, s))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int new_s = accept (s, &addr, &addrlen);
+
+ if (new_s == INVALID_SOCKET)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ NetSocketRef result;
+ if (!RememberSocketsRef (new_s, result))
+ {
+ // !!! Need to un-accept?
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ if (!SocketsToNetLibAddr (addr, addrlen, *sockAddrP, *addrLenP))
+ {
+ // !!! Need to un-accept?
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ *errP = 0;
+ return (Int16) result;
+}
+
+// Shutdown a connection in one or both directions.
+// Only applies to stream based (i.e. TCP) sockets.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketShutdown(UInt16 libRefNum,
+ NetSocketRef sRef,
+ Int16 direction,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ SOCKET s;
+ int how;
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsDirection (direction, how))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ int result = shutdown (s, how);
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Gets the local and remote addresses of a socket. Useful for TCP sockets that
+// get dynamically bound at connect time.
+// Returns 0 on success, -1 on error. If error, *errP gets filled in with error code.
+
+Int16 Platform_NetLib::SocketAddr(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetSocketAddrType* locAddrP,
+ Int16* locAddrLenP,
+ NetSocketAddrType* remAddrP,
+ Int16* remAddrLenP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ int result = 0;
+ SOCKET s;
+
+ if (!NetLibToSocketsRef (sRef, s))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ if (locAddrP && locAddrLenP)
+ {
+ sockaddr locName;
+ socklen_t locNamelen = sizeof (locName);
+
+ result = getsockname (s, &locName, &locNamelen);
+
+ // For unbound sockets, NetLib returns 0.0.0.0
+ // !!! Assumes AF_INET family!
+
+ if (result == -1 && ::PrvGetError () == WSAEINVAL)
+ {
+ result = errNone;
+
+ sockaddr_in& inLocName = (sockaddr_in&) locName;
+
+ memset (&inLocName, 0, sizeof (inLocName));
+
+ inLocName.sin_family = AF_INET;
+ inLocName.sin_port = htons(0);
+ inLocName.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ if (!SocketsToNetLibAddr (locName, locNamelen, *locAddrP, *locAddrLenP))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+ }
+
+ if (remAddrP && remAddrLenP)
+ {
+ sockaddr remName;
+ socklen_t remNamelen = sizeof (remName);
+
+ result = getpeername (s, &remName, &remNamelen);
+
+ if (result)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ if (!SocketsToNetLibAddr (remName, remNamelen, *remAddrP, *remAddrLenP))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+//--------------------------------------------------
+// Sending and Receiving
+//--------------------------------------------------
+// Send data through a socket. The data is specified through the NetIOParamType
+// structure.
+// Flags is one or more of netMsgFlagXXX.
+// Returns # of bytes sent on success, or -1 on error. If error, *errP gets filled
+// in with error code.
+
+Int16 Platform_NetLib::SendPB(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetIOParamType* pbP,
+ UInt16 sendFlags,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+
+ SOCKET s;
+ int flags;
+ int result;
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsFlags (sendFlags, flags))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ // Wait till the socket is ready to send.
+
+ if (timeout >= 0)
+ {
+ fd_set hostWriteFDs;
+ struct timeval hostTimeout;
+ struct timeval *hTp = NULL;
+
+ FD_ZERO(&hostWriteFDs);
+ FD_SET(s, &hostWriteFDs);
+
+ // Convert ticks to microseconds.
+
+ const uint64 kMicrosecondsPerSecond = 1000000;
+ const uint64 kSysTicksPerSecond = 100; // !!! Should really call SysTicksPerSecond.
+
+ uint64 usecs = timeout * kMicrosecondsPerSecond / kSysTicksPerSecond;
+
+ hostTimeout.tv_sec = usecs / kMicrosecondsPerSecond;
+ hostTimeout.tv_usec = usecs % kMicrosecondsPerSecond;
+ hTp = &hostTimeout;
+
+ result = select (s + 1, NULL, &hostWriteFDs, NULL, hTp);
+ if (result == SOCKET_ERROR)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+ else if (!result)
+ {
+ *errP = netErrTimeout;
+ return -1;
+ }
+ }
+
+ // Collapse the scatter-write array into a single big buffer.
+
+ UInt16 ii;
+ long bigBufferSize = 0;
+ for (ii = 0; ii < pbP->iovLen; ++ii)
+ {
+ bigBufferSize += pbP->iov[ii].bufLen;
+ }
+
+ StMemory bigBuffer (bigBufferSize);
+
+ long offset = 0;
+ for (ii = 0; ii < pbP->iovLen; ++ii)
+ {
+ memcpy (bigBuffer.Get() + offset, pbP->iov[ii].bufP, pbP->iov[ii].bufLen);
+ offset += pbP->iov[ii].bufLen;
+ }
+
+ // Determine if we need to set up a return address buffer.
+
+ sockaddr name;
+ sockaddr* nameP = NULL;
+ socklen_t namelen = 0;
+
+ if (pbP->addrP)
+ {
+ nameP = &name;
+ namelen = sizeof (name);
+
+ if (!NetLibToSocketsAddr (*(NetSocketAddrType*) pbP->addrP, pbP->addrLen, name, namelen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+ }
+
+ // Make the send call.
+ //
+ // In previous versions of this function, we tried to make some determination
+ // as to whether send() or sendto() needed to be called. However,
+ // according to the Windows sockets documentation, "On a connection-oriented
+ // socket, the to and tolen parameters are ignored, making sento equivalent
+ // to send". And the GUSI sources back this up. So we just use sendto in
+ // all cases.
+
+ result = sendto (s, bigBuffer.Get(), bigBufferSize, flags, nameP, namelen);
+
+ // If there was an error, translate and return it.
+
+ if (result == SOCKET_ERROR)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Send data through a socket. The data to send is passed in a single buffer,
+// unlike NetLibSendPB. If toAddrP is not nil, the data will be sent to
+// address *toAddrP.
+// Flags is one or more of netMsgFlagXXX.
+// Returns # of bytes sent on success, or -1 on error. If error, *errP gets filled
+// in with error code.
+
+Int16 Platform_NetLib::Send(UInt16 libRefNum,
+ NetSocketRef sRef,
+ const MemPtr bufP,
+ UInt16 bufLen,
+ UInt16 sendFlags,
+ MemPtr toAddrP,
+ UInt16 toLen,
+ Int32 timeout,
+ Err* errP)
+{
+ // Init the iov
+
+ NetIOVecType iov;
+ iov.bufP = (UInt8*) bufP;
+ iov.bufLen = bufLen;
+
+ // Form a paramBlock for the Platform_NetLib::SendPB call
+
+ NetIOParamType pb;
+ if (toLen)
+ {
+ pb.addrP = (UInt8*) toAddrP;
+ pb.addrLen = toLen;
+ }
+ else
+ {
+ pb.addrP = 0;
+ pb.addrLen = 0;
+ }
+
+ pb.iov = &iov;
+ pb.iovLen = 1;
+
+ // Do the call
+
+ Int16 result = SendPB (libRefNum, sRef, &pb, sendFlags, timeout, errP);
+
+ return result;
+}
+
+
+// Receive data from a socket. The data is gatthered into buffers specified in the
+// NetIOParamType structure.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+
+Int16 Platform_NetLib::ReceivePB(UInt16 libRefNum,
+ NetSocketRef sRef,
+ NetIOParamType* pbP,
+ UInt16 rcvFlags,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+
+ SOCKET s;
+ int flags;
+ int result;
+
+ if (!NetLibToSocketsRef (sRef, s) ||
+ !NetLibToSocketsFlags (rcvFlags, flags))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ // Wait till the socket is ready to receive.
+
+ if (timeout >= 0)
+ {
+ fd_set hostReadFDs;
+ struct timeval hostTimeout;
+ struct timeval *hTp = NULL;
+
+ FD_ZERO(&hostReadFDs);
+ FD_SET(s, &hostReadFDs);
+
+ // Convert ticks to microseconds.
+
+ const uint64 kMicrosecondsPerSecond = 1000000;
+ const uint64 kSysTicksPerSecond = 100; // !!! Should really call SysTicksPerSecond.
+
+ uint64 usecs = timeout * kMicrosecondsPerSecond / kSysTicksPerSecond;
+
+ hostTimeout.tv_sec = usecs / kMicrosecondsPerSecond;
+ hostTimeout.tv_usec = usecs % kMicrosecondsPerSecond;
+ hTp = &hostTimeout;
+
+ result = select (s + 1, &hostReadFDs, NULL, NULL, hTp);
+ if (result == SOCKET_ERROR)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+ else if (!result)
+ {
+ *errP = netErrTimeout;
+ return -1;
+ }
+ }
+
+ // Collapse the gather-read array into a single big buffer.
+
+ // First, get the size for the big buffer.
+
+ UInt16 ii;
+ long bigBufferSize = 0;
+ for (ii = 0; ii < pbP->iovLen; ++ii)
+ {
+ bigBufferSize += pbP->iov[ii].bufLen;
+ }
+
+ // Second, allocate the buffer.
+
+ StMemory bigBuffer (bigBufferSize);
+
+ // Third, copy the input buffer's contents to the big buffer.
+
+ long offset = 0;
+ for (ii = 0; ii < pbP->iovLen; ++ii)
+ {
+ memcpy (bigBuffer.Get () + offset, pbP->iov[ii].bufP, pbP->iov[ii].bufLen);
+ offset += pbP->iov[ii].bufLen;
+ }
+
+ // Determine if we need to set up a return address buffer.
+
+ sockaddr name;
+ sockaddr* nameP = NULL;
+ socklen_t namelen = 0;
+
+ if (pbP->addrP)
+ {
+ nameP = &name;
+ namelen = sizeof (name);
+ }
+
+ // Make the receive call.
+ //
+ // In previous versions of this function, we tried to make some determination
+ // as to whether recv() or recvfrom() needed to be called. However,
+ // according to my Linux man page, recv() is the same as recvfrom() but with
+ // a NULL name parameter. So we just use recvfrom in all cases.
+
+ result = recvfrom (s, bigBuffer.Get (), bigBufferSize, flags, nameP, &namelen);
+
+ // If there was an error, translate and return it.
+
+ if (result == SOCKET_ERROR)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ // If we established a return address buffer, return the result
+ // back to the caller.
+
+ if (pbP->addrP)
+ {
+ if (!SocketsToNetLibAddr (name, namelen, *(NetSocketAddrType*) pbP->addrP, pbP->addrLen))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+ }
+
+ // Copy the chunks of the big buffer back into the iov array.
+
+ offset = 0;
+ for (ii = 0; ii < pbP->iovLen; ++ii)
+ {
+ memcpy (pbP->iov[ii].bufP, bigBuffer.Get () + offset, pbP->iov[ii].bufLen);
+ offset += pbP->iov[ii].bufLen;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+// Receive data from a socket. The data is read into a single buffer, unlike
+// NetLibReceivePB. If fromAddrP is not nil, *fromLenP must be initialized to
+// the size of the buffer that fromAddrP points to and on exit *fromAddrP will
+// have the address of the sender in it.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+
+Int16 Platform_NetLib::Receive(UInt16 libRefNum,
+ NetSocketRef sRef,
+ MemPtr bufP,
+ UInt16 bufLen,
+ UInt16 rcvFlags,
+ MemPtr fromAddrP,
+ UInt16* fromLenP,
+ Int32 timeout,
+ Err* errP)
+{
+ NetIOParamType pb;
+ NetIOVecType iov;
+
+ // Assume no error
+ *errP = 0;
+
+ // If no buflen, return 0
+ if (!bufLen)
+ return 0;
+
+ //-------------------------------------------------------------------------
+ // Socket read
+ // Form a paramBlock for the NetLibReceivePB call
+ //-------------------------------------------------------------------------
+ if (fromLenP)
+ {
+ pb.addrLen = *fromLenP;
+ pb.addrP = (UInt8*) fromAddrP;
+ }
+ else
+ {
+ pb.addrLen = 0;
+ pb.addrP = 0;
+ }
+
+ pb.iov = &iov;
+ pb.iovLen = 1;
+
+ // Init the iov
+ iov.bufP = (UInt8*) bufP;
+ iov.bufLen = bufLen;
+
+ // Do the call
+ Int16 result = ReceivePB (libRefNum, sRef, &pb, rcvFlags, timeout, errP);
+
+ // Update the address length, if passed
+ if (fromLenP)
+ *fromLenP = pb.addrLen;
+
+ return result;
+}
+
+// Receive data from a socket directly into a (write-protected) Data Manager
+// record.
+// If fromAddrP is not nil, *fromLenP must be initialized to
+// the size of the buffer that fromAddrP points to and on exit *fromAddrP will
+// have the address of the sender in it.
+// Flags is one or more of netMsgFlagXXX.
+// Timeout is max # of ticks to wait, or -1 for infinite, or 0 for none.
+// Returns # of bytes received, or -1 on error. If error, *errP gets filled in
+// with error code.
+
+Int16 Platform_NetLib::DmReceive(UInt16 libRefNum,
+ NetSocketRef sRef,
+ MemPtr recordP,
+ UInt32 recordOffset,
+ UInt16 rcvLen,
+ UInt16 rcvFlags,
+ MemPtr fromAddrP,
+ UInt16* fromLenP,
+ Int32 timeout,
+ Err* errP)
+{
+ Int16 result = Receive (libRefNum, sRef, ((char*) recordP) + recordOffset,
+ rcvLen, rcvFlags, fromAddrP, fromLenP, timeout, errP);
+
+ return result;
+}
+
+
+//--------------------------------------------------
+// Name Lookups
+//--------------------------------------------------
+
+NetHostInfoPtr Platform_NetLib::GetHostByName(UInt16 libRefNum,
+ Char* nameP,
+ NetHostInfoBufPtr bufP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ hostent* pHostEnt = gethostbyname (nameP);
+
+ if (!pHostEnt)
+ {
+#if PLATFORM_MAC
+ *errP = PrvGetTranslatedHError ();
+#else
+ *errP = PrvGetTranslatedError ();
+#endif
+ return NULL;
+ }
+
+ if (!SocketsToNetLibHostEnt (*pHostEnt, *bufP))
+ {
+ *errP = netErrParamErr;
+ return NULL;
+ }
+
+ *errP = 0;
+ return &(bufP->hostInfo);
+}
+
+
+NetHostInfoPtr Platform_NetLib::GetHostByAddr(UInt16 libRefNum,
+ UInt8* addrP,
+ UInt16 len,
+ UInt16 type,
+ NetHostInfoBufPtr bufP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ hostent* pHostEnt = gethostbyaddr ((const char*) addrP, len, type);
+
+ if (!pHostEnt)
+ {
+#if PLATFORM_MAC
+ *errP = PrvGetTranslatedHError ();
+#else
+ *errP = PrvGetTranslatedError ();
+#endif
+ return NULL;
+ }
+
+ if (!SocketsToNetLibHostEnt (*pHostEnt, *bufP))
+ {
+ *errP = netErrParamErr;
+ return NULL;
+ }
+
+ *errP = 0;
+ return &(bufP->hostInfo);
+}
+
+
+NetServInfoPtr Platform_NetLib::GetServByName(UInt16 libRefNum,
+ Char* servNameP,
+ Char* protoNameP,
+ NetServInfoBufPtr bufP,
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(timeout)
+
+ servent* pServEnt = getservbyname (servNameP, protoNameP);
+
+ if (!pServEnt)
+ {
+ *errP = PrvGetTranslatedError ();
+ return NULL;
+ }
+
+ if (!SocketsToNetLibServEnt (*pServEnt, *bufP))
+ {
+ *errP = netErrParamErr;
+ return NULL;
+ }
+
+ *errP = 0;
+ return &(bufP->servInfo);
+}
+
+
+// Looks up a mail exchange name and returns a list of hostnames for it. Caller
+// must pass space for list of return names (hostNames), space for
+// list of priorities for those hosts (priorities) and max # of names to
+// return (maxEntries).
+// Returns # of entries found, or -1 on error. If error, *errP gets filled in
+// with error code.
+
+Int16 Platform_NetLib::GetMailExchangeByName(UInt16 libRefNum,
+ Char* mailNameP,
+ UInt16 maxEntries,
+ Char hostNames[][netDNSMaxDomainName+1],
+ UInt16 priorities[],
+ Int32 timeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+ UNUSED_PARAM(mailNameP)
+ UNUSED_PARAM(maxEntries)
+ UNUSED_PARAM(hostNames)
+ UNUSED_PARAM(priorities)
+ UNUSED_PARAM(timeout)
+
+ *errP = 0;
+ // TODO
+ return -1;
+}
+
+
+//--------------------------------------------------
+// System level
+//--------------------------------------------------
+
+Int16 Platform_NetLib::Select(UInt16 libRefNum,
+ UInt16 netWidth,
+ NetFDSetType* netReadFDs,
+ NetFDSetType* netWriteFDs,
+ NetFDSetType* netExceptFDs,
+ Int32 netTimeout,
+ Err* errP)
+{
+ UNUSED_PARAM(libRefNum)
+
+ fd_set hostReadFDs;
+ fd_set hostWriteFDs;
+ fd_set hostExceptFDs;
+ int hostWidth = 0;
+
+ fd_set* hostReadFDsP = &hostReadFDs;
+ fd_set* hostWriteFDsP = &hostWriteFDs;
+ fd_set* hostExceptFDsP = &hostExceptFDs;
+
+ if (!NetLibToSocketsFDSet (netReadFDs, netWidth, hostReadFDsP, hostWidth) ||
+ !NetLibToSocketsFDSet (netWriteFDs, netWidth, hostWriteFDsP, hostWidth) ||
+ !NetLibToSocketsFDSet (netExceptFDs, netWidth, hostExceptFDsP, hostWidth))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ timeval hostTimeout;
+ timeval *hTp = NULL;
+ if (netTimeout >= 0)
+ {
+ // Convert ticks (100ths of a second) to microseconds.
+
+ hostTimeout.tv_sec = netTimeout / 100;
+ hostTimeout.tv_usec = (netTimeout % 100) * 10000;
+ hTp = &hostTimeout;
+ }
+
+ int result = select (hostWidth, hostReadFDsP, hostWriteFDsP, hostExceptFDsP, hTp);
+
+ netWidth = 0;
+ if (!SocketsToNetLibFDSet (hostReadFDsP, hostWidth, netReadFDs, netWidth) ||
+ !SocketsToNetLibFDSet (hostWriteFDsP, hostWidth, netWriteFDs, netWidth) ||
+ !SocketsToNetLibFDSet (hostExceptFDsP, hostWidth, netExceptFDs, netWidth))
+ {
+ *errP = netErrParamErr;
+ return -1;
+ }
+
+ if (result == SOCKET_ERROR)
+ {
+ *errP = PrvGetTranslatedError ();
+ return -1;
+ }
+
+ *errP = 0;
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsRef
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsRef (const NetSocketRef inSocket,
+ SOCKET& outSocket)
+{
+ if (inSocket < netMinSocketRefNum || inSocket > netMaxSocketRefNum)
+ return false;
+
+ outSocket = gSockets [inSocket - netMinSocketRefNum];
+
+ if (outSocket == INVALID_SOCKET)
+ return false;
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: RememberSocketsRef
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool RememberSocketsRef (const SOCKET inSocket,
+ NetSocketRef& outSocket)
+{
+ for (int ii = 0; ii < netMaxNumSockets; ++ii)
+ {
+ if (gSockets[ii] == INVALID_SOCKET)
+ {
+ gSockets[ii] = inSocket;
+ outSocket = ii + netMinSocketRefNum;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ForgetSocketsRef
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool ForgetSocketsRef (NetSocketRef sRef)
+{
+ if (sRef >= netMinSocketRefNum && sRef <= netMaxSocketRefNum)
+ {
+ gSockets [sRef - netMinSocketRefNum] = INVALID_SOCKET;
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsDomain
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsDomain (const NetSocketAddrEnum inDomain,
+ u_short& outDomain)
+{
+ Bool result = true;
+
+ switch (inDomain)
+ {
+ case netSocketAddrRaw:
+ outDomain = AF_UNSPEC;
+ break;
+
+ case netSocketAddrINET:
+ outDomain = AF_INET;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsType
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsType ( const NetSocketTypeEnum inType,
+ int& outType)
+{
+ Bool result = true;
+
+ switch (inType)
+ {
+ case netSocketTypeStream:
+ outType = SOCK_STREAM;
+ break;
+
+ case netSocketTypeDatagram:
+ outType = SOCK_DGRAM;
+ break;
+
+ case netSocketTypeRaw:
+ outType = SOCK_RAW;
+ break;
+
+ case netSocketTypeReliableMsg:
+ outType = SOCK_RDM;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsProtocol
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsProtocol ( const Int16 inProtocol,
+ int& outProtocol)
+{
+ Bool result = true;
+
+ switch (inProtocol)
+ {
+ // This first case takes care of situations where applications
+ // call NetLibOpenSocket, passing in zero for the protocol parameter.
+ // Zero doesn't appear to be a valid value when looking at NetMgr.h
+ // but zero *is* defined in WinSock.h, and applications *do* pass it in...
+ //
+ // Actually, the NetLib.c function comments say:
+ //
+ // * protocol - Ignored for datagram or stream sockets in the
+ // * INET domain. If there were more than
+ // * one protocol that implements stream oriented services,
+ // * for example, this parameter would indicate which protocol
+ // * to use.
+ //
+ // It goes on to describe how this parameter is really only used with
+ // "raw" sockets in the INET domain.
+
+ case 0:
+ outProtocol = IPPROTO_IP;
+ break;
+
+ case netSocketProtoIPICMP:
+ outProtocol = IPPROTO_ICMP;
+ break;
+
+ case netSocketProtoIPTCP:
+ outProtocol = IPPROTO_TCP;
+ break;
+
+ case netSocketProtoIPUDP:
+ outProtocol = IPPROTO_UDP;
+ break;
+
+ case netSocketProtoIPRAW:
+ outProtocol = IPPROTO_RAW;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsDirection
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsDirection ( const Int16 inDirection,
+ int& outDirection)
+{
+ Bool result = true;
+
+ switch (inDirection)
+ {
+ case netSocketDirInput:
+ outDirection = SD_RECEIVE;
+ break;
+
+ case netSocketDirOutput:
+ outDirection = SD_SEND;
+ break;
+
+ case netSocketDirBoth:
+ outDirection = SD_BOTH;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsFlags
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsFlags (const UInt16 inFlags, int& outFlags)
+{
+ // Return false if there are any flags set other than the ones we know about.
+ if ((inFlags & ~(netIOFlagOutOfBand | netIOFlagPeek | netIOFlagDontRoute)) != 0)
+ {
+ return false;
+ }
+
+ outFlags = 0;
+
+ if ((inFlags & netIOFlagOutOfBand) != 0)
+ {
+ outFlags |= MSG_OOB;
+ }
+
+ if ((inFlags & netIOFlagPeek) != 0)
+ {
+ outFlags |= MSG_PEEK;
+ }
+
+ if ((inFlags & netIOFlagDontRoute) != 0)
+ {
+ outFlags |= MSG_DONTROUTE;
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsOptions ( const NetSocketOptLevelEnum inOptLevel,
+ const NetSocketOptEnum inOptName,
+ const MemPtr inOptVal,
+ const UInt16 inOptValLen,
+ int& outOptLevel,
+ int& outOptName,
+ char*& outOptVal,
+ socklen_t& outOptValLen)
+{
+ Bool result = false;
+
+ switch (inOptLevel)
+ {
+ case netSocketOptLevelIP:
+ outOptLevel = IPPROTO_IP;
+ switch (inOptName)
+ {
+#ifdef IP_OPTIONS
+ case netSocketOptIPOptions: // Not supported by WinSock 1.x
+ outOptName = IP_OPTIONS;
+ goto Common;
+#endif
+ default: // Tell gcc to shut up about unhandled enumeration values.
+ break;
+ }
+ break;
+
+ case netSocketOptLevelTCP:
+ outOptLevel = IPPROTO_TCP;
+ switch (inOptName)
+ {
+#ifdef TCP_NODELAY
+ case netSocketOptTCPNoDelay:
+ outOptName = TCP_NODELAY;
+ goto Common;
+#endif
+
+#ifdef TCP_MAXSEG
+ case netSocketOptTCPMaxSeg: // Not supported by WinSock
+ outOptName = TCP_MAXSEG;
+ goto Common;
+#endif
+ default: // Tell gcc to shut up about unhandled enumeration values.
+ break;
+ }
+ break;
+
+ case netSocketOptLevelSocket:
+ outOptLevel = SOL_SOCKET;
+ switch (inOptName)
+ {
+#ifdef SO_DEBUG
+ case netSocketOptSockDebug:
+ outOptName = SO_DEBUG;
+ goto Common;
+#endif
+
+#ifdef SO_ACCEPTCONN
+ case netSocketOptSockAcceptConn:
+ outOptName = SO_ACCEPTCONN;
+ goto Common;
+#endif
+
+#ifdef SO_REUSEADDR
+ case netSocketOptSockReuseAddr:
+ outOptName = SO_REUSEADDR;
+ goto Common;
+#endif
+
+#ifdef SO_KEEPALIVE
+ case netSocketOptSockKeepAlive:
+ outOptName = SO_KEEPALIVE;
+ goto Common;
+#endif
+
+#ifdef SO_DONTROUTE
+ case netSocketOptSockDontRoute:
+ outOptName = SO_DONTROUTE;
+ goto Common;
+#endif
+
+#ifdef SO_BROADCAST
+ case netSocketOptSockBroadcast:
+ outOptName = SO_BROADCAST;
+ goto Common;
+#endif
+
+#ifdef SO_USELOOPBACK
+ case netSocketOptSockUseLoopback:
+ outOptName = SO_USELOOPBACK;
+ goto Common;
+#endif
+
+#ifdef SO_LINGER
+ case netSocketOptSockLinger:
+ outOptName = SO_LINGER;
+ if (inOptValLen == sizeof (NetSocketLingerType))
+ {
+ outOptValLen = sizeof (linger);
+ outOptVal = (char*) Platform::AllocateMemory (outOptValLen);
+
+ NetSocketLingerType val = *(NetSocketLingerType*) inOptVal;
+
+ Canonical (val.onOff); // Byteswap on LE machines
+ Canonical (val.time); // Byteswap on LE machines
+
+ ((linger*) outOptVal)->l_onoff = val.onOff;
+ ((linger*) outOptVal)->l_linger = val.time;
+
+ result = true;
+ }
+ break;
+#endif
+
+#ifdef SO_OOBINLINE
+ case netSocketOptSockOOBInLine:
+ outOptName = SO_OOBINLINE;
+ goto Common;
+#endif
+
+#ifdef SO_SNDBUF
+ case netSocketOptSockSndBufSize:
+ outOptName = SO_SNDBUF;
+ goto Common;
+#endif
+
+#ifdef SO_RCVBUF
+ case netSocketOptSockRcvBufSize:
+ outOptName = SO_RCVBUF;
+ goto Common;
+#endif
+
+#ifdef SO_SNDLOWAT
+ case netSocketOptSockSndLowWater: // Not supported by WinSock
+ outOptName = SO_SNDLOWAT;
+ goto Common;
+#endif
+
+#ifdef SO_RCVLOWAT
+ case netSocketOptSockRcvLowWater: // Not supported by WinSock
+ outOptName = SO_RCVLOWAT;
+ goto Common;
+#endif
+
+#ifdef SO_SNDTIMEO
+ case netSocketOptSockSndTimeout: // Not supported by WinSock
+ outOptName = SO_SNDTIMEO;
+ goto Common;
+#endif
+
+#ifdef SO_RCVTIMEO
+ case netSocketOptSockRcvTimeout: // Not supported by WinSock
+ outOptName = SO_RCVTIMEO;
+ goto Common;
+#endif
+
+#ifdef SO_ERROR
+ case netSocketOptSockErrorStatus:
+ outOptName = SO_ERROR;
+ goto Common;
+#endif
+
+#ifdef SO_TYPE
+ case netSocketOptSockSocketType:
+ outOptName = SO_TYPE;
+ goto Common;
+#endif
+
+ default: // Tell gcc to shut up about unhandled enumeration values.
+ break;
+
+Common:
+ result = NetLibToSocketsScalarOption (inOptVal, inOptValLen, outOptVal, outOptValLen);
+ break;
+
+// case netSocketOptSockNonBlocking: // Palm OS Exclusive (special support added in SocketOptionSet)
+// case netSocketOptSockRequireErrClear: // Palm OS Exclusive
+// case netSocketOptSockMultiPktAddr: // Palm OS Exclusive
+ }
+ break;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibOptions
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibOptions (const int inOptLevel,
+ const int inOptName,
+ /*const*/ char*& inOptVal,
+ const int inOptValLen,
+ NetSocketOptLevelEnum outOptLevel,
+ NetSocketOptEnum outOptName,
+ MemPtr outOptVal,
+ UInt16 outOptValLen)
+{
+ UNUSED_PARAM(outOptLevel)
+ UNUSED_PARAM(outOptName)
+
+ Bool result = false;
+
+ switch (inOptLevel)
+ {
+ case IPPROTO_IP:
+ switch (inOptName)
+ {
+#ifdef IP_OPTIONS
+ case IP_OPTIONS: // Not supported by WinSock 1.x
+ goto Common;
+#endif
+ }
+ break;
+
+ case IPPROTO_TCP:
+ switch (inOptName)
+ {
+#ifdef TCP_NODELAY
+ case TCP_NODELAY:
+ goto Common;
+#endif
+
+#ifdef TCP_MAXSEG
+ case TCP_MAXSEG: // Not supported by WinSock
+ goto Common;
+#endif
+ }
+ break;
+
+ case SOL_SOCKET:
+ switch (inOptName)
+ {
+#ifdef SO_ACCEPTCONN
+ case SO_ACCEPTCONN:
+ goto Common;
+#endif
+
+#ifdef SO_USELOOPBACK
+ case SO_USELOOPBACK:
+ goto Common;
+#endif
+
+#ifdef SO_DEBUG
+ case SO_DEBUG:
+ goto Common;
+#endif
+
+#ifdef SO_REUSEADDR
+ case SO_REUSEADDR:
+ goto Common;
+#endif
+
+#ifdef SO_KEEPALIVE
+ case SO_KEEPALIVE:
+ goto Common;
+#endif
+
+#ifdef SO_DONTROUTE
+ case SO_DONTROUTE:
+ goto Common;
+#endif
+
+#ifdef SO_BROADCAST
+ case SO_BROADCAST:
+ goto Common;
+#endif
+
+#ifdef SO_LINGER
+ case SO_LINGER:
+ if (inOptValLen == sizeof (linger))
+ {
+ linger val = *(linger*) inOptVal;
+
+ Canonical (val.l_onoff); // Byteswap on LE machines
+ Canonical (val.l_linger); // Byteswap on LE machines
+
+ ((NetSocketLingerType*) outOptVal)->onOff = val.l_onoff;
+ ((NetSocketLingerType*) outOptVal)->time = val.l_linger;
+
+ Platform::DisposeMemory (inOptVal);
+
+ result = true;
+ }
+ break;
+#endif
+
+#ifdef SO_OOBINLINE
+ case SO_OOBINLINE:
+ goto Common;
+#endif
+
+#ifdef SO_SNDBUF
+ case SO_SNDBUF:
+ goto Common;
+#endif
+
+#ifdef SO_RCVBUF
+ case SO_RCVBUF:
+ goto Common;
+#endif
+
+#ifdef SO_SNDLOWAT
+ case SO_SNDLOWAT: // Not supported by WinSock
+ goto Common;
+#endif
+
+#ifdef SO_RCVLOWAT
+ case SO_RCVLOWAT: // Not supported by WinSock
+ goto Common;
+#endif
+
+#ifdef SO_SNDTIMEO
+ case SO_SNDTIMEO: // Not supported by WinSock
+ goto Common;
+#endif
+
+#ifdef SO_RCVTIMEO
+ case SO_RCVTIMEO: // Not supported by WinSock
+ goto Common;
+#endif
+
+#ifdef SO_ERROR
+ case SO_ERROR:
+ goto Common;
+#endif
+
+#ifdef SO_TYPE
+ case SO_TYPE:
+ goto Common;
+#endif
+
+// case netSocketOptSockNonBlocking: // Palm OS Exclusive (special support added in SocketOptionGet)
+// case netSocketOptSockRequireErrClear: // Palm OS Exclusive
+// case netSocketOptSockMultiPktAddr: // Palm OS Exclusive
+
+Common:
+ result = SocketsToNetLibScalarOption (inOptVal, inOptValLen, outOptVal, outOptValLen);
+ break;
+ }
+ break;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsAddr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsAddr (const NetSocketAddrType& inAddr,
+ const Int16 inAddrLen,
+ sockaddr& outAddr,
+ int outAddrLen)
+{
+ UNUSED_PARAM (inAddrLen)
+
+ Bool result = true;
+
+ switch (inAddr.family)
+ {
+ case netSocketAddrRaw:
+ outAddr.sa_family = AF_UNSPEC;
+#if HAVE_SA_LEN
+ outAddr.sa_len = sizeof (sockaddr);
+#endif
+ memcpy (outAddr.sa_data, inAddr.data, outAddrLen - offsetof (sockaddr, sa_data));
+ break;
+
+ case netSocketAddrINET:
+ ((sockaddr_in&) outAddr).sin_family = AF_INET;
+#if HAVE_SA_LEN
+ ((sockaddr_in&) outAddr).sin_len = sizeof (sockaddr_in);
+#endif
+ ((sockaddr_in&) outAddr).sin_port = ((NetSocketAddrINType&) inAddr).port;
+ ((sockaddr_in&) outAddr).sin_addr.s_addr = ((NetSocketAddrINType&) inAddr).addr;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibAddr
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibAddr (const sockaddr& inAddr,
+ int inAddrLen,
+ NetSocketAddrType& outAddr,
+ Int16 outAddrLen)
+{
+ UNUSED_PARAM (inAddrLen)
+
+ Bool result = true;
+
+ switch (inAddr.sa_family)
+ {
+ case AF_UNSPEC:
+ outAddr.family = netSocketAddrRaw;
+ memcpy (outAddr.data, inAddr.sa_data, outAddrLen - offsetof (NetSocketAddrType, data));
+ break;
+
+ case AF_INET:
+ ((NetSocketAddrINType&) outAddr).family = netSocketAddrINET;
+ ((NetSocketAddrINType&) outAddr).port = ((sockaddr_in&) inAddr).sin_port;
+ ((NetSocketAddrINType&) outAddr).addr = ((sockaddr_in&) inAddr).sin_addr.s_addr;
+ break;
+
+ default:
+ result = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibHostEnt
+ *
+ * DESCRIPTION: Convert a sockets hostent to a NetLib NetHostInfoBufType
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibHostEnt ( const hostent& inHostEnt,
+ NetHostInfoBufType& outHostEnt)
+{
+ Bool result = true;
+
+ // hostent.h_name -> NetHostInfoBufType.name
+ // NetHostInfoBufType.hostInfo.nameP
+ strcpy (outHostEnt.name, inHostEnt.h_name);
+ outHostEnt.hostInfo.nameP = outHostEnt.name;
+
+ // hostent.h_aliases -> NetHostInfoBufType.aliasList
+ // NetHostInfoBufType.aliases
+ // NetHostInfoBufType.hostInfo.nameAliasesP
+ char* curSrcAlias;
+ char* curDestAlias = outHostEnt.aliases[0];
+ long index = 0;
+ while ((index < netDNSMaxAliases) &&
+ ((curSrcAlias = inHostEnt.h_aliases[index]) != NULL))
+ {
+ outHostEnt.aliasList[index] = curDestAlias;
+ strcpy (curDestAlias, curSrcAlias);
+ curDestAlias += strlen (curDestAlias) + 1;
+ if ((((long) curDestAlias) & 1) != 0)
+ ++curDestAlias;
+ ++index;
+ }
+
+ outHostEnt.aliasList[index] = NULL;
+ outHostEnt.hostInfo.nameAliasesP = outHostEnt.aliasList;
+
+ // hostent.h_addrtype -> NetHostInfoBufType.hostInfo.addrType
+ outHostEnt.hostInfo.addrType = inHostEnt.h_addrtype;
+
+ // hostent.h_length -> NetHostInfoBufType.hostInfo.addrLen
+ outHostEnt.hostInfo.addrLen = inHostEnt.h_length;
+
+ // hostent.h_addr_list -> NetHostInfoBufType.addressList
+ // NetHostInfoBufType.address
+ // NetHostInfoBufType.hostInfo.addrListP
+ char* curSrcAddr;
+ NetIPAddr* curDestAddr = outHostEnt.address;
+ /*long*/ index = 0;
+ while ((index < netDNSMaxAddresses) &&
+ ((curSrcAddr = inHostEnt.h_addr_list[index]) != NULL))
+ {
+ outHostEnt.addressList[index] = curDestAddr;
+ memcpy (curDestAddr, curSrcAddr, inHostEnt.h_length);
+ curDestAddr = (NetIPAddr*) (((char*) curDestAddr) + inHostEnt.h_length);
+ ++index;
+ }
+
+ // Comment from PrvDNSNameToAddressHandler in NetStack1.c:
+ //
+ // Long, long ago in a galaxy not so far away, Ron defined a struct
+ // called NetHostInfoBufType. Unfortunately, this struct has a bug
+ // in it, but its too late to fix the problem, because 10 zillion
+ // developers are already using this struct. The problem is that
+ // there can be up to netDNSMaxAddresses + 1 addresses in the array
+ // of addresses referenced via the field addrListP, but he only
+ // reserved space for netDNSMaxAddresses addresses. The additional
+ // address is needed to zero-terminate the list in the case when
+ // the maximum number of DNS addresses are returned. Oh well, too
+ // late now. The problem observed by many is that the null termination
+ // was overwritten the following array, which happened to be the first
+ // returned DNS address. Many folks assume a minimum of at least one
+ // address and just use the first, but if the first returned DNS address
+ // is zero, then bad things happen (or nothing happen!). So, the
+ // so-so solution is to return only netDNSMaxAddresses - 1 entries
+ // (using the last entry for the null termination), even when the
+ // maximum really was returned. Although, by now, most poor
+ // developers have written their own DNS lookup routines and won't
+ // get to use this lovely bug fix anyway.
+
+ if (index == netDNSMaxAddresses)
+ --index;
+
+ outHostEnt.addressList[index] = 0;
+ outHostEnt.hostInfo.addrListP = (UInt8**) &outHostEnt.addressList[0];
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibServEnt
+ *
+ * DESCRIPTION: Convert a sockets servent to a NetLib NetServInfoBufType
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibServEnt ( const servent& inServEnt,
+ NetServInfoBufType& outServEnt)
+{
+ Bool result = true;
+
+ // servent.s_name -> NetServInfoBufType.name
+ // NetServInfoBufType.servInfo.nameP
+ strcpy (outServEnt.name, inServEnt.s_name);
+ outServEnt.servInfo.nameP = outServEnt.name;
+
+ // servent.s_aliases -> NetServInfoBufType.aliasList
+ // NetServInfoBufType.aliases
+ // NetServInfoBufType.servInfo.nameAliasesP
+ char* curSrcAlias;
+ char* curDestAlias = outServEnt.aliases[0];
+ long index = 0;
+ while ((curSrcAlias = inServEnt.s_aliases[index]) != NULL)
+ {
+ outServEnt.aliasList[index] = curDestAlias;
+ strcpy (curDestAlias, curSrcAlias);
+ curDestAlias += strlen (curDestAlias) + 1;
+ if ((((long) curDestAlias) & 1) != 0)
+ ++curDestAlias;
+ ++index;
+
+ if (index == netServMaxAliases)
+ break;
+ }
+
+ outServEnt.aliasList[index] = NULL;
+ outServEnt.servInfo.nameAliasesP = outServEnt.aliasList;
+
+ // servent.s_port -> NetServInfoButType.servInfo.port
+ outServEnt.servInfo.port = inServEnt.s_port;
+
+ // servent.s_proto -> NetServInfoBufType.protoName
+ // NetServInfoBufType.servInfo.protoP
+ strcpy (outServEnt.protoName, inServEnt.s_proto);
+ outServEnt.servInfo.protoP = outServEnt.protoName;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsFDSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsFDSet ( const NetFDSetType* inFDSet,
+ UInt16 inWidth,
+ fd_set*& outFSSet,
+ int& outWidth)
+{
+ Bool result = true;
+ fd_set* finalSetPtr = NULL;
+
+ if (inFDSet)
+ {
+ FD_ZERO (outFSSet);
+
+ if (inWidth > netMaxNumSockets)
+ {
+ inWidth = netMaxNumSockets;
+ }
+
+ for (int ii = 0; ii < inWidth; ++ii)
+ {
+ NetSocketRef sRef = ii + netMinSocketRefNum;
+
+ if (netFDIsSet (sRef, inFDSet))
+ {
+ SOCKET s = gSockets [ii];
+ if (s != INVALID_SOCKET)
+ {
+ FD_SET (s, outFSSet);
+ finalSetPtr = outFSSet;
+
+ outWidth = FD_SETSIZE;
+ }
+ }
+ }
+ }
+
+ outFSSet = finalSetPtr;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibFDSet
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibFDSet ( const fd_set* inFDSet,
+ int inWidth,
+ NetFDSetType* outFSSet,
+ UInt16& outWidth)
+{
+ Bool result = true;
+
+ if (inFDSet && outFSSet)
+ {
+ netFDZero (outFSSet);
+
+ if (inWidth > FD_SETSIZE)
+ {
+ inWidth = FD_SETSIZE;
+ }
+
+ for (int ii = 0; ii < netMaxNumSockets; ++ii)
+ {
+ SOCKET s = gSockets[ii];
+
+ if (s != INVALID_SOCKET && FD_ISSET (s, inFDSet))
+ {
+ netFDSet ((netMinSocketRefNum + ii), outFSSet);
+
+ if (outWidth < ii)
+ {
+ outWidth = ii;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: NetLibToSocketsScalarOption
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool NetLibToSocketsScalarOption ( const MemPtr inOptVal,
+ const UInt16 inOptValLen,
+ char*& outOptVal,
+ socklen_t& outOptValLen)
+{
+ Bool result = true;
+
+ if (inOptVal)
+ {
+ uint32 val = 0;
+ if (inOptValLen == sizeof (uint8))
+ {
+ uint8 temp = *(uint8*) inOptVal;
+ Canonical (temp); // Byteswap on LE machines
+ val = temp;
+ }
+ else if (inOptValLen == sizeof (uint16))
+ {
+ uint16 temp = *(uint16*) inOptVal;
+ Canonical (temp); // Byteswap on LE machines
+ val = temp;
+ }
+ else if (inOptValLen == sizeof (uint32))
+ {
+ uint32 temp = *(uint32*) inOptVal;
+ Canonical (temp); // Byteswap on LE machines
+ val = temp;
+ }
+ else
+ {
+ result = false;
+ }
+
+ if (result)
+ {
+ outOptValLen = sizeof (uint32);
+ outOptVal = (char*) Platform::AllocateMemory (outOptValLen);
+ *(uint32*) outOptVal = val;
+ }
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SocketsToNetLibScalarOption
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+Bool SocketsToNetLibScalarOption (/*const*/ char*& inOptVal,
+ const int inOptValLen,
+ MemPtr outOptVal,
+ UInt16 outOptValLen)
+{
+ Bool result = true;
+
+ if (inOptVal && outOptVal)
+ {
+ if (inOptValLen == outOptValLen)
+ {
+ if (inOptValLen == sizeof (uint8))
+ {
+ uint8 val = *(uint8*) inOptVal;
+ Canonical (val); // Byteswap on LE machines
+ *(uint8*) outOptVal = val;
+ }
+ else if (inOptValLen == sizeof (uint16))
+ {
+ uint16 val = *(uint16*) inOptVal;
+ Canonical (val); // Byteswap on LE machines
+ *(uint16*) outOptVal = val;
+ }
+ else if (inOptValLen == sizeof (uint32))
+ {
+ uint32 val = *(uint32*) inOptVal;
+ Canonical (val); // Byteswap on LE machines
+ *(uint32*) outOptVal = val;
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ result = false;
+ }
+ }
+
+ Platform::DisposeMemory (inOptVal);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetError
+ *
+ * DESCRIPTION: Returns the most recent sockets error number.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: Sockets error number
+ *
+ ***********************************************************************/
+
+uint32 PrvGetError (void)
+{
+#if PLATFORM_MAC || PLATFORM_UNIX
+ uint32 err = errno;
+#endif
+
+#if PLATFORM_WINDOWS
+ uint32 err = ::WSAGetLastError ();
+#endif
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetTranslatedError
+ *
+ * DESCRIPTION: Returns the most recent sockets error number translated
+ * into a NetLib error number.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: NetLib error number
+ *
+ ***********************************************************************/
+
+Err PrvGetTranslatedError (void)
+{
+ uint32 err = ::PrvGetError ();
+
+ return PrvTranslateError (err);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetTranslatedHError
+ *
+ * DESCRIPTION: Returns the most recent sockets error number translated
+ * into a NetLib error number.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: NetLib error number
+ *
+ ***********************************************************************/
+
+#if PLATFORM_MAC
+extern int h_errno;
+const int kHErrNoBase = 30000;
+
+Err PrvGetTranslatedHError (void)
+{
+ // For some reason (I don't know...maybe BSD sockets is like this, too),
+ // GUSI returns errors from gethostbyname() and gethostbyaddr() in h_errno.
+
+ uint32 err = h_errno + kHErrNoBase;
+
+ return PrvTranslateError (err);
+}
+#endif
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvTranslateError
+ *
+ * DESCRIPTION: Convert a Windows Sockets error number to a NetLib error
+ * number.
+ *
+ * PARAMETERS: err - Windows Sockets error number (probably from
+ * WSAGetLastError)
+ *
+ * RETURNED: NetLib error number
+ *
+ ***********************************************************************/
+
+Err PrvTranslateError (uint32 err)
+{
+ Err result = netErrParamErr; // Default error number
+
+ switch (err)
+ {
+#if PLATFORM_MAC || PLATFORM_UNIX
+// case EPERM: // 1 /* Operation not permitted */
+// case ENOENT: // 2 /* No such file or directory */
+// case ESRCH: // 3 /* No such process */
+ case EINTR: // 4 /* Interrupted system call */
+ result = netErrUserCancel;
+ break;
+
+// case EIO: // 5 /* Input/output error */
+// case ENXIO: // 6 /* Device not configured */
+// case E2BIG: // 7 /* Argument list too long */
+// case ENOEXEC: // 8 /* Exec format error */
+// case EBADF: // 9 /* Bad file descriptor */
+// case ECHILD: // 10 /* No child processes */
+ case EDEADLK: // 11 /* Resource deadlock avoided */
+ /* 11 was EAGAIN */
+ result = netErrWouldBlock;
+ break;
+
+ case ENOMEM: // 12 /* Cannot allocate memory */
+ result = netErrOutOfMemory;
+ break;
+
+ case EACCES: // 13 /* Permission denied */
+ result = netErrAuthFailure;
+ break;
+
+// case EFAULT: // 14 /* Bad address */
+// case ENOTBLK: // 15 /* Block device required */
+ case EBUSY: // 16 /* Device busy */
+ result = netErrSocketBusy;
+ break;
+
+// case EEXIST: // 17 /* File exists */
+// case EXDEV: // 18 /* Cross-device link */
+// case ENODEV: // 19 /* Operation not supported by device */
+// case ENOTDIR: // 20 /* Not a directory */
+// case EISDIR: // 21 /* Is a directory */
+// case EINVAL: // 22 /* Invalid argument */
+// case ENFILE: // 23 /* Too many open files in system */
+// case EMFILE: // 24 /* Too many open files */
+// case ENOTTY: // 25 /* Inappropriate ioctl for device */
+// case ETXTBSY: // 26 /* Text file busy */
+// case EFBIG: // 27 /* File too large */
+// case ENOSPC: // 28 /* No space left on device */
+// case ESPIPE: // 29 /* Illegal seek */
+ case EROFS: // 30 /* Read-only file system */
+ result = netErrReadOnlySetting;
+ break;
+
+// case EMLINK: // 31 /* Too many links */
+// case EPIPE: // 32 /* Broken pipe */
+/* math software */
+// case EDOM: // 33 /* Numerical argument out of domain */
+// case ERANGE: // 34 /* Result too large */
+ case EAGAIN: // 35 /* Resource temporarily unavailable */
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK: // EAGAIN /* Operation would block */
+#endif
+ case EINPROGRESS: // 36 /* Operation now in progress */
+ // result = netErrSocketBusy;
+ result = netErrWouldBlock;
+ break;
+
+/* These are defined to be the same under QNX/Neutrino */
+#if EALREADY != EBUSY
+ case EALREADY: // 37 /* Operation already in progress */
+ result = netErrAlreadyInProgress;
+ break;
+#endif
+/* ipc/network software -- argument errors */
+ case ENOTSOCK: // 38 /* Socket operation on non-socket */
+ result = netErrNoSocket;
+ break;
+
+ case EDESTADDRREQ: // 39 /* Destination address required */
+ result = netErrIPNoDst;
+ break;
+
+ case EMSGSIZE: // 40 /* Message too long */
+ result = netErrMessageTooBig;
+ break;
+
+// case EPROTOTYPE: // 41 /* Protocol wrong type for socket */
+ case ENOPROTOOPT: // 42 /* Protocol not available */
+ result = netErrUnknownProtocol;
+ break;
+
+ case EPROTONOSUPPORT: // 43 /* Protocol not supported */
+ result = netErrUnknownProtocol;
+ break;
+
+ case ESOCKTNOSUPPORT: // 44 /* Socket type not supported */
+ result = netErrWrongSocketType;
+ break;
+
+ case EOPNOTSUPP: // 45 /* Operation not supported on socket */
+ result = netErrWrongSocketType;
+ break;
+
+ case EPFNOSUPPORT: // 46 /* Protocol family not supported */
+ result = netErrUnknownService;
+ break;
+
+ case EAFNOSUPPORT: // 47 /* Address family not supported by protocol family */
+ result = netErrUnknownService;
+ break;
+
+ case EADDRINUSE: // 48 /* Address already in use */
+ result = netErrPortInUse;
+ break;
+
+ case EADDRNOTAVAIL: // 49 /* Can't assign requested address */
+ result = netErrPortInUse;
+ break;
+
+/* ipc/network software -- operational errors */
+ case ENETDOWN: // 50 /* Network is down */
+ result = netErrUnreachableDest;
+ break;
+
+ case ENETUNREACH: // 51 /* Network is unreachable */
+ result = netErrNoInterfaces;
+ break;
+
+ case ENETRESET: // 52 /* Network dropped connection on reset */
+ case ECONNABORTED: // 53 /* Software caused connection abort */
+ case ECONNRESET: // 54 /* Connection reset by peer */
+ result = netErrSocketClosedByRemote;
+ break;
+
+ case ENOBUFS: // 55 /* No buffer space available */
+ result = netErrNoTCB;
+ break;
+
+ case EISCONN: // 56 /* Socket is already connected */
+ result = netErrSocketAlreadyConnected;
+ break;
+
+ case ENOTCONN: // 57 /* Socket is not connected */
+ result = netErrSocketNotConnected;
+ break;
+
+ case ESHUTDOWN: // 58 /* Can't send after socket shutdown */
+ result = netErrSocketNotOpen;
+ break;
+
+// case ETOOMANYREFS: // 59 /* Too many references: can't splice */
+ case ETIMEDOUT: // 60 /* Connection timed out */
+ result = netErrTimeout;
+ break;
+
+ case ECONNREFUSED: // 61 /* Connection refused */
+ result = netErrTimeout;
+ break;
+
+// case ELOOP: // 62 /* Too many levels of symbolic links */
+// case ENAMETOOLONG: // 63 /* File name too long */
+ case EHOSTDOWN: // 64 /* Host is down */
+ case EHOSTUNREACH: // 65 /* No route to host */
+ result = netErrIPNoRoute;
+ break;
+
+// case ENOTEMPTY: // 66 /* Directory not empty */
+// case EPROCLIM: // 67 /* Too many processes */
+// case EUSERS: // 68 /* Too many users */
+// case EDQUOT: // 69 /* Disc quota exceeded */
+
+/* Network File System */
+// case ESTALE: // 70 /* Stale NFS file handle */
+// case EREMOTE: // 71 /* Too many levels of remote in path */
+// case EBADRPC: // 72 /* RPC struct is bad */
+// case ERPCMISMATCH: // 73 /* RPC version wrong */
+// case EPROGUNAVAIL: // 74 /* RPC prog. not avail */
+// case EPROGMISMATCH: // 75 /* Program version wrong */
+// case EPROCUNAVAIL: // 76 /* Bad procedure for program */
+// case ENOLCK: // 77 /* No locks available */
+// case ENOSYS: // 78 /* Function not implemented */
+// case EFTYPE: // 79 /* Inappropriate file type or format */
+#endif // PLATFORM_MAC || PLATFORM_UNIX
+
+#if PLATFORM_MAC
+ case HOST_NOT_FOUND + kHErrNoBase: // 1 /* Authoritative Answer Host not found */
+ result = netErrDNSUnreachable;
+ break;
+
+ case TRY_AGAIN + kHErrNoBase: // 2 /* Non-Authoritive Host not found, or SERVERFAIL */
+ result = netErrDNSServerFailure;
+ break;
+
+ case NO_RECOVERY + kHErrNoBase: // 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+ result = netErrDNSRefused;
+ break;
+
+ case NO_DATA + kHErrNoBase: // 4 /* Valid name, no data record of requested type */
+// case NO_ADDRESS + kHErrNoBase: // 4 /* no address, look for MX record */
+ result = netErrDNSNonexistantName;
+ break;
+#endif
+
+#if PLATFORM_WINDOWS
+ case WSAEACCES:
+ // (10013)
+ // Permission denied.
+ // An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).
+ result = netErrWrongSocketType; // BEST I CAN THINK OF.
+ break;
+
+ case WSAEADDRINUSE:
+ // (10048)
+ // Address already in use.
+ // Only one usage of each socket address (protocol/IP address/port) is normally permitted. This error occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that wasn't closed properly, or one that is still in the process of closing. For server applications that need to bind multiple sockets to the same port number, consider using setsockopt(SO_REUSEADDR). Client applications usually need not call bind at all - connect will choose an unused port automatically. When bind is called with a wild-card address (involving ADDR_ANY), a WSAEADDRINUSE error could be delayed until the specific address is "committed." This could happen with a call to other function later, including connect, listen, WSAConnect or WSAJoinLeaf.
+ result = netErrPortInUse;
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ // (10049)
+ // Cannot assign requested address.
+ // The requested address is not valid in its context. Normally results from an attempt to bind to an address that is not valid for the local machine. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote machine (e.g. address or port 0).
+ result = netErrParamErr;
+ break;
+
+ case WSAEAFNOSUPPORT:
+ // (10047)
+ // Address family not supported by protocol family.
+ // An address incompatible with the requested protocol was used. All sockets are created with an associated "address family" (i.e. AF_INET for Internet Protocols) and a generic protocol type (i.e. SOCK_STREAM). This error will be returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, e.g. in sendto.
+ result = netErrParamErr;
+ break;
+
+ case WSAEALREADY:
+ // (10037)
+ // Operation already in progress.
+ // An operation was attempted on a non-blocking socket that already had an operation in progress - i.e. calling connect a second time on a non-blocking socket that is already connecting, or canceling an asynchronous request (WSAAsyncGetXbyY) that has already been canceled or completed.
+ result = netErrAlreadyInProgress;
+ break;
+
+ case WSAECONNABORTED:
+ // (10053)
+ // Software caused connection abort.
+ // An established connection was aborted by the software in your host machine, possibly due to a data transmission timeout or protocol error.
+ result = netErrSocketClosedByRemote;
+ break;
+
+ case WSAECONNREFUSED:
+ // (10061)
+ // Connection refused.
+ // No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host - i.e. one with no server application running.
+ result = netErrTimeout; // As near as I can tell, if a connection is refused, NetLib merely closes the connection and eventually times out.
+ break;
+
+ case WSAECONNRESET:
+ // (10054)
+ // Connection reset by peer.
+ // A existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, or the remote host used a "hard close" (see setsockopt for more information on the SO_LINGER option on the remote socket.) This error may also result if a connection was broken due to "keep-alive" activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
+ result = netErrSocketClosedByRemote;
+ break;
+
+ case WSAEDESTADDRREQ:
+ // (10039)
+ // Destination address required.
+ // A required address was omitted from an operation on a socket. For example, this error will be returned if sendto is called with the remote address of ADDR_ANY.
+ result = netErrParamErr;
+ break;
+
+ case WSAEFAULT:
+ // (10014)
+ // Bad address.
+ // The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument which is a sockaddr is smaller than sizeof(sockaddr).
+ result = netErrParamErr;
+ break;
+
+ case WSAEHOSTDOWN:
+ // (10064)
+ // Host is down.
+ // A socket operation failed because the destination host was down. A socket operation encountered a dead host. Networking activity on the local host has not been initiated. These conditions are more likely to be indicated by the error WSAETIMEDOUT.
+ result = netErrTimeout;
+ break;
+
+ case WSAEHOSTUNREACH:
+ // (10065)
+ // No route to host.
+ // A socket operation was attempted to an unreachable host. See WSAENETUNREACH
+ result = netErrUnreachableDest;
+ break;
+
+ case WSAEINPROGRESS:
+ // (10036)
+ // Operation now in progress.
+ // A blocking operation is currently executing. Windows Sockets only allows a single blocking operation to be outstanding per task (or thread), and if any other function call is made (whether or not it references that or any other socket) the function fails with the WSAEINPROGRESS error.
+ result = netErrAlreadyInProgress;
+ break;
+
+ case WSAEINTR:
+ // (10004)
+ // Interrupted function call.
+ // A blocking operation was interrupted by a call to WSACancelBlockingCall.
+ result = netErrUserCancel;
+ break;
+
+ case WSAEINVAL:
+ // (10022)
+ // Invalid argument.
+ // Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket - for instance, calling accept on a socket that is not listening.
+ result = netErrParamErr;
+ break;
+
+ case WSAEISCONN:
+ // (10056)
+ // Socket is already connected.
+ // A connect request was made on an already connected socket. Some implementations also return this error if sendto is called on a connected SOCK_DGRAM socket (For SOCK_STREAM sockets, the to parameter in sendto is ignored), although other implementations treat this as a legal occurrence.
+ result = netErrSocketAlreadyConnected;
+ break;
+
+ case WSAEMFILE:
+ // (10024)
+ // Too many open files.
+ // Too many open sockets. Each implementation may have a maximum number of socket handles available, either globally, per process or per thread.
+ result = netErrNoMoreSockets;
+ break;
+
+ case WSAEMSGSIZE:
+ // (10040)
+ // Message too long.
+ // A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself.
+ result = netErrMessageTooBig;
+ break;
+
+ case WSAENETDOWN:
+ // (10050)
+ // Network is down.
+ // A socket operation encountered a dead network. This could indicate a serious failure of the network system (i.e. the protocol stack that the WinSock DLL runs over), the network interface, or the local network itself.
+ result = netErrUnreachableDest;
+ break;
+
+ case WSAENETRESET:
+ // (10052)
+ // Network dropped connection on reset.
+ // The connection has been broken due to "keep-alive" activity detecting a failure while the operation was in progress. It can also be returned by setsockopt if an attempt is made to set SO_KEEPALIVE on a connection that has already failed.
+ result = netErrSocketClosedByRemote;
+ break;
+
+ case WSAENETUNREACH:
+ // (10051)
+ // Network is unreachable.
+ // A socket operation was attempted to an unreachable network. This usually means the local software knows no route to reach the remote host.
+ result = netErrUnreachableDest;
+ break;
+
+ case WSAENOBUFS:
+ // (10055)
+ // No buffer space available.
+ // An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
+ result = netErrOutOfMemory;
+ break;
+
+ case WSAENOPROTOOPT:
+ // (10042)
+ // Bad protocol option.
+ // An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call.
+ result = netErrParamErr;
+ break;
+
+ case WSAENOTCONN:
+ // (10057)
+ // Socket is not connected.
+ // A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this error - for example, setsockopt setting SO_KEEPALIVE if the connection has been reset.
+ result = netErrSocketNotConnected;
+ break;
+
+ case WSAENOTSOCK:
+ // (10038)
+ // Socket operation on non-socket.
+ // An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.
+ result = netErrParamErr;
+ break;
+
+ case WSAEOPNOTSUPP:
+ // (10045)
+ // Operation not supported.
+ // The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation, for example, trying to accept a connection on a datagram socket.
+ result = netErrWrongSocketType;
+ break;
+
+ case WSAEPFNOSUPPORT:
+ // (10046)
+ // Protocol family not supported.
+ // The protocol family has not been configured into the system or no implementation for it exists. Has a slightly different meaning to WSAEAFNOSUPPORT, but is interchangeable in most cases, and all Windows Sockets functions that return one of these specify WSAEAFNOSUPPORT.
+ result = netErrParamErr;
+ break;
+
+ case WSAEPROCLIM:
+ // (10067)
+ // Too many processes.
+ // A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously. WSAStartup may fail with this error if the limit has been reached.
+ result = netErrOutOfResources;
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ // (10043)
+ // Protocol not supported.
+ // The requested protocol has not been configured into the system, or no implementation for it exists. For example, a socket call requests a SOCK_DGRAM socket, but specifies a stream protocol.
+ result = netErrUnknownProtocol;
+ break;
+
+ case WSAEPROTOTYPE:
+ // (10041)
+ // Protocol wrong type for socket.
+ // A protocol was specified in the socket function call that does not support the semantics of the socket type requested. For example, the ARPA Internet UDP protocol cannot be specified with a socket type of SOCK_STREAM.
+ result = netErrUnknownProtocol;
+ break;
+
+ case WSAESHUTDOWN:
+ // (10058)
+ // Cannot send after socket shutdown.
+ // A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call. By calling shutdown a partial close of a socket is requested, which is a signal that sending or receiving or both has been discontinued.
+ result = netErrNotOpen;
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ // (10044)
+ // Socket type not supported.
+ // The support for the specified socket type does not exist in this address family. For example, the optional type SOCK_RAW might be selected in a socket call, and the implementation does not support SOCK_RAW sockets at all.
+ result = netErrParamErr;
+ break;
+
+ case WSAETIMEDOUT:
+ // (10060)
+ // Connection timed out.
+ // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
+ result = netErrTimeout;
+ break;
+
+// case WSATYPE_NOT_FOUND:
+ // (10109)
+ // Class type not found.
+ // The specified class was not found.
+
+ case WSAEWOULDBLOCK:
+ // (10035)
+ // Resource temporarily unavailable.
+ // This error is returned from operations on non-blocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a non-fatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a non-blocking SOCK_STREAM socket, since some time must elapse for the connection to be established.
+ result = netErrWouldBlock;
+ break;
+
+ case WSAHOST_NOT_FOUND:
+ // (11001)
+ // Host not found.
+ // No such host is known. The name is not an official hostname or alias, or it cannot be found in the database(s) being queried. This error may also be returned for protocol and service queries, and means the specified name could not be found in the relevant database.
+ result = netErrDNSNonexistantName;
+ break;
+
+// case WSA_INVALID_HANDLE:
+ // (OS dependent)
+ // Specified event object handle is invalid.
+ // An application attempts to use an event object, but the specified handle is not valid.
+
+// case WSA_INVALID_PARAMETER:
+ // (OS dependent)
+ // One or more parameters are invalid.
+ // An application used a Windows Sockets function which directly maps to a Win32 function. The Win32 function is indicating a problem with one or more parameters.
+
+// case WSAINVALIDPROCTABLE:
+ // (OS dependent)
+ // Invalid procedure table from service provider.
+ // A service provider returned a bogus proc table to WS2_32.DLL. (Usually caused by one or more of the function pointers being NULL.)
+
+// case WSAINVALIDPROVIDER:
+ // (OS dependent)
+ // Invalid service provider version number.
+ // A service provider returned a version number other than 2.0.
+
+// case WSA_IO_INCOMPLETE:
+ // (OS dependent)
+ // Overlapped I/O event object not in signaled state.
+ // The application has tried to determine the status of an overlapped operation which is not yet completed. Applications that use WSAGetOverlappedResult (with the fWait flag set to false) in a polling mode to determine when an overlapped operation has completed will get this error code until the operation is complete.
+
+// case WSA_IO_PENDING:
+ // (OS dependent)
+ // Overlapped operations will complete later.
+ // The application has initiated an overlapped operation which cannot be completed immediately. A completion indication will be given at a later time when the operation has been completed.
+
+// case WSA_NOT_ENOUGH_MEMORY:
+ // (OS dependent)
+ // Insufficient memory available.
+ // An application used a Windows Sockets function which directly maps to a Win32 function. The Win32 function is indicating a lack of required memory resources.
+
+ case WSANOTINITIALISED:
+ // (10093)
+ // Successful WSAStartup not yet performed.
+ // Either the application hasn't called WSAStartup or WSAStartup failed. The application may be accessing a socket which the current active task does not own (i.e. trying to share a socket between tasks), or WSACleanup has been called too many times.
+ result = netErrNotOpen;
+ break;
+
+ case WSANO_DATA:
+ // (11004)
+ // Valid name, no data record of requested type.
+ // The requested name is valid and was found in the database, but it does not have the correct associated data being resolved for. The usual example for this is a hostname -> address translation attempt (using gethostbyname or WSAAsyncGetHostByName) which uses the DNS (Domain Name Server), and an MX record is returned but no A record - indicating the host itself exists, but is not directly reachable.
+ result = netErrDNSFormat;
+ break;
+
+ case WSANO_RECOVERY:
+ // (11003)
+ // This is a non-recoverable error.
+ // This indicates some sort of non-recoverable error occurred during a database lookup. This may be because the database files (e.g. BSD-compatible HOSTS, SERVICES or PROTOCOLS files) could not be found, or a DNS request was returned by the server with a severe error.
+ result = netErrInternal;
+ break;
+
+// case WSAPROVIDERFAILEDINIT:
+ // (OS dependent)
+ // Unable to initialize a service provider.
+ // Either a service provider's DLL could not be loaded (LoadLibrary failed) or the provider's WSPStartup/NSPStartup function failed.
+
+// case WSASYSCALLFAILURE:
+ // (OS dependent)
+ // System call failure.
+ // Returned when a system call that should never fail does. For example, if a call to WaitForMultipleObjects fails or one of the registry functions fails trying to manipulate theprotocol/namespace catalogs.
+
+ case WSASYSNOTREADY:
+ // (10091)
+ // Network subsystem is unavailable.
+ // This error is returned by WSAStartup if the Windows Sockets implementation cannot function at this time because the underlying system it uses to provide network services is currently unavailable. Users should check:
+ // * that the appropriate Windows Sockets DLL file is in the current path,
+ // * that they are not trying to use more than one Windows Sockets implementation simultaneously. If there is more than one WINSOCK DLL on your system, be sure the first one in the path is appropriate for the network subsystem currently loaded.
+ // * the Windows Sockets implementation documentation to be sure all necessary components are currently installed and configured correctly.
+ result = netErrInternal;
+ break;
+
+ case WSATRY_AGAIN:
+ // (11002)
+ // Non-authoritative host not found.
+ // This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server. A retry at some time later may be successful.
+ result = netErrDNSTimeout;
+ break;
+
+ case WSAVERNOTSUPPORTED:
+ // (10092)
+ // WINSOCK.DLL version out of range.
+ // The current Windows Sockets implementation does not support the Windows Sockets specification version requested by the application. Check that no old Windows Sockets DLL files are being accessed.
+ result = netErrInternal;
+ break;
+
+ case WSAEDISCON:
+ // (10094)
+ // Graceful shutdown in progress.
+ // Returned by WSARecv and WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence.
+ result = netErrSocketNotConnected;
+ break;
+
+// case WSA_OPERATION_ABORTED:
+ // (OS dependent)
+ // Overlapped operation aborted.
+ // An overlapped operation was canceled due to the closure of the socket, or the execution of the SIO_FLUSH command in WSAIoctl.
+#endif // PLATFORM_WINDOWS
+ }
+
+ PRINTF ("PrvTranslateError: mapping host error code %ld (0x%08lX) to NetLib code %ld (0x%08lX).",
+ err, err, result, result);
+
+ return result;
+}
diff --git a/SrcShared/PreferenceMgr.cpp b/SrcShared/PreferenceMgr.cpp
new file mode 100644
index 0000000..f15bab3
--- /dev/null
+++ b/SrcShared/PreferenceMgr.cpp
@@ -0,0 +1,2564 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "PreferenceMgr.h"
+
+#include "EmCPU.h" // gCPU
+#include "EmHAL.h" // EmHAL::GetLineDriverState
+#include "EmMapFile.h" // EmMapFile
+#include "EmSession.h" // EmSessionStopper
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "EmTransportSocket.h" // EmTransportSocket
+#include "EmTransportUSB.h" // EmTransportUSB
+#include "Platform.h" // _stricmp
+#include "StringConversions.h" // ToString, FromString
+
+#include <algorithm> // find()
+#include <ctype.h> // isdigit
+
+Preferences* gPrefs;
+EmulatorPreferences* gEmuPrefs;
+omni_mutex Preferences::fgPrefsMutex;
+
+
+// Define all the keys
+
+#define DEFINE_PREF_KEYS(name, type, init) const char* kPrefKey##name = #name;
+FOR_EACH_PREF(DEFINE_PREF_KEYS)
+
+static void PrvFilterFileRefList (PrefKeyType key);
+static EmTransportType PrvGetTransportTypeFromPortName (const char* portName);
+
+static Bool PrvFirstBeginsWithSecond (const string& first, const string& second)
+{
+ // Return true if the first string starts with the second string, and
+ // if the point where they both end in common is either the end of
+ // the first string or a delimiter indicating that a sub-part follows.
+
+ return
+ (first.size () >= second.size ()) &&
+ (memcmp (first.c_str (), second.c_str (), second.size ()) == 0) &&
+ ((first.size () == second.size ()) ||
+ (first[second.size ()] == '.') ||
+ (first[second.size ()] == '['));
+}
+
+
+// ----------------------------------------------------------------------
+// * BasePreference
+//
+// Clients of the prefernces sub-system access the data via Preference
+// objects. These objects are created from the Preference class,
+// which the client templatizes based on the data type in which they
+// want the data returned.
+//
+// Preference descends from BasePreference, which implements generic
+// functionality. If we were to put this functionality into Preference
+// itself, we'd have massive unnecessary code bloat.
+// ----------------------------------------------------------------------
+
+/***********************************************************************
+ *
+ * FUNCTION: BasePreference constructor
+ *
+ * DESCRIPTION: Initializes all the data members.
+ *
+ * PARAMETERS: name - name of the key used to fetch the data.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+BasePreference::BasePreference (PrefKeyType name, bool acquireLock) :
+ fName (name),
+ fLoaded (false),
+ fChanged (false),
+ fAcquireLock (acquireLock)
+{
+}
+
+BasePreference::BasePreference (long index, bool acquireLock) :
+ fName (::ToString (index)),
+ fLoaded (false),
+ fChanged (false),
+ fAcquireLock (acquireLock)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: BasePreference destructor
+ *
+ * DESCRIPTION: Destroys all the data members.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+BasePreference::~BasePreference (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: BasePreference::Load
+ *
+ * DESCRIPTION: Lock the preference data and attempt to load the item
+ * specified by the key (specified to the constructor).
+ * If the data was able to be loaded (which pretty much
+ * means that we were able to convert it into the correct
+ * type, set fLoaded to true.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void BasePreference::Load (void)
+{
+ if (fAcquireLock)
+ {
+ // Lock this here. In case DoLoad sets the prefix, we don't want
+ // any other threads accidently using or changing that prefix.
+
+ omni_mutex_lock lock (Preferences::fgPrefsMutex);
+
+ if (this->DoLoad ())
+ {
+ fLoaded = true;
+ }
+ }
+ else
+ {
+ if (this->DoLoad ())
+ {
+ fLoaded = true;
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: BasePreference::Save
+ *
+ * DESCRIPTION: If the data has been change (via operator=()), lock the
+ * preference data and store the entry back out to it.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void BasePreference::Save (void)
+{
+ if (fChanged)
+ {
+ // Lock this here. In case DoSave sets the prefix, we don't want
+ // any other threads accidently using or chaning that prefix.
+
+ if (fAcquireLock)
+ {
+ omni_mutex_lock lock (Preferences::fgPrefsMutex);
+
+ this->DoSave ();
+ fChanged = false;
+ }
+ else
+ {
+ this->DoSave ();
+ fChanged = false;
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------
+// * Preference<T>
+//
+// Clients of the prefernces sub-system access the data via Preference
+// objects. These objects are created from the Preference class,
+// which the client templatizes based on the data type in which they
+// want the data returned.
+//
+// Once an object has been created, the preference value can be fetched
+// with the * operator:
+//
+// Preference<bool> pref(kPrefKeySomeSetting);
+// if (*pref)
+// ...
+//
+// The value can also be fetched with the -> operator:
+//
+// Preference<RGBType> pref(kPrefKeySomeColor);
+// if (pref->fRed == 0 && pref->fGreen == 0 && pref->fBlue == 0)
+// ...
+//
+// The value can be changed by simply assigning to the Preference object:
+//
+// Preference<string> pref(kPrefKeySomeString);
+// pref = string ("new string value");
+//
+// You can find out if there is a valid value for the desired preference
+// by calling Loaded():
+//
+// Preference<bool> pref1(kPrefKeySomeSetting);
+// pref1 = true;
+//
+// Preference<GremlinInfo> pref2(kPrefKeySomeSetting);
+// if (pref2.Loaded ())
+// ... fails because we can't convert a bool to a GremlinInfo...
+//
+// Preference<bool> pref3("bogus undefined key);
+// if (pref3.Loaded ())
+// ... fails because we key was not found...
+//
+// ----------------------------------------------------------------------
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preference<T> constructor
+ *
+ * DESCRIPTION: Calls BasePreference to initialize the base members,
+ * then calls Load() to load the data.
+ *
+ * PARAMETERS: name - name of the key used to fetch the data.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+template <class T>
+Preference<T>::Preference (PrefKeyType name, bool acquireLock) :
+ BasePreference (name, acquireLock),
+ fValue (T())
+{
+ this->Load ();
+}
+
+template <class T>
+Preference<T>::Preference (long index, bool acquireLock) :
+ BasePreference (index, acquireLock),
+ fValue (T())
+{
+ this->Load ();
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preference<T> destructor
+ *
+ * DESCRIPTION: Ensures that any changes are flushed back to the
+ * preference collection before destructing the base class.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+template <class T>
+Preference<T>::~Preference (void)
+{
+ this->Save ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preference<T>::DoLoad
+ *
+ * DESCRIPTION: Virtual function responsible for the actual conversion
+ * of string information into natural data types.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if the function could be loaded and converted.
+ * False otherwise.
+ *
+ ***********************************************************************/
+
+template <class T>
+bool Preference<T>::DoLoad (void)
+{
+ string value;
+
+ if (gPrefs->GetPref (fName, value) && ::FromString (value, fValue))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preference<T>::DoSave
+ *
+ * DESCRIPTION: Virtual function responsible for the actual conversion
+ * of our natural data types into strings.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+template <class T>
+void Preference<T>::DoSave (void)
+{
+ gPrefs->SetPref (fName, ::ToString (fValue));
+}
+
+
+// ----------------------------------------------------------------------
+// Instantiations of Preference class for all non-compound types.
+// ----------------------------------------------------------------------
+
+template class Preference<bool>;
+template class Preference<char>;
+template class Preference<signed char>;
+template class Preference<unsigned char>;
+template class Preference<signed short>;
+template class Preference<unsigned short>;
+template class Preference<signed int>;
+template class Preference<unsigned int>;
+template class Preference<signed long>;
+template class Preference<unsigned long>;
+
+//template class Preference<EmDirRef>;
+template class Preference<EmFileRef>;
+template class Preference<string>;
+
+//template class Preference<Bool>;
+template class Preference<CloseActionType>;
+template class Preference<EmDevice>;
+template class Preference<EmErrorHandlingOption>;
+
+
+// ----------------------------------------------------------------------
+// Specializations of Preference class for compound types.
+//
+// template Preference<Configuration>;
+// template Preference<DatabaseInfo>;
+// template Preference<DatabaseInfoList>;
+// template Preference<EmFileRefList>;
+// template Preference<GremlinInfo>;
+// template Preference<PointType>;
+// template Preference<EmPoint>;
+// template Preference<RGBType>;
+// template Preference<SkinNameList>;
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<Configuration>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("fDeviceType", value) && ::FromString (value, fValue.fDevice) &&
+ gPrefs->GetPref ("fRAMSize", value) && ::FromString (value, fValue.fRAMSize) &&
+ gPrefs->GetPref ("fROMFile", value) && ::FromString (value, fValue.fROMFile))
+ {
+ loaded = true;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<Configuration>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("fDeviceType", ::ToString (fValue.fDevice));
+ gPrefs->SetPref ("fRAMSize", ::ToString (fValue.fRAMSize));
+ gPrefs->SetPref ("fROMFile", ::ToString (fValue.fROMFile));
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<DatabaseInfo>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("creator", value) && ::FromString (value, fValue.creator) &&
+ gPrefs->GetPref ("type", value) && ::FromString (value, fValue.type) &&
+ gPrefs->GetPref ("version", value) && ::FromString (value, fValue.version) &&
+ gPrefs->GetPref ("dbID", value) && ::FromString (value, fValue.dbID) &&
+ gPrefs->GetPref ("cardNo", value) && ::FromString (value, fValue.cardNo) &&
+ gPrefs->GetPref ("modDate", value) && ::FromString (value, fValue.modDate) &&
+ gPrefs->GetPref ("dbAttrs", value) && ::FromString (value, fValue.dbAttrs) &&
+ gPrefs->GetPref ("name", value) && ::FromString (value, fValue.name))
+ {
+ loaded = true;
+
+ // Workaround a bug in older Posers. I forgot to write out the dbName,
+ // so not all preference files have that field. If it's there, read it.
+ // Otherwise, use application name.
+ //
+ // !!! May instead want to set dbName to "\0" and try to fix it up later.
+ if (gPrefs->GetPref ("dbName", value) && ::FromString (value, fValue.dbName))
+ {
+ }
+ else
+ {
+ strcpy (fValue.dbName, fValue.name);
+ }
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<DatabaseInfo>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("creator", ::ToString (fValue.creator));
+ gPrefs->SetPref ("type", ::ToString (fValue.type));
+ gPrefs->SetPref ("version", ::ToString (fValue.version));
+ gPrefs->SetPref ("dbID", ::ToString (fValue.dbID));
+ gPrefs->SetPref ("cardNo", ::ToString (fValue.cardNo));
+ gPrefs->SetPref ("modDate", ::ToString (fValue.modDate));
+ gPrefs->SetPref ("dbAttrs", ::ToString (fValue.dbAttrs));
+ gPrefs->SetPref ("name", ::ToString (fValue.name));
+ gPrefs->SetPref ("dbName", ::ToString (fValue.dbName));
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<DatabaseInfoList>::DoLoad (void)
+{
+ bool loaded = true;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ while (1)
+ {
+ Preference<DatabaseInfo> pref (ii++, false);
+ if (!pref.Loaded ())
+ break;
+
+ fValue.push_back (*pref);
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<DatabaseInfoList>::DoSave (void)
+{
+ gPrefs->DeletePref (fName);
+
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ DatabaseInfoList::iterator iter = fValue.begin ();
+ while (iter != fValue.end ())
+ {
+ Preference<DatabaseInfo> pref (ii++, false);
+ pref = *iter;
+
+ ++iter;
+ }
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<EmFileRefList>::DoLoad (void)
+{
+ bool loaded = true;
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ while (1)
+ {
+ Preference<EmFileRef> pref (ii++, false);
+ if (!pref.Loaded ())
+ break;
+
+ fValue.push_back (*pref);
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<EmFileRefList>::DoSave (void)
+{
+ gPrefs->DeletePref (fName);
+
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ EmFileRefList::iterator iter = fValue.begin ();
+ while (iter != fValue.end ())
+ {
+ Preference<EmFileRef> pref (ii++, false);
+ pref = *iter;
+
+ ++iter;
+ }
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<GremlinInfo>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("fNumber", value) && ::FromString (value, fValue.fNumber) &&
+ gPrefs->GetPref ("fSteps", value) && ::FromString (value, fValue.fSteps) &&
+ gPrefs->GetPref ("fSaveFrequency", value) && ::FromString (value, fValue.fSaveFrequency))
+ {
+ loaded = true;
+ }
+
+ if (loaded)
+ {
+ Preference<DatabaseInfoList> pref ("fAppList", false);
+ if (pref.Loaded ())
+ {
+ fValue.fAppList = *pref;
+ }
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<GremlinInfo>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("fNumber", ::ToString (fValue.fNumber));
+ gPrefs->SetPref ("fSteps", ::ToString (fValue.fSteps));
+ gPrefs->SetPref ("fSaveFrequency", ::ToString (fValue.fSaveFrequency));
+
+ // Save the fAppList collection.
+ {
+ Preference<DatabaseInfoList> pref ("fAppList", false);
+ pref = fValue.fAppList;
+ }
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<HordeInfo>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ // If the old fields exist, convert them to new fields and delete them.
+ if (gPrefs->GetPref ("fDepthBound", value) && ::FromString (value, fValue.fSwitchDepth) &&
+ gPrefs->GetPref ("fSaveFrequency", value) && ::FromString (value, fValue.fSaveFrequency) &&
+ gPrefs->GetPref ("fMaxDepth", value) && ::FromString (value, fValue.fMaxDepth))
+ {
+ fValue.OldToNew (); // Transfer the old fields to the new fields.
+
+ gPrefs->SetPref ("fDepthSwitch", ::ToString (fValue.fDepthSwitch));
+ gPrefs->SetPref ("fDepthSave", ::ToString (fValue.fDepthSave));
+ gPrefs->SetPref ("fDepthStop", ::ToString (fValue.fDepthStop));
+ gPrefs->SetPref ("fCanSwitch", ::ToString (fValue.fCanSwitch));
+ gPrefs->SetPref ("fCanSave", ::ToString (fValue.fCanSave));
+ gPrefs->SetPref ("fCanStop", ::ToString (fValue.fCanStop));
+
+ gPrefs->DeletePref ("fDepthBound");
+ gPrefs->DeletePref ("fSaveFrequency");
+ gPrefs->DeletePref ("fMaxDepth");
+ }
+
+ if (gPrefs->GetPref ("fStartNumber", value) && ::FromString (value, fValue.fStartNumber) &&
+ gPrefs->GetPref ("fStopNumber", value) && ::FromString (value, fValue.fStopNumber) &&
+ gPrefs->GetPref ("fDepthSwitch", value) && ::FromString (value, fValue.fDepthSwitch) &&
+ gPrefs->GetPref ("fDepthSave", value) && ::FromString (value, fValue.fDepthSave) &&
+ gPrefs->GetPref ("fDepthStop", value) && ::FromString (value, fValue.fDepthStop) &&
+ gPrefs->GetPref ("fCanSwitch", value) && ::FromString (value, fValue.fCanSwitch) &&
+ gPrefs->GetPref ("fCanSave", value) && ::FromString (value, fValue.fCanSave) &&
+ gPrefs->GetPref ("fCanStop", value) && ::FromString (value, fValue.fCanStop) &&
+ gPrefs->GetPref ("fFirstLaunchedAppName", value) && ::FromString (value, fValue.fFirstLaunchedAppName))
+ {
+ loaded = true;
+ fValue.NewToOld (); // Transfer the new fields to the old fields.
+ }
+
+ if (loaded)
+ {
+ Preference<DatabaseInfoList> pref ("fAppList", false);
+ if (pref.Loaded ())
+ {
+ fValue.fAppList = *pref;
+ }
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<HordeInfo>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("fStartNumber", ::ToString (fValue.fStartNumber));
+ gPrefs->SetPref ("fStopNumber", ::ToString (fValue.fStopNumber));
+ gPrefs->SetPref ("fDepthSwitch", ::ToString (fValue.fDepthSwitch));
+ gPrefs->SetPref ("fDepthSave", ::ToString (fValue.fDepthSave));
+ gPrefs->SetPref ("fDepthStop", ::ToString (fValue.fDepthStop));
+ gPrefs->SetPref ("fCanSwitch", ::ToString (fValue.fCanSwitch));
+ gPrefs->SetPref ("fCanSave", ::ToString (fValue.fCanSave));
+ gPrefs->SetPref ("fCanStop", ::ToString (fValue.fCanStop));
+ gPrefs->SetPref ("fFirstLaunchedAppName", ::ToString (fValue.fFirstLaunchedAppName));
+
+ // Save the fAppList collection.
+ {
+ Preference<DatabaseInfoList> pref ("fAppList", false);
+ pref = fValue.fAppList;
+ }
+
+
+ gPrefs->PopPrefix ();
+}
+
+
+// ----------------------------------------------------------------------
+
+ // It's odd that we have to provide explicit specializations of the
+ // constructor and destructor for Preference<PointType>. I think it
+ // has something to do with the fact that PointType doesn't have a
+ // constructor of its own.
+
+template <>
+Preference<PointType>::Preference (PrefKeyType name, bool acquireLock) :
+ BasePreference (name, acquireLock)
+ //, fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<PointType>::Preference (long index, bool acquireLock) :
+ BasePreference (index, acquireLock)
+ //, fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<PointType>::~Preference (void)
+{
+ this->Save ();
+}
+
+template <>
+bool Preference<PointType>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("x", value) && ::FromString (value, fValue.x) &&
+ gPrefs->GetPref ("y", value) && ::FromString (value, fValue.y))
+ {
+ loaded = true;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<PointType>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("x", ::ToString (fValue.x));
+ gPrefs->SetPref ("y", ::ToString (fValue.y));
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+ // It's odd that we have to provide explicit specializations of the
+ // constructor and destructor for Preference<EmPoint>.
+
+template <>
+Preference<EmPoint>::Preference (PrefKeyType name, bool acquireLock) :
+ BasePreference (name, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<EmPoint>::Preference (long index, bool acquireLock) :
+ BasePreference (index, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<EmPoint>::~Preference (void)
+{
+ this->Save ();
+}
+
+template <>
+bool Preference<EmPoint>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("x", value) && ::FromString (value, fValue.fX) &&
+ gPrefs->GetPref ("y", value) && ::FromString (value, fValue.fY))
+ {
+ loaded = true;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<EmPoint>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("x", ::ToString (fValue.fX));
+ gPrefs->SetPref ("y", ::ToString (fValue.fY));
+
+ gPrefs->PopPrefix ();
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+Preference<RGBType>::Preference (PrefKeyType name, bool acquireLock) :
+ BasePreference (name, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<RGBType>::Preference (long index, bool acquireLock) :
+ BasePreference (index, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<RGBType>::~Preference (void)
+{
+ this->Save ();
+}
+
+template <>
+bool Preference<RGBType>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("red", value) && ::FromString (value, fValue.fRed) &&
+ gPrefs->GetPref ("green", value) && ::FromString (value, fValue.fGreen) &&
+ gPrefs->GetPref ("blue", value) && ::FromString (value, fValue.fBlue))
+ {
+ loaded = true;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<RGBType>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("red", ::ToString (fValue.fRed));
+ gPrefs->SetPref ("green", ::ToString (fValue.fGreen));
+ gPrefs->SetPref ("blue", ::ToString (fValue.fBlue));
+
+ gPrefs->PopPrefix ();
+}
+
+
+// ----------------------------------------------------------------------
+// Also SkinNameList and PortNameList.
+
+template <>
+void Preference<StringList>::DoSave (void)
+{
+// gPrefs->DeletePref (fName);
+
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ StringList::iterator iter = fValue.begin ();
+ while (iter != fValue.end ())
+ {
+ Preference<string> pref (ii++, false);
+ pref = *iter;
+
+ ++iter;
+ }
+
+ gPrefs->PopPrefix ();
+}
+
+
+template <>
+bool Preference<StringList>::DoLoad (void)
+{
+ bool loaded = true;
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ while (1)
+ {
+ Preference<string> pref (ii, false);
+ if (!pref.Loaded ())
+ break;
+
+ fValue.push_back (*pref);
+
+ ++ii;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+// ----------------------------------------------------------------------
+
+template <>
+Preference<SlotInfoType>::Preference (PrefKeyType name, bool acquireLock) :
+ BasePreference (name, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<SlotInfoType>::Preference (long index, bool acquireLock) :
+ BasePreference (index, acquireLock),
+ fValue ()
+{
+ this->Load ();
+}
+
+template <>
+Preference<SlotInfoType>::~Preference (void)
+{
+ this->Save ();
+}
+
+template <>
+bool Preference<SlotInfoType>::DoLoad (void)
+{
+ bool loaded = false;
+ string value;
+
+ gPrefs->PushPrefix (fName);
+
+ if (gPrefs->GetPref ("fSlotNumber", value) && ::FromString (value, fValue.fSlotNumber) &&
+ gPrefs->GetPref ("fSlotOccupied", value) && ::FromString (value, fValue.fSlotOccupied) &&
+ gPrefs->GetPref ("fSlotRoot", value) && ::FromString (value, fValue.fSlotRoot))
+ {
+ loaded = true;
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<SlotInfoType>::DoSave (void)
+{
+ gPrefs->PushPrefix (fName);
+
+ gPrefs->SetPref ("fSlotNumber", ::ToString (fValue.fSlotNumber));
+ gPrefs->SetPref ("fSlotOccupied", ::ToString (fValue.fSlotOccupied));
+ gPrefs->SetPref ("fSlotRoot", ::ToString (fValue.fSlotRoot));
+
+ gPrefs->PopPrefix ();
+}
+
+
+// ----------------------------------------------------------------------
+
+template <>
+bool Preference<SlotInfoList>::DoLoad (void)
+{
+ bool loaded = true;
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ while (1)
+ {
+ Preference<SlotInfoType> pref (ii++, false);
+ if (!pref.Loaded ())
+ break;
+
+ fValue.push_back (*pref);
+ }
+
+ gPrefs->PopPrefix ();
+
+ return loaded;
+}
+
+template <>
+void Preference<SlotInfoList>::DoSave (void)
+{
+ gPrefs->DeletePref (fName);
+
+ gPrefs->PushPrefix (fName);
+
+ long ii = 0;
+ SlotInfoList::iterator iter = fValue.begin ();
+ while (iter != fValue.end ())
+ {
+ Preference<SlotInfoType> pref (ii++, false);
+ pref = *iter;
+
+ ++iter;
+ }
+
+ gPrefs->PopPrefix ();
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::Preferences
+ *
+ * DESCRIPTION: Constructor. Does nothing but construct data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Preferences::Preferences (void) :
+ fPreferences ()
+{
+ if (gPrefs == NULL)
+ gPrefs = this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::~Preferences
+ *
+ * DESCRIPTION: Destructor. Does nothing but destruct data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Preferences::~Preferences (void)
+{
+ if (gPrefs == this)
+ gPrefs = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::Load
+ *
+ * DESCRIPTION: Loads the preferences from the storage medium.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::Load (void)
+{
+ StringStringMap mapData;
+
+ if (!this->ReadPreferences (mapData))
+ return;
+
+ StringStringMap::iterator iter = mapData.begin ();
+ while (iter != mapData.end ())
+ {
+ string key = iter->first;
+ string value = iter->second;
+
+ this->SetPref (key, value);
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::Save
+ *
+ * DESCRIPTION: Saves the preferences to the storage medium.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::Save (void)
+{
+ this->StripUnused ();
+
+ this->WritePreferences (fPreferences);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::GetPref
+ *
+ * DESCRIPTION: Returns the specified preference. The given key is
+ * prepended with any prefixes, and the resulting key is
+ * used to look up the value.
+ *
+ * PARAMETERS: key - the key used to look up the preference's value.
+ *
+ * value - the found value (if any).
+ *
+ * RETURNED: True if the key/value could be found, false otherwise.
+ *
+ ***********************************************************************/
+
+bool Preferences::GetPref (const string& key, string& value)
+{
+ // Locking done in Preference::DoLoad.
+// omni_mutex_lock lock (fgPrefsMutex);
+
+ string fullKey = gPrefs->ExpandKey (key);
+
+ iterator iter = fPreferences.find (fullKey);
+ if (iter == fPreferences.end ())
+ return false;
+
+ value = iter->second;
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::SetPref
+ *
+ * DESCRIPTION: Store the given key/value pair into our collection. If
+ * an entry with the given key already exists, its value
+ * is updated with the specified one.
+ *
+ * If the value is changed or newly added, then send out
+ * notification to anyone registered for this preference.
+ *
+ * PARAMETERS: key - the key used to look up the preference.
+ *
+ * value - the value to associate with the key.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::SetPref (const string& key, const string& value)
+{
+ // Locking done in Preference::DoSave.
+// omni_mutex_lock lock (fgPrefsMutex);
+
+ string fullKey = gPrefs->ExpandKey (key);
+ Bool doNotify = false;
+
+ iterator iter = fPreferences.find(fullKey);
+ if (iter == fPreferences.end ())
+ {
+ doNotify = true;
+ fPreferences[fullKey] = value;
+ }
+ else
+ {
+ doNotify = (iter->second != value);
+ iter->second = value;
+ }
+
+ if (doNotify)
+ {
+ this->DoNotify (fullKey);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::DeletePref
+ *
+ * DESCRIPTION: Delete a preference from our collection. The delete
+ * operation works on the given key and all sub-keys (that
+ * is, all keys that have "key" as its prefix).
+ *
+ * PARAMETERS: key - the key for the value or value to delete.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::DeletePref (const string& key)
+{
+ // Locking done in Preference::DoSave.
+// omni_mutex_lock lock (fgPrefsMutex);
+
+ string deleteKey = gPrefs->ExpandKey (key);
+
+ // Iterate over all the entries in the map.
+
+ iterator iter = fPreferences.begin ();
+ while (iter != fPreferences.end ())
+ {
+ // For each entry, get the key.
+
+ string thisKey (iter->first.c_str());
+
+ if (::PrvFirstBeginsWithSecond (thisKey, deleteKey))
+ {
+ fPreferences.erase (iter);
+ iter = fPreferences.begin ();
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ this->DoNotify (deleteKey);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::PushPrefix
+ *
+ * DESCRIPTION: Push a prefix onto our internal stack. These prefixes
+ * are used later to build a full key with which to fetch
+ * and store preference values.
+ *
+ * PARAMETERS: prefix - the subkey to push onto our stack.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::PushPrefix (const string& prefix)
+{
+ // Locking done in Preference::DoSave/DoLoad.
+// omni_mutex_lock lock (fgPrefsMutex);
+
+ fPrefixes.push_back (prefix);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::PushPrefix
+ *
+ * DESCRIPTION: Push a prefix onto our internal stack. These prefixes
+ * are used later to build a full key with which to fetch
+ * and store preference values.
+ *
+ * PARAMETERS: index - the subkey to push onto our stack.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::PushPrefix (long index)
+{
+ this->PushPrefix (::ToString (index));
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::PopPrefix
+ *
+ * DESCRIPTION: Pop a prefix off of our internal stack.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::PopPrefix (void)
+{
+ // Locking done in Preference::DoSave/DoLoad.
+// omni_mutex_lock lock (fgPrefsMutex);
+
+ fPrefixes.pop_back ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::ExpandKey
+ *
+ * DESCRIPTION: Prepend the given key with the prefixes pushed onto
+ * our stack. Prefixes are prepended in such as way as to
+ * look like a "C" expression. "Fields" are seperated with
+ * dots, and array subscripts are surround with brackets.
+ *
+ * PARAMETERS: name - the part of the key that will appear at the
+ * very end of the expanded key. If this name is
+ * empty, the expanded key will end with the last
+ * prefix pushed onto the stack.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+string Preferences::ExpandKey (const string& name)
+{
+ string key;
+
+ PrefixType::iterator iter = fPrefixes.begin ();
+
+ if (iter == fPrefixes.end ())
+ {
+ key = name;
+ }
+ else
+ {
+ key = *iter++;
+
+ while (iter != fPrefixes.end ())
+ {
+ if (!iter->empty ())
+ key = this->AppendName (key, *iter);
+
+ ++iter;
+ }
+
+ if (!name.empty ())
+ {
+ key = this->AppendName (key, name);
+ }
+ }
+
+ return key;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::AppendName
+ *
+ * DESCRIPTION: Append a single prefix to the full expanded key as it
+ * is built up from left to right.
+ *
+ * PARAMETERS: key - the expanded key so far.
+ *
+ * name - the subkey to append to it.
+ *
+ * RETURNED: The catenated value. If name looks like a number, the
+ * catenated result is:
+ *
+ * key[name]
+ *
+ * Otherwise, we return:
+ *
+ * key.name
+ *
+ ***********************************************************************/
+
+string Preferences::AppendName (string key, const string& name)
+{
+ if (isdigit (name[0]))
+ {
+ key = key + "[" + name + "]";
+ }
+ else
+ {
+ key = key + "." + name;
+ }
+
+ return key;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::AddNotification
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::AddNotification (PrefNotifyFunc fn, PrefKeyType key, PrefRefCon refCon)
+{
+ PrefKeyList prefList;
+
+ prefList.push_back (key);
+ this->AddNotification (fn, prefList, refCon);
+}
+
+
+void Preferences::AddNotification (PrefNotifyFunc fn, const PrefKeyList& keyList, PrefRefCon refCon)
+{
+ PrefNotifyList::iterator iter = fNotifications.begin ();
+ while (iter != fNotifications.end ())
+ {
+ if (iter->fFunc == fn)
+ {
+ break;
+ }
+
+ ++iter;
+ }
+
+ if (iter == fNotifications.end ())
+ {
+ PrefNotifyType entry;
+
+ entry.fFunc = fn;
+ entry.fRefCon = refCon;
+
+ fNotifications.push_back (entry);
+
+ iter = fNotifications.end () - 1;
+ }
+
+ // Add the list of keys for which this function wants notification.
+ // (Hmmm...doesn't check for duplicates...should it?)
+
+ iter->fKeyList.insert (iter->fKeyList.end (), keyList.begin (), keyList.end ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::RemoveNotification
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::RemoveNotification (PrefNotifyFunc fn)
+{
+ PrefNotifyList::iterator iter = fNotifications.begin ();
+ while (iter != fNotifications.end ())
+ {
+ if (iter->fFunc == fn)
+ {
+ fNotifications.erase (iter);
+ break;
+ }
+
+ ++iter;
+ }
+}
+
+
+void Preferences::RemoveNotification (PrefNotifyFunc fn, PrefKeyType key)
+{
+ PrefKeyList prefList;
+
+ prefList.push_back (key);
+ this->RemoveNotification (fn, prefList);
+}
+
+
+void Preferences::RemoveNotification (PrefNotifyFunc /*fn*/, const PrefKeyList& /*keyList*/)
+{
+#if 0
+ PrefNotifyList::iterator iter = fNotifications.find(fn);
+
+ if (iter != fNotifications.end ())
+ {
+ // !!! TBD
+ }
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: DoNotify
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::DoNotify (const string& key)
+{
+ PrefNotifyList::iterator listIter = fNotifications.begin ();
+ while (listIter != fNotifications.end ())
+ {
+ // For each key in the list, see if it matches the specified key.
+
+ PrefKeyList::iterator keyIter = listIter->fKeyList.begin ();
+ while (keyIter != listIter->fKeyList.end ())
+ {
+ if (::PrvFirstBeginsWithSecond (key, *keyIter))
+ {
+ // It does, so call the notification function.
+
+ (listIter->fFunc) (keyIter->c_str (), listIter->fRefCon);
+ }
+
+ ++keyIter;
+ }
+
+
+ ++listIter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::ReadPreferences
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool Preferences::ReadPreferences (StringStringMap& prefData)
+{
+ EmFileRef prefRef (this->GetPrefRef ());
+ return EmMapFile::Read (prefRef, prefData);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::WritePreferences
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::WritePreferences (const StringStringMap& prefData)
+{
+ EmFileRef prefRef (this->GetPrefRef ());
+ EmMapFile::Write (prefRef, prefData);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::GetPrefRef
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmFileRef Preferences::GetPrefRef (void)
+{
+ EmDirRef poserDir (EmDirRef::GetEmulatorDirectory ());
+ EmDirRef prefDir (EmDirRef::GetPrefsDirectory ());
+
+#if PLATFORM_MAC
+
+ string name ("Palm OS Emulator Prefs");
+
+#elif PLATFORM_UNIX
+
+ string name (".poserrc");
+
+#elif PLATFORM_WINDOWS
+
+ string name ("Palm OS Emulator.ini");
+
+#else
+
+ #error "Undefined platform"
+
+#endif
+
+ EmFileRef poserResult (poserDir, name);
+ if (poserResult.Exists ())
+ return poserResult;
+
+ EmFileRef prefResult (prefDir, name);
+
+ return prefResult;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::WriteBanner
+ *
+ * DESCRIPTION: Write a descriptive banner to the preference file.
+ * Useful so that people will know what the contents of
+ * the file are for (in case they can't glean that from
+ * the name of the file).
+ *
+ * PARAMETERS: f - the open FILE to write the banner to.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::WriteBanner (FILE*)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::ReadBanner
+ *
+ * DESCRIPTION: Read the banner in the given file, possibly validating
+ * it.
+ *
+ * PARAMETERS: f - the open FILE containing the banner.
+ *
+ * RETURNED: True if it looks like this is our file, false if it
+ * looks like this file contains something else.
+ *
+ ***********************************************************************/
+
+Bool Preferences::ReadBanner (FILE*)
+{
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Preferences::StripUnused
+ *
+ * DESCRIPTION: Called to remove any obsolete or otherwise stray
+ * settings from our collection. Usually called some time
+ * before the updated settings are rewritten back to disk.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Preferences::StripUnused (void)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::EmulatorPreferences
+ *
+ * DESCRIPTION: Constructor. Establishes default values for all the
+ * preferences we'll be using.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmulatorPreferences::EmulatorPreferences (void) :
+ Preferences (),
+ fTransports ()
+{
+ if (gEmuPrefs == NULL)
+ gEmuPrefs = this;
+
+ // Set up default values for all the keys.
+ //
+ // Warning: this method works implicitly off of "gPrefs", and so will
+ // fail when trying to create additional preference objects.
+
+ #define INIT_PREF_KEYS(name, type, init) \
+ { \
+ Preference<type> pref (kPrefKey##name); \
+ pref = type init; \
+ }
+
+ FOR_EACH_INIT_PREF(INIT_PREF_KEYS)
+
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ fTransports[ii] = NULL;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::~EmulatorPreferences
+ *
+ * DESCRIPTION: Destructor.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmulatorPreferences::~EmulatorPreferences (void)
+{
+ for (EmUARTDeviceType ii = kUARTBegin; ii < kUARTEnd; ++ii)
+ {
+ delete fTransports[ii];
+ }
+
+ if (gEmuPrefs == this)
+ gEmuPrefs = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::Load
+ *
+ * DESCRIPTION: Install the correct set of logging preferences after the
+ * settings have been loaded from the file. Also, make
+ * sure the list of skin preferences is large enough so
+ * that we can look up the skin for any device without
+ * having to check the array size all over the place.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::Load (void)
+{
+ Preferences::Load ();
+
+ // Migrate over any old prefs to any new way of handling them.
+
+ this->MigrateOldPrefs ();
+
+ // Let's set up some default configuration in case there isn't
+ // one in the prefs file (or it was invalid).
+
+ Preference<Configuration> prefConfig (kPrefKeyLastConfiguration);
+ if (!prefConfig.Loaded())
+ {
+ prefConfig = Configuration (EmDevice ("PalmIII"), 1024, EmFileRef());
+ }
+
+ // Create the transports used by the UARTs.
+
+ this->SetTransports ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::GetIndMRU
+ *
+ * DESCRIPTION: Return a PRC or PSF file from the corresponding list of
+ * files, based on the given index.
+ *
+ * PARAMETERS: The index of the file to return.
+ *
+ * RETURNED: The nth file in the list. If index is off the end of
+ * the list, a non-specified EmFileRef (that is, one
+ * for which the IsSpecified method returns false) is
+ * returned.
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::GetDatabaseMRU (EmFileRefList& files)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPRC_MRU);
+ files = *pref;
+}
+
+
+void EmulatorPreferences::GetSessionMRU (EmFileRefList& files)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPSF_MRU);
+ files = *pref;
+}
+
+
+void EmulatorPreferences::GetROMMRU (EmFileRefList& files)
+{
+ Preference<EmFileRefList> pref (kPrefKeyROM_MRU);
+ files = *pref;
+}
+
+
+EmFileRef EmulatorPreferences::GetIndPRCMRU (int index)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPRC_MRU);
+ EmFileRefList mru = *pref;
+ return this->GetIndMRU (mru, index);
+}
+
+
+EmFileRef EmulatorPreferences::GetIndRAMMRU (int index)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPSF_MRU);
+ EmFileRefList mru = *pref;
+ return this->GetIndMRU (mru, index);
+}
+
+
+EmFileRef EmulatorPreferences::GetIndROMMRU (int index)
+{
+ Preference<EmFileRefList> pref (kPrefKeyROM_MRU);
+ EmFileRefList mru = *pref;
+ return this->GetIndMRU (mru, index);
+}
+
+
+EmFileRef EmulatorPreferences::GetIndMRU (const EmFileRefList& fileList, int index)
+{
+ if ((EmFileRefList::size_type) index < fileList.size ())
+ return fileList [index];
+
+ return EmFileRef();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::UpdateMRU
+ *
+ * DESCRIPTION: Update the MRU list for PRC and PSF files. The given
+ * file is inserted at the beginning of the list. If
+ * the file previously existed in the list, it is removed
+ * from its old location. The length of the list is
+ * limited to MRU_COUNT
+ *
+ * PARAMETERS: newFile - the file to move to the beginning of the list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::UpdatePRCMRU (const EmFileRef& newFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPRC_MRU);
+ EmFileRefList mru = *pref;
+ this->UpdateMRU (mru, newFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::UpdateRAMMRU (const EmFileRef& newFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPSF_MRU);
+ EmFileRefList mru = *pref;
+ this->UpdateMRU (mru, newFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::UpdateROMMRU (const EmFileRef& newFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyROM_MRU);
+ EmFileRefList mru = *pref;
+ this->UpdateMRU (mru, newFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::UpdateMRU (EmFileRefList& fileList, const EmFileRef& newFile)
+{
+ this->RemoveMRU (fileList, newFile);
+
+ fileList.insert (fileList.begin (), newFile);
+
+ while (fileList.size () > MRU_COUNT)
+ fileList.pop_back ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::RemoveMRU
+ *
+ * DESCRIPTION: Remove the given PRC or PSF file from its MRU list.
+ *
+ * PARAMETERS: oldFile - the file to remove.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::RemovePRCMRU (const EmFileRef& oldFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPRC_MRU);
+ EmFileRefList mru = *pref;
+ this->RemoveMRU (mru, oldFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::RemoveRAMMRU (const EmFileRef& oldFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyPSF_MRU);
+ EmFileRefList mru = *pref;
+ this->RemoveMRU (mru, oldFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::RemoveROMMRU (const EmFileRef& oldFile)
+{
+ Preference<EmFileRefList> pref (kPrefKeyROM_MRU);
+ EmFileRefList mru = *pref;
+ this->RemoveMRU (mru, oldFile);
+ pref = mru;
+}
+
+
+void EmulatorPreferences::RemoveMRU (EmFileRefList& fileList, const EmFileRef& oldFile)
+{
+ EmFileRefList::iterator iter = find (fileList.begin (), fileList.end (), oldFile);
+
+ if (iter != fileList.end ())
+ fileList.erase (iter);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::SetTransports
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::SetTransports (void)
+{
+ {
+ Preference<EmTransportDescriptor> pref (kPrefKeyPortSerial);
+ this->SetTransportForDevice (kUARTSerial, pref->CreateTransport ());
+ }
+
+ {
+ Preference<EmTransportDescriptor> pref (kPrefKeyPortIR);
+ this->SetTransportForDevice (kUARTIR, pref->CreateTransport ());
+ }
+
+ {
+ Preference<EmTransportDescriptor> pref (kPrefKeyPortMystery);
+ this->SetTransportForDevice (kUARTMystery, pref->CreateTransport ());
+ }
+}
+
+
+void EmulatorPreferences::SetTransportForDevice (EmUARTDeviceType type,
+ EmTransport* transport)
+{
+ EmSessionStopper stopper (gSession, kStopNow);
+
+ delete fTransports[type];
+ fTransports[type] = transport;
+
+ // If the transport exists and needs to be opened, open it.
+
+ if (transport && gCPU && EmHAL::GetLineDriverState (type))
+ {
+ transport->Open ();
+ }
+}
+
+
+EmTransport* EmulatorPreferences::GetTransportForDevice (EmUARTDeviceType type)
+{
+ return fTransports[type];
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Errors::LogMessage
+// ---------------------------------------------------------------------------
+// Return whether or not the message should be logged.
+
+Bool EmulatorPreferences::LogMessage (Bool isFatal)
+{
+ {
+ if (isFatal && LogErrorMessages ())
+ return true;
+ }
+
+ {
+ if (!isFatal && LogWarningMessages ())
+ return true;
+ }
+
+ {
+ Preference<Bool> pref ("SilentRunning");
+ if (pref.Loaded () && *pref)
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrvGetPrefKey
+// ---------------------------------------------------------------------------
+// Return the key for the preference that tells us to handle the error or
+// warning in this situation.
+
+static PrefKeyType PrvGetPrefKey (Bool isFatal)
+{
+ PrefKeyType prefKey = NULL;
+
+ if (Hordes::IsOn ())
+ {
+ prefKey = isFatal ? kPrefKeyErrorOn : kPrefKeyWarningOn;
+ }
+ else
+ {
+ prefKey = isFatal ? kPrefKeyErrorOff : kPrefKeyWarningOff;
+ }
+
+ return prefKey;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmulatorPreferences::ShouldQuit
+// ---------------------------------------------------------------------------
+// Return whether or not this error should cause us to quit.
+
+Bool EmulatorPreferences::ShouldQuit (Bool isFatal)
+{
+ // If SilentRunning is set, then we quit on fatal errors.
+
+ if (isFatal)
+ {
+ Preference<Bool> pref ("SilentRunning");
+ if (pref.Loaded () && *pref)
+ return true;
+ }
+
+ // If the old ExitOnErrors preference is set, then we
+ // quit on fatal errors.
+
+ if (isFatal)
+ {
+ Preference<Bool> pref ("ExitOnErrors");
+ if (pref.Loaded () && *pref)
+ return true;
+ }
+
+ // Otherwise, get the setting for this situation and
+ // see if it tells us to quit.
+
+ PrefKeyType prefKey = ::PrvGetPrefKey (isFatal);
+ Preference<EmErrorHandlingOption> pref (prefKey);
+ return (*pref == kQuit);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmulatorPreferences::ShouldContinue
+// ---------------------------------------------------------------------------
+// Return whether or not this error should be logged but not displayed.
+
+Bool EmulatorPreferences::ShouldContinue (Bool isFatal)
+{
+ // If SilentRunning is set, then we continue on warnings.
+
+ if (!isFatal)
+ {
+ Preference<Bool> pref ("SilentRunning");
+ if (pref.Loaded () && *pref)
+ return true;
+ }
+
+ // If the old ContinueOnWarnings preference is set, then we
+ // continue on warnings.
+
+ if (!isFatal)
+ {
+ Preference<Bool> pref ("ContinueOnWarnings");
+ if (pref.Loaded () && *pref)
+ return true;
+ }
+
+ // Otherwise, get the setting for this situation and
+ // see if it tells us to quit.
+
+ PrefKeyType prefKey = ::PrvGetPrefKey (isFatal);
+ Preference<EmErrorHandlingOption> pref (prefKey);
+ return (*pref == kContinue);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmulatorPreferences::ShouldNextGremlin
+// ---------------------------------------------------------------------------
+// Return whether or not this error should cause us to switch to the next
+// Gremlin in a Horde.
+
+Bool EmulatorPreferences::ShouldNextGremlin (Bool isFatal)
+{
+ // Otherwise, get the setting for this situation and
+ // see if it tells us to quit.
+
+ PrefKeyType prefKey = ::PrvGetPrefKey (isFatal);
+ Preference<EmErrorHandlingOption> pref (prefKey);
+ return (*pref == kSwitch);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::WriteBanner
+ *
+ * DESCRIPTION: Write out a banner indicating that that is a Poser
+ * preference file.
+ *
+ * PARAMETERS: f - the open FILE to write the banner to.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::WriteBanner (FILE* f)
+{
+ fprintf (f, "# Palm OS Emulator Preferences\n\n");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::ReadBanner
+ *
+ * DESCRIPTION: Do nothing.
+ *
+ * PARAMETERS: f - the open FILE containing the banner.
+ *
+ * RETURNED: True if it looks like this is our file, false if it
+ * looks like this file contains something else.
+ *
+ ***********************************************************************/
+
+Bool EmulatorPreferences::ReadBanner (FILE*)
+{
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::StripUnused
+ *
+ * DESCRIPTION: Called to remove any obsolete or otherwise stray
+ * settings from our collection. Usually called some time
+ * before the updated settings are rewritten back to disk.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static bool PrvCheckKey (PrefKeyType key)
+{
+ #define REMOVE_UNUSED(name, type, init) \
+ if (::PrefKeysEqual (key, kPrefKey##name)) \
+ return true;
+ FOR_EACH_PREF(REMOVE_UNUSED)
+
+ return false;
+}
+
+void EmulatorPreferences::StripUnused (void)
+{
+ // Iterate over all the entries in the map.
+
+ iterator iter = fPreferences.begin ();
+ while (iter != fPreferences.end ())
+ {
+ // For each entry, get the key, and then just the root part of
+ // the key (everything before the first '.' or '[', if any).
+
+ string keyRoot (iter->first);
+
+ string::size_type dotPos = keyRoot.find ('.');
+ if (dotPos != string::npos)
+ keyRoot.erase (dotPos);
+
+ string::size_type bracketPos = keyRoot.find ('[');
+ if (bracketPos != string::npos)
+ keyRoot.erase (bracketPos);
+
+ // See if this key (root) is one that we still support.
+ // If not, then remove it.
+
+ if (!::PrvCheckKey (keyRoot.c_str ()))
+ {
+ // According to MSDN's documentation, erase is supposed to
+ // return an iterator to the next element. MSL doesn't
+ // seem to follow that description.
+// iter = fPreferences.erase (iter);
+
+ fPreferences.erase (iter);
+ iter = fPreferences.begin ();
+ continue;
+ }
+
+ // If this is one of the old Skins preferences, remove it.
+
+ keyRoot = iter->first;
+ bracketPos = keyRoot.find ('[');
+
+ if (bracketPos != string::npos)
+ {
+ keyRoot.erase (bracketPos + 1);
+
+ if (keyRoot == "Skins[")
+ {
+ fPreferences.erase (iter);
+ iter = fPreferences.begin ();
+ continue;
+ }
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmulatorPreferences::MigrateOldPrefs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmulatorPreferences::MigrateOldPrefs (void)
+{
+ // Migrate any old skin preferences to the current format.
+
+ {
+ const char* kDeviceName[] =
+ {
+ NULL,
+ "Pilot",
+ "Pilot",
+ "PalmPilot",
+ "PalmPilot",
+ NULL,
+ "PalmIII",
+ "PalmVII",
+ NULL,
+ NULL,
+ "PalmV",
+ "PalmIIIx",
+ NULL,
+ "PalmIIIc",
+ "PalmVIIEZ",
+ "PalmIIIe",
+ "PalmVx",
+ "Symbol1700",
+ "TRGpro",
+ "Visor",
+ "PalmM100",
+ "PalmVIIx",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "VZDevice",
+ NULL,
+ NULL,
+ "VisorPrism",
+ "VisorPlatinum",
+ NULL
+ };
+
+ for (size_t index = 0; index < countof (kDeviceName); ++index)
+ {
+ if (kDeviceName[index])
+ {
+ char oldPrefKey[20];
+ sprintf (oldPrefKey, "%s[%d]", kPrefKeySkins, index);
+
+ Preference<SkinName> oldSkinPref (oldPrefKey);
+ if (!oldSkinPref.Loaded ())
+ break;
+
+ char newPrefKey[20];
+ sprintf (newPrefKey, "%s.%s", kPrefKeySkins, kDeviceName[index]);
+
+ Preference<SkinName> newSkinPref (newPrefKey);
+ newSkinPref = *oldSkinPref;
+ }
+ }
+ }
+
+ // Filter the MRU lists, removing references to items no longer there.
+
+ ::PrvFilterFileRefList (kPrefKeyPRC_MRU);
+ ::PrvFilterFileRefList (kPrefKeyPSF_MRU);
+ ::PrvFilterFileRefList (kPrefKeyROM_MRU);
+
+ // If this is the first time Poser 3.3 is being run, then set the
+ // logging options for errors and warnings to true in Gremlin mode.
+
+ StringStringMap mapData;
+
+ if (this->ReadPreferences (mapData))
+ {
+ if (mapData.find ("DialogBeep") == mapData.end ())
+ {
+ Preference<uint8> prefLogWarnings (kPrefKeyLogWarningMessages);
+ Preference<uint8> prefLogErrors (kPrefKeyLogErrorMessages);
+
+ prefLogWarnings = *prefLogWarnings | kGremlinLogging;
+ prefLogErrors = *prefLogErrors | kGremlinLogging;
+ }
+ }
+
+ // If there's a CommPortList preference, migrate that over
+ // to the CommPort preference.
+
+ Preference<string> prefCommPort ("CommPort");
+ Preference<StringList> prefCommPortList ("CommPortList");
+
+ if (prefCommPortList.Loaded () && prefCommPortList->size () > 0)
+ {
+ prefCommPort = (*prefCommPortList)[0];
+ }
+
+ // Migrate forward old port redirection settings to new ones.
+ // (Yes, this is done in addition to the migration done previously.
+ // Each migration represents different changes in Poser's evolution.)
+
+ // Convert CommPort, SerialTargetHost, and SerialTargetPort.
+
+ {
+ Preference<string> oldHost ("SerialTargetHost");
+ Preference<string> oldPort ("SerialTargetPort");
+
+ if (oldHost.Loaded ())
+ {
+ Preference<string> newHost (kPrefKeyPortSerialSocket);
+
+ newHost = *oldHost + ":" + *oldPort;
+ }
+ }
+
+ {
+ Preference<string> oldPref ("CommPort");
+ if (oldPref.Loaded ())
+ {
+ Preference<EmTransportDescriptor> newPref (kPrefKeyPortSerial);
+ EmTransportType type = PrvGetTransportTypeFromPortName (oldPref->c_str ());
+
+ if (type == kTransportSerial)
+ {
+ newPref = EmTransportDescriptor (kTransportSerial, *oldPref);
+ }
+ else if (type == kTransportSocket)
+ {
+ Preference<string> newHost (kPrefKeyPortSerialSocket);
+
+ newPref = EmTransportDescriptor (kTransportSocket, *newHost);
+ }
+ else
+ {
+ newPref = EmTransportDescriptor (kTransportNull);
+ }
+ }
+ }
+
+ // Convert IRPort, IRTargetHost, and IRTargetPort.
+
+ {
+ Preference<string> oldHost ("IRTargetHost");
+ Preference<string> oldPort ("IRTargetPort");
+
+ if (oldHost.Loaded ())
+ {
+ Preference<string> newHost (kPrefKeyPortIRSocket);
+
+ newHost = *oldHost + ":" + *oldPort;
+ }
+ }
+
+ {
+ Preference<string> oldPref ("IRPort");
+ if (oldPref.Loaded ())
+ {
+ Preference<EmTransportDescriptor> newPref (kPrefKeyPortIR);
+ EmTransportType type = PrvGetTransportTypeFromPortName (oldPref->c_str ());
+
+ if (type == kTransportSerial)
+ {
+ newPref = EmTransportDescriptor (kTransportSerial, *oldPref);
+ }
+ else if (type == kTransportSocket)
+ {
+ Preference<string> newHost (kPrefKeyPortIRSocket);
+
+ newPref = EmTransportDescriptor (kTransportSocket, *newHost);
+ }
+ else
+ {
+ newPref = EmTransportDescriptor (kTransportNull);
+ }
+ }
+ }
+
+ // Establish Mystery Port
+
+ {
+ Preference<EmTransportDescriptor> pref (kPrefKeyPortMystery);
+
+ if (!pref.Loaded ())
+ {
+ pref = EmTransportDescriptor (kTransportNull);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvFilterFileRefList
+ *
+ * DESCRIPTION: Remove files from the given list that no longer appear
+ * to exist.
+ *
+ * PARAMETERS: key - the key of the preference containing the list
+ * of files to check.
+ *
+ * RETURNED: Nothing, but the preference is altered.
+ *
+ ***********************************************************************/
+
+void PrvFilterFileRefList (PrefKeyType key)
+{
+ Preference<EmFileRefList> pref (key);
+ EmFileRefList mruList = *pref;
+
+ EmFileRefList::iterator iter = mruList.begin ();
+
+ while (iter != mruList.end ())
+ {
+ if (!iter->Exists ())
+ {
+ EmFileRefList::difference_type index = iter - mruList.begin ();
+ mruList.erase (iter);
+ iter = mruList.begin () + index;
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ pref = mruList;
+}
+
+
+/**********************************************************************
+ *
+ * FUNCTION: PrvGetTransportTypeFromPortName
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+EmTransportType PrvGetTransportTypeFromPortName (const char* portName)
+{
+#if PLATFORM_UNIX
+ if (portName && strlen (portName) > 0)
+ {
+ if (portName[0] == '/')
+ {
+ return kTransportSerial;
+ }
+
+ return kTransportSocket;
+ }
+#else
+ {
+ EmTransportDescriptorList names;
+ EmTransportSerial::GetDescriptorList (names);
+ EmTransportDescriptorList::iterator iter = names.begin ();
+
+ while (iter != names.end ())
+ {
+ if (!strcmp (portName, iter->GetSchemeSpecific ().c_str ()))
+ {
+ return kTransportSerial;
+ }
+
+ ++iter;
+ }
+ }
+
+ {
+ EmTransportDescriptorList names;
+ EmTransportSocket::GetDescriptorList (names);
+ EmTransportDescriptorList::iterator iter = names.begin ();
+
+ while (iter != names.end ())
+ {
+ if (!strcmp (portName, iter->GetSchemeSpecific ().c_str ()))
+ {
+ return kTransportSocket;
+ }
+
+ ++iter;
+ }
+ }
+
+ {
+ EmTransportDescriptorList names;
+ EmTransportUSB::GetDescriptorList (names);
+ EmTransportDescriptorList::iterator iter = names.begin ();
+
+ while (iter != names.end ())
+ {
+ if (!strcmp (portName, iter->GetSchemeSpecific ().c_str ()))
+ {
+ return kTransportUSB;
+ }
+
+ ++iter;
+ }
+ }
+#endif
+
+ return kTransportNull;
+}
+
+bool PrefKeysEqual (PrefKeyType key1, PrefKeyType key2)
+{
+ return _stricmp (key1, key2) == 0;
+}
diff --git a/SrcShared/PreferenceMgr.h b/SrcShared/PreferenceMgr.h
new file mode 100644
index 0000000..2c1c032
--- /dev/null
+++ b/SrcShared/PreferenceMgr.h
@@ -0,0 +1,409 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _PREFERENCEMGR_H_
+#define _PREFERENCEMGR_H_
+
+#include "EmFileRef.h" // EmFileRefList, EmFileRef
+#include "EmTransport.h" // EmTransportType
+#include "EmHAL.h" // EmUARTDeviceType
+#include "Skins.h" // SkinNameList
+
+#include "omnithread.h" // omni_mutex
+
+#include <stdio.h> // FILE
+#include <map>
+#include <vector>
+
+class EmTransport;
+
+/*
+ This file contains the routines for loading, saving, and accessing a collection
+ of preferences/settings.
+
+ All settings are accessed via the Preference class. This is a templatized class
+ that is specialized on the type of the setting and parameterized on the name of
+ the setting. This sounds nasty, but in practice is simple. For example, say you
+ needed to access whether or not NetLib redirection was turned on. You would use
+ the following:
+
+ Preference<bool> pref(kPrefKeyRedirectNetLib);
+
+ if (*pref)
+ {
+ // It's on.
+ }
+
+ Changing a value works similarly:
+
+ Preference<DeviceType> pref(kPrefKeyDeviceType);
+ *pref = kDevicePalmIII;
+
+ When the Preference object is destructed, it's new value is written back out to
+ the Preference Manager.
+
+ The Preference Manager is the "container" for all the preferences used by the
+ application. You can think of it as a map/dictionary/associative array. You
+ directly access the Preference Manager in order to create it, have it load the
+ collection of preferences from disk, have it save them to disk, and to destroy
+ it. While there are GetPref and SetPref methods on this class, those are for
+ the use of the Preference objects.
+
+ All preferences are saved as text in the form:
+
+ <key>=<value>
+
+ <key> is any unique string. It can consist of any text characters except for
+ '='. Keys can have subparts separated by '.', and can indicate array indices
+ with "[#]". For example:
+
+ Scale=2
+ GremlinInfo.fNumber=100
+ PRC_MRU[0]=MyApplication.prc
+ GremlinInfo.fAppList[0].name=AddressBook
+
+ With the Preference class, it's possible to pull in all or part of the
+ hierarchical information. For instance:
+
+ Preference<GremlinInfo> pref("GremlinInfo");
+ Preference<DatabaseInfoList> pref("GremlinInfo.fAppList");
+ Preference<DatabaseInfo> pref("GremlinInfo.fAppList[0]");
+ Preference<string> pref("GremlinInfo.fAppList[0].name");
+*/
+
+typedef const char* PrefKeyType;
+
+bool PrefKeysEqual (PrefKeyType, PrefKeyType);
+
+class BasePreference
+{
+ public:
+ BasePreference (PrefKeyType name, bool = true);
+ BasePreference (long index, bool = true);
+ virtual ~BasePreference (void);
+
+ bool Loaded (void) { return fLoaded; }
+
+ void Flush (void) { this->Save (); }
+
+ protected:
+ void Load (void);
+ void Save (void);
+
+ protected:
+ virtual bool DoLoad (void) = 0;
+ virtual void DoSave (void) = 0;
+
+ protected:
+ string fName;
+ bool fLoaded;
+ bool fChanged;
+ bool fAcquireLock;
+};
+
+template <class T>
+class Preference : public BasePreference
+{
+ public:
+ Preference (PrefKeyType name, bool = true);
+ Preference (long index, bool = true);
+ virtual ~Preference (void);
+
+ // I would *like* to have these operators. That way, I could pass in a
+ // "Preference<Foo>" any place that accepts a "const Foo&" as a parameter.
+ // However, CodeWarrior seems to use the conversion operators here in place
+ // that accept merely a "Foo&", which has lead to some problems.
+// operator const T&() const { return *GetValue (); }
+// operator const T*() const { return GetValue (); }
+ const T& operator*() const { return *GetValue (); }
+ const T* operator->() const { return GetValue (); }
+
+ const T* GetValue () const { EmAssert (fLoaded); return &fValue; }
+
+ const T& operator=(const T& rhs) { fValue = rhs;
+ fLoaded = true;
+ fChanged = true;
+ this->Flush ();
+ return fValue; }
+
+ protected:
+ virtual bool DoLoad (void);
+ virtual void DoSave (void);
+
+ private:
+ T fValue;
+};
+
+typedef void* PrefRefCon;
+typedef void (*PrefNotifyFunc)(PrefKeyType, PrefRefCon);
+typedef StringList PrefKeyList;
+
+enum
+{
+ MRU_COUNT = 9
+};
+
+class Preferences
+{
+ public:
+ Preferences (void);
+ virtual ~Preferences (void);
+
+ virtual void Load (void);
+ virtual void Save (void);
+
+// This should work, but CW doesn't appear to like it.
+// private:
+// template <class T> friend class Preference;
+ public:
+ bool GetPref (const string& key, string& value);
+ void SetPref (const string& key, const string& value);
+ void DeletePref (const string& key);
+
+ public:
+ void PushPrefix (const string& prefix);
+ void PushPrefix (long index);
+ void PopPrefix (void);
+
+ string ExpandKey (const string& name);
+ string AppendName (string key, const string& name);
+
+ public:
+ void AddNotification (PrefNotifyFunc, PrefKeyType, PrefRefCon = NULL);
+ void AddNotification (PrefNotifyFunc, const PrefKeyList&, PrefRefCon = NULL);
+ void RemoveNotification (PrefNotifyFunc);
+ void RemoveNotification (PrefNotifyFunc, PrefKeyType);
+ void RemoveNotification (PrefNotifyFunc, const PrefKeyList&);
+ void DoNotify (const string& key);
+
+ protected:
+ virtual Bool ReadPreferences (StringStringMap&);
+ virtual void WritePreferences (const StringStringMap&);
+ virtual EmFileRef GetPrefRef (void);
+ virtual void WriteBanner (FILE*);
+ virtual Bool ReadBanner (FILE*);
+ virtual void StripUnused (void);
+
+ protected:
+ typedef StringStringMap PrefList;
+ typedef PrefList::value_type PrefPairType;
+ typedef PrefList::iterator iterator;
+
+ PrefList fPreferences;
+
+ typedef StringList PrefixType;
+ PrefixType fPrefixes;
+
+ struct PrefNotifyType
+ {
+ PrefNotifyFunc fFunc;
+ PrefKeyList fKeyList;
+ PrefRefCon fRefCon;
+ };
+ typedef vector<PrefNotifyType> PrefNotifyList;
+
+ PrefNotifyList fNotifications;
+
+ public:
+ static omni_mutex fgPrefsMutex;
+};
+
+extern Preferences* gPrefs;
+
+
+class EmulatorPreferences : public Preferences
+{
+ public:
+ EmulatorPreferences (void);
+ virtual ~EmulatorPreferences(void);
+
+ virtual void Load (void);
+
+ void GetDatabaseMRU (EmFileRefList&);
+ void GetSessionMRU (EmFileRefList&);
+ void GetROMMRU (EmFileRefList&);
+
+ EmFileRef GetIndPRCMRU (int);
+ EmFileRef GetIndRAMMRU (int);
+ EmFileRef GetIndROMMRU (int);
+ EmFileRef GetIndMRU (const EmFileRefList&, int);
+
+ void UpdatePRCMRU (const EmFileRef&);
+ void UpdateRAMMRU (const EmFileRef&);
+ void UpdateROMMRU (const EmFileRef&);
+ void UpdateMRU (EmFileRefList&, const EmFileRef&);
+
+ void RemovePRCMRU (const EmFileRef&);
+ void RemoveRAMMRU (const EmFileRef&);
+ void RemoveROMMRU (const EmFileRef&);
+ void RemoveMRU (EmFileRefList&, const EmFileRef&);
+
+ void SetTransports (void);
+
+ void SetTransportForDevice (EmUARTDeviceType, EmTransport*);
+ EmTransport* GetTransportForDevice (EmUARTDeviceType);
+
+ // Utility routines for determining what should happen in DoDialog.
+
+ Bool LogMessage (Bool isFatal);
+ Bool ShouldQuit (Bool isFatal);
+ Bool ShouldContinue (Bool isFatal);
+ Bool ShouldNextGremlin (Bool isFatal);
+
+ protected:
+ virtual void WriteBanner (FILE*);
+ virtual Bool ReadBanner (FILE*);
+ virtual void StripUnused (void);
+ void MigrateOldPrefs (void);
+
+ EmTransport* fTransports[kUARTEnd];
+};
+
+extern EmulatorPreferences* gEmuPrefs;
+
+
+/*
+ The FOR_EACH_PREF macro is used to manage the preferences keys. Preferences
+ are accessed via keys passed to the Preference constructor. These keys have
+ the symbolic form:
+
+ kPrefKey<Label>
+
+ The macro below is used to declare the keys used to access the settings, define
+ the keys, initialize the settings to default values.
+*/
+
+#define FOR_EACH_PREF(DO_TO_PREF) \
+ FOR_EACH_UNINIT_PREF(DO_TO_PREF) \
+ FOR_EACH_INIT_PREF(DO_TO_PREF)
+
+#define FOR_EACH_UNINIT_PREF(DO_TO_PREF) \
+ DO_TO_PREF(WindowLocation, unused, unused) \
+ DO_TO_PREF(GCWLocation, unused, unused) \
+ DO_TO_PREF(MPWLocation, unused, unused) \
+ DO_TO_PREF(BackgroundColor, unused, unused) \
+ DO_TO_PREF(HighlightColor, unused, unused)
+
+
+#define FOR_EACH_INIT_PREF(DO_TO_PREF) \
+ DO_TO_PREF(RedirectNetLib, bool, (true)) \
+ DO_TO_PREF(EnableSounds, bool, (false)) \
+ DO_TO_PREF(CloseAction, CloseActionType, (kSaveAsk)) \
+ DO_TO_PREF(UserName, string, ("Palm OS Emulator")) \
+ \
+ DO_TO_PREF(PortSerial, EmTransportDescriptor, (kTransportNull)) \
+ DO_TO_PREF(PortIR, EmTransportDescriptor, (kTransportNull)) \
+ DO_TO_PREF(PortMystery, EmTransportDescriptor, (kTransportNull)) \
+ DO_TO_PREF(PortDownload, EmTransportDescriptor, (kTransportNull)) \
+ \
+ DO_TO_PREF(PortSerialSocket, string, ("")) \
+ DO_TO_PREF(PortIRSocket, string, ("")) \
+ \
+ DO_TO_PREF(ReportFreeChunkAccess, bool, (true)) \
+ DO_TO_PREF(ReportHardwareRegisterAccess, bool, (true)) \
+ DO_TO_PREF(ReportLowMemoryAccess, bool, (true)) \
+ DO_TO_PREF(ReportLowStackAccess, bool, (true)) \
+ DO_TO_PREF(ReportMemMgrDataAccess, bool, (true)) \
+ DO_TO_PREF(ReportMemMgrLeaks, bool, (true)) \
+ DO_TO_PREF(ReportMemMgrSemaphore, bool, (true)) \
+ DO_TO_PREF(ReportOffscreenObject, bool, (true)) \
+ DO_TO_PREF(ReportOverlayErrors, bool, (true)) \
+ DO_TO_PREF(ReportProscribedFunction, bool, (true)) \
+ DO_TO_PREF(ReportROMAccess, bool, (true)) \
+ DO_TO_PREF(ReportScreenAccess, bool, (true)) \
+ DO_TO_PREF(ReportSizelessObject, bool, (true)) \
+ DO_TO_PREF(ReportStackAlmostOverflow, bool, (true)) \
+ DO_TO_PREF(ReportStrictIntlChecks, bool, (true)) \
+ DO_TO_PREF(ReportSystemGlobalAccess, bool, (true)) \
+ DO_TO_PREF(ReportUIMgrDataAccess, bool, (true)) \
+ DO_TO_PREF(ReportUnlockedChunkAccess, bool, (true)) \
+ \
+ DO_TO_PREF(ReportLockedRecords, bool, (false)) \
+ DO_TO_PREF(ReportSysFatalAlert, bool, (true)) \
+ \
+ DO_TO_PREF(InterceptSysFatalAlert, bool, (true)) \
+ DO_TO_PREF(DialogBeep, bool, (false)) \
+ \
+ DO_TO_PREF(LogErrorMessages, uint8, (2)) \
+ DO_TO_PREF(LogWarningMessages, uint8, (2)) \
+ DO_TO_PREF(LogGremlins, uint8, (0)) \
+ DO_TO_PREF(LogCPUOpcodes, uint8, (0)) \
+ DO_TO_PREF(LogEnqueuedEvents, uint8, (0)) \
+ DO_TO_PREF(LogDequeuedEvents, uint8, (0)) \
+ DO_TO_PREF(LogSystemCalls, uint8, (0)) \
+ DO_TO_PREF(LogApplicationCalls, uint8, (0)) \
+ DO_TO_PREF(LogSerial, uint8, (0)) \
+ DO_TO_PREF(LogSerialData, uint8, (0)) \
+ DO_TO_PREF(LogNetLib, uint8, (0)) \
+ DO_TO_PREF(LogNetLibData, uint8, (0)) \
+ DO_TO_PREF(LogExgMgr, uint8, (0)) \
+ DO_TO_PREF(LogExgMgrData, uint8, (0)) \
+ DO_TO_PREF(LogHLDebugger, uint8, (0)) \
+ DO_TO_PREF(LogHLDebuggerData, uint8, (0)) \
+ DO_TO_PREF(LogLLDebugger, uint8, (0)) \
+ DO_TO_PREF(LogLLDebuggerData, uint8, (0)) \
+ DO_TO_PREF(LogRPC, uint8, (0)) \
+ DO_TO_PREF(LogRPCData, uint8, (0)) \
+ \
+ DO_TO_PREF(LogFileSize, long, (1 * 1024L * 1024L)) \
+ DO_TO_PREF(LogDefaultDir, EmDirRef, ()) \
+ \
+ DO_TO_PREF(DebuggerSocketPort, long, (6414)) \
+ DO_TO_PREF(RPCSocketPort, long, (6415)) \
+ \
+ DO_TO_PREF(WarnAboutSkinsDir, bool, (true)) \
+ \
+ DO_TO_PREF(AskAboutStartMenu, bool, (true)) \
+ DO_TO_PREF(StartMenuItem, EmFileRef, ()) \
+ \
+ DO_TO_PREF(FillNewBlocks, bool, (false)) \
+ DO_TO_PREF(FillResizedBlocks, bool, (false)) \
+ DO_TO_PREF(FillDisposedBlocks, bool, (false)) \
+ DO_TO_PREF(FillStack, bool, (false)) \
+ \
+ DO_TO_PREF(LastConfiguration, Configuration, (EmDevice ("PalmIII"), 1024, EmFileRef())) \
+ \
+ DO_TO_PREF(GremlinInfo, GremlinInfo, ()) \
+ DO_TO_PREF(HordeInfo, HordeInfo, ()) \
+ \
+ DO_TO_PREF(LastPSF, EmFileRef, ()) \
+ \
+ DO_TO_PREF(ROM_MRU, EmFileRefList, ()) \
+ DO_TO_PREF(PRC_MRU, EmFileRefList, ()) \
+ DO_TO_PREF(PSF_MRU, EmFileRefList, ()) \
+ \
+ DO_TO_PREF(Skins, SkinNameList, ()) \
+ DO_TO_PREF(Scale, ScaleType, (2)) \
+ DO_TO_PREF(DimWhenInactive, bool, (true)) \
+ DO_TO_PREF(ShowDebugMode, bool, (true)) \
+ DO_TO_PREF(ShowGremlinMode, bool, (true)) \
+ DO_TO_PREF(StayOnTop, bool, (false)) \
+ \
+ DO_TO_PREF(WarningOff, EmErrorHandlingOption, (kShow)) \
+ DO_TO_PREF(ErrorOff, EmErrorHandlingOption, (kShow)) \
+ DO_TO_PREF(WarningOn, EmErrorHandlingOption, (kShow)) \
+ DO_TO_PREF(ErrorOn, EmErrorHandlingOption, (kShow)) \
+ \
+ DO_TO_PREF(LastTracerType, string, ("")) \
+ DO_TO_PREF(TracerTypes, string, ("")) \
+ \
+ DO_TO_PREF(FfsHome, string, ("")) \
+ \
+ DO_TO_PREF(SlotList, SlotInfoList, ()) \
+
+
+// Declare all the keys
+#define DECLARE_PREF_KEYS(name, type, init) extern PrefKeyType kPrefKey##name;
+FOR_EACH_PREF(DECLARE_PREF_KEYS)
+
+#endif // _PREFERENCEMGR_H_
diff --git a/SrcShared/Profiling.cpp b/SrcShared/Profiling.cpp
new file mode 100644
index 0000000..2af3dee
--- /dev/null
+++ b/SrcShared/Profiling.cpp
@@ -0,0 +1,2111 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Profiling.h"
+
+#include "EmHAL.h" // GetSystemClockFrequency
+#include "EmMemory.h" // EmMemCheckAddress, EmMemGet16
+#include "EmPalmFunction.h" // FindFunctionName, GetTrapName
+#include "EmStreamFile.h" // EmStreamFile
+#include "Miscellaneous.h" // IsSystemTrap, StMemory
+#include "Platform.h" // Platform::Debugger
+#include "Strings.r.h" // kStr_ values
+#include "UAE.h" // m68k_areg, m68k_dreg, regs, m68k_getpc, get_iword
+
+
+/*
+ P.S. Here are some notes on interpreting the output
+
+ Times are all theoretically in milliseconds. Internally, Poser is faking
+ a clock by counting reads, writes, wait states, and extra cycles for many
+ 68K instructions. I'd estimate this count is correct to within a few percent,
+ and I have a list of known incorrect instructions I'm working on getting more
+ accurate. (Notable issues: JSR, RTS, RTE fall one read short each, for 6 or 8
+ cycles each depending on ROM or RAM, ANDSR, ORSR, and other "SR" instructions
+ are 2 reads short, for 12 or 16 cycles.)
+
+ Anyway, the cycle counts are stored as 64-bit integers in the profiler output,
+ and a multiplier is applied to scale the result to milliseconds based on a
+ 58.xxx MHz clock. So a number like 5661.518 is a bit over 5 1/2 seconds, and
+ 1.255 is a bit over 1 1/4 milliseconds. (In theory at least, I'm still
+ validating the data, if you see anything that strikes you as inaccurate, please
+ tell me about it!)
+
+ The function names mostly come from the ROM.Map file, but there are a few
+ special cases:
+
+ "functions" is a top-level cover that includes all regular function calls
+ "interrupts" is a top-level node that includes all interrupts (except the ones
+ Poser has patched out)
+ "partial" means profiling was started in the middle of the function, so we
+ don't have the address of the fn and consequently don't have a name.
+ "overflow" is a lump of all functions called when we're out of space to track
+ more unique calls, where unique means called from the same path to
+ the "root" of the call tree.
+ "unknown" is a function for which no name could be found. Many functions in
+ .prc files show up as unknown.
+
+ The rest of the names all take the form "Name $address.x" where:
+ Name- is the name of the function or trap.
+ address-For regular functions, the 4 byte address.
+ -For traps, the 2 byte trap number.
+ -For interrupts, the 1 byte interrupt number.
+ x- debugging info, where the name comes from.
+ 't' = trap names table built in Poser,
+ 'm'= the ROM.Map file
+ 'd'=the symbol built into the ROM by the compiler
+ 'i'=invalid address flag (usually due to POSERs implementation internals)
+
+ The other columns are defined as follows. Note MINIMUM and STACK SPACE are
+ NOT what you expect:
+
+ count - the number of times the functions was called.
+ only - time spent in the function, not counting child fns or interrupts.
+ % (by only) - percentage of total profiling time spent in this fn/call.
+ +Children - time spent in the function including child fns, but not
+ including interrupts
+ % (by +Children) - percentage of total profiling time spent in the fn and its kids
+ Average - "Only" divided by "count"
+ Maximum - the maximum time (in msec) spent in any 1 call to the fn.
+ Minimum - NOT WHAT YOU EXPECT. This is actually the time spent handling
+ interrupts for calls to that particlular instance of that fn.
+ Due to the way the "Summary" is calculated, this number won't
+ be correct in summary views.
+ Stack space - NOT WHAT YOU EXPECT. More of a trap/interrupt counter plus
+ some debug info. The number in that field for a particular
+ fn entry is incremented by 1 every time the fn is interrupted,
+ by 10000 if the fn call is made by a faked up RTS instead of
+ a JSR, and 1000 if the function was executing when an RTS
+ occurred that didn't return to it's called but instead returned
+ to some fn farther up the call chain. Again, this will only
+ be useful in the detail view, since the summary does some
+ computation on it.
+
+
+ Please respond to palm-dev-forum@ls.palm.com
+ To: palm-dev-forum@ls.palm.com
+ Subject: Re: RE: Emulator profiling...
+
+ At 7:14 PM -0700 10/6/98, Kenichi Okuyama wrote:
+ >I'll be pleased if you can give us any good information source
+ >beside source code itself, about POSE's profiler. Like, byte
+ >alignment size( is it 4? or 8 on Mac... I don't know about Mac
+ >really ), etc. Those informations, we can't get them from source
+ >code itself, and since I don't have Mac, I can't get them from
+ >project file for Mac, you see.
+
+ I don't think alignment matters much at all for virtually all of the structs.
+
+ The only ones where alignment will be important are the ones written to be
+ compatible with the MW profiler. These are ProfFileHeader and FnCallRecord
+ in Profiling.cpp. All the elements of those structs are either 4 or 8
+ bytes wide.
+
+ The MW profiler file consists of 3 sections. The first section is a
+ header, incompletely described by ProfFileHeader in Profiling.cpp.
+
+ The second section is a big tree of function call blocks. Each block is
+ described by the FnCallRecord struct. The tree is maintained via two
+ pointers in each record, called 'kid' and 'sib', which contain array
+ indexes. kid points to the first child of a given node, sib points to a
+ given node's next sibling. So to enumerate all the kids for a given node
+ you go to that node's kid, then follow the sib links from kid to kid until
+ you get a sib value of -1, which is the end of the sibling list. The other
+ fields in the function call record are pretty much self explanitory. (Note
+ however that the POSER profiler uses cyclesMax and stackUsed for other
+ things! They track trap dispatcher overhead right now.)
+
+ The 3rd section contains the names of all the functions, stored in a string
+ table. The string table is just a concatenation of all the name strings,
+ seperated only by the terminating nulls, with each unique name appearing
+ only once. The FnCallRecord's address field stores the offset of the start
+ of that function's name into the string table. (It's sort of a normalized
+ char *) That structure is a byte stream, there is no other alignment. The
+ function FindOrAddString is used to build the string table when dumping a
+ profiler file.
+
+ >Also, if possible, what kind of information is kept in that profile
+ >file, like function name, call count, running time, etc.
+
+ FnCallRecord should pretty much explain that. The only other interesting
+ thing to note is that the data isn't stored on a function by function basis.
+ Rather, it's stored by unique occurrences of a function. That is, say
+ function A calls function C, and function B also calls function C. There
+ will be two nodes in the function tree (two records) for function C, one
+ storing information from calls from function A, and a second storing
+ information from calls from function B. Recursive functions will create a
+ whole bunch of nodes, one for each level of recursion. ..but that's
+ necessary to properly create the call tree that the MW profiler displays.
+
+ ...the MW profiler's "summary" mode does a lot of work! It has to go
+ through the whole tree and collect the data for each node that represents a
+ given function call and summarize it. That was one of the reasons I chose
+ to try to output MW profiler files!
+
+ I think if I had to make a windows profiler, I'd start with the ProfileDump
+ function in Profiling.cpp. You could change that routine to take the data
+ collected and output whatever you wanted.
+
+ You might look at ProfilePrint, which does a text dump of the gathered
+ profile data. RecursivePrintBlock will give you a good start on something
+ that translates the MW function records into some other data format.
+
+ --Bob
+
+
+ Please respond to palm-dev-forum@3com.com
+ To: palm-dev-forum@ls.3com.com
+ Subject: POSER Profiling under Windows
+
+ The #1 item on my to-do list post-Palm Computing Platform Developer
+ Conference was to update the Windows emulator to enable profiling. I'm
+ happy to say this is done (more or less), and a build is now available.
+ It's 2.1d23, and you can download it at
+ http://palm.3com.com/devzone/pose/seed.html
+
+ There still is no nice viewer for Windows. Instead, the emulator now
+ outputs both the MW Profiler format file and a tab delimited text file
+ containing the same information. Until a nice viewer exists for Windows,
+ you can open the text file in a text editor or spreadsheet app and get at
+ the profiling info.
+
+ For convenience, the text file output is pre-sorted by the "time in
+ function and all it's children" category.
+
+ For inconvenience, all levels of function calls (down into the kernel and
+ beyond) are displayed. Typically this is WAY too much information. The
+ only advice I can offer is a strategy for getting rid of it:
+
+ The first column contains the nesting level of the function -- it defines
+ the "tree". So if there's too much detail inside a particular function
+ call, you can note the number in the fist column, then search downward for
+ an equal number. The intervening lines (often very many) are sub-calls
+ from that first call, and you might want to simply delete them to make the
+ output more readable.
+
+ That is, say you get something like this:
+
+ 1 foo ...
+ 2 bar ...
+ 3 baz ...
+ 4 cj_fdkjqwfd ...
+ 5 kp_sdlsvbnf ...
+ 4 cj_aslkqwsd ...
+ 5 lkaflds ...
+ 6 cj_sdldsfdl ...
+ 7 tm_eouas ...
+ 6 cj_werofs ...
+ 3 qux ...
+
+ If you're only interested in where function foo is spending it's time, you
+ can note that baz and qux are both sub-calls, and everything in-between
+ them are sub-sub-calls that baz made. Anyway, just deleting the lines with
+ nesting level 4 and above will considerably clean up the output and make it
+ easier to read.
+
+ --Bob
+
+*/
+
+// sizes of buffers to use
+#define AVGNAMELENGTH 64
+#define MAXNESTEDINTERRUPTS 8
+
+// max length of routine name (C++ mangled names can be this long!)
+#define MAX_ROUTINE_NAME 256
+
+// shared values exported via Profiling.h
+int64 gClockCycles;
+int64 gReadCycles;
+int64 gWriteCycles;
+
+long gReadMismatch; // debug
+long gWriteMismatch; // debug
+
+int gProfilingEnabled;
+int gProfilingOn;
+int gProfilingCounted;
+int gProfilingDetailed;
+
+emuptr gProfilingEnterAddress;
+emuptr gProfilingReturnAddress;
+emuptr gProfilingExitAddress;
+
+// Internal stuff
+
+int64 gCyclesCounted; // cycles actually counted against functions
+
+static int gMaxCalls;
+static int gMaxDepth;
+
+#define PROFILE_ONE_FN 0 // set to 1 to profile on a particular fn enter/exit
+#define FNTOPROFILE sysTrapDmGetNextDatabaseByTypeCreator
+
+#define NOADDRESS (0x00000000)
+#define ROOTADDRESS (0xFFFFFFFF)
+#define INTERRUPTADDRESS (0xFFFFFFFE)
+#define OVERFLOWADDRESS (0xFFFFFFFD)
+#define NORECORD (-1)
+
+/*
+ The profile output file is composed of three sections. A header section
+ of 0x200 bytes, then a section of FnCallRecord structures containing an
+ array of function data, followed by a string table containing the names
+ of each function. The functions are represented in a tree, where each
+ node represents a given function when called from a particular path to
+ the root of the tree. That is, if A calls C and B calls C, then there
+ will be at least 2 records in the tree representing calls to C, once
+ when called from A and another when called from B. I say at least 2
+ because A and B themselves may be called from multiple places, and each
+ unique version of A and B will also have a unique child node representing C.
+
+ Header
+
+ The header section contains things like the number of functions in the
+ function data array, and offset to the start of the string table, the
+ size of the string table, and the record number (array index) of the
+ root node in the function tree.
+*/
+
+struct ProfFileHeader
+{
+ Int32 proF; // 'proF'
+ Int32 version; // 0x00040002
+ Int32 fnCount; // number of unique fns (records) in log
+ Int32 four; // 0x00000004
+
+ Int32 zeros1; // 0x00000000
+ Int32 zeros2; // 0x00000000
+ Int32 unknown; // 0xB141A3A9 - maybe timebase data
+ Int32 recordsSize; // size of header plus size of data (or offset to string table)
+
+ Int32 stringTableSize;// size of string table in bytes
+ int64 overhead; // count for overhead
+ Int32 rootRec; // record number of root of tree
+
+ Int32 sixtyfour1; // 0x00000064
+ Int32 sixtyfour2; // 0x00000064
+ Int32 countsPerTime; // translation between counts at nodes and integers in column
+ // 0x00FD0000 = 16.580608 MHz with display in seconds
+ // 0x000040C4 = 16.580608 MHz with display in milliseconds
+ Int32 oddstuff0; // seems like it can be 0, set by profiler tool itself
+
+ Int32 oddstuff1; // seems like it can be 0, set by profiler tool itself
+ Int32 oddstuff2; // seems like it can be 0, set by profiler tool itself
+ Int32 oddstuff3; // seems like it can be 0, set by profiler tool itself
+ Int32 oddstuff4; // seems like it can be 0, set by profiler tool itself
+};
+const int kProfFileHeaderSize = 0x200; // bytes (gregs)
+
+/*
+ Function Array
+
+ Following the header (starting at offset 0x200 in the file) is an array
+ of header.fnCount structs as defined below. Each struct represents a unique
+ node in the tree. Most of these values are straightfoward, and appear in
+ the results view representing what you expect. The sib and kid records
+ determine the relationship to other functions in the tree. Children of a
+ given node are found by looking at the node's kid field to find the first
+ child, then look at the child's sib field to find the adjacent nodes which
+ are all considered children of the first kid's parent. If the sib or kid
+ contain -1 then there are no sibling or children nodes.
+*/
+
+struct FnCallRecord
+{
+ emuptr address; // address of fn, also offset from start of name table to this fn's name
+ Int32 entries; // times function was called
+ int64 cyclesSelf; // profiling data for this fn alone
+ int64 cyclesPlusKids; // profiling data for this fn with kids
+ int64 cyclesMin; // profiling data for this fn alone, min
+ int64 cyclesMax; // profiling data for this fn alone, max
+ Int32 sib; // record number of sib, -1 for no sibs
+ Int32 kid; // record number of kid, -1 for no kids
+ Int32 stackUsed; // bytes of stack used by fn, we use it to count unmatched returns
+};
+const int kFnCallRecordSize = 52; // bytes (gregs)
+
+struct FnStackRecord
+{
+ int32 call; // fn data block for fn being called
+ emuptr returnAddress; // return address aka (SP) to calling fn
+ int64 cyclesAtEntry; // cycle count when fn was called
+ int64 cyclesAtInterrupt; // cycle count when fn was interrupted
+ int64 cyclesInKids; // number of cycles spent in subroutines and interrupts
+ int64 cyclesInInterrupts; // number of cycles spent in interrupts for this fn alone
+ int64 cyclesInInterruptsInKids; // how much of cyclesInKids is interrupts
+ int16 opcode; // cached opcode for instruction profiling
+};
+
+/*
+
+ To put this all together graphically, let's assume that an application
+ starts off and calls FuncA, FuncB, and FuncC, in that order. As well,
+ FuncC calls FuncA. At the point where FuncC calls FuncA, our "calls"
+ and "gCallStack" structures look as follows:
+
+ gCallStack
+ 0: PilotMain
+ 1: FuncC
+ 2: FuncA
+
+ gCallTree (as flat array)
+ 0: Root record
+ 1: PilotMain (called from Root)
+ 2: FuncA (called from PilotMain)
+ 3: FuncB (called from PilotMain)
+ 4: FuncC (called from PilotMain)
+ 5: FuncA (called from FuncC)
+
+ gCallTree (as tree)
+
+ PilotMain
+ | (kid)
+ V
+ FuncA -----> FuncB -----> FuncC
+ (sib) (sib) | (kid)
+ V
+ FuncA (gCallTree[5], not gCallTree[2])
+*/
+
+// call tree
+static FnCallRecord* gCallTree = NULL;
+static int32 gFirstFreeCallRec;
+static int32 gRootRecord;
+static int32 gExceptionRecord;
+static int32 gOverflowRecord;
+
+// call stack (interrupts and calls in interrupts on same stack)
+static FnStackRecord* gCallStack = NULL;
+static int gCallStackSP;
+
+// interrupt tracking, interrupt stack is gCallStackSP when interrupt happened
+static int gInterruptDepth;
+static int gInterruptStack[MAXNESTEDINTERRUPTS];
+static int64 gInterruptCount;
+static int64 gInterruptCycles;
+
+static unsigned long gMissedCount; // debug
+static unsigned long gExtraPopCount; // debug
+static int gInterruptMismatch; // debug
+
+// for detailed (instruction level) profiling
+static int gInInstruction;
+static FILE* gProfilingDetailLog;
+static int64 gClockCyclesLast;
+static int64 gClockCyclesSaved;
+static int64 gReadCyclesSaved;
+static int64 gWriteCyclesSaved;
+static emuptr gDetailStartAddr;
+static emuptr gDetailStopAddr;
+
+
+
+//---------------------------------------------------------------------
+// Get function name out of debug symbols compiler produces
+//---------------------------------------------------------------------
+
+struct ROMMapRecord
+{
+ emuptr address;
+ char* name;
+};
+ROMMapRecord* gROMMap = NULL;
+int gROMMapEnd = 0;
+
+
+// ¥¥¥ÊDOLATER ¥¥¥
+// We need to handle shared library routines, which are called by
+// trap dispatcher. They start at 0x0000A800
+
+#define kOpcode_ADD 0x0697 // ADD.L X, (A7)
+#define kOpcode_LINK 0x4E50
+#define kOpcode_RTE 0x4E73
+#define kOpcode_RTD 0x4E74
+#define kOpcode_RTS 0x4E75
+#define kOpcode_JMP 0x4ED0
+
+#define FIRSTTRAP 0x0000A000UL
+#define LASTTRAP (FIRSTTRAP + 0x0001000)
+
+#define LAST_EXCEPTION 0x100
+
+#define IS_TRAP_16(addr) (((addr) >= FIRSTTRAP) && ((addr) < LASTTRAP))
+#define IS_TRAP_32(addr) IS_TRAP_16((addr) >> 16)
+#define PACK_TRAP_INFO(trap, extra) ((((uint32) (trap)) << 16) | ((uint16) (extra)))
+#define TRAP_NUM(field) (((field) >> 16) & 0x0FFFF)
+#define TRAP_EXTRA(field) ((field) & 0x0FFFF)
+
+// Creates unique file names for Profile output files
+
+string CreateFileNameForProfile (Bool forText);
+
+
+uint32 gCyclesPerSecond;
+
+uint32 inline PrvGetCyclesPerSecond (void)
+{
+ if (gCyclesPerSecond == 0)
+ {
+ gCyclesPerSecond = EmHAL::GetSystemClockFrequency ();
+ }
+
+ return gCyclesPerSecond;
+}
+
+uint32 inline PrvGetCyclesPerMillisecond (void)
+{
+ return PrvGetCyclesPerSecond () / 1000;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ GetRoutineName
+// ---------------------------------------------------------------------------
+// GetRoutineName turns an address (or interrupt number or trap number) into a
+// string representation for that function. It attempts to use the ROM.map
+// data to find the function name, and if no match is found it steps through
+// the instructions found at the address indicated until it finds the end of
+// the function, then looks for the debug symbol. If the address was to a
+// function in a code resource and the resource was moved, then the name will
+// be incorrect. GetRoutineName is completely responsible for turning an
+// address into a name, and it will always return some string, even if passed
+// an invalid address.
+
+// Llamagraphics, Inc: Rather than passing in a buffer of unknown length,
+// GetRoutineName now returns a statically allocated string that's good
+// until the next time GetRoutineName is called. This eliminates the need
+// for dynamically allocating space in the heap for this string, and makes
+// it easier to ensure that the buffer isn't overrun.
+
+static char * GetRoutineName (emuptr addr)
+{
+ // Llamagraphics, Inc: IMPORTANT!!!
+ // C++ routine names stored in MacsBug format can take a full 256 characters
+ // to store. Any text that we append in addition to the MacsBug name must be
+ // allowed for in the buffer size.
+ static char buffer[256 + 18];
+ emuptr startAddr;
+
+ // if it's a dummy function header, say so
+ if (addr == NOADDRESS)
+ {
+ strcpy(buffer, Platform::GetString (kStr_ProfPartial).c_str ());
+ return buffer;
+ }
+
+ if (addr == ROOTADDRESS)
+ {
+ strcpy(buffer, Platform::GetString (kStr_ProfFunctions).c_str ());
+ return buffer;
+ }
+
+ if (addr == INTERRUPTADDRESS)
+ {
+ strcpy(buffer, Platform::GetString (kStr_ProfInterrupts).c_str ());
+ return buffer;
+ }
+
+ if (addr == OVERFLOWADDRESS)
+ {
+ strcpy(buffer, Platform::GetString (kStr_ProfOverflow).c_str ());
+ return buffer;
+ }
+
+ if (addr < LAST_EXCEPTION)
+ {
+ sprintf(buffer, Platform::GetString (kStr_ProfInterruptX).c_str (), addr);
+ return buffer;
+ }
+
+ // check for traps
+ if (IS_TRAP_32(addr))
+ {
+ sprintf(buffer, Platform::GetString (kStr_ProfTrapNameAddress).c_str (),
+ ::GetTrapName (TRAP_NUM(addr), TRAP_EXTRA(addr), true), TRAP_NUM(addr));
+ return buffer;
+ }
+
+ // look up address in the ROM map
+ if (gROMMap != NULL)
+ {
+ int i = 0;
+ // ¥¥¥ÊDOLATER ¥¥¥ use binary search, since gROMMap is sorted by address
+ while (i < gROMMapEnd && addr > gROMMap[i].address)
+ i++;
+ if (i < gROMMapEnd && addr == gROMMap[i].address)
+ {
+ sprintf(buffer, Platform::GetString (kStr_ProfROMNameAddress).c_str (), gROMMap[i].name, addr);
+ return buffer;
+ }
+ }
+
+ // if not in the map, try to get the symbol out of the ROM itself
+ // Llamagraphics, Inc: Pass in the size of the buffer to FindFunctionName,
+ // which prevents it from truncating the name at 31 characters.
+ ::FindFunctionName (addr, buffer, &startAddr, NULL, sizeof(buffer));
+
+ if (strlen (buffer) == 0)
+ {
+ // no symbol in ROM or invalid address, just output address
+ sprintf (buffer, Platform::GetString (kStr_ProfUnknownName).c_str (), addr);
+ }
+ else
+ {
+ if (startAddr != addr)
+ sprintf(&buffer[strlen(buffer)], "+$%04lX", addr-startAddr);
+
+#if 0
+ // Removed this for now. From Catherine White (cewhite@llamagraphics.com):
+ //
+ // By the way, including the 12 char absolute address in square brackets
+ // interferes with the MW Profiler feature that unmangles C++ function
+ // names. In our copy of the Emulator we've chosen to eliminate the absolute
+ // address because we prefer to see the unmangled names in the profiler. It
+ // makes it easier to see what is going on.
+
+ // Hack the address onto the end
+ sprintf(&buffer[strlen(buffer)], " [$%08lX]", addr);
+#endif
+ }
+
+ return buffer;
+}
+
+
+
+
+
+//---------------------------------------------------------------------
+// Converting addresses to human readable names
+//---------------------------------------------------------------------
+
+char* gStringTable = NULL;
+int gStringTableEnd;
+int gStringTableCapacity;
+
+
+// ---------------------------------------------------------------------------
+// ¥ InitStringTable
+// ---------------------------------------------------------------------------
+// Allocate the string table
+
+static void InitStringTable (void)
+{
+ // Llamagraphics, Inc: Since the gStringTable can now grow dynamically,
+ // the initial value for gStringTableCapacity isn't so crucial as it once
+ // was. AVGNAMELENGTH * MAXUNIQUEFNS may be overkill.
+
+ gStringTableCapacity = AVGNAMELENGTH * MAXUNIQUEFNS;
+ gStringTable = (char*) Platform::AllocateMemory (gStringTableCapacity);
+ gStringTableEnd = 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CleanupStringTable
+// ---------------------------------------------------------------------------
+
+static void CleanupStringTable (void)
+{
+ Platform::DisposeMemory (gStringTable);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ FindOrAddString
+// ---------------------------------------------------------------------------
+
+static int FindOrAddString (const char* newS)
+{
+ int offset = 0;
+ while (offset < gStringTableEnd)
+ {
+ if (strcmp (&gStringTable[offset], newS) == 0)
+ return offset;
+ else
+ offset += strlen (&gStringTable[offset]) + 1;
+ }
+
+ // Llamagraphics, Inc: Added code to automatically increase the size of
+ // the gStringTable as needed. This is part of the solution for handling
+ // long mangled C++ function names.
+
+ gStringTableEnd = offset + strlen(newS) + 1;
+ if (gStringTableEnd > gStringTableCapacity)
+ {
+ // We need to increase the capacity of the gStringTable. Note that
+ // even though we've modified gStringTableEnd, offset contains the
+ // previous value of gStringTableEnd.
+
+ gStringTableCapacity = (gStringTableEnd * 8) / 5; // a moderately bigger number
+ char* newTable = (char*) Platform::AllocateMemory (gStringTableCapacity);
+ memcpy (newTable, gStringTable, offset);
+ Platform::DisposeMemory (gStringTable);
+ gStringTable = newTable;
+ }
+
+ strcpy (&gStringTable[offset], newS);
+ return offset;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ LinearAddressToStrings
+// ---------------------------------------------------------------------------
+
+// Llamagraphics, Inc: This routine used to be recursive, but we rewrote
+// it to be linear because the recursive version was blowing the stack
+// on the Macintosh.
+
+static void LinearAddressToStrings (void)
+{
+ for (int32 i = 0; i < gFirstFreeCallRec; ++i)
+ {
+ // Not all addresses are valid. For instance, I've seen the value
+ // 0x011dec94 in gCallTree[x].address, which is either the address of the
+ // TRAP $C instruction used to regain control in ATrap::DoCall, or
+ // December 11, 1994.
+ // ...but that's OK, GetRoutineName handles that (calls EmMemCheckAddress)
+
+ gCallTree[i].address = FindOrAddString (GetRoutineName (gCallTree[i].address));
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CheckTree
+// ---------------------------------------------------------------------------
+
+#if 0
+
+// Llamagraphics, Inc: We wrote this routine to sanity check the calls
+// tree and make sure that the kid and sib links were consistant. It
+// didn't turn up any problems, but might come in handy in the future.
+// It did help us understand that recursing on siblings is a bad idea...
+
+static void CheckTree (void)
+{
+ EmAssert (gFirstFreeCallRec <= gMaxCalls);
+
+ bool* isUsed = new bool[gMaxCalls];
+ int* pending = new int[gMaxDepth];
+
+ EmAssert (isUsed != 0);
+ EmAssert (pending != 0);
+
+ for (int i = 0; i < gMaxCalls; ++i)
+ isUsed[i] = false;
+
+ for (int i = 0; i < gMaxDepth; ++i)
+ pending[i] = NORECORD;
+
+ int depth = 0;
+ int maxDepth = 0;
+ int recordsProcessed = 0;
+
+ // To start with, just the root node is pending
+ pending[depth++] = gRootRecord;
+ while (depth > 0)
+ {
+ // Pop off the current record
+ int current = pending[--depth];
+
+ // If the current record is NORECORD, then we're done
+ // at this level and can continue popping to the next level.
+ if (current == NORECORD)
+ continue;
+
+ EmAssert ((current >= 0) && (current < gFirstFreeCallRec));
+
+ ++recordsProcessed;
+
+ // Make sure that this is the first time that we've processed
+ // this record.
+
+ EmAssert (!isUsed[current]);
+ isUsed[current] = true;
+
+ // If we have a sibling, push it on the stack.
+ if (gCallTree[current].sib != NORECORD)
+ {
+ EmAssert (depth < gMaxDepth);
+ pending[depth++] = gCallTree[current].sib;
+ if (depth > maxDepth)
+ maxDepth = depth;
+ }
+
+ // If we have a kid, push it on the stack.
+ if (gCallTree[current].kid != NORECORD)
+ {
+ EmAssert (depth < gMaxDepth);
+ pending[depth++] = gCallTree[current].kid;
+ if (depth > maxDepth)
+ maxDepth = depth;
+ }
+ }
+
+ // Make sure that all of the records were used.
+ for (int i = 0; i < gFirstFreeCallRec; ++i)
+ {
+ EmAssert (isUsed[i]);
+ }
+
+ EmAssert (recordsProcessed == gFirstFreeCallRec);
+
+ delete [] isUsed;
+ delete [] pending;
+}
+
+#endif
+
+//---------------------------------------------------------------------
+// debugging routine to print profiling stuff to a log file
+//---------------------------------------------------------------------
+
+#if PLATFORM_WINDOWS
+#define LINE_FORMAT_SPEC "%d\t%d\t%d\t%s\t%ld\t%I64d\t%.3f\t%.1f\t%I64d\t%.3f\t%.1f\t%.3f\t%.3f\t%.3f\t%ld\n"
+#else // MAC
+#define LINE_FORMAT_SPEC "%d\t%d\t%d\t%s\t%ld\t%lld\t%.3f\t%.1f\t%lld\t%.3f\t%.1f\t%.3f\t%.3f\t%.3f\t%ld\n"
+#endif
+
+#define MAXNESTING 80
+
+
+// ---------------------------------------------------------------------------
+// ¥ RecursivePrintBlock
+// ---------------------------------------------------------------------------
+
+static void RecursivePrintBlock(FILE* resultsLog, int i, int depth, int parent)
+{
+ while (i != NORECORD)
+ {
+ // Use statics in this function to reduce stack frame size
+ // from 272 bytes to 160 bytes. Printing each number by itself
+ // instead of with one long formatting string further reduces
+ // the stack frame size to 96 bytes.
+ //
+ // And, yes, these efforts are important. We were easly using
+ // 190K of stack space, blowing the space allocated on the Mac.
+
+ static double cyclesSelfms;
+ static double cyclesSelfpct;
+ static double cyclesKidsms;
+ static double cyclesKidspct;
+
+ cyclesSelfms = gCallTree[i].cyclesSelf / PrvGetCyclesPerMillisecond ();
+ cyclesSelfpct = gCallTree[i].cyclesSelf / gCyclesCounted * 100;
+ cyclesKidsms = gCallTree[i].cyclesPlusKids / PrvGetCyclesPerMillisecond ();
+ cyclesKidspct = gCallTree[i].cyclesPlusKids / gCyclesCounted * 100;
+
+ static double temp1;
+ static double temp2;
+ static double temp3;
+
+ temp1 = (double) gCallTree[i].cyclesSelf / (double)gCallTree[i].entries / (double)PrvGetCyclesPerMillisecond ();
+ temp2 = (double) gCallTree[i].cyclesMax / (double)PrvGetCyclesPerMillisecond ();
+ temp3 = (double) gCallTree[i].cyclesMin / (double)PrvGetCyclesPerMillisecond ();
+
+ fprintf (resultsLog, "%d", i);
+ fprintf (resultsLog, "\t%d", parent);
+ fprintf (resultsLog, "\t%d", depth);
+ fprintf (resultsLog, "\t%s", GetRoutineName (gCallTree[i].address));
+ fprintf (resultsLog, "\t%ld", gCallTree[i].entries);
+ fprintf (resultsLog, "\t%lld", gCallTree[i].cyclesSelf);
+ fprintf (resultsLog, "\t%.3f", cyclesSelfms);
+ fprintf (resultsLog, "\t%.1f", cyclesSelfpct);
+ fprintf (resultsLog, "\t%lld", gCallTree[i].cyclesPlusKids);
+ fprintf (resultsLog, "\t%.3f", cyclesKidsms);
+ fprintf (resultsLog, "\t%.1f", cyclesKidspct);
+ fprintf (resultsLog, "\t%.3f", temp1);
+ fprintf (resultsLog, "\t%.3f", temp2);
+ fprintf (resultsLog, "\t%.3f", temp3);
+ fprintf (resultsLog, "\t%ld\n", gCallTree[i].stackUsed);
+
+ RecursivePrintBlock (resultsLog, gCallTree[i].kid, depth + 1, i);
+
+ // Was:
+ //
+ // RecursivePrintBlock(resultsLog, gCallTree[i].sib, depth, parent);
+ //
+ // Recoded to manually force tail-recursion. Doing this bumped
+ // the stack frame size back up to 112 bytes, but hopefully this is
+ // greatly offset by not recursing as much.
+
+ i = gCallTree[i].sib;
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PrintBlock
+// ---------------------------------------------------------------------------
+
+static void PrintBlock(FILE *resultsLog, int i)
+{
+ RecursivePrintBlock (resultsLog, i, 0, NORECORD);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ RecursiveSortKids
+// ---------------------------------------------------------------------------
+
+static void RecursiveSortKids(int parent)
+{
+ if (parent != NORECORD)
+ {
+ int i = gCallTree[parent].kid;
+ int iprev = NORECORD;
+
+ while (i != NORECORD)
+ {
+ // sort the kids of each node
+ RecursiveSortKids(i);
+
+ // start at root, examine each node until insertion point is found
+ int j = gCallTree[parent].kid;
+ int jprev = NORECORD;
+
+ while ( j != NORECORD &&
+ j != i &&
+ gCallTree[i].cyclesPlusKids < gCallTree[j].cyclesPlusKids)
+ {
+ jprev = j;
+ j = gCallTree[j].sib;
+ }
+
+ // assuming inserting eariler in list, update pointers.
+ if (j != NORECORD)
+ {
+ if (j == i)
+ {
+ // no need to insert, since it's in the right place, so just go on
+ iprev = i;
+ }
+ else
+ {
+ // moving i, so first remove i from list
+ if (iprev == NORECORD) Platform::Debugger(); // should never happen, i replacing itself!
+ gCallTree[iprev].sib = gCallTree[i].sib;
+
+ // insert i before j
+ if (jprev == NORECORD)
+ {
+ gCallTree[i].sib = gCallTree[parent].kid;
+ gCallTree[parent].kid = i;
+ }
+ else
+ {
+ gCallTree[i].sib = gCallTree[jprev].sib;
+ gCallTree[jprev].sib = i;
+ }
+ }
+ }
+
+ // go on to next node
+ i = gCallTree[iprev].sib;
+ }
+
+ }
+}
+
+
+//---------------------------------------------------------------------
+// Call stack and call record management routines
+//---------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ PopCallStackFn
+// ---------------------------------------------------------------------------
+// PopCallStackFn is used when a function or interrupt is being exited from.
+// It updates the nodes in the tree to properly track call counts and time
+// spent in interrupts and in children. It is called both during normal
+// function or interrupt exit and by cleanup code that's trying to keep the
+// profiler's call stack in sync with the CPU's call stack.
+
+static int64 PopCallStackFn(Boolean normalReturn)
+{
+ EmAssert (gCallStackSP >= 0);
+
+ // cyclesThisCall includes all interrupts and kids
+ int64 cyclesThisCall = gClockCycles - gCallStack[gCallStackSP].cyclesAtEntry;
+
+ // cyclesInMe does not include interrupts or kids
+ int64 cyclesInMe = cyclesThisCall - gCallStack[gCallStackSP].cyclesInKids;
+
+ int64 totalCyclesInInterrupts = gCallStack[gCallStackSP].cyclesInInterrupts +
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids;
+
+ int32 exiter = gCallStack[gCallStackSP].call;
+
+ gCallTree[exiter].entries++;
+
+ gCallTree[exiter].cyclesPlusKids = gCallTree[exiter].cyclesPlusKids + cyclesThisCall;
+ gCallTree[exiter].cyclesPlusKids = gCallTree[exiter].cyclesPlusKids - totalCyclesInInterrupts;
+
+ gCallTree[exiter].cyclesSelf = gCallTree[exiter].cyclesSelf + cyclesInMe;
+
+ // using cyclesMin to count time in interrupt handlers
+ gCallTree[exiter].cyclesMin = gCallTree[exiter].cyclesMin +
+ gCallStack[gCallStackSP].cyclesInInterrupts;
+
+ if ((cyclesInMe - gCallTree[exiter].cyclesMax) > 0)
+ gCallTree[exiter].cyclesMax = cyclesInMe;
+
+ if (!normalReturn)
+ gCallTree[exiter].stackUsed += 10000;
+
+ --gCallStackSP;
+ if (gCallStackSP >= 0) {
+ gCallStack[gCallStackSP].cyclesInKids = gCallStack[gCallStackSP].cyclesInKids +
+ cyclesThisCall;
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids =
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids +
+ totalCyclesInInterrupts;
+ }
+
+ return cyclesThisCall;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ FindOrAddCall
+// ---------------------------------------------------------------------------
+// FindOrAddCall is used when a function or interrupt is being entered. It
+// looks to see if the function has prevously been called from the current
+// function or interrupt, and if so returns the existing record. If not, a
+// new record is allocated, initialized, and plugged into the tree.
+
+static int FindOrAddCall (int head, emuptr address)
+{
+ int newR = NORECORD;
+ int current = NORECORD;
+ int prev = NORECORD;
+
+ if (head == gOverflowRecord)
+ return gOverflowRecord;
+
+ if (head == NORECORD)
+ {
+ newR = gFirstFreeCallRec++; // head is empty, just create record
+ }
+ else
+ {
+ // look for existing
+ current = head;
+ while (current != NORECORD && gCallTree[current].address != address)
+ {
+ // Because of the "head == NORECORD" test above, we are guaranteed
+ // to enter the loop body at least once, thus initializing "prev".
+ // This is important, because we use "prev" later.
+
+ prev = current;
+ current = gCallTree[current].sib;
+ }
+
+ if (current != NORECORD) // also returns if current == gOverflowRecord, good!
+ return current;
+
+ newR = gFirstFreeCallRec++;
+ if (newR >= gMaxCalls)
+ return gOverflowRecord;
+
+ gCallTree[prev].sib = newR;
+ }
+
+ if (newR >= gMaxCalls)
+ return gOverflowRecord;
+
+ EmAssert ( address == ROOTADDRESS ||
+ address == INTERRUPTADDRESS ||
+ address == OVERFLOWADDRESS ||
+ IS_TRAP_32(address) ||
+ EmMemCheckAddress (address, 2));
+
+ // fill record
+ gCallTree[newR].sib = NORECORD;
+ gCallTree[newR].kid = NORECORD;
+ gCallTree[newR].address = address;
+ gCallTree[newR].entries = 0;
+ gCallTree[newR].cyclesSelf = 0;
+ gCallTree[newR].cyclesPlusKids = 0;
+ gCallTree[newR].cyclesMin = 0; // 0xFFFFFFFFFFFFFFFF;
+ gCallTree[newR].cyclesMax = 0;
+ gCallTree[newR].stackUsed = 0;
+
+ return newR;
+}
+
+
+#pragma mark -
+
+//---------------------------------------------------------------------
+// Main entry points, exported via Profiling.h
+//---------------------------------------------------------------------
+
+Bool ProfileCanInit (void)
+{
+ return !gProfilingEnabled;
+}
+
+Bool ProfileCanStart (void)
+{
+ return !gProfilingOn;
+}
+
+Bool ProfileCanStop (void)
+{
+ return gProfilingEnabled && gProfilingOn;
+}
+
+Bool ProfileCanDump (void)
+{
+ return gProfilingEnabled;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileInit
+// ---------------------------------------------------------------------------
+// ProfileInit allocates the stack and tree with the passed sizes, and
+// initializes a bunch of other data structures.
+
+void ProfileInit(int maxCalls, int maxDepth)
+{
+ EmAssert (::ProfileCanInit ());
+
+ // initialize globals
+ gClockCycles = 0;
+ gReadCycles = 0;
+ gWriteCycles = 0;
+
+ gReadMismatch = 0; // debug
+ gWriteMismatch = 0; // debug
+
+ gProfilingEnabled = true;
+ gProfilingOn = false;
+ gProfilingCounted = false;
+ gProfilingDetailed = false;
+ gInterruptCycles = 0;
+ gInterruptCount = 0;
+ gMaxCalls = maxCalls;
+ gMaxDepth = maxDepth;
+
+ gMissedCount = 0; // debug
+ gExtraPopCount = 0; // debug
+ gInterruptMismatch = 0; // debug
+
+ // initialize call tree
+ // Llamagraphics, Inc: Dispose of old gCallTree rather than calling Debugger()
+
+ Platform::DisposeMemory (gCallTree);
+ gCallTree = (FnCallRecord*) Platform::AllocateMemory (sizeof (FnCallRecord) * gMaxCalls);
+
+ gFirstFreeCallRec = 0;
+ gExceptionRecord = FindOrAddCall (NORECORD, INTERRUPTADDRESS);
+ gOverflowRecord = FindOrAddCall (NORECORD, OVERFLOWADDRESS);
+
+ // initialize call stack
+ // Llamagraphics, Inc: Dispose of old gCallStack rather than calling Debugger()
+
+ Platform::DisposeMemory (gCallStack);
+ gCallStack = (FnStackRecord*) Platform::AllocateMemory (sizeof (FnStackRecord) * gMaxDepth);
+
+ gCallStackSP = 0;
+
+ gCallStack[gCallStackSP].call = gRootRecord = FindOrAddCall (NORECORD, NOADDRESS);
+ gCallStack[gCallStackSP].returnAddress = NOADDRESS;
+ gCallStack[gCallStackSP].cyclesAtEntry = gClockCycles;
+ gCallStack[gCallStackSP].cyclesInKids = 0;
+ gCallStack[gCallStackSP].cyclesInInterrupts = 0;
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids = 0;
+
+ gProfilingDetailLog = NULL;
+
+ // ¥¥¥ for testing
+ // ProfileDetailFn(0x10CA68A0, true);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileCleanup
+// ---------------------------------------------------------------------------
+// ProfileCleanup frees the data structures allocated in ProfileInit.
+
+void ProfileCleanup()
+{
+ EmAssert (::ProfileCanDump ());
+
+ gProfilingEnabled = false;
+
+ Platform::DisposeMemory (gCallTree);
+ Platform::DisposeMemory (gCallStack);
+
+ if (gProfilingDetailLog != NULL)
+ fclose (gProfilingDetailLog);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileStart
+// ---------------------------------------------------------------------------
+// ProfileStart turns on the profiling flags. Currently it assumes that it is
+// not called from within an interrupt, often is not the case. When invoked
+// from the POSER UI, the CPU is often currently processing an interrupt.
+
+void ProfileStart()
+{
+ // If the system's not initialized, initialize it with
+ // default settings.
+
+ if (::ProfileCanInit ())
+ {
+ ::ProfileInit (MAXFNCALLS, MAXDEPTH);
+ }
+
+
+ if (gCallStackSP != 0) // debug check
+ Platform::Debugger ();
+
+ gProfilingOn = true;
+ gInterruptDepth = -1;
+ gInInstruction = false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileStop
+// ---------------------------------------------------------------------------
+// ProfileStop turns off collection of profiling data. If there are functions
+// currently on the profiling stack, they are popped.
+
+void ProfileStop()
+{
+ EmAssert (::ProfileCanStop ());
+
+ // pop any functions on stack, updating cycles on the way up
+ // stop when gCallStackSP == 0, which matches fake "root" fn
+
+ while (gInterruptDepth >= 0) // means we stopped profiling in an interrupt...
+ ProfileInterruptExit (NOADDRESS);
+
+ while (gCallStackSP > 0)
+ PopCallStackFn (false); // doesn't gather stats on the way out
+
+ gProfilingOn = false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfilePrint
+// ---------------------------------------------------------------------------
+
+void ProfilePrint(const char* fileName)
+{
+ if (!gProfilingEnabled)
+ Platform::Debugger ();
+
+ if (gProfilingOn)
+ return;
+
+ gCyclesCounted = gCallTree[gRootRecord].cyclesPlusKids +
+ gCallTree[gExceptionRecord].cyclesPlusKids +
+ gCallTree[gOverflowRecord].cyclesPlusKids;
+
+ string textFileName;
+ if (fileName == NULL)
+ {
+ textFileName = CreateFileNameForProfile (true); // for text = true
+ fileName = textFileName.c_str ();
+ }
+
+ FILE* resultsLog = fopen (fileName, "w");
+
+ fputs ("index\tparent\tdepth\tfunction name\tcount\tonly cycles\tonly msec\tonly %\tplus kids cycles\tplus kids msec\tplus kids %\taverage msec\tmax msec\tinterrupt msec\tinterrupt count/debug\n", resultsLog);
+
+ RecursiveSortKids (gRootRecord);
+ RecursiveSortKids (gExceptionRecord);
+
+ PrintBlock (resultsLog, gRootRecord);
+
+ // in case ProfilePrint was called on its own, dump out exception and overflow nodes
+ // (these will be sibs of gRootRecord if called from ProfileDump)
+
+ if (gCallTree[gRootRecord].sib == NORECORD)
+ PrintBlock (resultsLog, gExceptionRecord);
+
+ if (gCallTree[gExceptionRecord].sib == NORECORD)
+ PrintBlock (resultsLog, gOverflowRecord);
+
+
+#if PLATFORM_WINDOWS
+ fprintf (resultsLog, "\tcycles counted:\t\t%I64d\n", gCyclesCounted);
+ fprintf (resultsLog, "\ttotal clocks:\t\t%I64d\n", gClockCycles);
+ fprintf (resultsLog, "\ttotal reads:\t\t%I64d\n", gReadCycles);
+ fprintf (resultsLog, "\ttotal writes:\t\t%I64d\n", gWriteCycles);
+#else // MAC
+ fprintf (resultsLog, "\tcycles counted:\t\t%lld\n", gCyclesCounted);
+ fprintf (resultsLog, "\ttotal clocks:\t\t%lld\n", gClockCycles);
+ fprintf (resultsLog, "\ttotal reads:\t\t%lld\n", gReadCycles);
+ fprintf (resultsLog, "\ttotal writes:\t\t%lld\n", gWriteCycles);
+#endif
+
+ fprintf (resultsLog, "\treturn level mis-matches:\t\t%ld\n", gExtraPopCount);
+ fprintf (resultsLog, "\tnon-matching returns:\t\t%ld\n", gMissedCount);
+
+ fclose (resultsLog);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ScanROMMapFile
+// ---------------------------------------------------------------------------
+// Process the next line of text from the ROM map file, and return true
+// if we found a valid name/address pair.
+
+static Boolean ScanROMMapFile(FILE* iROMMapFile, char* oRoutineName, emuptr* oAddr)
+{
+ // Read in the next line from the ROM map file, which looks like:
+ // MenuGetVisible $10d06916
+ // WARNING - the scan length for the name _must_ match MAX_ROUTINE_NAME
+
+ int numArgs = fscanf (iROMMapFile, " %256s $%lx \n", oRoutineName, oAddr);
+
+ if (numArgs != 2)
+ {
+ // See if we hit one of the Segment entries, which looks like:
+ // Segment "launcherSeg2" size=$10d00e68
+
+ if ((strcmp (oRoutineName, "Segment") == 0) && (numArgs == 1))
+ {
+ fscanf (iROMMapFile, " %*s size=$%*x \n");
+ }
+ else
+ {
+ // DOLATER kwk - this should display an error.
+ Platform::Debugger ();
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileDump
+// ---------------------------------------------------------------------------
+// ProfileDump reads in the ROM.map file, turns all the addresses in the call
+// tree into real function names, generating the string table in the process,
+// then dumps out the header, tree, and stringtable to disk. This operation is
+// destructive to the function tree, and cannot be done more than once. (It
+// should probably call ProfileCleanup to make sure this doesn't happen.)
+
+void ProfileDump (const char* fileName)
+{
+ // If profiling is occurring, stop it.
+
+ if (::ProfileCanStop ())
+ {
+ ::ProfileStop ();
+ }
+
+ EmAssert (::ProfileCanDump ());
+
+ // Zero this out so that it can be refetched and recached for the
+ // current processor.
+
+ gCyclesPerSecond = 0;
+
+ string mwfFileName;
+ if (fileName == NULL)
+ {
+ mwfFileName = CreateFileNameForProfile (false);
+ fileName = mwfFileName.c_str (); // for text = false
+ }
+
+ long romRoutineNameBytes = 0;
+ long romRoutineNames = 0;
+ char romRoutineName[MAX_ROUTINE_NAME + 1];
+ emuptr addr;
+
+ // DOLATER kwk - try to open <rom name>.map in same folder as current ROM file.
+ // If that fails, go for "ROM.map" in same folder as Poser.
+ FILE* romMapFile = fopen("ROM.map", "r");
+
+ // If we have a ROM map, count the number of routines and the space required
+ // to save all of the routine names. Note that previously the max rom function
+ // names was set to 3000, but currently we've got 5808 names in a 4.0 build.
+ if (romMapFile)
+ {
+ while (!feof (romMapFile))
+ {
+ if (ScanROMMapFile(romMapFile, romRoutineName, &addr))
+ {
+ romRoutineNames += 1;
+ romRoutineNameBytes += strlen(romRoutineName) + 1;
+ }
+ }
+
+ rewind(romMapFile);
+ }
+
+ // Read in the names & addresses from the ROM map file
+ if (gROMMap != NULL)
+ Platform::Debugger();
+ gROMMap = (ROMMapRecord*)Platform::AllocateMemory(sizeof(ROMMapRecord) * romRoutineNames);
+ gROMMapEnd = 0;
+
+ StMemory names (romRoutineNameBytes);
+ char *namesEnd = names.Get();
+
+ if (romMapFile)
+ {
+ while (!feof (romMapFile))
+ {
+ if (ScanROMMapFile (romMapFile, romRoutineName, &addr))
+ {
+ if (gROMMapEnd >= romRoutineNames)
+ {
+ Platform::Debugger ();
+ }
+
+ gROMMap[gROMMapEnd].address = addr;
+ gROMMap[gROMMapEnd++].name = namesEnd;
+ strcpy(namesEnd, romRoutineName);
+ namesEnd += strlen(romRoutineName) + 1;
+ }
+ }
+
+ fclose (romMapFile);
+ }
+
+ // fix up trees a bit (sum cycle counts for root nodes)
+
+ gCallTree[gRootRecord].address = ROOTADDRESS;
+ int current = gCallTree[gRootRecord].kid;
+ while (current != NORECORD)
+ {
+ gCallTree[gRootRecord].cyclesPlusKids += gCallTree[current].cyclesPlusKids;
+ current = gCallTree[current].sib;
+ }
+
+ current = gCallTree[gExceptionRecord].kid;
+ while (current != NORECORD)
+ {
+ gCallTree[gExceptionRecord].cyclesPlusKids += gCallTree[current].cyclesPlusKids;
+ current = gCallTree[current].sib;
+ }
+
+ // compute total cycles counted
+
+ gCyclesCounted = gCallTree[gRootRecord].cyclesPlusKids +
+ gCallTree[gExceptionRecord].cyclesPlusKids +
+ gCallTree[gOverflowRecord].cyclesPlusKids;
+
+ // debugging
+
+ if (gCallTree[gRootRecord].sib != NORECORD ||
+ gCallTree[gExceptionRecord].sib != NORECORD ||
+ gCallTree[gOverflowRecord].sib != NORECORD ||
+ gCallTree[gOverflowRecord].kid != NORECORD)
+ {
+ Platform::Debugger ();
+ }
+
+ // fix up top-level records
+ gCallTree[gRootRecord].sib = gExceptionRecord;
+ gCallTree[gExceptionRecord].sib = gOverflowRecord;
+
+ // free pointer could be really large...
+ if (gFirstFreeCallRec > gMaxCalls)
+ gFirstFreeCallRec = gMaxCalls;
+
+ // dump out a plain text file too
+ char textName[256];
+ strcpy (textName, fileName);
+ if (::EndsWith (textName, ".mwp"))
+ textName[strlen (textName) - 4] = 0;
+ strcat (textName, ".txt");
+ EmFileRef textRef (textName);
+ ProfilePrint (textRef.GetFullPath().c_str());
+
+ // munge all the addresses to produce the string table
+ InitStringTable();
+
+ // Llamagraphics, Inc: Replaced RecursiveAddressToString() with
+ // LinearAddressToString(), since the recursive version was blowing
+ // the stack on the Macintosh.
+ LinearAddressToStrings();
+
+ // do a little cleanup now
+ Platform::DisposeMemory (gROMMap);
+
+ // create the header blocks
+ ProfFileHeader header;
+
+ header.proF = 'proF';
+ header.version = 0x00040002;
+ header.fnCount = gFirstFreeCallRec;
+ header.four = 0x00000004;
+
+ header.zeros1 = 0x00000000;
+ header.zeros2 = 0x00000000;
+ header.unknown = 0x00000000;
+
+// header.recordsSize = sizeof(ProfFileHeader) + gFirstFreeCallRec * sizeof(FnCallRecord);
+ header.recordsSize = kProfFileHeaderSize + gFirstFreeCallRec * kFnCallRecordSize; // gregs
+ header.stringTableSize = gStringTableEnd;
+ header.overhead = gClockCycles - gCyclesCounted;
+ header.rootRec = gRootRecord;
+
+ header.sixtyfour1 = 0x00000064;
+ header.sixtyfour2 = 0x00000064;
+ header.countsPerTime = PrvGetCyclesPerSecond ()/100; // times will be shown in milliseconds
+
+ header.oddstuff0 = 0x00000000;
+ header.oddstuff1 = 0x00000000;
+ header.oddstuff2 = 0x00000000;
+ header.oddstuff3 = 0x00000000;
+ header.oddstuff4 = 0x00000000;
+
+ char profName[256];
+ strcpy (profName, fileName);
+ if (!::EndsWith (profName, ".mwp"))
+ strcat (profName, ".mwp");
+
+ EmFileRef profRef (profName);
+ EmStreamFile stream (profRef, kCreateOrEraseForUpdate,
+ kFileCreatorCodeWarriorProfiler, kFileTypeProfile);
+
+// stream.PutBytes (&header, sizeof(ProfFileHeader));
+// stream.PutBytes (gCallTree, sizeof(FnCallRecord) * gFirstFreeCallRec);
+
+ // We can't just write sizeof(...) with a pointer to
+ // the structure because the structure alignment is
+ // different for different platforms / architectures, etc.
+ // The Metrowerks Profiler format is big endian.
+
+ // Write out header
+
+ stream << header.proF;
+ stream << header.version;
+ stream << header.fnCount;
+ stream << header.four;
+
+ stream << header.zeros1;
+ stream << header.zeros2;
+ stream << header.unknown;
+
+ stream << header.recordsSize;
+ stream << header.stringTableSize;
+ stream << header.overhead;
+ stream << header.rootRec;
+
+ stream << header.sixtyfour1;
+ stream << header.sixtyfour2;
+ stream << header.countsPerTime;
+
+ stream << header.oddstuff0;
+ stream << header.oddstuff1;
+ stream << header.oddstuff2;
+ stream << header.oddstuff3;
+ stream << header.oddstuff4;
+
+ while (stream.GetMarker () != kProfFileHeaderSize)
+ stream << (uint8) 0;
+
+ // Write out the function records
+
+ for (int ii = 0; ii < gFirstFreeCallRec; ++ii)
+ {
+ stream << gCallTree[ii].address;
+ stream << gCallTree[ii].entries;
+
+ stream << gCallTree[ii].cyclesSelf;
+ stream << gCallTree[ii].cyclesPlusKids;
+ stream << gCallTree[ii].cyclesMin;
+ stream << gCallTree[ii].cyclesMax;
+
+ stream << gCallTree[ii].sib;
+ stream << gCallTree[ii].kid;
+ stream << gCallTree[ii].stackUsed;
+ }
+
+ // Write out the string table.
+
+ stream.PutBytes (gStringTable, gStringTableEnd);
+
+ // cleanup
+
+ ::CleanupStringTable ();
+
+ // Llamagraphics, Inc: After dumping, the gCallTree[i].address slots are
+ // offsets into the string table rather than machine addresses. This
+ // means that the profiling information can't continue to be used, so
+ // let's dispose of it now and remove the danger of it being misinterpreted.
+
+ ::ProfileCleanup ();
+}
+
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileFnEnter
+// ---------------------------------------------------------------------------
+// ProfileFnEnter is called by the emulator when a JSR is executed, and at a
+// couple of other places. It creates a record for the function (or reuses an
+// existing record), and updates the profiler's call stack.
+//
+// ProfileFnEnter also supports a special profiling mode. If the profiler is
+// built with PROFILE_ONE_FN on, then it's assumed that whenever profiling has
+// been initialized, you always want to start profiling when a specified
+// function is entered, and stop profiling when that function is exited. That
+// way you get profiling information for a particular function no matter who
+// it's called from. In this case, ProfileFnEnter may be called before
+// ProfileStart has been called, and if it detects that the target function
+// has been entered it will start profiling at that point.
+
+void ProfileFnEnter(emuptr destAddress, emuptr returnAddress)
+{
+ if (!gProfilingOn)
+ {
+#if PROFILE_ONE_FN
+ if (address == FNTOPROFILE)
+ ProfileStart ();
+ else
+ return;
+#else
+ return;
+#endif
+ }
+
+ if (gInInstruction)
+ ProfileInstructionExit(NOADDRESS);
+
+ // If destAddress contains a trapword, save the trapword along
+ // with some other information that might be useful (like the
+ // library reference number if we're calling a library function).
+ if (IS_TRAP_16(destAddress))
+ {
+ if (IsSystemTrap (destAddress))
+ {
+ uint16 trapWord = 0xA000 | SysTrapIndex (destAddress);
+
+ if (trapWord == sysTrapIntlDispatch ||
+ trapWord == sysTrapOmDispatch ||
+ trapWord == sysTrapTsmDispatch ||
+ trapWord == sysTrapFlpDispatch ||
+ trapWord == sysTrapFlpEmDispatch ||
+ trapWord == sysTrapSerialDispatch)
+ {
+ destAddress = PACK_TRAP_INFO(destAddress, m68k_dreg (regs, 2));
+ }
+ else
+ {
+ destAddress = PACK_TRAP_INFO(destAddress, 0);
+ }
+ }
+ else
+ {
+ destAddress = PACK_TRAP_INFO(destAddress, EmMemGet16 (m68k_areg (regs, 7)));
+ }
+ }
+
+ // Check for jumping to the IntlDispatch routine dispatcher. If so, then record
+ // the address of the routine that we're going to be dispatching to, versus the
+ // dispatcher itself.
+
+ // DOLATER kwk - also do this for other dispatched traps (see above for the list)
+ // Perhaps it would make more sense to set state when we hit one of these traps,
+ // and then when this routine gets called (as a result of handling the RTE),
+ // we could be smarter and more efficient about knowing that a different address
+ // needed to be calculated.
+
+ else
+ {
+ emuptr realDestAddress = GetIntlDispatchAddress (destAddress, m68k_dreg (regs, 2));
+ if (realDestAddress != EmMemNULL)
+ {
+ destAddress = realDestAddress;
+ }
+ }
+
+ // get the caller fn
+ int caller = gCallStack[gCallStackSP].call;
+
+ // debug check, watch for overflow
+ if (gCallStackSP >= gMaxDepth-1)
+ Platform::Debugger();
+
+ // push record for callee
+ gCallStack[++gCallStackSP].returnAddress = returnAddress;
+ gCallStack[gCallStackSP].cyclesAtEntry = gClockCycles;
+ gCallStack[gCallStackSP].cyclesInKids = 0;
+ gCallStack[gCallStackSP].cyclesInInterrupts = 0;
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids = 0;
+ gCallStack[gCallStackSP].call = FindOrAddCall (gCallTree[caller].kid, destAddress);
+
+ // check if this was first kid and update parent
+ if (gCallTree[caller].kid == NORECORD && gCallStack[gCallStackSP].call != gOverflowRecord)
+ gCallTree[caller].kid = gCallStack[gCallStackSP].call;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileFnExit
+// ---------------------------------------------------------------------------
+// ProfileFnExit is called by the emulator when an RTS is executed The Palm OS
+// does some funny things such that there is not always an RTS for every JSR.
+// To handle this, ProfileFnExit has to be smart, so it keeps the return
+// address when a function is called and compares it to the destination
+// address for the RTS. Most of the time they match, and everything is fine,
+// but when they don't one of two things may be happening: either a function
+// is being called not by using JSR, but rather by pushing the callee's
+// address on the stack then executing an RTS, or a RTS has been skipped and
+// the stack has been cleaned up by the executing code (the kernel does this.)
+//
+// If the return address is not what we expected based on the profiling stack,
+// then the first thing we do is walk up the stack looking to see if the
+// address matches some higher function. If it does, the stack is popped up to
+// the function we expect, and the intervening functions are flagged as
+// improperly exited. If no match was found, we assume it's a long jump
+// disguised as an RTS, and call ProfileFnEnter instead.
+//
+// The profiler's call stack can (commonly) be popped to empty. This happens
+// when the function that was executing when ProfileStart was called exits. If
+// profiling is started from the POSER UI, this happens very often, so we do
+// the best we can: create a new fake "root" for the call tree, representing
+// the function we're returning to, and continue on. If profiling was started
+// by the PROFILE_ONE_FN trick, then a pop to empty is considered exiting the
+// target function, and profiling is turned off.
+
+void ProfileFnExit(emuptr returnAddress, emuptr oldAddress)
+{
+ if (!gProfilingOn)
+ return;
+
+ if (gInInstruction)
+ ProfileInstructionExit(NOADDRESS);
+
+ // sanity check, try to make sure the returns match the calls we think they do
+ if (gCallStack[gCallStackSP].returnAddress != NOADDRESS
+ && gCallStack[gCallStackSP].returnAddress != returnAddress)
+ {
+ int trySP = gCallStackSP;
+ while (--trySP >= 0)
+ if (returnAddress == gCallStack[trySP].returnAddress)
+ break;
+
+ if (trySP >= 0)
+ {
+ // found a match on stack, so pop up to it
+ while (gCallStackSP > trySP)
+ {
+ gExtraPopCount++; // debug, count extra pops
+ PopCallStackFn(false);
+ }
+ }
+ else if (gCallStackSP != 0)
+ // could be a longjump disguised as an RTS, so push instead
+ {
+ ProfileFnEnter(returnAddress, oldAddress);
+ gCallTree[gCallStack[gCallStackSP].call].stackUsed += 100000; // mark it as wierdly called
+ gMissedCount++; // debug, count unmatched returns
+ return;
+ }
+ }
+
+ PopCallStackFn(true);
+
+#if PROFILE_ONE_FN
+ // if we started on entering a function, stop when it exits
+ if (gCallStackSP == 0)
+ ProfileStop();
+#else
+ // or an alternate thing to do if we pop too far, re-root and continue
+ if (gCallStackSP < 0)
+ {
+ // uh oh, we must have exited the fn we started profiling in!
+ // make a new root to handle the new enclosing function
+ gRootRecord = FindOrAddCall (NORECORD, NOADDRESS);
+ if (gRootRecord == gOverflowRecord)
+ Platform::Debugger();
+ gCallTree[gRootRecord].kid = gCallStack[0].call; // old root
+ gCallStack[0].returnAddress = NOADDRESS;
+ gCallStack[0].call = gRootRecord;
+ // gCallStack[0].cyclesAtEntry = ... don't change, it's the time profiling was started
+ gCallStack[0].cyclesInKids = gClockCycles - gCallStack[0].cyclesAtEntry;
+ gCallStack[0].cyclesInInterrupts = 0;
+ gCallStack[0].cyclesInInterruptsInKids = 0;
+ gCallStackSP = 0;
+ }
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileInterruptEnter
+// ---------------------------------------------------------------------------
+// ProfileInterruptEnter does almost the same thing as ProfileFnEnter. The
+// difference is that the current call is added to the "interrupt" root rather
+// than the currently executing function, and the profile's call stack pointer
+// is pushed onto the profiler's interrupt stack.
+
+void ProfileInterruptEnter(int32 iException, emuptr returnAddress)
+{
+ if (!gProfilingOn)
+ return;
+
+ if (gInInstruction)
+ ProfileInstructionExit(NOADDRESS);
+
+ // get the caller fn
+ gCallStack[gCallStackSP].cyclesAtInterrupt = gClockCycles;
+ gInterruptCount++;
+ gInterruptStack[++gInterruptDepth] = gCallStackSP; // mark the fn that was interrupted
+
+ // debug check, watch for overflow
+ if (gCallStackSP >= gMaxDepth-1)
+ Platform::Debugger();
+
+ // push record for callee
+ gCallStack[++gCallStackSP].returnAddress = returnAddress;
+ gCallStack[gCallStackSP].cyclesAtEntry = gClockCycles;
+ gCallStack[gCallStackSP].cyclesInKids = 0;
+ gCallStack[gCallStackSP].cyclesInInterrupts = 0;
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids = 0;
+ gCallStack[gCallStackSP].call = FindOrAddCall (gCallTree[gExceptionRecord].kid, iException);
+ // check if this was first exception and update gExceptionRecord
+ if (gCallTree[gExceptionRecord].kid == NORECORD && gCallStack[gCallStackSP].call != gOverflowRecord)
+ gCallTree[gExceptionRecord].kid = gCallStack[gCallStackSP].call;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ProfileInterruptExit
+// ---------------------------------------------------------------------------
+// ProfileInterruptExit works much like ProfileFnExit, the calls stack's
+// record for the interrupt "function" is popped. Unlike with RTS, RTE is
+// reliably matched with an interrupt exit, so it's not necessary to do the
+// funny call stack searching. However, when the RTE executes it's possible
+// that there may still be some unmatched calls (JSRs) that were executed as
+// part of processing the interrupt. (The kernel does this regularly.) So we
+// make sure to pop all the functions off the profiler's call stack until we
+// get to the one indicated by the profiler's interrupt stack.
+//
+// The Palm OS trap handler performs trap calls by pushing stuff on the CPU
+// stack so that the RTE will jump to the real function (and then later be
+// able to do an RTS from that fn to get back to the code that executed the
+// TRAP interrupt.) To handle this, the RTE destination is compared to the PC
+// that was saved when the interrupt happened, and if they addresses don't
+// match then ProfileFnEnter is called to track the "fake" function entry.
+
+void ProfileInterruptExit(emuptr returnAddress)
+{
+ int32 needsFakeCall = NOADDRESS;
+
+ if (!gProfilingOn)
+ return;
+
+ if (gInInstruction)
+ ProfileInstructionExit(NOADDRESS);
+
+ if (gInterruptDepth < 0) // means we started profiling in an interrupt... oh well
+ return;
+
+ if (gCallStackSP <= gInterruptStack[gInterruptDepth])
+ Platform::Debugger();
+
+ while (gCallStackSP > gInterruptStack[gInterruptDepth]+1)
+ {
+ // mismatched jsr/rts set inside interrupt handler, deal with it
+ gExtraPopCount++; // debug, count extra pops
+ PopCallStackFn(false);
+ }
+
+ // sanity check, try to make sure the returns match the calls we think they do
+ if (gCallStack[gCallStackSP].returnAddress != returnAddress)
+ {
+ // trap handler is sneaky, and pushes stuff on the stack so that the RTE jumps
+ // to the implementation of the trap. Detect this by noticing the RTE address didn't
+ // match and generating a fake function call.
+ if (gCallTree[gCallStack[gCallStackSP].call].address == 0x2F)
+ needsFakeCall = gCallStack[gCallStackSP].returnAddress + 2; // +2 to skip trap word
+ else
+ gInterruptMismatch++;
+ }
+
+ // pop the interrupt block
+ int64 cyclesThisCall = PopCallStackFn(true);
+ EmAssert(gCallStackSP >= 0);
+
+ gInterruptDepth--;
+ gInterruptCycles += cyclesThisCall;
+
+ // store interrupt time so we can subtract it later from the cycles for the function itself
+ gCallStack[gCallStackSP].cyclesInInterrupts += cyclesThisCall;
+ gCallTree[gCallStack[gCallStackSP].call].stackUsed += 1; // count other interrupts this way
+
+ // trap interrupt
+ if (needsFakeCall != NOADDRESS)
+ ProfileFnEnter(returnAddress, needsFakeCall);
+}
+
+
+
+void ProfileDetailFn(emuptr addr, int logInstructions)
+{
+ ::FindFunctionName(addr, NULL, &gDetailStartAddr, &gDetailStopAddr, 0);
+
+ gProfilingDetailed = true;
+
+ if (logInstructions && gProfilingDetailLog == NULL)
+ {
+ gProfilingDetailLog = fopen("ProfilingDetail.txt", "w");
+ fputs("PC\topcode\tinstruction:\tclocks\treads\twrites\ttotal:\tclocks\treads\twrites\t", gProfilingDetailLog);
+ }
+}
+
+
+
+void ProfileInstructionEnter(emuptr instructionAddress)
+{
+ if (!gProfilingOn)
+ return;
+
+ if (instructionAddress < gDetailStartAddr ||
+ instructionAddress > gDetailStopAddr)
+ return;
+
+ // get the caller fn
+ int caller = gCallStack[gCallStackSP].call;
+
+ // debug check, watch for overflow
+ if (gCallStackSP >= gMaxDepth-1)
+ Platform::Debugger();
+
+ // push record for instruction
+ gCallStack[++gCallStackSP].returnAddress = instructionAddress;
+ gCallStack[gCallStackSP].cyclesAtEntry = gClockCycles;
+ gCallStack[gCallStackSP].cyclesInKids = 0;
+ gCallStack[gCallStackSP].cyclesInInterrupts = 0;
+ gCallStack[gCallStackSP].cyclesInInterruptsInKids = 0;
+ gCallStack[gCallStackSP].call = FindOrAddCall (gCallTree[caller].kid, instructionAddress);
+ gCallStack[gCallStackSP].opcode = get_iword(0);
+
+ // check if this was first kid and update parent
+ if (gCallTree[caller].kid == NORECORD && gCallStack[gCallStackSP].call != gOverflowRecord)
+ gCallTree[caller].kid = gCallStack[gCallStackSP].call;
+
+ gClockCyclesSaved = gClockCycles;
+ gReadCyclesSaved = gReadCycles;
+ gWriteCyclesSaved = gWriteCycles;
+
+ gInInstruction = true;
+}
+
+
+void ProfileInstructionExit(emuptr instructionAddress)
+{
+ if (!gProfilingOn)
+ return;
+
+ if (!gInInstruction)
+ return;
+
+ if (instructionAddress == NOADDRESS)
+ instructionAddress = gCallStack[gCallStackSP].returnAddress;
+
+ // sanity check, try to make sure the returns match the calls we think they do
+ if (gCallStack[gCallStackSP].returnAddress != instructionAddress)
+ Platform::Debugger();
+
+ if (gProfilingDetailLog != NULL)
+ {
+ char hackBuffer[512];
+ sprintf(hackBuffer,
+ "$%08lX\t$%04X\t \t%lld\t%lld\t%lld\t \t%lld\t%lld\t%lld\n",
+ instructionAddress,
+ gCallStack[gCallStackSP].opcode,
+ gClockCycles - gClockCyclesSaved,
+ gReadCycles - gReadCyclesSaved,
+ gWriteCycles - gWriteCyclesSaved,
+ gClockCycles,
+ gReadCycles,
+ gWriteCycles);
+
+ if ((gClockCyclesLast - gClockCyclesSaved) != 0)
+ fputs("\n", gProfilingDetailLog);
+
+ if (instructionAddress == gDetailStartAddr)
+ fputs("\t-->\tJSR\n", gProfilingDetailLog);
+
+ fputs(hackBuffer, gProfilingDetailLog);
+
+ if (gCallStack[gCallStackSP].opcode == kOpcode_RTS) // RTS
+ fputs("\t<--\tRTS\n", gProfilingDetailLog);
+
+ gClockCyclesLast = gClockCycles;
+ }
+
+ PopCallStackFn(true);
+
+ gInInstruction = false;
+}
+
+
+
+#pragma mark -
+
+void ProfileTest()
+{
+ ProfileInit(15,5);
+ ProfileStart();
+ ProfileIncrementClock(110 * PrvGetCyclesPerSecond ());
+
+ ProfileInterruptExit(0x55555555);
+ ProfileIncrementClock(110 * PrvGetCyclesPerSecond ());
+
+ ProfileFnEnter(0xAAAAAAAA, 0); // new
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xBBBBBBBB, 0); // new kid
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xCCCCCCCC, 0); // new kid
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xDDDDDDDD, 0); // new sib at end
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xCCCCCCCC, 0); // same kid
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xBBBBBBBB, 0); // same kid
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xCCCCCCCC, 0); // new kid
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xDDDDDDDD, 0); // new sib at end
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xCCCCCCCC, 0); // new kid
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+
+ ProfileIncrementClock(120 * PrvGetCyclesPerSecond ());
+ ProfileInterruptEnter(0x11111111, 0); // interrupt
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0x22222222, 0); // new kid
+ ProfileIncrementClock(1 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileInterruptExit(0);
+
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xCCCCCCCC, 0); // new kid in middle
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnEnter(0xAAAAAAAA, 0); // new kid at beginning
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ ProfileFnExit(0, 0);
+ ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ // ProfileFnExit(0);
+ // ProfileIncrementClock(100 * PrvGetCyclesPerSecond ());
+ // ProfileFnExit(0);
+
+ ProfileInterruptEnter(0x99999999, 0); // interrupt
+ ProfileIncrementClock(10 * PrvGetCyclesPerSecond ());
+
+ ProfileStop();
+ ProfileDump(NULL);
+ ProfileCleanup();
+}
+
+#if _DEBUG
+
+void ProfileIncrementClock(unsigned long by)
+{
+ gClockCycles += by;
+}
+
+void ProfileIncrementRead(int reads, int waitstates)
+{
+ gClockCycles += reads * (4 + waitstates);
+ gReadCycles += reads;
+}
+
+void ProfileIncrementWrite(int writes, int waitstates)
+{
+ gClockCycles += writes * (4 + waitstates);
+ gWriteCycles += writes;
+}
+
+#endif
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CreateFileNameForProfile
+ *
+ * DESCRIPTION: Creates a file reference based on the base file name
+ * passed in to the constructor. A new file reference is
+ * always created.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: nothing, but fileName is set properly as a side effect
+ *
+ ***********************************************************************/
+
+string CreateFileNameForProfile (Bool forText)
+{
+ EmFileRef result;
+ char buffer[32];
+
+ EmDirRef poserDir = EmDirRef::GetEmulatorDirectory ();
+
+ // Look for an unused file name.
+
+ UInt32 fileIndex = 0;
+
+ do
+ {
+ ++fileIndex;
+
+ if (forText)
+ sprintf (buffer, "%s_%04ld.txt", "Profile Results", fileIndex);
+ else
+ sprintf (buffer, "%s_%04ld.mwp", "Profile Results", fileIndex);
+
+ result = EmFileRef (poserDir, buffer);
+ }
+ while (result.IsSpecified () && result.Exists ());
+
+ return buffer;
+}
diff --git a/SrcShared/Profiling.h b/SrcShared/Profiling.h
new file mode 100644
index 0000000..fab4009
--- /dev/null
+++ b/SrcShared/Profiling.h
@@ -0,0 +1,333 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _PROFILING_H_
+#define _PROFILING_H_
+
+#include "sysconfig.h" // STATIC_INLINE
+
+// wait states vary with hardware
+
+// !!! Yow, this stuff is all wrong! This sets up values at *compile* time.
+// We need them to change at *run* time.
+
+#define PILOT 1
+#define PALM_PILOT 2
+#define PALM_III 3
+#define PALM_V 5 // also PALM_IIIx
+#define PALM_VII 7
+#define PALM_VII_EZ 8
+#define AUSTIN 9
+
+
+#define PALM_HARDWARE_TYPE PALM_III
+
+
+
+#if PALM_HARDWARE_TYPE == PILOT
+
+#define WAITSTATES_ROM 2
+#define WAITSTATES_SRAM 4
+#define WAITSTATES_DRAM 4
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+
+#elif PALM_HARDWARE_TYPE == PALM_PILOT
+
+#define WAITSTATES_ROM 2
+#define WAITSTATES_SRAM 4
+#define WAITSTATES_DRAM 4
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+
+#elif PALM_HARDWARE_TYPE == PALM_III
+
+#define WAITSTATES_ROM 2
+#define WAITSTATES_SRAM 4 // according to Wayne Harrington
+#define WAITSTATES_DRAM 4 // according to Wayne Harrington
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+#elif PALM_HARDWARE_TYPE == PALM_V
+
+#define WAITSTATES_ROM 1
+#define WAITSTATES_SRAM 1
+#define WAITSTATES_DRAM 1
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+
+#elif PALM_HARDWARE_TYPE == PALM_VII
+
+#define WAITSTATES_ROM 1
+#define WAITSTATES_SRAM 2 // not sure about this yet
+#define WAITSTATES_DRAM 2 // not sure about this yet
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+#elif PALM_HARDWARE_TYPE == AUSTIN
+
+#define WAITSTATES_ROM 1
+#define WAITSTATES_SRAM 1
+#define WAITSTATES_DRAM 1
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+#elif PALM_HARDWARE_TYPE == PALM_VII_EZ
+
+#define WAITSTATES_ROM 1
+#define WAITSTATES_SRAM 1
+#define WAITSTATES_DRAM 1
+#define WAITSTATES_REGISTERS 0
+#define WAITSTATES_SED1375 4
+#define WAITSTATES_PLD 0 // !!! What's this value?
+#define WAITSTATES_DUMMYBANK 99 // hopefully won't be used!
+
+#endif // PALM_HARDWARE_TYPE
+
+
+
+
+// Standard macros for incrementing our counters
+
+#define CYCLE_GETLONG(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementRead (2, waitstates)
+
+#define CYCLE_GETWORD(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementRead (1, waitstates)
+
+#define CYCLE_GETBYTE(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementRead (1, waitstates)
+
+
+#define CYCLE_PUTLONG(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementWrite (2, waitstates)
+
+#define CYCLE_PUTWORD(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementWrite (1, waitstates)
+
+#define CYCLE_PUTBYTE(waitstates) \
+ if (!(gProfilingEnabled && gProfilingCounted)) ; \
+ else ProfileIncrementWrite (1, waitstates)
+
+
+ // Declare these before including UAE.h, as UAE.h refers
+ // to them (well, gProfilingEnabled at least).
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Public (HostControl) functions
+extern Bool ProfileCanInit (void);
+extern Bool ProfileCanStart (void);
+extern Bool ProfileCanStop (void);
+extern Bool ProfileCanDump (void);
+
+extern void ProfileInit(int maxCalls, int maxDepth);
+extern void ProfileStart();
+extern void ProfileStop();
+
+// note, ProfileDump destructively modifies the profile data,
+// you must call ProfileCleanup after dumping, do not attempt
+// to gather more profiling data.
+extern void ProfileDump(const char* dumpFileName);
+
+extern void ProfilePrint(const char* textFileName);
+extern void ProfileCleanup();
+
+extern void ProfileDetailFn(emuptr addr, int logInstructions);
+
+
+// Private (Emulator Only) stuff
+
+ // Indicates that the profiling system has been initialized
+ // by calling ProfileInit. Set back to false after ProfileCleanup.
+ // If true, adds calls to ProfileIncrementClock throught the 68K
+ // emuilator. Also controls calls to ProfileFnEnter, ProfileFnExit,
+ // ProfileInterruptEnter and ProfileInterruptExit, (but that seems
+ // redundant with gProfilingOn). Finally, enables cycle counting for
+ // memory accesses (but only if gProfilingCounted is also true).
+extern int gProfilingEnabled;
+
+ // Set to false in ProfileInit and ProfileStop, set to true in ProfileStart.
+ // If false, ProfileFnEnter, ProfileFnExit, ProfileInterruptEnter and
+ // ProfileInterruptExit merely return.
+extern int gProfilingOn;
+
+ // Set to false in ProfileInit, set to true at the start of the loop in
+ // Emulator::Execute and false at the end of the loop.
+ // It controls whether or not memory access cycles are counted. It
+ // is always checked in conjunction with gProfilingEnabled; both have
+ // to be true in order for memory access cycles to be counted.
+extern int gProfilingCounted;
+
+
+ // Set to false in ProfileInit, set to true by HostControl to enable
+ // detailed profiling of a given address range (typically one function)
+extern int gProfilingDetailed;
+
+#ifdef __cplusplus
+
+class StDisableAllProfiling
+{
+ public:
+ StDisableAllProfiling () :
+ fOld (gProfilingEnabled)
+ {
+ gProfilingEnabled = false;
+ }
+
+ ~StDisableAllProfiling ()
+ {
+ gProfilingEnabled = fOld;
+ }
+
+ private:
+ int fOld;
+};
+
+class StDisableFunctionTracking
+{
+ public:
+ StDisableFunctionTracking () :
+ fOld (gProfilingOn)
+ {
+ gProfilingOn = false;
+ }
+
+ ~StDisableFunctionTracking ()
+ {
+ gProfilingOn = fOld;
+ }
+
+ private:
+ int fOld;
+};
+
+class StDisableMemoryCycleCounting
+{
+ public:
+ StDisableMemoryCycleCounting () :
+ fOld (gProfilingCounted)
+ {
+ gProfilingCounted = false;
+ }
+
+ ~StDisableMemoryCycleCounting ()
+ {
+ gProfilingCounted = fOld;
+ }
+
+ private:
+ int fOld;
+};
+
+#endif
+
+
+#define DEFAULT_RESULTS_FILENAME "Profile Results.mwp"
+#define DEFAULT_RESULTS_TEXT_FILENAME "Profile Results.txt"
+
+#define HAS_PROFILING_DEBUG 0 // turn on code to help debug profiler
+
+
+// ¥¥¥ normally passed in to ProfileInit, but here for CEmulatorApp.cpp
+#define MAXFNCALLS 0x10000
+#define MAXUNIQUEFNS 2500
+#define MAXDEPTH 200
+
+
+
+ // Total running clock cycles. Includes opcode execution
+ // time and memory fetch time.
+extern int64 gClockCycles;
+
+ // Portion of gClockCycles spent reading memory.
+extern int64 gReadCycles;
+
+ // Portion of gClockCycles spent writing memory.
+extern int64 gWriteCycles;
+
+
+#if _DEBUG
+
+void ProfileIncrementClock(unsigned long by);
+void ProfileIncrementRead(int reads, int waitstates);
+void ProfileIncrementWrite(int writes, int waitstates);
+
+#else
+
+STATIC_INLINE void ProfileIncrementClock(unsigned long by)
+{
+ gClockCycles += by;
+}
+
+STATIC_INLINE void ProfileIncrementRead(int reads, int waitstates)
+{
+ gClockCycles += reads * (4 + waitstates);
+ gReadCycles += reads;
+}
+
+STATIC_INLINE void ProfileIncrementWrite(int writes, int waitstates)
+{
+ gClockCycles += writes * (4 + waitstates);
+ gWriteCycles += writes;
+}
+#endif
+
+
+extern void ProfileFnEnter(emuptr destAddress, emuptr returnAddress);
+extern void ProfileFnExit(emuptr returnAddress, emuptr oldAddress);
+
+extern void ProfileInterruptEnter(int32 iException, emuptr returnAddress);
+extern void ProfileInterruptExit(emuptr returnAddress);
+
+extern void ProfileInstructionEnter(emuptr instructionAddress);
+extern void ProfileInstructionExit(emuptr instructionAddress);
+
+// debugging stuff
+
+extern long gReadMismatch;
+extern long gWriteMismatch;
+
+extern void ProfileTest();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _PROFILING_H_ */
+
+
diff --git a/SrcShared/ROMStubs.cpp b/SrcShared/ROMStubs.cpp
new file mode 100644
index 0000000..d7c112e
--- /dev/null
+++ b/SrcShared/ROMStubs.cpp
@@ -0,0 +1,3220 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "ROMStubs.h"
+
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmSubroutine.h" // EmSubroutine
+#include "Marshal.h" // CALLER_PUT_PARAM_VAL
+#include "Miscellaneous.h" // StMemoryMapper
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Clipboard Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * trap patches that keep the Palm Clipboard in sync with the host clipboard.
+// --------------------
+
+void ClipboardAddItem (const ClipboardFormatType format, const void* ptr, UInt16 length)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "const ClipboardFormatType format, const void* ptr, UInt16 length");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ClipboardFormatType, format);
+ CALLER_PUT_PARAM_PTR (void, ptr, length, Marshal::kInput);
+ CALLER_PUT_PARAM_VAL (UInt16, length);
+
+ // Call the function.
+ sub.Call (sysTrapClipboardAddItem);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * trap patches that keep the Palm Clipboard in sync with the host clipboard.
+// --------------------
+
+MemHandle ClipboardGetItem (const ClipboardFormatType format, UInt16* length)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "const ClipboardFormatType format, UInt16* length");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ClipboardFormatType, format);
+ CALLER_PUT_PARAM_REF (UInt16, length, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapClipboardGetItem);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (length);
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Control Manager functions
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// ¥ CtlGetLabel, used in Minimization
+// ---------------------------------------------------------------------------
+
+const Char* CtlGetLabel (const ControlType *controlP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("const Char *", "const ControlType *controlP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ControlType*, controlP);
+
+ // Call the function.
+ sub.Call (sysTrapCtlGetLabel);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (const Char*);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Desktop Link Server functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by SetHotSyncUserName when the user name needs to be set (during
+// boot-up, after a .psf file has been loaded, and after the preferences
+// have changed.
+// --------------------
+
+Err DlkDispatchRequest (DlkServerSessionPtr sessP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "DlkServerSessionType* sessP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (DlkServerSessionType, sessP, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapDlkDispatchRequest);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called
+//
+// * in Patches::PostLoad to get the user name so that it
+// can be used to establish the preference setting.
+// --------------------
+
+Err DlkGetSyncInfo (UInt32* succSyncDateP, UInt32* lastSyncDateP,
+ DlkSyncStateType* syncStateP, Char* nameBufP,
+ Char* logBufP, Int32* logLenP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "UInt32* succSyncDateP, UInt32* lastSyncDateP,"
+ "DlkSyncStateType* syncStateP, Char* nameBufP,"
+ "Char* logBufP, Int32* logLenP");
+
+ // Set the parameters.
+ Int32 logLen = logLenP ? *logLenP : 0;
+
+ CALLER_PUT_PARAM_REF (UInt32, succSyncDateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, lastSyncDateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (DlkSyncStateType, syncStateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_PTR (Char, nameBufP, dlkUserNameBufSize, Marshal::kInOut);
+ CALLER_PUT_PARAM_PTR (Char, logBufP, logLen, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Int32, logLenP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDlkGetSyncInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (succSyncDateP);
+ CALLER_GET_PARAM_REF (lastSyncDateP);
+ CALLER_GET_PARAM_REF (syncStateP);
+ CALLER_GET_PARAM_REF (logLenP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Data Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * from My_DmCreateDatabaseFromImage after a database was successfully
+// installed, or after an error occurs (different code paths). This
+// function is called any time a .prc, .pdb, or .pqa file is installed.
+//
+// * from My_ShlExportAsPilotFile (same comments)
+//
+// * from AppGetExtraInfo after opening a resource database to get its name.
+// This function is called any time a list of databases is needed (for
+// example, in the New Gremlin and Export Database dialogs).
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state.
+// --------------------
+
+Err DmCloseDatabase (DmOpenRef dbR)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "DmOpenRef dbR");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+
+ // Call the function.
+ sub.Call (sysTrapDmCloseDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called
+//
+// * from My_DmCreateDatabaseFromImage. This function is called any
+// time a .prc, .pdb, or .pqa file is installed.
+// --------------------
+
+Err DmCreateDatabase (UInt16 cardNo, const Char * const nameP,
+ UInt32 creator, UInt32 type, Boolean resDB)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 cardNo, const Char * const nameP, "
+ "UInt32 creator, UInt32 type, Boolean resDB");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_STR (Char, nameP);
+ CALLER_PUT_PARAM_VAL (UInt32, creator);
+ CALLER_PUT_PARAM_VAL (UInt32, type);
+ CALLER_PUT_PARAM_VAL (Boolean, resDB);
+
+ // Call the function.
+ sub.Call (sysTrapDmCreateDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * when exporting a database (first to generate the list of databases
+// that can be exported, then again to later determine if the
+// database is a resource database or not).
+//
+// * when we need to switch to another application. Mostly called when
+// starting a Gremlin on a particular application.
+//
+// * after an application has been launched, in order to collect information
+// on that application for later error reporting.
+// --------------------
+
+Err DmDatabaseInfo (UInt16 cardNo, LocalID dbID, Char* nameP,
+ UInt16* attributesP, UInt16* versionP, UInt32* crDateP,
+ UInt32* modDateP, UInt32* bckUpDateP,
+ UInt32* modNumP, LocalID* appInfoIDP,
+ LocalID* sortInfoIDP, UInt32* typeP,
+ UInt32* creatorP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "UInt16 cardNo, LocalID dbID, Char* nameP,"
+ "UInt16* attributesP, UInt16* versionP, UInt32* crDateP,"
+ "UInt32* modDateP, UInt32* bckUpDateP,"
+ "UInt32* modNumP, LocalID* appInfoIDP,"
+ "LocalID* sortInfoIDP, UInt32* typeP,"
+ "UInt32* creatorP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (LocalID, dbID);
+ CALLER_PUT_PARAM_PTR (Char, nameP, dmDBNameLength, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt16, attributesP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt16, versionP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, crDateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, modDateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, bckUpDateP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, modNumP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, appInfoIDP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, sortInfoIDP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, typeP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, creatorP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDmDatabaseInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (attributesP);
+ CALLER_GET_PARAM_REF (versionP);
+ CALLER_GET_PARAM_REF (crDateP);
+ CALLER_GET_PARAM_REF (modDateP);
+ CALLER_GET_PARAM_REF (bckUpDateP);
+ CALLER_GET_PARAM_REF (modNumP);
+ CALLER_GET_PARAM_REF (appInfoIDP);
+ CALLER_GET_PARAM_REF (sortInfoIDP);
+ CALLER_GET_PARAM_REF (typeP);
+ CALLER_GET_PARAM_REF (creatorP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * from LoadPalmFile to delete a previous version of a database
+// that we're trying to install.
+//
+// * from My_DmCreateDatabaseFromImage if the attempt to install a
+// database fails.
+// --------------------
+
+Err DmDeleteDatabase (UInt16 cardNo, LocalID dbID)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 cardNo, LocalID dbID");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (LocalID, dbID);
+
+ // Call the function.
+ sub.Call (sysTrapDmDeleteDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage)
+// in order to get the dbID of the database it just created.
+//
+// * by the application install code (LoadPalmFile) to determine
+// if there's a previous instance of the application that needs
+// to be deleted.
+//
+// * by the application export code (My_ShlExportAsPilotFile) to find
+// the database to be exported.
+//
+// * by code that switches to an application installed from the
+// AutoRun directory.
+// --------------------
+
+LocalID DmFindDatabase (UInt16 cardNo, const Char* nameP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("LocalID", "UInt16 cardNo, const Char* nameP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_STR (Char, nameP);
+
+ // Call the function.
+ sub.Call (sysTrapDmFindDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (LocalID);
+}
+
+// --------------------
+// Called:
+//
+// * by AppGetExtraInfo to get the 'tAIN' resource.
+//
+// * by CollectCurrentAppInfo to get the 'tAIN' and 'tver' resources.
+// --------------------
+
+MemHandle DmGet1Resource (DmResType type, DmResID id)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmResType type, DmResID id");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmResType, type);
+ CALLER_PUT_PARAM_VAL (DmResID, id);
+
+ // Call the function.
+ sub.Call (sysTrapDmGet1Resource);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by GetDatabases when iterating over all the databases in the system.
+// Called when generating a list of databases to display (e.g.,
+// in the New Gremlin and Export Database dialogs).
+// --------------------
+
+LocalID DmGetDatabase (UInt16 cardNo, UInt16 index)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("LocalID", "UInt16 cardNo, UInt16 index");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+
+ // Call the function.
+ sub.Call (sysTrapDmGetDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (LocalID);
+}
+
+// --------------------
+// Called:
+//
+// * by the application export code (My_ShlExportAsPilotFile) when failing
+// to find or open the requested database.
+//
+// * AppGetExtraInfo when failing to open an application database in
+// order to get its name.
+// --------------------
+
+Err DmGetLastErr (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapDmGetLastErr);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins (Gremlins::New) when it needs to find the application
+// responsible for a "runnable" database.
+//
+// * same comments for Patches::SwitchToApp.
+// --------------------
+
+Err DmGetNextDatabaseByTypeCreator (Boolean newSearch, DmSearchStatePtr stateInfoP,
+ UInt32 type, UInt32 creator, Boolean onlyLatestVers,
+ UInt16* cardNoP, LocalID* dbIDP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "Boolean newSearch, DmSearchStatePtr stateInfoP, "
+ "UInt32 type, UInt32 creator, Boolean onlyLatestVers, "
+ "UInt16* cardNoP, LocalID* dbIDP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (Boolean, newSearch);
+ CALLER_PUT_PARAM_REF (DmSearchStateType, stateInfoP, Marshal::kInOut);
+ CALLER_PUT_PARAM_VAL (UInt32, type);
+ CALLER_PUT_PARAM_VAL (UInt32, creator);
+ CALLER_PUT_PARAM_VAL (Boolean, onlyLatestVers);
+ CALLER_PUT_PARAM_REF (UInt16, cardNoP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, dbIDP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDmGetNextDatabaseByTypeCreator);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (stateInfoP);
+ CALLER_GET_PARAM_REF (cardNoP);
+ CALLER_GET_PARAM_REF (dbIDP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state.
+// --------------------
+
+MemHandle DmGetResource (DmResType type, DmResID id)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmResType type, DmResID id");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmResType, type);
+ CALLER_PUT_PARAM_VAL (DmResID, id);
+
+ // Call the function.
+ sub.Call (sysTrapDmGetResource);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by the application export code (My_ShlExportAsPilotFile)
+// when iterating over all the resources.
+// --------------------
+
+MemHandle DmGetResourceIndex (DmOpenRef dbP, UInt16 index)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmOpenRef dbP, UInt16 index");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+
+ // Call the function.
+ sub.Call (sysTrapDmGetResourceIndex);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage)
+// to create an app info block.
+// --------------------
+
+MemHandle DmNewHandle (DmOpenRef dbR, UInt32 size)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmOpenRef dbR, UInt32 size");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+ CALLER_PUT_PARAM_VAL (UInt32, size);
+
+ // Call the function.
+ sub.Call (sysTrapDmNewHandle);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage)
+// to create new records.
+// --------------------
+
+MemHandle DmNewRecord (DmOpenRef dbR, UInt16* atP, UInt32 size)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmOpenRef dbR, UInt16* atP, UInt32 size");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+ CALLER_PUT_PARAM_REF (UInt16, atP, Marshal::kInOut);
+ CALLER_PUT_PARAM_VAL (UInt32, size);
+
+ // Call the function.
+ sub.Call (sysTrapDmNewRecord);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (atP);
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage)
+// to create new resources.
+//
+// * while booting up (InstallCalibrationInfo) as part of the process
+// of setting the calibration info to an identity state.
+// --------------------
+
+MemHandle DmNewResource (DmOpenRef dbR, DmResType resType, DmResID resID, UInt32 size)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmOpenRef dbR, DmResType resType, DmResID resID, UInt32 size");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+ CALLER_PUT_PARAM_VAL (DmResType, resType);
+ CALLER_PUT_PARAM_VAL (DmResID, resID);
+ CALLER_PUT_PARAM_VAL (UInt32, size);
+
+ // Call the function.
+ sub.Call (sysTrapDmNewResource);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * .
+// --------------------
+
+DmOpenRef DmNextOpenDatabase (DmOpenRef currentP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("DmOpenRef", "DmOpenRef currentP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, currentP);
+
+ // Call the function.
+ sub.Call (sysTrapDmNextOpenDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (DmOpenRef);
+}
+
+// --------------------
+// Called:
+//
+// * when iterating over all databases in the system (GetDatabases).
+// Called when generating a list of databases to display (e.g.,
+// in the New Gremlin and Export Database dialogs).
+// --------------------
+
+UInt16 DmNumDatabases (UInt16 cardNo)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "UInt16 cardNo");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+
+ // Call the function.
+ sub.Call (sysTrapDmNumDatabases);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by the application export code (My_ShlExportAsPilotFile)
+// in order to loop over all the records/resources in a database.
+// --------------------
+
+UInt16 DmNumRecords (DmOpenRef dbP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "DmOpenRef dbP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+
+ // Call the function.
+ sub.Call (sysTrapDmNumRecords);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * .
+// --------------------
+UInt16 DmNumResources (DmOpenRef dbP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "DmOpenRef dbP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+
+ // Call the function.
+ sub.Call (sysTrapDmNumResources);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage)
+// so that new records/resources can be added to the new database.
+//
+// * by the application export code (My_ShlExportAsPilotFile)
+// so that records/resources can be retrieved and written out.
+//
+// * by AppGetExtraInfo to get information out of an application's
+// 'tAIN' resource.
+// --------------------
+
+DmOpenRef DmOpenDatabase (UInt16 cardNo, LocalID dbID, UInt16 mode)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("DmOpenRef", "UInt16 cardNo, LocalID dbID, UInt16 mode");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (LocalID, dbID);
+ CALLER_PUT_PARAM_VAL (UInt16, mode);
+
+ // Call the function.
+ sub.Call (sysTrapDmOpenDatabase);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (DmOpenRef);
+}
+
+// --------------------
+// Called:
+//
+// * after an application has been launched (CollectCurrentAppInfo)
+// to get the app's dbID and card number.
+// --------------------
+
+Err DmOpenDatabaseInfo (DmOpenRef dbP, LocalID* dbIDP,
+ UInt16* openCountP, UInt16* modeP, UInt16* cardNoP,
+ Boolean* resDBP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "DmOpenRef dbP, LocalID* dbIDP, "
+ "UInt16* openCountP, UInt16* modeP, UInt16* cardNoP,"
+ "Boolean* resDBP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+ CALLER_PUT_PARAM_REF (LocalID, dbIDP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt16, openCountP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt16, modeP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt16, cardNoP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Boolean, resDBP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDmOpenDatabaseInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (dbIDP);
+ CALLER_GET_PARAM_REF (openCountP);
+ CALLER_GET_PARAM_REF (modeP);
+ CALLER_GET_PARAM_REF (cardNoP);
+ CALLER_GET_PARAM_REF (resDBP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by the application export code (My_ShlExportAsPilotFile) in order
+// to get information about exported records.
+// --------------------
+
+Err DmRecordInfo (DmOpenRef dbP, UInt16 index,
+ UInt16* attrP, UInt32* uniqueIDP, LocalID* chunkIDP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "DmOpenRef dbP, UInt16 index,"
+ "UInt16* attrP, UInt32* uniqueIDP, LocalID* chunkIDP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+ CALLER_PUT_PARAM_REF (UInt16, attrP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, uniqueIDP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, chunkIDP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDmRecordInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (attrP);
+ CALLER_GET_PARAM_REF (uniqueIDP);
+ CALLER_GET_PARAM_REF (chunkIDP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by the application install code (My_DmCreateDatabaseFromImage) to release
+// records created by DmNewRecord.
+// --------------------
+
+Err DmReleaseRecord (DmOpenRef dbR, UInt16 index, Boolean dirty)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "DmOpenRef dbR, UInt16 index, Boolean dirty");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+ CALLER_PUT_PARAM_VAL (Boolean, dirty);
+
+ // Call the function.
+ sub.Call (sysTrapDmReleaseRecord);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by all code that calls DmNewResource, DmGet1Resource, DmGetResource,
+// DmGetResourceIndex, etc.
+// --------------------
+
+Err DmReleaseResource (MemHandle resourceH)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemHandle resourceH");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemHandle, resourceH);
+
+ // Call the function.
+ sub.Call (sysTrapDmReleaseResource);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by application export code (My_ShlExportAsPilotFile) to get
+// information about the resources being written out.
+// --------------------
+
+Err DmResourceInfo (DmOpenRef dbP, UInt16 index,
+ DmResType* resTypeP, DmResID* resIDP,
+ LocalID* chunkLocalIDP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "DmOpenRef dbP, UInt16 index,"
+ "DmResType* resTypeP, DmResID* resIDP,"
+ "LocalID* chunkLocalIDP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+ CALLER_PUT_PARAM_REF (DmResType, resTypeP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (DmResID, resIDP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, chunkLocalIDP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapDmResourceInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (resTypeP);
+ CALLER_GET_PARAM_REF (resIDP);
+ CALLER_GET_PARAM_REF (chunkLocalIDP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by application export code (My_ShlExportAsPilotFile) to get
+// information about the records being written out.
+// --------------------
+
+MemHandle DmQueryRecord (DmOpenRef dbP, UInt16 index)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemHandle", "DmOpenRef dbP, UInt16 index");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbP);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+
+ // Call the function.
+ sub.Call (sysTrapDmQueryRecord);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemHandle);
+}
+
+// --------------------
+// Called:
+//
+// * by application install code (My_DmCreateDatabaseFromImage) to
+// set the attributes of newly-created databases.
+// --------------------
+
+Err DmSetDatabaseInfo (UInt16 cardNo, LocalID dbID, const Char* nameP,
+ UInt16* attributesP, UInt16* versionP, UInt32* crDateP,
+ UInt32* modDateP, UInt32* bckUpDateP,
+ UInt32* modNumP, LocalID* appInfoIDP,
+ LocalID* sortInfoIDP, UInt32* typeP,
+ UInt32* creatorP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "UInt16 cardNo, LocalID dbID, const Char* nameP,"
+ "UInt16* attributesP, UInt16* versionP, UInt32* crDateP,"
+ "UInt32* modDateP, UInt32* bckUpDateP,"
+ "UInt32* modNumP, LocalID* appInfoIDP,"
+ "LocalID* sortInfoIDP, UInt32* typeP,"
+ "UInt32* creatorP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (LocalID, dbID);
+ CALLER_PUT_PARAM_STR (Char, nameP);
+ CALLER_PUT_PARAM_REF (UInt16, attributesP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt16, versionP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, crDateP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, modDateP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, bckUpDateP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, modNumP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (LocalID, appInfoIDP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (LocalID, sortInfoIDP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, typeP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, creatorP, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapDmSetDatabaseInfo);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by application install code (My_DmCreateDatabaseFromImage) to
+// set the attributes of newly-created records.
+// --------------------
+
+Err DmSetRecordInfo (DmOpenRef dbR, UInt16 index, UInt16* attrP, UInt32* uniqueIDP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "DmOpenRef dbR, UInt16 index, UInt16* attrP, UInt32* uniqueIDP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (DmOpenRef, dbR);
+ CALLER_PUT_PARAM_VAL (UInt16, index);
+ CALLER_PUT_PARAM_REF (UInt16, attrP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (UInt32, uniqueIDP, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapDmSetRecordInfo);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by application install code (My_DmCreateDatabaseFromImage) to
+// copy data into the newly-created records and resources.
+//
+// * while booting up (InstallCalibrationInfo) as part of the process
+// of setting the calibration info to an identity state.
+// --------------------
+
+Err DmWrite (MemPtr recordP, UInt32 offset, const void * const srcP, UInt32 bytes)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemPtr recordP, UInt32 offset, const void * const srcP, UInt32 bytes");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemPtr, recordP);
+ CALLER_PUT_PARAM_VAL (UInt32, offset);
+ CALLER_PUT_PARAM_PTR (void, srcP, bytes, Marshal::kInput);
+ CALLER_PUT_PARAM_VAL (UInt32, bytes);
+
+ // Call the function.
+ sub.Call (sysTrapDmWrite);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Event Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by Gremlins app switch code to insert an app stop event
+// --------------------
+
+void EvtAddEventToQueue (EventType* event)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "EventType* event");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (EventType, event, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapEvtAddEventToQueue);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins and key event insertion code (StubAppEnqueueKey) to
+// insert a key event.
+// --------------------
+
+Err EvtEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 ascii, UInt16 keycode, UInt16 modifiers");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, ascii);
+ CALLER_PUT_PARAM_VAL (UInt16, keycode);
+ CALLER_PUT_PARAM_VAL (UInt16, modifiers);
+
+ // Call the function.
+ sub.Call (sysTrapEvtEnqueueKey);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins and pen event insertion code (StubEnqueuePt) to
+// insert a pen event.
+// --------------------
+
+Err EvtEnqueuePenPoint (PointType* ptP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "PointType* ptP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (PointType, ptP, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapEvtEnqueuePenPoint);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins code (FakeEventXY) in order to target silkscreen buttons.
+// --------------------
+
+const PenBtnInfoType* EvtGetPenBtnList(UInt16* numButtons)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("const PenBtnInfoType*", "UInt16* numButtons");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (UInt16, numButtons, Marshal::kOutput);
+
+ // Call the function.
+ sub.Call (sysTrapEvtGetPenBtnList);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (numButtons);
+
+ // Return the result.
+ RETURN_RESULT_PTR (const PenBtnInfoType*);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins code (Gremlins::GetFakeEvent) to make sure the device
+// doesn't fall asleep, even though Gremlins is pumping in key events.
+// --------------------
+
+Err EvtResetAutoOffTimer (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapEvtResetAutoOffTimer);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (Gremlins::New, Gremlins::Resume, Hordes::Step) to
+// wake a device out of snooze mode or a call to EvtGetEvent with an
+// infinite timeout.
+//
+// * by pen and key event insertion code to wake a device out of snooze
+// mode or a call to EvtGetEvent with an infinite timeout.
+//
+// * by HostSignalWait if the caller is looking for an idle event.
+// --------------------
+
+Err EvtWakeup (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapEvtWakeup);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+
+#if 0
+// ---------------------------------------------------------------------------
+// ¥ Exchange Manager functions
+// ---------------------------------------------------------------------------
+
+#pragma mark -
+
+typedef enum
+{
+ exgLibTrapHandleEvent = sysLibTrapCustom,
+ exgLibTrapConnect,
+ exgLibTrapAccept,
+ exgLibTrapDisconnect,
+ exgLibTrapPut,
+ exgLibTrapGet,
+ exgLibTrapSend,
+ exgLibTrapReceive,
+ exgLibTrapControl, // <-- Needed for this
+ exgLibReserved1,
+ exgLibTrapLast
+} ExgLibTrapNumberEnum;
+
+Err ExgLibControl(UInt16 libRefNum, UInt16 op, void *valueP, UInt16 *valueLenP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 libRefNum, UInt16 op, emuptr valueP, emuptr valueLenP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, libRefNum);
+ CALLER_PUT_PARAM_VAL (UInt16, op);
+ CALLER_PUT_PARAM_VAL (emuptr, valueP);
+ CALLER_PUT_PARAM_VAL (emuptr, valueLenP);
+
+ sub.SetParamVal ("libRefNum", libRefNum);
+ sub.SetParamVal ("op", op);
+ sub.SetParamVal ("valueP", valueP);
+ sub.SetParamVal ("valueLenP", valueLenP);
+
+ sub.Call (exgLibTrapControl);
+
+ Err result;
+ sub.GetReturnVal (result);
+ return result;
+}
+#endif
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Field Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (IsFocus, SpaceLeftInFocus) to see if a field
+// is editable.
+// --------------------
+
+void FldGetAttributes (const FieldType* fld, const FieldAttrPtr attrP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "const FieldType* fld, const FieldAttrPtr attrP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FieldType*, fld);
+ CALLER_PUT_PARAM_REF (FieldAttrType, attrP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapFldGetAttributes);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (attrP);
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * by EventOutput to try to find out where the gremlin tapped inside a field.
+// --------------------
+
+UInt16 FldGetInsPtPosition (const FieldType* fld)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FieldType* fld");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FieldType*, fld);
+
+ // Call the function.
+ sub.Call (sysTrapFldGetInsPtPosition);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (SpaceLeftInFocus) to determine if more characters
+// should be jammed into a field.
+// --------------------
+
+UInt16 FldGetMaxChars (const FieldType* fld)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FieldType* fld");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FieldType*, fld);
+
+ // Call the function.
+ sub.Call (sysTrapFldGetMaxChars);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (SpaceLeftInFocus) to determine if more characters
+// should be jammed into a field.
+// --------------------
+
+UInt16 FldGetTextLength (const FieldType* fld)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FieldType* fld");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FieldType*, fld);
+
+ // Call the function.
+ sub.Call (sysTrapFldGetTextLength);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Minimization code to get the text of a field to beautify the output.
+// --------------------
+
+Char* FldGetTextPtr (FieldType* fldP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Char*", "FieldType* fldP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FieldType*, fldP);
+
+ // Call the function.
+ sub.Call (sysTrapFldGetTextPtr);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (Char*);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Font Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (FakeLocalMovement) to generate strokes based on
+// the font height.
+// --------------------
+
+Int16 FntLineHeight (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Int16", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapFntLineHeight);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Int16);
+}
+
+// --------------------
+// Called:
+//
+// --------------------
+
+UInt8 FntSetFont (UInt8 fontId)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt8", "UInt8 fontId");
+
+ // Set the parameters.
+
+ CALLER_PUT_PARAM_VAL (UInt8, fontId);
+
+ // Call the function.
+ sub.Call (sysTrapFntSetFont);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL(UInt8);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Form Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (GetFocusObject) to determine if the active form
+// is the active window.
+//
+// * by Gremlin code (FakeEventXY) to see if there's a form that should
+// be targeted.
+// --------------------
+
+FormType* FrmGetActiveForm (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("FormType*", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetActiveForm);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (FormType*);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (GetFocusObject) when trying to determine the
+// object that has the focus and that should get preferred attention.
+// --------------------
+
+UInt16 FrmGetFocus (const FormType* frm)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FormType* frm");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetFocus);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * EmEventOutput::GetEventInfo
+// --------------------
+
+UInt16 FrmGetFormId (const FormType* frm)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FormType* frm");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetFormId);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (CollectOKObjects) in order to iterate over
+// all the objects in a form.
+// --------------------
+
+UInt16 FrmGetNumberOfObjects (const FormType* frm)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FormType* frm");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetNumberOfObjects);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (FakeEventXY) to generate a random point within
+// a form object.
+//
+// * by Gremlin code (CollectOKObjects) to get the bounds of an object
+// for validation.
+// --------------------
+
+void FrmGetObjectBounds (const FormType* frm, const UInt16 pObjIndex, const RectanglePtr r)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "const FormType* frm, const UInt16 pObjIndex, const RectanglePtr r");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+ CALLER_PUT_PARAM_VAL (UInt16, pObjIndex);
+ CALLER_PUT_PARAM_REF (RectangleType, r, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetObjectBounds);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (r);
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (CollectOKObjects) to get the ID of an object
+// for use in any error messages that might occur.
+// --------------------
+
+UInt16 FrmGetObjectId (const FormType* frm, const UInt16 objIndex)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FormType* frm, const UInt16 objIndex");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+ CALLER_PUT_PARAM_VAL (UInt16, objIndex);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetObjectId);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by minimization code, when replaying the events the final time,
+// in order to grab the control names.
+// --------------------
+
+UInt16 FrmGetObjectIndex (const FormType* formP, UInt16 objID)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const FormType* formP, UInt16 objID");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, formP);
+ CALLER_PUT_PARAM_VAL (UInt16, objID);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetObjectIndex);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (GetFocusObject) to get a pointer to a table object
+// so that we can call TblGetCurrentField on it.
+//
+// * by Gremlin code (CollectOKObjects) to get a pointer to control
+// and list objects so that we can validate them.
+// --------------------
+
+MemPtr FrmGetObjectPtr (const FormType* frm, const UInt16 objIndex)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemPtr", "const FormType* frm, const UInt16 objIndex");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+ CALLER_PUT_PARAM_VAL (UInt16, objIndex);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetObjectPtr);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemPtr);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (GetFocusObject) to see if the focussed object
+// is a table that might have an embedded field.
+//
+// * by Gremlin code (CollectOKObjects) to see if the object we're
+// iterating over is one that we'd like to emulate a tap on.
+// --------------------
+
+FormObjectKind FrmGetObjectType (const FormType* frm, const UInt16 objIndex)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("FormObjectKind", "const FormType* frm, const UInt16 objIndex");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+ CALLER_PUT_PARAM_VAL (UInt16, objIndex);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetObjectType);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (FormObjectKind);
+}
+
+// --------------------
+// Called:
+//
+// * by logging code (StubEmFrmGetTitle) to get the form's title.
+// --------------------
+
+const Char* FrmGetTitle (const FormType* frm)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("const Char*", "const FormType* frm");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetTitle);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (const Char*);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (GetFocusObject, FakeEventXY) to determine if the active
+// form is the active window.
+// --------------------
+
+WinHandle FrmGetWindowHandle (const FormType* frm)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("WinHandle", "const FormType* frm");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (FormType*, frm);
+
+ // Call the function.
+ sub.Call (sysTrapFrmGetWindowHandle);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (WinHandle);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ File System functions
+// ---------------------------------------------------------------------------
+
+typedef enum {
+ FSTrapLibAPIVersion = sysLibTrapCustom,
+ FSTrapCustomControl, // <-- Needed for this
+ FSTrapFilesystemType,
+
+ FSTrapFileCreate,
+ FSTrapFileOpen,
+ FSTrapFileClose,
+ FSTrapFileRead,
+ FSTrapFileWrite,
+ FSTrapFileDelete,
+ FSTrapFileRename,
+ FSTrapFileSeek,
+ FSTrapFileEOF,
+ FSTrapFileTell,
+ FSTrapFileResize,
+ FSTrapFileAttributesGet,
+ FSTrapFileAttributesSet,
+ FSTrapFileDateGet,
+ FSTrapFileDateSet,
+ FSTrapFileSize,
+
+ FSTrapDirCreate,
+ FSTrapDirEntryEnumerate,
+
+ FSTrapVolumeFormat,
+ FSTrapVolumeMount,
+ FSTrapVolumeUnmount,
+ FSTrapVolumeInfo,
+ FSTrapVolumeLabelGet,
+ FSTrapVolumeLabelSet,
+ FSTrapVolumeSize,
+
+ FSMaxSelector = FSTrapVolumeSize,
+
+ FSBigSelector = 0x7FFF // Force FSLibSelector to be 16 bits.
+} FSLibSelector;
+
+Err FSCustomControl (UInt16 fsLibRefNum, UInt32 apiCreator, UInt16 apiSelector,
+ void *valueP, UInt16 *valueLenP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "UInt16 fsLibRefNum, UInt32 apiCreator, UInt16 apiSelector, "
+ "emuptr valueP, UInt16 *valueLenP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, fsLibRefNum);
+ CALLER_PUT_PARAM_VAL (UInt32, apiCreator);
+ CALLER_PUT_PARAM_VAL (UInt16, apiSelector);
+ CALLER_PUT_PARAM_VAL (emuptr, valueP); // !!! Only works for our mount/unmount calls!
+ CALLER_PUT_PARAM_REF (UInt16, valueLenP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (FSTrapCustomControl);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (valueLenP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Feature Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * by Gremlin code (IntlMgrExists) to see if the Intenational Manager
+// exists before trying to call it.
+//
+// * by Gremlin code (Gremlins::GetFakeEvent) to see what language system
+// we're using (so we know whether to use the English or Japanese quotes).
+//
+// * during bootup (patch on FtrInit) to get the ROM version.
+// --------------------
+
+Err FtrGet (UInt32 creator, UInt16 featureNum, UInt32* valueP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt32 creator, UInt16 featureNum, UInt32* valueP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt32, creator);
+ CALLER_PUT_PARAM_VAL (UInt16, featureNum);
+ CALLER_PUT_PARAM_REF (UInt32, valueP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapFtrGet);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (valueP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * to install the 'pose' feature after creating or loading a session.
+//
+// * by Poser's debugger handling code (Debug::EventCallback) after a
+// connection to an external debugger is established.
+//
+// * after creating a new session and we are currently connected to a debugger.
+//
+// * after reloading a .psf file and we are currently connected to a debugger.
+// --------------------
+
+Err FtrSet (UInt32 creator, UInt16 featureNum, UInt32 newValue)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt32 creator, UInt16 featureNum, UInt32 newValue");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt32, creator);
+ CALLER_PUT_PARAM_VAL (UInt16, featureNum);
+ CALLER_PUT_PARAM_VAL (UInt32, newValue);
+
+ // Call the function.
+ sub.Call (sysTrapFtrSet);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Poser's debugger handling code (Debug::EventCallback) when it
+// detects that the connection to an external debugger has been broken.
+//
+// * after reloading a .psf file and we are not currently connected to a debugger.
+// --------------------
+
+Err FtrUnregister (UInt32 creator, UInt16 featureNum)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt32 creator, UInt16 featureNum");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt32, creator);
+ CALLER_PUT_PARAM_VAL (UInt16, featureNum);
+
+ // Call the function.
+ sub.Call (sysTrapFtrUnregister);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ International Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * By dialog code, if the check is enabled.
+// --------------------
+
+Boolean IntlSetStrictChecks (Boolean iStrictChecks)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Boolean", "Boolean iStrictChecks");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (Boolean, iStrictChecks);
+
+ // Call the function.
+ sub.CallSelector (sysTrapIntlDispatch, intlIntlStrictChecks);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Boolean);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ List Manager functions
+// ---------------------------------------------------------------------------
+
+#pragma mark -
+
+// --------------------
+// Called:
+//
+// * by PrvValidateFormObjectSize in Miscellaneous.cpp to determine if
+// a zero-height list has any items.
+// --------------------
+
+Int16 LstGetNumberOfItems (const ListType* lst)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Int16", "const ListType* lst");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ListType*, lst);
+
+ // Call the function.
+ sub.Call (sysTrapLstGetNumberOfItems);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Int16);
+}
+
+// --------------------
+// Called:
+//
+// * By EventOutput code to try to find out which
+// item in a list was tapped by a gremlin.
+// --------------------
+
+Int16 LstGetSelection (const ListType* lst)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Int16", "const ListType* lst");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ListType*, lst);
+
+ // Call the function.
+ sub.Call (sysTrapLstGetSelection);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Int16);
+}
+
+// --------------------
+// Called:
+//
+// * By EventOutput code to try to find the
+// text of the item in a list that was tapped by a gremlin.
+// --------------------
+
+Char * LstGetSelectionText (const ListType *lst, Int16 itemNum)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Char *", "const ListType* lst, Int16 itemNum");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (ListType*, lst);
+ CALLER_PUT_PARAM_VAL (Int16, itemNum);
+
+ // Call the function.
+ sub.Call (sysTrapLstGetSelectionText);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (Char*);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Memory Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * in our patch to SysUIAppSwitch (called as MemPtrFree) to free up any
+// left over cmdPBP's.
+// --------------------
+
+Err MemChunkFree (MemPtr chunkDataP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemPtr chunkDataP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemPtr, chunkDataP);
+
+ // Call the function.
+ sub.Call (sysTrapMemChunkFree);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * during the application install process (My_DmCreateDatabaseFromImage)
+// in order to lock a database handle before calling DmWrite.
+//
+// * by our SysAppStartup patch (CollectCurrentAppInfo) to get information
+// from the 'tAIN' or 'tver' resources.
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state.
+// --------------------
+
+MemPtr MemHandleLock (MemHandle h)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemPtr", "MemHandle h");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemHandle, h);
+
+ // Call the function.
+ sub.Call (sysTrapMemHandleLock);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemPtr);
+}
+
+// --------------------
+// Called:
+//
+// * during the application export process (My_ShlExportAsPilotFile)
+// all over the place
+// --------------------
+
+UInt32 MemHandleSize (MemHandle h)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt32", "MemHandle h");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemHandle, h);
+
+ // Call the function.
+ sub.Call (sysTrapMemHandleSize);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt32);
+}
+
+// --------------------
+// Called:
+//
+// * during the application install process (My_DmCreateDatabaseFromImage)
+// to set the app info block field after the block's been created.
+// --------------------
+
+LocalID MemHandleToLocalID (MemHandle h)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("LocalID", "MemHandle h");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemHandle, h);
+
+ // Call the function.
+ sub.Call (sysTrapMemHandleToLocalID);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (LocalID);
+}
+
+// --------------------
+// Called:
+//
+// * during the application install process (My_DmCreateDatabaseFromImage)
+// in order to unlock a database handle after copying the data
+// into it.
+//
+// * getting information about a database (AppGetExtraInfo) from its 'tAIN'
+// resource or app info block.
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state.
+// --------------------
+
+Err MemHandleUnlock (MemHandle h)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemHandle h");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemHandle, h);
+
+ // Call the function.
+ sub.Call (sysTrapMemHandleUnlock);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * from our patch to MemInitHeapTable when walking all current
+// heaps to locate them all.
+// --------------------
+
+UInt16 MemHeapID (UInt16 cardNo, UInt16 heapIndex)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "UInt16 cardNo, UInt16 heapIndex");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (UInt16, heapIndex);
+
+ // Call the function.
+ sub.Call (sysTrapMemHeapID);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * by EmPalmHeap::GetHeapHeaderInfo (heapID) in order to get a heap
+// pointer that can be passed to EmPalmHeap::GetHeapHeaderInfo (ptr).
+// This version of GetHeapHeaderInfo is called from the version of
+// the EmPalmHeap constructor that taks a heap ID. This version of
+// the constructor is called from our patches on MemInitHeapTable
+// and MemHeapInit.
+// --------------------
+
+MemPtr MemHeapPtr (UInt16 heapID)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemPtr", "UInt16 heapID");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, heapID);
+
+ // Call the function.
+ sub.Call (sysTrapMemHeapPtr);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemPtr);
+}
+
+// --------------------
+// Called:
+//
+// * while getting an application's name (AppGetExtraInfo) from
+// the app info block -- we need to determine if the block
+// is a handle or not so that we know whether or not to lock it.
+// --------------------
+
+LocalIDKind MemLocalIDKind (LocalID local)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("LocalIDKind", "LocalID local");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (LocalID, local);
+
+ // Call the function.
+ sub.Call (sysTrapMemLocalIDKind);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (LocalIDKind);
+}
+
+// --------------------
+// Called:
+//
+// * when exporting a database (My_ShlExportAsPilotFile) to get the
+// app info and sort info handles so that we can get their sizes.
+//
+// * while getting an application's name (AppGetExtraInfo) from the
+// app info block.
+// --------------------
+
+MemPtr MemLocalIDToGlobal (LocalID local, UInt16 cardNo)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemPtr", "LocalID local, UInt16 cardNo");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (LocalID, local);
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+
+ // Call the function.
+ sub.Call (sysTrapMemLocalIDToGlobal);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemPtr);
+}
+
+// --------------------
+// Called:
+//
+// * when iterating over all databases in the system (GetDatabases).
+// Called when generating a list of databases to display (e.g.,
+// in the New Gremlin and Export Database dialogs).
+// --------------------
+
+UInt16 MemNumCards (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapMemNumCards);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up on a patch to MemInitHeapTable to determine
+// how many heaps we need to track.
+// --------------------
+
+UInt16 MemNumHeaps (UInt16 cardNo)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "UInt16 cardNo");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+
+ // Call the function.
+ sub.Call (sysTrapMemNumHeaps);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * when booting up (PrvSetCurrentDate) to set the current date
+// stored in the non-volatile data section.
+// --------------------
+
+Err MemNVParams (Boolean set, SysNVParamsPtr paramsP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "Boolean set, SysNVParamsPtr paramsP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (Boolean, set);
+ CALLER_PUT_PARAM_REF (SysNVParamsType, paramsP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapMemNVParams);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (paramsP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins (Gremlins::New) when it needs to create a cmdPBP telling
+// Clipper which PQA to launch.
+//
+// * same comments for Patches::SwitchToApp, called when a .pqa was in
+// AutoRun or AutoRunAndQuit.
+// --------------------
+
+MemPtr MemPtrNew (UInt32 size)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("MemPtr", "UInt32 size");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt32, size);
+
+ // Call the function.
+ sub.Call (sysTrapMemPtrNew);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (MemPtr);
+}
+
+// --------------------
+// Called:
+//
+// * by Gremlins (Gremlins::New) when it needs to create a cmdPBP telling
+// Clipper which PQA to launch.
+//
+// * same comments for Patches::SwitchToApp, called when a .pqa was in
+// AutoRun or AutoRunAndQuit.
+// --------------------
+
+Err MemPtrSetOwner (MemPtr p, UInt16 owner)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemPtr p, UInt16 owner");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemPtr, p);
+ CALLER_PUT_PARAM_VAL (UInt16, owner);
+
+ // Call the function.
+ sub.Call (sysTrapMemPtrSetOwner);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * while generate a list of databases and their names. Some non-application
+// databases have special resources with this information; the resource
+// size needs to be checked to see if this information is included.
+//
+// * by our SysAppStartup patch (CollectCurrentAppInfo) to get the size of the stack.
+// --------------------
+
+UInt32 MemPtrSize (MemPtr p)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt32", "MemPtr p");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemPtr, p);
+
+ // Call the function.
+ sub.Call (sysTrapMemPtrSize);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt32);
+}
+
+// --------------------
+// Called:
+//
+// * during the application export process (My_ShlExportAsPilotFile)
+// in order to unlock a database handle after copying the data
+// out of it.
+// --------------------
+
+Err MemPtrUnlock (MemPtr p)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "MemPtr p");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (MemPtr, p);
+
+ // Call the function.
+ sub.Call (sysTrapMemPtrUnlock);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Net Library functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * NetLib redirection code (Platform_NetLib::OpenConfig) to activate
+// the configuration passed into NetOpenConfig. The process mirrors
+// that which goes on in NetLib itself.
+// --------------------
+
+Err NetLibConfigMakeActive (UInt16 refNum, UInt16 configIndex)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 refNum, UInt16 configIndex");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, refNum);
+ CALLER_PUT_PARAM_VAL (UInt16, configIndex);
+
+ // Call the function.
+ sub.Call (netLibConfigMakeActive);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Pen Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * while starting a Gremlin (ResetCalibrationInfo) to reset the Pen
+// calibration information *after* the Pen manager has read the
+// preference file (that is, merely changing the preference data
+// won't work, since PenOpen has already read it).
+// --------------------
+
+Err PenCalibrate (PointType* digTopLeftP, PointType* digBotRightP,
+ PointType* scrTopLeftP, PointType* scrBotRightP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err",
+ "PointType* digTopLeftP, PointType* digBotRightP,"
+ "PointType* scrTopLeftP, PointType* scrBotRightP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (PointType, digTopLeftP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (PointType, digBotRightP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (PointType, scrTopLeftP, Marshal::kInput);
+ CALLER_PUT_PARAM_REF (PointType, scrBotRightP, Marshal::kInput);
+
+ // Call the function.
+ sub.Call (sysTrapPenCalibrate);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state.
+// --------------------
+
+Err PenRawToScreen(PointType* penP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "PointType* penP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (PointType, penP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapPenRawToScreen);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (penP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * our EvtEnqueuePenPoint wrapper.
+// --------------------
+
+Err PenScreenToRaw (PointType* penP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "PointType* penP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (PointType, penP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapPenScreenToRaw);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (penP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Peferences Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state (1.0 devices only).
+// --------------------
+
+DmOpenRef PrefOpenPreferenceDBV10 (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("DmOpenRef", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapPrefOpenPreferenceDBV10);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (DmOpenRef);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up (InstallCalibrationInfo) or starting a Gremlin
+// (ResetCalibrationInfo) as part of the process of setting the
+// calibration info to an identity state (2.0 devices and later).
+// --------------------
+
+DmOpenRef PrefOpenPreferenceDB (Boolean saved)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("DmOpenRef", "Boolean saved");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (Boolean, saved);
+
+ // Call the function.
+ sub.Call (sysTrapPrefOpenPreferenceDB);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (DmOpenRef);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up in a tailpatch to UIInitialize to turn off
+// any auto-off values.
+// --------------------
+
+void PrefSetPreference (SystemPreferencesChoice choice, UInt32 value)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "SystemPreferencesChoice choice, UInt32 value");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (SystemPreferencesChoice, choice);
+ CALLER_PUT_PARAM_VAL (UInt32, value);
+
+ // Call the function.
+ sub.Call (sysTrapPrefSetPreference);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ System Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * in a headpatch to SysUIAppSwitch to see if the application we're
+// switching to is allowed (it may not be during Gremlins).
+// --------------------
+
+Err SysCurAppDatabase (UInt16* cardNoP, LocalID* dbIDP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16* cardNoP, LocalID* dbIDP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (UInt16, cardNoP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (LocalID, dbIDP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapSysCurAppDatabase);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (cardNoP);
+ CALLER_GET_PARAM_REF (dbIDP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * in the memory access checking code (GWH_ExamineChunk) to iterate
+// the tasks. This is part of the hueristic to see if a task
+// that's being terminated is still trying to access its stack after
+// it's been deleted.
+// --------------------
+
+Err SysKernelInfo (MemPtr p)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "SysKernelInfoPtr p");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (SysKernelInfoType, p, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapSysKernelInfo);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (p);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * .
+// --------------------
+
+Err SysLibFind (const Char *nameP, UInt16 *refNumP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "const Char *nameP, UInt16 *refNumP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_STR (Char, nameP);
+ CALLER_PUT_PARAM_REF (UInt16, refNumP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapSysLibFind);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (refNumP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * .
+// --------------------
+
+Err SysLibLoad (UInt32 libType, UInt32 libCreator, UInt16 *refNumP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt32 libType, UInt32 libCreator, UInt16 *refNumP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt32, libType);
+ CALLER_PUT_PARAM_VAL (UInt32, libCreator);
+ CALLER_PUT_PARAM_REF (UInt16, refNumP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapSysLibLoad);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (refNumP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+// --------------------
+// Called:
+//
+// * .
+// --------------------
+
+SysLibTblEntryPtr SysLibTblEntry (UInt16 refNum)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("SysLibTblEntryPtr", "UInt16 refNum");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, refNum);
+
+ // Call the function.
+ sub.Call (sysTrapSysLibTblEntry);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (SysLibTblEntryPtr);
+}
+
+// --------------------
+// Called:
+//
+// * while booting up in a tailpatch to UIInitialize to turn off
+// any auto-off values.
+// --------------------
+
+UInt16 SysSetAutoOffTime (UInt16 seconds)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "UInt16 seconds");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, seconds);
+
+ // Call the function.
+ sub.Call (sysTrapSysSetAutoOffTime);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (Gremlins::New) to switch to an approved application
+// (either one on the approved list, or one that can "run" one on the
+// approved like, like a PQA).
+//
+// * By Patches::SwitchToApp to switch to a given application. This
+// function is called after booting or loading a session and the user
+// has a file in the AutoRun or AutoRunAndQuit directories.
+// --------------------
+
+Err SysUIAppSwitch (UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Err", "UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt16, cardNo);
+ CALLER_PUT_PARAM_VAL (LocalID, dbID);
+ CALLER_PUT_PARAM_VAL (UInt16, cmd);
+ CALLER_PUT_PARAM_VAL (MemPtr, cmdPBP);
+
+ // Call the function.
+ sub.Call (sysTrapSysUIAppSwitch);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Err);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Table Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * By EventOutput code
+// --------------------
+
+Coord TblGetColumnSpacing (const TableType* tableP, Int16 column)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Coord", "const TableType* tableP, Int16 column");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (TableType*, tableP);
+ CALLER_PUT_PARAM_VAL (Int16, column);
+
+ // Call the function.
+ sub.Call (sysTrapTblGetColumnSpacing);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Coord);
+}
+
+// --------------------
+// Called:
+//
+// * By EventOutput code
+// --------------------
+
+Coord TblGetColumnWidth (const TableType* tableP, Int16 column)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Coord", "const TableType* tableP, Int16 column");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (TableType*, tableP);
+ CALLER_PUT_PARAM_VAL (Int16, column);
+
+ // Call the function.
+ sub.Call (sysTrapTblGetColumnWidth);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Coord);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (GetFocusObject) to determine if there's a sub-field
+// in a table that needs to be targeted.
+// --------------------
+
+FieldPtr TblGetCurrentField (const TableType* table)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("FieldPtr", "const TableType* table");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (TableType*, table);
+
+ // Call the function.
+ sub.Call (sysTrapTblGetCurrentField);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (FieldPtr);
+}
+
+// --------------------
+// Called:
+//
+// * By EventOutput code
+// --------------------
+
+Coord TblGetRowHeight (const TableType* tableP, Int16 row)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Coord", "const TableType* tableP, Int16 row");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (TableType*, tableP);
+ CALLER_PUT_PARAM_VAL (Int16, row);
+
+ // Call the function.
+ sub.Call (sysTrapTblGetRowHeight);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (Coord);
+}
+
+// --------------------
+// Called:
+//
+// * By EventOutput code (GetPreviousEventInfo) to try to find out where
+// in the table was tapped by a gremlin.
+// --------------------
+
+Boolean TblGetSelection (const TableType* tableP, Int16* rowP, Int16* columnP)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("Boolean", "const TableType* tableP, Int16* rowP, Int16* columnP");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (TableType*, tableP);
+ CALLER_PUT_PARAM_REF (Int16, rowP, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Int16, columnP, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapTblGetSelection);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (rowP);
+ CALLER_GET_PARAM_REF (columnP);
+
+ // Return the result.
+ RETURN_RESULT_VAL (Boolean);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Text Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (GetFakeEvent) when generating the percentage
+// that any character is randomly posted to the application.
+// --------------------
+
+UInt8 TxtByteAttr(UInt8 inByte)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt8", "UInt8 inByte");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (UInt8, inByte);
+
+ // Call the function.
+ sub.CallSelector (sysTrapIntlDispatch, intlTxtByteAttr);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt8);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (GetFakeEvent) when generating the percentage
+// that any character is randomly posted to the application.
+// --------------------
+
+UInt16 TxtCharBounds (const Char* inText, UInt32 inOffset, UInt32* outStart, UInt32* outEnd)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const Char* inText, UInt32 inOffset, UInt32* outStart, UInt32* outEnd");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_PTR (Char, inText, inOffset + 4, Marshal::kInput);
+ CALLER_PUT_PARAM_VAL (UInt32, inOffset);
+ CALLER_PUT_PARAM_REF (UInt32, outStart, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (UInt32, outEnd, Marshal::kInOut);
+
+ // Call the function.
+ sub.CallSelector (sysTrapIntlDispatch, intlTxtCharBounds);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (outStart);
+ CALLER_GET_PARAM_REF (outEnd);
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (SendCharsToType) when iterating over the hardcoded
+// text to be posted to the application.
+// --------------------
+
+UInt16 TxtGetNextChar (const Char* inText, UInt32 inOffset, WChar* outChar)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("UInt16", "const Char* inText, UInt32 inOffset, WChar* outChar");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_PTR (Char, inText, inOffset + 4, Marshal::kInput);
+ CALLER_PUT_PARAM_VAL (UInt32, inOffset);
+ CALLER_PUT_PARAM_REF (WChar, outChar, Marshal::kInOut);
+
+ // Call the function.
+ sub.CallSelector (sysTrapIntlDispatch, intlTxtGetNextChar);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (outChar);
+
+ // Return the result.
+ RETURN_RESULT_VAL (UInt16);
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ Window Manager functions
+// ---------------------------------------------------------------------------
+
+// --------------------
+// Called:
+//
+// * By Gremlins code (FakeEventXY) after picking a window object to click on.
+// --------------------
+
+void WinDisplayToWindowPt (Int16* extentX, Int16* extentY)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "Int16* extentX, Int16* extentY");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (Int16, extentX, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Int16, extentY, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapWinDisplayToWindowPt);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (extentX);
+ CALLER_GET_PARAM_REF (extentY);
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (GetFocusObject) to make sure that the active window
+// is also the active form.
+//
+// * By Gremlin code (RandomWindowXY) to determine if there's a window
+// within which a pen event should be generated.
+//
+// * By Gremlin code (RandomWindowXY) to set the draw window before calling
+// WinGetWindowBounds.
+// --------------------
+
+WinHandle WinGetActiveWindow (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("WinHandle", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapWinGetActiveWindow);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (WinHandle);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlin code (FakeLocalMovement) to clip random pen dragging
+// to the window's bounds.
+//
+// * By Gremlin code (RandomScreenXY) to generate a random pen event
+// within a window's bounds.
+//
+// * By Gremlin code (FakeEventXY) to clip a random pen event within
+// an object to the window's bounds.
+//
+// * By Gremlin code (CollectOKObjects) to check to see if all objects
+// are within the window's bounds.
+// --------------------
+
+void WinGetDisplayExtent (Int16* extentX, Int16* extentY)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "Int16* extentX, Int16* extentY");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (Int16, extentX, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Int16, extentY, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapWinGetDisplayExtent);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (extentX);
+ CALLER_GET_PARAM_REF (extentY);
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * By logging code (StubEmPrintFormID) to walk the window list in
+// order to ensure that a WinHandle is valid before trying to get
+// its name/title.
+// --------------------
+
+WinHandle WinGetFirstWindow (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("WinHandle", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapWinGetFirstWindow);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (WinHandle);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlins code (RandomWindowXY) before calling WinGetWindowBounds
+// while determining a random location to tap in the window.
+//
+// !!! This is renamed to WinGetDrawWindowBounds in Bellagio.
+// --------------------
+
+void WinGetWindowBounds (RectanglePtr r)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "RectanglePtr r");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (RectangleType, r, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapWinGetDrawWindowBounds);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (r);
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// * In our tailpatch of TblHandleEvent to fix a Palm OS 3.5 bug.
+// --------------------
+
+void WinPopDrawState (void)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "void");
+
+ // Set the parameters.
+
+ // Call the function.
+ sub.Call (sysTrapWinPopDrawState);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+}
+
+// --------------------
+// Called:
+//
+// --------------------
+
+WinHandle WinSetDrawWindow (WinHandle winHandle)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("WinHandle", "WinHandle winHandle");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_VAL (WinHandle, winHandle);
+
+ // Call the function.
+ sub.Call (sysTrapWinSetDrawWindow);
+
+ // Write back any "by ref" parameters.
+
+ // Return the result.
+ RETURN_RESULT_PTR (WinHandle);
+}
+
+// --------------------
+// Called:
+//
+// * By Gremlins code (FakeEventXY) after picking a window object to click on.
+// --------------------
+
+void WinWindowToDisplayPt (Int16* extentX, Int16* extentY)
+{
+ // Prepare the stack.
+ CALLER_SETUP ("void", "Int16* extentX, Int16* extentY");
+
+ // Set the parameters.
+ CALLER_PUT_PARAM_REF (Int16, extentX, Marshal::kInOut);
+ CALLER_PUT_PARAM_REF (Int16, extentY, Marshal::kInOut);
+
+ // Call the function.
+ sub.Call (sysTrapWinWindowToDisplayPt);
+
+ // Write back any "by ref" parameters.
+ CALLER_GET_PARAM_REF (extentX);
+ CALLER_GET_PARAM_REF (extentY);
+
+ // Return the result.
+}
diff --git a/SrcShared/ROMStubs.h b/SrcShared/ROMStubs.h
new file mode 100644
index 0000000..2d8de76
--- /dev/null
+++ b/SrcShared/ROMStubs.h
@@ -0,0 +1,191 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _ROMSTUBS_H_
+#define _ROMSTUBS_H_
+
+void ClipboardAddItem (const ClipboardFormatType format, const void* ptr, UInt16 length);
+MemHandle ClipboardGetItem (const ClipboardFormatType format, UInt16* length);
+
+const Char* CtlGetLabel (const ControlType *controlP);
+
+Err DlkDispatchRequest (DlkServerSessionPtr sessP);
+Err DlkGetSyncInfo (UInt32* succSyncDateP, UInt32* lastSyncDateP,
+ DlkSyncStateType* syncStateP, Char* nameBufP,
+ Char* logBufP, Int32* logLenP);
+
+Err DmCloseDatabase (DmOpenRef dbR);
+Err DmCreateDatabase (UInt16 cardNo, const Char * const nameP,
+ UInt32 creator, UInt32 type, Boolean resDB);
+Err DmDatabaseInfo (UInt16 cardNo, LocalID dbID, Char* nameP,
+ UInt16* attributesP, UInt16* versionP, UInt32* crDateP,
+ UInt32* modDateP, UInt32* bckUpDateP,
+ UInt32* modNumP, LocalID* appInfoIDP,
+ LocalID* sortInfoIDP, UInt32* typeP,
+ UInt32* creatorP);
+Err DmDeleteDatabase (UInt16 cardNo, LocalID dbID);
+LocalID DmFindDatabase (UInt16 cardNo, const Char* nameP);
+MemHandle DmGet1Resource (DmResType type, DmResID id);
+LocalID DmGetDatabase (UInt16 cardNo, UInt16 index);
+Err DmGetLastErr (void);
+Err DmGetNextDatabaseByTypeCreator (Boolean newSearch, DmSearchStatePtr stateInfoP,
+ UInt32 type, UInt32 creator, Boolean onlyLatestVers,
+ UInt16* cardNoP, LocalID* dbIDP);
+MemHandle DmGetResource (DmResType type, DmResID id);
+MemHandle DmGetResourceIndex (DmOpenRef dbP, UInt16 index);
+MemHandle DmNewHandle (DmOpenRef dbR, UInt32 size);
+MemHandle DmNewRecord (DmOpenRef dbR, UInt16* atP, UInt32 size);
+MemHandle DmNewResource (DmOpenRef dbR, DmResType resType, DmResID resID, UInt32 size);
+DmOpenRef DmNextOpenDatabase(DmOpenRef currentP);
+UInt16 DmNumDatabases (UInt16 cardNo);
+UInt16 DmNumRecords (DmOpenRef dbP);
+UInt16 DmNumResources (DmOpenRef dbP);
+DmOpenRef DmOpenDatabase (UInt16 cardNo, LocalID dbID, UInt16 mode);
+Err DmOpenDatabaseInfo (DmOpenRef dbP, LocalID* dbIDP,
+ UInt16* openCountP, UInt16* modeP, UInt16* cardNoP,
+ Boolean* resDBP);
+Err DmRecordInfo (DmOpenRef dbP, UInt16 index,
+ UInt16* attrP, UInt32* uniqueIDP, LocalID* chunkIDP);
+Err DmReleaseRecord (DmOpenRef dbR, UInt16 index, Boolean dirty);
+Err DmReleaseResource (MemHandle resourceH);
+Err DmResourceInfo (DmOpenRef dbP, UInt16 index,
+ DmResType* resTypeP, DmResID* resIDP,
+ LocalID* chunkLocalIDP);
+MemHandle DmQueryRecord (DmOpenRef dbP, UInt16 index);
+Err DmSetDatabaseInfo (UInt16 cardNo, LocalID dbID, const Char* nameP,
+ UInt16* attributesP, UInt16* versionP, UInt32* crDateP,
+ UInt32* modDateP, UInt32* bckUpDateP,
+ UInt32* modNumP, LocalID* appInfoIDP,
+ LocalID* sortInfoIDP, UInt32* typeP,
+ UInt32* creatorP);
+Err DmSetRecordInfo (DmOpenRef dbR, UInt16 index, UInt16* attrP, UInt32* uniqueIDP);
+Err DmWrite (MemPtr recordP, UInt32 offset, const void * const srcP, UInt32 bytes);
+
+void EvtAddEventToQueue (EventType* event);
+Err EvtEnqueueKey (UInt16 ascii, UInt16 keycode, UInt16 modifiers);
+Err EvtEnqueuePenPoint (PointType* ptP);
+const PenBtnInfoType* EvtGetPenBtnList(UInt16* numButtons);
+Err EvtResetAutoOffTimer (void);
+Err EvtWakeup (void);
+
+Err ExgLibControl(UInt16 libRefNum, UInt16 op, void *valueP, UInt16 *valueLenP);
+
+void FldGetAttributes (const FieldType* fld, const FieldAttrPtr attrP);
+UInt16 FldGetInsPtPosition (const FieldType* fld);
+UInt16 FldGetMaxChars (const FieldType* fld);
+UInt16 FldGetTextLength (const FieldType* fld);
+Char* FldGetTextPtr (FieldType* fldP);
+
+Int16 FntLineHeight (void);
+UInt8 FntSetFont (UInt8 fontId);
+
+FormType* FrmGetActiveForm (void);
+UInt16 FrmGetFocus (const FormType* frm);
+UInt16 FrmGetFormId (const FormType* frm);
+UInt16 FrmGetNumberOfObjects (const FormType* frm);
+void FrmGetObjectBounds (const FormType* frm, const UInt16 pObjIndex, const RectanglePtr r);
+UInt16 FrmGetObjectId (const FormType* frm, const UInt16 objIndex);
+UInt16 FrmGetObjectIndex (const FormType* formP, UInt16 objID);
+MemPtr FrmGetObjectPtr (const FormType* frm, const UInt16 objIndex);
+FormObjectKind FrmGetObjectType (const FormType* frm, const UInt16 objIndex);
+const Char* FrmGetTitle (const FormType* frm);
+WinHandle FrmGetWindowHandle (const FormType* frm);
+
+Err FSCustomControl(UInt16 fsLibRefNum, UInt32 apiCreator, UInt16 apiSelector,
+ void *valueP, UInt16 *valueLenP);
+
+Err FtrGet (UInt32 creator, UInt16 featureNum, UInt32* valueP);
+Err FtrSet (UInt32 creator, UInt16 featureNum, UInt32 newValue);
+Err FtrUnregister (UInt32 creator, UInt16 featureNum);
+
+Boolean IntlSetStrictChecks (Boolean iStrictChecks);
+
+UInt32 KeyHandleInterrupt(Boolean periodic, UInt32 status);
+
+Int16 LstGetNumberOfItems (const ListType* lst);
+Int16 LstGetSelection (const ListType* lst);
+Char * LstGetSelectionText (const ListType *listP, Int16 itemNum);
+
+Err MemChunkFree (MemPtr chunkDataP);
+MemPtr MemHandleLock (MemHandle h);
+UInt32 MemHandleSize (MemHandle h);
+LocalID MemHandleToLocalID (MemHandle h);
+Err MemHandleUnlock (MemHandle h);
+UInt16 MemHeapID (UInt16 cardNo, UInt16 heapIndex);
+MemPtr MemHeapPtr (UInt16 heapID);
+LocalIDKind MemLocalIDKind (LocalID local);
+MemPtr MemLocalIDToGlobal (LocalID local, UInt16 cardNo);
+UInt16 MemNumCards (void);
+UInt16 MemNumHeaps (UInt16 cardNo);
+Err MemNVParams (Boolean set, SysNVParamsPtr paramsP);
+MemPtr MemPtrNew (UInt32 size);
+Err MemPtrSetOwner (MemPtr p, UInt16 owner);
+UInt32 MemPtrSize (MemPtr p);
+Err MemPtrUnlock (MemPtr p);
+
+Err NetLibConfigMakeActive (UInt16 refNum, UInt16 configIndex);
+
+Err PenCalibrate (PointType* digTopLeftP, PointType* digBotRightP,
+ PointType* scrTopLeftP, PointType* scrBotRightP);
+Err PenRawToScreen(PointType* penP);
+Err PenScreenToRaw (PointType* penP);
+
+DmOpenRef PrefOpenPreferenceDBV10 (void);
+DmOpenRef PrefOpenPreferenceDB (Boolean saved);
+void PrefSetPreference (SystemPreferencesChoice choice, UInt32 value);
+
+Err SysCurAppDatabase (UInt16* cardNoP, LocalID* dbIDP);
+Err SysKernelInfo (MemPtr p);
+Err SysLibFind (const Char *nameP, UInt16 *refNumP);
+Err SysLibLoad (UInt32 libType, UInt32 libCreator, UInt16 *refNumP);
+SysLibTblEntryPtr SysLibTblEntry (UInt16 refNum);
+UInt16 SysSetAutoOffTime (UInt16 seconds);
+Err SysUIAppSwitch (UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP);
+
+Coord TblGetColumnSpacing (const TableType* tableP, Int16 column);
+Coord TblGetColumnWidth (const TableType* tableP, Int16 column);
+FieldPtr TblGetCurrentField (const TableType* table);
+Boolean TblGetSelection (const TableType* tableP, Int16* rowP, Int16* columnP);
+Coord TblGetRowHeight (const TableType* tableP, Int16 row);
+
+UInt8 TxtByteAttr(UInt8 inByte);
+UInt16 TxtCharBounds (const Char* inText, UInt32 inOffset, UInt32* outStart, UInt32* outEnd);
+UInt16 TxtGetNextChar (const Char* inText, UInt32 inOffset, WChar* outChar);
+
+extern void WinDisplayToWindowPt (Int16* extentX, Int16* extentY);
+WinHandle WinGetActiveWindow (void);
+void WinGetDisplayExtent (Int16* extentX, Int16* extentY);
+WinHandle WinGetFirstWindow (void);
+void WinGetWindowBounds (RectanglePtr r);
+void WinPopDrawState (void);
+WinHandle WinSetDrawWindow (WinHandle winHandle);
+void WinWindowToDisplayPt (Int16* extentX, Int16* extentY);
+
+#define MemPtrFree( p) \
+ MemChunkFree(p)
+
+// convert host Int16 to network Int16
+#define NetHToNS(x) (x)
+
+// convert host long to network long
+#define NetHToNL(x) (x)
+
+// convert network Int16 to host Int16
+#define NetNToHS(x) (x)
+
+// convert network long to host long
+#define NetNToHL(x) (x)
+
+
+
+#endif /* _ROMSTUBS_H_ */
diff --git a/SrcShared/SLP.cpp b/SrcShared/SLP.cpp
new file mode 100644
index 0000000..25b3fee
--- /dev/null
+++ b/SrcShared/SLP.cpp
@@ -0,0 +1,1074 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "SLP.h"
+
+#include "Byteswapping.h" // Canonical
+#include "DebugMgr.h" // Debug::HandleNewPacket
+#include "EmErrCodes.h" // kError_NoError
+#include "EmException.h" // EmExceptionReset
+#include "EmPalmFunction.h" // GetTrapName
+#include "EmRPC.h" // RPC::HandleNewPacket, slkSocketRPC
+#include "EmSession.h" // EmSessionStopper
+#include "Logging.h" // LogAppendMsg
+#include "SocketMessaging.h" // CSocket::Write
+#include "StringData.h" // kExceptionNames, kPacketNames
+
+#define PacketName(command) (kPacketNames[command])
+
+#define PRINTF if (!this->LogFlow ()) ; else LogAppendMsg
+
+static void PrvPrintHeader (const EmAliasSlkPktHeaderType<LAS>& header);
+static void PrvPrintHeader (const EmProxySlkPktHeaderType& header);
+static void PrvPrintBody (const EmAliasSysPktBodyType<LAS>& body);
+static void PrvPrintBody (const EmProxySysPktBodyType& body);
+static void PrvPrintFooter (const EmAliasSlkPktFooterType<LAS>& footer);
+static void PrvPrintFooter (const EmProxySlkPktFooterType& footer);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::SLP
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+SLP::SLP (void) :
+ fSocket (NULL),
+ fHeader (),
+ fBody (),
+ fFooter (),
+ fHavePacket(false),
+ fSendReply (true)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::SLP
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+SLP::SLP (CSocket* s) :
+ fSocket (s),
+ fHeader (),
+ fBody (),
+ fFooter (),
+ fHavePacket (false),
+ fSendReply (true)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::SLP
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+SLP::SLP (const SLP& other) :
+ fSocket (other.fSocket),
+ fHeader (other.fHeader),
+ fBody (other.fBody),
+ fFooter (other.fFooter),
+ fHavePacket (other.fHavePacket),
+ fSendReply (other.fSendReply)
+{
+ EmAssert (fSocket);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::~SLP
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+SLP::~SLP (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::EventCallback
+ *
+ * DESCRIPTION: Standard callback for handling SLP packets. If data
+ * is received, we stop the emulator thread and call
+ * HandleDataReceived to read the dispatch the packet.
+ * Nothing is done by default on connect and disconnect
+ * events.
+ *
+ * PARAMETERS: s - the socket that connected, disconnected, or received
+ * some data.
+ *
+ * event - a code indicating what happened.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SLP::EventCallback (CSocket* s, int event)
+{
+ switch (event)
+ {
+ case CSocket::kConnected:
+ {
+ break;
+ }
+
+ case CSocket::kDataReceived:
+ {
+ ErrCode result;
+ do {
+ SLP slp (s);
+ result = slp.HandleDataReceived ();
+ } while (result == errNone && s->HasUnreadData (500));
+ break;
+ }
+
+ case CSocket::kDisconnected:
+ {
+// if (s == fSocket)
+// {
+// fSocket = NULL;
+// }
+ break;
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::HandleDataReceived
+ *
+ * DESCRIPTION: Called when received data is pending in the socket.
+ * Read that data, break it down into header, body, and
+ * footer sections, and call HandleNewPacket to dispatch
+ * it to the right sub-system.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: An error indicating what bad things happened.
+ *
+ ***********************************************************************/
+
+ErrCode SLP::HandleDataReceived (void)
+{
+ ErrCode result = errNone;
+
+// do {
+ EmAssert (fSocket);
+
+ long amtRead;
+ ErrCode err = fSocket->Read ( this->Header ().GetPtr (),
+ this->Header ().GetSize (),
+ &amtRead);
+
+ if (err == errNone && amtRead == (long) this->Header ().GetSize ())
+ {
+ fHavePacket = true;
+
+ if (this->Header ().bodySize > 0)
+ {
+ fSocket->Read ( this->Body ().GetPtr (),
+ this->Header ().bodySize,
+ NULL);
+ }
+
+ if (!fSocket->ShortPacketHack ())
+ {
+ fSocket->Read ( this->Footer ().GetPtr (),
+ this->Footer ().GetSize (),
+ NULL);
+ }
+
+ if (this->Header ().bodySize >= 2)
+ result = this->HandleNewPacket ();
+ else
+ result = errNone; // !!! Body is too small ... what to do?
+ }
+ else
+ {
+// fSocket = NULL; // Disconnected?
+ if (err == errNone)
+ {
+ result = 1;
+ }
+ }
+// } while (result == errNone && fSocket && fSocket->HasUnreadData (500));
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::HandleNewPacket
+ *
+ * DESCRIPTION: Dispatch the packet information to the right sub-system.
+ *
+ * PARAMETERS: header - contents of header part of message.
+ *
+ * body - contents of body part of message.
+ *
+ * footer - contents of footer part of message. May
+ * not be valid with all sockets.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SLP::HandleNewPacket ()
+{
+ ErrCode result = kError_NoError;
+
+ // Say that we're here. Do this after setting gLastestHeader, as the PRINTF
+ // macro looks at it.
+
+ PRINTF ("Entering SLP::HandleNewPacket.");
+
+ // Print the logging information if requested.
+
+ if (this->LogData ())
+ {
+ // PrvPrintBody calls GetTrapName -> FindTrapName -> GetFunctionAddress ->
+ // GetSysFunctionAddress -> LowMem::GetTrapAddress, which creates
+ // a CEnableFullAccess object. In order to create one of those outside
+ // the CPU thread, we must stop the CPU thread first.
+ EmSessionStopper stopper (gSession, kStopNow);
+ if (stopper.Stopped ())
+ {
+ PrvPrintHeader (this->Header ());
+ PrvPrintBody (this->Body ());
+ PrvPrintFooter (this->Footer ());
+ }
+ }
+ else if (this->LogFlow ())
+ {
+ if (PacketName (this->Body().command))
+ LogAppendMsg (" Received %s packet.", PacketName (this->Body().command));
+ else
+ LogAppendMsg (" Received unknown (0x%02X) packet.", (UInt8) this->Body().command);
+ }
+
+ // Dispatch the packet to the right sub-system.
+
+ switch (this->Header().dest)
+ {
+ case slkSocketDebugger:
+ {
+ EmSessionStopper stopper (gSession, kStopNow);
+ if (stopper.Stopped ())
+ {
+ try
+ {
+ result = Debug::HandleNewPacket (*this);
+ }
+ catch (EmExceptionReset&)
+ {
+ gSession->Reset (kResetSoft);
+ throw;
+ }
+ }
+ }
+ break;
+
+ case slkSocketConsole:
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped ())
+ {
+ try
+ {
+ result = Debug::HandleNewPacket (*this);
+ }
+ catch (EmExceptionReset&)
+ {
+ gSession->Reset (kResetSoft);
+ throw;
+ }
+ }
+ }
+ break;
+
+ case slkSocketRPC:
+ {
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+ if (stopper.Stopped ())
+ {
+ try
+ {
+ result = RPC::HandleNewPacket (*this);
+ }
+ catch (EmExceptionReset&)
+ {
+ gSession->Reset (kResetSoft);
+ throw;
+ }
+ }
+ }
+ break;
+
+ default:
+ result = slkErrWrongDestSocket;
+ PRINTF ("Unknown destination: %ld.", (long) this->Header ().dest);
+ break;
+ }
+
+ PRINTF ("Exiting SLP::HandleNewPacket.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::SendPacket
+ *
+ * DESCRIPTION: Sends the given packet to the external debugger.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SLP::SendPacket (const void* bodyP, long bodySize)
+{
+ PRINTF ("Entering SLP::SendPacket.");
+
+ if (!fSendReply)
+ {
+ PRINTF ("Not sending a reply because we were asked not to.");
+ PRINTF ("Exiting SLP::SendPacket.");
+ return errNone;
+ }
+
+ // Fold all the parts into a buffer: header, body, footer.
+
+ long totalSize = EmAliasSlkPktHeaderType<LAS>::GetSize () +
+ bodySize +
+ EmAliasSlkPktFooterType<LAS>::GetSize ();
+ StMemory buffer (totalSize);
+ char* bufferP = (char*) buffer.Get ();
+
+ EmAliasSlkPktHeaderType<LAS> header (&bufferP[0]);
+ EmAliasSysPktBodyType<LAS> body (&bufferP[header.GetSize ()]);
+ EmAliasSlkPktFooterType<LAS> footer (&bufferP[header.GetSize () + bodySize]);
+
+
+ // Gen up a header. If we're replying to a packet from an external
+ // source, use the information from it to form a reply (socket
+ // numbers and transaction ID). Otherwise, stuff in some of our
+ // own values.
+
+ if (this->HavePacket())
+ {
+ header.signature1 = slkPktHeaderSignature1;
+ header.signature2 = slkPktHeaderSignature2;
+ header.dest = this->Header().src;
+ header.src = this->Header().dest;
+ header.type = slkPktTypeSystem;
+ header.bodySize = bodySize;
+ header.transId = this->Header().transId;
+ header.checksum = 0;
+ }
+ else
+ {
+ header.signature1 = slkPktHeaderSignature1;
+ header.signature2 = slkPktHeaderSignature2;
+ header.dest = slkSocketDebugger; // !!! May want to parameterize these two.
+ header.src = slkSocketDebugger; // !!! May want to parameterize these two.
+ header.type = slkPktTypeSystem;
+ header.bodySize = bodySize;
+ header.transId = 0;
+ header.checksum = 0;
+ }
+
+ // Compute and stuff the header checksum
+
+ header.checksum = SLP::CalcHdrChecksum (0,
+ (UInt8*) header.GetPtr (),
+ header.offsetof_checksum ());
+
+ if (this->LogData ())
+ PrvPrintHeader (header);
+
+ // Copy in the packet body and byteswap it.
+
+ memcpy (body.GetPtr (), bodyP, bodySize);
+
+ if (this->LogData ())
+ {
+ PrvPrintBody (body);
+ }
+ else if (this->LogFlow ())
+ {
+ if (PacketName (body.command))
+ LogAppendMsg (" Sending %s packet.", PacketName (body.command));
+ else
+ LogAppendMsg (" Sending unknown (0x%02X) packet.", (UInt8) body.command);
+ }
+
+ // Re-introduce byteswapping bugs if necessary for clients
+ // that expect them.
+
+ EmAssert (fSocket);
+ if (fSocket->ByteswapHack ())
+ {
+ if (body.command == sysPktRPCRsp)
+ {
+ EmAliasSysPktRPCType<LAS> rpc (body.GetPtr ());
+
+ Canonical (*(uint32*) rpc.resultD0.GetPtr ());
+ Canonical (*(uint32*) rpc.resultA0.GetPtr ());
+ }
+ else if (body.command == sysPktReadRegsRsp)
+ {
+ EmAliasSysPktReadRegsRspType<LAS> regs (body.GetPtr ());
+ uint32* regsPtr = (uint32*) regs.reg.GetPtr ();
+
+ Canonical (*regsPtr++); // D0
+ Canonical (*regsPtr++); // D1
+ Canonical (*regsPtr++); // D2
+ Canonical (*regsPtr++); // D3
+ Canonical (*regsPtr++); // D4
+ Canonical (*regsPtr++); // D5
+ Canonical (*regsPtr++); // D6
+ Canonical (*regsPtr++); // D7
+ Canonical (*regsPtr++); // A0
+ Canonical (*regsPtr++); // A1
+ Canonical (*regsPtr++); // A2
+ Canonical (*regsPtr++); // A3
+ Canonical (*regsPtr++); // A4
+ Canonical (*regsPtr++); // A5
+ Canonical (*regsPtr++); // A6
+
+ Canonical (*(uint32*) regs.reg.usp.GetPtr ());
+ Canonical (*(uint32*) regs.reg.ssp.GetPtr ());
+ Canonical (*(uint32*) regs.reg.pc.GetPtr ());
+ Canonical (*(uint16*) regs.reg.sr.GetPtr ());
+ }
+ }
+
+
+ // Calculate the footer checksum
+
+ footer.crc16 = ::Crc16CalcBlock (header.GetPtr (), header.GetSize(), 0);
+ footer.crc16 = ::Crc16CalcBlock (body.GetPtr (), bodySize, footer.crc16);
+ if (this->LogData ())
+ PrvPrintFooter (footer);
+
+
+ // Send it to the external client.
+
+ if (fSocket->ShortPacketHack ())
+ {
+ totalSize -= EmAliasSlkPktFooterType<LAS>::GetSize ();
+ }
+
+ long amtWritten;
+ ErrCode result = fSocket->Write (bufferP, totalSize, &amtWritten);
+
+ PRINTF ("Exiting SLP::SendPacket.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::HavePacket
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool SLP::HavePacket (void) const
+{
+ return fHavePacket;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::GetPacketSize
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+long SLP::GetPacketSize (void) const
+{
+ EmAssert (this->HavePacket());
+
+ return EmProxySlkPktHeaderType::GetSize () +
+ this->Header ().bodySize +
+ EmProxySlkPktFooterType::GetSize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::Header
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+const EmProxySlkPktHeaderType& SLP::Header (void) const
+{
+ return fHeader;
+}
+
+EmProxySlkPktHeaderType& SLP::Header (void)
+{
+ return fHeader;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::Body
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+const EmProxySysPktBodyType& SLP::Body (void) const
+{
+ return fBody;
+}
+
+EmProxySysPktBodyType& SLP::Body (void)
+{
+ return fBody;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP:: Footer
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+const EmProxySlkPktFooterType& SLP::Footer (void) const
+{
+ return fFooter;
+}
+
+EmProxySlkPktFooterType& SLP::Footer (void)
+{
+ return fFooter;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::DeferReply
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SLP::DeferReply (Bool v)
+{
+ fSendReply = !v;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::CalcHdrChecksum
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+SlkPktHeaderChecksum SLP::CalcHdrChecksum (SlkPktHeaderChecksum start,
+ UInt8* bufP, Int32 count)
+{
+ do {
+ start += *bufP++;
+ } while (--count);
+
+ return start;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::LogFlow
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool SLP::LogFlow (void)
+{
+ UInt8 dest = slkSocketDebugger;
+ if (this->HavePacket())
+ dest = this->Header().dest;
+
+ switch (dest)
+ {
+ case slkSocketDebugger:
+ case slkSocketConsole:
+ return LogHLDebugger ();
+
+ case slkSocketRPC:
+ return LogRPC ();
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SLP::LogData
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool SLP::LogData (void)
+{
+ UInt8 dest = slkSocketDebugger;
+ if (this->HavePacket())
+ dest = this->Header().dest;
+
+ switch (dest)
+ {
+ case slkSocketDebugger:
+ case slkSocketConsole:
+ return LogHLDebuggerData ();
+
+ case slkSocketRPC:
+ return LogRPCData ();
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPrintHeader
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvPrintHeader (const EmAliasSlkPktHeaderType<LAS>& header)
+{
+ return;
+
+ LogAppendMsg (" header.signature1 = 0x%04X", (UInt16) header.signature1);
+ LogAppendMsg (" header.signature2 = 0x%02X", (UInt8) header.signature2);
+ LogAppendMsg (" header.dest = 0x%02X", (UInt8) header.dest);
+ LogAppendMsg (" header.src = 0x%02X", (UInt8) header.src);
+ LogAppendMsg (" header.type = 0x%02X", (UInt8) header.type);
+ LogAppendMsg (" header.bodySize = 0x%04X", (UInt16) header.bodySize);
+ LogAppendMsg (" header.transId = 0x%02X", (UInt8) header.transId);
+ LogAppendMsg (" header.checksum = 0x%02X", (SlkPktHeaderChecksum) header.checksum);
+}
+
+
+void PrvPrintHeader (const EmProxySlkPktHeaderType& header)
+{
+ return;
+
+ EmAliasSlkPktHeaderType<LAS> alias (header.GetPtr ());
+ PrvPrintHeader (alias);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPrintBody
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvPrintBody (const EmAliasSysPktBodyType<LAS>& body)
+{
+ static UInt16 gLastNumReadBytes;
+
+ if (PacketName (body.command))
+ {
+ LogAppendMsg (" body.command = 0x%02X / %s.",
+ (UInt8) body.command,
+ PacketName (body.command));
+ }
+ else
+ {
+ LogAppendMsg (" body.command = 0x%02X / <unknown command>.",
+ (UInt8) body.command);
+ }
+
+ switch (body.command)
+ {
+ case sysPktStateCmd:
+ break;
+ case sysPktStateRsp:
+ {
+ EmAliasSysPktStateRspType<LAS> body2 (body.GetPtr ());
+ int what = body2.exceptionId / 4;
+
+ LogAppendMsg (" body.resetted = %s", (Boolean) body2.resetted ? "true" : "false");
+ LogAppendMsg (" body.exceptionId = 0x%02X / %s", what, kExceptionNames [what]);
+
+ LogAppendMsg (" body.reg.d[0] = 0x%08X", (UInt32) body2.reg.d[0]);
+ LogAppendMsg (" body.reg.d[1] = 0x%08X", (UInt32) body2.reg.d[1]);
+ LogAppendMsg (" body.reg.d[2] = 0x%08X", (UInt32) body2.reg.d[2]);
+ LogAppendMsg (" body.reg.d[3] = 0x%08X", (UInt32) body2.reg.d[3]);
+ LogAppendMsg (" body.reg.d[4] = 0x%08X", (UInt32) body2.reg.d[4]);
+ LogAppendMsg (" body.reg.d[5] = 0x%08X", (UInt32) body2.reg.d[5]);
+ LogAppendMsg (" body.reg.d[6] = 0x%08X", (UInt32) body2.reg.d[6]);
+ LogAppendMsg (" body.reg.d[7] = 0x%08X", (UInt32) body2.reg.d[7]);
+
+ LogAppendMsg (" body.reg.a[0] = 0x%08X", (UInt32) body2.reg.a[0]);
+ LogAppendMsg (" body.reg.a[1] = 0x%08X", (UInt32) body2.reg.a[1]);
+ LogAppendMsg (" body.reg.a[2] = 0x%08X", (UInt32) body2.reg.a[2]);
+ LogAppendMsg (" body.reg.a[3] = 0x%08X", (UInt32) body2.reg.a[3]);
+ LogAppendMsg (" body.reg.a[4] = 0x%08X", (UInt32) body2.reg.a[4]);
+ LogAppendMsg (" body.reg.a[5] = 0x%08X", (UInt32) body2.reg.a[5]);
+ LogAppendMsg (" body.reg.a[6] = 0x%08X", (UInt32) body2.reg.a[6]);
+
+ LogAppendMsg (" body.reg.usp = 0x%08X", (UInt32) body2.reg.usp);
+ LogAppendMsg (" body.reg.ssp = 0x%08X", (UInt32) body2.reg.ssp);
+ LogAppendMsg (" body.reg.pc = 0x%08X", (UInt32) body2.reg.pc);
+ LogAppendMsg (" body.reg.sr = 0x%04X", (UInt16) body2.reg.sr);
+
+ LogAppendMsg (" body.bp[0].addr = 0x%08X", (emuptr) body2.bp[0].addr);
+ LogAppendMsg (" body.bp[1].addr = 0x%08X", (emuptr) body2.bp[1].addr);
+ LogAppendMsg (" body.bp[2].addr = 0x%08X", (emuptr) body2.bp[2].addr);
+ LogAppendMsg (" body.bp[3].addr = 0x%08X", (emuptr) body2.bp[3].addr);
+ LogAppendMsg (" body.bp[4].addr = 0x%08X", (emuptr) body2.bp[4].addr);
+ LogAppendMsg (" body.bp[5].addr = 0x%08X", (emuptr) body2.bp[5].addr);
+
+ LogAppendMsg (" body.startAddr = 0x%08X", (emuptr) body2.startAddr);
+ LogAppendMsg (" body.endAddr = 0x%08X", (emuptr) body2.endAddr);
+ LogAppendMsg (" body.name = %s", (char*) body2.name.GetPtr ());
+ LogAppendMsg (" body.trapTableRev = %d", (UInt8) body2.trapTableRev);
+ break;
+ }
+
+ case sysPktReadMemCmd:
+ {
+ EmAliasSysPktReadMemCmdType<LAS> body2 (body.GetPtr ());
+ LogAppendMsg (" body.address = 0x%08X", (emuptr) body2.address);
+ LogAppendMsg (" body.numBytes = 0x%04X", (UInt16) body2.numBytes);
+
+ gLastNumReadBytes = body2.numBytes;
+ break;
+ }
+ case sysPktReadMemRsp:
+ {
+ EmAliasSysPktReadMemRspType<LAS> body2 (body.GetPtr ());
+ LogAppendData (body2.data.GetPtr (), gLastNumReadBytes, " body.data = ");
+ break;
+ }
+
+ case sysPktWriteMemCmd:
+ {
+ EmAliasSysPktWriteMemCmdType<LAS> body2 (body.GetPtr ());
+ LogAppendMsg (" body.address = 0x%08X", (emuptr) body2.address);
+ LogAppendMsg (" body.numBytes = 0x%04X", (UInt16) body2.numBytes);
+ LogAppendData (body2.data.GetPtr (), body2.numBytes, " body.data = ");
+ break;
+ }
+ case sysPktWriteMemRsp:
+ break;
+
+ case sysPktSingleStepCmd:
+ break;
+// case sysPktSingleStepRsp:
+// break;
+
+ case sysPktGetRtnNameCmd:
+ {
+ EmAliasSysPktRtnNameRspType<LAS> body2 (body.GetPtr ());
+ LogAppendMsg (" body.address = 0x%08X", (emuptr) body2.address);
+ break;
+ }
+ case sysPktGetRtnNameRsp:
+ {
+ EmAliasSysPktRtnNameRspType<LAS> body2 (body.GetPtr ());
+ LogAppendMsg (" body.startAddr = 0x%08X", (emuptr) body2.startAddr);
+ LogAppendMsg (" body.endAddr = 0x%08X", (emuptr) body2.endAddr);
+ LogAppendMsg (" body.name = %s", (char*) body2.name.GetPtr ());
+ break;
+ }
+
+ case sysPktReadRegsCmd:
+ break;
+ case sysPktReadRegsRsp:
+ break;
+
+ case sysPktWriteRegsCmd:
+ break;
+ case sysPktWriteRegsRsp:
+ break;
+
+ case sysPktContinueCmd:
+ break;
+// case sysPktContinueRsp:
+// break;
+
+ case sysPktRPCCmd:
+ case sysPktRPCRsp:
+ {
+ EmAliasSysPktRPCType<LAS> body2 (body.GetPtr ());
+ LogAppendMsg (" body.trapWord = 0x%04X / %s.", (UInt16) body2.trapWord,
+ ::GetTrapName (body2.trapWord));
+ if (body.command == sysPktRPCRsp)
+ {
+ LogAppendMsg (" body.resultD0 = 0x%08X.", (UInt32) body2.resultD0);
+ LogAppendMsg (" body.resultA0 = 0x%08X.", (UInt32) body2.resultA0);
+ }
+
+ LogAppendMsg (" body.numParams = 0x%04X.", (UInt16) body2.numParams);
+
+ void* paramPtr = body2.param.GetPtr ();
+
+ for (UInt16 ii = 0; ii < body2.numParams; ++ii)
+ {
+ EmAliasSysPktRPCParamType<LAS> param (paramPtr);
+
+ if (param.byRef)
+ {
+ LogAppendData (param.asByte.GetPtr (), param.size,
+ " body.param%d = %d bytes of data.", ii, (UInt8) param.size);
+ }
+ else if (body.command == sysPktRPCCmd)
+ {
+ if (param.size == 1)
+ {
+ LogAppendMsg (" body.param%d = 0x%02X.", ii, (UInt8) param.asByte);
+ }
+ else if (param.size == 2)
+ {
+ LogAppendMsg (" body.param%d = 0x%04X.", ii, (UInt16) param.asShort);
+ }
+ else if (param.size == 4)
+ {
+ LogAppendMsg (" body.param%d = 0x%08X.", ii, (UInt32) param.asLong);
+ }
+ }
+
+ paramPtr = ((char*) param.asByte.GetPtr ()) + ((param.size + 1) & ~1);
+ }
+ break;
+ }
+
+ case sysPktGetBreakpointsCmd:
+ break;
+ case sysPktGetBreakpointsRsp:
+ break;
+
+// case sysPktSetBreakpointsCmd:
+// break;
+ case sysPktSetBreakpointsRsp:
+ break;
+
+ case sysPktRemoteUIUpdCmd:
+ break;
+// case sysPktRemoteUIUpdRsp:
+// break;
+
+ case sysPktRemoteEvtCmd:
+ break;
+// case sysPktRemoteEvtRsp:
+// break;
+
+// case sysPktDbgBreakToggleCmd:
+// break;
+ case sysPktDbgBreakToggleRsp:
+ break;
+
+ case sysPktFlashCmd:
+ break;
+ case sysPktFlashRsp:
+ break;
+
+ case sysPktCommCmd:
+ break;
+ case sysPktCommRsp:
+ break;
+
+ case sysPktGetTrapBreaksCmd:
+ break;
+ case sysPktGetTrapBreaksRsp:
+ break;
+
+ case sysPktSetTrapBreaksCmd:
+ break;
+ case sysPktSetTrapBreaksRsp:
+ break;
+
+ case sysPktGremlinsCmd:
+ break;
+// case sysPktGremlinsRsp:
+// break;
+
+ case sysPktFindCmd:
+ break;
+ case sysPktFindRsp:
+ break;
+
+ case sysPktGetTrapConditionsCmd:
+ break;
+ case sysPktGetTrapConditionsRsp:
+ break;
+
+ case sysPktSetTrapConditionsCmd:
+ break;
+ case sysPktSetTrapConditionsRsp:
+ break;
+
+ case sysPktChecksumCmd:
+ break;
+ case sysPktChecksumRsp:
+ break;
+
+ case sysPktExecFlashCmd:
+ break;
+ case sysPktExecFlashRsp:
+ break;
+
+ case sysPktRemoteMsgCmd:
+ break;
+// case sysPktRemoteMsgRsp:
+// break;
+
+ default:
+ break;
+ }
+}
+
+
+void PrvPrintBody (const EmProxySysPktBodyType& body)
+{
+ EmAliasSysPktBodyType<LAS> alias (body.GetPtr ());
+ PrvPrintBody (alias);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvPrintFooter
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvPrintFooter (const EmAliasSlkPktFooterType<LAS>& footer)
+{
+ return;
+
+ LogAppendMsg (" footer.crc16 = 0x%02X", (UInt16) footer.crc16);
+}
+
+void PrvPrintFooter (const EmProxySlkPktFooterType& footer)
+{
+ return;
+
+ EmAliasSlkPktFooterType<LAS> alias (footer.GetPtr ());
+ PrvPrintFooter (alias);
+}
diff --git a/SrcShared/SLP.h b/SrcShared/SLP.h
new file mode 100644
index 0000000..4546364
--- /dev/null
+++ b/SrcShared/SLP.h
@@ -0,0 +1,74 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef SLP_H_
+#define SLP_H_
+
+#include "EmPalmStructs.h" // SlkPktHeaderType, SysPktBodyType, LAS
+#include "EmTypes.h" // ErrCode
+
+class CSocket;
+
+class SLP
+{
+ public:
+ SLP (void);
+ SLP (CSocket*);
+ SLP (const SLP&);
+ ~SLP (void);
+
+ static void EventCallback (CSocket* s, int event);
+ ErrCode HandleDataReceived (void);
+
+ ErrCode HandleNewPacket (void);
+ ErrCode SendPacket (const void* body, long size);
+
+ Bool HavePacket (void) const;
+ long GetPacketSize (void) const;
+
+ const EmProxySlkPktHeaderType& Header (void) const;
+ const EmProxySysPktBodyType& Body (void) const;
+ const EmProxySlkPktFooterType& Footer (void) const;
+
+ EmProxySlkPktHeaderType& Header (void);
+ EmProxySysPktBodyType& Body (void);
+ EmProxySlkPktFooterType& Footer (void);
+
+ void DeferReply (Bool);
+
+ Bool HasSocket (CSocket* s) { return s == fSocket; }
+
+ private:
+ void SetHeader (void);
+ void SetBody (void);
+ void SetFooter (void);
+
+ SlkPktHeaderChecksum CalcHdrChecksum (SlkPktHeaderChecksum start,
+ UInt8* bufP, Int32 count);
+
+ Bool LogData (void);
+ Bool LogFlow (void);
+
+ private:
+ CSocket* fSocket;
+
+ EmProxySlkPktHeaderType fHeader;
+ EmProxySysPktBodyType fBody;
+ EmProxySlkPktFooterType fFooter;
+
+ Bool fHavePacket;
+ Bool fSendReply;
+};
+
+
+#endif // SPL_H_
diff --git a/SrcShared/SessionFile.cpp b/SrcShared/SessionFile.cpp
new file mode 100644
index 0000000..a5e2f72
--- /dev/null
+++ b/SrcShared/SessionFile.cpp
@@ -0,0 +1,1142 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "SessionFile.h"
+
+#include "Byteswapping.h" // Canonical
+#include "EmErrCodes.h" // kError_InvalidDevice
+#include "EmPalmStructs.h" // EmProxySED1376RegsType
+#include "EmStreamFile.h" // EmStreamFile
+#include "ErrorHandling.h" // Errors::Throw
+#include "Miscellaneous.h" // StMemory, RunLengthEncode, GzipEncode, etc.
+#include "UAE.h" // regstruct
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile constructor
+ *
+ * DESCRIPTION: Initialize the SessionFile object. Sets the fFile data
+ * member to refer to the given ChunkFile (which must
+ * exist for the life of the SessionFile).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+SessionFile::SessionFile (ChunkFile& f) :
+ fFile (f),
+ fCanReload (false),
+ fCfg (),
+ fReadBugFixes (false),
+ fChangedBugFixes (false),
+ fBugFixes (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile destructor
+ *
+ * DESCRIPTION: Releases SessionFile resources. Currently does nothing.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+SessionFile::~SessionFile (void)
+{
+ if (fChangedBugFixes)
+ {
+ this->WriteBugFixes (fBugFixes);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadROMFileReference
+ *
+ * DESCRIPTION: Read a reference to a paired ROM file from the session
+ * file. For robustness, several approaches are used to
+ * find a ROM file. Because these approaches are platform-
+ * specific, most of the work is off-loaded to the Platform
+ * sub-system. If the file reference can be read, it's
+ * recorded in the configuration record to be used the next
+ * time a new session is created.
+ *
+ * PARAMETERS: f - reference to EmFileRef to receive the read value.
+ *
+ * RETURNED: True if a value could be found, false otherwise.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadROMFileReference (EmFileRef& f)
+{
+ // Look for a ROM reference using a platform-specific method.
+
+ if (Platform::ReadROMFileReference (fFile, f))
+ return true;
+
+ // If a path can't be found, look for a simple ROM name.
+
+ string name;
+ if (fFile.ReadString (SessionFile::kROMNameTag, name))
+ {
+ // First, look in the same directory as the session file.
+
+ try
+ {
+ // Get the stream this ChunkFile is using and see if it's
+ // a file-based stream.
+
+ EmStream& stream = fFile.GetStream ();
+ EmStreamFile& fileStream = dynamic_cast<EmStreamFile&> (stream);
+
+ // If so, get the directory this file is in.
+
+ EmFileRef sessionRef = fileStream.GetFileRef ();
+ EmDirRef sessionParent = sessionRef.GetParent ();
+
+ f = EmFileRef (sessionParent, name);
+
+ if (f.Exists ())
+ return true;
+ }
+ catch (...) // Exception thrown if dynamic_cast fails.
+ {
+ }
+
+ // If not there, look in the same directory as Poser itself.
+
+ EmDirRef emulatorDir = EmDirRef::GetEmulatorDirectory ();
+
+ // Return this reference, even if the file doesn't exist.
+ // That way, we can at least form error messages.
+
+ f = EmFileRef (emulatorDir, name);
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadRAMImage
+ *
+ * DESCRIPTION: Read the RAM image from the session file. Attempts to
+ * read a number of versions of the image, including
+ * compressed and uncompressed versions. If the image can
+ * be read, its size is recorded in the configuration
+ * record to be used the next time a new session is created.
+ *
+ * PARAMETERS: image - reference to the pointer to receive the address
+ * of the RAM image.
+ *
+ * size - reference to the integer to receive the size of
+ * the RAM image.
+ *
+ * RETURNED: True if the image was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadRAMImage (void* image)
+{
+ Bool result = this->ReadChunk (kRAMDataTag, image, kGzipCompression);
+
+ if (!result)
+ result = this->ReadChunk (kRLERAMDataTag, image, kRLECompression);
+
+ if (!result)
+ result = this->ReadChunk (kUncompRAMDataTag, image, kNoCompression);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadMetaRAMImage
+ *
+ * DESCRIPTION: Read the MetaRAM image from the session file. Attempts
+ * to read a number of versions of the image, including
+ * compressed and uncompressed versions.
+ *
+ * PARAMETERS: image - reference to the pointer to receive the address
+ * of the MetaRAM image.
+ *
+ * size - reference to the integer to receive the size of
+ * the MetaRAM image.
+ *
+ * RETURNED: True if the image was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadMetaRAMImage (void* image)
+{
+ Bool result = this->ReadChunk (kMetaRAMDataTag, image, kGzipCompression);
+
+ if (!result)
+ result = this->ReadChunk (kRLEMetaRAMDataTag, image, kRLECompression);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadMetaROMImage
+ *
+ * DESCRIPTION: Read the MetaROM image from the session file. Attempts
+ * to read a number of versions of the image, including
+ * compressed and uncompressed versions.
+ *
+ * PARAMETERS: image - reference to the pointer to receive the address
+ * of the MetaROM image.
+ *
+ * size - reference to the integer to receive the size of
+ * the MetaROM image.
+ *
+ * RETURNED: True if the image was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadMetaROMImage (void* image)
+{
+ Bool result = this->ReadChunk (kMetaROMDataTag, image, kGzipCompression);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadHwrDBallType
+ *
+ * DESCRIPTION: Read the Dragonball hardware registers from the
+ * session file.
+ *
+ * PARAMETERS: hwRegs - reference to the struct to receive the register
+ * data.
+ *
+ * RETURNED: True if the data was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadHwrDBallType (HwrM68328Type& hwRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kDBRegs, chunk))
+ {
+ memcpy (&hwRegs, chunk.GetPointer (), sizeof (hwRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadHwrDBallEZType
+ *
+ * DESCRIPTION: Read the DragonballEZ hardware registers from the
+ * session file.
+ *
+ * PARAMETERS: hwRegs - reference to the struct to receive the register
+ * data.
+ *
+ * RETURNED: True if the data was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadHwrDBallEZType (HwrM68EZ328Type& hwRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kDBEZRegs, chunk))
+ {
+ memcpy (&hwRegs, chunk.GetPointer (), sizeof (hwRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadHwrDBallVZType
+ *
+ * DESCRIPTION: Read the DragonballVZ hardware registers from the
+ * session file.
+ *
+ * PARAMETERS: hwRegs - reference to the struct to receive the register
+ * data.
+ *
+ * RETURNED: True if the data was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadHwrDBallVZType (HwrM68VZ328Type& hwRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kDBVZRegs, chunk))
+ {
+ memcpy (&hwRegs, chunk.GetPointer (), sizeof (hwRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadHwrDBallSZType
+ *
+ * DESCRIPTION: Read the DragonballSZ hardware registers from the
+ * session file.
+ *
+ * PARAMETERS: hwRegs - reference to the struct to receive the register
+ * data.
+ *
+ * RETURNED: True if the data was found and could be read in.
+ *
+ ***********************************************************************/
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadDBallRegs
+ *
+ * DESCRIPTION: Read the Dragonball CPU registers structure from the
+ * session file.
+ *
+ * PARAMETERS: cpuRegs - reference to the struct to receive the register
+ * data.
+ *
+ * RETURNED: True if the data was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadDBallRegs (regstruct& cpuRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kCPURegs, chunk))
+ {
+ memcpy (&cpuRegs, chunk.GetPointer (), sizeof (cpuRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadDeviceType
+ *
+ * DESCRIPTION: Read the id of the device to emulate. If the id can be
+ * read, it's recorded in the configuration record to be
+ * used the next time a new session is created.
+ *
+ * PARAMETERS: v - reference to the EmDevice to receive the read value.
+ *
+ * RETURNED: True if the value was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadDevice (EmDevice& v)
+{
+ v = EmDevice ();
+
+ // Look up the device by the string.
+
+ string deviceTypeString;
+
+ if (fFile.ReadString (kDeviceTypeString, deviceTypeString))
+ {
+ v = EmDevice (deviceTypeString);
+ }
+
+ return v.Supported ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadBugFixes
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: v - reference to the BugFixes to receive the read value.
+ *
+ * RETURNED: True if the value was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadBugFixes (BugFixes& v)
+{
+ uint32 bits;
+ Bool result = fFile.ReadInt (kBugsTag, bits);
+
+ if (result)
+ {
+ v = (BugFixes) bits;
+ }
+
+ return result;
+}
+
+
+Bool SessionFile::ReadSED1375RegsType (SED1375RegsType& sedRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kSED1375Regs, chunk))
+ {
+ memcpy (&sedRegs, chunk.GetPointer (), sizeof (sedRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+Bool SessionFile::ReadSED1375Image (void* image)
+{
+ Bool result = this->ReadChunk (kSED1375Image, image, kGzipCompression);
+
+ return result;
+}
+
+
+Bool SessionFile::ReadSED1375Palette (uint16 palette[256])
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kSED1375Palette, chunk))
+ {
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ memcpy (palette, chunk.GetPointer (), size);
+ return true;
+ }
+
+ return false;
+}
+
+
+Bool SessionFile::ReadSED1376RegsType (SED1376RegsType& sedRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kSED1376Regs, chunk))
+ {
+ memcpy (&sedRegs, chunk.GetPointer (), EmProxySED1376RegsType::GetSize ());
+ return true;
+ }
+
+ return false;
+}
+
+
+Bool SessionFile::ReadSED1376Palette (RGBType palette[256])
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kSED1376Palette, chunk))
+ {
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ memcpy (palette, chunk.GetPointer (), size);
+ return true;
+ }
+
+ return false;
+}
+
+
+// SessionFile::ReadMediaQRegsType is defined in SessionFile.h
+
+
+Bool SessionFile::ReadMediaQImage (void* image)
+{
+ Bool result = this->ReadChunk (kMediaQImage, image, kGzipCompression);
+
+ return result;
+}
+
+
+Bool SessionFile::ReadMediaQPalette (RGBType palette[256])
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kMediaQPalette, chunk))
+ {
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ memcpy (palette, chunk.GetPointer (), size);
+ return true;
+ }
+
+ return false;
+}
+
+
+Bool SessionFile::ReadPLDRegsType (HwrJerryPLDType& pldRegs)
+{
+ Chunk chunk;
+ if (fFile.ReadChunk (kPLDRegs, chunk))
+ {
+ memcpy (&pldRegs, chunk.GetPointer (), sizeof (pldRegs));
+ return true;
+ }
+
+ return false;
+}
+
+
+Bool SessionFile::ReadConfiguration (Configuration& cfg)
+{
+ if (!this->ReadDevice (cfg.fDevice))
+ return false;
+
+ if (!this->ReadROMFileReference (cfg.fROMFile))
+ return false;
+
+ cfg.fRAMSize = this->GetRAMImageSize ();
+ if (cfg.fRAMSize == ChunkFile::kChunkNotFound)
+ return false;
+
+ cfg.fRAMSize /= 1024;
+
+ return true;
+}
+
+
+long SessionFile::GetRAMImageSize (void)
+{
+ long numBytes;
+
+ Chunk chunk;
+ if (fFile.ReadChunk (kRAMDataTag, chunk) || fFile.ReadChunk (kRLERAMDataTag, chunk))
+ {
+ EmStreamChunk s (chunk);
+ s >> numBytes;
+ }
+ else
+ {
+ numBytes = fFile.FindChunk (kUncompRAMDataTag);
+ }
+
+ return numBytes;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteROMFileReference
+ *
+ * DESCRIPTION: Write a reference to the ROM file to use for this
+ * session. For robustness, the reference is written out
+ * in several different ways. Because the way the file is
+ * later looked up is platform-dependent, most of the work
+ * is off-loaded to the Platform sub-system.
+ *
+ * PARAMETERS: f - reference to the EmFileRef for the ROM file.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteROMFileReference (const EmFileRef& f)
+{
+ // Save a ROM reference using a platform-specific method.
+
+ Platform::WriteROMFileReference (fFile, f);
+
+ // Save the name of the ROM file.
+
+ string romFileName = f.GetName ();
+ fFile.WriteString (SessionFile::kROMNameTag, romFileName);
+
+ // Remember that we were using this ROM file most recently.
+
+ fCfg.fROMFile = f;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteRAMImage
+ *
+ * DESCRIPTION: Write the given data as the RAM image for the session
+ * file. The data is written using the default compression.
+ *
+ * PARAMETERS: image - pointer to the data to be written. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * size - number of bytes in the image.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteRAMImage (const void* image, uint32 size)
+{
+ this->WriteChunk (kRAMDataTag, size, image, kGzipCompression);
+ fCfg.fRAMSize = size / 1024;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteMetaRAMImage
+ *
+ * DESCRIPTION: Write the given data as the MetaRAM image for the session
+ * file. The data is written using the default compression.
+ *
+ * PARAMETERS: image - pointer to the data to be written. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * size - number of bytes in the image.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteMetaRAMImage (const void* image, uint32 size)
+{
+ this->WriteChunk (kMetaRAMDataTag, size, image, kGzipCompression);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteMetaROMImage
+ *
+ * DESCRIPTION: Write the given data as the MetaROM image for the session
+ * file. The data is written using the default compression.
+ *
+ * PARAMETERS: image - pointer to the data to be written. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * size - number of bytes in the image.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteMetaROMImage (const void* image, uint32 size)
+{
+ this->WriteChunk (kMetaROMDataTag, size, image, kGzipCompression);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteHwrDBallType
+ *
+ * DESCRIPTION: Write the Dragonball hardware registers to the session
+ * file.
+ *
+ * PARAMETERS: hwRegs - the DB registers to write to disk. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteHwrDBallType (const HwrM68328Type& hwRegs)
+{
+ fFile.WriteChunk (kDBRegs, sizeof (hwRegs), &hwRegs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteHwrDBallEZType
+ *
+ * DESCRIPTION: Write the Dragonball EZ hardware registers to the session
+ * file.
+ *
+ * PARAMETERS: hwRegs - the DB registers to write to disk. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteHwrDBallEZType (const HwrM68EZ328Type& hwRegs)
+{
+ fFile.WriteChunk (kDBEZRegs, sizeof (hwRegs), &hwRegs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteHwrDBallVZType
+ *
+ * DESCRIPTION: Write the Dragonball VZ hardware registers to the session
+ * file.
+ *
+ * PARAMETERS: hwRegs - the DB registers to write to disk. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteHwrDBallVZType (const HwrM68VZ328Type& hwRegs)
+{
+ fFile.WriteChunk (kDBVZRegs, sizeof (hwRegs), &hwRegs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteHwrDBallSZType
+ *
+ * DESCRIPTION: Write the Dragonball SZ hardware registers to the session
+ * file.
+ *
+ * PARAMETERS: hwRegs - the DB registers to write to disk. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteDBallRegs
+ *
+ * DESCRIPTION: Write the Dragonball CPU registers to the session file.
+ *
+ * PARAMETERS: cpuRegs - the registers to write to disk. No munging
+ * of this data is performed; it is expected that any
+ * byteswapping has already taken place.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteDBallRegs (const regstruct& cpuRegs)
+{
+ fFile.WriteChunk (kCPURegs, sizeof (cpuRegs), &cpuRegs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteDeviceType
+ *
+ * DESCRIPTION: Write the id of the device to emulate.
+ *
+ * PARAMETERS: v - id of the device to emulate.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteDevice (const EmDevice& v)
+{
+ fFile.WriteString (kDeviceTypeString, v.GetIDString ());
+
+ // Remember that we were using this device most recently.
+
+ fCfg.fDevice = v;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteBugFixes
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: v - flags of fixed bugs.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteBugFixes (const BugFixes& v)
+{
+ fFile.WriteInt (kBugsTag, (uint32) v);
+}
+
+
+void SessionFile::WriteSED1375RegsType (const SED1375RegsType& sedRegs)
+{
+ fFile.WriteChunk (kSED1375Regs, sizeof (sedRegs), &sedRegs);
+}
+
+void SessionFile::WriteSED1375Image (const void* image, uint32 size)
+{
+ this->WriteChunk (kSED1375Image, size, image, kGzipCompression);
+}
+
+void SessionFile::WriteSED1375Palette (const uint16 palette[256])
+{
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ fFile.WriteChunk (kSED1375Palette, size, palette);
+}
+
+void SessionFile::WriteSED1376RegsType (const SED1376RegsType& sedRegs)
+{
+ fFile.WriteChunk (kSED1376Regs, EmProxySED1376RegsType::GetSize (), &sedRegs);
+}
+
+void SessionFile::WriteSED1376Palette (const RGBType palette[256])
+{
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ fFile.WriteChunk (kSED1376Palette, size, palette);
+}
+
+// SessionFile::WriteMediaQRegsType is defined in SessionFile.h
+
+void SessionFile::WriteMediaQImage (const void* image, uint32 size)
+{
+ this->WriteChunk (kMediaQImage, size, image, kGzipCompression);
+}
+
+void SessionFile::WriteMediaQPalette (const RGBType palette[256])
+{
+ // Note: "sizeof (palette)" gives 4, not 512.
+ int size = 256 * sizeof (palette[0]);
+ fFile.WriteChunk (kMediaQPalette, size, palette);
+}
+
+void SessionFile::WritePLDRegsType (const HwrJerryPLDType& pldRegs)
+{
+ fFile.WriteChunk (kPLDRegs, sizeof (pldRegs), &pldRegs);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::SetCanReload
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SessionFile::SetCanReload (Bool val)
+{
+ fCanReload = val;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::GetCanReload
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::GetCanReload (void)
+{
+ return fCanReload;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::FixBug
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SessionFile::FixBug (BugFix val)
+{
+ fBugFixes |= val;
+ fChangedBugFixes = true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::IncludesBugFix
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::IncludesBugFix (BugFix val)
+{
+ if (!fReadBugFixes)
+ {
+ this->ReadBugFixes (fBugFixes);
+ fReadBugFixes = true;
+ }
+
+ return (fBugFixes & val) != 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::ReadChunk
+ *
+ * DESCRIPTION: Read an arbitrary chunk of data, utilizing the given
+ * type of compression, returning a pointer to the read
+ * data and the size of the data.
+ *
+ * PARAMETERS: tag - marker identifying the data to be read.
+ *
+ * size - reference to the integer to receive the number
+ * of bytes in the data. This size may not be the same
+ * as the size of the chunk if the chunk is compressed.
+ *
+ * image - reference to the pointer to receive the address
+ * of the read data.
+ *
+ * compType - type of compression used for this chunk. The
+ * caller is expected to know what kind of compression
+ * is being used; the compression type is not stored
+ * along with the chunk.
+ *
+ * RETURNED: True if the image was found and could be read in.
+ *
+ ***********************************************************************/
+
+Bool SessionFile::ReadChunk (ChunkFile::Tag tag, void* image,
+ CompressionType compType)
+{
+ // Get the size of the chunk.
+
+ long chunkSize = fFile.FindChunk (tag);
+ if (chunkSize == ChunkFile::kChunkNotFound)
+ {
+ return false;
+ }
+
+ if (chunkSize)
+ {
+ // If no compression is being used, just read the data.
+
+ if (compType == kNoCompression)
+ {
+ fFile.ReadChunk (chunkSize, image);
+ }
+
+ // The data is compressed.
+
+ else
+ {
+ // Use the chunk size to create a buffer.
+
+ StMemory packedImage (chunkSize);
+
+ // Read the chunk into memory.
+
+ fFile.ReadChunk (chunkSize, packedImage.Get ());
+
+ // The size of the unpacked image is stored as the first 4 bytes
+ // of the chunk.
+
+ long unpackedSize = *(long*) packedImage.Get ();
+ Canonical (unpackedSize);
+
+ // Get pointers to the source (packed) data and
+ // destination (unpacked) data.
+
+ void* src = packedImage.Get () + sizeof (long);
+ void* dest = image;
+
+ // Decompress the data into the dest buffer.
+
+ if (compType == kGzipCompression)
+ ::GzipDecode (&src, &dest, chunkSize - sizeof (long), unpackedSize);
+ else
+ ::RunLengthDecode (&src, &dest, chunkSize - sizeof (long), unpackedSize);
+ }
+ }
+
+ return true;
+}
+
+
+Bool SessionFile::ReadChunk (ChunkFile::Tag tag, Chunk& chunk,
+ CompressionType compType)
+{
+ // Get the size of the chunk.
+
+ long chunkSize = fFile.FindChunk (tag);
+ if (chunkSize == ChunkFile::kChunkNotFound)
+ {
+ return false;
+ }
+
+ if (chunkSize)
+ {
+ // If no compression is being used, just read the data.
+
+ if (compType == kNoCompression)
+ {
+ chunk.SetLength (chunkSize);
+ fFile.ReadChunk (chunkSize, chunk.GetPointer ());
+ }
+
+ // The data is compressed.
+
+ else
+ {
+ // Use the chunk size to create a buffer.
+
+ StMemory packedImage (chunkSize);
+
+ // Read the chunk into memory.
+
+ fFile.ReadChunk (chunkSize, packedImage.Get ());
+
+ // The size of the unpacked image is stored as the first 4 bytes
+ // of the chunk.
+
+ long unpackedSize = *(long*) packedImage.Get ();
+ Canonical (unpackedSize);
+
+ chunk.SetLength (unpackedSize);
+
+ // Get pointers to the source (packed) data and
+ // destination (unpacked) data.
+
+ void* src = packedImage.Get () + sizeof (long);
+ void* dest = chunk.GetPointer ();
+
+ // Decompress the data into the dest buffer.
+
+ if (compType == kGzipCompression)
+ ::GzipDecode (&src, &dest, chunkSize - sizeof (long), unpackedSize);
+ else
+ ::RunLengthDecode (&src, &dest, chunkSize - sizeof (long), unpackedSize);
+ }
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SessionFile::WriteChunk
+ *
+ * DESCRIPTION: Write an arbitrary chunk of data, utilizing the given
+ * type of compression.
+ *
+ * PARAMETERS: tag - marker used to later retrieve the data.
+ *
+ * size - number of bytes in the image to write.
+ *
+ * image - pointer to the image to write.
+ *
+ * compType - type of compression to use.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SessionFile::WriteChunk (ChunkFile::Tag tag, uint32 size,
+ const void* image, CompressionType compType)
+{
+ // No compression to be used; just write the data out as-is.
+
+ if (compType == kNoCompression)
+ {
+ fFile.WriteChunk (tag, size, image);
+ }
+
+ // Use some form of compression.
+
+ else
+ {
+ // Get the worst-case size for the compressed data.
+
+ long worstPackedSize = sizeof (long) +
+ ((compType == kGzipCompression)
+ ? ::GzipWorstSize (size)
+ : ::RunLengthWorstSize (size));
+
+ // Create a new buffer to hold the compressed data.
+
+ StMemory packedImage (worstPackedSize);
+
+ // Write out the uncompressed size of the data as the first
+ // 4 bytes of the chunk.
+
+ Canonical (size);
+ *(long*) packedImage.Get () = size;
+ Canonical (size);
+
+ // Get pointers to the source (unpacked) data and
+ // destination (packed) data.
+
+ void* src = (void*) image;
+ void* dest = packedImage.Get () + sizeof (long);
+
+ // Compress the data.
+
+ if (compType == kGzipCompression)
+ ::GzipEncode (&src, &dest, size, worstPackedSize);
+ else
+ ::RunLengthEncode (&src, &dest, size, worstPackedSize);
+
+ // Calculate the compressed size of the data.
+
+ long packedSize = (char*) dest - (char*) packedImage;
+
+ // Write the compressed data to the file.
+
+ fFile.WriteChunk (tag, packedSize, packedImage.Get ());
+ }
+}
+
+void SessionFile::WriteChunk (ChunkFile::Tag tag, const Chunk& chunk, CompressionType compType)
+{
+ this->WriteChunk (tag, chunk.GetLength (), chunk.GetPointer (), compType);
+}
diff --git a/SrcShared/SessionFile.h b/SrcShared/SessionFile.h
new file mode 100644
index 0000000..3c6fb23
--- /dev/null
+++ b/SrcShared/SessionFile.h
@@ -0,0 +1,257 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _SESSIONFILE_H_
+#define _SESSIONFILE_H_
+
+#include "ChunkFile.h" // ChunkFile
+#include "EmDevice.h" // EmDevice
+#include "EmStructs.h" // Configuration, RGBType
+#include "Platform.h" // Platform
+
+struct HwrJerryPLDType;
+struct HwrM68328Type;
+struct HwrM68EZ328Type;
+struct HwrM68VZ328Type;
+struct HwrM68SZ328Type;
+struct regstruct;
+struct SED1375RegsType;
+struct SED1376RegsType;
+
+class SessionFile
+{
+ public:
+ typedef uint32 BugFixes;
+ enum BugFix
+ {
+ kBugByteswappedStructs = 1 // Fixes bug where SED1375RegsType, HwrDBallEZType, HwrDBallType were
+ // stored in host-endian format.
+ };
+
+ public:
+ SessionFile (ChunkFile& f);
+ ~SessionFile (void);
+
+ // ---------- Reading ----------
+
+ Bool ReadDevice (EmDevice&);
+
+ Bool ReadROMFileReference (EmFileRef&);
+
+ Bool ReadDBallRegs (regstruct&);
+ Bool ReadHwrDBallType (HwrM68328Type&);
+ Bool ReadHwrDBallEZType (HwrM68EZ328Type&);
+ Bool ReadHwrDBallVZType (HwrM68VZ328Type&);
+ Bool ReadDBallState (Chunk& chunk) { return fFile.ReadChunk (kDBState, chunk); }
+ Bool ReadDBallEZState (Chunk& chunk) { return fFile.ReadChunk (kDBEZState, chunk); }
+ Bool ReadDBallVZState (Chunk& chunk) { return fFile.ReadChunk (kDBEZState, chunk); }
+
+ Bool ReadSED1375RegsType (SED1375RegsType&);
+ Bool ReadSED1375Image (void*);
+ Bool ReadSED1375Palette (uint16 [256]);
+
+ Bool ReadSED1376RegsType (SED1376RegsType&);
+ Bool ReadSED1376Palette (RGBType [256]);
+
+ Bool ReadMediaQRegsType (Chunk& chunk) { return fFile.ReadChunk (kMediaQRegs, chunk); }
+ Bool ReadMediaQImage (void*);
+ Bool ReadMediaQPalette (RGBType [256]);
+
+ Bool ReadPLDRegsType (HwrJerryPLDType&);
+
+ Bool ReadGremlinInfo (Chunk& chunk) { return fFile.ReadChunk (kGremlinInfo, chunk); }
+ Bool ReadGremlinHistory (Chunk& chunk) { return this->ReadChunk (kGremlinHistory, chunk, kGzipCompression); }
+ Bool ReadDebugInfo (Chunk& chunk) { return fFile.ReadChunk (kDebugInfo, chunk); }
+ Bool ReadMetaInfo (Chunk& chunk) { return fFile.ReadChunk (kMetaInfo, chunk); }
+ Bool ReadPatchInfo (Chunk& chunk) { return fFile.ReadChunk (kPatchInfo, chunk); }
+ Bool ReadProfileInfo (Chunk& chunk) { return fFile.ReadChunk (kProfileInfo, chunk); }
+ Bool ReadLoggingInfo (Chunk& chunk) { return fFile.ReadChunk (kLoggingInfo, chunk); }
+ Bool ReadStackInfo (Chunk& chunk) { return fFile.ReadChunk (kStackInfo, chunk); }
+ Bool ReadHeapInfo (Chunk& chunk) { return fFile.ReadChunk (kHeapInfo, chunk); }
+
+ Bool ReadPlatformInfo (Chunk& chunk) { return fFile.ReadChunk (kPlatformInfo, chunk); }
+ Bool ReadPlatformInfoMac (Chunk& chunk) { return fFile.ReadChunk (kPlatformMac, chunk); }
+ Bool ReadPlatformInfoWin (Chunk& chunk) { return fFile.ReadChunk (kPlatformWindows, chunk); }
+ Bool ReadPlatformInfoUnix (Chunk& chunk) { return fFile.ReadChunk (kPlatformUnix, chunk); }
+
+ Bool ReadRAMImage (void*);
+ Bool ReadMetaRAMImage (void*);
+ Bool ReadMetaROMImage (void*);
+
+ Bool ReadBugFixes (BugFixes&);
+
+ // ---------- Writing ----------
+
+ void WriteDevice (const EmDevice&);
+
+ void WriteROMFileReference (const EmFileRef&);
+
+ void WriteDBallRegs (const regstruct&);
+ void WriteHwrDBallType (const HwrM68328Type&);
+ void WriteHwrDBallEZType (const HwrM68EZ328Type&);
+ void WriteHwrDBallVZType (const HwrM68VZ328Type&);
+ void WriteDBallState (const Chunk& chunk) { fFile.WriteChunk (kDBState, chunk); }
+ void WriteDBallEZState (const Chunk& chunk) { fFile.WriteChunk (kDBEZState, chunk); }
+ void WriteDBallVZState (const Chunk& chunk) { fFile.WriteChunk (kDBEZState, chunk); }
+
+ void WriteSED1375RegsType (const SED1375RegsType&);
+ void WriteSED1375Image (const void*, uint32);
+ void WriteSED1375Palette (const uint16 [256]);
+
+ void WriteSED1376RegsType (const SED1376RegsType&);
+ void WriteSED1376Palette (const RGBType [256]);
+
+ void WriteMediaQRegsType (const Chunk& chunk) { fFile.WriteChunk (kMediaQRegs, chunk); }
+ void WriteMediaQImage (const void*, uint32);
+ void WriteMediaQPalette (const RGBType [256]);
+
+ void WritePLDRegsType (const HwrJerryPLDType&);
+
+ void WriteGremlinInfo (const Chunk& chunk) { fFile.WriteChunk (kGremlinInfo, chunk); }
+ void WriteGremlinHistory (const Chunk& chunk) { this->WriteChunk (kGremlinHistory, chunk, kGzipCompression); }
+ void WriteDebugInfo (const Chunk& chunk) { fFile.WriteChunk (kDebugInfo, chunk); }
+ void WriteMetaInfo (const Chunk& chunk) { fFile.WriteChunk (kMetaInfo, chunk); }
+ void WritePatchInfo (const Chunk& chunk) { fFile.WriteChunk (kPatchInfo, chunk); }
+ void WriteProfileInfo (const Chunk& chunk) { fFile.WriteChunk (kProfileInfo, chunk); }
+ void WriteLoggingInfo (const Chunk& chunk) { fFile.WriteChunk (kLoggingInfo, chunk); }
+ void WriteStackInfo (const Chunk& chunk) { fFile.WriteChunk (kStackInfo, chunk); }
+ void WriteHeapInfo (const Chunk& chunk) { fFile.WriteChunk (kHeapInfo, chunk); }
+
+ void WritePlatformInfo (const Chunk& chunk) { fFile.WriteChunk (kPlatformInfo, chunk); }
+ void WritePlatformInfoMac (const Chunk& chunk) { fFile.WriteChunk (kPlatformMac, chunk); }
+ void WritePlatformInfoWin (const Chunk& chunk) { fFile.WriteChunk (kPlatformWindows, chunk); }
+ void WritePlatformInfoUnix (const Chunk& chunk) { fFile.WriteChunk (kPlatformUnix, chunk); }
+
+ void WriteRAMImage (const void*, uint32);
+ void WriteMetaRAMImage (const void*, uint32);
+ void WriteMetaROMImage (const void*, uint32);
+
+ void WriteBugFixes (const BugFixes&);
+
+ // ---------- Other ----------
+
+ Bool ReadConfiguration (Configuration&);
+ long GetRAMImageSize (void);
+
+ // As information is saved to the file, certain parts are recorded
+ // here. That way, this information can be save to the preference
+ // file/registry so that newly created sessions can be based on the
+ // most recently used settings.
+
+ Configuration GetConfiguration (void) { return fCfg; }
+
+ void SetCanReload (Bool);
+ Bool GetCanReload (void);
+
+ void FixBug (BugFix);
+ Bool IncludesBugFix (BugFix);
+
+ private:
+ enum CompressionType
+ {
+ kNoCompression,
+ kRLECompression,
+ kGzipCompression
+ };
+
+ Bool ReadChunk (ChunkFile::Tag tag,
+ void*,
+ CompressionType);
+
+ Bool ReadChunk (ChunkFile::Tag tag,
+ Chunk& chunk,
+ CompressionType);
+
+ void WriteChunk (ChunkFile::Tag tag,
+ uint32,
+ const void*,
+ CompressionType);
+
+ void WriteChunk (ChunkFile::Tag tag,
+ const Chunk& chunk,
+ CompressionType);
+
+ // These functions access kROMAliasTag, kROMNameTag, kROMPathTag
+ friend Bool Platform::ReadROMFileReference (ChunkFile&, EmFileRef&);
+ friend void Platform::WriteROMFileReference (ChunkFile&, const EmFileRef&);
+
+ enum
+ {
+ kDeviceType = 'DTyp', // Device type (Pilot 1000, PalmPilot, Palm III, etc.)
+ kDeviceTypeString = 'DStr', // Device type as string (preferred)
+
+ kROMAliasTag = 'ROMa', // Macintosh alias
+ kROMNameTag = 'ROMn', // Simple file name
+ kROMWindowsPathTag = 'ROMp', // Full file path (Windows format)
+ kROMUnixPathTag = 'ROMu', // Full file path (Unix format)
+
+ kCPURegs = 'Creg', // CPU registers (D0-D7, A0-A7, PC, CCR, SR, etc.).
+ kDBRegs = 'DB ', // Memory-mapped registers struct.
+ kDBEZRegs = 'DBEZ', // Memory-mapped registers struct.
+ kDBVZRegs = 'DBVZ', // Memory-mapped registers struct.
+ kDBState = 'DSt8', // Extra state stored outside of the memory-mapped registers struct.
+ kDBEZState = 'ESt8', // Extra state stored outside of the memory-mapped registers struct.
+ kDBVZState = 'VSt8', // Extra state stored outside of the memory-mapped registers struct.
+
+ kSED1375Regs = '5reg', // Memory-mapped registers struct.
+ kSED1375Image = '5ram', // LCD buffer memory.
+ kSED1375Palette = '5clt', // LCD color lookup table.
+
+ kSED1376Regs = '6reg', // Memory-mapped registers struct.
+ kSED1376Palette = '6clt', // LCD color lookup table.
+
+ kMediaQRegs = 'MQrg', // Memory-mapped registers struct.
+ kMediaQImage = 'MQim', // LCD buffer memory.
+ kMediaQPalette = 'MQcl', // LCD color lookup table.
+
+ kPLDRegs = 'pld ', // Memory-mapped registers struct.
+
+ kGremlinInfo = 'grem', // Gremlin state
+ kGremlinHistory = 'hist', // Gremlin event history
+ kDebugInfo = 'dbug', // Debug state
+ kMetaInfo = 'meta', // MetaMemory state
+ kPatchInfo = 'ptch', // Trappatch state
+ kProfileInfo = 'prof', // Profiling state
+ kLoggingInfo = 'log ', // Standard LogStream data
+ kStackInfo = 'stak', // List of currently known stacks
+ kHeapInfo = 'heap', // Heap state
+
+ kPlatformInfo = 'plat', // Information managed by the Platform sub-system that has analogs on all platforms.
+ kPlatformMac = 'mac ', // Mac-specific information
+ kPlatformWindows = 'wind', // Windows-specific information
+ kPlatformUnix = 'unix', // Unix-specific information
+
+ kTimeDelta = 'Time', // Delta between the actual time and the time set by
+ // the user via the General preference panel.
+
+ kRAMDataTag = 'zram', // gzip compressed RAM image
+ kMetaRAMDataTag = 'zmrm', // gzip compressed meta-RAM image
+ kMetaROMDataTag = 'zmro', // gzip compressed meta-ROM image
+
+ kBugsTag = 'bugz', // bit flags indicating bug fixes in file format
+
+ kRLERAMDataTag = 'cram', // RLE compressed RAM image - obsolete
+ kRLEMetaRAMDataTag = 'mram', // RLE compressed meta-RAM image - obsolete
+ kUncompRAMDataTag = 'ram ' // Uncompressed RAM image - obsolete
+ };
+
+ private:
+ ChunkFile& fFile;
+ Bool fCanReload;
+ Configuration fCfg;
+ bool fReadBugFixes;
+ bool fChangedBugFixes;
+ BugFixes fBugFixes;
+};
+
+#endif // _SESSIONFILE_H_
diff --git a/SrcShared/Skins.cpp b/SrcShared/Skins.cpp
new file mode 100644
index 0000000..ab2a349
--- /dev/null
+++ b/SrcShared/Skins.cpp
@@ -0,0 +1,1485 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Skins.h"
+
+#include "ChunkFile.h" // Chunk
+#include "EmApplication.h" // gApplication
+#include "EmFileRef.h" // EmFileRef
+#include "EmMapFile.h" // EmMapFile
+#include "EmSession.h" // gSession
+#include "EmStreamFile.h" // EmStreamFile, kOpenExistingForRead
+#include "Miscellaneous.h" // StartsWith
+#include "Platform.h" // _stricmp
+#include "PreferenceMgr.h" // Preference
+#include "Strings.r.h" // kStr_MissingSkins
+
+#include <algorithm> // find()
+
+struct ButtonBounds
+{
+ SkinElementType fButton;
+ EmRect fBounds;
+};
+typedef vector<ButtonBounds> ButtonBoundsList;
+
+struct ButtonBoundsX
+{
+ SkinElementType fButton;
+ RectangleType fBounds;
+};
+
+struct Skinfo
+{
+ Skinfo () :
+ fSkinFile (),
+ fName (),
+ fImageName1x (),
+ fImageName2x (),
+ fDevices (),
+ fButtons ()
+ {}
+
+ EmFileRef fSkinFile;
+ SkinName fName;
+ string fImageName1x;
+ string fImageName2x;
+ RGBType fBackgroundColor;
+ RGBType fHighlightColor;
+ EmDeviceList fDevices;
+ ButtonBoundsList fButtons;
+};
+typedef vector<Skinfo> SkinList;
+
+
+static EmDevice gCurrentDevice;
+static Skinfo gCurrentSkin;
+static ScaleType gCurrentScale;
+
+static void PrvBuildSkinList (SkinList&);
+static void PrvGetSkins (const EmDevice&, SkinList& results);
+static Bool PrvGetNamedSkin (const EmDevice&, const SkinName& name, Skinfo& result);
+static void PrvGetGenericSkin (Skinfo& skin);
+static void PrvGetDefaultSkin (const EmDevice&, Skinfo& skin);
+static void PrvSetSkin (const EmDevice&, const Skinfo&, ScaleType scale);
+static EmRect PrvGetTouchscreen (void);
+static SkinElementType PrvTestPoint (const EmPoint&, int outset);
+static SkinName PrvGetSkinName (const EmDevice& device);
+
+
+static const char* kElementNames[] =
+{
+ "PowerButton",
+ "UpButton",
+ "DownButton",
+ "App1Button",
+ "App2Button",
+ "App3Button",
+ "App4Button",
+ "CradleButton",
+ "Antenna",
+ "ContrastButton",
+
+ // Symbol-specific
+ "TriggerLeft",
+ "TriggerCenter",
+ "TriggerRight",
+ "UpButtonLeft",
+ "UpButtonRight",
+ "DownButtonLeft",
+ "DownButtonRight",
+
+ "Touchscreen",
+ "LCD",
+ "LED"
+};
+
+
+static const char kGenericSkinName[] = "Generic";
+
+static ButtonBoundsX kGenericButtons [] =
+{
+ { kElement_PowerButton, { { 1, 274 }, { 16, 24 } } },
+ { kElement_UpButton, { { 96, 272 }, { 32, 16 } } },
+ { kElement_DownButton, { { 96, 293 }, { 32, 16 } } },
+ { kElement_App1Button, { { 23, 270 }, { 32, 32 } } },
+ { kElement_App2Button, { { 60, 270 }, { 32, 32 } } },
+ { kElement_App3Button, { { 131, 270 }, { 32, 32 } } },
+ { kElement_App4Button, { { 168, 270 }, { 32, 32 } } },
+ { kElement_CradleButton, { { 0, 0 }, { 0, 0 } } },
+ { kElement_Antenna, { { 0, 0 }, { 0, 0 } } },
+ { kElement_ContrastButton, { { 0, 0 }, { 0, 0 } } },
+ { kElement_Touchscreen, { { 32, 32 }, { 160, 220 } } },
+ { kElement_LCD, { { 32, 32 }, { 160, 160 } } },
+ { kElement_LED, { { 1, 274 }, { 16, 24 } } }
+};
+
+static RGBType kGenericBackgroundColor (0x7B, 0x8C, 0x5A);
+static RGBType kGenericHighlightColor (0x64, 0xF0, 0xDC);
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetSkinName
+ *
+ * DESCRIPTION: Get the name of the user-chosen skin for the given
+ * device type.
+ *
+ * PARAMETERS: type - the device type for which we need the name
+ * of the skin to use.
+ *
+ * RETURNED: The skin name. At the very least, this will be the
+ * name of some default skin if the user hasn't made a
+ * choice or if the chosen skin is invalid.
+ *
+ ***********************************************************************/
+
+SkinName SkinGetSkinName (const EmDevice& device)
+{
+ // Get the chosen skin for this device.
+
+ SkinName name = ::PrvGetSkinName (device);
+
+ // If the name is empty or invalid, chose a default skin.
+
+ if (!::SkinValidSkin (device, name))
+ {
+ name = ::SkinGetDefaultSkinName (device);
+ }
+
+ return name;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetDefaultSkinName
+ *
+ * DESCRIPTION: Get the name of the user-chosen skin for the given
+ * device type.
+ *
+ * PARAMETERS: type - the device type for which we need the name
+ * of the skin to use.
+ *
+ * RETURNED: The skin name. At the very least, this will be the
+ * name of some default skin if the user hasn't made a
+ * choice or if the chosen skin is invalid.
+ *
+ ***********************************************************************/
+
+SkinName SkinGetDefaultSkinName (const EmDevice& device)
+{
+ Skinfo skin;
+ ::PrvGetDefaultSkin (device, skin);
+ return skin.fName;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetSkinNames
+ *
+ * DESCRIPTION: Get the list of names of available skins for the given
+ * device.
+ *
+ * PARAMETERS: type - the device for which the list of skins should
+ * be returned. If kDeviceUnspecified, return all
+ * skins for all devices.
+ *
+ * results - receives the list of skin names. Any skin
+ * names are *added* to this list; the list is not
+ * cleared out first.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SkinGetSkinNames (const EmDevice& device, SkinNameList& results)
+{
+ // Always push on the name of the default skin first.
+
+ results.push_back (kGenericSkinName);
+
+ // Get the names of any custom skins for the device and
+ // add those, too.
+
+ SkinList skins;
+ ::PrvGetSkins (device, skins);
+
+ SkinList::iterator iter = skins.begin ();
+ while (iter != skins.end ())
+ {
+ results.push_back (iter->fName);
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinSetSkin
+ *
+ * DESCRIPTION: Establish the skin to use, based on the current settings.
+ * All other funtions in this module will then work within
+ * the context of the specified skin.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void SkinSetSkin (void)
+{
+ EmAssert (gSession);
+
+ Configuration cfg = gSession->GetConfiguration ();
+ SkinName skinName = ::PrvGetSkinName (cfg.fDevice);
+ Preference<ScaleType> scalePref (kPrefKeyScale);
+
+ ::SkinSetSkin (cfg.fDevice, *scalePref, skinName);
+}
+
+
+void SkinSetSkin (const EmDevice& device, ScaleType scale, const SkinName& name)
+{
+ Skinfo skin;
+
+ if (!::PrvGetNamedSkin (device, name, skin))
+ {
+ ::PrvGetDefaultSkin (device, skin);
+ }
+
+ ::PrvSetSkin (device, skin, scale);
+}
+
+
+void SkinSetSkinName (const EmDevice& device, const SkinName& name)
+{
+ string idString (device.GetIDString ());
+ string prefKey (kPrefKeySkins + ("." + idString));
+
+ Preference<SkinName> prefSkin (prefKey.c_str ());
+ prefSkin = name;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetSkinfoFile
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmFileRef SkinGetSkinfoFile (void)
+{
+ return gCurrentSkin.fSkinFile;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetSkinFile
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmFileRef SkinGetSkinFile (void)
+{
+ return ::SkinGetSkinFile (gCurrentScale);
+}
+
+
+EmFileRef SkinGetSkinFile (ScaleType scale)
+{
+ EmFileRef skinfoFile = ::SkinGetSkinfoFile ();
+
+ if (!skinfoFile.IsSpecified ())
+ {
+ return EmFileRef ();
+ }
+
+ EmAssert (!gApplication->SkinfoResourcePresent ());
+ EmAssert (!gApplication->Skin1xResourcePresent ());
+ EmAssert (!gApplication->Skin2xResourcePresent ());
+
+ string name;
+
+ if (scale == 1)
+ name = gCurrentSkin.fImageName1x.c_str();
+ else
+ name = gCurrentSkin.fImageName2x.c_str();
+
+ EmDirRef skinDir = skinfoFile.GetParent ();
+ EmFileRef skinImage (skinDir, name);
+
+ // If the skin file doesn't exist, try looking for it
+ // in a Mac or Windows sub-directory. This helps development
+ // of the emulator, as images for different platforms are
+ // stored in directories with those names. This sub-directory
+ // looking shouldn't be needed for the image archive made
+ // available to developers.
+
+ if (!skinImage.Exists ())
+ {
+#if PLATFORM_MAC
+ EmDirRef skinSubDir (skinDir, "Mac");
+#else
+ EmDirRef skinSubDir (skinDir, "Windows");
+#endif
+
+ skinImage = EmFileRef (skinSubDir, name);
+ if (!skinImage.Exists ())
+ {
+ EmFileRef temp;
+ return (temp);
+ }
+ }
+
+ return skinImage;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetSkinStream
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmStream* SkinGetSkinStream (void)
+{
+ return ::SkinGetSkinStream (gCurrentScale);
+}
+
+
+EmStream* SkinGetSkinStream (ScaleType scale)
+{
+ EmStream* result = NULL;
+
+ if (gCurrentSkin.fName == kGenericSkinName)
+ return result;
+
+ if (gApplication->IsBound ())
+ {
+ // If we're bound, open up a stream on the resource data.
+
+ Bool haveRes;
+ Chunk* chunk = new Chunk;
+
+ if (scale == 1)
+ haveRes = gApplication->GetSkin1xResource (*chunk);
+ else
+ haveRes = gApplication->GetSkin2xResource (*chunk);
+
+ if (haveRes)
+ result = new EmStreamChunk (chunk);
+ else
+ delete chunk;
+ }
+ else
+ {
+ EmFileRef file = ::SkinGetSkinFile (scale);
+
+ if (file.Exists ())
+ {
+ // If we're not bound, try opening a stream on the file.
+
+ result = new EmStreamFile (file, kOpenExistingForRead);
+ }
+ }
+
+ if (!result)
+ {
+ // If we can't get the image, revert to the default image.
+ // !!! Should probably also remove the skin from the skin list.
+
+ Skinfo skin;
+ ::PrvGetDefaultSkin (gCurrentDevice, skin);
+ ::PrvSetSkin (gCurrentDevice, skin, scale);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinValidSkin
+ *
+ * DESCRIPTION: Returns whether the given device has a skin with the
+ * given name.
+ *
+ * PARAMETERS: type - the device type.
+ *
+ * skinName - the skin name.
+ *
+ * RETURNED: True if the given device has a skin with the given name.
+ * False otherwise.
+ *
+ ***********************************************************************/
+
+Bool SkinValidSkin (const EmDevice& device, const SkinName& skinName)
+{
+ SkinNameList skins;
+ ::SkinGetSkinNames (device, skins);
+
+ SkinNameList::iterator iter = skins.begin ();
+ while (iter != skins.end ())
+ {
+ if (*iter == skinName)
+ {
+ return true;
+ }
+
+ ++iter;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetBackgroundColor
+ *
+ * DESCRIPTION: Return the default background color for the current
+ * skin.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The default background color.
+ *
+ ***********************************************************************/
+
+RGBType SkinGetBackgroundColor (void)
+{
+ return gCurrentSkin.fBackgroundColor;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetHighlightColor
+ *
+ * DESCRIPTION: Return the default highlight color for the current
+ * skin.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The default highlight color.
+ *
+ ***********************************************************************/
+
+RGBType SkinGetHighlightColor (void)
+{
+ return gCurrentSkin.fHighlightColor;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinTestPoint
+ *
+ * DESCRIPTION: Tests the given point to see what skin element it's over.
+ *
+ * PARAMETERS: pt - location in the window to test.
+ *
+ * RETURNED: If the point is within an element, returns the id for
+ * that element. If an element was just missed, returns
+ * kElement_None. Otherwise, returns kElement_Frame.
+ *
+ ***********************************************************************/
+
+SkinElementType SkinTestPoint (const EmPoint& pt)
+{
+ // See if we hit an element. PrvTestPoint will return either the
+ // element hit or kElement_Frame if none were hit. If an element
+ // was hit, return it.
+
+ SkinElementType result = ::PrvTestPoint (pt, 0);
+
+ if (result != kElement_Frame)
+ return result;
+
+ // Test again, this time allowing for some slop around the
+ // elements. If an element was hit this time, then we hit the
+ // small "dead area" we allow around the elements. In that case,
+ // we want to return kElement_None. Otherwise, if no element was
+ // hit, signal that the frame was hit.
+
+ result = ::PrvTestPoint (pt, 5);
+ if (result != kElement_Frame)
+ return kElement_None;
+
+ return kElement_Frame;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinWindowToTouchscreen
+ *
+ * DESCRIPTION: Convert a point from window coordinates to LCD
+ * coordinates.
+ *
+ * PARAMETERS: pt - point in window coordinates to convert.
+ *
+ * RETURNED: The point in LCD coordinates (where the topleft corner
+ * of the LCD is 0,0 and the scale is 1x).
+ *
+ ***********************************************************************/
+
+EmPoint SkinWindowToTouchscreen (const EmPoint& pt)
+{
+ EmPoint result = pt;
+ EmRect r = ::PrvGetTouchscreen ();
+
+ result -= r.TopLeft ();
+
+ if (result.fX < 0)
+ result.fX = 0;
+
+ if (result.fY < 0)
+ result.fY = 0;
+
+ if (result.fX >= r.Width ())
+ result.fX = r.Width () - 1;
+
+ if (result.fY >= r.Height ())
+ result.fY = r.Height () - 1;
+
+ result = ::SkinScaleDown (result);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinLCDToWindow
+ *
+ * DESCRIPTION: Convert a point from LCD coordinates to window
+ * coordinates.
+ *
+ * PARAMETERS: pt - point in LCD coordinates to convert.
+ *
+ * RETURNED: The point in window coordinates (where the topleft
+ * corner of the window is 0,0 and the scale is the
+ * scale chosen by the user).
+ *
+ ***********************************************************************/
+
+EmPoint SkinTouchscreenToWindow (const EmPoint& lcdPt)
+{
+ EmPoint result = lcdPt;
+ EmRect r = ::PrvGetTouchscreen ();
+
+ result += r.TopLeft ();
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinGetElementInfo
+ *
+ * DESCRIPTION: Get information on the given element.
+ *
+ * PARAMETERS: index - index of the element we're querying.
+ *
+ * type - type of the element we've queried
+ *
+ * bounds - bounds of the element we've queried. The
+ * is scaled up if necessary.
+ *
+ * RETURNED: TRUE if there was such an element. FALSE if index is
+ * out of range.
+ *
+ ***********************************************************************/
+
+Bool SkinGetElementInfo (int index, SkinElementType& type, EmRect& bounds)
+{
+ if (index < (int) gCurrentSkin.fButtons.size ())
+ {
+ type = gCurrentSkin.fButtons[index].fButton;
+ bounds = gCurrentSkin.fButtons[index].fBounds;
+ bounds = ::SkinScaleUp (bounds);
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinScaleDown
+ *
+ * DESCRIPTION: Convert a point from 1x or 2x to just 1x.
+ *
+ * PARAMETERS: pt - point to change.
+ *
+ * RETURNED: Normalized point.
+ *
+ ***********************************************************************/
+
+EmPoint SkinScaleDown (const EmPoint& pt)
+{
+ EmAssert (gCurrentScale > 0);
+
+ EmPoint result = pt;
+
+ result /= EmPoint (gCurrentScale, gCurrentScale);
+
+ return result;
+}
+
+
+EmRect SkinScaleDown (const EmRect& r)
+{
+ EmAssert (gCurrentScale > 0);
+
+ EmRect result = r;
+
+ result /= EmPoint (gCurrentScale, gCurrentScale);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SkinScaleUp
+ *
+ * DESCRIPTION: Convert a point to 1x or 2x, depending on the scaling
+ * factor.
+ *
+ * PARAMETERS: pt - point to change.
+ *
+ * RETURNED: Denormalized point.
+ *
+ ***********************************************************************/
+
+EmPoint SkinScaleUp (const EmPoint& pt)
+{
+ EmAssert (gCurrentScale > 0);
+
+ EmPoint result = pt;
+
+ result *= EmPoint (gCurrentScale, gCurrentScale);
+
+ return result;
+}
+
+
+EmRect SkinScaleUp (const EmRect& r)
+{
+ EmAssert (gCurrentScale > 0);
+
+ EmRect result = r;
+
+ result *= EmPoint (gCurrentScale, gCurrentScale);
+
+ return result;
+}
+
+
+#pragma mark -
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static int PrvGetNumber (const string& s)
+{
+ // Get the (stringized) component to convert.
+
+ string numString = ::Strip (s, " \t", true, true);
+
+ // Try converting it from hex to numeric format.
+
+ int result;
+ int scanned = sscanf (numString.c_str (), "0x%X", &result);
+
+ // If that failed, try converting it from decimal to numeric format.
+ // We have to be careful about scanning "0". That text will match
+ // the "0" in "0x%X", causing it to return EOF, but not filling
+ // in "result".
+
+ if (scanned == 0 || scanned == EOF)
+ scanned = sscanf (numString.c_str (), "%d", &result);
+
+ // If that failed, throw an exception.
+
+ if (scanned == 0 || scanned == EOF)
+ throw 1;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static uint8 PrvGetOneRGB (const StringList& rgbs, int component)
+{
+ // Convert the string to a number.
+
+ int result = ::PrvGetNumber (rgbs[component]);
+
+ // If that failed, or if the resulting number is out of range,
+ // throw an exception indicating an invalid input.
+
+ if (result < 0 || result > 255)
+ throw 1;
+
+ return (uint8) result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static RGBType PrvGetRGB (const StringStringMap& entries, const char* key)
+{
+ RGBType result;
+
+ // Get the string containing the devices.
+
+ string rgbString = entries.find (key)->second;
+
+ // Break it up into parts.
+
+ StringList rgbs;
+ ::SeparateList (rgbs, rgbString, ',');
+
+ // Make sure we have the right number
+
+ if (rgbs.size () != 3)
+ throw 1;
+
+ result.fRed = ::PrvGetOneRGB (rgbs, 0);
+ result.fGreen = ::PrvGetOneRGB (rgbs, 1);
+ result.fBlue = ::PrvGetOneRGB (rgbs, 2);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static EmDeviceList PrvGetDeviceList (const StringStringMap& entries)
+{
+ EmDeviceList result;
+
+ // Get the string containing the devices.
+
+ string devicesString = entries.find ("Devices")->second;
+
+ // Break it up into parts.
+
+ StringList deviceNames;
+ ::SeparateList (deviceNames, devicesString, ',');
+
+ // Iterate over the given device names, and see if they're
+ // supported or valid.
+
+ StringList::iterator iter = deviceNames.begin ();
+ while (iter != deviceNames.end ())
+ {
+ // Get a device name, and remove any leading or trailing whitespace.
+
+ string deviceName = ::Strip (*iter, " \t", true, true);
+
+ // Create a device object from it.
+
+ EmDevice device (deviceName);
+
+ // If the name was accepted, add the device to the list.
+
+ if (device.Supported ())
+ {
+ result.push_back (device);
+ }
+
+ ++iter;
+ }
+
+ // If no valid devices were provided, throw an exception to signal
+ // the caller that a completely invalid list was provided.
+
+ if (result.size () == 0)
+ throw 1;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static SkinElementType PrvGetElementType (const string& s)
+{
+ // Get the element name and try to ID it.
+
+ string eltName = ::Strip (s, " \t", true, true);
+
+ for (SkinElementType ii = kElement_First; ii < kElement_NumElements; ++ii)
+ {
+ if (kElementNames[ii] != NULL &&
+ _stricmp (eltName.c_str (), kElementNames[ii]) == 0)
+ {
+ return ii;
+ }
+ }
+
+ // If we couldn't determine the name, error out.
+
+ throw 1;
+
+ return kElement_None; // (For the compiler)
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static ButtonBounds PrvGetOneElement (const string& s)
+{
+ ButtonBounds result;
+
+ // Break up the string into its parts, which should be an
+ // element name followed by its bounds.
+
+ StringList parts;
+ ::SeparateList (parts, s, ',');
+
+ // Make sure we have the right number of pieces.
+
+ if (parts.size () != 5)
+ throw 1;
+
+ result.fButton = ::PrvGetElementType (parts[0]);
+
+ // Get the bounds
+
+ RectangleType rect;
+ rect.topLeft.x = ::PrvGetNumber (parts[1]);
+ rect.topLeft.y = ::PrvGetNumber (parts[2]);
+ rect.extent.x = ::PrvGetNumber (parts[3]);
+ rect.extent.y = ::PrvGetNumber (parts[4]);
+
+ result.fBounds = EmRect (rect);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static ButtonBoundsList PrvGetElementList (const StringStringMap& entries)
+{
+ ButtonBoundsList result;
+ Bool haveLCD = false;
+ Bool haveTouchScreen = false;
+
+ // Iterate over all of the entries in "entries", looking for ones
+ // that start with "Element".
+
+ StringStringMap::const_iterator iter = entries.begin ();
+ while (iter != entries.end ())
+ {
+ if (::StartsWith (iter->first.c_str (), "Element"))
+ {
+ ButtonBounds elt = ::PrvGetOneElement (iter->second);
+ result.push_back (elt);
+
+ if (elt.fButton == kElement_LCD)
+ haveLCD = true;
+
+ if (elt.fButton == kElement_Touchscreen)
+ haveTouchScreen = true;
+ }
+
+ ++iter;
+ }
+
+ if (!haveLCD || !haveTouchScreen)
+ throw 1;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static void PrvAddSkin (SkinList& skins, StringStringMap& entries,
+ const EmFileRef* file = NULL)
+{
+ // Check for required fields.
+
+ if (entries.find ("Name") == entries.end () ||
+ entries.find ("File1x") == entries.end () ||
+ entries.find ("File2x") == entries.end () ||
+ entries.find ("BackgroundColor") == entries.end () ||
+ entries.find ("HighlightColor") == entries.end () ||
+ entries.find ("Devices") == entries.end ())
+ {
+ return;
+ }
+
+ // Now extract the values.
+
+ try
+ {
+ Skinfo skin;
+
+ skin.fSkinFile = file ? *file : EmFileRef();
+ skin.fName = entries["Name"];
+ skin.fImageName1x = entries["File1x"];
+ skin.fImageName2x = entries["File2x"];
+ skin.fBackgroundColor = ::PrvGetRGB (entries, "BackgroundColor");
+ skin.fHighlightColor = ::PrvGetRGB (entries, "HighlightColor");
+ skin.fDevices = ::PrvGetDeviceList (entries);
+ skin.fButtons = ::PrvGetElementList (entries);
+
+ skins.push_back (skin);
+ }
+ catch (...)
+ {
+ }
+}
+
+static void PrvAddSkin (SkinList& skins, EmStream& skinStream)
+{
+ StringStringMap entries;
+ EmMapFile::Read (skinStream, entries);
+
+ PrvAddSkin (skins, entries);
+}
+
+static void PrvAddSkin (SkinList& skins, const EmFileRef& skinFile)
+{
+ StringStringMap entries;
+ EmMapFile::Read (skinFile, entries);
+
+ PrvAddSkin (skins, entries, &skinFile);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: .
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+static void PrvScanForSkinFiles (SkinList& skins, const EmDirRef& skinDir)
+{
+ EmDirRefList dirs;
+ EmFileRefList files;
+ skinDir.GetChildren (&files, &dirs);
+
+ // Look for any *.skin files in the given directory.
+ {
+ EmFileRefList::iterator iter = files.begin ();
+ while (iter != files.end ())
+ {
+ if (iter->IsType (kFileTypeSkin))
+ {
+ ::PrvAddSkin (skins, *iter);
+ }
+
+ ++iter;
+ }
+ }
+
+ // Now recurse into sub-directories.
+ {
+ EmDirRefList::iterator iter = dirs.begin ();
+ while (iter != dirs.end ())
+ {
+ string name = iter->GetName ();
+ if (name.size () < 2 ||
+ name[0] != '(' ||
+ name[name.size () - 1] != ')')
+ {
+ ::PrvScanForSkinFiles (skins, *iter);
+ }
+
+ ++iter;
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvBuildSkinList
+ *
+ * DESCRIPTION: Create the full list of skins known to the emulator.
+ * This list of skins includes both the built-in ones and
+ * any found on disk.
+ *
+ * PARAMETERS: skins - receives the list of skins. The list of skins
+ * is *added* to this collection; it is not cleared
+ * out first.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void PrvBuildSkinList (SkinList& skins)
+{
+ // If we're a "bound" Poser, the skin list consists of the
+ // skin we're bound to.
+
+ if (gApplication->IsBound ())
+ {
+ Chunk chunk;
+ if (gApplication->GetSkinfoResource (chunk))
+ {
+ EmStreamChunk stream (chunk);
+ ::PrvAddSkin (skins, stream);
+ }
+
+ return;
+ }
+
+ // Look for a sub-directory named "Skins".
+
+ EmDirRef scanDir (EmDirRef::GetEmulatorDirectory (), "Skins");
+
+ if (!scanDir.Exists ())
+ scanDir = EmDirRef (EmDirRef::GetEmulatorDirectory (), "skins");
+
+#if PLATFORM_UNIX
+ // On Unix, also look in the /usr/local/share/pose and /usr/share/pose directories.
+
+ if (!scanDir.Exists ())
+ scanDir = EmDirRef ("/usr/local/share/pose/Skins");
+
+ if (!scanDir.Exists ())
+ scanDir = EmDirRef ("/usr/local/share/pose/skins");
+
+ if (!scanDir.Exists ())
+ scanDir = EmDirRef ("/usr/share/pose/Skins");
+
+ if (!scanDir.Exists ())
+ scanDir = EmDirRef ("/usr/share/pose/skins");
+#endif
+
+ if (scanDir.Exists ())
+ {
+ ::PrvScanForSkinFiles (skins, scanDir);
+ }
+}
+
+
+#pragma mark -
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvSetSkin
+ *
+ * DESCRIPTION: Common low-level routine to setting the current skin.
+ *
+ * PARAMETERS: skin - new skin.
+ *
+ * scale - new scale.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvSetSkin (const EmDevice& device, const Skinfo& skin, ScaleType scale)
+{
+ gCurrentDevice = device;
+ gCurrentSkin = skin;
+ gCurrentScale = scale;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetSkins
+ *
+ * DESCRIPTION: Get the list of available skins for the given device.
+ * Does not include the generic skin.
+ *
+ * PARAMETERS: type - the device for which the list of skins should
+ * be returned. If kDeviceUnspecified, return all
+ * skins for all devices.
+ *
+ * results - receives the list of skins. Any skins are
+ * *added* to this list; the list is not cleared out
+ * first.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvGetSkins (const EmDevice& device, SkinList& results)
+{
+ static SkinList gFullSkinList;
+ static Bool gInitialized;
+
+ if (!gInitialized)
+ {
+ gInitialized = true;
+ ::PrvBuildSkinList (gFullSkinList);
+ }
+
+ SkinList::iterator iter = gFullSkinList.begin ();
+ while (iter != gFullSkinList.end ())
+ {
+ if (!device.Supported () || // Add everything!
+ find (iter->fDevices.begin (), iter->fDevices.end (), device) != iter->fDevices.end ())
+ {
+ results.push_back (*iter);
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetNamedSkin
+ *
+ * DESCRIPTION: Find the Skinfo for the given device and that has the
+ * given name.
+ *
+ * PARAMETERS: type - the device whose skin we're looking for.
+ *
+ * name - the name of the skin to find.
+ *
+ * result - reference to the Skinfo in which to place the
+ * found skin information, if any.
+ *
+ * RETURNED: True if the skin could be found, false othewise.
+ *
+ ***********************************************************************/
+
+Bool PrvGetNamedSkin (const EmDevice& device, const SkinName& name, Skinfo& result)
+{
+ if (name == kGenericSkinName)
+ {
+ ::PrvGetGenericSkin (result);
+ return true;
+ }
+
+ SkinList skins;
+ ::PrvGetSkins (device, skins);
+
+ SkinList::iterator iter = skins.begin();
+ while (iter != skins.end ())
+ {
+ if (iter->fName == name)
+ {
+ result = *iter;
+ return true;
+ }
+
+ ++iter;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetGenericSkin
+ *
+ * DESCRIPTION: Return skin information for the "generic" skin, the one
+ * that is built-in and can be used for any device if a
+ * custom one cannot be found.
+ *
+ * PARAMETERS: skin - reference to the Skinfo in which to place the
+ * default skin information.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvGetGenericSkin (Skinfo& skin)
+{
+ skin.fDevices.clear ();
+ skin.fButtons.clear ();
+
+ skin.fName = kGenericSkinName;
+ skin.fImageName1x = "";
+ skin.fImageName2x = "";
+ skin.fBackgroundColor = kGenericBackgroundColor;
+ skin.fHighlightColor = kGenericHighlightColor;
+
+ for (size_t ii = 0; ii < countof (kGenericButtons); ++ii)
+ {
+ ButtonBoundsX buttonX = kGenericButtons[ii];
+ ButtonBounds button;
+ button.fButton = buttonX.fButton;
+ button.fBounds = EmRect (buttonX.fBounds);
+ skin.fButtons.push_back (button);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetDefaultSkin
+ *
+ * DESCRIPTION: Return default skin information for the given device.
+ * This function returns information in the case that
+ * a skin with a desired name could not be found.
+ *
+ * PARAMETERS: type - the device whose default skin information we want.
+ *
+ * skin - reference to the Skinfo in which to place the
+ * default skin information.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void PrvGetDefaultSkin (const EmDevice& device, Skinfo& skin)
+{
+ SkinList skins;
+ ::PrvGetSkins (device, skins);
+
+ if (skins.size () == 0)
+ {
+ ::PrvGetGenericSkin (skin);
+ }
+ else
+ {
+ skin = skins[0];
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetTouchscreen
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+EmRect PrvGetTouchscreen (void)
+{
+ int index = 0;
+ SkinElementType type;
+ EmRect bounds;
+
+ while (::SkinGetElementInfo (index, type, bounds))
+ {
+ if (type == kElement_Touchscreen)
+ {
+ return bounds;
+ }
+
+ ++index;
+ }
+
+ EmAssert (false);
+
+ // Shut up the compiler
+ return bounds;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvTestPoint
+ *
+ * DESCRIPTION: Test the given point against all of the skin elements.
+ * An optional outset value can be provided which is
+ * used to modify the element bounds before they are
+ * tested.
+ *
+ * PARAMETERS: pt - window location to test.
+ *
+ * outset - outset value to apply to the bounds of all
+ * the skin elements.
+ *
+ * RETURNED: If one contains the given point, return that skin
+ * element. Otherwise, return kElement_Frame.
+ *
+ ***********************************************************************/
+
+SkinElementType PrvTestPoint (const EmPoint& pt, int outset)
+{
+ ButtonBoundsList::iterator iter = gCurrentSkin.fButtons.begin ();
+ while (iter != gCurrentSkin.fButtons.end ())
+ {
+ EmRect bounds = iter->fBounds;
+ bounds = ::SkinScaleUp (bounds);
+ bounds.Inset (-outset, -outset);
+
+ if (bounds.Contains (pt))
+ return iter->fButton;
+
+ ++iter;
+ }
+
+ return kElement_Frame;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetSkinName
+ *
+ * DESCRIPTION: Returns the name of the skin to use for the given
+ * device. The preferences are first queried to see if
+ * there is a skin name registered under any of the
+ * ID strings by which this device is known ("Palm m100",
+ * "m100", "Calvin", etc.). If not, then an empty skin
+ * name is returned.
+ *
+ * PARAMETERS: device - the device object for which the skin is needed.
+ *
+ * RETURNED: The name of the preferred skin for the device, or an
+ * empty skin name if one could not be found.
+ *
+ ***********************************************************************/
+
+SkinName PrvGetSkinName (const EmDevice& device)
+{
+ SkinName result;
+ StringList deviceNames = device.GetIDStrings ();
+ StringList::iterator iter = deviceNames.begin ();
+
+ while (iter != deviceNames.end ())
+ {
+ string prefKey (kPrefKeySkins + ("." + *iter));
+ Preference<SkinName> pref (prefKey.c_str ());
+
+ if (pref.Loaded ())
+ {
+ result = *pref;
+ break;
+ }
+
+ ++iter;
+ }
+
+ return result;
+}
diff --git a/SrcShared/Skins.h b/SrcShared/Skins.h
new file mode 100644
index 0000000..1c8e2e7
--- /dev/null
+++ b/SrcShared/Skins.h
@@ -0,0 +1,95 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _SKINS_H_
+#define _SKINS_H_
+
+#include "EmDevice.h" // EmDevice
+#include "EmRect.h" // EmRect
+#include "EmStructs.h" // RGBType
+
+class EmStream;
+
+enum SkinElementType
+{
+ kElement_First,
+
+ kElement_PowerButton = kElement_First,
+ kElement_UpButton,
+ kElement_DownButton,
+ kElement_App1Button,
+ kElement_App2Button,
+ kElement_App3Button,
+ kElement_App4Button,
+ kElement_CradleButton,
+ kElement_Antenna,
+ kElement_ContrastButton,
+
+ // Symbol-specific
+ kElement_TriggerLeft,
+ kElement_TriggerCenter,
+ kElement_TriggerRight,
+ kElement_UpButtonLeft,
+ kElement_UpButtonRight,
+ kElement_DownButtonLeft,
+ kElement_DownButtonRight,
+
+ kElement_Touchscreen,
+ kElement_LCD,
+ kElement_LED,
+
+ kElement_NumElements,
+
+ kElement_Frame = -1,
+ kElement_None = -2
+};
+
+DEFINE_SCALAR_MODIFIERS (SkinElementType)
+
+
+typedef string SkinName;
+typedef vector<SkinName> SkinNameList;
+
+
+SkinName SkinGetSkinName (const EmDevice&);
+SkinName SkinGetDefaultSkinName (const EmDevice&);
+void SkinGetSkinNames (const EmDevice&, SkinNameList&);
+
+void SkinSetSkin (void);
+void SkinSetSkin (const EmDevice&, ScaleType scale, const SkinName&);
+void SkinSetSkinName (const EmDevice&, const SkinName&);
+
+EmFileRef SkinGetSkinfoFile (void);
+EmFileRef SkinGetSkinFile (void);
+EmFileRef SkinGetSkinFile (ScaleType scale);
+
+EmStream* SkinGetSkinStream (void);
+EmStream* SkinGetSkinStream (ScaleType scale);
+
+Bool SkinValidSkin (const EmDevice&, const SkinName&);
+
+RGBType SkinGetBackgroundColor (void);
+RGBType SkinGetHighlightColor (void);
+
+SkinElementType SkinTestPoint (const EmPoint& windowPt);
+EmPoint SkinWindowToTouchscreen (const EmPoint& windowPt);
+EmPoint SkinTouchscreenToWindow (const EmPoint& lcdPt);
+Bool SkinGetElementInfo (int index, SkinElementType&, EmRect&);
+
+EmPoint SkinScaleDown (const EmPoint&);
+EmRect SkinScaleDown (const EmRect&);
+
+EmPoint SkinScaleUp (const EmPoint&);
+EmRect SkinScaleUp (const EmRect&);
+
+#endif // _SKINS_H_
diff --git a/SrcShared/SocketMessaging.cpp b/SrcShared/SocketMessaging.cpp
new file mode 100644
index 0000000..4a1b9fc
--- /dev/null
+++ b/SrcShared/SocketMessaging.cpp
@@ -0,0 +1,1170 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "SocketMessaging.h"
+
+#include "EmException.h" // EmExceptionReset
+#include "EmSession.h" // EmSessionStopper
+#include "Logging.h" // LogAppendMsg
+
+#include <algorithm> // find()
+
+#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
+#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
+#endif
+
+// ---------------------------------------------------------------------------
+// ¥ Stuff
+// ---------------------------------------------------------------------------
+
+#define PRINTF if (!LogLLDebugger ()) ; else LogAppendMsg
+
+
+// ---------------------------------------------------------------------------
+// ¥ CSocket
+// ---------------------------------------------------------------------------
+
+typedef vector<CSocket*> SocketList;
+static SocketList gSockets;
+static SocketList gSocketsToBeAdded;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::Startup
+ *
+ * DESCRIPTION: Create all the sockets we'll need for the application
+ * and start them listening for clients. Call this once
+ * at application startup.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void CSocket::Startup (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::Shutdown
+ *
+ * DESCRIPTION: Close all the sockets we've created. Call this once at
+ * application shutdown.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void CSocket::Shutdown (void)
+{
+ // Add any sockets waiting to be added to gSockets.
+
+ CSocket::AddPending ();
+
+ SocketList::iterator iter = gSockets.begin ();
+ while (iter != gSockets.end ())
+ {
+ CSocket* s = *iter;
+
+ if (!s->Deleted())
+ {
+ s->Close ();
+ s->Delete();
+ }
+
+ ++iter;
+ }
+
+ CSocket::DeletePending ();
+
+ EmAssert (gSockets.size() == 0);
+ EmAssert (gSocketsToBeAdded.size() == 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::IdleAll
+ *
+ * DESCRIPTION: Idle all of the created sockets.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode CSocket::IdleAll (void)
+{
+ // Prevent recursion
+ static Boolean inIdleAll;
+ if (inIdleAll)
+ return errNone;
+
+ inIdleAll = true;
+
+// PRINTF ("CSocket::IdleAll -- calling AddPending (1)...");
+ CSocket::AddPending ();
+
+// PRINTF ("CSocket::IdleAll -- calling DeletePending (1)...");
+ CSocket::DeletePending ();
+
+ // Iterate over all the (non-deleted) sockets and Idle them.
+
+ ErrCode err = errNone;
+ SocketList::iterator iter = gSockets.begin ();
+
+ while (iter != gSockets.end ())
+ {
+ if (!(*iter)->Deleted ())
+ {
+// PRINTF ("CSocket::IdleAll -- Idling (0x%08X)...", (*iter));
+ err = (*iter)->Idle ();
+ if (err != errNone)
+ break;
+ }
+
+ ++iter;
+ }
+
+// PRINTF ("CSocket::IdleAll -- calling AddPending (2)...");
+ CSocket::AddPending ();
+
+// PRINTF ("CSocket::IdleAll -- calling DeletePending (2)...");
+ CSocket::DeletePending ();
+
+ inIdleAll = false;
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::AddPending
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void CSocket::AddPending (void)
+{
+ SocketList::iterator iter = gSocketsToBeAdded.begin ();
+ while (iter != gSocketsToBeAdded.end ())
+ {
+ gSockets.push_back (*iter);
+ ++iter;
+ }
+
+ gSocketsToBeAdded.clear();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::DeletePending
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+
+void CSocket::DeletePending (void)
+{
+ // Delete any sockets pending to be deleted.
+
+ SocketList::iterator iter = gSockets.begin ();
+
+ while (iter != gSockets.end ())
+ {
+ if ((*iter)->Deleted ())
+ {
+ delete *iter;
+ iter = gSockets.erase(iter);
+ continue;
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::CSocket
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+CSocket::CSocket (void) :
+ fDeleted (false)
+{
+ gSocketsToBeAdded.push_back (this);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::~CSocket
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+CSocket::~CSocket (void)
+{
+ EmAssert (fDeleted);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::Delete
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void CSocket::Delete (void)
+{
+ PRINTF ("CSocket(0x%08X)::Delete...", this);
+// EmAssert (!fDeleted);
+ fDeleted = true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::Deleted
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool CSocket::Deleted (void) const
+{
+ return fDeleted;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::ShortPacketHack
+ *
+ * DESCRIPTION: In general, we should be using the full Serial Link
+ * Protocol format, which includes a header, body, and
+ * footer. However, for stupid reasons, I was too lazy
+ * to implement the protocol for all transports, and
+ * omitted the footer and didn't fill in the header
+ * checksum field. The SLP sub-system needs to know if
+ * the guy at the other end of this socket is expecting
+ * the full protocol or just the abbreviated one.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True for full packets (checksums and footers).
+ *
+ ***********************************************************************/
+
+Bool CSocket::ShortPacketHack (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CSocket::ByteswapHack
+ *
+ * DESCRIPTION: In general, all data is sent in Big-Endian format.
+ * However, due to a bug, some fields in some packets
+ * didn't get byteswapped. This bug was fixed when using
+ * TCP sockets as the transport medium, but people
+ * connecting via other methods already expect the broken
+ * format, so we have to still support that for them.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True for mis-byteswapped packets.
+ *
+ ***********************************************************************/
+
+Bool CSocket::ByteswapHack (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ CTCPSocket
+// ---------------------------------------------------------------------------
+
+enum { kSocketState_Unconnected, kSocketState_Listening, kSocketState_Connected };
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::CTCPSocket
+ *
+ * DESCRIPTION: Creates and initializes the socket object. Nothing else
+ * is attempted at this time (that is, no underlying
+ * SOCKET objects are created, no listening is performed,
+ * no connections are attempted).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+CTCPSocket::CTCPSocket (EventCallback fn, int port) :
+ fEventCallback (fn),
+ fPort (port),
+ fSocketState (kSocketState_Unconnected),
+ fListeningSocket (INVALID_SOCKET),
+ fConnectedSocket (INVALID_SOCKET)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::~CTCPSocket
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+CTCPSocket::~CTCPSocket (void)
+{
+ EmAssert (fSocketState == kSocketState_Unconnected);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::Open
+ *
+ * DESCRIPTION: Starts up the sockets mechanism for communicating with
+ * the debugger. It first attempts to connect to the
+ * debugger, assuming that it's been started up and issued
+ * a listen(). If that fails, it creates a socket to
+ * listen on itself.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::Open (void)
+{
+ PRINTF ("CTCPSocket(0x%08X)::Open...", this);
+
+ EmAssert (fSocketState == kSocketState_Unconnected);
+ EmAssert (fListeningSocket == INVALID_SOCKET);
+ EmAssert (fConnectedSocket == INVALID_SOCKET);
+
+ int result;
+ sockaddr addr;
+
+#if TRY_TO_CONNECT_BEFORE_LISTENING
+ fConnectedSocket = this->NewSocket ();
+ if (fConnectedSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...NewSocket failed for connecting socket; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+
+ // Attempt to connect to that address (in case anyone is listening).
+
+ result = connect (fConnectedSocket, this->FillAddress (&addr, true), sizeof(addr));
+ if (result == 0)
+ {
+ PRINTF ("...connected!");
+
+ fSocketState = kSocketState_Connected;
+ return errNone;
+ }
+
+ // Didn't connect; attempt to bind to that address so that we
+ // can listen for connections.
+
+ closesocket (fConnectedSocket);
+ fConnectedSocket = INVALID_SOCKET;
+#endif
+
+ fListeningSocket = this->NewSocket ();
+ if (fListeningSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...NewSocket failed for listening socket; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ result = bind (fListeningSocket, this->FillAddress (&addr, false), sizeof(addr));
+ if (result != 0)
+ {
+ PRINTF ("...bind failed; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ // Start listening for a connection.
+
+ result = listen (fListeningSocket, 1);
+ if (result != 0)
+ {
+ PRINTF ("...listen failed; result = %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ PRINTF ("...listening for connection");
+
+ fSocketState = kSocketState_Listening;
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::Close
+ *
+ * DESCRIPTION: Closes the sockets session. Closes all sockets, sets
+ * our state to unconnected, and closes down the sockets
+ * library (on Windows).
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::Close (void)
+{
+ PRINTF ("CTCPSocket(0x%08X)::Close...", this);
+
+ Bool needDisconnectNotification = false;
+
+ if (fConnectedSocket != INVALID_SOCKET)
+ {
+ closesocket (fConnectedSocket);
+ fConnectedSocket = INVALID_SOCKET;
+ PRINTF ("...closed connection port...");
+ needDisconnectNotification = fSocketState == kSocketState_Connected;
+ }
+
+ if (fListeningSocket != INVALID_SOCKET)
+ {
+ closesocket (fListeningSocket);
+ fListeningSocket = INVALID_SOCKET;
+ PRINTF ("...closed listening port...");
+ }
+
+ fSocketState = kSocketState_Unconnected;
+
+ // Tell the callback function that the socket is now disconnected
+ // (and not even listening). Send out this notification at this
+ // point so that the callback function can put the socket back into
+ // the listening state if it wants.
+
+ if (needDisconnectNotification && fEventCallback)
+ {
+ fEventCallback (this, kDisconnected);
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::Idle
+ *
+ * DESCRIPTION: Perform idle-time maintenance on this socket. Mostly
+ * this means looking for any newly-arrived data.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::Idle (void)
+{
+ if (this->HasUnreadData (0))
+ {
+ if (fEventCallback)
+ {
+ try
+ {
+ fEventCallback (this, kDataReceived);
+ }
+ catch (const EmExceptionReset& e)
+ {
+ EmSessionStopper stopper (gSession, kStopNow);
+ e.Display ();
+ }
+ }
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::Write
+ *
+ * DESCRIPTION: Writes data out to the buffer.
+ *
+ * PARAMETERS: buffer - pointer to the data to be written.
+ *
+ * amountToWrite - number of bytes in the buffer.
+ *
+ * RETURNED: Nothing.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::Write (const void* buffer, long amountToWrite, long* amtWritten)
+{
+ PRINTF ("CTCPSocket(0x%08X)::Write...", this);
+
+ long dummy;
+ if (!amtWritten)
+ amtWritten = &dummy;
+
+ *amtWritten = 0;
+
+ if (this->CheckConnection ())
+ {
+ if (LogLLDebuggerData ())
+ LogAppendData (buffer, amountToWrite, "...writing %ld bytes.", amountToWrite);
+ else
+ PRINTF ("...writing %ld bytes.", amountToWrite);
+
+ while (amountToWrite)
+ {
+ int sentThisTime = send (fConnectedSocket,
+ &((char*) buffer)[*amtWritten],
+ amountToWrite, 0);
+
+ if (sentThisTime == SOCKET_ERROR )
+ {
+ PRINTF ("...error calling send: %08X", this->GetError ());
+
+ return this->ErrorOccurred ();
+ }
+
+ *amtWritten += sentThisTime;
+ amountToWrite -= sentThisTime;
+ }
+ }
+ else
+ {
+ PRINTF ("...no connection.");
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::Read
+ *
+ * DESCRIPTION: Read bytes from the socket. At most sizeOfBuffer bytes
+ * are read. It is assumed that HasUnreadData has already
+ * been called and returned true.
+ *
+ * PARAMETERS: buffer - pointer to the buffer to put the data.
+ *
+ * sizeOfBuffer - size of the buffer.
+ *
+ * RETURNED: The actual number of bytes read..
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::Read (void* buffer, long sizeOfBuffer, long* amtRead)
+{
+ PRINTF ("CTCPSocket(0x%08X)::Read...", this);
+
+ long dummy;
+ if (!amtRead)
+ amtRead = &dummy;
+
+ *amtRead = 0;
+
+ if (this->CheckConnection ())
+ {
+ while (*amtRead < sizeOfBuffer)
+ {
+ long r = recv (fConnectedSocket, ((char*) buffer) + *amtRead, sizeOfBuffer - *amtRead, 0);
+
+ // More from the sockets manual for the select() function:
+ //
+ // For connection-oriented sockets, readability can also indicate that
+ // a request to close the socket has been received from the peer. If the
+ // virtual circuit was closed gracefully, and all data was received, then
+ // a recv will return immediately with zero bytes read. If the virtual
+ // circuit was reset, then a recv will complete immediately with an error
+ // code such as WSAECONNRESET. The presence of OOB data will be checked
+ // if the socket option SO_OOBINLINE has been enabled (see setsockopt).
+
+ if (r == 0 && *amtRead == 0)
+ {
+ // OK, the connection was closed on the other side. Close it on
+ // our side, too.
+
+ PRINTF ("...found a closed connection.");
+ this->Close ();
+ return errNone;
+ }
+
+ if (r == SOCKET_ERROR)
+ {
+ PRINTF ("...error calling recv: %08X", this->GetError ());
+
+ return this->ErrorOccurred ();
+ }
+
+ if (r > 0)
+ {
+ *amtRead += r;
+
+ if (LogLLDebuggerData ())
+ LogAppendData (((char*) buffer) + *amtRead - r, r,
+ "...got %ld of %ld bytes of data.", *amtRead, sizeOfBuffer);
+ else
+ PRINTF ("...got %ld of %ld bytes of data.", *amtRead, sizeOfBuffer);
+ }
+ }
+ }
+ else
+ {
+ PRINTF ("...no connection.");
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::ConnectPending
+ *
+ * DESCRIPTION: Returns whether or not there is a pending connect. This
+ * function can be called at any time. It will only return
+ * true if there is a non-blocking listen issued with a
+ * pending connect that we haven't yet accepted.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if there is a pending connect. If there is, the
+ * caller should next call CTCPSocket::AcceptConnection.
+ *
+ ***********************************************************************/
+
+Bool CTCPSocket::ConnectPending (void)
+{
+ // From the sockets manual for the select() function:
+ //
+ // The parameter readfds identifies the sockets that are to be
+ // checked for readability. If the socket is currently in the
+ // listen state, it will be marked as readable if an incoming
+ // connection request has been received such that an accept is
+ // guaranteed to complete without blocking. For other sockets,
+ // readability means that queued data is available for reading
+ // such that a call to recv, WSARecv, WSARecvFrom, or recvfrom
+ // is guaranteed not to block.
+
+ Bool havePendingConnect = false;
+
+#if 0
+ if (fSocketState == kSocketState_Unconnected)
+ {
+ PRINTF ("CTCPSocket(0x%08X)::ConnectPending...", this);
+ PRINTF ("...starting to listen for connection.");
+
+ this->Open ();
+ }
+#endif
+
+ if (fSocketState == kSocketState_Listening)
+ {
+ EmAssert (fListeningSocket != INVALID_SOCKET);
+ EmAssert (fConnectedSocket == INVALID_SOCKET);
+
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+ FD_SET (fListeningSocket, &readfds);
+
+ timeval timeout = {0, 0}; // Don't wait at all
+
+ int result = select (fListeningSocket + 1, &readfds, NULL, NULL, &timeout);
+
+ if (result > 0 && FD_ISSET (fListeningSocket, &readfds))
+ {
+ PRINTF ("CTCPSocket(0x%08X)::ConnectPending...", this);
+ PRINTF ("...have pending connection.");
+
+ havePendingConnect = true;
+ }
+ else if (result == SOCKET_ERROR)
+ {
+ PRINTF ("CTCPSocket(0x%08X)::ConnectPending...", this);
+ PRINTF ("...error calling select: %08X", this->GetError ());
+
+ result = this->GetError ();
+ }
+ else if (result > 0)
+ {
+ PRINTF ("CTCPSocket(0x%08X)::ConnectPending...", this);
+ PRINTF ("...fell through cases in kSocketState_Listening");
+ }
+ }
+
+ return havePendingConnect;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::AcceptConnection
+ *
+ * DESCRIPTION: Accepts a pending connection. Assumes that
+ * ConnectPending has already been called and returned
+ * true. After this, the socket connection should be open
+ * for business.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::AcceptConnection (void)
+{
+ PRINTF ("CTCPSocket(0x%08X)::AcceptConnection...", this);
+
+ EmAssert (fSocketState == kSocketState_Listening);
+ EmAssert (fListeningSocket != INVALID_SOCKET);
+ EmAssert (fConnectedSocket == INVALID_SOCKET);
+
+ sockaddr addr;
+ socklen_t addr_len;
+
+ memset (&addr, 0, sizeof (addr));
+ addr_len = sizeof(addr);
+
+ fConnectedSocket = accept (fListeningSocket, &addr, &addr_len);
+
+ if (fConnectedSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...error calling accept: %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+ closesocket (fListeningSocket);
+ fListeningSocket = INVALID_SOCKET;
+
+ // Set the socket to not use the "Nagle delay algorithm" that clumps
+ // batches of small writes together into one big send.
+
+ protoent* protocolEntity = getprotobyname ("tcp");
+ if (!protocolEntity)
+ {
+ PRINTF ("...error calling getprotobyname: %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+
+#ifdef TCP_NODELAY
+ int tmp = 1;
+ if (setsockopt (fConnectedSocket, protocolEntity->p_proto, TCP_NODELAY, (char*) &tmp, sizeof (tmp)))
+ {
+ PRINTF ("...error calling setsockopt: %08X", this->GetError ());
+ return this->ErrorOccurred ();
+ }
+#endif
+
+ PRINTF ("...accepted the connection.");
+
+ fSocketState = kSocketState_Connected;
+
+ if (fEventCallback)
+ {
+ fEventCallback (this, kConnected);
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::IsConnected
+ *
+ * DESCRIPTION: Returns whether or not we have a live connection to an
+ * external debugger via a socket. This function can be
+ * called at any time.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+Bool CTCPSocket::IsConnected (void)
+{
+ // If we thought we were connected, see if we still are.
+
+ if (fSocketState == kSocketState_Connected)
+ {
+ // From the sockets manual for the select() function:
+ //
+ // If a socket is processing a connect call (nonblocking), a socket is
+ // writable if the connection establishment successfully completes. If
+ // the socket is not processing a connect call, writability means a send,
+ // sendto, or WSASendto are guaranteed to succeed.
+
+ fd_set writefds;
+
+ FD_ZERO (&writefds);
+ FD_SET (fConnectedSocket, &writefds);
+
+ timeval timeout = {0, 0}; // Don't wait at all
+
+ int result = select (fConnectedSocket+1, NULL, &writefds, NULL, &timeout);
+
+ Bool isConnected = result > 0 && FD_ISSET (fConnectedSocket, &writefds);
+
+ // If we're no longer connected, update our internal state.
+
+ if (!isConnected)
+ {
+ PRINTF ("CTCPSocket(0x%08X)::IsConnected...", this);
+ PRINTF ("...found a broken connection, or error calling select: %08X", this->GetError ());
+
+ this->ErrorOccurred ();
+ }
+ }
+
+ return fSocketState == kSocketState_Connected;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::CheckConnection
+ *
+ * DESCRIPTION: Attempt to ensure that a connection is in place.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if a connection is in place. False otherwise.
+ *
+ ***********************************************************************/
+
+Bool CTCPSocket::CheckConnection (void)
+{
+ if (!this->IsConnected() && this->ConnectPending ())
+ {
+ this->AcceptConnection ();
+ }
+
+ return this->IsConnected ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::HasUnreadData
+ *
+ * DESCRIPTION: Returns whether or not there is data to be read from
+ * the socket.
+ *
+ * PARAMETERS: msecs - time to wait in milliseconds for any data.
+ *
+ * RETURNED: True if there is data to be read. There is no way to
+ * get how many bytes are currently in the buffer.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+Bool CTCPSocket::HasUnreadData (long msecs)
+{
+ Bool hasData = false;
+
+ // From the sockets manual for the select() function:
+ //
+ // The parameter readfds identifies the sockets that are to be
+ // checked for readability. If the socket is currently in the
+ // listen state, it will be marked as readable if an incoming
+ // connection request has been received such that an accept is
+ // guaranteed to complete without blocking. For other sockets,
+ // readability means that queued data is available for reading
+ // such that a call to recv, WSARecv, WSARecvFrom, or recvfrom
+ // is guaranteed not to block.
+
+ if (this->CheckConnection ())
+ {
+ EmAssert (fSocketState == kSocketState_Connected);
+
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+ FD_SET (fConnectedSocket, &readfds);
+
+ timeval timeout = {msecs / 1000, msecs * 1000};
+
+ int result = select (fConnectedSocket+1, &readfds, NULL, NULL, &timeout);
+
+ if (result > 0 && FD_ISSET (fConnectedSocket, &readfds))
+ {
+ PRINTF ("CTCPSocket(0x%08X)::HasUnreadData...", this);
+ PRINTF ("...has pending data.");
+
+ hasData = true;
+ }
+ else if (result == SOCKET_ERROR)
+ {
+ PRINTF ("CTCPSocket(0x%08X)::HasUnreadData...", this);
+ PRINTF ("...error calling select: %08X", this->GetError ());
+
+ this->ErrorOccurred ();
+ return false;
+ }
+ }
+
+ return hasData;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::NewSocket
+ *
+ * DESCRIPTION: Creates and returns a new socket configured the way we
+ * like it. The way we like it is: reusable after it's
+ * closed, uses "keep alive" packets, and non-blocking.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The created socket, or INVALID_SOCKET on error.
+ *
+ * On any error, the sub-system will be closed down. All
+ * sockets will be closed and the state will be set to
+ * unconnected.
+ *
+ ***********************************************************************/
+
+SOCKET CTCPSocket::NewSocket (void)
+{
+ PRINTF ("CTCPSocket(0x%08X)::NewSocket...", this);
+
+ int tmp;
+ int result;
+
+ SOCKET newSocket = socket (AF_INET, SOCK_STREAM, 0);
+ if (newSocket == INVALID_SOCKET)
+ {
+ PRINTF ("...error calling socket: %08X", this->GetError ());
+ goto Error;
+ }
+
+ // Allow rapid reuse of this port.
+
+ tmp = 1;
+ result = setsockopt (newSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &tmp, sizeof(tmp));
+ if (result != 0)
+ {
+ PRINTF ("...error calling setsockopt (SO_REUSEADDR): %08X", this->GetError ());
+ goto Error;
+ }
+
+ // Enable TCP keep alive process.
+
+ tmp = 1;
+ result = setsockopt (newSocket, SOL_SOCKET, SO_KEEPALIVE, (char*) &tmp, sizeof(tmp));
+ if (result != 0)
+ {
+ PRINTF ("...error calling setsockopt (SO_KEEPALIVE): %08X", this->GetError ());
+ goto Error;
+ }
+
+ return newSocket;
+
+Error:
+ if (newSocket != INVALID_SOCKET)
+ {
+ closesocket (newSocket);
+ }
+
+ return INVALID_SOCKET;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::FillAddress
+ *
+ * DESCRIPTION: Fill in a sockaddr data structure with values
+ * appropriate for connecting. For now, this is an
+ * Internet address on the local machine with port 2000.
+ *
+ * PARAMETERS: addr - the sockaddr to fill in.
+ *
+ * RETURNED: The same sockaddr passed in.
+ *
+ ***********************************************************************/
+
+sockaddr* CTCPSocket::FillAddress (sockaddr* addr, bool forConnect)
+{
+ PRINTF ("CTCPSocket(0x%08X)::FillAddress...", this);
+
+ sockaddr_in* addr_in = (sockaddr_in*) addr;
+
+#ifdef HAVE_SIN_LEN
+ addr_in->sin_len = sizeof (*addr_in);
+#endif
+ addr_in->sin_family = AF_INET;
+ addr_in->sin_port = htons (fPort);
+ addr_in->sin_addr.s_addr = htonl (forConnect ? INADDR_LOOPBACK : INADDR_ANY);
+
+ return addr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::ErrorOccurred
+ *
+ * DESCRIPTION: Handles any internal errors.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::ErrorOccurred (void)
+{
+ ErrCode result = this->GetError ();
+
+ this->Close ();
+
+ return result; // Return the original error code.
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: CTCPSocket::GetError
+ *
+ * DESCRIPTION: Returns the error code for the last operation.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The error code as returned by WSAGetLastError (on
+ * Windows) or errno (on the Mac or UNIX).
+ *
+ ***********************************************************************/
+
+ErrCode CTCPSocket::GetError (void)
+{
+#if defined (_WIN32)
+ return (ErrCode) ::WSAGetLastError ();
+#else
+ return (ErrCode) errno;
+#endif
+}
diff --git a/SrcShared/SocketMessaging.h b/SrcShared/SocketMessaging.h
new file mode 100644
index 0000000..69f94b7
--- /dev/null
+++ b/SrcShared/SocketMessaging.h
@@ -0,0 +1,95 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _SOCKETMESSAGING_H_
+#define _SOCKETMESSAGING_H_
+
+
+struct sockaddr;
+
+
+class CSocket
+{
+ public:
+ enum { kConnected, kDataReceived, kDisconnected };
+ typedef void (*EventCallback) (CSocket*, int event);
+
+ public:
+ static void Startup (void);
+ static void Shutdown (void);
+ static ErrCode IdleAll (void);
+
+ public:
+ CSocket (void);
+
+ // Call Delete() instead of the destructor. Our architecture
+ // is such that sockets can delete themselves while IdleAll
+ // is executing. Doing that causes IdleAll to freak out,
+ // so we have Delete() in order to defer the actual deletion.
+ void Delete (void);
+ Bool Deleted (void) const;
+
+ virtual ErrCode Open (void) = 0;
+ virtual ErrCode Close (void) = 0;
+ virtual ErrCode Write (const void* buffer, long amountToWrite, long* amtWritten) = 0;
+ virtual ErrCode Read (void* buffer, long sizeOfBuffer, long* amtRead) = 0;
+ virtual Bool HasUnreadData (long timeout) = 0;
+ virtual ErrCode Idle (void) = 0;
+
+ virtual Bool ShortPacketHack (void);
+ virtual Bool ByteswapHack (void);
+
+ protected:
+ virtual ~CSocket (void);
+
+ static void AddPending (void);
+ static void DeletePending (void);
+
+ private:
+ Bool fDeleted;
+};
+
+class CTCPSocket : public CSocket
+{
+ public:
+ CTCPSocket (EventCallback, int port);
+ virtual ~CTCPSocket (void);
+
+ virtual ErrCode Open (void);
+ virtual ErrCode Close (void);
+ virtual ErrCode Write (const void* buffer, long amountToWrite, long* amtWritten);
+ virtual ErrCode Read (void* buffer, long sizeOfBuffer, long* amtRead);
+ virtual Bool HasUnreadData (long timeout);
+ virtual ErrCode Idle (void);
+
+ Bool ConnectPending (void);
+ ErrCode AcceptConnection (void);
+ Bool IsConnected (void);
+ Bool CheckConnection (void);
+
+ protected:
+ SOCKET NewSocket (void);
+ sockaddr* FillAddress (sockaddr* addr, bool forConnect);
+ ErrCode ErrorOccurred (void);
+ ErrCode GetError (void);
+
+ EventCallback fEventCallback;
+ int fPort;
+
+ int fSocketState;
+ SOCKET fListeningSocket;
+ SOCKET fConnectedSocket;
+};
+
+#endif /* _SOCKETMESSAGING_H_ */
+
diff --git a/SrcShared/Startup.cpp b/SrcShared/Startup.cpp
new file mode 100644
index 0000000..a9150fa
--- /dev/null
+++ b/SrcShared/Startup.cpp
@@ -0,0 +1,1642 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Startup.h"
+
+#include "EmDocument.h" // EmDocument::AskNewSession
+#include "EmPalmStructs.h" // EmProxyDatabaseHdrType
+#include "EmSession.h" // gSession, EmSessionStopper
+#include "EmStreamFile.h" // EmStreamFile
+#include "Hordes.h" // Hordes::SetGremlinsHome
+#include "Miscellaneous.h" // IsExecutable, GetLoadableFileList
+#include "Platform.h" // ForceStartupScreen
+#include "PreferenceMgr.h" // Preference
+#include "Strings.r.h" // kStr_Autoload, etc.
+
+#include <algorithm> // find()
+#include <string>
+#include <utility> // make_pair()
+#include <vector>
+
+// Startup actions.
+//static Bool gAskWhatToDo;
+static Bool gCreateSession;
+static Bool gOpenSession;
+static Bool gMinimize;
+
+// Post-startup actions.
+static Bool gStartNewHorde;
+static Bool gHordeQuitWhenDone;
+static Bool gMinimizeQuitWhenDone;
+// Quit actions.
+static Bool gQuitOnExit;
+
+// Action-specific data.
+static Configuration gCfg; // For CreateSession.
+static EmFileRef gSessionOpenRef; // For OpenSession.
+static EmFileRef gMinimizeRef; // For Minimize
+static HordeInfo gHorde; // For StartNewGremlin
+static StringList gHordeApps; // For StartNewGremlin
+
+ // These are the files listed on the command line.
+static string gAutoRunApp;
+static EmFileRefList gAutoLoadFiles1;
+//static EmFileRefList gAutoRunFiles1;
+//static EmFileRefList gAutoRunAndQuitFiles1;
+
+ // These are the files found in the Auto* directories.
+static EmFileRefList gAutoLoadFiles2;
+static EmFileRefList gAutoRunFiles2;
+static EmFileRefList gAutoRunAndQuitFiles2;
+
+
+// These are the keys we use when tracking what the user has specified.
+
+static const char kOptPSF[] = "psf";
+static const char kOptROM[] = "rom";
+static const char kOptRAM[] = "ram";
+static const char kOptDevice[] = "device";
+static const char kOptSkin[] = "skin";
+static const char kOptLoad[] = "load";
+static const char kOptRun[] = "run";
+static const char kOptMinimize[] = "minimize";
+static const char kOptQuitOnExit[] = "quit_on_exit";
+static const char kOptPreference[] = "preference";
+static const char kOptHordeFirst[] = "horde_first";
+static const char kOptHordeLast[] = "horde_last";
+static const char kOptHordeApps[] = "horde_apps";
+static const char kOptHordeSaveDir[] = "horde_save_dir";
+static const char kOptHordeSaveFreq[] = "horde_save_freq";
+static const char kOptHordeDepthMax[] = "horde_depth_max";
+static const char kOptHordeDepthSwitch[] = "horde_depth_switch";
+static const char kOptHordeQuitWhenDone[] = "horde_quit_when_done";
+
+
+// These are the options the user can specify on the command line.
+
+static const struct
+{
+ const char* option;
+ const char* optKey;
+ int optType; // 0 == no parameter, 1 = has parameter
+}
+kOptionMap [] =
+{
+ { "-psf", kOptPSF, 1 },
+ { "-rom", kOptROM, 1 },
+ { "-ram", kOptRAM, 1 },
+ { "-ram_size", kOptRAM, 1 },
+ { "-device", kOptDevice, 1 },
+ { "-skin", kOptSkin, 1 },
+ { "-silkscreen", kOptSkin, 1 },
+ { "-load_apps", kOptLoad, 1 },
+ { "-run_app", kOptRun, 1 },
+ { "-minimize", kOptMinimize, 1 },
+ { "-quit_on_exit", kOptQuitOnExit, 0 },
+ { "-preference", kOptPreference, 1 },
+ { "-pref", kOptPreference, 1 },
+ { "-d", kOptPreference, 1 },
+ { "-horde", kOptHordeFirst, 1 },
+ { "-horde_first", kOptHordeFirst, 1 },
+ { "-horde_last", kOptHordeLast, 1 },
+ { "-horde_apps", kOptHordeApps, 1 },
+ { "-horde_save_dir", kOptHordeSaveDir, 1 },
+ { "-horde_save_freq", kOptHordeSaveFreq, 1 },
+ { "-horde_depth_max", kOptHordeDepthMax, 1 },
+ { "-horde_depth_switch", kOptHordeDepthSwitch, 1 },
+ { "-horde_quit_when_done", kOptHordeQuitWhenDone, 0 }
+};
+
+
+
+
+// Handy macro for helping us find and access options in the OptionList.
+// For the option with the base name "name", this macro defines:
+//
+// "iter<name>" An iterator pointing to the named OptionList entry.
+// "have<name>" A bool that says whether the iterator points to
+// something valid.
+// "opt<name>" A string reference that refers to the option value
+// if "have<name>" is true.
+
+#define DEFINE_VARS(name) \
+ OptionList::iterator iter##name = options.find(kOpt##name); \
+ Bool have##name = iter##name != options.end(); \
+ string& opt##name = iter##name->second
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvGetDatabaseInfosFromAppNames
+ *
+ * DESCRIPTION: Given a list of application names (as determined either
+ * by their 'tAIN' resources or their database names) and
+ * return AppInfos for all applications installed in the
+ * system with those names.
+ *
+ * PARAMETERS: names - the StringList with the names of the applications
+ * to search for. *All* executables are considered,
+ * includes .prc's and .pqa's.
+ *
+ * results - the DatabaseInfoList to receive the DatabaseInfos of
+ * the executables with a name that appears in the
+ * "names" collection.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::PrvGetDatabaseInfosFromAppNames (const StringList& names, DatabaseInfoList& results)
+{
+ StringList namesCopy (names);
+
+ if (!namesCopy.empty())
+ {
+ // If the string list begins with a "-", then the list is
+ // a list of files to be *skipped*.
+
+ Bool mustBeFound = true;
+ string firstName = namesCopy[0];
+ if (firstName[0] == '-')
+ {
+ mustBeFound = false;
+ firstName.erase (firstName.begin ());
+ namesCopy[0] = firstName;
+ }
+
+ // Get a list of installed applications.
+
+ DatabaseInfoList dbInfos;
+ ::GetDatabases (dbInfos, kApplicationsOnly);
+
+ // For each application in the list we just got, see if it was
+ // specified in the user's name list.
+
+ DatabaseInfoList::iterator infoIter = dbInfos.begin();
+ while (infoIter != dbInfos.end())
+ {
+ string appInfoName(infoIter->name);
+ StringList::const_iterator nameIter = find (namesCopy.begin(), namesCopy.end(), appInfoName);
+ Bool found = nameIter != namesCopy.end();
+
+ // Check to see if one of two things are true:
+ //
+ // * The installed application is on the include list.
+ // * The installed application in not on the exclude list.
+ //
+ // If either case is true, push it onto our "results" list.
+
+ if (found == mustBeFound)
+ {
+ results.push_back (*infoIter);
+ }
+
+ ++infoIter;
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvDontUnderstand
+ * FUNCTION: PrvMissingArgument
+ * FUNCTION: PrvInvalidRAMSize
+ * FUNCTION: PrvInvalidSkin
+ *
+ * DESCRIPTION: Display error messages concerning poor, misunderstood
+ * switches and their parameters.
+ *
+ * PARAMETERS: The switch ("-foo") guy who caused the problem.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+static string PrvWrap (const string& s, int chars_per_line)
+{
+ string result (s);
+ int index = 0;
+ int last_space = -1;
+ int last_cr = -1;
+
+ while (index < (int) result.size ())
+ {
+ char ch = result[index];
+
+ if (ch == ' ')
+ {
+ last_space = index;
+ }
+ else if (ch == '\n')
+ {
+ last_cr = index;
+ last_space = -1;
+ }
+
+ // Have we accumulated enough characters?
+
+ if (index - last_cr >= chars_per_line)
+ {
+ EmAssert (last_space >= 0);
+
+ result [last_space] = '\n';
+ last_cr = last_space;
+ last_space = -1;
+ }
+
+ ++index;
+ }
+
+ return result;
+}
+
+
+void Startup::PrvError (const char* msg)
+{
+#if PLATFORM_UNIX
+ printf ("%s\n", msg);
+#else
+ EmDlg::DoCommonDialog (msg, kDlgFlags_OK);
+#endif
+}
+
+void Startup::PrvDontUnderstand (const char* arg)
+{
+ char buffer[200];
+ sprintf (buffer, "Don't understand the command line parameter \"%s\".", arg);
+ Startup::PrvError (buffer);
+}
+
+void Startup::PrvMissingArgument (const char* arg)
+{
+ char buffer[200];
+ sprintf (buffer, "The command line parameter \"%s\" needs to be followed by an "
+ "argument (\"No, it doesn't.\" \"Yes, it does.\" \"No, it doesn't...\").", arg);
+ Startup::PrvError (buffer);
+}
+
+void Startup::PrvInvalidRAMSize (const char* arg)
+{
+ char buffer[200];
+ sprintf (buffer, "\"%s\" is an invalid RAM size. Specify 128, 256, 512, 1024, "
+ "2048, 4096, 8192, or 16384.", arg);
+ Startup::PrvError (buffer);
+}
+
+void Startup::PrvInvalidSkin (const char* argSkin, const char* argDevice)
+{
+ char buffer[200];
+ sprintf (buffer, "The skin \"%s\" cannot be used with the device \"%s\".", argSkin, argDevice);
+ Startup::PrvError (buffer);
+}
+
+void Startup::PrvInvalidPreference (const char* pref)
+{
+ char buffer[200];
+ sprintf (buffer, "Don't understand the preference parameter \"%s\".", pref);
+ Startup::PrvError (buffer);
+}
+
+void Startup::PrvPrintHelp (void)
+{
+ printf ("Options are:\n");
+ printf (" -psf <file> Session file to open at startup\n");
+ printf (" -rom <file> ROM file to use at startup\n");
+ printf (" -ram_size <size> Amount of RAM (in K) to emulate at startup\n");
+ printf (" -device <name> Device type to use at startup\n");
+ printf (" -skin <name> Name of skin to use for the device\n");
+ printf (" -load_apps <name(s)> Comma-seperated list of names of .prc files to load at startup\n");
+ printf (" -run_app <name> Name of file to automatically run at startup\n");
+ printf (" -quit_on_exit Cause Poser to quit after -run application exits\n");
+ printf (" -pref <key=value> Change a preference setting\n");
+ printf ("\n");
+
+ Platform::PrintHelp ();
+
+ string help (
+ "\n"
+ "Specifying the -psf option on the command line causes Poser to attempt "
+ "to load and run the specified session file at startup.\n"
+ "\n"
+ "Specifying the -rom, -ram_size, and -device options on the command line "
+ "causes Poser to create a new session based on those specifications. If "
+ "only some of those three options are specified, then Poser will present "
+ "a New Session dialog with the specified items already filled in.\n"
+ "\n"
+ "The parameter passed with the -skin option is the name "
+ "of the silkscreen as defined in the .skin file.\n"
+ "\n"
+ "The parameter passed with the -load_apps option is a comma-seperated list "
+ "of file names. The parameter passed with the -run_app option is the name "
+ "of the Palm OS application itself, not the name of the file it came from. "
+ "This is generally the name that appears in the Palm OS Launcher.\n"
+ "\n"
+ "The -pref option can be used to change a preference setting. The parameter "
+ "passed with is is of the for key=value, where \"key\" is any of the keys "
+ "displayed in the preference file, and value is the value you want it to be. "
+ "Note that using this option *changes* the preference. It does not override "
+ "the preference. Thus, when the emulator exits, the value specified on the "
+ "command line will be written to the preference file.\n"
+ "\n"
+ );
+
+ help = ::PrvWrap (help, 78);
+ printf ("%s", help.c_str ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvCollectOptions
+ *
+ * DESCRIPTION: Breaks up the command line text into pairs of switches
+ * (the "-foo" part) and their optional parameters (anything
+ * that comes after the "-foo" part). Switches are
+ * validated, and they and any parameter are added to
+ * the given OptionList.
+ *
+ * PARAMETERS: argc, argv - standard C parameters describing the
+ * command line.
+ *
+ * options - the OptionList to received the parsed and
+ * validated parameters.
+ *
+ * RETURNED: True if everything went swimmingly. If an error occurred
+ * (for instance, an invalid switch was specified or a
+ * switch that needed a parameter didn't have one), the
+ * error is reported and the function returns false.
+ *
+ ***********************************************************************/
+
+static OptionList* gOptions;
+static PreferenceList* gPreferences;
+
+int Startup::PrvParseOneOption (int argc, char** argv, int& argIndex)
+{
+ const char* arg = argv[argIndex];
+
+ // For this argument, see if it is a recognized switch.
+
+ for (size_t ii = 0; ii < countof (kOptionMap); ++ii)
+ {
+ if (_stricmp (arg, kOptionMap[ii].option) == 0)
+ {
+ // It's recognized; see if we need to also collect a parameter.
+
+ if (kOptionMap[ii].optType == 0)
+ {
+ // No parameter, just add the switch to our collection.
+
+ (*gOptions)[kOptionMap[ii].optKey] = "";
+ argIndex += 1;
+ return 1;
+ }
+ else if (kOptionMap[ii].optType == 1)
+ {
+ if ((argIndex + 1) < argc)
+ {
+ // Add the switch and parameter to our collection.
+ // Put preferences on a seperate list -- a multimap
+ // -- so that we can support more than one. All others
+ // go into a map collection so that we respond to just
+ // the last specified option.
+
+ if (kOptionMap[ii].optKey == kOptPreference)
+ gPreferences->insert (make_pair (kOptionMap[ii].optKey, argv[argIndex + 1]));
+ else
+ (*gOptions)[kOptionMap[ii].optKey] = argv[argIndex + 1];
+
+ argIndex += 2;
+ return 2;
+ }
+ else
+ {
+ // Needed a parameter, but there wasn't one.
+ Startup::PrvMissingArgument (arg);
+ return 0;
+ }
+ }
+ }
+ }
+
+ // If we got here, we didn't understand the argument. Perhap someone
+ // provided a file name without a preceding -psf or -rom (this can happen
+ // in Windows when someone drops such a file on the application's icon).
+ // See if that's the case and try to support it.
+
+ EmFileRef ref (arg);
+ if (ref.Exists ())
+ {
+ if (ref.IsType (kFileTypeROM))
+ {
+ (*gOptions)[kOptROM] = arg;
+ argIndex += 1;
+ return 1;
+ }
+
+ if (ref.IsType (kFileTypeSession))
+ {
+ (*gOptions)[kOptPSF] = arg;
+ argIndex += 1;
+ return 1;
+ }
+ }
+
+ // And if we got this far, return an error.
+
+ return 0;
+}
+
+
+Bool Startup::PrvCollectOptions (int argc, char** argv,
+ OptionList& options,
+ PreferenceList& prefs)
+{
+ // Iterate over the command line arguments.
+
+ gOptions = &options;
+ gPreferences = &prefs;
+
+ int errorArg;
+
+ if (!Platform::CollectOptions (argc, argv, errorArg, &Startup::PrvParseOneOption))
+ {
+ Startup::PrvDontUnderstand (argv[errorArg]);
+ Startup::PrvPrintHelp ();
+ return false;
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvConvertRAM
+ *
+ * DESCRIPTION: Convert a -ram parameter into a number and validate it.
+ *
+ * PARAMETERS: str - the switch parameter.
+ *
+ * ramSize - the RAMSizeType to receive the converted value.
+ *
+ * RETURNED: True if everything went well. If the resulting value
+ * was not a valid RAMSizeType value, then returns false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvConvertRAM (const string& str, RAMSizeType& ramSize)
+{
+ ramSize = atol (str.c_str ());
+
+ MemoryTextList sizes;
+ ::GetMemoryTextList (sizes);
+
+ MemoryTextList::iterator iter = sizes.begin ();
+ while (iter != sizes.end ())
+ {
+ if (ramSize == iter->first)
+ {
+ return true;
+ }
+
+ ++iter;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvParseFileList
+ *
+ * DESCRIPTION: Break up a comma-delimited list of files, returning the
+ * pieces in a EmFileRefList.
+ *
+ * PARAMETERS: fileList - the EmFileRefList to receive the files from the
+ * comma-delimited list. This collection is *not* first
+ * cleared out, so it's possible to add to the
+ * collection with this function.
+ *
+ * option - the string containing the comma-delimited files.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::PrvParseFileList (EmFileRefList& fileList, string option)
+{
+ StringList items;
+ ::SeparateList (items, option, ',');
+
+ StringList::iterator iter = items.begin ();
+ while (iter != items.end ())
+ {
+ fileList.push_back (EmFileRef (*iter));
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandleOpenSessionParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptPSF
+ * kOptMinimize
+ *
+ * PARAMETERS: options - the OptionList containing the complete set
+ * of parsed switches and parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandleOpenSessionParameters (OptionList& options)
+{
+ DEFINE_VARS(PSF);
+ DEFINE_VARS(Minimize);
+
+ if (havePSF)
+ {
+ // Clear out any previous action
+
+ Startup::ScheduleAskWhatToDo ();
+
+ // Schedule the new action
+
+ EmFileRef psfRef = EmFileRef (optPSF);
+ Startup::ScheduleOpenSession (psfRef);
+ }
+
+ if (haveMinimize)
+ {
+ // Clear out any previous action
+
+ Startup::ScheduleAskWhatToDo ();
+
+ // Schedule the new action
+
+ EmFileRef MinimizeRef = EmFileRef (optMinimize);
+ Startup::ScheduleMinimize (MinimizeRef);
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandleCreateSessionParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptROM
+ * kOptRAM
+ * kOptDevice
+ *
+ * PARAMETERS: options - the OptionList containing the complete set
+ * of parsed switches and parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandleCreateSessionParameters (OptionList& options)
+{
+ DEFINE_VARS(ROM);
+ DEFINE_VARS(RAM);
+ DEFINE_VARS(Device);
+
+ Bool haveSome = haveROM || haveRAM || haveDevice;
+ Bool haveAll = haveROM && haveRAM && haveDevice;
+
+ if (haveSome)
+ {
+ Preference<Configuration> prefConfig (kPrefKeyLastConfiguration);
+ Configuration cfg = *prefConfig;
+
+ // Check for a specified ROM file.
+
+ if (haveROM)
+ {
+ cfg.fROMFile = EmFileRef (optROM);
+ }
+
+ // Check for a specified RAM size.
+
+ if (haveRAM)
+ {
+ if (!Startup::PrvConvertRAM (optRAM, cfg.fRAMSize))
+ {
+ Startup::PrvInvalidRAMSize (optRAM.c_str ());
+ return false;
+ }
+ }
+
+ // Check for a specified device type.
+
+ if (haveDevice)
+ {
+ EmDevice device (optDevice);
+ if (device.Supported ())
+ {
+ cfg.fDevice = device;
+ }
+ else
+ {
+ Startup::PrvDontUnderstand (optDevice.c_str ());
+ return false;
+ }
+ }
+
+ // Try to start up with the specified parameters.
+ // If the command line didn't specify all the required values, ask for them.
+
+ if (!haveAll && !EmDocument::AskNewSession (cfg))
+ {
+ // User cancelled the "New Configuration" dialog.
+ // Bring up the dialog with the New/Open/Download/Exit buttons.
+
+ Startup::ScheduleAskWhatToDo ();
+ }
+ else
+ {
+ // Clear out any previous action
+
+ Startup::ScheduleAskWhatToDo ();
+
+ // Schedule the new action
+
+ Startup::ScheduleCreateSession (cfg);
+ }
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandleNewHordeParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptHordeFirst
+ * kOptHordeLast
+ * kOptHordeApps
+ * kOptHordeSaveDir
+ * kOptHordeSaveFreq
+ * kOptHordeDepthMax
+ * kOptHordeDepthSwitch
+ * kOptHordeQuitWhenDone
+ *
+ * PARAMETERS: options - the OptionList containing the complete set
+ * of parsed switches and parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandleNewHordeParameters (OptionList& options)
+{
+ DEFINE_VARS(HordeFirst);
+ DEFINE_VARS(HordeLast);
+ DEFINE_VARS(HordeApps);
+ DEFINE_VARS(HordeSaveDir);
+ DEFINE_VARS(HordeSaveFreq);
+ DEFINE_VARS(HordeDepthMax);
+ DEFINE_VARS(HordeDepthSwitch);
+ DEFINE_VARS(HordeQuitWhenDone);
+
+ UNUSED_PARAM(optHordeQuitWhenDone);
+
+ if (haveHordeFirst ||
+ haveHordeLast ||
+ haveHordeApps ||
+ haveHordeSaveDir ||
+ haveHordeSaveFreq ||
+ haveHordeDepthMax ||
+ haveHordeDepthSwitch)
+ {
+ HordeInfo info;
+ StringList appNames;
+
+ if (haveHordeFirst)
+ {
+ info.fStartNumber = atoi (optHordeFirst.c_str ());
+
+ if (!haveHordeLast)
+ {
+ info.fStopNumber = info.fStartNumber;
+ }
+ }
+
+ if (haveHordeLast)
+ {
+ info.fStopNumber = atoi (optHordeLast.c_str ());
+
+ if (!haveHordeFirst)
+ {
+ info.fStartNumber = info.fStopNumber;
+ }
+ }
+
+ if (!haveHordeFirst && !haveHordeLast)
+ {
+ info.fStartNumber = 0;
+ info.fStopNumber = 0;
+ }
+
+ if (haveHordeApps)
+ {
+ // Get the list of user-specified names.
+ // We can't do much more with them now -- like look up
+ // the applications on the device -- as the device may
+ // not be up and running at this time. We have to defer
+ // doing that until we're ready to start the Gremlin.
+
+ ::SeparateList (appNames, optHordeApps, ',');
+
+ }
+
+ if (haveHordeSaveDir)
+ {
+ Hordes::SetGremlinsHome (optHordeSaveDir);
+ }
+ else
+ {
+ Hordes::SetGremlinsHomeToDefault ();
+ }
+
+ if (haveHordeSaveFreq)
+ {
+ info.fSaveFrequency = atoi (optHordeSaveFreq.c_str ());
+ }
+
+ if (haveHordeDepthMax)
+ {
+ info.fMaxDepth = atoi (optHordeDepthMax.c_str ());
+ }
+
+ if (haveHordeDepthSwitch)
+ {
+ info.fSwitchDepth = atoi (optHordeDepthSwitch.c_str ());
+ }
+
+ if (haveHordeFirst || haveHordeLast)
+ {
+ info.OldToNew (); // Transfer old fields to new.
+
+ Startup::ScheduleNewHorde (info, appNames);
+ }
+ }
+
+ gHordeQuitWhenDone = haveHordeQuitWhenDone;
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandleAutoLoadParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptLoad
+ * kOptRun
+ * kOptQuitOnExit
+ *
+ * PARAMETERS: options - the OptionList containing the complete set
+ * of parsed switches and parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandleAutoLoadParameters (OptionList& options)
+{
+ DEFINE_VARS(Load);
+ DEFINE_VARS(Run);
+ DEFINE_VARS(QuitOnExit);
+
+ UNUSED_PARAM (optQuitOnExit)
+
+ if (haveLoad)
+ {
+ Startup::PrvParseFileList (gAutoLoadFiles1, optLoad);
+ }
+
+ if (haveRun)
+ {
+ gAutoRunApp = optRun;
+ }
+
+ if (haveQuitOnExit)
+ {
+ Startup::ScheduleQuitOnExit ();
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandleSkinParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptDevice
+ * kOptSkin
+ *
+ * PARAMETERS: options - the OptionList containing the complete set
+ * of parsed switches and parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandleSkinParameters (OptionList& options)
+{
+ DEFINE_VARS(Device);
+ DEFINE_VARS(Skin);
+
+ if (haveSkin && haveDevice)
+ {
+ EmDevice device (optDevice);
+
+ if (!device.Supported ())
+ {
+ Startup::PrvDontUnderstand (optDevice.c_str ());
+ return false;
+ }
+
+ if (!::SkinValidSkin (device, optSkin))
+ {
+ Startup::PrvInvalidSkin (optSkin.c_str (), optDevice.c_str ());
+ return false;
+ }
+
+ ::SkinSetSkinName (device, optSkin);
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvHandlePreferenceParameters
+ *
+ * DESCRIPTION: Handle the following command line options:
+ *
+ * kOptPreference
+ *
+ * PARAMETERS: prefs - the PreferenceList containing the complete set
+ * of parsed preference parameters.
+ *
+ * RETURNED: True if everything when OK. If there's something wrong
+ * with the specifications, this function displays an
+ * error message and return false.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvHandlePreferenceParameters (PreferenceList& prefs)
+{
+ PreferenceList::iterator iter = prefs.begin ();
+ while (iter != prefs.end ())
+ {
+ string fullPrefString = iter->second;
+ string::size_type equalsPos = fullPrefString.find ('=');
+
+ if (equalsPos == string::npos)
+ {
+ Startup::PrvInvalidPreference (fullPrefString.c_str ());
+ return false;
+ }
+
+ string key = fullPrefString.substr (0, equalsPos);
+ string value = fullPrefString.substr (equalsPos + 1);
+
+ Preference<string> pref (key.c_str ());
+ pref = value;
+
+ ++iter;
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvParseCommandLine
+ *
+ * DESCRIPTION: Parse up the command line into its consituent parts,
+ * validate the parts, and act on the specifications.
+ *
+ * PARAMETERS: argc, argv - standard C parameters describing the
+ * command line.
+ *
+ * RETURNED: Nothing. All actions to be taken based on the users
+ * specifications are recorded in global variables.
+ *
+ ***********************************************************************/
+
+Bool Startup::PrvParseCommandLine (int argc, char** argv)
+{
+ OptionList options;
+ PreferenceList prefs;
+
+ // Convert the command line into a map of switch/parameter pairs.
+
+ if (!Startup::PrvCollectOptions (argc, argv, options, prefs))
+ goto BadParameter;
+
+ // Handle kOptPSF.
+
+ if (!Startup::PrvHandleOpenSessionParameters (options))
+ goto BadParameter;
+
+ // Handle kOptROM, kOptRAM, and kOptDevice.
+
+ if (!Startup::PrvHandleCreateSessionParameters (options))
+ goto BadParameter;
+
+ // Handle kOptHordeFirst, kOptHordeLast, kOptHordeApps, kOptHordeSaveDir,
+ // kOptHordeSaveFreq, kOptHordeDepthMax, kOptHordeDepthSwitch, and
+ // kOptHordeQuitWhenDone.
+
+ if (!Startup::PrvHandleNewHordeParameters (options))
+ goto BadParameter;
+
+ // Handle kOptLoad, kOptRun, and kOptQuitOnExit.
+
+ if (!Startup::PrvHandleAutoLoadParameters (options))
+ goto BadParameter;
+
+ // Handle kOptSkin
+ if (!Startup::PrvHandleSkinParameters (options))
+ goto BadParameter;
+
+ // Handle preference changes.
+ if (!Startup::PrvHandlePreferenceParameters (prefs))
+ goto BadParameter;
+
+ return true;
+
+BadParameter:
+ // All bets are off. Bring up the dialog with the
+ // New/Open/Download/Exit buttons.
+
+ Startup::ScheduleAskWhatToDo ();
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::DetermineStartupActions
+ *
+ * DESCRIPTION: Determine what to do at startup time, based on any
+ * command-line options, what the user was doing when they
+ * last ran Poser, and whether or not the CapsLock key
+ * is toggled.
+ *
+ * In general, the startup rules are as follows:
+ *
+ * 1 If the Caps Lock key is toggled in the ON position, always bring
+ * up the New/Open/... dialog.
+ *
+ * 2 Scan the command line for startup parameters. If an error occurs
+ * trying to scan the command line, the error is reported and the user
+ * is presented with the New/Open/... dialog.
+ *
+ * 3 Use the .psf file if one is specified. If an error occurs trying
+ * to load the file, the error is reported and the user is presented
+ * with the New/Open/... dialog.
+ *
+ * 4 If any of -rom, -ram, -device, or -silkscreen are specified, try
+ * to start a new session based on those values. If all are specified,
+ * the new session is automatically created. If any of those four
+ * values are missing, the "New Configuration" dialog is displayed.
+ * If the user cancels the dialog, or if there is an error creating
+ * the new session, any error is reported and the user is presented
+ * with the New/Open/... dialog.
+ *
+ * 5 If no command line options are specified, try re-opening the last
+ * saved .psf file (this step is skipped if the user last created a
+ * new session, but did NOT save that session to a file). If an error
+ * occurs trying to load the file, the error is reported and the user
+ * is presented with the New/Open/... dialog.
+ *
+ * 6 Try creating a new session based on the settings the user last
+ * specified when creating a session. If there is an error creating
+ * the new session, the error is reported and the user is presented
+ * with the New/Open/... dialog.
+ *
+ * 7 Finally, if all else fails, present the user with the New/Open/...
+ * dialog.
+ *
+ * PARAMETERS: argc, argv - standard C parameters describing the
+ * command line.
+ *
+ * RETURNED: True if we were able to determine a startup course of
+ * action. If false is returned, something horrible happened.
+ * The caller should assume that an error was reported,
+ * and that the application should quit.
+ *
+ ***********************************************************************/
+
+Bool Startup::DetermineStartupActions (int argc, char** argv)
+{
+ // By default, throw up our hands.
+
+ Startup::ScheduleAskWhatToDo ();
+
+ // See if the user wants to force the appearance of the Startup
+ // screen (by holding down the ShiftLock key) and skip the auto-
+ // loading of the previous session file.
+
+ if (!Platform::ForceStartupScreen ())
+ {
+ Preference<Configuration> pref1 (kPrefKeyLastConfiguration);
+ Preference<EmFileRef> pref2 (kPrefKeyLastPSF);
+
+ Configuration cfg = *pref1;
+ EmFileRef ramFileRef = *pref2;
+
+ // See if there was a previously saved RAM file. If so, open it.
+
+ if (ramFileRef.IsSpecified ())
+ {
+ Startup::ScheduleOpenSession (ramFileRef);
+ }
+
+ // Else, see if there was a previously created document. If so,
+ // create a new document based on its settings.
+
+ else if (cfg.IsValid () )
+ {
+ Startup::ScheduleCreateSession (cfg);
+ }
+
+ // Now that default actions have been established, let's see if
+ // there's anything interesting on the command line.
+
+ if (!Startup::PrvParseCommandLine (argc, argv))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::GetAutoLoads
+ *
+ * DESCRIPTION: Return the list of applications that should automatically
+ * be loaded at startup time, regardless of whether a new
+ * session was created or an old one loaded. The list of
+ * applications is collected from the command line and from
+ * the specially-named AutoLoad, AutoRun, and AutoRunAndQuit
+ * directories.
+ *
+ * PARAMETERS: fileList - the EmFileRefList to receive the files to load.
+ * The collection is cleared out before the new items
+ * are added to it.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::PrvLookForAutoloads (void)
+{
+ gAutoLoadFiles2.clear();
+ gAutoRunFiles2.clear();
+ gAutoRunAndQuitFiles2.clear();
+
+ ::GetLoadableFileList (Platform::GetString (kStr_Autoload), gAutoLoadFiles2);
+ ::GetLoadableFileList (Platform::GetString (kStr_Autorun), gAutoRunFiles2);
+ ::GetLoadableFileList (Platform::GetString (kStr_AutorunAndQuit), gAutoRunAndQuitFiles2);
+}
+
+void Startup::PrvAppendFiles (EmFileRefList& list1, const EmFileRefList& list2)
+{
+ list1.insert(list1.end(), list2.begin(), list2.end());
+}
+
+void Startup::GetAutoLoads (EmFileRefList& fileList)
+{
+ fileList.clear();
+
+ Startup::PrvLookForAutoloads();
+
+ Startup::PrvAppendFiles (fileList, gAutoLoadFiles1);
+// Startup::PrvAppendFiles (fileList, gAutoRunFiles1);
+// Startup::PrvAppendFiles (fileList, gAutoRunAndQuitFiles1);
+
+ Startup::PrvAppendFiles (fileList, gAutoLoadFiles2);
+ Startup::PrvAppendFiles (fileList, gAutoRunFiles2);
+ Startup::PrvAppendFiles (fileList, gAutoRunAndQuitFiles2);
+
+ if (/*gAutoRunAndQuitFiles1.size() +*/ gAutoRunAndQuitFiles2.size() > 0)
+ {
+ Startup::ScheduleQuitOnExit ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::GetAutoRunApp
+ *
+ * DESCRIPTION: Returns the *database name* of the application to
+ * switch to at startup time.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The name of the database of the executable.
+ *
+ ***********************************************************************/
+
+string Startup::PrvTryGetApp (const EmFileRefList& fileList)
+{
+ string result;
+
+ EmFileRefList::const_iterator iter = fileList.begin();
+ while (iter != fileList.end())
+ {
+ if ((*iter).IsType (kFileTypePalmApp)) // egcs can't handle iter->IsType()!!!
+ {
+ try
+ {
+ EmStreamFile stream (*iter, kOpenExistingForRead);
+
+ EmProxyDatabaseHdrType header;
+ stream.GetBytes (header.GetPtr (), header.GetSize ());
+
+ if (::IsExecutable (header.type, header.creator, header.attributes))
+ {
+ result = (char*) header.name.GetPtr ();
+ break;
+ }
+ }
+ catch (...)
+ {
+ }
+ }
+
+ ++iter;
+ }
+
+ return result;
+}
+
+string Startup::GetAutoRunApp (void)
+{
+ string result;
+
+ // Get the name the user specified on the command line (if any)
+ // and get the DatabaseInfo for it, so that we can get the database name.
+
+ if (!gAutoRunApp.empty())
+ {
+ StringList appNames;
+ appNames.push_back (gAutoRunApp);
+
+ DatabaseInfoList dbInfos;
+ Startup::PrvGetDatabaseInfosFromAppNames (appNames, dbInfos);
+
+ if (dbInfos.size() > 0)
+ {
+ result = dbInfos.begin()->dbName;
+ }
+ }
+
+ // If the user didn't specify an executable, or we couldn't find
+ // that executable, then work from the files found in the AutoRun
+ // and AutoRunAndQuit directories.
+
+// if (result.empty())
+// result = Startup::PrvTryGetApp (gAutoRunFiles1);
+
+ if (result.empty())
+ result = Startup::PrvTryGetApp (gAutoRunFiles2);
+
+// if (result.empty())
+// result = Startup::PrvTryGetApp (gAutoRunAndQuitFiles1);
+
+ if (result.empty())
+ result = Startup::PrvTryGetApp (gAutoRunAndQuitFiles2);
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::AskWhatToDo
+ *
+ * DESCRIPTION: Return whether or not we are supposed to ask the user
+ * what to do (that is, display the dialog box with the
+ * New, Open, Download, and Quit buttons). In general,
+ * this function returns true if there's nothing else
+ * scheduled to be done (create a session, open a session,
+ * or quit the emulator).
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::AskWhatToDo (void)
+{
+// Bool result = gAskWhatToDo;
+// gAskWhatToDo = false;
+// return result;
+
+ return !gCreateSession && !gOpenSession;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::CreateSession
+ *
+ * DESCRIPTION: Return whether or not we are supposed to create a new
+ * session based on previously determined criteria. This
+ * is a one-shot function: subsequent calls will return
+ * false until ScheduleCreateSession is called again.
+ *
+ * PARAMETERS: cfg - the Configuration to receive the information to
+ * be used when creating the new session.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::CreateSession (Configuration& cfg)
+{
+ Bool result = gCreateSession;
+ if (result)
+ cfg = gCfg;
+ gCreateSession = false;
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::OpenSession
+ *
+ * DESCRIPTION: Return whether or not we are supposed to open an old
+ * session based on previously determined criteria. This
+ * is a one-shot function: subsequent calls will return
+ * false until ScheduleOpenSession is called again.
+ *
+ * PARAMETERS: ref - the EmFileRef to receive the reference to
+ * the .psf file to be opened.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::OpenSession (EmFileRef& ref)
+{
+ Bool result = gOpenSession;
+
+ if (result)
+ {
+ ref = gSessionOpenRef;
+ }
+
+ gOpenSession = false;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::Minimize
+ *
+ * DESCRIPTION: Return whether or not we are supposed to open an old
+ * session based on previously determined criteria. This
+ * is a one-shot function: subsequent calls will return
+ * false until ScheduleOpenSession is called again.
+ *
+ * PARAMETERS: ref - the EmFileRef to receive the reference to
+ * the .psf file to be opened.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::Minimize (EmFileRef& ref)
+{
+ Bool result = gMinimize;
+
+ if (result)
+ {
+ ref = gMinimizeRef;
+ }
+
+ gMinimize = false;
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::NewHorde
+ *
+ * DESCRIPTION: Return whether or not we are supposed to start a horde
+ * session based on previously determined criteria. This
+ * is a one-shot function: subsequent calls will return
+ * false until ScheduleNewHorde is called again.
+ *
+ * PARAMETERS: info - the HordeInfo to receive the information used to
+ * create the new horde.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::NewHorde (HordeInfo* info)
+{
+ Bool result = gStartNewHorde;
+
+ if (info != NULL)
+ {
+ if (result)
+ {
+ *info = gHorde;
+
+ // Find the AppInfos for the user-specified applications.
+
+ EmSessionStopper stopper (gSession, kStopOnSysCall);
+
+ Startup::PrvGetDatabaseInfosFromAppNames (gHordeApps, info->fAppList);
+ }
+
+ gStartNewHorde = false;
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::HordeQuitWhenDone
+ *
+ * DESCRIPTION: Return whether or not we are supposed to quit the
+ * emulator session when the Horde has completed.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::HordeQuitWhenDone (void)
+{
+ return gHordeQuitWhenDone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::MinimizeQuitWhenDone
+ *
+ * DESCRIPTION: Return whether or not we are supposed to quit the
+ * emulator session when the Horde has completed.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::MinimizeQuitWhenDone (void)
+{
+ return gMinimizeQuitWhenDone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::QuitOnExit
+ *
+ * DESCRIPTION: Return whether or not Poser is supposed to quit when
+ * a particular application exits.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool Startup::QuitOnExit (void)
+{
+ Bool result = gQuitOnExit;
+// gQuitOnExit = false;
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::Clear
+ *
+ * DESCRIPTION: Clear all settings.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::Clear (void)
+{
+ gCreateSession = false;
+ gOpenSession = false;
+ gStartNewHorde = false;
+ gQuitOnExit = false;
+
+ gAutoRunApp = "";
+ gAutoLoadFiles1.clear();
+ gAutoLoadFiles2.clear();
+ gAutoRunFiles2.clear();
+ gAutoRunAndQuitFiles2.clear();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleAskWhatToDo
+ *
+ * DESCRIPTION: Schedule our "state machine" so that AskWhatToDo will
+ * return True.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleAskWhatToDo (void)
+{
+ Startup::Clear ();
+// gAskWhatToDo = true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleCreateSession
+ *
+ * DESCRIPTION: Schedule our "state machine" so that CreateSession will
+ * return True.
+ *
+ * PARAMETERS: cfg - the Configuration returned to the caller of
+ * CreatSession.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleCreateSession (const Configuration& cfg)
+{
+ gCreateSession = true;
+// gAskWhatToDo = false;
+ gCfg = cfg;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleOpenSession
+ *
+ * DESCRIPTION: Schedule our "state machine" so that OpenSession will
+ * return True.
+ *
+ * PARAMETERS: ref - the EmFileRef returned to the caller of
+ * OpenSession.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleOpenSession (const EmFileRef& ref)
+{
+ gOpenSession = true;
+// gAskWhatToDo = false;
+ gSessionOpenRef = ref;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleMinimize
+ *
+ * DESCRIPTION: Schedule our "state machine" so that OpenSession will
+ * return True.
+ *
+ * PARAMETERS: ref - the EmFileRef returned to the caller of
+ * OpenSession.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleMinimize (const EmFileRef& ref)
+{
+ gMinimize = true;
+ gMinimizeQuitWhenDone = true;
+// gAskWhatToDo = false;
+ gMinimizeRef = ref;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleNewHorde
+ *
+ * DESCRIPTION: Schedule our "state machine" so that NewHorde will
+ * return True.
+ *
+ * PARAMETERS: info - the HordeInfo returned to the caller of NewHorde.
+ *
+ * appNames - names of the applications to inflict the
+ * Gremlins on. Normally, this information is
+ * specified in the fAppList field of the HordeInfo.
+ * However, at the time this function is called,
+ * we may not be able to generate the DatabaseInfoList
+ * (the emulator may be just starting up and not
+ * emulating a Palm OS environment, yet). So we
+ * remember the names here. When NewHorde is called,
+ * the appNames list is converted into an DatabaseInfoList.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleNewHorde (const HordeInfo& info, const StringList& appNames)
+{
+ gStartNewHorde = true;
+ gHorde = info;
+ gHordeApps = appNames;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Startup::ScheduleQuitOnExit
+ *
+ * DESCRIPTION: Schedule our "state machine" so that QuitOnExit will
+ * return True.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Startup::ScheduleQuitOnExit (void)
+{
+ gQuitOnExit = true;
+}
diff --git a/SrcShared/Startup.h b/SrcShared/Startup.h
new file mode 100644
index 0000000..151aae0
--- /dev/null
+++ b/SrcShared/Startup.h
@@ -0,0 +1,88 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _STARTUP_H_
+#define _STARTUP_H_
+
+#include "EmFileRef.h" // EmFileRefList
+#include "EmStructs.h" // StringList
+
+#include <string> // string
+#include <map> // multimap
+
+struct Configuration;
+struct HordeInfo;
+class EmFileRef;
+
+typedef StringStringMap OptionList;
+typedef multimap<string, string> PreferenceList;
+
+class Startup
+{
+ public:
+ static Bool DetermineStartupActions (int argc, char** argv);
+
+ static void GetAutoLoads (EmFileRefList&);
+ static string GetAutoRunApp (void);
+
+ // Getters...
+
+ static Bool AskWhatToDo (void);
+ static Bool CreateSession (Configuration&);
+ static Bool OpenSession (EmFileRef&);
+ static Bool Minimize (EmFileRef&);
+ static Bool NewHorde (HordeInfo*);
+ static Bool HordeQuitWhenDone (void);
+ static Bool MinimizeQuitWhenDone (void);
+ static Bool CloseSession (EmFileRef&);
+ static Bool QuitOnExit (void);
+
+ private:
+ static void PrvGetDatabaseInfosFromAppNames (const StringList& names, DatabaseInfoList& results);
+ static void PrvError (const char* msg);
+ static void PrvDontUnderstand (const char* arg);
+ static void PrvMissingArgument (const char* arg);
+ static void PrvInvalidRAMSize (const char* arg);
+ static void PrvInvalidSkin (const char* argSkin, const char* argDevice);
+ static void PrvInvalidPreference (const char* pref);
+ static void PrvPrintHelp (void);
+ static int PrvParseOneOption (int argc, char** argv, int& argIndex);
+ static Bool PrvCollectOptions (int argc, char** argv,
+ OptionList& options,
+ PreferenceList& prefs);
+ static Bool PrvConvertRAM (const string& str, RAMSizeType& ramSize);
+ static void PrvParseFileList (EmFileRefList& fileList, string option);
+ static Bool PrvHandleOpenSessionParameters (OptionList& options);
+ static Bool PrvHandleCreateSessionParameters (OptionList& options);
+ static Bool PrvHandleNewHordeParameters (OptionList& options);
+ static Bool PrvHandleAutoLoadParameters (OptionList& options);
+ static Bool PrvHandleSkinParameters (OptionList& options);
+ static Bool PrvHandlePreferenceParameters (PreferenceList& prefs);
+ static Bool PrvParseCommandLine (int argc, char** argv);
+ static void PrvLookForAutoloads (void);
+ static void PrvAppendFiles (EmFileRefList& list1, const EmFileRefList& list2);
+ static string PrvTryGetApp (const EmFileRefList& fileList);
+
+ private:
+ // Setters...
+
+ static void Clear (void);
+ static void ScheduleAskWhatToDo (void);
+ static void ScheduleCreateSession (const Configuration&);
+ static void ScheduleOpenSession (const EmFileRef&);
+ static void ScheduleMinimize (const EmFileRef&);
+ static void ScheduleNewHorde (const HordeInfo&, const StringList&);
+ static void ScheduleQuitOnExit (void);
+};
+
+#endif /* _STARTUP_H_ */
diff --git a/SrcShared/String2 b/SrcShared/String2
new file mode 100644
index 0000000..52d3987
--- /dev/null
+++ b/SrcShared/String2
@@ -0,0 +1,193 @@
+// string standard header
+#ifndef _STRING_
+#define _STRING_
+#include "xstring2"
+#include <istream>
+
+#ifdef _MSC_VER
+#pragma pack(push,8)
+#endif /* _MSC_VER */
+_STD_BEGIN
+ // basic_string TEMPLATE OPERATORS
+template<class _E, class _Tr, class _A> inline
+ basic_string<_E, _Tr, _A> __cdecl operator+(
+ const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (basic_string<_E, _Tr, _A>(_L) += _R); }
+template<class _E, class _Tr, class _A> inline
+ basic_string<_E, _Tr, _A> __cdecl operator+(const _E *_L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (basic_string<_E, _Tr, _A>(_L) += _R); }
+template<class _E, class _Tr, class _A> inline
+ basic_string<_E, _Tr, _A> __cdecl operator+(
+ const _E _L, const basic_string<_E, _Tr, _A>& _R)
+ {return (basic_string<_E, _Tr, _A>(1, _L) += _R); }
+template<class _E, class _Tr, class _A> inline
+ basic_string<_E, _Tr, _A> __cdecl operator+(
+ const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (basic_string<_E, _Tr, _A>(_L) += _R); }
+template<class _E, class _Tr, class _A> inline
+ basic_string<_E, _Tr, _A> __cdecl operator+(
+ const basic_string<_E, _Tr, _A>& _L, const _E _R)
+ {return (basic_string<_E, _Tr, _A>(_L) += _R); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator==(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_L.compare(_R) == 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator==(const _E * _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_R.compare(_L) == 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator==(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (_L.compare(_R) == 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator!=(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_L == _R)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator!=(const _E *_L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_L == _R)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator!=(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (!(_L == _R)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_L.compare(_R) < 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<(const _E * _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_R.compare(_L) > 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (_L.compare(_R) < 0); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_R < _L); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>(const _E * _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (_R < _L); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (_R < _L); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<=(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_R < _L)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<=(const _E * _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_R < _L)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator<=(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (!(_R < _L)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>=(const basic_string<_E, _Tr, _A>& _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_L < _R)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>=(const _E * _L,
+ const basic_string<_E, _Tr, _A>& _R)
+ {return (!(_L < _R)); }
+template<class _E, class _Tr, class _A> inline
+ bool __cdecl operator>=(const basic_string<_E, _Tr, _A>& _L,
+ const _E *_R)
+ {return (!(_L < _R)); }
+ // basic_string INSERTERS AND EXTRACTORS
+template<class _E, class _Tr, class _A> inline
+ basic_istream<_E, _Tr>& __cdecl operator>>(
+ basic_istream<_E, _Tr>& _I,
+ basic_string<_E, _Tr, _A>& _X)
+ {typedef ctype<_E> _Ctype;
+ typedef basic_istream<_E, _Tr> _Myis;
+ ios_base::iostate _St = ios_base::goodbit;
+ bool _Chg = false;
+ _X.erase();
+ const _Myis::sentry _Ok(_I);
+ if (_Ok)
+ {const _Ctype& _Fac = _USE(_I.getloc(), _Ctype);
+ _TRY_IO_BEGIN
+ _A::size_type _N = 0 < _I.width()
+ && _I.width() < _X.max_size()
+ ? _I.width() : _X.max_size();
+ _Tr::int_type _C = _I.rdbuf()->sgetc();
+ for (; 0 < --_N; _C = _I.rdbuf()->snextc())
+ if(_Tr::eq_int_type(_Tr::eof(), _C))
+ {_St |= ios_base::eofbit;
+ break; }
+ else if (_Fac.is(_Ctype::space,
+ _Tr::to_char_type(_C)))
+ break;
+ else
+ {_X.append(1, _Tr::to_char_type(_C));
+ _Chg = true; }
+ _CATCH_IO_(_I); }
+ _I.width(0);
+ if (!_Chg)
+ _St |= ios_base::failbit;
+ _I.setstate(_St);
+ return (_I); }
+template<class _E, class _Tr, class _A> inline
+ basic_istream<_E, _Tr>& __cdecl getline(basic_istream<_E, _Tr>& _I,
+ basic_string<_E, _Tr, _A>& _X)
+ {return (getline(_I, _X, _I.widen('\n'))); }
+template<class _E, class _Tr, class _A> inline
+ basic_istream<_E, _Tr>& __cdecl getline(basic_istream<_E, _Tr>& _I,
+ basic_string<_E, _Tr, _A>& _X, const _E _D)
+ {typedef basic_istream<_E, _Tr> _Myis;
+ ios_base::iostate _St = ios_base::goodbit;
+ bool _Chg = false;
+ _X.erase();
+ const _Myis::sentry _Ok(_I, true);
+ if (_Ok)
+ {_TRY_IO_BEGIN
+ _Tr::int_type _C = _I.rdbuf()->sgetc();
+ for (; ; _C = _I.rdbuf()->snextc())
+ if (_Tr::eq_int_type(_Tr::eof(), _C))
+ {_St |= ios_base::eofbit;
+ break; }
+ else if (_Tr::eq(_C, _D))
+ {_Chg = true;
+ _I.rdbuf()->snextc();
+ break; }
+ else if (_X.max_size() <= _X.size())
+ {_St |= ios_base::failbit;
+ break; }
+ else
+ _X += _Tr::to_char_type(_C), _Chg = true;
+ _CATCH_IO_(_I); }
+ if (!_Chg)
+ _St |= ios_base::failbit;
+ _I.setstate(_St);
+ return (_I); }
+template<class _E, class _Tr, class _A> inline
+ basic_ostream<_E, _Tr>& __cdecl operator<<(
+ basic_ostream<_E, _Tr>& _O,
+ const basic_string<_E, _Tr, _A>& _X)
+ {
+ for (_A::size_type _N = 0; _N < _X.size(); ++_N)
+ if (_Tr::eq_int_type(_Tr::eof(),
+ _O.rdbuf()->sputc(_X[_N])))
+ break;
+ return (_O); }
+_STD_END
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+#endif /* _STRING */
+
+/*
+ * Copyright (c) 1994 by P.J. Plauger. ALL RIGHTS RESERVED.
+ * Consult your license regarding permissions and restrictions.
+ */
diff --git a/SrcShared/StringConversions.cpp b/SrcShared/StringConversions.cpp
new file mode 100644
index 0000000..3a46820
--- /dev/null
+++ b/SrcShared/StringConversions.cpp
@@ -0,0 +1,370 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "StringConversions.h"
+
+#include "EmDirRef.h" // EmDirRef
+#include "EmFileRef.h" // EmFileRef
+#include "EmTransport.h" // EmTransportDescriptor
+#include "Platform.h" // _stricmp
+
+#include <ctype.h> // isprint
+#include <stdio.h> // sscanf, sprintf
+
+// Handy macro for performing some common unsigned string compares.
+
+#define CHECK_STRING(s1, s2, v) \
+ if (_stricmp (s1.c_str(), s2) == 0) \
+ { \
+ value = v; \
+ return true; \
+ }
+
+
+
+// We convert a lot of numbers into strings; this value is the
+// minimum buffer size to hold the converted string.
+
+const int kMaxIntStringSize = 12; // sign + 4xxxyyyzzz + NULL
+
+
+
+
+// ----------------------------------------------------------------------
+// Our preferences routines need to convert our preference data to and
+// from string format (the format in which the data is stored on disk).
+// Following are a bunch of overloaded routines for converting strings
+// into all the data types we use for preferences.
+// ----------------------------------------------------------------------
+
+bool FromString (const string& s, bool& value)
+{
+ if (s == "0" || _stricmp (s.c_str (), "false") == 0)
+ value = false;
+ else
+ value = true;
+
+ return true;
+}
+
+
+bool FromString (const string& s, char& value)
+{
+ if (s.size () == 1 && isprint (s[0]))
+ {
+ value = s[0];
+ return true;
+ }
+
+ return false;
+}
+
+
+bool FromString (const string& s, signed char& value)
+{
+ short temp;
+ int result = sscanf (s.c_str (), "%hd", &temp);
+ if (result == 1)
+ value = (signed char) temp;
+ return result == 1;
+}
+
+
+bool FromString (const string& s, unsigned char& value)
+{
+ unsigned short temp;
+ int result = sscanf (s.c_str (), "%hu", &temp);
+ if (result == 1)
+ value = (unsigned char) temp;
+ return result == 1;
+}
+
+
+bool FromString (const string& s, signed short& value)
+{
+ int result = sscanf (s.c_str (), "%hd", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, unsigned short& value)
+{
+ int result = sscanf (s.c_str (), "%hu", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, signed int& value)
+{
+ int result = sscanf (s.c_str (), "%d", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, unsigned int& value)
+{
+ int result = sscanf (s.c_str (), "%u", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, signed long& value)
+{
+ int result = sscanf (s.c_str (), "%ld", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, unsigned long& value)
+{
+ int result = sscanf (s.c_str (), "%lu", &value);
+ return result == 1;
+}
+
+
+bool FromString (const string& s, string& value)
+{
+ value = s;
+ return true;
+}
+
+
+bool FromString (const string& s, char* value)
+{
+ strcpy (value, s.c_str ());
+ return true;
+}
+
+
+/*
+ // Seems to conflict with standard scalar types
+bool FromString (const string& s, Bool& value)
+{
+ bool temp;
+ if (::FromString (s, temp))
+ {
+ value = (Bool) temp;
+ return true;
+ }
+
+ return false;
+}
+*/
+
+
+bool FromString (const string& s, CloseActionType& value)
+{
+ CHECK_STRING (s, "SaveAlways", kSaveAlways)
+ CHECK_STRING (s, "SaveAsk", kSaveAsk)
+ CHECK_STRING (s, "SaveNever", kSaveNever)
+
+ return false;
+}
+
+
+bool FromString (const string& s, EmDevice& value)
+{
+ value = EmDevice (s);
+
+ return value.Supported () != 0;
+}
+
+
+bool FromString (const string& s, EmDirRef& value)
+{
+ return value.FromPrefString (s);
+}
+
+
+bool FromString (const string& s, EmErrorHandlingOption& value)
+{
+ CHECK_STRING (s, "ShowDialog", kShow)
+ CHECK_STRING (s, "Continue", kContinue)
+ CHECK_STRING (s, "Quit", kQuit)
+ CHECK_STRING (s, "NextGremlin", kSwitch)
+
+ return false;
+}
+
+
+bool FromString (const string& s, EmFileRef& value)
+{
+ return value.FromPrefString (s);
+}
+
+
+bool FromString (const string& s, EmTransportDescriptor& value)
+{
+ value = EmTransportDescriptor (s);
+ return true;
+}
+
+
+// ----------------------------------------------------------------------
+// Our preferences routine need to convert our preference data to and
+// from string format (the format in which the data is stored on disk).
+// Following are a bunch of overloaded routines for converting data
+// (in all the types we use for preferences) into strings.
+// ----------------------------------------------------------------------
+
+string ToString (bool value)
+{
+ if (value)
+ return "1";
+ return "0";
+}
+
+
+string ToString (char value)
+{
+ return string (1, value);
+}
+
+
+string ToString (signed char value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%hd", (short) value);
+ return buffer;
+}
+
+
+string ToString (unsigned char value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%hu", (unsigned short) value);
+ return buffer;
+}
+
+
+string ToString (signed short value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%hd", value);
+ return buffer;
+}
+
+
+string ToString (unsigned short value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%hu", value);
+ return buffer;
+}
+
+
+string ToString (signed int value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%d", value);
+ return buffer;
+}
+
+
+string ToString (unsigned int value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%u", value);
+ return buffer;
+}
+
+
+string ToString (signed long value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%ld", value);
+ return buffer;
+}
+
+
+string ToString (unsigned long value)
+{
+ char buffer[kMaxIntStringSize];
+ sprintf (buffer, "%lu", value);
+ return buffer;
+}
+
+
+string ToString (const string& value)
+{
+ return value;
+}
+
+
+string ToString (const char* value)
+{
+ return string (value);
+}
+
+
+/*
+
+ // Seems to conflict with standard scalar types
+string ToString (Bool value)
+{
+ return ::ToString ((bool) value);
+}
+
+*/
+
+
+string ToString (CloseActionType value)
+{
+ switch (value)
+ {
+ case kSaveAlways: return "SaveAlways";
+ case kSaveAsk: return "SaveAsk";
+ case kSaveNever: return "SaveNever";
+ }
+
+ return "";
+}
+
+
+string ToString (const EmDevice& value)
+{
+ return value.GetIDString ();
+}
+
+
+string ToString (const EmDirRef& value)
+{
+ return value.ToPrefString ();
+}
+
+
+string ToString (EmErrorHandlingOption value)
+{
+ switch (value)
+ {
+ case kShow: return "ShowDialog";
+ case kContinue: return "Continue";
+ case kQuit: return "Quit";
+ case kSwitch: return "NextGremlin";
+ }
+
+ return "";
+}
+
+
+string ToString (const EmFileRef& value)
+{
+ return value.ToPrefString ();
+}
+
+
+string ToString (const EmTransportDescriptor& value)
+{
+ return value.GetDescriptor ();
+}
diff --git a/SrcShared/StringConversions.h b/SrcShared/StringConversions.h
new file mode 100644
index 0000000..352ee9d
--- /dev/null
+++ b/SrcShared/StringConversions.h
@@ -0,0 +1,78 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef StringConversions_h
+#define StringConversions_h
+
+#include "EmDevice.h" // EmDevice
+
+#include <string>
+
+class EmDirRef;
+class EmFileRef;
+class EmTransportDescriptor;
+
+
+// ----------------------------------------------------------------------
+// Our preferences routines need to convert our preference data to and
+// from string format (the format in which the data is stored on disk).
+// Following are a bunch of overloaded routines for converting strings
+// into all the data types we use for preferences.
+// ----------------------------------------------------------------------
+
+bool FromString (const string& s, bool& value);
+bool FromString (const string& s, char& value);
+bool FromString (const string& s, signed char& value);
+bool FromString (const string& s, unsigned char& value);
+bool FromString (const string& s, signed short& value);
+bool FromString (const string& s, unsigned short& value);
+bool FromString (const string& s, signed int& value);
+bool FromString (const string& s, unsigned int& value);
+bool FromString (const string& s, signed long& value);
+bool FromString (const string& s, unsigned long& value);
+bool FromString (const string& s, string& value);
+bool FromString (const string& s, char* value);
+bool FromString (const string& s, CloseActionType& value);
+bool FromString (const string& s, EmDevice& value);
+bool FromString (const string& s, EmDirRef& value);
+bool FromString (const string& s, EmErrorHandlingOption& value);
+bool FromString (const string& s, EmFileRef& value);
+bool FromString (const string& s, EmTransportDescriptor& value);
+
+// ----------------------------------------------------------------------
+// Our preferences routines need to convert our preference data to and
+// from string format (the format in which the data is stored on disk).
+// Following are a bunch of overloaded routines for converting data
+// (in all the types we use for preferences) into strings.
+// ----------------------------------------------------------------------
+
+string ToString (bool value);
+string ToString (char value);
+string ToString (signed char value);
+string ToString (unsigned char value);
+string ToString (signed short value);
+string ToString (unsigned short value);
+string ToString (signed int value);
+string ToString (unsigned int value);
+string ToString (signed long value);
+string ToString (unsigned long value);
+string ToString (const string& value);
+string ToString (const char* value);
+string ToString (CloseActionType value);
+string ToString (const EmDevice& value);
+string ToString (const EmDirRef& value);
+string ToString (EmErrorHandlingOption value);
+string ToString (const EmFileRef& value);
+string ToString (const EmTransportDescriptor& value);
+
+#endif /* StringConversions_h */
diff --git a/SrcShared/StringData.cpp b/SrcShared/StringData.cpp
new file mode 100644
index 0000000..e9cfa30
--- /dev/null
+++ b/SrcShared/StringData.cpp
@@ -0,0 +1,265 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "StringData.h"
+
+// ---------------------------------------------------------------------------
+// ¥ Names of exception types
+// ---------------------------------------------------------------------------
+
+const char* kExceptionNames [] =
+{
+ "initStack", // initial stack pointer
+ "initPC", // initial PC
+
+ "busErr", // 08 / 2
+ "addressErr", // 0C / 3
+ "illegalInstr", // 10 / 4
+ "divideByZero", // 14 / 5
+ "chk", // 18 / 6
+ "trap", // 1C / 7
+ "privilege", // 20 / 8
+ "trace", // 24 / 9
+ "aTrap", // 28 / A
+ "fTrap", // 2C / B
+ "reserved12", // 30 / C
+ "coproc", // 34 / D
+ "formatErr", // 38 / E
+ "unitializedInt", // 3C / F
+
+ "reserved0", // 40-5C / 10-17
+ "reserved1",
+ "reserved2",
+ "reserved3",
+ "reserved4",
+ "reserved5",
+ "reserved6",
+ "reserved7",
+
+ "spuriousInt", // 60 / 18
+ "autoVec1", // 64 / 19
+ "autoVec2", // 68 / 1A
+ "autoVec3", // 6C / 1B
+ "autoVec4", // 70 / 1C
+ "autoVec5", // 74 / 1D
+ "autoVec6", // 78 / 1E
+ "autoVec7", // 7C / 1F
+
+ "trap0", // 80 - BC / 20 - 2F
+ "trap1",
+ "trap2",
+ "trap3",
+ "trap4",
+ "trap5",
+ "trap6",
+ "trap7",
+ "trap8",
+ "trap9",
+ "trap10",
+ "trap11",
+ "trap12",
+ "trap13",
+ "trap14",
+ "trap15",
+
+ "unassigned0", // C0 - FC / 30 - 3F
+ "unassigned1",
+ "unassigned2",
+ "unassigned3",
+ "unassigned4",
+ "unassigned5",
+ "unassigned6",
+ "unassigned7",
+ "unassigned8",
+ "unassigned9",
+ "unassigned10",
+ "unassigned11",
+ "unassigned12",
+ "unassigned13",
+ "unassigned14",
+ "unassigned15"
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ Names of system packets
+// ---------------------------------------------------------------------------
+
+const char* kPacketNames [256] =
+{
+ "sysPktStateCmd", // 0x00
+ "sysPktReadMemCmd", // 0x01
+ "sysPktWriteMemCmd", // 0x02
+ "sysPktSingleStepCmd", // 0x03
+ "sysPktGetRtnNameCmd", // 0x04
+ "sysPktReadRegsCmd", // 0x05
+ "sysPktWriteRegsCmd", // 0x06
+ "sysPktContinueCmd", // 0x07
+ NULL, // 0x08
+ NULL, // 0x09
+ "sysPktRPCCmd", // 0x0A
+ "sysPktGetBreakpointsCmd", // 0x0B
+ "sysPktSetBreakpointsCmd", // 0x0C
+// "sysPktRemoteUIUpdCmd", // 0x0B
+// "sysPktRemoteEvtCmd", // 0x0C
+ "sysPktDbgBreakToggleCmd", // 0x0D
+ "sysPktFlashCmd", // 0x0E
+ "sysPktCommCmd", // 0x0F
+ "sysPktGetTrapBreaksCmd", // 0x10
+ "sysPktSetTrapBreaksCmd", // 0x11
+ "sysPktGremlinsCmd", // 0x12
+ "sysPktFindCmd", // 0x13
+ "sysPktGetTrapConditionsCmd", // 0x14
+ "sysPktSetTrapConditionsCmd", // 0x15
+ "sysPktChecksumCmd", // 0x16
+ "sysPktExecFlashCmd", // 0x17
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x18 - 0x1F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x20 - 0x27
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x28 - 0x2F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x30 - 0x37
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x38 - 0x3F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x40 - 0x47
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x48 - 0x4F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x50 - 0x57
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x58 - 0x5F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x60 - 0x67
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x68 - 0x6F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x70 - 0x77
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x78 - 0x7E
+ "sysPktRemoteMsg", // 0x7F
+
+ "sysPktStateRsp", // 0x80
+ "sysPktReadMemRsp", // 0x81
+ "sysPktWriteMemRsp", // 0x82
+ "sysPktSingleStepRsp", // 0x83
+ "sysPktGetRtnNameRsp", // 0x84
+ "sysPktReadRegsRsp", // 0x85
+ "sysPktWriteRegsRsp", // 0x86
+ "sysPktContinueRsp", // 0x87
+ NULL, // 0x88
+ NULL, // 0x89
+ "sysPktRPCRsp", // 0x8A
+ "sysPktGetBreakpointsRsp", // 0x8B
+ "sysPktSetBreakpointsRsp", // 0x8C
+// "sysPktRemoteUIUpdRsp", // 0x8B
+// "sysPktRemoteEvtRsp", // 0x8C
+ "sysPktDbgBreakToggleRsp", // 0x8D
+ "sysPktFlashRsp", // 0x8E
+ "sysPktCommRsp", // 0x8F
+ "sysPktGetTrapBreaksRsp", // 0x90
+ "sysPktSetTrapBreaksRsp", // 0x91
+ "sysPktGremlinsRsp", // 0x92
+ "sysPktFindRsp", // 0x93
+ "sysPktGetTrapConditionsRsp", // 0x94
+ "sysPktSetTrapConditionsRsp", // 0x95
+ "sysPktChecksumRsp", // 0x96
+ "sysPktExecFlashRsp", // 0x97
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x98 - 0x9F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xA0 - 0xA7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xA8 - 0xAF
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xB0 - 0xB7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xB8 - 0xBF
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xC0 - 0xC7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xC8 - 0xCF
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xD0 - 0xD7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xD8 - 0xDF
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xE0 - 0xE7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xE8 - 0x6F
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xF0 - 0xF7
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0xF8 - 0xFE
+ "sysPktRemoteMsg" // 0xFF
+};
+
+
+// ---------------------------------------------------------------------------
+// ¥ VirtualKeyDescriptions
+// ---------------------------------------------------------------------------
+// Return a key description
+
+const char* kVirtualKeyDescriptions [] =
+{
+ " (vchrLowBattery)", // 0x0101
+ " (vchrEnterDebugger)", // 0x0102
+ " (vchrNextField)", // 0x0103
+ " (vchrStartConsole)", // 0x0104
+ " (vchrMenu)", // 0x0105
+ " (vchrCommand)", // 0x0106
+ " (vchrConfirm)", // 0x0107
+ " (vchrLaunch)", // 0x0108
+ " (vchrKeyboard)", // 0x0109
+ " (vchrFind)", // 0x010A
+ " (vchrCalc)", // 0x010B
+ " (vchrPrevField)", // 0x010C
+ " (vchrAlarm)", // 0x010D
+ " (vchrRonamatic)", // 0x010E
+ " (vchrGraffitiReference)", // 0x010F
+ " (vchrKeyboardAlpha)", // 0x0110
+ " (vchrKeyboardNumeric)", // 0x0111
+ " (vchrLock)", // 0x0112
+ " (vchrBacklight)", // 0x0113
+ " (vchrAutoOff)", // 0x0114
+ " (vchrExgTest)", // 0x0115
+ " (vchrSendData)", // 0x0116
+ " (vchrIrReceive)", // 0x0117
+ " (vchrTsm1)", // 0x0118
+ " (vchrTsm2)", // 0x0119
+ " (vchrTsm3)", // 0x011A
+ " (vchrTsm4)", // 0x011B
+ " (vchrRadioCoverageOK)", // 0x011C
+ " (vchrRadioCoverageFail)", // 0x011D
+ " (vchrPowerOff)", // 0x011E
+ " (vchrResumeSleep)", // 0x011F
+ " (vchrLateWakeup)", // 0x0120
+ " (vchrTsmMode)", // 0x0121
+ " (vchrBrightness)", // 0x0122
+ " (vchrContrast)", // 0x0123
+ " (vchrExpCardInserted)", // 0x0124
+ " (vchrExpCardRemoved)", // 0x0125
+ " (vchrAttnStateChanged)", // 0x0126
+ " (vchrAttnUnsnooze)", // 0x0127
+ " (vchrAttnIndicatorTapped)", // 0x0128
+ " (vchrAttnAllowClose)", // 0x0129
+ " (vchrAttnReopen)", // 0x012A
+ " (vchrCardCloseMenu)", // 0x012B
+ " (vchrIrGotData)" // 0x012C
+};
+
+const size_t gVirtualKeyDescriptionsCount = countof (kVirtualKeyDescriptions);
+
+const char* kHardKeyDescriptions [] =
+{
+ " (irObCloseChr)", // 0x01FB
+ " (irGotDataChr)", // 0x01FC - vchrIrGotData in 4.0
+ " (irInitLibChr)", // 0x01FD
+ " (irSerialChr)", // 0x01FE
+ " (vchrExgIntData)", // 0x01FF
+ "", // 0x0200
+ "", // 0x0201
+ "", // 0x0202
+ "", // 0x0203
+ " (vchrHard1)", // 0x0204
+ " (vchrHard2)", // 0x0205
+ " (vchrHard3)", // 0x0206
+ " (vchrHard4)", // 0x0207
+ " (vchrHardPower)", // 0x0208
+ " (vchrHardCradle)", // 0x0209
+ " (vchrHardCradle2)", // 0x020A
+ " (vchrHardContrast)", // 0x020B
+ " (vchrHardAntenna)", // 0x020C
+ " (vchrHardBrightness)" // 0x020D
+ " (vchrPageUpWhenOff)" // 0x020E
+ " (vchrHardEarbud)" // 0x020F
+};
+
+const size_t gHardKeyDescriptionsCount = countof (kHardKeyDescriptions);
diff --git a/SrcShared/StringData.h b/SrcShared/StringData.h
new file mode 100644
index 0000000..7efa9ad
--- /dev/null
+++ b/SrcShared/StringData.h
@@ -0,0 +1,25 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _STRINGDATA_H_
+#define _STRINGDATA_H_
+
+extern const char* kExceptionNames[];
+extern const char* kPacketNames[];
+extern const char* kVirtualKeyDescriptions[];
+extern const char* kHardKeyDescriptions[];
+
+extern const size_t gVirtualKeyDescriptionsCount;
+extern const size_t gHardKeyDescriptionsCount;
+
+#endif /* _STRINGDATA_H_ */
diff --git a/SrcShared/Strings.r.h b/SrcShared/Strings.r.h
new file mode 100644
index 0000000..8664287
--- /dev/null
+++ b/SrcShared/Strings.r.h
@@ -0,0 +1,549 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// Resource IDs for strings.
+
+// 1000 - 1999: Message Templates
+// 1000 - 1199: Error messages
+// 1200 - 1399: Other messages
+// 1400 - 1499: Menu strings
+// 2000 - xxxx: Template Parts
+// 2000 - 2199: Misc parts
+// 2200 - 2399: Operations descriptions
+// 2400 - 2599: Error descriptions
+// 2400 - 2499: OS Errors (e.g., "the file was not found")
+// 2500 - 2599: User/app errors (e.g., "I don't understand that file")
+// 2600 - 2799: Recovery strings (e.g., "Reboot and try again")
+// 2900 - 2964: Exception descriptions (e.g., "bus error")
+// 3000 - 4999: Palm OS system function names
+// 5000 - 6999: Palm OS Library function names
+// 7000 - xxxx: Palm OS Error descriptions
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Error messages
+// --------------------------------------------------------------------------------
+
+#pragma mark Message Templates -- Error messages
+
+#define kStr_OpError 1000
+#define kStr_OpErrorRecover 1001
+
+// Hardware Exceptions
+
+#define kStr_ErrBusError 1010
+#define kStr_ErrAddressError 1011
+#define kStr_ErrIllegalInstruction 1012
+#define kStr_ErrDivideByZero 1013
+#define kStr_ErrCHKInstruction 1014
+#define kStr_ErrTRAPVInstruction 1015
+#define kStr_ErrPrivilegeViolation 1016
+#define kStr_ErrTrace 1017
+#define kStr_ErrATrap 1018
+#define kStr_ErrFTrap 1019
+#define kStr_ErrTRAPx 1020
+
+// Special cases to hardware exceptions
+
+#define kStr_ErrStorageHeap 1030
+#define kStr_ErrNoDrawWindow 1031
+#define kStr_ErrNoGlobals 1032
+#define kStr_ErrSANE 1033
+#define kStr_ErrTRAP0 1034
+#define kStr_ErrTRAP8 1035
+
+// Fatal Poser-detected errors
+
+#define kStr_ErrStackOverflow 1040
+#define kStr_ErrUnimplementedTrap 1041
+#define kStr_ErrInvalidRefNum 1042
+#define kStr_ErrCorruptedHeap 1043
+#define kStr_ErrInvalidPC1 1044
+#define kStr_ErrInvalidPC2 1045
+
+// Non-fatal Poser-detected errors
+
+#define kStr_ErrLowMemory 1050
+#define kStr_ErrSystemGlobals 1051
+#define kStr_ErrScreen 1052
+#define kStr_ErrHardwareRegisters 1053
+#define kStr_ErrROM 1054
+#define kStr_ErrMemMgrStructures 1055
+#define kStr_ErrMemMgrSemaphore 1056
+#define kStr_ErrFreeChunk 1057
+#define kStr_ErrUnlockedChunk 1058
+#define kStr_ErrLowStack 1059
+#define kStr_ErrStackFull 1060
+#define kStr_ErrSizelessObject 1061
+#define kStr_ErrOffscreenObject 1062
+#define kStr_ErrFormAccess 1063
+#define kStr_ErrFormObjectListAccess 1064
+#define kStr_ErrFormObjectAccess 1065
+#define kStr_ErrWindowAccess 1066
+#define kStr_ErrBitmapAccess 1067
+#define kStr_ErrProscribedFunction 1068
+#define kStr_ErrStepSpy 1069
+#define kStr_ErrWatchpoint 1070
+#define kStr_ErrMemoryLeak 1071
+#define kStr_ErrMemoryLeaks 1072
+
+// Palm OS-detected errors
+
+#define kStr_ErrSysFatalAlert 1080
+#define kStr_ErrDbgMessage 1081
+
+// Other errors
+
+#define kStr_BadChecksum 1100
+#define kStr_UnknownDeviceWarning 1101
+#define kStr_UnknownDeviceError 1102
+#define kStr_MissingSkins 1103
+#define kStr_InconsistentDatabaseDates 1104
+#define kStr_NULLDatabaseDate 1105
+#define kStr_NeedHostFS 1106
+#define kStr_InvalidAddressNotEven 1107
+#define kStr_InvalidAddressNotInROMOrRAM 1108
+#define kStr_CannotParseCondition 1109
+#define kStr_UserNameTooLong 1110
+
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Other messages
+// --------------------------------------------------------------------------------
+
+#pragma mark Message Templates -- Other messages
+
+// Loading/saving
+
+#define kStr_SaveSessionAs 1200
+#define kStr_LoadSession 1201
+#define kStr_LoadSessionForReplay 1202
+#define kStr_LoadSessionForMinimize 1203
+#define kStr_SaveScreenAs 1204
+#define kStr_ImportFile 1205
+#define kStr_SaveBeforeClosing 1206
+#define kStr_SaveBeforeQuitting 1207
+
+#define kStr_GremlinNumber 1210
+#define kStr_GremlinXofYEvents 1211
+#define kStr_GremlinXEvents 1212
+#define kStr_GremlinElapsedTime 1213
+
+#define kStr_MinimizePassNumber 1220
+#define kStr_MinimizeXofYEvents 1221
+#define kStr_MinimizeElapsedTime 1222
+#define kStr_MinimizeRange 1223
+#define kStr_MinimizeDiscarded 1224
+
+#define kStr_AppAndVers 1230
+#define kStr_XofYFiles 1231
+#define kStr_GremlinStarted 1232
+#define kStr_GremlinEnded 1233
+#define kStr_EntireDevice 1234
+#define kStr_ErrDisplayMessage 1235
+#define kStr_UnknownFatalError 1236
+#define kStr_EmulatorOff 1237
+#define kStr_LogFileSize 1238
+#define kStr_InternalErrorException 1239
+#define kStr_InternalErrorMessage 1240
+#define kStr_WillNowReset 1241
+#define kStr_CommPortError 1242
+#define kStr_SocketsError 1243
+#define kStr_MustTurnOnLogging 1244
+#define kStr_MustTurnOnShowDialog 1245
+
+#define kStr_ROMTransferInstructions 1250 // ... 1258
+
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Menu strings
+// --------------------------------------------------------------------------------
+
+#define kStr_MenuSessionNew 1400
+#define kStr_MenuSessionOpenOther 1401
+#define kStr_MenuSessionClose 1402
+#define kStr_MenuSessionSave 1403
+#define kStr_MenuSessionSaveAs 1404
+#define kStr_MenuSessionBound 1405
+#define kStr_MenuScreenSave 1406
+#define kStr_MenuSessionInfo 1407
+
+#define kStr_MenuImportOther 1410
+#define kStr_MenuExport 1411
+#define kStr_MenuHotSync 1412
+#define kStr_MenuReset 1413
+#define kStr_MenuDownloadROM 1414
+
+#define kStr_MenuUndo 1420
+#define kStr_MenuCut 1421
+#define kStr_MenuCopy 1422
+#define kStr_MenuPaste 1423
+#define kStr_MenuClear 1424
+
+#define kStr_MenuPreferences 1430
+#define kStr_MenuLogging 1431
+#define kStr_MenuDebugging 1432
+#define kStr_MenuErrorHandling 1433
+#define kStr_MenuTracing 1434
+#define kStr_MenuSkins 1435
+#define kStr_MenuHostFS 1436
+#define kStr_MenuBreakpoints 1437
+
+#define kStr_MenuGremlinsNew 1440
+#define kStr_MenuGremlinsSuspend 1441
+#define kStr_MenuGremlinsStep 1442
+#define kStr_MenuGremlinsResume 1443
+#define kStr_MenuGremlinsStop 1444
+#define kStr_MenuEventReplay 1445
+#define kStr_MenuEventMinimize 1446
+
+#if HAS_PROFILING
+
+#define kStr_MenuProfileStart 1450
+#define kStr_MenuProfileStop 1451
+#define kStr_MenuProfileDump 1452
+
+#endif
+
+#define kStr_MenuAbout 1460
+#define kStr_MenuQuit 1461
+#define kStr_MenuFile 1462
+#define kStr_MenuEdit 1463
+#define kStr_MenuGremlins 1464
+#define kStr_MenuProfile 1465
+#define kStr_MenuOpen 1466
+#define kStr_MenuImport 1467
+#define kStr_MenuSettings 1468
+#define kStr_MenuEmpty 1469
+#define kStr_MenuBlank 1470
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Misc parts
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Misc parts
+
+#define kStr_AppName 2000
+#define kStr_Untitled 2001
+#define kStr_DefaultROMName 2002
+#define kStr_ProfileResults 2003
+#define kStr_Autoload 2004
+#define kStr_Autorun 2005
+#define kStr_AutorunAndQuit 2006
+
+#define kStr_ReadFrom 2010
+#define kStr_WroteTo 2011
+#define kStr_WrittenTo 2012
+
+#define kStr_CurrentAppUC 2020
+#define kStr_CurrentAppLC 2021
+#define kStr_UnknownVersion 2022
+
+#define kStr_OK 2030
+#define kStr_Cancel 2031
+#define kStr_Yes 2032
+#define kStr_No 2033
+#define kStr_Continue 2034
+#define kStr_Debug 2035
+#define kStr_Reset 2036
+
+#define kStr_Browse 2040
+#define kStr_EmptyMRU 2041
+#define kStr_OtherMRU 2042
+
+#define kStr_ProfPartial 2050
+#define kStr_ProfFunctions 2051
+#define kStr_ProfInterrupts 2052
+#define kStr_ProfOverflow 2053
+#define kStr_ProfInterruptX 2054
+#define kStr_ProfTrapNameAddress 2055
+#define kStr_ProfROMNameAddress 2056
+#define kStr_ProfDebugNameAddress 2057
+#define kStr_ProfUnknownName 2058
+
+#define kStr_UnknownTrapNumber 2060
+#define kStr_UnknownErrorCode 2061
+
+#define kStr_NoPort 2070
+
+#define kStr_ChunkNotInHeap 2080
+#define kStr_ChunkTooLarge 2081
+#define kStr_InvalidFlags 2082
+#define kStr_HOffsetNotInMPT 2083
+#define kStr_HOffsetNotBackPointing 2084
+#define kStr_InvalidLockCount 2085
+
+#define kStr_UnmappedAddress 2090
+#define kStr_NotInCodeSegment 2091
+#define kStr_OddAddress 2092
+
+#define kStr_Waiting 2100
+#define kStr_Transferring 2101
+
+// Reasons for why the PC was changed
+
+#define kStr_WhenRTS 2110
+#define kStr_WhenRTE 2111
+#define kStr_WhenJSR 2112
+#define kStr_WhenException 2113
+#define kStr_WhenSysCall 2114
+
+
+#define kStr_ShowInDialog 2120
+#define kStr_AutomaticallyContinue 2121
+#define kStr_AutomaticallyQuit 2122
+#define kStr_NextGremlin 2123
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Operations descriptions
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Operations descriptions
+
+#define kStr_GenericOperation 2200
+
+#define kStr_CmdAbout 2210
+
+#define kStr_CmdNew 2220
+#define kStr_CmdOpen 2221
+#define kStr_CmdClose 2222
+#define kStr_CmdSave 2223
+#define kStr_CmdSaveBound 2224
+#define kStr_CmdSaveScreen 2225
+#define kStr_CmdSessionInfo 2226
+#define kStr_CmdInstall 2227
+#define kStr_CmdInstallMany 2228
+#define kStr_CmdExportDatabase 2229
+#define kStr_CmdHotSync 2230
+#define kStr_CmdReset 2231
+#define kStr_CmdTransferROM 2232
+#define kStr_CmdQuit 2233
+
+#define kStr_CmdPreferences 2240
+#define kStr_CmdLoggingOptions 2241
+#define kStr_CmdDebugOptions 2242
+#define kStr_CmdErrorHandling 2243
+#define kStr_CmdSkins 2244
+#define kStr_CmdBreakpoints 2245
+#define kStr_CmdTracingOptions 2246
+#define kStr_CmdHostFSOptions 2247
+
+#define kStr_CmdGremlinNew 2250
+#define kStr_CmdGremlinSuspend 2251
+#define kStr_CmdGremlinStep 2252
+#define kStr_CmdGremlinResume 2253
+#define kStr_CmdGremlinStop 2254
+#define kStr_CmdEventReplay 2255
+#define kStr_CmdEventMinimize 2256
+
+#define kStr_CmdProfileStart 2260
+#define kStr_CmdProfileStop 2261
+#define kStr_CmdProfileDump 2262
+
+#define kStr_ResizeWindow 2270
+#define kStr_EnterKey 2271
+#define kStr_EnterPen 2272
+#define kStr_PressButton 2273
+#define kStr_OpenFiles 2274
+#define kStr_LoadPreferences 2275
+#define kStr_OpenTheSerialPort 2276
+
+#define kStr_CmdTracingSuspend 2280
+#define kStr_CmdTracingResume 2281
+#define kStr_CmdTracingReconnect 2282
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions -- OS Errors
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Error descriptions -- OS Errors
+
+#define kStr_GenericError 2400
+#define kStr_UserCancel 2401 // userCanceledErr
+#define kStr_TimeoutError 2402 // kernelTimeoutErr
+
+#define kStr_DirectoryFull 2410 // dirFulErr
+#define kStr_DiskFull 2411 // dskFulErr
+#define kStr_DiskMissing 2412 // nsvErr, volOffLinErr, volGoneErr
+#define kStr_IOError 2413 // ioErr
+#define kStr_BadFileName 2414 // bdNamErr
+#define kStr_TooManyFilesOpen 2415 // tmfoErr
+#define kStr_FileNotFound 2416 // fnfErr
+#define kStr_DiskWriteProtected 2417 // wPrErr
+#define kStr_FileLocked 2418 // fLckdErr, permErr
+#define kStr_DiskLocked 2419 // vLckdErr
+#define kStr_FileBusy 2420 // fBsyErr
+#define kStr_DuplicateFileName 2421 // dupFNErr
+
+#define kStr_MemFull 2430 // memFullErr, kError_OutOfMemory
+
+#define kStr_SerialPortBusy 2440
+
+#define kStr_GenericPalmError 2480
+#define kStr_DmErrDatabaseOpen 2481 // dmErrDatabaseOpen
+#define kStr_MemErrNotEnoughSpace 2482 // memErrNotEnoughSpace
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions -- User/app errors
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Error descriptions -- User/app errors
+
+#define kStr_OnlySameType 2500
+#define kStr_OnlyOnePSF 2501
+#define kStr_OnlyOneROM 2502
+#define kStr_UnknownType 2503
+
+#define kStr_OldFormat 2510
+#define kStr_WrongROMForType 2511 // kError_WrongROMForType
+
+#define kStr_BadROM 2520 // kError_BadROM
+#define kStr_UnsupportedROM 2521 // kError_UnsupportedROM
+#define kStr_InvalidDevice 2522 // kError_InvalidDevice
+#define kStr_InvalidSession 2523 // kError_InvalidSessionFile
+#define kStr_InvalidConfiguration 2524 // kError_InvalidConfiguration
+
+#define kStr_NameNotNULLTerminated 2530
+#define kStr_NameNotPrintable 2531
+#define kStr_FileTooSmall 2532
+#define kStr_nextRecordListIDNonZero 2533
+#define kStr_ResourceTooSmall 2534
+#define kStr_RecordTooSmall 2535
+#define kStr_ResourceOutOfRange 2536
+#define kStr_RecordOutOfRange 2537
+#define kStr_OverlappingResource 2538
+#define kStr_OverlappingRecord 2539
+#define kStr_ResourceMemError 2540
+#define kStr_RecordMemError 2541
+#define kStr_AppInfoMemError 2542
+#define kStr_DuplicateResource 2543
+
+#define kStr_SystemUseOnly 2550
+#define kStr_Obsolete 2551
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Recovery strings
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Recovery strings
+
+#define kStr_DeleteSomeFiles 2610
+#define kStr_UnlockTheDisk 2611
+#define kStr_UnlockTheFile 2612
+
+#define kStr_NeedMoreRAM 2620
+
+#define kStr_TransferAROM 2630
+#define kStr_DownloadAROM 2631
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Exception descriptions
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Exception descriptions
+
+#define kStr_ExceptionBase 2900
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Palm OS function names
+// --------------------------------------------------------------------------------
+
+#pragma mark Template Parts -- Palm OS function names
+
+#define kStr_SysTrapBase 3000
+
+#define kStr_LibTrapBase 5000
+#define kStr_HTALLibTrapBase kStr_LibTrapBase + 100
+#define kStr_INetLibTrapBase kStr_LibTrapBase + 200
+#define kStr_IrLibTrapBase kStr_LibTrapBase + 300
+#define kStr_NetLibTrapBase kStr_LibTrapBase + 400
+#define kStr_NPILibTrapBase kStr_LibTrapBase + 500
+#define kStr_RailLibTrapBase kStr_LibTrapBase + 600
+#define kStr_SecLibTrapBase kStr_LibTrapBase + 700
+#define kStr_SerLibTrapBase kStr_LibTrapBase + 800
+#define kStr_WebLibTrapBase kStr_LibTrapBase + 900
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions
+// --------------------------------------------------------------------------------
+#pragma mark Template Parts -- Palm OS Error descriptions
+
+#define kStr_PalmOSErrorBase 7000
+
+// Copied from SystemMgr.h -- needed for string ID assignments
+
+/************************************************************
+ * Error Classes for each manager
+ *************************************************************/
+#define errNone 0x0000 // No error
+
+#define memErrorClass 0x0100 // Memory Manager
+#define dmErrorClass 0x0200 // Data Manager
+#define serErrorClass 0x0300 // Serial Manager
+#define slkErrorClass 0x0400 // Serial Link Manager
+#define sysErrorClass 0x0500 // System Manager
+#define fplErrorClass 0x0600 // Floating Point Library
+#define flpErrorClass 0x0680 // New Floating Point Library
+#define evtErrorClass 0x0700 // System Event Manager
+#define sndErrorClass 0x0800 // Sound Manager
+#define almErrorClass 0x0900 // Alarm Manager
+#define timErrorClass 0x0A00 // Time Manager
+#define penErrorClass 0x0B00 // Pen Manager
+#define ftrErrorClass 0x0C00 // Feature Manager
+#define cmpErrorClass 0x0D00 // Connection Manager (HotSync)
+#define dlkErrorClass 0x0E00 // Desktop Link Manager
+#define padErrorClass 0x0F00 // PAD Manager
+#define grfErrorClass 0x1000 // Graffiti Manager
+#define mdmErrorClass 0x1100 // Modem Manager
+#define netErrorClass 0x1200 // Net Library
+#define htalErrorClass 0x1300 // HTAL Library
+#define inetErrorClass 0x1400 // INet Library
+#define exgErrorClass 0x1500 // Exg Manager
+#define fileErrorClass 0x1600 // File Stream Manager
+#define rfutErrorClass 0x1700 // RFUT Library
+#define txtErrorClass 0x1800 // Text Manager
+#define tsmErrorClass 0x1900 // Text Services Library
+#define webErrorClass 0x1A00 // Web Library
+#define secErrorClass 0x1B00 // Security Library
+#define emuErrorClass 0x1C00 // Emulator Control Manager
+#define flshErrorClass 0x1D00 // Flash Manager
+#define pwrErrorClass 0x1E00 // Power Manager
+#define cncErrorClass 0x1F00 // Connection Manager (Serial Communication)
+#define actvErrorClass 0x2000 // Activation application
+#define radioErrorClass 0x2100 // Radio Manager (Library)
+#define dispErrorClass 0x2200 // Display Driver Errors.
+#define bltErrorClass 0x2300 // Blitter Driver Errors.
+#define winErrorClass 0x2400 // Window manager.
+#define omErrorClass 0x2500 // Overlay Manager
+#define menuErrorClass 0x2600 // Menu Manager
+#define lz77ErrorClass 0x2700 // Lz77 Library
+#define smsErrorClass 0x2800 // Sms Library
+#define expErrorClass 0x2900 // Expansion Manager and Slot Driver Library
+#define vfsErrorClass 0x2A00 // Virtual Filesystem Manager and Filesystem library
+#define lmErrorClass 0x2B00 // Locale Manager
+#define intlErrorClass 0x2C00 // International Manager
+#define pdiErrorClass 0x2D00 // PDI Library
+#define attnErrorClass 0x2E00 // Attention Manager
+#define telErrorClass 0x2F00 // Telephony Manager
+#define hwrErrorClass 0x3000 // Hardware Manager (HAL)
+#define blthErrorClass 0x3100 // Bluetooth Library Error Class
+#define udaErrorClass 0x3200 // UDA Manager Error Class
+
+#define errInfoClass 0x7F00 // special class shows information w/o error code
+#define appErrorClass 0x8000 // Application-defined errors
+
diff --git a/SrcShared/Strings.txt b/SrcShared/Strings.txt
new file mode 100644
index 0000000..70320c5
--- /dev/null
+++ b/SrcShared/Strings.txt
@@ -0,0 +1,7302 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+// 1000 - 1999: Message Templates
+// 1000 - 1199: Error messages
+// 1200 - 1399: Other messages
+// 1400 - 1499: Menu strings
+// 2000 - 2999: Template Parts
+// 2000 - 2199: Misc parts
+// 2200 - 2399: Operations descriptions
+// 2400 - 2599: Error descriptions
+// 2400 - 2499: OS Errors (e.g., "the file was not found")
+// 2500 - 2599: User/app errors (e.g., "I don't understand that file")
+// 2600 - 2799: Recovery strings (e.g., "Reboot and try again")
+// 2900 - 2964: Exception descriptions (e.g., "bus error")
+// 3000 - 4999: Palm OS system function names
+// 5000 - 6999: Palm OS Library function names
+// 7000 - xxxx: Palm OS Error descriptions
+
+#include "Strings.r.h" // kStr_ values
+
+
+
+START
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Error messages
+// --------------------------------------------------------------------------------
+
+ID=kStr_OpError
+ENGLISH=Could not %operation because %reason.
+
+ID=kStr_OpErrorRecover
+ENGLISH=Could not %operation because %reason. %recovery.
+
+
+// Hardware Exceptions
+
+ID=kStr_ErrBusError
+ENGLISH=%App just %op memory location %mem, causing a bus error.\n\nA Òbus errorÓ means that the application accessed a memory location that is not in RAM or ROM, nor corresponds to a memory-mapped hardware register.
+
+ID=kStr_ErrAddressError
+ENGLISH=%App just %op memory location %mem, causing an address error.\n\nAn Òaddress errorÓ means that the application accessed a 2- or 4-byte value at an odd (i.e., not even) memory address.
+
+ID=kStr_ErrIllegalInstruction
+ENGLISH=%App just executed an illegal or unknown machine language instruction. The opcode executed was %ins.
+
+ID=kStr_ErrDivideByZero
+ENGLISH=%App just divided an integer by zero.
+
+ID=kStr_ErrCHKInstruction
+ENGLISH=%App just executed a CHK machine language instruction that failed. Invoking this instruction is not supported in Palm OS applications.
+
+ID=kStr_ErrTRAPVInstruction
+ENGLISH=%App just executed a TRAPV machine language instruction that failed. Invoking this instruction is not supported in Palm OS applications.
+
+ID=kStr_ErrPrivilegeViolation
+ENGLISH=%App just executed opcode %ins, a privileged machine language instruction.\n\nA Òprivileged machine language instructionÓ is one reserved for use by the operating system. Invoking such instructions is not supported in Palm OS applications.
+
+ID=kStr_ErrTrace
+ENGLISH=%App just executed an instruction with the CPUÕs ÒtraceÓ mode enabled. Normally, this mode is enabled by a debugger for the purpose of single-stepping through an application. However, no debugger is currently connected to handle trace mode.
+
+ID=kStr_ErrATrap
+ENGLISH=%App just executed an illegal or unknown machine language instruction. The opcode executed was %ins.
+
+ID=kStr_ErrFTrap
+ENGLISH=%App just executed an illegal or unknown machine language instruction. The opcode executed was %ins.
+
+ID=kStr_ErrTRAPx
+ENGLISH=%App just executed a ÒTRAP #%numÓ machine language instruction. Invoking such instructions is not supported in Palm OS applications.
+
+
+// Special cases to hardware exceptions
+
+ID=kStr_ErrStorageHeap
+ENGLISH=%App just %op memory location %mem, which is in the storage heap. In order to protect the integrity of the userÕs data, such direct access is not allowed. Instead, applications should use special Palm OS functions for this purpose.
+
+ID=kStr_ErrNoDrawWindow
+ENGLISH=%App just %op memory location %mem. This access usually indicates that the application is calling a Window Manager function without first establishing a valid DrawWindow.
+
+ID=kStr_ErrNoGlobals
+ENGLISH=%App just %op memory location %mem. This access usually means that the application accessed a global variable after PilotMain was called with a launch code that does not support globals. The last launch code sent to the application was Ò%launch_codeÓ.
+
+ID=kStr_ErrSANE
+ENGLISH=%App just performed a floating point operation using a calling sequence specific to the Mac OS. This indicates that the application was compiled with the incorrect Floating Point option in the development environment that created it.
+
+ID=kStr_ErrTRAP0
+ENGLISH=%App just executed a ÒTRAP #0Ó machine language instruction. This instruction is often used by debuggers to set breakpoints. However, no debugger is currently connected to handle the breakpoint.
+
+ID=kStr_ErrTRAP8
+ENGLISH=%App just executed a ÒTRAP #8Ó machine language instruction. This instruction is generated when calling the DbgBreak function as a method for breaking into an external debugger. However, no debugger is currently connected.
+
+
+// Fatal Poser-detected errors
+
+ID=kStr_ErrStackOverflow
+ENGLISH=%App has overflowed the stack. The functions currently using the stack are: %sc.
+
+ID=kStr_ErrUnimplementedTrap
+ENGLISH=%App called Palm OS routine #%trap_num (%trap_name). This routine does not exist in this version of the Palm OS.
+
+ID=kStr_ErrInvalidRefNum
+ENGLISH=%App called a function in a shared library using a reference number of %ref_num. This reference number does not correspond to any currently installed library and is invalid.
+
+ID=kStr_ErrCorruptedHeap
+ENGLISH=During a regular checkup, Palm OS Emulator determined that the dynamic heap chunk with header address %mem got corrupted. %corruption_type.
+
+ID=kStr_ErrInvalidPC1
+ENGLISH=%App just changed the emulated program counter to %mem. This address is invalid because %reason.
+
+ID=kStr_ErrInvalidPC2
+ENGLISH=%App just changed the emulated program counter to %mem. This address is invalid because %reason. The program counter was changed when %when.
+
+
+// Non-fatal Poser-detected errors
+
+ID=kStr_ErrLowMemory
+ENGLISH=%App just %op memory location %mem, which is in low memory.\n\nÒLow memoryÓ is defined as the first 256 bytes of memory. It should not be directly accessed by applications under any circumstances.
+
+ID=kStr_ErrSystemGlobals
+ENGLISH=%App just %op memory location %mem, which is in the Palm OS global variables.\n\nÒPalm OS global variablesÓ are memory locations reserved for the private use of the Palm OS. They should not be directly accessed by applications under any circumstances.
+
+ID=kStr_ErrScreen
+ENGLISH=%App just %op memory location %mem, which is in screen memory.\n\nÒScreen memoryÓ is the area of RAM containing the pixels appearing on the LCD display. It should not be directly accessed by applications under any circumstances. Instead, they should use the Window Manager functions for altering the contents of the display.
+
+ID=kStr_ErrHardwareRegisters
+ENGLISH=%App just %op memory location %mem, which is in the memory-mapped hardware registers.\n\nÒMemory-mapped hardware registersÓ are memory locations that control the operation of your handheld deviceÕs hardware. They should not be directly accessed by applications under any circumstances.
+
+ID=kStr_ErrROM
+ENGLISH=%App just %op memory location %mem, which is in the ROM.\n\nSuch an access has no effect, and usually indicates an error in the application.
+
+ID=kStr_ErrMemMgrStructures
+ENGLISH=%App just %op memory location %mem, which is in Memory Manager data structures.\n\nThese data structures include things like the headers preceding each block in a heap, as well as the heap header itself. Such an access usually means that an application allocated a buffer (possibly with MemPtrNew) that wasnÕt large enough for its purpose. When the application then tries to write data to the buffer, it writes off the end of the buffer, accessing the start of the buffer following it in memory.
+
+ID=kStr_ErrMemMgrSemaphore
+ENGLISH=The Memory Manager semaphore has been held for longer than 1 minute. Palm recommends that applications not acquire the Memory Manager semaphore at all, but that if they do, they should not hold the semaphore any longer than that.
+
+ID=kStr_ErrFreeChunk
+ENGLISH=%App just %op memory location %mem, which is in an unallocated chunk of memory.\n\nAn Òunallocated chunk of memoryÓ is a chunk of memory that has not been reserved for use by the application through calling MemPtrNew or MemHandleNew. It should not be accessed by applications under any circumstances. Such an access usually means that an application is accessing a chunk that used to be allocated to the application but has since been returned with MemPtrFree or MemHandleFree.
+
+ID=kStr_ErrUnlockedChunk
+ENGLISH=%App just %op memory location %mem, which is in an unlocked chunk of memory.\n\nAn Òunlocked chunk of memoryÓ is one that has been allocated with MemHandleNew but that has not been locked with MemHandleLock. Such an access usually means that an application allocated a buffer with MemHandleNew, locked it with MemHandleLock, unlocked it with MemHandleUnlock, and then used the pointer that was returned by MemHandleLock.
+
+ID=kStr_ErrLowStack
+ENGLISH=%App just %op memory location %mem, which is in the unused portion of the stack. The stack range is %stack_low - %stack_high, and the stack pointer is %stack_pointer.\n\nThe ÒstackÓ is the area of RAM used to contain function parameters and local variables. The used portion of the stack is indicated by the stack pointer. Applications may access the area of the stack above the stack pointer, but not below it.
+
+ID=kStr_ErrStackFull
+ENGLISH=%App is close to overflowing the stack. The functions currently using the stack are: %sc.
+
+ID=kStr_ErrSizelessObject
+ENGLISH=Form object ID #%obj_id (left = %left, top = %top, right = %right, bottom = %bottom) from %app has a height or width of zero. Applications should hide objects by calling FrmHideObject instead of setting their dimensions to zero.\n\nAnother way to get this error message is to call FrmCopyTitle or FrmCopyLabel to change a title or label to a string larger than what was specified in the form resource. Doing this often corrupts other objects on the form.
+
+ID=kStr_ErrOffscreenObject
+ENGLISH=Form object ID #%obj_id (left = %left, top = %top, right = %right, bottom = %bottom) from %app is completely offscreen. Applications should hide objects by calling FrmHideObject instead of placing them completely offscreen.\n\nAnother way to get this error message is to call FrmCopyTitle or FrmCopyLabel to change a title or label to a string larger than what was specified in the form resource. Doing this often corrupts other objects on the form.
+
+ID=kStr_ErrFormAccess
+ENGLISH=%App just %op memory location %mem, which is in the Ò%fieldÓ field of the form starting at %form.\n\nThe data at this memory location is owned by the Form Manager. Applications should not access the data directly. Instead, they should make the appropriate Form Manager calls.
+
+ID=kStr_ErrFormObjectListAccess
+ENGLISH=%App just %op memory location %mem, which is in the Ò%fieldÓ field of the form object list entry with index #%index, which belongs to the form starting at %form.\n\nThe data at this memory location is owned by the Form Manager. Applications should not access the data directly. Instead, they should make the appropriate Form Manager calls.
+
+ID=kStr_ErrFormObjectAccess
+ENGLISH=%App just %op memory location %mem, which is in the Ò%fieldÓ field of the %type starting at %object, which belongs to the form starting at %form.\n\nThe data at this memory location is owned by the Form Manager. Applications should not access the data directly. Instead, they should make the appropriate Form Manager calls.
+
+ID=kStr_ErrWindowAccess
+ENGLISH=%App just %op memory location %mem, which is in the Ò%fieldÓ field of the window starting at %window.\n\nThe data at this memory location is owned by the Window Manager. Applications should not access the data directly. Instead, they should make the appropriate Window Manager calls.
+
+ID=kStr_ErrBitmapAccess
+ENGLISH=%App just %op memory location %mem, which is in the Ò%fieldÓ field of the bitmap starting at %bitmap.\n\nThe data at this memory location is owned by the Palm OS. Applications should not access the data directly. Instead, they should make the appropriate Palm OS calls.
+
+ID=kStr_ErrProscribedFunction
+ENGLISH=%App just called Palm OS routine Ò%function_nameÓ.\n\nApplications should not call this function because %reason.
+
+ID=kStr_ErrStepSpy
+ENGLISH=%App just %op memory location %mem, changing it from %old_value to %new_value.
+
+ID=kStr_ErrWatchpoint
+ENGLISH=%App just %op memory location %mem, which is in the range from %watch_start to %watch_end specified in the Breakpoint dialog box.
+
+ID=kStr_ErrMemoryLeak
+ENGLISH=Found %num_leaks memory leak for %app. Information concerning the leak can be found in the log file.
+
+ID=kStr_ErrMemoryLeaks
+ENGLISH=Found %num_leaks memory leaks for %app. Information concerning the leaks can be found in the log file.
+
+
+// Palm OS-detected errors
+
+ID=kStr_ErrSysFatalAlert
+ENGLISH=%App called SysFatalAlert with the message: Ò%messageÓ.
+
+ID=kStr_ErrDbgMessage
+ENGLISH=%App called DbgMessage with the message: Ò%messageÓ.
+
+
+// Other errors
+
+ID=kStr_BadChecksum
+ENGLISH=The ROM youÕve chosen has an invalid checksum.\n
+ \n
+ The most common reason for an invalid checksum has been from the use of
+ utility programs that modify the contents of the ROM without also updating
+ its internal checksum.\n
+ \n
+ Palm, Inc. does not support the use of this ROM. Use it with caution.
+
+ID=kStr_UnknownDeviceWarning
+ENGLISH=Unable to determine an appropriate device to emulate for this ROM file.\n
+ \n
+ Palm, Inc. does not support the use of this ROM. Use it with caution,
+ as the operation of a ROM with an incorrect device emulation will certainly
+ cause the ROM to crash, and may crash the Palm OS Emulator.
+
+ID=kStr_UnknownDeviceError
+ENGLISH=This ROM is for a device not supported by this version of the emulator.\n
+ \n
+ Palm, Inc. does not support the use of this ROM.
+
+ID=kStr_MissingSkins
+ENGLISH=Palm OS Emulator needs ÒskinÓ files in order to correctly
+ display the hardware devices it emulates. The Emulator looks
+ for these skins in a directory called ÒSkinsÓ. However,
+ that directory was not found.\n
+ \n
+ Previous versions of the Emulator would look for any directory
+ starting with the word ÒSkinsÓ and search that directory for
+ skin files. With the current Emulator, the directory must be
+ named exactly ÒSkinsÓ.\n
+ \n
+ If you donÕt have any skin files at all, you can download them
+ from the Emulator download Web page:\n
+ \n
+ <http://www.palmos.com/dev/tech/tools/emulator>\n
+ \n
+ Follow the instructions included with that archive for installing
+ the files.
+
+ID=kStr_InconsistentDatabaseDates
+ENGLISH=The creation date (%cr_date) in the database header inside Ò%database_nameÓ is
+ more recent than the modification date (%mod_date).\n
+ \n
+ The Emulator does not consider this to be a problem, and neither does the Palm
+ OS. However, some versions of HotSync will test for this condition and report
+ an error, so you may wish to fix the database before trying to install it on a
+ device.
+
+ID=kStr_NULLDatabaseDate
+ENGLISH=The creation date in the database header inside Ò%database_nameÓ is zero.\n
+ \n
+ The Emulator does not consider this to be a problem, and neither does the Palm
+ OS. However, some versions of HotSync will test for this condition and report
+ an error, so you may wish to fix the database before trying to install it on a
+ device.
+
+ID=kStr_NeedHostFS
+ENGLISH=In order to make use of the information specified in this dialog,
+ you need to have installed HostFS.prc. You can download this file from
+ the Palm OS Emulator download Web page:\n
+ \n
+ <http://www.palmos.com/dev/tech/tools/emulator/>
+
+ID=kStr_InvalidAddressNotEven
+ENGLISH=The address "%s" is invalid because it is not even.
+
+ID=kStr_InvalidAddressNotInROMOrRAM
+ENGLISH=The address "%s" is invalid because it is not in ROM or RAM.
+
+ID=kStr_CannotParseCondition
+ENGLISH=Can't parse the condition "%s".
+
+ID=kStr_UserNameTooLong
+ENGLISH=The name entered into the HotSync User Name field is too long. It needs
+ to be 40 characters or less.
+
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Other messages
+// --------------------------------------------------------------------------------
+
+ID=kStr_SaveSessionAs
+ENGLISH=Save session as:
+
+ID=kStr_LoadSession
+ENGLISH=Load session:
+
+ID=kStr_LoadSessionForReplay
+ENGLISH=Load session for replay:
+
+ID=kStr_LoadSessionForMinimize
+ENGLISH=Load session for minimize:
+
+ID=kStr_SaveScreenAs
+ENGLISH=Save screen as:
+
+ID=kStr_ImportFile
+ENGLISH=Import file:
+
+ID=kStr_SaveBeforeClosing
+ENGLISH=Save changes to the %AppName document Ò%DocNameÓ before closing?
+
+ID=kStr_SaveBeforeQuitting
+ENGLISH=Save changes to the %AppName document Ò%DocNameÓ before quitting?
+
+
+ID=kStr_GremlinNumber
+ENGLISH=Gremlin #%gremlin_number
+
+ID=kStr_GremlinXofYEvents
+ENGLISH=Event %current_event of %last_event
+
+ID=kStr_GremlinXEvents
+ENGLISH=Event %current_event
+
+ID=kStr_GremlinElapsedTime
+ENGLISH=Elapsed Time: %elapsed_time
+
+
+ID=kStr_MinimizePassNumber
+ENGLISH=Pass #%pass_number
+
+ID=kStr_MinimizeXofYEvents
+ENGLISH=Event %current_event of %last_event
+
+ID=kStr_MinimizeElapsedTime
+ENGLISH=Elapsed Time: %elapsed_time
+
+ID=kStr_MinimizeRange
+ENGLISH=Excluding range %first_event to %last_event
+
+ID=kStr_MinimizeDiscarded
+ENGLISH=Discarded %num_discarded_events of %num_total_events events
+
+
+ID=kStr_AppAndVers
+ENGLISH=%application %version
+
+ID=kStr_XofYFiles
+ENGLISH=%d of %d files
+
+ID=kStr_GremlinStarted
+ENGLISH=Gremlin #%d started, %ld steps.\n
+
+ID=kStr_GremlinEnded
+ENGLISH=Gremlin #%d stopped at event %ld of %ld after %ld milliseconds.\n
+
+ID=kStr_EntireDevice
+ENGLISH=Entire Palm OS device
+
+ID=kStr_ErrDisplayMessage
+ENGLISH=%s, Line: %d, %s
+
+ID=kStr_UnknownFatalError
+ENGLISH=Unknown fatal error occurred!
+
+ID=kStr_EmulatorOff
+ENGLISH=The emulator is not ready to %s at this time.\n(Perhaps it is turned off?)
+
+ID=kStr_LogFileSize
+ENGLISH============================================================\n
+ This file contains only the last %ldK of generated text.\n
+ ===========================================================\n\n
+
+ID=kStr_InternalErrorException
+ENGLISH=Hardware exception #%d occurred while the emulator was calling the Palm OS function Ò%sÓ.
+
+ID=kStr_InternalErrorMessage
+ENGLISH=%s\n\nThe error occurred while the emulator was calling the Palm OS function Ò%sÓ.
+
+ID=kStr_WillNowReset
+ENGLISH= The emulator is now in an unstable state and will reset.
+
+ID=kStr_CommPortError
+ENGLISH=The emulator could not open port %transport. Please make sure that it is not in use by another application, and that the emulated IR and Serial ports are not mapped to the same physical port, then reconfirm your port selection in PreferencesÉ.
+
+ID=kStr_SocketsError
+ENGLISH=The emulator could not open a sockets connection to %transport. Please check your TCP settings, and then reconfirm your host selection in PreferencesÉ.
+
+ID=kStr_MustTurnOnLogging
+ENGLISH=In order to utilize error handling options that don't display messages in a dialog box, the corresponding logging options must be turned on. Should those options be turned on now?
+
+ID=kStr_MustTurnOnShowDialog
+ENGLISH=In order to safely turn off logging options for errors and warnings, the corresponding error handling options must be set to "Show in dialog". Should those options be set now?
+
+
+ID=kStr_ROMTransferInstructions+0
+ENGLISH=1. You should find a file named ÒROM Transfer.prcÓ included\n
+ with the Palm OS Emulator. This is a Palm OS application\n
+ you should install on your Palm OS device before continuing.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+1
+ENGLISH=2. Choose an appropriate serial port and speed from the menus\n
+ below. Faster speeds do not always work correctly. Choose\n
+ a slower speed if you experience problems.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+2
+ENGLISH=3. Place your Palm OS device in its cradle and run the ÒROM\n
+ TransferÓ application.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+3
+ENGLISH=4. Select the same speed from the menu in ÒROM TransferÓ as\n
+ you chose below.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+4
+ENGLISH=5. Disable HotSync or any other application that may be using\n
+ the selected serial port.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+5
+ENGLISH=6. Tap the ÒBegin TransferÓ button in the ÒROM TransferÓ\n
+ application on the Palm device.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+6
+ENGLISH=7. Click the ÒBeginÓ button in this dialog. The Palm OS\n
+ Emulator will wait for your Palm device to respond.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+7
+ENGLISH=8. The transfer will take several minutes, so please be patient.\n
+ If an error occurs during the transfer, the application may\n
+ be unresponsive or may appear to hang. If this happens,\n
+ wait for a few minutes to give the application a chance to\n
+ time-out. It should then resume normal operation.\n
+ \n
+
+ID=kStr_ROMTransferInstructions+8
+ENGLISH=9. After the ROM has been transferred to your desktop computer,\n
+ you will be asked to save it to a file. Save it with an\n
+ appropriate name (for example, ÒPalm III.romÓ). Then\n
+ create a a new emulator session using that ROM.
+
+
+// --------------------------------------------------------------------------------
+// Message Templates -- Menu strings
+// --------------------------------------------------------------------------------
+
+ID=kStr_MenuSessionNew
+ENGLISH=&NewÉ\tN
+
+ID=kStr_MenuSessionOpenOther
+ENGLISH=&OtherÉ\tO
+
+ID=kStr_MenuSessionClose
+ENGLISH=&Close\tW
+
+ID=kStr_MenuSessionSave
+ENGLISH=&Save\tS
+
+ID=kStr_MenuSessionSaveAs
+ENGLISH=Save &AsÉ
+
+ID=kStr_MenuSessionBound
+ENGLISH=Save &Bound EmulatorÉ
+
+ID=kStr_MenuScreenSave
+ENGLISH=Sa&ve ScreenÉ\tM
+
+ID=kStr_MenuSessionInfo
+ENGLISH=Session InfoÉ
+
+ID=kStr_MenuImportOther
+ENGLISH=&OtherÉ\tI
+
+ID=kStr_MenuExport
+ENGLISH=Export &DatabaseÉ
+
+ID=kStr_MenuHotSync
+ENGLISH=&HotSync\tH
+
+ID=kStr_MenuReset
+ENGLISH=&ResetÉ\tR
+
+ID=kStr_MenuDownloadROM
+ENGLISH=&Transfer ROMÉ\tD
+
+ID=kStr_MenuUndo
+ENGLISH=&Undo\tZ
+
+ID=kStr_MenuCut
+ENGLISH=Cu&t\tX
+
+ID=kStr_MenuCopy
+ENGLISH=&Copy\tC
+
+ID=kStr_MenuPaste
+ENGLISH=&Paste\tV
+
+ID=kStr_MenuClear
+ENGLISH=Clea&r
+
+#if PLATFORM_WINDOWS
+
+ID=kStr_MenuPreferences
+ENGLISH=&PropertiesÉ\t/
+
+#else
+
+ID=kStr_MenuPreferences
+ENGLISH=&PreferencesÉ\t/
+
+#endif
+
+ID=kStr_MenuLogging
+ENGLISH=&LoggingÉ\tL
+
+ID=kStr_MenuDebugging
+ENGLISH=&DebuggingÉ\t\\
+
+ID=kStr_MenuErrorHandling
+ENGLISH=&Error HandlingÉ\tE
+
+ID=kStr_MenuTracing
+ENGLISH=&TracingÉ\tT
+
+ID=kStr_MenuSkins
+ENGLISH=&SkinsÉ\tK
+
+ID=kStr_MenuHostFS
+ENGLISH=&HostFSÉ
+
+ID=kStr_MenuBreakpoints
+ENGLISH=&BreakpointsÉ\tB
+
+ID=kStr_MenuGremlinsNew
+ENGLISH=&NewÉ\tG
+
+ID=kStr_MenuGremlinsStep
+ENGLISH=&Step
+
+ID=kStr_MenuGremlinsResume
+ENGLISH=&Resume
+
+ID=kStr_MenuGremlinsStop
+ENGLISH=Sto&p
+
+ID=kStr_MenuEventReplay
+ENGLISH=Repla&yÉ
+
+ID=kStr_MenuEventMinimize
+ENGLISH=&MinimizeÉ
+
+#if HAS_PROFILING
+
+ID=kStr_MenuProfileStart
+ENGLISH=&Start\t[
+
+ID=kStr_MenuProfileStop
+ENGLISH=Sto&p\t]
+
+ID=kStr_MenuProfileDump
+ENGLISH=&Dump
+
+#endif
+
+ID=kStr_MenuAbout
+ENGLISH=About Palm OS¨ Emulator
+
+#if PLATFORM_WINDOWS
+
+ID=kStr_MenuQuit
+ENGLISH=E&xit\tQ
+
+#else
+
+ID=kStr_MenuQuit
+ENGLISH=&Quit\tQ
+
+#endif
+
+ID=kStr_MenuFile
+ENGLISH=File
+
+ID=kStr_MenuEdit
+ENGLISH=Edit
+
+ID=kStr_MenuGremlins
+ENGLISH=Gremlins
+
+ID=kStr_MenuProfile
+ENGLISH=Profile
+
+ID=kStr_MenuOpen
+ENGLISH=&Open
+
+ID=kStr_MenuImport
+ENGLISH=&Install Application/Database
+
+ID=kStr_MenuSettings
+ENGLISH=S&ettings
+
+ID=kStr_MenuEmpty
+ENGLISH=(empty)
+
+ID=kStr_MenuBlank
+ENGLISH=
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Misc parts
+// --------------------------------------------------------------------------------
+
+ID=kStr_AppName
+ENGLISH=Palm OS¨ Emulator
+
+ID=kStr_Untitled
+ENGLISH=untitled
+
+ID=kStr_DefaultROMName
+ENGLISH=Palm.ROM
+
+ID=kStr_ProfileResults
+ENGLISH=Profile Results
+
+ID=kStr_Autoload
+ENGLISH=Autoload
+
+ID=kStr_Autorun
+ENGLISH=Autorun
+
+ID=kStr_AutorunAndQuit
+ENGLISH=AutorunAndQuit
+
+ID=kStr_ReadFrom
+ENGLISH=read from
+
+ID=kStr_WroteTo
+ENGLISH=wrote to
+
+ID=kStr_WrittenTo
+ENGLISH=written directly to
+
+
+ID=kStr_CurrentAppUC
+ENGLISH=The current application
+
+ID=kStr_CurrentAppLC
+ENGLISH=the current application
+
+ID=kStr_UnknownVersion
+ENGLISH=unknown version
+
+
+ID=kStr_OK
+ENGLISH=OK
+
+ID=kStr_Cancel
+ENGLISH=Cancel
+
+ID=kStr_Yes
+ENGLISH=Yes
+
+ID=kStr_No
+ENGLISH=No
+
+ID=kStr_Continue
+ENGLISH=Continue
+
+ID=kStr_Debug
+ENGLISH=Debug
+
+ID=kStr_Reset
+ENGLISH=ResetÉ
+
+
+ID=kStr_Browse
+ENGLISH=Browse
+
+ID=kStr_EmptyMRU
+ENGLISH=(empty)
+
+ID=kStr_OtherMRU
+ENGLISH=OtherÉ
+
+
+ID=kStr_ProfPartial
+ENGLISH=partial
+
+ID=kStr_ProfFunctions
+ENGLISH=functions
+
+ID=kStr_ProfInterrupts
+ENGLISH=interrupts
+
+ID=kStr_ProfOverflow
+ENGLISH=overflow
+
+ID=kStr_ProfInterruptX
+ENGLISH=interrupt $%02lX
+
+ID=kStr_ProfTrapNameAddress
+ENGLISH=%s $%04lX.t
+
+ID=kStr_ProfROMNameAddress
+ENGLISH=%s $%08lX.m
+
+ID=kStr_ProfDebugNameAddress
+ENGLISH= $%08lX.d
+
+ID=kStr_ProfUnknownName
+ENGLISH=unknown $%08lX
+
+
+ID=kStr_UnknownTrapNumber
+ENGLISH=unknown trap number
+
+ID=kStr_UnknownErrorCode
+ENGLISH=unknown error code
+
+
+ID=kStr_NoPort
+ENGLISH=None
+
+
+ID=kStr_ChunkNotInHeap
+ENGLISH=The chunk was not within the heap it was supposed to be
+
+ID=kStr_ChunkTooLarge
+ENGLISH=The size of the chunk (%chunk_size) was larger than the currently accepted maximum (%chunk_max)
+
+ID=kStr_InvalidFlags
+ENGLISH=Some unused flags were set to Ò1Ó
+
+ID=kStr_HOffsetNotInMPT
+ENGLISH=The ÒhOffsetÓ field of the chunk header did not reference a memory location within a master pointer block
+
+ID=kStr_HOffsetNotBackPointing
+ENGLISH=The master pointer referenced by the ÒhOffsetÓ field in the chunk header didnÕt point back to the chunk
+
+ID=kStr_InvalidLockCount
+ENGLISH=The lock count for a fixed block was not 15
+
+
+ID=kStr_UnmappedAddress
+ENGLISH=itÕs in neither ROM nor RAM
+
+ID=kStr_NotInCodeSegment
+ENGLISH=itÕs not in a valid memory chunk
+
+ID=kStr_OddAddress
+ENGLISH=itÕs not even
+
+
+ID=kStr_Waiting
+ENGLISH=WaitingÉ
+
+ID=kStr_Transferring
+ENGLISH=TransferringÉ
+
+// Reasons for why the PC was changed
+
+
+ID=kStr_WhenRTS
+ENGLISH=returning from a subroutine to the routine that called it, indicating that the return address on the stack was corrupted by a previous operation (possibly by writing past the end of an array local to the subroutine).
+
+ID=kStr_WhenRTE
+ENGLISH=returning processing an interrupt, indicating that the return address on the stack was corrupted by a previous operation (possibly by writing past the end of an array local to the interrupt service routine).
+
+ID=kStr_WhenJSR
+ENGLISH=attempting to perform an indirect jump operation, indicating that the function pointer being used is invalid.
+
+ID=kStr_WhenException
+ENGLISH=processing a hardware exception, indicating that the exception vector table has been overwritten.
+
+ID=kStr_WhenSysCall
+ENGLISH=invoking a Palm OS System function, indicating that the system dispatch table has been overwritten.
+
+
+ID=kStr_ShowInDialog
+ENGLISH=Show in dialog
+
+ID=kStr_AutomaticallyContinue
+ENGLISH=Automatically continue
+
+ID=kStr_AutomaticallyQuit
+ENGLISH=Automatically quit Emulator
+
+ID=kStr_NextGremlin
+ENGLISH=Switch to next Gremlin
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Operations descriptions
+// --------------------------------------------------------------------------------
+
+ID=kStr_GenericOperation
+ENGLISH=complete the operation
+
+
+ID=kStr_CmdAbout
+ENGLISH=show the About box
+
+
+ID=kStr_CmdNew
+ENGLISH=create a new session
+
+ID=kStr_CmdOpen
+ENGLISH=open the file Ò%filenameÓ
+
+ID=kStr_CmdClose
+ENGLISH=close the window
+
+ID=kStr_CmdSave
+ENGLISH=save the file Ò%filenameÓ
+
+ID=kStr_CmdSaveBound
+ENGLISH=save a bound emulator
+
+ID=kStr_CmdSaveScreen
+ENGLISH=save the screen
+
+ID=kStr_CmdSessionInfo
+ENGLISH=display session info
+
+ID=kStr_CmdInstall
+ENGLISH=install the Palm OS file Ò%filenameÓ
+
+ID=kStr_CmdInstallMany
+ENGLISH=install the Palm OS files
+
+ID=kStr_CmdExportDatabase
+ENGLISH=export the database
+
+ID=kStr_CmdHotSync
+ENGLISH=start the HotSync
+
+ID=kStr_CmdReset
+ENGLISH=reset the device
+
+ID=kStr_CmdTransferROM
+ENGLISH=transfer the ROM
+
+ID=kStr_CmdQuit
+ENGLISH=quit the application
+
+
+ID=kStr_CmdPreferences
+ENGLISH=open the Preferences dialog box
+
+ID=kStr_CmdLoggingOptions
+ENGLISH=open the Logging Options dialog box
+
+ID=kStr_CmdDebugOptions
+ENGLISH=open the Debug Options dialog box
+
+ID=kStr_CmdErrorHandling
+ENGLISH=open the Error Handling dialog box
+
+ID=kStr_CmdTracingOptions
+ENGLISH=open the Trace Options dialog box
+
+ID=kStr_CmdSkins
+ENGLISH=open the Skins dialog box
+
+ID=kStr_CmdBreakpoints
+ENGLISH=open the Breakpoints dialog box
+
+
+ID=kStr_CmdGremlinNew
+ENGLISH=start the gremlin
+
+ID=kStr_CmdGremlinSuspend
+ENGLISH=suspend the gremlin
+
+ID=kStr_CmdGremlinStep
+ENGLISH=step the gremlin
+
+ID=kStr_CmdGremlinResume
+ENGLISH=resume the gremlin
+
+ID=kStr_CmdGremlinStop
+ENGLISH=stop the gremlin
+
+ID=kStr_CmdEventReplay
+ENGLISH=replay event file
+
+ID=kStr_CmdEventMinimize
+ENGLISH=start event Minimization
+
+
+#if HAS_PROFILING
+ID=kStr_CmdProfileStart
+ENGLISH=start profiling
+
+ID=kStr_CmdProfileStop
+ENGLISH=stop profiling
+
+ID=kStr_CmdProfileDump
+ENGLISH=dump the profiling results
+
+#endif
+
+
+ID=kStr_CmdTracingSuspend
+ENGLISH=suspend sending trace
+
+ID=kStr_CmdTracingResume
+ENGLISH=send trace again
+
+ID=kStr_CmdTracingReconnect
+ENGLISH=reconnect to Palm Reporter
+
+
+ID=kStr_ResizeWindow
+ENGLISH=resize the window
+
+ID=kStr_EnterKey
+ENGLISH=enter the key
+
+ID=kStr_EnterPen
+ENGLISH=enter the pen stroke
+
+ID=kStr_PressButton
+ENGLISH=press the hardware button
+
+ID=kStr_OpenFiles
+ENGLISH=open the selected files
+
+ID=kStr_LoadPreferences
+ENGLISH=load the application preferences
+
+ID=kStr_OpenTheSerialPort
+ENGLISH=open the serial port
+
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions -- OS Errors
+// --------------------------------------------------------------------------------
+
+ID=kStr_GenericError
+ENGLISH=error %error occurred
+
+ID=kStr_UserCancel
+ENGLISH=the user cancelled
+
+ID=kStr_TimeoutError
+ENGLISH=the operation timed out
+
+
+// Disk errors
+ID=kStr_DirectoryFull
+ENGLISH=the directory is full
+
+ID=kStr_DiskFull
+ENGLISH=the disk is full
+
+ID=kStr_DiskMissing
+ENGLISH=the disk is not present
+
+ID=kStr_IOError
+ENGLISH=of a random I/O error
+
+ID=kStr_BadFileName
+ENGLISH=the file name is badly formed
+
+ID=kStr_TooManyFilesOpen
+ENGLISH=too many files are open
+
+ID=kStr_FileNotFound
+ENGLISH=the file wasnÕt found
+
+ID=kStr_DiskWriteProtected
+ENGLISH=the disk is write protected
+
+ID=kStr_FileLocked
+ENGLISH=the file is locked
+
+ID=kStr_DiskLocked
+ENGLISH=the disk is locked
+
+ID=kStr_FileBusy
+ENGLISH=it is being used by another application
+
+ID=kStr_DuplicateFileName
+ENGLISH=a file with that name already exists
+
+
+// Memory errors
+ID=kStr_MemFull
+ENGLISH=the application ran out of memory
+
+
+// Communications errors
+ID=kStr_SerialPortBusy
+ENGLISH=it is being used by another application
+
+
+// PPC Toolbox errors
+
+// Apple event errors
+
+// Palm OS Errors
+
+ID=kStr_GenericPalmError
+ENGLISH=Palm OS error %error (%error_desc) occurred
+
+ID=kStr_DmErrDatabaseOpen
+ENGLISH=the database is currently open
+
+ID=kStr_MemErrNotEnoughSpace
+ENGLISH=the device is out of memory
+
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions -- User/app errors
+// --------------------------------------------------------------------------------
+
+ID=kStr_OnlySameType
+ENGLISH=you can only drag files of the same type onto the Emulator window
+
+ID=kStr_OnlyOnePSF
+ENGLISH=you can only drag one Palm Session File onto the Emulator window at a time
+
+ID=kStr_OnlyOneROM
+ENGLISH=you can only drag one Palm ROM File onto the Emulator window at a time
+
+ID=kStr_UnknownType
+ENGLISH=the Emulator doesnÕt support the file you just dragged onto its window
+
+
+// PSF file errors
+ID=kStr_OldFormat
+ENGLISH=the file appears to be in an old format
+
+ID=kStr_WrongROMForType
+ENGLISH=the chosen ROM file cannot be used with the specified hardware device
+
+
+// ROM file errors
+ID=kStr_BadROM
+ENGLISH=it doesnÕt appear to be a valid ROM file
+
+ID=kStr_UnsupportedROM
+ENGLISH=this Debug 2.0 ROM is not supported
+
+ID=kStr_InvalidDevice
+ENGLISH=this version of the Palm OS Emulator does not support the device required
+ by this session file
+
+ID=kStr_InvalidSession
+ENGLISH=the session file doesn't have the minimum information required to create a new session
+
+ID=kStr_InvalidConfiguration
+ENGLISH=the given configuration information is not supported by this version of the Palm OS Emulator
+
+
+// PRC, PDB, PQA file errors
+ID=kStr_NameNotNULLTerminated
+ENGLISH=the database name (Ò%database_nameÓ) is too long
+
+ID=kStr_NameNotPrintable
+ENGLISH=the database name (Ò%database_nameÓ) contains invalid characters. Only
+ standard printable ASCII characters (that is, characters with values in
+ the range 0x20 - 0x7E) are allowed.\n
+ \n
+ If you need to display a name in the Launcher with additional characters,
+ you can specify that name in the applicationÕs 'tAIN' resource. You can set
+ this in the ÒApplication Icon NameÓ field in the ÒProject SettingsÓ section
+ of ÒConstructor for Palm OSÓ, or in the ÒAPPLICATIONICONNAMEÓ field of ÒpilrcÓ
+
+ID=kStr_FileTooSmall
+ENGLISH=the file is too small to contain all the information it claims to have
+
+ID=kStr_nextRecordListIDNonZero
+ENGLISH=the internal header field nextRecordListID is non-zero
+
+ID=kStr_ResourceTooSmall
+ENGLISH=the size of resource '%res_type'(%res_id) is zero or negative
+
+ID=kStr_RecordTooSmall
+ENGLISH=the size of record #%record_number is negative
+
+ID=kStr_ResourceOutOfRange
+ENGLISH=the entry for resource '%res_type'(%res_id) indicates that the data for the resource is outside the range of the file
+
+ID=kStr_RecordOutOfRange
+ENGLISH=the entry for record #%record_number indicates that the data for the resource is outside the range of the file
+
+ID=kStr_OverlappingResource
+ENGLISH=the resource '%res_type'(%res_id) overlaps another resource
+
+ID=kStr_OverlappingRecord
+ENGLISH=record #%record_number overlaps another record
+
+ID=kStr_ResourceMemError
+ENGLISH=an out of memory error occurred while installing resource '%res_type'(%res_id). ItÕs possible that the reason for this error is because the size of this resource (%res_size) is larger than the currently allowed maximum of 65505
+
+ID=kStr_RecordMemError
+ENGLISH=an out of memory error occurred while installing record #%record_number. ItÕs possible that the reason for this error is because the size of this record (%res_size) is larger than the currently allowed maximum of 65505
+
+ID=kStr_AppInfoMemError
+ENGLISH=an out of memory error occurred while installing the app info block. ItÕs possible that the size of this record (%res_size) is larger than the currently allowed maximum of 65505
+
+ID=kStr_DuplicateResource
+ENGLISH=a duplicate '%res_type'(%res_id) resource was found
+
+
+ID=kStr_SystemUseOnly
+ENGLISH=it is reserved for system use only
+
+ID=kStr_Obsolete
+ENGLISH=it is obsolete and will be removed from a future version of the Palm OS
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Recovery strings
+// --------------------------------------------------------------------------------
+
+ID=kStr_DeleteSomeFiles
+ENGLISH=Delete some files and try again, or try saving to a different disk
+
+ID=kStr_UnlockTheDisk
+ENGLISH=Unlock the disk and try again
+
+ID=kStr_UnlockTheFile
+ENGLISH=Unlock the file and try again
+
+
+ID=kStr_NeedMoreRAM
+ENGLISH=Please give the application more memory
+
+
+ID=kStr_TransferAROM
+ENGLISH=To download the ROM from your Palm device, choose ÒTransfer ROMÉÓ from the File menu
+
+ID=kStr_DownloadAROM
+ENGLISH=Please download the latest from http://www.palm.com
+
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Exception descriptions
+// --------------------------------------------------------------------------------
+
+ID=kStr_ExceptionBase + 0
+ENGLISH=<Nothing>
+
+ID=kStr_ExceptionBase + 1
+ENGLISH=<Nothing>
+
+ID=kStr_ExceptionBase + 2
+ENGLISH=bus error
+
+ID=kStr_ExceptionBase + 3
+ENGLISH=address error
+
+ID=kStr_ExceptionBase + 4
+ENGLISH=illegal instruction
+
+ID=kStr_ExceptionBase + 5
+ENGLISH=divide by zero
+
+ID=kStr_ExceptionBase + 6
+ENGLISH=CHK instruction
+
+ID=kStr_ExceptionBase + 7
+ENGLISH=TRAP instruction
+
+ID=kStr_ExceptionBase + 8
+ENGLISH=privilege violation
+
+ID=kStr_ExceptionBase + 9
+ENGLISH=trace
+
+ID=kStr_ExceptionBase + 10
+ENGLISH=line 1010 instruction
+
+ID=kStr_ExceptionBase + 11
+ENGLISH=line 1111 instruction
+
+ID=kStr_ExceptionBase + 12
+ENGLISH=reserved - 12
+
+ID=kStr_ExceptionBase + 13
+ENGLISH=coprocessor error
+
+ID=kStr_ExceptionBase + 14
+ENGLISH=format error
+
+ID=kStr_ExceptionBase + 15
+ENGLISH=uninitialized interrupt
+
+ID=kStr_ExceptionBase + 16
+ENGLISH=reserved - 0
+
+ID=kStr_ExceptionBase + 17
+ENGLISH=reserved - 1
+
+ID=kStr_ExceptionBase + 18
+ENGLISH=reserved - 2
+
+ID=kStr_ExceptionBase + 19
+ENGLISH=reserved - 3
+
+ID=kStr_ExceptionBase + 20
+ENGLISH=reserved - 4
+
+ID=kStr_ExceptionBase + 21
+ENGLISH=reserved - 5
+
+ID=kStr_ExceptionBase + 22
+ENGLISH=reserved - 6
+
+ID=kStr_ExceptionBase + 23
+ENGLISH=reserved - 7
+
+ID=kStr_ExceptionBase + 24
+ENGLISH=spurious interrupt
+
+ID=kStr_ExceptionBase + 25
+ENGLISH=interrupt - 1
+
+ID=kStr_ExceptionBase + 26
+ENGLISH=interrupt - 2
+
+ID=kStr_ExceptionBase + 27
+ENGLISH=interrupt - 3
+
+ID=kStr_ExceptionBase + 28
+ENGLISH=interrupt - 4
+
+ID=kStr_ExceptionBase + 29
+ENGLISH=interrupt - 5
+
+ID=kStr_ExceptionBase + 30
+ENGLISH=interrupt - 6
+
+ID=kStr_ExceptionBase + 31
+ENGLISH=interrupt - 7
+
+ID=kStr_ExceptionBase + 32
+ENGLISH=TRAP $0
+
+ID=kStr_ExceptionBase + 33
+ENGLISH=TRAP $1
+
+ID=kStr_ExceptionBase + 34
+ENGLISH=TRAP $2
+
+ID=kStr_ExceptionBase + 35
+ENGLISH=TRAP $3
+
+ID=kStr_ExceptionBase + 36
+ENGLISH=TRAP $4
+
+ID=kStr_ExceptionBase + 37
+ENGLISH=TRAP $5
+
+ID=kStr_ExceptionBase + 38
+ENGLISH=TRAP $6
+
+ID=kStr_ExceptionBase + 39
+ENGLISH=TRAP $7
+
+ID=kStr_ExceptionBase + 40
+ENGLISH=TRAP $8
+
+ID=kStr_ExceptionBase + 41
+ENGLISH=TRAP $9
+
+ID=kStr_ExceptionBase + 42
+ENGLISH=TRAP $A
+
+ID=kStr_ExceptionBase + 43
+ENGLISH=TRAP $B
+
+ID=kStr_ExceptionBase + 44
+ENGLISH=TRAP $C
+
+ID=kStr_ExceptionBase + 45
+ENGLISH=TRAP $D
+
+ID=kStr_ExceptionBase + 46
+ENGLISH=TRAP $E
+
+ID=kStr_ExceptionBase + 47
+ENGLISH=TRAP $F
+
+ID=kStr_ExceptionBase + 48
+ENGLISH=unassigned - 0
+
+ID=kStr_ExceptionBase + 49
+ENGLISH=unassigned - 1
+
+ID=kStr_ExceptionBase + 50
+ENGLISH=unassigned - 2
+
+ID=kStr_ExceptionBase + 51
+ENGLISH=unassigned - 3
+
+ID=kStr_ExceptionBase + 52
+ENGLISH=unassigned - 4
+
+ID=kStr_ExceptionBase + 53
+ENGLISH=unassigned - 5
+
+ID=kStr_ExceptionBase + 54
+ENGLISH=unassigned - 6
+
+ID=kStr_ExceptionBase + 55
+ENGLISH=unassigned - 7
+
+ID=kStr_ExceptionBase + 56
+ENGLISH=unassigned - 8
+
+ID=kStr_ExceptionBase + 57
+ENGLISH=unassigned - 9
+
+ID=kStr_ExceptionBase + 58
+ENGLISH=unassigned - 10
+
+ID=kStr_ExceptionBase + 59
+ENGLISH=unassigned - 11
+
+ID=kStr_ExceptionBase + 60
+ENGLISH=unassigned - 12
+
+ID=kStr_ExceptionBase + 61
+ENGLISH=unassigned - 13
+
+ID=kStr_ExceptionBase + 62
+ENGLISH=unassigned - 14
+
+ID=kStr_ExceptionBase + 63
+ENGLISH=unassigned - 15
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- System function names
+// --------------------------------------------------------------------------------
+
+/*
+ The following strings were generated with the following MPW script:
+
+ #######################################################################
+ # Setup Variables
+ #######################################################################
+ set TrapNum 1
+ set Space '[ ¶t]+'
+
+ Set Src "Phantom:Palm:Projects:Palm:Viewer:dev:4.0:primary:Incs:Core:CoreTraps.h"
+ set Dest "{DesktopFolder}SystemTrapNames"
+
+ #######################################################################
+ # Copy the System Header File to a temporary file
+ #######################################################################
+ duplicate -y -d "{Src}" "{Dest}"
+ setfile -a l "{Dest}"
+ open "{Dest}"
+ Target "{Dest}"
+
+ #######################################################################
+ # Delete everything except the trap table enumerated type
+ #######################################################################
+ replace ¥:/sysTrapBaseÅ/ ""
+ replace /¶#define[ ¶t]+sysTrapLastTrapNumber/:° ""
+
+ #######################################################################
+ # Get rid of Comments
+ #######################################################################
+ find ¥
+ replace -c ° /¶/¶/Å/ ""
+
+ #######################################################################
+ # Go through and replace each line with a debugger script command
+ #######################################################################
+ Set Exit 0
+ Set TrapNum 0
+ Find ¥
+ Loop
+ replace /¥#define[ ¶t]+sysTrap([a-zA-Z0-9]+)¨1Å°/ "ID=kStr_SysTrapBase+{TrapNum}¶nENGLISH=¨1¶n"
+ Break If {Status} != 0
+ Set TrapNum `Evaluate {TrapNum}+1`
+ End
+
+ #######################################################################
+ # Strip trailing spaces. Collapse multiple blank lines.
+ #######################################################################
+ Find ¥
+ Replace -c ° /[¶t¶f ]+°/ ""
+
+ Find ¥
+ Replace -c ° /¶n[¶n]+/ "¶n¶n"
+
+ Close -y "{Dest}"
+*/
+
+ID=kStr_SysTrapBase+0
+ENGLISH=MemInit
+
+ID=kStr_SysTrapBase+1
+ENGLISH=MemInitHeapTable
+
+ID=kStr_SysTrapBase+2
+ENGLISH=MemStoreInit
+
+ID=kStr_SysTrapBase+3
+ENGLISH=MemCardFormat
+
+ID=kStr_SysTrapBase+4
+ENGLISH=MemCardInfo
+
+ID=kStr_SysTrapBase+5
+ENGLISH=MemStoreInfo
+
+ID=kStr_SysTrapBase+6
+ENGLISH=MemStoreSetInfo
+
+ID=kStr_SysTrapBase+7
+ENGLISH=MemNumHeaps
+
+ID=kStr_SysTrapBase+8
+ENGLISH=MemNumRAMHeaps
+
+ID=kStr_SysTrapBase+9
+ENGLISH=MemHeapID
+
+ID=kStr_SysTrapBase+10
+ENGLISH=MemHeapPtr
+
+ID=kStr_SysTrapBase+11
+ENGLISH=MemHeapFreeBytes
+
+ID=kStr_SysTrapBase+12
+ENGLISH=MemHeapSize
+
+ID=kStr_SysTrapBase+13
+ENGLISH=MemHeapFlags
+
+ID=kStr_SysTrapBase+14
+ENGLISH=MemHeapCompact
+
+ID=kStr_SysTrapBase+15
+ENGLISH=MemHeapInit
+
+ID=kStr_SysTrapBase+16
+ENGLISH=MemHeapFreeByOwnerID
+
+ID=kStr_SysTrapBase+17
+ENGLISH=MemChunkNew
+
+ID=kStr_SysTrapBase+18
+ENGLISH=MemChunkFree
+
+ID=kStr_SysTrapBase+19
+ENGLISH=MemPtrNew
+
+ID=kStr_SysTrapBase+20
+ENGLISH=MemPtrRecoverHandle
+
+ID=kStr_SysTrapBase+21
+ENGLISH=MemPtrFlags
+
+ID=kStr_SysTrapBase+22
+ENGLISH=MemPtrSize
+
+ID=kStr_SysTrapBase+23
+ENGLISH=MemPtrOwner
+
+ID=kStr_SysTrapBase+24
+ENGLISH=MemPtrHeapID
+
+ID=kStr_SysTrapBase+25
+ENGLISH=MemPtrCardNo
+
+ID=kStr_SysTrapBase+26
+ENGLISH=MemPtrToLocalID
+
+ID=kStr_SysTrapBase+27
+ENGLISH=MemPtrSetOwner
+
+ID=kStr_SysTrapBase+28
+ENGLISH=MemPtrResize
+
+ID=kStr_SysTrapBase+29
+ENGLISH=MemPtrResetLock
+
+ID=kStr_SysTrapBase+30
+ENGLISH=MemHandleNew
+
+ID=kStr_SysTrapBase+31
+ENGLISH=MemHandleLockCount
+
+ID=kStr_SysTrapBase+32
+ENGLISH=MemHandleToLocalID
+
+ID=kStr_SysTrapBase+33
+ENGLISH=MemHandleLock
+
+ID=kStr_SysTrapBase+34
+ENGLISH=MemHandleUnlock
+
+ID=kStr_SysTrapBase+35
+ENGLISH=MemLocalIDToGlobal
+
+ID=kStr_SysTrapBase+36
+ENGLISH=MemLocalIDKind
+
+ID=kStr_SysTrapBase+37
+ENGLISH=MemLocalIDToPtr
+
+ID=kStr_SysTrapBase+38
+ENGLISH=MemMove
+
+ID=kStr_SysTrapBase+39
+ENGLISH=MemSet
+
+ID=kStr_SysTrapBase+40
+ENGLISH=MemStoreSearch
+
+ID=kStr_SysTrapBase+41
+ENGLISH=SysReserved10Trap1
+
+ID=kStr_SysTrapBase+42
+ENGLISH=MemKernelInit
+
+ID=kStr_SysTrapBase+43
+ENGLISH=MemHandleFree
+
+ID=kStr_SysTrapBase+44
+ENGLISH=MemHandleFlags
+
+ID=kStr_SysTrapBase+45
+ENGLISH=MemHandleSize
+
+ID=kStr_SysTrapBase+46
+ENGLISH=MemHandleOwner
+
+ID=kStr_SysTrapBase+47
+ENGLISH=MemHandleHeapID
+
+ID=kStr_SysTrapBase+48
+ENGLISH=MemHandleDataStorage
+
+ID=kStr_SysTrapBase+49
+ENGLISH=MemHandleCardNo
+
+ID=kStr_SysTrapBase+50
+ENGLISH=MemHandleSetOwner
+
+ID=kStr_SysTrapBase+51
+ENGLISH=MemHandleResize
+
+ID=kStr_SysTrapBase+52
+ENGLISH=MemHandleResetLock
+
+ID=kStr_SysTrapBase+53
+ENGLISH=MemPtrUnlock
+
+ID=kStr_SysTrapBase+54
+ENGLISH=MemLocalIDToLockedPtr
+
+ID=kStr_SysTrapBase+55
+ENGLISH=MemSetDebugMode
+
+ID=kStr_SysTrapBase+56
+ENGLISH=MemHeapScramble
+
+ID=kStr_SysTrapBase+57
+ENGLISH=MemHeapCheck
+
+ID=kStr_SysTrapBase+58
+ENGLISH=MemNumCards
+
+ID=kStr_SysTrapBase+59
+ENGLISH=MemDebugMode
+
+ID=kStr_SysTrapBase+60
+ENGLISH=MemSemaphoreReserve
+
+ID=kStr_SysTrapBase+61
+ENGLISH=MemSemaphoreRelease
+
+ID=kStr_SysTrapBase+62
+ENGLISH=MemHeapDynamic
+
+ID=kStr_SysTrapBase+63
+ENGLISH=MemNVParams
+
+ID=kStr_SysTrapBase+64
+ENGLISH=DmInit
+
+ID=kStr_SysTrapBase+65
+ENGLISH=DmCreateDatabase
+
+ID=kStr_SysTrapBase+66
+ENGLISH=DmDeleteDatabase
+
+ID=kStr_SysTrapBase+67
+ENGLISH=DmNumDatabases
+
+ID=kStr_SysTrapBase+68
+ENGLISH=DmGetDatabase
+
+ID=kStr_SysTrapBase+69
+ENGLISH=DmFindDatabase
+
+ID=kStr_SysTrapBase+70
+ENGLISH=DmDatabaseInfo
+
+ID=kStr_SysTrapBase+71
+ENGLISH=DmSetDatabaseInfo
+
+ID=kStr_SysTrapBase+72
+ENGLISH=DmDatabaseSize
+
+ID=kStr_SysTrapBase+73
+ENGLISH=DmOpenDatabase
+
+ID=kStr_SysTrapBase+74
+ENGLISH=DmCloseDatabase
+
+ID=kStr_SysTrapBase+75
+ENGLISH=DmNextOpenDatabase
+
+ID=kStr_SysTrapBase+76
+ENGLISH=DmOpenDatabaseInfo
+
+ID=kStr_SysTrapBase+77
+ENGLISH=DmResetRecordStates
+
+ID=kStr_SysTrapBase+78
+ENGLISH=DmGetLastErr
+
+ID=kStr_SysTrapBase+79
+ENGLISH=DmNumRecords
+
+ID=kStr_SysTrapBase+80
+ENGLISH=DmRecordInfo
+
+ID=kStr_SysTrapBase+81
+ENGLISH=DmSetRecordInfo
+
+ID=kStr_SysTrapBase+82
+ENGLISH=DmAttachRecord
+
+ID=kStr_SysTrapBase+83
+ENGLISH=DmDetachRecord
+
+ID=kStr_SysTrapBase+84
+ENGLISH=DmMoveRecord
+
+ID=kStr_SysTrapBase+85
+ENGLISH=DmNewRecord
+
+ID=kStr_SysTrapBase+86
+ENGLISH=DmRemoveRecord
+
+ID=kStr_SysTrapBase+87
+ENGLISH=DmDeleteRecord
+
+ID=kStr_SysTrapBase+88
+ENGLISH=DmArchiveRecord
+
+ID=kStr_SysTrapBase+89
+ENGLISH=DmNewHandle
+
+ID=kStr_SysTrapBase+90
+ENGLISH=DmRemoveSecretRecords
+
+ID=kStr_SysTrapBase+91
+ENGLISH=DmQueryRecord
+
+ID=kStr_SysTrapBase+92
+ENGLISH=DmGetRecord
+
+ID=kStr_SysTrapBase+93
+ENGLISH=DmResizeRecord
+
+ID=kStr_SysTrapBase+94
+ENGLISH=DmReleaseRecord
+
+ID=kStr_SysTrapBase+95
+ENGLISH=DmGetResource
+
+ID=kStr_SysTrapBase+96
+ENGLISH=DmGet1Resource
+
+ID=kStr_SysTrapBase+97
+ENGLISH=DmReleaseResource
+
+ID=kStr_SysTrapBase+98
+ENGLISH=DmResizeResource
+
+ID=kStr_SysTrapBase+99
+ENGLISH=DmNextOpenResDatabase
+
+ID=kStr_SysTrapBase+100
+ENGLISH=DmFindResourceType
+
+ID=kStr_SysTrapBase+101
+ENGLISH=DmFindResource
+
+ID=kStr_SysTrapBase+102
+ENGLISH=DmSearchResource
+
+ID=kStr_SysTrapBase+103
+ENGLISH=DmNumResources
+
+ID=kStr_SysTrapBase+104
+ENGLISH=DmResourceInfo
+
+ID=kStr_SysTrapBase+105
+ENGLISH=DmSetResourceInfo
+
+ID=kStr_SysTrapBase+106
+ENGLISH=DmAttachResource
+
+ID=kStr_SysTrapBase+107
+ENGLISH=DmDetachResource
+
+ID=kStr_SysTrapBase+108
+ENGLISH=DmNewResource
+
+ID=kStr_SysTrapBase+109
+ENGLISH=DmRemoveResource
+
+ID=kStr_SysTrapBase+110
+ENGLISH=DmGetResourceIndex
+
+ID=kStr_SysTrapBase+111
+ENGLISH=DmQuickSort
+
+ID=kStr_SysTrapBase+112
+ENGLISH=DmQueryNextInCategory
+
+ID=kStr_SysTrapBase+113
+ENGLISH=DmNumRecordsInCategory
+
+ID=kStr_SysTrapBase+114
+ENGLISH=DmPositionInCategory
+
+ID=kStr_SysTrapBase+115
+ENGLISH=DmSeekRecordInCategory
+
+ID=kStr_SysTrapBase+116
+ENGLISH=DmMoveCategory
+
+ID=kStr_SysTrapBase+117
+ENGLISH=DmOpenDatabaseByTypeCreator
+
+ID=kStr_SysTrapBase+118
+ENGLISH=DmWrite
+
+ID=kStr_SysTrapBase+119
+ENGLISH=DmStrCopy
+
+ID=kStr_SysTrapBase+120
+ENGLISH=DmGetNextDatabaseByTypeCreator
+
+ID=kStr_SysTrapBase+121
+ENGLISH=DmWriteCheck
+
+ID=kStr_SysTrapBase+122
+ENGLISH=DmMoveOpenDBContext
+
+ID=kStr_SysTrapBase+123
+ENGLISH=DmFindRecordByID
+
+ID=kStr_SysTrapBase+124
+ENGLISH=DmGetAppInfoID
+
+ID=kStr_SysTrapBase+125
+ENGLISH=DmFindSortPositionV10
+
+ID=kStr_SysTrapBase+126
+ENGLISH=DmSet
+
+ID=kStr_SysTrapBase+127
+ENGLISH=DmCreateDatabaseFromImage
+
+ID=kStr_SysTrapBase+128
+ENGLISH=DbgSrcMessage
+
+ID=kStr_SysTrapBase+129
+ENGLISH=DbgMessage
+
+ID=kStr_SysTrapBase+130
+ENGLISH=DbgGetMessage
+
+ID=kStr_SysTrapBase+131
+ENGLISH=DbgCommSettings
+
+ID=kStr_SysTrapBase+132
+ENGLISH=ErrDisplayFileLineMsg
+
+ID=kStr_SysTrapBase+133
+ENGLISH=ErrSetJump
+
+ID=kStr_SysTrapBase+134
+ENGLISH=ErrLongJump
+
+ID=kStr_SysTrapBase+135
+ENGLISH=ErrThrow
+
+ID=kStr_SysTrapBase+136
+ENGLISH=ErrExceptionList
+
+ID=kStr_SysTrapBase+137
+ENGLISH=SysBroadcastActionCode
+
+ID=kStr_SysTrapBase+138
+ENGLISH=SysUnimplemented
+
+ID=kStr_SysTrapBase+139
+ENGLISH=SysColdBoot
+
+ID=kStr_SysTrapBase+140
+ENGLISH=SysReset
+
+ID=kStr_SysTrapBase+141
+ENGLISH=SysDoze
+
+ID=kStr_SysTrapBase+142
+ENGLISH=SysAppLaunch
+
+ID=kStr_SysTrapBase+143
+ENGLISH=SysAppStartup
+
+ID=kStr_SysTrapBase+144
+ENGLISH=SysAppExit
+
+ID=kStr_SysTrapBase+145
+ENGLISH=SysSetA5
+
+ID=kStr_SysTrapBase+146
+ENGLISH=SysSetTrapAddress
+
+ID=kStr_SysTrapBase+147
+ENGLISH=SysGetTrapAddress
+
+ID=kStr_SysTrapBase+148
+ENGLISH=SysTranslateKernelErr
+
+ID=kStr_SysTrapBase+149
+ENGLISH=SysSemaphoreCreate
+
+ID=kStr_SysTrapBase+150
+ENGLISH=SysSemaphoreDelete
+
+ID=kStr_SysTrapBase+151
+ENGLISH=SysSemaphoreWait
+
+ID=kStr_SysTrapBase+152
+ENGLISH=SysSemaphoreSignal
+
+ID=kStr_SysTrapBase+153
+ENGLISH=SysTimerCreate
+
+ID=kStr_SysTrapBase+154
+ENGLISH=SysTimerWrite
+
+ID=kStr_SysTrapBase+155
+ENGLISH=SysTaskCreate
+
+ID=kStr_SysTrapBase+156
+ENGLISH=SysTaskDelete
+
+ID=kStr_SysTrapBase+157
+ENGLISH=SysTaskTrigger
+
+ID=kStr_SysTrapBase+158
+ENGLISH=SysTaskID
+
+ID=kStr_SysTrapBase+159
+ENGLISH=SysTaskUserInfoPtr
+
+ID=kStr_SysTrapBase+160
+ENGLISH=SysTaskDelay
+
+ID=kStr_SysTrapBase+161
+ENGLISH=SysTaskSetTermProc
+
+ID=kStr_SysTrapBase+162
+ENGLISH=SysUILaunch
+
+ID=kStr_SysTrapBase+163
+ENGLISH=SysNewOwnerID
+
+ID=kStr_SysTrapBase+164
+ENGLISH=SysSemaphoreSet
+
+ID=kStr_SysTrapBase+165
+ENGLISH=SysDisableInts
+
+ID=kStr_SysTrapBase+166
+ENGLISH=SysRestoreStatus
+
+ID=kStr_SysTrapBase+167
+ENGLISH=SysUIAppSwitch
+
+ID=kStr_SysTrapBase+168
+ENGLISH=SysCurAppInfoPV20
+
+ID=kStr_SysTrapBase+169
+ENGLISH=SysHandleEvent
+
+ID=kStr_SysTrapBase+170
+ENGLISH=SysInit
+
+ID=kStr_SysTrapBase+171
+ENGLISH=SysQSort
+
+ID=kStr_SysTrapBase+172
+ENGLISH=SysCurAppDatabase
+
+ID=kStr_SysTrapBase+173
+ENGLISH=SysFatalAlert
+
+ID=kStr_SysTrapBase+174
+ENGLISH=SysResSemaphoreCreate
+
+ID=kStr_SysTrapBase+175
+ENGLISH=SysResSemaphoreDelete
+
+ID=kStr_SysTrapBase+176
+ENGLISH=SysResSemaphoreReserve
+
+ID=kStr_SysTrapBase+177
+ENGLISH=SysResSemaphoreRelease
+
+ID=kStr_SysTrapBase+178
+ENGLISH=SysSleep
+
+ID=kStr_SysTrapBase+179
+ENGLISH=SysKeyboardDialogV10
+
+ID=kStr_SysTrapBase+180
+ENGLISH=SysAppLauncherDialog
+
+ID=kStr_SysTrapBase+181
+ENGLISH=SysSetPerformance
+
+ID=kStr_SysTrapBase+182
+ENGLISH=SysBatteryInfoV20
+
+ID=kStr_SysTrapBase+183
+ENGLISH=SysLibInstall
+
+ID=kStr_SysTrapBase+184
+ENGLISH=SysLibRemove
+
+ID=kStr_SysTrapBase+185
+ENGLISH=SysLibTblEntry
+
+ID=kStr_SysTrapBase+186
+ENGLISH=SysLibFind
+
+ID=kStr_SysTrapBase+187
+ENGLISH=SysBatteryDialog
+
+ID=kStr_SysTrapBase+188
+ENGLISH=SysCopyStringResource
+
+ID=kStr_SysTrapBase+189
+ENGLISH=SysKernelInfo
+
+ID=kStr_SysTrapBase+190
+ENGLISH=SysLaunchConsole
+
+ID=kStr_SysTrapBase+191
+ENGLISH=SysTimerDelete
+
+ID=kStr_SysTrapBase+192
+ENGLISH=SysSetAutoOffTime
+
+ID=kStr_SysTrapBase+193
+ENGLISH=SysFormPointerArrayToStrings
+
+ID=kStr_SysTrapBase+194
+ENGLISH=SysRandom
+
+ID=kStr_SysTrapBase+195
+ENGLISH=SysTaskSwitching
+
+ID=kStr_SysTrapBase+196
+ENGLISH=SysTimerRead
+
+ID=kStr_SysTrapBase+197
+ENGLISH=StrCopy
+
+ID=kStr_SysTrapBase+198
+ENGLISH=StrCat
+
+ID=kStr_SysTrapBase+199
+ENGLISH=StrLen
+
+ID=kStr_SysTrapBase+200
+ENGLISH=StrCompare
+
+ID=kStr_SysTrapBase+201
+ENGLISH=StrIToA
+
+ID=kStr_SysTrapBase+202
+ENGLISH=StrCaselessCompare
+
+ID=kStr_SysTrapBase+203
+ENGLISH=StrIToH
+
+ID=kStr_SysTrapBase+204
+ENGLISH=StrChr
+
+ID=kStr_SysTrapBase+205
+ENGLISH=StrStr
+
+ID=kStr_SysTrapBase+206
+ENGLISH=StrAToI
+
+ID=kStr_SysTrapBase+207
+ENGLISH=StrToLower
+
+ID=kStr_SysTrapBase+208
+ENGLISH=SerReceiveISP
+
+ID=kStr_SysTrapBase+209
+ENGLISH=SlkOpen
+
+ID=kStr_SysTrapBase+210
+ENGLISH=SlkClose
+
+ID=kStr_SysTrapBase+211
+ENGLISH=SlkOpenSocket
+
+ID=kStr_SysTrapBase+212
+ENGLISH=SlkCloseSocket
+
+ID=kStr_SysTrapBase+213
+ENGLISH=SlkSocketRefNum
+
+ID=kStr_SysTrapBase+214
+ENGLISH=SlkSocketSetTimeout
+
+ID=kStr_SysTrapBase+215
+ENGLISH=SlkFlushSocket
+
+ID=kStr_SysTrapBase+216
+ENGLISH=SlkSetSocketListener
+
+ID=kStr_SysTrapBase+217
+ENGLISH=SlkSendPacket
+
+ID=kStr_SysTrapBase+218
+ENGLISH=SlkReceivePacket
+
+ID=kStr_SysTrapBase+219
+ENGLISH=SlkSysPktDefaultResponse
+
+ID=kStr_SysTrapBase+220
+ENGLISH=SlkProcessRPC
+
+ID=kStr_SysTrapBase+221
+ENGLISH=ConPutS
+
+ID=kStr_SysTrapBase+222
+ENGLISH=ConGetS
+
+ID=kStr_SysTrapBase+223
+ENGLISH=FplInit
+
+ID=kStr_SysTrapBase+224
+ENGLISH=FplFree
+
+ID=kStr_SysTrapBase+225
+ENGLISH=FplFToA
+
+ID=kStr_SysTrapBase+226
+ENGLISH=FplAToF
+
+ID=kStr_SysTrapBase+227
+ENGLISH=FplBase10Info
+
+ID=kStr_SysTrapBase+228
+ENGLISH=FplLongToFloat
+
+ID=kStr_SysTrapBase+229
+ENGLISH=FplFloatToLong
+
+ID=kStr_SysTrapBase+230
+ENGLISH=FplFloatToULong
+
+ID=kStr_SysTrapBase+231
+ENGLISH=FplMul
+
+ID=kStr_SysTrapBase+232
+ENGLISH=FplAdd
+
+ID=kStr_SysTrapBase+233
+ENGLISH=FplSub
+
+ID=kStr_SysTrapBase+234
+ENGLISH=FplDiv
+
+ID=kStr_SysTrapBase+235
+ENGLISH=WinScreenInit
+
+ID=kStr_SysTrapBase+236
+ENGLISH=ScrCopyRectangle
+
+ID=kStr_SysTrapBase+237
+ENGLISH=ScrDrawChars
+
+ID=kStr_SysTrapBase+238
+ENGLISH=ScrLineRoutine
+
+ID=kStr_SysTrapBase+239
+ENGLISH=ScrRectangleRoutine
+
+ID=kStr_SysTrapBase+240
+ENGLISH=ScrScreenInfo
+
+ID=kStr_SysTrapBase+241
+ENGLISH=ScrDrawNotify
+
+ID=kStr_SysTrapBase+242
+ENGLISH=ScrSendUpdateArea
+
+ID=kStr_SysTrapBase+243
+ENGLISH=ScrCompressScanLine
+
+ID=kStr_SysTrapBase+244
+ENGLISH=ScrDeCompressScanLine
+
+ID=kStr_SysTrapBase+245
+ENGLISH=TimGetSeconds
+
+ID=kStr_SysTrapBase+246
+ENGLISH=TimSetSeconds
+
+ID=kStr_SysTrapBase+247
+ENGLISH=TimGetTicks
+
+ID=kStr_SysTrapBase+248
+ENGLISH=TimInit
+
+ID=kStr_SysTrapBase+249
+ENGLISH=TimSetAlarm
+
+ID=kStr_SysTrapBase+250
+ENGLISH=TimGetAlarm
+
+ID=kStr_SysTrapBase+251
+ENGLISH=TimHandleInterrupt
+
+ID=kStr_SysTrapBase+252
+ENGLISH=TimSecondsToDateTime
+
+ID=kStr_SysTrapBase+253
+ENGLISH=TimDateTimeToSeconds
+
+ID=kStr_SysTrapBase+254
+ENGLISH=TimAdjust
+
+ID=kStr_SysTrapBase+255
+ENGLISH=TimSleep
+
+ID=kStr_SysTrapBase+256
+ENGLISH=TimWake
+
+ID=kStr_SysTrapBase+257
+ENGLISH=CategoryCreateListV10
+
+ID=kStr_SysTrapBase+258
+ENGLISH=CategoryFreeListV10
+
+ID=kStr_SysTrapBase+259
+ENGLISH=CategoryFind
+
+ID=kStr_SysTrapBase+260
+ENGLISH=CategoryGetName
+
+ID=kStr_SysTrapBase+261
+ENGLISH=CategoryEditV10
+
+ID=kStr_SysTrapBase+262
+ENGLISH=CategorySelectV10
+
+ID=kStr_SysTrapBase+263
+ENGLISH=CategoryGetNext
+
+ID=kStr_SysTrapBase+264
+ENGLISH=CategorySetTriggerLabel
+
+ID=kStr_SysTrapBase+265
+ENGLISH=CategoryTruncateName
+
+ID=kStr_SysTrapBase+266
+ENGLISH=ClipboardAddItem
+
+ID=kStr_SysTrapBase+267
+ENGLISH=ClipboardCheckIfItemExist
+
+ID=kStr_SysTrapBase+268
+ENGLISH=ClipboardGetItem
+
+ID=kStr_SysTrapBase+269
+ENGLISH=CtlDrawControl
+
+ID=kStr_SysTrapBase+270
+ENGLISH=CtlEraseControl
+
+ID=kStr_SysTrapBase+271
+ENGLISH=CtlHideControl
+
+ID=kStr_SysTrapBase+272
+ENGLISH=CtlShowControl
+
+ID=kStr_SysTrapBase+273
+ENGLISH=CtlGetValue
+
+ID=kStr_SysTrapBase+274
+ENGLISH=CtlSetValue
+
+ID=kStr_SysTrapBase+275
+ENGLISH=CtlGetLabel
+
+ID=kStr_SysTrapBase+276
+ENGLISH=CtlSetLabel
+
+ID=kStr_SysTrapBase+277
+ENGLISH=CtlHandleEvent
+
+ID=kStr_SysTrapBase+278
+ENGLISH=CtlHitControl
+
+ID=kStr_SysTrapBase+279
+ENGLISH=CtlSetEnabled
+
+ID=kStr_SysTrapBase+280
+ENGLISH=CtlSetUsable
+
+ID=kStr_SysTrapBase+281
+ENGLISH=CtlEnabled
+
+ID=kStr_SysTrapBase+282
+ENGLISH=EvtInitialize
+
+ID=kStr_SysTrapBase+283
+ENGLISH=EvtAddEventToQueue
+
+ID=kStr_SysTrapBase+284
+ENGLISH=EvtCopyEvent
+
+ID=kStr_SysTrapBase+285
+ENGLISH=EvtGetEvent
+
+ID=kStr_SysTrapBase+286
+ENGLISH=EvtGetPen
+
+ID=kStr_SysTrapBase+287
+ENGLISH=EvtSysInit
+
+ID=kStr_SysTrapBase+288
+ENGLISH=EvtGetSysEvent
+
+ID=kStr_SysTrapBase+289
+ENGLISH=EvtProcessSoftKeyStroke
+
+ID=kStr_SysTrapBase+290
+ENGLISH=EvtGetPenBtnList
+
+ID=kStr_SysTrapBase+291
+ENGLISH=EvtSetPenQueuePtr
+
+ID=kStr_SysTrapBase+292
+ENGLISH=EvtPenQueueSize
+
+ID=kStr_SysTrapBase+293
+ENGLISH=EvtFlushPenQueue
+
+ID=kStr_SysTrapBase+294
+ENGLISH=EvtEnqueuePenPoint
+
+ID=kStr_SysTrapBase+295
+ENGLISH=EvtDequeuePenStrokeInfo
+
+ID=kStr_SysTrapBase+296
+ENGLISH=EvtDequeuePenPoint
+
+ID=kStr_SysTrapBase+297
+ENGLISH=EvtFlushNextPenStroke
+
+ID=kStr_SysTrapBase+298
+ENGLISH=EvtSetKeyQueuePtr
+
+ID=kStr_SysTrapBase+299
+ENGLISH=EvtKeyQueueSize
+
+ID=kStr_SysTrapBase+300
+ENGLISH=EvtFlushKeyQueue
+
+ID=kStr_SysTrapBase+301
+ENGLISH=EvtEnqueueKey
+
+ID=kStr_SysTrapBase+302
+ENGLISH=EvtDequeueKeyEvent
+
+ID=kStr_SysTrapBase+303
+ENGLISH=EvtWakeup
+
+ID=kStr_SysTrapBase+304
+ENGLISH=EvtResetAutoOffTimer
+
+ID=kStr_SysTrapBase+305
+ENGLISH=EvtKeyQueueEmpty
+
+ID=kStr_SysTrapBase+306
+ENGLISH=EvtEnableGraffiti
+
+ID=kStr_SysTrapBase+307
+ENGLISH=FldCopy
+
+ID=kStr_SysTrapBase+308
+ENGLISH=FldCut
+
+ID=kStr_SysTrapBase+309
+ENGLISH=FldDrawField
+
+ID=kStr_SysTrapBase+310
+ENGLISH=FldEraseField
+
+ID=kStr_SysTrapBase+311
+ENGLISH=FldFreeMemory
+
+ID=kStr_SysTrapBase+312
+ENGLISH=FldGetBounds
+
+ID=kStr_SysTrapBase+313
+ENGLISH=FldGetTextPtr
+
+ID=kStr_SysTrapBase+314
+ENGLISH=FldGetSelection
+
+ID=kStr_SysTrapBase+315
+ENGLISH=FldHandleEvent
+
+ID=kStr_SysTrapBase+316
+ENGLISH=FldPaste
+
+ID=kStr_SysTrapBase+317
+ENGLISH=FldRecalculateField
+
+ID=kStr_SysTrapBase+318
+ENGLISH=FldSetBounds
+
+ID=kStr_SysTrapBase+319
+ENGLISH=FldSetText
+
+ID=kStr_SysTrapBase+320
+ENGLISH=FldGetFont
+
+ID=kStr_SysTrapBase+321
+ENGLISH=FldSetFont
+
+ID=kStr_SysTrapBase+322
+ENGLISH=FldSetSelection
+
+ID=kStr_SysTrapBase+323
+ENGLISH=FldGrabFocus
+
+ID=kStr_SysTrapBase+324
+ENGLISH=FldReleaseFocus
+
+ID=kStr_SysTrapBase+325
+ENGLISH=FldGetInsPtPosition
+
+ID=kStr_SysTrapBase+326
+ENGLISH=FldSetInsPtPosition
+
+ID=kStr_SysTrapBase+327
+ENGLISH=FldSetScrollPosition
+
+ID=kStr_SysTrapBase+328
+ENGLISH=FldGetScrollPosition
+
+ID=kStr_SysTrapBase+329
+ENGLISH=FldGetTextHeight
+
+ID=kStr_SysTrapBase+330
+ENGLISH=FldGetTextAllocatedSize
+
+ID=kStr_SysTrapBase+331
+ENGLISH=FldGetTextLength
+
+ID=kStr_SysTrapBase+332
+ENGLISH=FldScrollField
+
+ID=kStr_SysTrapBase+333
+ENGLISH=FldScrollable
+
+ID=kStr_SysTrapBase+334
+ENGLISH=FldGetVisibleLines
+
+ID=kStr_SysTrapBase+335
+ENGLISH=FldGetAttributes
+
+ID=kStr_SysTrapBase+336
+ENGLISH=FldSetAttributes
+
+ID=kStr_SysTrapBase+337
+ENGLISH=FldSendChangeNotification
+
+ID=kStr_SysTrapBase+338
+ENGLISH=FldCalcFieldHeight
+
+ID=kStr_SysTrapBase+339
+ENGLISH=FldGetTextHandle
+
+ID=kStr_SysTrapBase+340
+ENGLISH=FldCompactText
+
+ID=kStr_SysTrapBase+341
+ENGLISH=FldDirty
+
+ID=kStr_SysTrapBase+342
+ENGLISH=FldWordWrap
+
+ID=kStr_SysTrapBase+343
+ENGLISH=FldSetTextAllocatedSize
+
+ID=kStr_SysTrapBase+344
+ENGLISH=FldSetTextHandle
+
+ID=kStr_SysTrapBase+345
+ENGLISH=FldSetTextPtr
+
+ID=kStr_SysTrapBase+346
+ENGLISH=FldGetMaxChars
+
+ID=kStr_SysTrapBase+347
+ENGLISH=FldSetMaxChars
+
+ID=kStr_SysTrapBase+348
+ENGLISH=FldSetUsable
+
+ID=kStr_SysTrapBase+349
+ENGLISH=FldInsert
+
+ID=kStr_SysTrapBase+350
+ENGLISH=FldDelete
+
+ID=kStr_SysTrapBase+351
+ENGLISH=FldUndo
+
+ID=kStr_SysTrapBase+352
+ENGLISH=FldSetDirty
+
+ID=kStr_SysTrapBase+353
+ENGLISH=FldSendHeightChangeNotification
+
+ID=kStr_SysTrapBase+354
+ENGLISH=FldMakeFullyVisible
+
+ID=kStr_SysTrapBase+355
+ENGLISH=FntGetFont
+
+ID=kStr_SysTrapBase+356
+ENGLISH=FntSetFont
+
+ID=kStr_SysTrapBase+357
+ENGLISH=FntGetFontPtr
+
+ID=kStr_SysTrapBase+358
+ENGLISH=FntBaseLine
+
+ID=kStr_SysTrapBase+359
+ENGLISH=FntCharHeight
+
+ID=kStr_SysTrapBase+360
+ENGLISH=FntLineHeight
+
+ID=kStr_SysTrapBase+361
+ENGLISH=FntAverageCharWidth
+
+ID=kStr_SysTrapBase+362
+ENGLISH=FntCharWidth
+
+ID=kStr_SysTrapBase+363
+ENGLISH=FntCharsWidth
+
+ID=kStr_SysTrapBase+364
+ENGLISH=FntDescenderHeight
+
+ID=kStr_SysTrapBase+365
+ENGLISH=FntCharsInWidth
+
+ID=kStr_SysTrapBase+366
+ENGLISH=FntLineWidth
+
+ID=kStr_SysTrapBase+367
+ENGLISH=FrmInitForm
+
+ID=kStr_SysTrapBase+368
+ENGLISH=FrmDeleteForm
+
+ID=kStr_SysTrapBase+369
+ENGLISH=FrmDrawForm
+
+ID=kStr_SysTrapBase+370
+ENGLISH=FrmEraseForm
+
+ID=kStr_SysTrapBase+371
+ENGLISH=FrmGetActiveForm
+
+ID=kStr_SysTrapBase+372
+ENGLISH=FrmSetActiveForm
+
+ID=kStr_SysTrapBase+373
+ENGLISH=FrmGetActiveFormID
+
+ID=kStr_SysTrapBase+374
+ENGLISH=FrmGetUserModifiedState
+
+ID=kStr_SysTrapBase+375
+ENGLISH=FrmSetNotUserModified
+
+ID=kStr_SysTrapBase+376
+ENGLISH=FrmGetFocus
+
+ID=kStr_SysTrapBase+377
+ENGLISH=FrmSetFocus
+
+ID=kStr_SysTrapBase+378
+ENGLISH=FrmHandleEvent
+
+ID=kStr_SysTrapBase+379
+ENGLISH=FrmGetFormBounds
+
+ID=kStr_SysTrapBase+380
+ENGLISH=FrmGetWindowHandle
+
+ID=kStr_SysTrapBase+381
+ENGLISH=FrmGetFormId
+
+ID=kStr_SysTrapBase+382
+ENGLISH=FrmGetFormPtr
+
+ID=kStr_SysTrapBase+383
+ENGLISH=FrmGetNumberOfObjects
+
+ID=kStr_SysTrapBase+384
+ENGLISH=FrmGetObjectIndex
+
+ID=kStr_SysTrapBase+385
+ENGLISH=FrmGetObjectId
+
+ID=kStr_SysTrapBase+386
+ENGLISH=FrmGetObjectType
+
+ID=kStr_SysTrapBase+387
+ENGLISH=FrmGetObjectPtr
+
+ID=kStr_SysTrapBase+388
+ENGLISH=FrmHideObject
+
+ID=kStr_SysTrapBase+389
+ENGLISH=FrmShowObject
+
+ID=kStr_SysTrapBase+390
+ENGLISH=FrmGetObjectPosition
+
+ID=kStr_SysTrapBase+391
+ENGLISH=FrmSetObjectPosition
+
+ID=kStr_SysTrapBase+392
+ENGLISH=FrmGetControlValue
+
+ID=kStr_SysTrapBase+393
+ENGLISH=FrmSetControlValue
+
+ID=kStr_SysTrapBase+394
+ENGLISH=FrmGetControlGroupSelection
+
+ID=kStr_SysTrapBase+395
+ENGLISH=FrmSetControlGroupSelection
+
+ID=kStr_SysTrapBase+396
+ENGLISH=FrmCopyLabel
+
+ID=kStr_SysTrapBase+397
+ENGLISH=FrmSetLabel
+
+ID=kStr_SysTrapBase+398
+ENGLISH=FrmGetLabel
+
+ID=kStr_SysTrapBase+399
+ENGLISH=FrmSetCategoryLabel
+
+ID=kStr_SysTrapBase+400
+ENGLISH=FrmGetTitle
+
+ID=kStr_SysTrapBase+401
+ENGLISH=FrmSetTitle
+
+ID=kStr_SysTrapBase+402
+ENGLISH=FrmAlert
+
+ID=kStr_SysTrapBase+403
+ENGLISH=FrmDoDialog
+
+ID=kStr_SysTrapBase+404
+ENGLISH=FrmCustomAlert
+
+ID=kStr_SysTrapBase+405
+ENGLISH=FrmHelp
+
+ID=kStr_SysTrapBase+406
+ENGLISH=FrmUpdateScrollers
+
+ID=kStr_SysTrapBase+407
+ENGLISH=FrmGetFirstForm
+
+ID=kStr_SysTrapBase+408
+ENGLISH=FrmVisible
+
+ID=kStr_SysTrapBase+409
+ENGLISH=FrmGetObjectBounds
+
+ID=kStr_SysTrapBase+410
+ENGLISH=FrmCopyTitle
+
+ID=kStr_SysTrapBase+411
+ENGLISH=FrmGotoForm
+
+ID=kStr_SysTrapBase+412
+ENGLISH=FrmPopupForm
+
+ID=kStr_SysTrapBase+413
+ENGLISH=FrmUpdateForm
+
+ID=kStr_SysTrapBase+414
+ENGLISH=FrmReturnToForm
+
+ID=kStr_SysTrapBase+415
+ENGLISH=FrmSetEventHandler
+
+ID=kStr_SysTrapBase+416
+ENGLISH=FrmDispatchEvent
+
+ID=kStr_SysTrapBase+417
+ENGLISH=FrmCloseAllForms
+
+ID=kStr_SysTrapBase+418
+ENGLISH=FrmSaveAllForms
+
+ID=kStr_SysTrapBase+419
+ENGLISH=FrmGetGadgetData
+
+ID=kStr_SysTrapBase+420
+ENGLISH=FrmSetGadgetData
+
+ID=kStr_SysTrapBase+421
+ENGLISH=FrmSetCategoryTrigger
+
+ID=kStr_SysTrapBase+422
+ENGLISH=UIInitialize
+
+ID=kStr_SysTrapBase+423
+ENGLISH=UIReset
+
+ID=kStr_SysTrapBase+424
+ENGLISH=InsPtInitialize
+
+ID=kStr_SysTrapBase+425
+ENGLISH=InsPtSetLocation
+
+ID=kStr_SysTrapBase+426
+ENGLISH=InsPtGetLocation
+
+ID=kStr_SysTrapBase+427
+ENGLISH=InsPtEnable
+
+ID=kStr_SysTrapBase+428
+ENGLISH=InsPtEnabled
+
+ID=kStr_SysTrapBase+429
+ENGLISH=InsPtSetHeight
+
+ID=kStr_SysTrapBase+430
+ENGLISH=InsPtGetHeight
+
+ID=kStr_SysTrapBase+431
+ENGLISH=InsPtCheckBlink
+
+ID=kStr_SysTrapBase+432
+ENGLISH=LstSetDrawFunction
+
+ID=kStr_SysTrapBase+433
+ENGLISH=LstDrawList
+
+ID=kStr_SysTrapBase+434
+ENGLISH=LstEraseList
+
+ID=kStr_SysTrapBase+435
+ENGLISH=LstGetSelection
+
+ID=kStr_SysTrapBase+436
+ENGLISH=LstGetSelectionText
+
+ID=kStr_SysTrapBase+437
+ENGLISH=LstHandleEvent
+
+ID=kStr_SysTrapBase+438
+ENGLISH=LstSetHeight
+
+ID=kStr_SysTrapBase+439
+ENGLISH=LstSetSelection
+
+ID=kStr_SysTrapBase+440
+ENGLISH=LstSetListChoices
+
+ID=kStr_SysTrapBase+441
+ENGLISH=LstMakeItemVisible
+
+ID=kStr_SysTrapBase+442
+ENGLISH=LstGetNumberOfItems
+
+ID=kStr_SysTrapBase+443
+ENGLISH=LstPopupList
+
+ID=kStr_SysTrapBase+444
+ENGLISH=LstSetPosition
+
+ID=kStr_SysTrapBase+445
+ENGLISH=MenuInit
+
+ID=kStr_SysTrapBase+446
+ENGLISH=MenuDispose
+
+ID=kStr_SysTrapBase+447
+ENGLISH=MenuHandleEvent
+
+ID=kStr_SysTrapBase+448
+ENGLISH=MenuDrawMenu
+
+ID=kStr_SysTrapBase+449
+ENGLISH=MenuEraseStatus
+
+ID=kStr_SysTrapBase+450
+ENGLISH=MenuGetActiveMenu
+
+ID=kStr_SysTrapBase+451
+ENGLISH=MenuSetActiveMenu
+
+ID=kStr_SysTrapBase+452
+ENGLISH=RctSetRectangle
+
+ID=kStr_SysTrapBase+453
+ENGLISH=RctCopyRectangle
+
+ID=kStr_SysTrapBase+454
+ENGLISH=RctInsetRectangle
+
+ID=kStr_SysTrapBase+455
+ENGLISH=RctOffsetRectangle
+
+ID=kStr_SysTrapBase+456
+ENGLISH=RctPtInRectangle
+
+ID=kStr_SysTrapBase+457
+ENGLISH=RctGetIntersection
+
+ID=kStr_SysTrapBase+458
+ENGLISH=TblDrawTable
+
+ID=kStr_SysTrapBase+459
+ENGLISH=TblEraseTable
+
+ID=kStr_SysTrapBase+460
+ENGLISH=TblHandleEvent
+
+ID=kStr_SysTrapBase+461
+ENGLISH=TblGetItemBounds
+
+ID=kStr_SysTrapBase+462
+ENGLISH=TblSelectItem
+
+ID=kStr_SysTrapBase+463
+ENGLISH=TblGetItemInt
+
+ID=kStr_SysTrapBase+464
+ENGLISH=TblSetItemInt
+
+ID=kStr_SysTrapBase+465
+ENGLISH=TblSetItemStyle
+
+ID=kStr_SysTrapBase+466
+ENGLISH=TblUnhighlightSelection
+
+ID=kStr_SysTrapBase+467
+ENGLISH=TblSetRowUsable
+
+ID=kStr_SysTrapBase+468
+ENGLISH=TblGetNumberOfRows
+
+ID=kStr_SysTrapBase+469
+ENGLISH=TblSetCustomDrawProcedure
+
+ID=kStr_SysTrapBase+470
+ENGLISH=TblSetRowSelectable
+
+ID=kStr_SysTrapBase+471
+ENGLISH=TblRowSelectable
+
+ID=kStr_SysTrapBase+472
+ENGLISH=TblSetLoadDataProcedure
+
+ID=kStr_SysTrapBase+473
+ENGLISH=TblSetSaveDataProcedure
+
+ID=kStr_SysTrapBase+474
+ENGLISH=TblGetBounds
+
+ID=kStr_SysTrapBase+475
+ENGLISH=TblSetRowHeight
+
+ID=kStr_SysTrapBase+476
+ENGLISH=TblGetColumnWidth
+
+ID=kStr_SysTrapBase+477
+ENGLISH=TblGetRowID
+
+ID=kStr_SysTrapBase+478
+ENGLISH=TblSetRowID
+
+ID=kStr_SysTrapBase+479
+ENGLISH=TblMarkRowInvalid
+
+ID=kStr_SysTrapBase+480
+ENGLISH=TblMarkTableInvalid
+
+ID=kStr_SysTrapBase+481
+ENGLISH=TblGetSelection
+
+ID=kStr_SysTrapBase+482
+ENGLISH=TblInsertRow
+
+ID=kStr_SysTrapBase+483
+ENGLISH=TblRemoveRow
+
+ID=kStr_SysTrapBase+484
+ENGLISH=TblRowInvalid
+
+ID=kStr_SysTrapBase+485
+ENGLISH=TblRedrawTable
+
+ID=kStr_SysTrapBase+486
+ENGLISH=TblRowUsable
+
+ID=kStr_SysTrapBase+487
+ENGLISH=TblReleaseFocus
+
+ID=kStr_SysTrapBase+488
+ENGLISH=TblEditing
+
+ID=kStr_SysTrapBase+489
+ENGLISH=TblGetCurrentField
+
+ID=kStr_SysTrapBase+490
+ENGLISH=TblSetColumnUsable
+
+ID=kStr_SysTrapBase+491
+ENGLISH=TblGetRowHeight
+
+ID=kStr_SysTrapBase+492
+ENGLISH=TblSetColumnWidth
+
+ID=kStr_SysTrapBase+493
+ENGLISH=TblGrabFocus
+
+ID=kStr_SysTrapBase+494
+ENGLISH=TblSetItemPtr
+
+ID=kStr_SysTrapBase+495
+ENGLISH=TblFindRowID
+
+ID=kStr_SysTrapBase+496
+ENGLISH=TblGetLastUsableRow
+
+ID=kStr_SysTrapBase+497
+ENGLISH=TblGetColumnSpacing
+
+ID=kStr_SysTrapBase+498
+ENGLISH=TblFindRowData
+
+ID=kStr_SysTrapBase+499
+ENGLISH=TblGetRowData
+
+ID=kStr_SysTrapBase+500
+ENGLISH=TblSetRowData
+
+ID=kStr_SysTrapBase+501
+ENGLISH=TblSetColumnSpacing
+
+ID=kStr_SysTrapBase+502
+ENGLISH=WinCreateWindow
+
+ID=kStr_SysTrapBase+503
+ENGLISH=WinCreateOffscreenWindow
+
+ID=kStr_SysTrapBase+504
+ENGLISH=WinDeleteWindow
+
+ID=kStr_SysTrapBase+505
+ENGLISH=WinInitializeWindow
+
+ID=kStr_SysTrapBase+506
+ENGLISH=WinAddWindow
+
+ID=kStr_SysTrapBase+507
+ENGLISH=WinRemoveWindow
+
+ID=kStr_SysTrapBase+508
+ENGLISH=WinSetActiveWindow
+
+ID=kStr_SysTrapBase+509
+ENGLISH=WinSetDrawWindow
+
+ID=kStr_SysTrapBase+510
+ENGLISH=WinGetDrawWindow
+
+ID=kStr_SysTrapBase+511
+ENGLISH=WinGetActiveWindow
+
+ID=kStr_SysTrapBase+512
+ENGLISH=WinGetDisplayWindow
+
+ID=kStr_SysTrapBase+513
+ENGLISH=WinGetFirstWindow
+
+ID=kStr_SysTrapBase+514
+ENGLISH=WinEnableWindow
+
+ID=kStr_SysTrapBase+515
+ENGLISH=WinDisableWindow
+
+ID=kStr_SysTrapBase+516
+ENGLISH=WinGetWindowFrameRect
+
+ID=kStr_SysTrapBase+517
+ENGLISH=WinDrawWindowFrame
+
+ID=kStr_SysTrapBase+518
+ENGLISH=WinEraseWindow
+
+ID=kStr_SysTrapBase+519
+ENGLISH=WinSaveBits
+
+ID=kStr_SysTrapBase+520
+ENGLISH=WinRestoreBits
+
+ID=kStr_SysTrapBase+521
+ENGLISH=WinCopyRectangle
+
+ID=kStr_SysTrapBase+522
+ENGLISH=WinScrollRectangle
+
+ID=kStr_SysTrapBase+523
+ENGLISH=WinGetDisplayExtent
+
+ID=kStr_SysTrapBase+524
+ENGLISH=WinGetWindowExtent
+
+ID=kStr_SysTrapBase+525
+ENGLISH=WinDisplayToWindowPt
+
+ID=kStr_SysTrapBase+526
+ENGLISH=WinWindowToDisplayPt
+
+ID=kStr_SysTrapBase+527
+ENGLISH=WinGetClip
+
+ID=kStr_SysTrapBase+528
+ENGLISH=WinSetClip
+
+ID=kStr_SysTrapBase+529
+ENGLISH=WinResetClip
+
+ID=kStr_SysTrapBase+530
+ENGLISH=WinClipRectangle
+
+ID=kStr_SysTrapBase+531
+ENGLISH=WinDrawLine
+
+ID=kStr_SysTrapBase+532
+ENGLISH=WinDrawGrayLine
+
+ID=kStr_SysTrapBase+533
+ENGLISH=WinEraseLine
+
+ID=kStr_SysTrapBase+534
+ENGLISH=WinInvertLine
+
+ID=kStr_SysTrapBase+535
+ENGLISH=WinFillLine
+
+ID=kStr_SysTrapBase+536
+ENGLISH=WinDrawRectangle
+
+ID=kStr_SysTrapBase+537
+ENGLISH=WinEraseRectangle
+
+ID=kStr_SysTrapBase+538
+ENGLISH=WinInvertRectangle
+
+ID=kStr_SysTrapBase+539
+ENGLISH=WinDrawRectangleFrame
+
+ID=kStr_SysTrapBase+540
+ENGLISH=WinDrawGrayRectangleFrame
+
+ID=kStr_SysTrapBase+541
+ENGLISH=WinEraseRectangleFrame
+
+ID=kStr_SysTrapBase+542
+ENGLISH=WinInvertRectangleFrame
+
+ID=kStr_SysTrapBase+543
+ENGLISH=WinGetFramesRectangle
+
+ID=kStr_SysTrapBase+544
+ENGLISH=WinDrawChars
+
+ID=kStr_SysTrapBase+545
+ENGLISH=WinEraseChars
+
+ID=kStr_SysTrapBase+546
+ENGLISH=WinInvertChars
+
+ID=kStr_SysTrapBase+547
+ENGLISH=WinGetPattern
+
+ID=kStr_SysTrapBase+548
+ENGLISH=WinSetPattern
+
+ID=kStr_SysTrapBase+549
+ENGLISH=WinSetUnderlineMode
+
+ID=kStr_SysTrapBase+550
+ENGLISH=WinDrawBitmap
+
+ID=kStr_SysTrapBase+551
+ENGLISH=WinModal
+
+ID=kStr_SysTrapBase+552
+ENGLISH=WinGetDrawWindowBounds
+
+ID=kStr_SysTrapBase+553
+ENGLISH=WinFillRectangle
+
+ID=kStr_SysTrapBase+554
+ENGLISH=WinDrawInvertedChars
+
+ID=kStr_SysTrapBase+555
+ENGLISH=PrefOpenPreferenceDBV10
+
+ID=kStr_SysTrapBase+556
+ENGLISH=PrefGetPreferences
+
+ID=kStr_SysTrapBase+557
+ENGLISH=PrefSetPreferences
+
+ID=kStr_SysTrapBase+558
+ENGLISH=PrefGetAppPreferencesV10
+
+ID=kStr_SysTrapBase+559
+ENGLISH=PrefSetAppPreferencesV10
+
+ID=kStr_SysTrapBase+560
+ENGLISH=SndInit
+
+ID=kStr_SysTrapBase+561
+ENGLISH=SndSetDefaultVolume
+
+ID=kStr_SysTrapBase+562
+ENGLISH=SndGetDefaultVolume
+
+ID=kStr_SysTrapBase+563
+ENGLISH=SndDoCmd
+
+ID=kStr_SysTrapBase+564
+ENGLISH=SndPlaySystemSound
+
+ID=kStr_SysTrapBase+565
+ENGLISH=AlmInit
+
+ID=kStr_SysTrapBase+566
+ENGLISH=AlmCancelAll
+
+ID=kStr_SysTrapBase+567
+ENGLISH=AlmAlarmCallback
+
+ID=kStr_SysTrapBase+568
+ENGLISH=AlmSetAlarm
+
+ID=kStr_SysTrapBase+569
+ENGLISH=AlmGetAlarm
+
+ID=kStr_SysTrapBase+570
+ENGLISH=AlmDisplayAlarm
+
+ID=kStr_SysTrapBase+571
+ENGLISH=AlmEnableNotification
+
+ID=kStr_SysTrapBase+572
+ENGLISH=HwrGetRAMMapping
+
+ID=kStr_SysTrapBase+573
+ENGLISH=HwrMemWritable
+
+ID=kStr_SysTrapBase+574
+ENGLISH=HwrMemReadable
+
+ID=kStr_SysTrapBase+575
+ENGLISH=HwrDoze
+
+ID=kStr_SysTrapBase+576
+ENGLISH=HwrSleep
+
+ID=kStr_SysTrapBase+577
+ENGLISH=HwrWake
+
+ID=kStr_SysTrapBase+578
+ENGLISH=HwrSetSystemClock
+
+ID=kStr_SysTrapBase+579
+ENGLISH=HwrSetCPUDutyCycle
+
+ID=kStr_SysTrapBase+580
+ENGLISH=HwrDisplayInit
+
+ID=kStr_SysTrapBase+581
+ENGLISH=HwrDisplaySleep
+
+ID=kStr_SysTrapBase+582
+ENGLISH=HwrTimerInit
+
+ID=kStr_SysTrapBase+583
+ENGLISH=HwrCursorV33
+
+ID=kStr_SysTrapBase+584
+ENGLISH=HwrBatteryLevel
+
+ID=kStr_SysTrapBase+585
+ENGLISH=HwrDelay
+
+ID=kStr_SysTrapBase+586
+ENGLISH=HwrEnableDataWrites
+
+ID=kStr_SysTrapBase+587
+ENGLISH=HwrDisableDataWrites
+
+ID=kStr_SysTrapBase+588
+ENGLISH=HwrLCDBaseAddrV33
+
+ID=kStr_SysTrapBase+589
+ENGLISH=HwrDisplayDrawBootScreen
+
+ID=kStr_SysTrapBase+590
+ENGLISH=HwrTimerSleep
+
+ID=kStr_SysTrapBase+591
+ENGLISH=HwrTimerWake
+
+ID=kStr_SysTrapBase+592
+ENGLISH=HwrDisplayWake
+
+ID=kStr_SysTrapBase+593
+ENGLISH=HwrIRQ1Handler
+
+ID=kStr_SysTrapBase+594
+ENGLISH=HwrIRQ2Handler
+
+ID=kStr_SysTrapBase+595
+ENGLISH=HwrIRQ3Handler
+
+ID=kStr_SysTrapBase+596
+ENGLISH=HwrIRQ4Handler
+
+ID=kStr_SysTrapBase+597
+ENGLISH=HwrIRQ5Handler
+
+ID=kStr_SysTrapBase+598
+ENGLISH=HwrIRQ6Handler
+
+ID=kStr_SysTrapBase+599
+ENGLISH=HwrDockSignals
+
+ID=kStr_SysTrapBase+600
+ENGLISH=HwrPluggedIn
+
+ID=kStr_SysTrapBase+601
+ENGLISH=Crc16CalcBlock
+
+ID=kStr_SysTrapBase+602
+ENGLISH=SelectDayV10
+
+ID=kStr_SysTrapBase+603
+ENGLISH=SelectTimeV33
+
+ID=kStr_SysTrapBase+604
+ENGLISH=DayDrawDaySelector
+
+ID=kStr_SysTrapBase+605
+ENGLISH=DayHandleEvent
+
+ID=kStr_SysTrapBase+606
+ENGLISH=DayDrawDays
+
+ID=kStr_SysTrapBase+607
+ENGLISH=DayOfWeek
+
+ID=kStr_SysTrapBase+608
+ENGLISH=DaysInMonth
+
+ID=kStr_SysTrapBase+609
+ENGLISH=DayOfMonth
+
+ID=kStr_SysTrapBase+610
+ENGLISH=DateDaysToDate
+
+ID=kStr_SysTrapBase+611
+ENGLISH=DateToDays
+
+ID=kStr_SysTrapBase+612
+ENGLISH=DateAdjust
+
+ID=kStr_SysTrapBase+613
+ENGLISH=DateSecondsToDate
+
+ID=kStr_SysTrapBase+614
+ENGLISH=DateToAscii
+
+ID=kStr_SysTrapBase+615
+ENGLISH=DateToDOWDMFormat
+
+ID=kStr_SysTrapBase+616
+ENGLISH=TimeToAscii
+
+ID=kStr_SysTrapBase+617
+ENGLISH=Find
+
+ID=kStr_SysTrapBase+618
+ENGLISH=FindStrInStr
+
+ID=kStr_SysTrapBase+619
+ENGLISH=FindSaveMatch
+
+ID=kStr_SysTrapBase+620
+ENGLISH=FindGetLineBounds
+
+ID=kStr_SysTrapBase+621
+ENGLISH=FindDrawHeader
+
+ID=kStr_SysTrapBase+622
+ENGLISH=PenOpen
+
+ID=kStr_SysTrapBase+623
+ENGLISH=PenClose
+
+ID=kStr_SysTrapBase+624
+ENGLISH=PenGetRawPen
+
+ID=kStr_SysTrapBase+625
+ENGLISH=PenCalibrate
+
+ID=kStr_SysTrapBase+626
+ENGLISH=PenRawToScreen
+
+ID=kStr_SysTrapBase+627
+ENGLISH=PenScreenToRaw
+
+ID=kStr_SysTrapBase+628
+ENGLISH=PenResetCalibration
+
+ID=kStr_SysTrapBase+629
+ENGLISH=PenSleep
+
+ID=kStr_SysTrapBase+630
+ENGLISH=PenWake
+
+ID=kStr_SysTrapBase+631
+ENGLISH=ResLoadForm
+
+ID=kStr_SysTrapBase+632
+ENGLISH=ResLoadMenu
+
+ID=kStr_SysTrapBase+633
+ENGLISH=FtrInit
+
+ID=kStr_SysTrapBase+634
+ENGLISH=FtrUnregister
+
+ID=kStr_SysTrapBase+635
+ENGLISH=FtrGet
+
+ID=kStr_SysTrapBase+636
+ENGLISH=FtrSet
+
+ID=kStr_SysTrapBase+637
+ENGLISH=FtrGetByIndex
+
+ID=kStr_SysTrapBase+638
+ENGLISH=GrfInit
+
+ID=kStr_SysTrapBase+639
+ENGLISH=GrfFree
+
+ID=kStr_SysTrapBase+640
+ENGLISH=GrfGetState
+
+ID=kStr_SysTrapBase+641
+ENGLISH=GrfSetState
+
+ID=kStr_SysTrapBase+642
+ENGLISH=GrfFlushPoints
+
+ID=kStr_SysTrapBase+643
+ENGLISH=GrfAddPoint
+
+ID=kStr_SysTrapBase+644
+ENGLISH=GrfInitState
+
+ID=kStr_SysTrapBase+645
+ENGLISH=GrfCleanState
+
+ID=kStr_SysTrapBase+646
+ENGLISH=GrfMatch
+
+ID=kStr_SysTrapBase+647
+ENGLISH=GrfGetMacro
+
+ID=kStr_SysTrapBase+648
+ENGLISH=GrfFilterPoints
+
+ID=kStr_SysTrapBase+649
+ENGLISH=GrfGetNumPoints
+
+ID=kStr_SysTrapBase+650
+ENGLISH=GrfGetPoint
+
+ID=kStr_SysTrapBase+651
+ENGLISH=GrfFindBranch
+
+ID=kStr_SysTrapBase+652
+ENGLISH=GrfMatchGlyph
+
+ID=kStr_SysTrapBase+653
+ENGLISH=GrfGetGlyphMapping
+
+ID=kStr_SysTrapBase+654
+ENGLISH=GrfGetMacroName
+
+ID=kStr_SysTrapBase+655
+ENGLISH=GrfDeleteMacro
+
+ID=kStr_SysTrapBase+656
+ENGLISH=GrfAddMacro
+
+ID=kStr_SysTrapBase+657
+ENGLISH=GrfGetAndExpandMacro
+
+ID=kStr_SysTrapBase+658
+ENGLISH=GrfProcessStroke
+
+ID=kStr_SysTrapBase+659
+ENGLISH=GrfFieldChange
+
+ID=kStr_SysTrapBase+660
+ENGLISH=GetCharSortValue
+
+ID=kStr_SysTrapBase+661
+ENGLISH=GetCharAttr
+
+ID=kStr_SysTrapBase+662
+ENGLISH=GetCharCaselessValue
+
+ID=kStr_SysTrapBase+663
+ENGLISH=PwdExists
+
+ID=kStr_SysTrapBase+664
+ENGLISH=PwdVerify
+
+ID=kStr_SysTrapBase+665
+ENGLISH=PwdSet
+
+ID=kStr_SysTrapBase+666
+ENGLISH=PwdRemove
+
+ID=kStr_SysTrapBase+667
+ENGLISH=GsiInitialize
+
+ID=kStr_SysTrapBase+668
+ENGLISH=GsiSetLocation
+
+ID=kStr_SysTrapBase+669
+ENGLISH=GsiEnable
+
+ID=kStr_SysTrapBase+670
+ENGLISH=GsiEnabled
+
+ID=kStr_SysTrapBase+671
+ENGLISH=GsiSetShiftState
+
+ID=kStr_SysTrapBase+672
+ENGLISH=KeyInit
+
+ID=kStr_SysTrapBase+673
+ENGLISH=KeyHandleInterrupt
+
+ID=kStr_SysTrapBase+674
+ENGLISH=KeyCurrentState
+
+ID=kStr_SysTrapBase+675
+ENGLISH=KeyResetDoubleTap
+
+ID=kStr_SysTrapBase+676
+ENGLISH=KeyRates
+
+ID=kStr_SysTrapBase+677
+ENGLISH=KeySleep
+
+ID=kStr_SysTrapBase+678
+ENGLISH=KeyWake
+
+ID=kStr_SysTrapBase+679
+ENGLISH=DlkControl
+
+ID=kStr_SysTrapBase+680
+ENGLISH=DlkStartServer
+
+ID=kStr_SysTrapBase+681
+ENGLISH=DlkGetSyncInfo
+
+ID=kStr_SysTrapBase+682
+ENGLISH=DlkSetLogEntry
+
+ID=kStr_SysTrapBase+683
+ENGLISH=IntlDispatch
+
+ID=kStr_SysTrapBase+684
+ENGLISH=SysLibLoad
+
+ID=kStr_SysTrapBase+685
+ENGLISH=SndPlaySmf
+
+ID=kStr_SysTrapBase+686
+ENGLISH=SndCreateMidiList
+
+ID=kStr_SysTrapBase+687
+ENGLISH=AbtShowAbout
+
+ID=kStr_SysTrapBase+688
+ENGLISH=MdmDial
+
+ID=kStr_SysTrapBase+689
+ENGLISH=MdmHangUp
+
+ID=kStr_SysTrapBase+690
+ENGLISH=DmSearchRecord
+
+ID=kStr_SysTrapBase+691
+ENGLISH=SysInsertionSort
+
+ID=kStr_SysTrapBase+692
+ENGLISH=DmInsertionSort
+
+ID=kStr_SysTrapBase+693
+ENGLISH=LstSetTopItem
+
+ID=kStr_SysTrapBase+694
+ENGLISH=SclSetScrollBar
+
+ID=kStr_SysTrapBase+695
+ENGLISH=SclDrawScrollBar
+
+ID=kStr_SysTrapBase+696
+ENGLISH=SclHandleEvent
+
+ID=kStr_SysTrapBase+697
+ENGLISH=SysMailboxCreate
+
+ID=kStr_SysTrapBase+698
+ENGLISH=SysMailboxDelete
+
+ID=kStr_SysTrapBase+699
+ENGLISH=SysMailboxFlush
+
+ID=kStr_SysTrapBase+700
+ENGLISH=SysMailboxSend
+
+ID=kStr_SysTrapBase+701
+ENGLISH=SysMailboxWait
+
+ID=kStr_SysTrapBase+702
+ENGLISH=SysTaskWait
+
+ID=kStr_SysTrapBase+703
+ENGLISH=SysTaskWake
+
+ID=kStr_SysTrapBase+704
+ENGLISH=SysTaskWaitClr
+
+ID=kStr_SysTrapBase+705
+ENGLISH=SysTaskSuspend
+
+ID=kStr_SysTrapBase+706
+ENGLISH=SysTaskResume
+
+ID=kStr_SysTrapBase+707
+ENGLISH=CategoryCreateList
+
+ID=kStr_SysTrapBase+708
+ENGLISH=CategoryFreeList
+
+ID=kStr_SysTrapBase+709
+ENGLISH=CategoryEditV20
+
+ID=kStr_SysTrapBase+710
+ENGLISH=CategorySelect
+
+ID=kStr_SysTrapBase+711
+ENGLISH=DmDeleteCategory
+
+ID=kStr_SysTrapBase+712
+ENGLISH=SysEvGroupCreate
+
+ID=kStr_SysTrapBase+713
+ENGLISH=SysEvGroupSignal
+
+ID=kStr_SysTrapBase+714
+ENGLISH=SysEvGroupRead
+
+ID=kStr_SysTrapBase+715
+ENGLISH=SysEvGroupWait
+
+ID=kStr_SysTrapBase+716
+ENGLISH=EvtEventAvail
+
+ID=kStr_SysTrapBase+717
+ENGLISH=EvtSysEventAvail
+
+ID=kStr_SysTrapBase+718
+ENGLISH=StrNCopy
+
+ID=kStr_SysTrapBase+719
+ENGLISH=KeySetMask
+
+ID=kStr_SysTrapBase+720
+ENGLISH=SelectDay
+
+ID=kStr_SysTrapBase+721
+ENGLISH=PrefGetPreference
+
+ID=kStr_SysTrapBase+722
+ENGLISH=PrefSetPreference
+
+ID=kStr_SysTrapBase+723
+ENGLISH=PrefGetAppPreferences
+
+ID=kStr_SysTrapBase+724
+ENGLISH=PrefSetAppPreferences
+
+ID=kStr_SysTrapBase+725
+ENGLISH=FrmPointInTitle
+
+ID=kStr_SysTrapBase+726
+ENGLISH=StrNCat
+
+ID=kStr_SysTrapBase+727
+ENGLISH=MemCmp
+
+ID=kStr_SysTrapBase+728
+ENGLISH=TblSetColumnEditIndicator
+
+ID=kStr_SysTrapBase+729
+ENGLISH=FntWordWrap
+
+ID=kStr_SysTrapBase+730
+ENGLISH=FldGetScrollValues
+
+ID=kStr_SysTrapBase+731
+ENGLISH=SysCreateDataBaseList
+
+ID=kStr_SysTrapBase+732
+ENGLISH=SysCreatePanelList
+
+ID=kStr_SysTrapBase+733
+ENGLISH=DlkDispatchRequest
+
+ID=kStr_SysTrapBase+734
+ENGLISH=StrPrintF
+
+ID=kStr_SysTrapBase+735
+ENGLISH=StrVPrintF
+
+ID=kStr_SysTrapBase+736
+ENGLISH=PrefOpenPreferenceDB
+
+ID=kStr_SysTrapBase+737
+ENGLISH=SysGraffitiReferenceDialog
+
+ID=kStr_SysTrapBase+738
+ENGLISH=SysKeyboardDialog
+
+ID=kStr_SysTrapBase+739
+ENGLISH=FntWordWrapReverseNLines
+
+ID=kStr_SysTrapBase+740
+ENGLISH=FntGetScrollValues
+
+ID=kStr_SysTrapBase+741
+ENGLISH=TblSetRowStaticHeight
+
+ID=kStr_SysTrapBase+742
+ENGLISH=TblHasScrollBar
+
+ID=kStr_SysTrapBase+743
+ENGLISH=SclGetScrollBar
+
+ID=kStr_SysTrapBase+744
+ENGLISH=FldGetNumberOfBlankLines
+
+ID=kStr_SysTrapBase+745
+ENGLISH=SysTicksPerSecond
+
+ID=kStr_SysTrapBase+746
+ENGLISH=HwrBacklightV33
+
+ID=kStr_SysTrapBase+747
+ENGLISH=DmDatabaseProtect
+
+ID=kStr_SysTrapBase+748
+ENGLISH=TblSetBounds
+
+ID=kStr_SysTrapBase+749
+ENGLISH=StrNCompare
+
+ID=kStr_SysTrapBase+750
+ENGLISH=StrNCaselessCompare
+
+ID=kStr_SysTrapBase+751
+ENGLISH=PhoneNumberLookup
+
+ID=kStr_SysTrapBase+752
+ENGLISH=FrmSetMenu
+
+ID=kStr_SysTrapBase+753
+ENGLISH=EncDigestMD5
+
+ID=kStr_SysTrapBase+754
+ENGLISH=DmFindSortPosition
+
+ID=kStr_SysTrapBase+755
+ENGLISH=SysBinarySearch
+
+ID=kStr_SysTrapBase+756
+ENGLISH=SysErrString
+
+ID=kStr_SysTrapBase+757
+ENGLISH=SysStringByIndex
+
+ID=kStr_SysTrapBase+758
+ENGLISH=EvtAddUniqueEventToQueue
+
+ID=kStr_SysTrapBase+759
+ENGLISH=StrLocalizeNumber
+
+ID=kStr_SysTrapBase+760
+ENGLISH=StrDelocalizeNumber
+
+ID=kStr_SysTrapBase+761
+ENGLISH=LocGetNumberSeparators
+
+ID=kStr_SysTrapBase+762
+ENGLISH=MenuSetActiveMenuRscID
+
+ID=kStr_SysTrapBase+763
+ENGLISH=LstScrollList
+
+ID=kStr_SysTrapBase+764
+ENGLISH=CategoryInitialize
+
+ID=kStr_SysTrapBase+765
+ENGLISH=EncDigestMD4
+
+ID=kStr_SysTrapBase+766
+ENGLISH=EncDES
+
+ID=kStr_SysTrapBase+767
+ENGLISH=LstGetVisibleItems
+
+ID=kStr_SysTrapBase+768
+ENGLISH=WinSetBounds
+
+ID=kStr_SysTrapBase+769
+ENGLISH=CategorySetName
+
+ID=kStr_SysTrapBase+770
+ENGLISH=FldSetInsertionPoint
+
+ID=kStr_SysTrapBase+771
+ENGLISH=FrmSetObjectBounds
+
+ID=kStr_SysTrapBase+772
+ENGLISH=WinSetColors
+
+ID=kStr_SysTrapBase+773
+ENGLISH=FlpDispatch
+
+ID=kStr_SysTrapBase+774
+ENGLISH=FlpEmDispatch
+
+ID=kStr_SysTrapBase+775
+ENGLISH=ExgInit
+
+ID=kStr_SysTrapBase+776
+ENGLISH=ExgConnect
+
+ID=kStr_SysTrapBase+777
+ENGLISH=ExgPut
+
+ID=kStr_SysTrapBase+778
+ENGLISH=ExgGet
+
+ID=kStr_SysTrapBase+779
+ENGLISH=ExgAccept
+
+ID=kStr_SysTrapBase+780
+ENGLISH=ExgDisconnect
+
+ID=kStr_SysTrapBase+781
+ENGLISH=ExgSend
+
+ID=kStr_SysTrapBase+782
+ENGLISH=ExgReceive
+
+ID=kStr_SysTrapBase+783
+ENGLISH=ExgRegisterData
+
+ID=kStr_SysTrapBase+784
+ENGLISH=ExgNotifyReceiveV35
+
+ID=kStr_SysTrapBase+785
+ENGLISH=SysReserved30Trap2
+
+ID=kStr_SysTrapBase+786
+ENGLISH=PrgStartDialogV31
+
+ID=kStr_SysTrapBase+787
+ENGLISH=PrgStopDialog
+
+ID=kStr_SysTrapBase+788
+ENGLISH=PrgUpdateDialog
+
+ID=kStr_SysTrapBase+789
+ENGLISH=PrgHandleEvent
+
+ID=kStr_SysTrapBase+790
+ENGLISH=ImcReadFieldNoSemicolon
+
+ID=kStr_SysTrapBase+791
+ENGLISH=ImcReadFieldQuotablePrintable
+
+ID=kStr_SysTrapBase+792
+ENGLISH=ImcReadPropertyParameter
+
+ID=kStr_SysTrapBase+793
+ENGLISH=ImcSkipAllPropertyParameters
+
+ID=kStr_SysTrapBase+794
+ENGLISH=ImcReadWhiteSpace
+
+ID=kStr_SysTrapBase+795
+ENGLISH=ImcWriteQuotedPrintable
+
+ID=kStr_SysTrapBase+796
+ENGLISH=ImcWriteNoSemicolon
+
+ID=kStr_SysTrapBase+797
+ENGLISH=ImcStringIsAscii
+
+ID=kStr_SysTrapBase+798
+ENGLISH=TblGetItemFont
+
+ID=kStr_SysTrapBase+799
+ENGLISH=TblSetItemFont
+
+ID=kStr_SysTrapBase+800
+ENGLISH=FontSelect
+
+ID=kStr_SysTrapBase+801
+ENGLISH=FntDefineFont
+
+ID=kStr_SysTrapBase+802
+ENGLISH=CategoryEdit
+
+ID=kStr_SysTrapBase+803
+ENGLISH=SysGetOSVersionString
+
+ID=kStr_SysTrapBase+804
+ENGLISH=SysBatteryInfo
+
+ID=kStr_SysTrapBase+805
+ENGLISH=SysUIBusy
+
+ID=kStr_SysTrapBase+806
+ENGLISH=WinValidateHandle
+
+ID=kStr_SysTrapBase+807
+ENGLISH=FrmValidatePtr
+
+ID=kStr_SysTrapBase+808
+ENGLISH=CtlValidatePointer
+
+ID=kStr_SysTrapBase+809
+ENGLISH=WinMoveWindowAddr
+
+ID=kStr_SysTrapBase+810
+ENGLISH=FrmAddSpaceForObject
+
+ID=kStr_SysTrapBase+811
+ENGLISH=FrmNewForm
+
+ID=kStr_SysTrapBase+812
+ENGLISH=CtlNewControl
+
+ID=kStr_SysTrapBase+813
+ENGLISH=FldNewField
+
+ID=kStr_SysTrapBase+814
+ENGLISH=LstNewList
+
+ID=kStr_SysTrapBase+815
+ENGLISH=FrmNewLabel
+
+ID=kStr_SysTrapBase+816
+ENGLISH=FrmNewBitmap
+
+ID=kStr_SysTrapBase+817
+ENGLISH=FrmNewGadget
+
+ID=kStr_SysTrapBase+818
+ENGLISH=FileOpen
+
+ID=kStr_SysTrapBase+819
+ENGLISH=FileClose
+
+ID=kStr_SysTrapBase+820
+ENGLISH=FileDelete
+
+ID=kStr_SysTrapBase+821
+ENGLISH=FileReadLow
+
+ID=kStr_SysTrapBase+822
+ENGLISH=FileWrite
+
+ID=kStr_SysTrapBase+823
+ENGLISH=FileSeek
+
+ID=kStr_SysTrapBase+824
+ENGLISH=FileTell
+
+ID=kStr_SysTrapBase+825
+ENGLISH=FileTruncate
+
+ID=kStr_SysTrapBase+826
+ENGLISH=FileControl
+
+ID=kStr_SysTrapBase+827
+ENGLISH=FrmActiveState
+
+ID=kStr_SysTrapBase+828
+ENGLISH=SysGetAppInfo
+
+ID=kStr_SysTrapBase+829
+ENGLISH=SysGetStackInfo
+
+ID=kStr_SysTrapBase+830
+ENGLISH=WinScreenMode
+
+ID=kStr_SysTrapBase+831
+ENGLISH=HwrLCDGetDepthV33
+
+ID=kStr_SysTrapBase+832
+ENGLISH=HwrGetROMToken
+
+ID=kStr_SysTrapBase+833
+ENGLISH=DbgControl
+
+ID=kStr_SysTrapBase+834
+ENGLISH=ExgDBRead
+
+ID=kStr_SysTrapBase+835
+ENGLISH=ExgDBWrite
+
+ID=kStr_SysTrapBase+836
+ENGLISH=HostControl
+
+ID=kStr_SysTrapBase+837
+ENGLISH=FrmRemoveObject
+
+ID=kStr_SysTrapBase+838
+ENGLISH=SysReserved30Trap1
+
+ID=kStr_SysTrapBase+839
+ENGLISH=ExpansionDispatch
+
+ID=kStr_SysTrapBase+840
+ENGLISH=FileSystemDispatch
+
+ID=kStr_SysTrapBase+841
+ENGLISH=OEMDispatch
+
+ID=kStr_SysTrapBase+842
+ENGLISH=HwrLCDContrastV33
+
+ID=kStr_SysTrapBase+843
+ENGLISH=SysLCDContrast
+
+ID=kStr_SysTrapBase+844
+ENGLISH=UIContrastAdjust
+
+ID=kStr_SysTrapBase+845
+ENGLISH=HwrDockStatus
+
+ID=kStr_SysTrapBase+846
+ENGLISH=FntWidthToOffset
+
+ID=kStr_SysTrapBase+847
+ENGLISH=SelectOneTime
+
+ID=kStr_SysTrapBase+848
+ENGLISH=WinDrawChar
+
+ID=kStr_SysTrapBase+849
+ENGLISH=WinDrawTruncChars
+
+ID=kStr_SysTrapBase+850
+ENGLISH=SysNotifyInit
+
+ID=kStr_SysTrapBase+851
+ENGLISH=SysNotifyRegister
+
+ID=kStr_SysTrapBase+852
+ENGLISH=SysNotifyUnregister
+
+ID=kStr_SysTrapBase+853
+ENGLISH=SysNotifyBroadcast
+
+ID=kStr_SysTrapBase+854
+ENGLISH=SysNotifyBroadcastDeferred
+
+ID=kStr_SysTrapBase+855
+ENGLISH=SysNotifyDatabaseAdded
+
+ID=kStr_SysTrapBase+856
+ENGLISH=SysNotifyDatabaseRemoved
+
+ID=kStr_SysTrapBase+857
+ENGLISH=SysWantEvent
+
+ID=kStr_SysTrapBase+858
+ENGLISH=FtrPtrNew
+
+ID=kStr_SysTrapBase+859
+ENGLISH=FtrPtrFree
+
+ID=kStr_SysTrapBase+860
+ENGLISH=FtrPtrResize
+
+ID=kStr_SysTrapBase+861
+ENGLISH=SysReserved31Trap1
+
+ID=kStr_SysTrapBase+862
+ENGLISH=HwrNVPrefSet
+
+ID=kStr_SysTrapBase+863
+ENGLISH=HwrNVPrefGet
+
+ID=kStr_SysTrapBase+864
+ENGLISH=FlashInit
+
+ID=kStr_SysTrapBase+865
+ENGLISH=FlashCompress
+
+ID=kStr_SysTrapBase+866
+ENGLISH=FlashErase
+
+ID=kStr_SysTrapBase+867
+ENGLISH=FlashProgram
+
+ID=kStr_SysTrapBase+868
+ENGLISH=AlmTimeChange
+
+ID=kStr_SysTrapBase+869
+ENGLISH=ErrAlertCustom
+
+ID=kStr_SysTrapBase+870
+ENGLISH=PrgStartDialog
+
+ID=kStr_SysTrapBase+871
+ENGLISH=SerialDispatch
+
+ID=kStr_SysTrapBase+872
+ENGLISH=HwrBattery
+
+ID=kStr_SysTrapBase+873
+ENGLISH=DmGetDatabaseLockState
+
+ID=kStr_SysTrapBase+874
+ENGLISH=CncGetProfileList
+
+ID=kStr_SysTrapBase+875
+ENGLISH=CncGetProfileInfo
+
+ID=kStr_SysTrapBase+876
+ENGLISH=CncAddProfile
+
+ID=kStr_SysTrapBase+877
+ENGLISH=CncDeleteProfile
+
+ID=kStr_SysTrapBase+878
+ENGLISH=SndPlaySmfResource
+
+ID=kStr_SysTrapBase+879
+ENGLISH=MemPtrDataStorage
+
+ID=kStr_SysTrapBase+880
+ENGLISH=ClipboardAppendItem
+
+ID=kStr_SysTrapBase+881
+ENGLISH=WiCmdV32
+
+ID=kStr_SysTrapBase+882
+ENGLISH=HwrDisplayAttributes
+
+ID=kStr_SysTrapBase+883
+ENGLISH=HwrDisplayDoze
+
+ID=kStr_SysTrapBase+884
+ENGLISH=HwrDisplayPalette
+
+ID=kStr_SysTrapBase+885
+ENGLISH=BltFindIndexes
+
+ID=kStr_SysTrapBase+886
+ENGLISH=BmpGetBits
+
+ID=kStr_SysTrapBase+887
+ENGLISH=BltCopyRectangle
+
+ID=kStr_SysTrapBase+888
+ENGLISH=BltDrawChars
+
+ID=kStr_SysTrapBase+889
+ENGLISH=BltLineRoutine
+
+ID=kStr_SysTrapBase+890
+ENGLISH=BltRectangleRoutine
+
+ID=kStr_SysTrapBase+891
+ENGLISH=ScrCompress
+
+ID=kStr_SysTrapBase+892
+ENGLISH=ScrDecompress
+
+ID=kStr_SysTrapBase+893
+ENGLISH=SysLCDBrightness
+
+ID=kStr_SysTrapBase+894
+ENGLISH=WinPaintChar
+
+ID=kStr_SysTrapBase+895
+ENGLISH=WinPaintChars
+
+ID=kStr_SysTrapBase+896
+ENGLISH=WinPaintBitmap
+
+ID=kStr_SysTrapBase+897
+ENGLISH=WinGetPixel
+
+ID=kStr_SysTrapBase+898
+ENGLISH=WinPaintPixel
+
+ID=kStr_SysTrapBase+899
+ENGLISH=WinDrawPixel
+
+ID=kStr_SysTrapBase+900
+ENGLISH=WinErasePixel
+
+ID=kStr_SysTrapBase+901
+ENGLISH=WinInvertPixel
+
+ID=kStr_SysTrapBase+902
+ENGLISH=WinPaintPixels
+
+ID=kStr_SysTrapBase+903
+ENGLISH=WinPaintLines
+
+ID=kStr_SysTrapBase+904
+ENGLISH=WinPaintLine
+
+ID=kStr_SysTrapBase+905
+ENGLISH=WinPaintRectangle
+
+ID=kStr_SysTrapBase+906
+ENGLISH=WinPaintRectangleFrame
+
+ID=kStr_SysTrapBase+907
+ENGLISH=WinPaintPolygon
+
+ID=kStr_SysTrapBase+908
+ENGLISH=WinDrawPolygon
+
+ID=kStr_SysTrapBase+909
+ENGLISH=WinErasePolygon
+
+ID=kStr_SysTrapBase+910
+ENGLISH=WinInvertPolygon
+
+ID=kStr_SysTrapBase+911
+ENGLISH=WinFillPolygon
+
+ID=kStr_SysTrapBase+912
+ENGLISH=WinPaintArc
+
+ID=kStr_SysTrapBase+913
+ENGLISH=WinDrawArc
+
+ID=kStr_SysTrapBase+914
+ENGLISH=WinEraseArc
+
+ID=kStr_SysTrapBase+915
+ENGLISH=WinInvertArc
+
+ID=kStr_SysTrapBase+916
+ENGLISH=WinFillArc
+
+ID=kStr_SysTrapBase+917
+ENGLISH=WinPushDrawState
+
+ID=kStr_SysTrapBase+918
+ENGLISH=WinPopDrawState
+
+ID=kStr_SysTrapBase+919
+ENGLISH=WinSetDrawMode
+
+ID=kStr_SysTrapBase+920
+ENGLISH=WinSetForeColor
+
+ID=kStr_SysTrapBase+921
+ENGLISH=WinSetBackColor
+
+ID=kStr_SysTrapBase+922
+ENGLISH=WinSetTextColor
+
+ID=kStr_SysTrapBase+923
+ENGLISH=WinGetPatternType
+
+ID=kStr_SysTrapBase+924
+ENGLISH=WinSetPatternType
+
+ID=kStr_SysTrapBase+925
+ENGLISH=WinPalette
+
+ID=kStr_SysTrapBase+926
+ENGLISH=WinRGBToIndex
+
+ID=kStr_SysTrapBase+927
+ENGLISH=WinIndexToRGB
+
+ID=kStr_SysTrapBase+928
+ENGLISH=WinScreenLock
+
+ID=kStr_SysTrapBase+929
+ENGLISH=WinScreenUnlock
+
+ID=kStr_SysTrapBase+930
+ENGLISH=WinGetBitmap
+
+ID=kStr_SysTrapBase+931
+ENGLISH=UIColorInit
+
+ID=kStr_SysTrapBase+932
+ENGLISH=UIColorGetTableEntryIndex
+
+ID=kStr_SysTrapBase+933
+ENGLISH=UIColorGetTableEntryRGB
+
+ID=kStr_SysTrapBase+934
+ENGLISH=UIColorSetTableEntry
+
+ID=kStr_SysTrapBase+935
+ENGLISH=UIColorPushTable
+
+ID=kStr_SysTrapBase+936
+ENGLISH=UIColorPopTable
+
+ID=kStr_SysTrapBase+937
+ENGLISH=CtlNewGraphicControl
+
+ID=kStr_SysTrapBase+938
+ENGLISH=TblGetItemPtr
+
+ID=kStr_SysTrapBase+939
+ENGLISH=UIBrightnessAdjust
+
+ID=kStr_SysTrapBase+940
+ENGLISH=UIPickColor
+
+ID=kStr_SysTrapBase+941
+ENGLISH=EvtSetAutoOffTimer
+
+ID=kStr_SysTrapBase+942
+ENGLISH=TsmDispatch
+
+ID=kStr_SysTrapBase+943
+ENGLISH=OmDispatch
+
+ID=kStr_SysTrapBase+944
+ENGLISH=DmOpenDBNoOverlay
+
+ID=kStr_SysTrapBase+945
+ENGLISH=DmOpenDBWithLocale
+
+ID=kStr_SysTrapBase+946
+ENGLISH=ResLoadConstant
+
+ID=kStr_SysTrapBase+947
+ENGLISH=HwrPreDebugInit
+
+ID=kStr_SysTrapBase+948
+ENGLISH=HwrResetNMI
+
+ID=kStr_SysTrapBase+949
+ENGLISH=HwrResetPWM
+
+ID=kStr_SysTrapBase+950
+ENGLISH=KeyBootKeys
+
+ID=kStr_SysTrapBase+951
+ENGLISH=DbgSerDrvOpen
+
+ID=kStr_SysTrapBase+952
+ENGLISH=DbgSerDrvClose
+
+ID=kStr_SysTrapBase+953
+ENGLISH=DbgSerDrvControl
+
+ID=kStr_SysTrapBase+954
+ENGLISH=DbgSerDrvStatus
+
+ID=kStr_SysTrapBase+955
+ENGLISH=DbgSerDrvWriteChar
+
+ID=kStr_SysTrapBase+956
+ENGLISH=DbgSerDrvReadChar
+
+ID=kStr_SysTrapBase+957
+ENGLISH=HwrPostDebugInit
+
+ID=kStr_SysTrapBase+958
+ENGLISH=HwrIdentifyFeatures
+
+ID=kStr_SysTrapBase+959
+ENGLISH=HwrModelSpecificInit
+
+ID=kStr_SysTrapBase+960
+ENGLISH=HwrModelInitStage2
+
+ID=kStr_SysTrapBase+961
+ENGLISH=HwrInterruptsInit
+
+ID=kStr_SysTrapBase+962
+ENGLISH=HwrSoundOn
+
+ID=kStr_SysTrapBase+963
+ENGLISH=HwrSoundOff
+
+ID=kStr_SysTrapBase+964
+ENGLISH=SysKernelClockTick
+
+ID=kStr_SysTrapBase+965
+ENGLISH=MenuEraseMenu
+
+ID=kStr_SysTrapBase+966
+ENGLISH=SelectTime
+
+ID=kStr_SysTrapBase+967
+ENGLISH=MenuCmdBarAddButton
+
+ID=kStr_SysTrapBase+968
+ENGLISH=MenuCmdBarGetButtonData
+
+ID=kStr_SysTrapBase+969
+ENGLISH=MenuCmdBarDisplay
+
+ID=kStr_SysTrapBase+970
+ENGLISH=HwrGetSilkscreenID
+
+ID=kStr_SysTrapBase+971
+ENGLISH=EvtGetSilkscreenAreaList
+
+ID=kStr_SysTrapBase+972
+ENGLISH=SysFatalAlertInit
+
+ID=kStr_SysTrapBase+973
+ENGLISH=DateTemplateToAscii
+
+ID=kStr_SysTrapBase+974
+ENGLISH=SecVerifyPW
+
+ID=kStr_SysTrapBase+975
+ENGLISH=SecSelectViewStatus
+
+ID=kStr_SysTrapBase+976
+ENGLISH=TblSetColumnMasked
+
+ID=kStr_SysTrapBase+977
+ENGLISH=TblSetRowMasked
+
+ID=kStr_SysTrapBase+978
+ENGLISH=TblRowMasked
+
+ID=kStr_SysTrapBase+979
+ENGLISH=FrmCustomResponseAlert
+
+ID=kStr_SysTrapBase+980
+ENGLISH=FrmNewGsi
+
+ID=kStr_SysTrapBase+981
+ENGLISH=MenuShowItem
+
+ID=kStr_SysTrapBase+982
+ENGLISH=MenuHideItem
+
+ID=kStr_SysTrapBase+983
+ENGLISH=MenuAddItem
+
+ID=kStr_SysTrapBase+984
+ENGLISH=FrmSetGadgetHandler
+
+ID=kStr_SysTrapBase+985
+ENGLISH=CtlSetGraphics
+
+ID=kStr_SysTrapBase+986
+ENGLISH=CtlGetSliderValues
+
+ID=kStr_SysTrapBase+987
+ENGLISH=CtlSetSliderValues
+
+ID=kStr_SysTrapBase+988
+ENGLISH=CtlNewSliderControl
+
+ID=kStr_SysTrapBase+989
+ENGLISH=BmpCreate
+
+ID=kStr_SysTrapBase+990
+ENGLISH=BmpDelete
+
+ID=kStr_SysTrapBase+991
+ENGLISH=BmpCompress
+
+ID=kStr_SysTrapBase+992
+ENGLISH=BmpGetColortable
+
+ID=kStr_SysTrapBase+993
+ENGLISH=BmpSize
+
+ID=kStr_SysTrapBase+994
+ENGLISH=BmpBitsSize
+
+ID=kStr_SysTrapBase+995
+ENGLISH=BmpColortableSize
+
+ID=kStr_SysTrapBase+996
+ENGLISH=WinCreateBitmapWindow
+
+ID=kStr_SysTrapBase+997
+ENGLISH=EvtSetNullEventTick
+
+ID=kStr_SysTrapBase+998
+ENGLISH=ExgDoDialog
+
+ID=kStr_SysTrapBase+999
+ENGLISH=SysUICleanup
+
+ID=kStr_SysTrapBase+1000
+ENGLISH=WinSetForeColorRGB
+
+ID=kStr_SysTrapBase+1001
+ENGLISH=WinSetBackColorRGB
+
+ID=kStr_SysTrapBase+1002
+ENGLISH=WinSetTextColorRGB
+
+ID=kStr_SysTrapBase+1003
+ENGLISH=WinGetPixelRGB
+
+ID=kStr_SysTrapBase+1004
+ENGLISH=SysReserved40Trap1
+
+ID=kStr_SysTrapBase+1005
+ENGLISH=SysReserved40Trap2
+
+ID=kStr_SysTrapBase+1006
+ENGLISH=SysReserved40Trap3
+
+ID=kStr_SysTrapBase+1007
+ENGLISH=SysReserved40Trap4
+
+ID=kStr_SysTrapBase+1008
+ENGLISH=CncMgrDispatch
+
+ID=kStr_SysTrapBase+1009
+ENGLISH=SysNotifyBroadcastFromInterrupt
+
+ID=kStr_SysTrapBase+1010
+ENGLISH=EvtWakeupWithoutNilEvent
+
+ID=kStr_SysTrapBase+1011
+ENGLISH=StrCompareAscii
+
+ID=kStr_SysTrapBase+1012
+ENGLISH=AccessorDispatch
+
+ID=kStr_SysTrapBase+1013
+ENGLISH=BltGetPixel
+
+ID=kStr_SysTrapBase+1014
+ENGLISH=BltPaintPixel
+
+ID=kStr_SysTrapBase+1015
+ENGLISH=ScrScreenInit
+
+ID=kStr_SysTrapBase+1016
+ENGLISH=ScrUpdateScreenBitmap
+
+ID=kStr_SysTrapBase+1017
+ENGLISH=ScrPalette
+
+ID=kStr_SysTrapBase+1018
+ENGLISH=ScrGetColortable
+
+ID=kStr_SysTrapBase+1019
+ENGLISH=ScrGetGrayPat
+
+ID=kStr_SysTrapBase+1020
+ENGLISH=ScrScreenLock
+
+ID=kStr_SysTrapBase+1021
+ENGLISH=ScrScreenUnlock
+
+ID=kStr_SysTrapBase+1022
+ENGLISH=FntPrvGetFontList
+
+ID=kStr_SysTrapBase+1023
+ENGLISH=ExgRegisterDatatype
+
+ID=kStr_SysTrapBase+1024
+ENGLISH=ExgNotifyReceive
+
+ID=kStr_SysTrapBase+1025
+ENGLISH=ExgNotifyGoto
+
+ID=kStr_SysTrapBase+1026
+ENGLISH=ExgRequest
+
+ID=kStr_SysTrapBase+1027
+ENGLISH=ExgSetDefaultApplication
+
+ID=kStr_SysTrapBase+1028
+ENGLISH=ExgGetDefaultApplication
+
+ID=kStr_SysTrapBase+1029
+ENGLISH=ExgGetTargetApplication
+
+ID=kStr_SysTrapBase+1030
+ENGLISH=ExgGetRegisteredApplications
+
+ID=kStr_SysTrapBase+1031
+ENGLISH=ExgGetRegisteredTypes
+
+ID=kStr_SysTrapBase+1032
+ENGLISH=ExgNotifyPreview
+
+ID=kStr_SysTrapBase+1033
+ENGLISH=ExgControl
+
+ID=kStr_SysTrapBase+1034
+ENGLISH=LmDispatch
+
+ID=kStr_SysTrapBase+1035
+ENGLISH=MemGetRomNVParams
+
+ID=kStr_SysTrapBase+1036
+ENGLISH=FntWCharWidth
+
+ID=kStr_SysTrapBase+1037
+ENGLISH=DmFindDatabaseWithTypeCreator
+
+ID=kStr_SysTrapBase+1038
+ENGLISH=SelectTimeZone
+
+ID=kStr_SysTrapBase+1039
+ENGLISH=TimeZoneToAscii
+
+ID=kStr_SysTrapBase+1040
+ENGLISH=StrNCompareAscii
+
+ID=kStr_SysTrapBase+1041
+ENGLISH=TimTimeZoneToUTC
+
+ID=kStr_SysTrapBase+1042
+ENGLISH=TimUTCToTimeZone
+
+ID=kStr_SysTrapBase+1043
+ENGLISH=PhoneNumberLookupCustom
+
+ID=kStr_SysTrapBase+1044
+ENGLISH=HwrDebugSelect
+
+ID=kStr_SysTrapBase+1045
+ENGLISH=BltRoundedRectangle
+
+ID=kStr_SysTrapBase+1046
+ENGLISH=BltRoundedRectangleFill
+
+ID=kStr_SysTrapBase+1047
+ENGLISH=WinPrvInitCanvas
+
+ID=kStr_SysTrapBase+1048
+ENGLISH=HwrCalcDynamicHeapSize
+
+ID=kStr_SysTrapBase+1049
+ENGLISH=HwrDebuggerEnter
+
+ID=kStr_SysTrapBase+1050
+ENGLISH=HwrDebuggerExit
+
+ID=kStr_SysTrapBase+1051
+ENGLISH=LstGetTopItem
+
+ID=kStr_SysTrapBase+1052
+ENGLISH=HwrModelInitStage3
+
+ID=kStr_SysTrapBase+1053
+ENGLISH=AttnIndicatorAllow
+
+ID=kStr_SysTrapBase+1054
+ENGLISH=AttnIndicatorAllowed
+
+ID=kStr_SysTrapBase+1055
+ENGLISH=AttnIndicatorEnable
+
+ID=kStr_SysTrapBase+1056
+ENGLISH=AttnIndicatorEnabled
+
+ID=kStr_SysTrapBase+1057
+ENGLISH=AttnIndicatorSetBlinkPattern
+
+ID=kStr_SysTrapBase+1058
+ENGLISH=AttnIndicatorGetBlinkPattern
+
+ID=kStr_SysTrapBase+1059
+ENGLISH=AttnIndicatorTicksTillNextBlink
+
+ID=kStr_SysTrapBase+1060
+ENGLISH=AttnIndicatorCheckBlink
+
+ID=kStr_SysTrapBase+1061
+ENGLISH=AttnInitialize
+
+ID=kStr_SysTrapBase+1062
+ENGLISH=AttnGetAttention
+
+ID=kStr_SysTrapBase+1063
+ENGLISH=AttnUpdate
+
+ID=kStr_SysTrapBase+1064
+ENGLISH=AttnForgetIt
+
+ID=kStr_SysTrapBase+1065
+ENGLISH=AttnGetCounts
+
+ID=kStr_SysTrapBase+1066
+ENGLISH=AttnListOpen
+
+ID=kStr_SysTrapBase+1067
+ENGLISH=AttnHandleEvent
+
+ID=kStr_SysTrapBase+1068
+ENGLISH=AttnEffectOfEvent
+
+ID=kStr_SysTrapBase+1069
+ENGLISH=AttnIterate
+
+ID=kStr_SysTrapBase+1070
+ENGLISH=AttnDoSpecialEffects
+
+ID=kStr_SysTrapBase+1071
+ENGLISH=AttnDoEmergencySpecialEffects
+
+ID=kStr_SysTrapBase+1072
+ENGLISH=AttnAllowClose
+
+ID=kStr_SysTrapBase+1073
+ENGLISH=AttnReopen
+
+ID=kStr_SysTrapBase+1074
+ENGLISH=AttnEnableNotification
+
+ID=kStr_SysTrapBase+1075
+ENGLISH=HwrLEDAttributes
+
+ID=kStr_SysTrapBase+1076
+ENGLISH=HwrVibrateAttributes
+
+ID=kStr_SysTrapBase+1077
+ENGLISH=SecGetPwdHint
+
+ID=kStr_SysTrapBase+1078
+ENGLISH=SecSetPwdHint
+
+ID=kStr_SysTrapBase+1079
+ENGLISH=HwrFlashWrite
+
+ID=kStr_SysTrapBase+1080
+ENGLISH=KeyboardStatusNew
+
+ID=kStr_SysTrapBase+1081
+ENGLISH=KeyboardStatusFree
+
+ID=kStr_SysTrapBase+1082
+ENGLISH=KbdSetLayout
+
+ID=kStr_SysTrapBase+1083
+ENGLISH=KbdGetLayout
+
+ID=kStr_SysTrapBase+1084
+ENGLISH=KbdSetPosition
+
+ID=kStr_SysTrapBase+1085
+ENGLISH=KbdGetPosition
+
+ID=kStr_SysTrapBase+1086
+ENGLISH=KbdSetShiftState
+
+ID=kStr_SysTrapBase+1087
+ENGLISH=KbdGetShiftState
+
+ID=kStr_SysTrapBase+1088
+ENGLISH=KbdDraw
+
+ID=kStr_SysTrapBase+1089
+ENGLISH=KbdErase
+
+ID=kStr_SysTrapBase+1090
+ENGLISH=KbdHandleEvent
+
+ID=kStr_SysTrapBase+1091
+ENGLISH=OEMDispatch2
+
+ID=kStr_SysTrapBase+1092
+ENGLISH=HwrCustom
+
+ID=kStr_SysTrapBase+1093
+ENGLISH=FrmGetActiveField
+
+ID=kStr_SysTrapBase+1094
+ENGLISH=SndPlaySmfIrregardless
+
+ID=kStr_SysTrapBase+1095
+ENGLISH=SndPlaySmfResourceIrregardless
+
+ID=kStr_SysTrapBase+1096
+ENGLISH=SndInterruptSmfIrregardless
+
+ID=kStr_SysTrapBase+1097
+ENGLISH=UdaMgrDispatch
+
+ID=kStr_SysTrapBase+1098
+ENGLISH=PalmPrivate1
+
+ID=kStr_SysTrapBase+1099
+ENGLISH=PalmPrivate2
+
+ID=kStr_SysTrapBase+1100
+ENGLISH=PalmPrivate3
+
+ID=kStr_SysTrapBase+1101
+ENGLISH=PalmPrivate4
+
+ID=kStr_SysTrapBase+1102
+ENGLISH=BmpGetDimensions
+
+ID=kStr_SysTrapBase+1103
+ENGLISH=BmpGetBitDepth
+
+ID=kStr_SysTrapBase+1104
+ENGLISH=BmpGetNextBitmap
+
+ID=kStr_SysTrapBase+1105
+ENGLISH=TblGetNumberOfColumns
+
+ID=kStr_SysTrapBase+1106
+ENGLISH=TblGetTopRow
+
+ID=kStr_SysTrapBase+1107
+ENGLISH=TblSetSelection
+
+ID=kStr_SysTrapBase+1108
+ENGLISH=FrmGetObjectIndexFromPtr
+
+ID=kStr_SysTrapBase+1109
+ENGLISH=BmpGetSizes
+
+ID=kStr_SysTrapBase+1110
+ENGLISH=WinGetBounds
+
+ID=kStr_SysTrapBase+1111
+ENGLISH=BltPaintPixels
+
+ID=kStr_SysTrapBase+1112
+ENGLISH=FldSetMaxVisibleLines
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Library function names
+// --------------------------------------------------------------------------------
+
+// --------------------
+// Common Library functions
+// --------------------
+
+ID=kStr_LibTrapBase+0
+ENGLISH=SysLibName
+
+ID=kStr_LibTrapBase+1
+ENGLISH=SysLibOpen
+
+ID=kStr_LibTrapBase+2
+ENGLISH=SysLibClose
+
+ID=kStr_LibTrapBase+3
+ENGLISH=SysLibSleep
+
+ID=kStr_LibTrapBase+4
+ENGLISH=SysLibWake
+
+
+// --------------------
+// HTAL Library
+// --------------------
+
+ID=kStr_HTALLibTrapBase+1
+ENGLISH=HtalLibOpen
+
+ID=kStr_HTALLibTrapBase+2
+ENGLISH=HtalLibClose
+
+ID=kStr_HTALLibTrapBase+3
+ENGLISH=HtalLibSleep
+
+ID=kStr_HTALLibTrapBase+4
+ENGLISH=HtalLibWake
+
+ID=kStr_HTALLibTrapBase+5
+ENGLISH=HtalLibSetOption
+
+ID=kStr_HTALLibTrapBase+6
+ENGLISH=HtalLibGetOption
+
+ID=kStr_HTALLibTrapBase+7
+ENGLISH=HtalLibControl
+
+ID=kStr_HTALLibTrapBase+8
+ENGLISH=HtalLibConnectPhase1
+
+ID=kStr_HTALLibTrapBase+9
+ENGLISH=HtalLibDisconnect
+
+ID=kStr_HTALLibTrapBase+10
+ENGLISH=HtalLibGetCommand
+
+ID=kStr_HTALLibTrapBase+11
+ENGLISH=HtalLibSendReply
+
+ID=kStr_HTALLibTrapBase+12
+ENGLISH=HtalLibCancel
+
+ID=kStr_HTALLibTrapBase+13
+ENGLISH=HtalLibMaxBlockSize
+
+ID=kStr_HTALLibTrapBase+14
+ENGLISH=HtalLibVersion
+
+ID=kStr_HTALLibTrapBase+15
+ENGLISH=HtalLibAddSegmentSizes
+
+ID=kStr_HTALLibTrapBase+16
+ENGLISH=HtalLibConnectPhase2
+
+
+// --------------------
+// INet Library
+// --------------------
+
+ID=kStr_INetLibTrapBase+1
+ENGLISH=INetLibOpen
+
+ID=kStr_INetLibTrapBase+2
+ENGLISH=INetLibClose
+
+ID=kStr_INetLibTrapBase+3
+ENGLISH=INetLibSleep
+
+ID=kStr_INetLibTrapBase+4
+ENGLISH=INetLibWake
+
+ID=kStr_INetLibTrapBase+5
+ENGLISH=INetLibSettingGet
+
+ID=kStr_INetLibTrapBase+6
+ENGLISH=INetLibSettingSet
+
+ID=kStr_INetLibTrapBase+7
+ENGLISH=INetLibGetEvent
+
+ID=kStr_INetLibTrapBase+8
+ENGLISH=INetLibURLOpen
+
+ID=kStr_INetLibTrapBase+9
+ENGLISH=INetLibSockRead
+
+ID=kStr_INetLibTrapBase+10
+ENGLISH=INetLibSockWrite
+
+ID=kStr_INetLibTrapBase+11
+ENGLISH=INetLibSockOpen
+
+ID=kStr_INetLibTrapBase+12
+ENGLISH=INetLibSockClose
+
+ID=kStr_INetLibTrapBase+13
+ENGLISH=INetLibSockStatus
+
+ID=kStr_INetLibTrapBase+14
+ENGLISH=INetLibSockSettingGet
+
+ID=kStr_INetLibTrapBase+15
+ENGLISH=INetLibSockSettingSet
+
+ID=kStr_INetLibTrapBase+16
+ENGLISH=INetLibSockConnect
+
+ID=kStr_INetLibTrapBase+17
+ENGLISH=INetLibURLCrack
+
+ID=kStr_INetLibTrapBase+18
+ENGLISH=INetLibURLsAdd
+
+ID=kStr_INetLibTrapBase+19
+ENGLISH=INetLibURLsCompare
+
+ID=kStr_INetLibTrapBase+20
+ENGLISH=INetLibURLGetInfo
+
+ID=kStr_INetLibTrapBase+21
+ENGLISH=INetLibSockHTTPReqCreate
+
+ID=kStr_INetLibTrapBase+22
+ENGLISH=INetLibSockHTTPAttrSet
+
+ID=kStr_INetLibTrapBase+23
+ENGLISH=INetLibSockHTTPReqSend
+
+ID=kStr_INetLibTrapBase+24
+ENGLISH=INetLibSockHTTPAttrGet
+
+ID=kStr_INetLibTrapBase+25
+ENGLISH=INetLibSockMailReqCreate
+
+ID=kStr_INetLibTrapBase+26
+ENGLISH=INetLibSockMailAttrSet
+
+ID=kStr_INetLibTrapBase+27
+ENGLISH=INetLibSockMailReqAdd
+
+ID=kStr_INetLibTrapBase+28
+ENGLISH=INetLibSockMailReqSend
+
+ID=kStr_INetLibTrapBase+29
+ENGLISH=INetLibSockMailAttrGet
+
+ID=kStr_INetLibTrapBase+30
+ENGLISH=inetLibTrapSockMailQueryProgress
+
+ID=kStr_INetLibTrapBase+31
+ENGLISH=INetLibCacheList
+
+ID=kStr_INetLibTrapBase+32
+ENGLISH=INetLibCacheGetObject
+
+ID=kStr_INetLibTrapBase+33
+ENGLISH=INetLibConfigMakeActive
+
+ID=kStr_INetLibTrapBase+34
+ENGLISH=INetLibConfigList
+
+ID=kStr_INetLibTrapBase+35
+ENGLISH=INetLibConfigIndexFromName
+
+ID=kStr_INetLibTrapBase+36
+ENGLISH=INetLibConfigDelete
+
+ID=kStr_INetLibTrapBase+37
+ENGLISH=INetLibConfigSaveAs
+
+ID=kStr_INetLibTrapBase+38
+ENGLISH=INetLibConfigRename
+
+ID=kStr_INetLibTrapBase+39
+ENGLISH=INetLibConfigAliasSet
+
+ID=kStr_INetLibTrapBase+40
+ENGLISH=INetLibConfigAliasGet
+
+
+// --------------------
+// IR Library
+// --------------------
+
+ID=kStr_IrLibTrapBase+1
+ENGLISH=ExgLibOpen
+
+ID=kStr_IrLibTrapBase+2
+ENGLISH=ExgLibCLose
+
+ID=kStr_IrLibTrapBase+3
+ENGLISH=ExgLibSleep
+
+ID=kStr_IrLibTrapBase+4
+ENGLISH=ExgLibWake
+
+ID=kStr_IrLibTrapBase+5
+ENGLISH=ExgLibHandleEvent
+
+ID=kStr_IrLibTrapBase+6
+ENGLISH=ExgLibConnect
+
+ID=kStr_IrLibTrapBase+7
+ENGLISH=ExgLibAccept
+
+ID=kStr_IrLibTrapBase+8
+ENGLISH=ExgLibDisconnect
+
+ID=kStr_IrLibTrapBase+9
+ENGLISH=ExgLibPut
+
+ID=kStr_IrLibTrapBase+10
+ENGLISH=ExgLibGet
+
+ID=kStr_IrLibTrapBase+11
+ENGLISH=ExgLibSend
+
+ID=kStr_IrLibTrapBase+12
+ENGLISH=ExgLibReceive
+
+ID=kStr_IrLibTrapBase+13
+ENGLISH=ExgLibControl
+
+ID=kStr_IrLibTrapBase+14
+ENGLISH=ExgLibReserved1
+
+ID=kStr_IrLibTrapBase+15
+ENGLISH=IrBind
+
+ID=kStr_IrLibTrapBase+16
+ENGLISH=IrUnBind
+
+ID=kStr_IrLibTrapBase+17
+ENGLISH=IrDiscoverReq
+
+ID=kStr_IrLibTrapBase+18
+ENGLISH=IrConnectIrLap
+
+ID=kStr_IrLibTrapBase+19
+ENGLISH=IrDisconnectIrLap
+
+ID=kStr_IrLibTrapBase+20
+ENGLISH=IrConnectReq
+
+ID=kStr_IrLibTrapBase+21
+ENGLISH=IrConnectRsp
+
+ID=kStr_IrLibTrapBase+22
+ENGLISH=IrDataReq
+
+ID=kStr_IrLibTrapBase+23
+ENGLISH=IrLocalBusy
+
+ID=kStr_IrLibTrapBase+24
+ENGLISH=IrMaxTxSize
+
+ID=kStr_IrLibTrapBase+25
+ENGLISH=IrMaxRxSize
+
+ID=kStr_IrLibTrapBase+26
+ENGLISH=IrSetDeviceInfo
+
+ID=kStr_IrLibTrapBase+27
+ENGLISH=IrIsNoProgress
+
+ID=kStr_IrLibTrapBase+28
+ENGLISH=IrIsRemoteBusy
+
+ID=kStr_IrLibTrapBase+29
+ENGLISH=IrIsMediaBusy
+
+ID=kStr_IrLibTrapBase+30
+ENGLISH=IrIsIrLapConnected
+
+ID=kStr_IrLibTrapBase+31
+ENGLISH=IrTestReq
+
+ID=kStr_IrLibTrapBase+32
+ENGLISH=IrIAS_Add
+
+ID=kStr_IrLibTrapBase+33
+ENGLISH=IrIAS_Query
+
+ID=kStr_IrLibTrapBase+34
+ENGLISH=IrIAS_SetDeviceName
+
+ID=kStr_IrLibTrapBase+35
+ENGLISH=IrIAS_Next
+
+ID=kStr_IrLibTrapBase+36
+ENGLISH=IrIrOpen
+
+ID=kStr_IrLibTrapBase+37
+ENGLISH=IrHandleEvent
+
+ID=kStr_IrLibTrapBase+38
+ENGLISH=IrWaitForEvent
+
+
+// --------------------
+// Net Library
+// --------------------
+
+ID=kStr_NetLibTrapBase+1
+ENGLISH=NetLibOpen
+
+ID=kStr_NetLibTrapBase+2
+ENGLISH=NetLibCLose
+
+ID=kStr_NetLibTrapBase+3
+ENGLISH=NetLibSleep
+
+ID=kStr_NetLibTrapBase+4
+ENGLISH=NetLibWake
+
+ID=kStr_NetLibTrapBase+5
+ENGLISH=NetLibAddrINToA
+
+ID=kStr_NetLibTrapBase+6
+ENGLISH=NetLibAddrAToIN
+
+ID=kStr_NetLibTrapBase+7
+ENGLISH=NetLibSocketOpen
+
+ID=kStr_NetLibTrapBase+8
+ENGLISH=NetLibSocketClose
+
+ID=kStr_NetLibTrapBase+9
+ENGLISH=NetLibSocketOptionSet
+
+ID=kStr_NetLibTrapBase+10
+ENGLISH=NetLibSocketOptionGet
+
+ID=kStr_NetLibTrapBase+11
+ENGLISH=NetLibSocketBind
+
+ID=kStr_NetLibTrapBase+12
+ENGLISH=NetLibSocketConnect
+
+ID=kStr_NetLibTrapBase+13
+ENGLISH=NetLibSocketListen
+
+ID=kStr_NetLibTrapBase+14
+ENGLISH=NetLibSocketAccept
+
+ID=kStr_NetLibTrapBase+15
+ENGLISH=NetLibSocketShutdown
+
+ID=kStr_NetLibTrapBase+16
+ENGLISH=NetLibSendPB
+
+ID=kStr_NetLibTrapBase+17
+ENGLISH=NetLibSend
+
+ID=kStr_NetLibTrapBase+18
+ENGLISH=NetLibReceivePB
+
+ID=kStr_NetLibTrapBase+19
+ENGLISH=NetLibReceive
+
+ID=kStr_NetLibTrapBase+20
+ENGLISH=NetLibDmReceive
+
+ID=kStr_NetLibTrapBase+21
+ENGLISH=NetLibSelect
+
+ID=kStr_NetLibTrapBase+22
+ENGLISH=*NetLibPrefsGet*
+
+ID=kStr_NetLibTrapBase+23
+ENGLISH=*NetLibPrefsSet*
+
+ID=kStr_NetLibTrapBase+24
+ENGLISH=*NetLibDrvrWake*
+
+ID=kStr_NetLibTrapBase+25
+ENGLISH=*NetLibInterfacePtr*
+
+ID=kStr_NetLibTrapBase+26
+ENGLISH=NetLibMaster
+
+ID=kStr_NetLibTrapBase+27
+ENGLISH=NetLibGetHostByName
+
+ID=kStr_NetLibTrapBase+28
+ENGLISH=NetLibSettingGet
+
+ID=kStr_NetLibTrapBase+29
+ENGLISH=NetLibSettingSet
+
+ID=kStr_NetLibTrapBase+30
+ENGLISH=NetLibIFAttach
+
+ID=kStr_NetLibTrapBase+31
+ENGLISH=NetLibIFDetach
+
+ID=kStr_NetLibTrapBase+32
+ENGLISH=NetLibIFGet
+
+ID=kStr_NetLibTrapBase+33
+ENGLISH=NetLibIFSettingGet
+
+ID=kStr_NetLibTrapBase+34
+ENGLISH=NetLibIFSettingSet
+
+ID=kStr_NetLibTrapBase+35
+ENGLISH=NetLibIFUp
+
+ID=kStr_NetLibTrapBase+36
+ENGLISH=NetLibIFDown
+
+ID=kStr_NetLibTrapBase+37
+ENGLISH=NetLibIFMediaUp
+
+ID=kStr_NetLibTrapBase+38
+ENGLISH=*NetLibScriptExecute*
+
+ID=kStr_NetLibTrapBase+39
+ENGLISH=NetLibGetHostByAddr
+
+ID=kStr_NetLibTrapBase+40
+ENGLISH=NetLibGetServByName
+
+ID=kStr_NetLibTrapBase+41
+ENGLISH=NetLibGetHostByAddr
+
+ID=kStr_NetLibTrapBase+42
+ENGLISH=NetLibFinishCloseWait
+
+ID=kStr_NetLibTrapBase+43
+ENGLISH=NetLibGetMailExchangeByName
+
+ID=kStr_NetLibTrapBase+44
+ENGLISH=*NetLibPrefsAppend*
+
+ID=kStr_NetLibTrapBase+45
+ENGLISH=*NetLibIFMediaDown*
+
+ID=kStr_NetLibTrapBase+46
+ENGLISH=NetLibOpenCount
+
+ID=kStr_NetLibTrapBase+47
+ENGLISH=NetLibTracePrintF
+
+ID=kStr_NetLibTrapBase+48
+ENGLISH=NetLibTracePutS
+
+ID=kStr_NetLibTrapBase+49
+ENGLISH=NetLibOpenIfCloseWait
+
+ID=kStr_NetLibTrapBase+50
+ENGLISH=NetLibHandlePowerOff
+
+ID=kStr_NetLibTrapBase+51
+ENGLISH=NetLibConnectionRefresh
+
+ID=kStr_NetLibTrapBase+52
+ENGLISH=NetLibBitMove
+
+ID=kStr_NetLibTrapBase+53
+ENGLISH=NetLibBitPutFixed
+
+ID=kStr_NetLibTrapBase+54
+ENGLISH=NetLibBitGetFixed
+
+ID=kStr_NetLibTrapBase+55
+ENGLISH=NetLibBitPutUIntV
+
+ID=kStr_NetLibTrapBase+56
+ENGLISH=NetLibBitGetUIntV
+
+ID=kStr_NetLibTrapBase+57
+ENGLISH=NetLibBitPutIntV
+
+ID=kStr_NetLibTrapBase+58
+ENGLISH=NetLibBitGetIntV
+
+ID=kStr_NetLibTrapBase+59
+ENGLISH=NetLibOpenConfig
+
+ID=kStr_NetLibTrapBase+60
+ENGLISH=NetLibConfigMakeActive
+
+ID=kStr_NetLibTrapBase+61
+ENGLISH=NetLibConfigList
+
+ID=kStr_NetLibTrapBase+62
+ENGLISH=NetLibConfigIndexFromName
+
+ID=kStr_NetLibTrapBase+63
+ENGLISH=NetLibConfigDelete
+
+ID=kStr_NetLibTrapBase+64
+ENGLISH=NetLibConfigSaveAs
+
+ID=kStr_NetLibTrapBase+65
+ENGLISH=NetLibConfigRename
+
+ID=kStr_NetLibTrapBase+66
+ENGLISH=NetLibConfigAliasSet
+
+ID=kStr_NetLibTrapBase+67
+ENGLISH=NetLibConfigAliasGet
+
+
+// --------------------
+// NetPlugIn Library
+// --------------------
+
+ID=kStr_NPILibTrapBase+1
+ENGLISH=NPILibOpen
+
+ID=kStr_NPILibTrapBase+2
+ENGLISH=NPILibClose
+
+ID=kStr_NPILibTrapBase+3
+ENGLISH=NPILibSleep
+
+ID=kStr_NPILibTrapBase+4
+ENGLISH=NPILibWake
+
+ID=kStr_NPILibTrapBase+5
+ENGLISH=NPILibInfo
+
+ID=kStr_NPILibTrapBase+6
+ENGLISH=NPILibSocketOpen
+
+ID=kStr_NPILibTrapBase+7
+ENGLISH=NPILibSocketClose
+
+ID=kStr_NPILibTrapBase+8
+ENGLISH=NPILibSocketOptionSet
+
+ID=kStr_NPILibTrapBase+9
+ENGLISH=NPILibSocketOptionGet
+
+ID=kStr_NPILibTrapBase+10
+ENGLISH=NPILibSocketBind
+
+ID=kStr_NPILibTrapBase+11
+ENGLISH=NPILibSocketConnect
+
+ID=kStr_NPILibTrapBase+12
+ENGLISH=NPILibSocketListen
+
+ID=kStr_NPILibTrapBase+13
+ENGLISH=NPILibSocketAccept
+
+ID=kStr_NPILibTrapBase+14
+ENGLISH=NPILibSocketShutdown
+
+ID=kStr_NPILibTrapBase+15
+ENGLISH=NPILibSocketAddr
+
+ID=kStr_NPILibTrapBase+16
+ENGLISH=NPILibSocketNativeRefnum
+
+ID=kStr_NPILibTrapBase+17
+ENGLISH=NPILibSocketReady
+
+ID=kStr_NPILibTrapBase+18
+ENGLISH=NPILibSocketReceivePB
+
+ID=kStr_NPILibTrapBase+19
+ENGLISH=NPILibSocketSendPB
+
+
+// --------------------
+// Rail Library
+// --------------------
+
+ID=kStr_RailLibTrapBase+1
+ENGLISH=RailLibOpen
+
+ID=kStr_RailLibTrapBase+2
+ENGLISH=RailLibClose
+
+ID=kStr_RailLibTrapBase+3
+ENGLISH=RailLibSleep
+
+ID=kStr_RailLibTrapBase+4
+ENGLISH=RailLibWake
+
+
+// --------------------
+// Security Library
+// --------------------
+
+ID=kStr_SecLibTrapBase+1
+ENGLISH=SecLibOpen
+
+ID=kStr_SecLibTrapBase+2
+ENGLISH=SecLibClose
+
+ID=kStr_SecLibTrapBase+3
+ENGLISH=SecLibSleep
+
+ID=kStr_SecLibTrapBase+4
+ENGLISH=SecLibWake
+
+ID=kStr_SecLibTrapBase+5
+ENGLISH=SecLibGetContextSize
+
+ID=kStr_SecLibTrapBase+6
+ENGLISH=SecLibResetSeqNum
+
+ID=kStr_SecLibTrapBase+7
+ENGLISH=SecLibGetSignedPublicKey
+
+ID=kStr_SecLibTrapBase+8
+ENGLISH=SecLibProcessSignedKey
+
+ID=kStr_SecLibTrapBase+9
+ENGLISH=SecLibEncryptBegin
+
+ID=kStr_SecLibTrapBase+10
+ENGLISH=SecLibEncrypt
+
+ID=kStr_SecLibTrapBase+11
+ENGLISH=SecLibEncryptEnd
+
+ID=kStr_SecLibTrapBase+12
+ENGLISH=SecLibDecryptBegin
+
+ID=kStr_SecLibTrapBase+13
+ENGLISH=SecLibDecrypt
+
+ID=kStr_SecLibTrapBase+14
+ENGLISH=SecLibDecryptEnd
+
+ID=kStr_SecLibTrapBase+15
+ENGLISH=SecLibDebug
+
+ID=kStr_SecLibTrapBase+16
+ENGLISH=SecRamEncrypt
+
+ID=kStr_SecLibTrapBase+17
+ENGLISH=SecRamDecrypt
+
+ID=kStr_SecLibTrapBase+18
+ENGLISH=SecLibSetKeyPath
+
+
+// --------------------
+// Serial Library
+// --------------------
+
+ID=kStr_SerLibTrapBase+1
+ENGLISH=SerLibOpen
+
+ID=kStr_SerLibTrapBase+2
+ENGLISH=SerLibClose
+
+ID=kStr_SerLibTrapBase+3
+ENGLISH=SerLibSleep
+
+ID=kStr_SerLibTrapBase+4
+ENGLISH=SerLibWake
+
+ID=kStr_SerLibTrapBase+5
+ENGLISH=SerGetSettings
+
+ID=kStr_SerLibTrapBase+6
+ENGLISH=SerSetSettings
+
+ID=kStr_SerLibTrapBase+7
+ENGLISH=SerGetStatus
+
+ID=kStr_SerLibTrapBase+8
+ENGLISH=SerClearErr
+
+ID=kStr_SerLibTrapBase+9
+ENGLISH=SerSend10
+
+ID=kStr_SerLibTrapBase+10
+ENGLISH=SerSendWait
+
+ID=kStr_SerLibTrapBase+11
+ENGLISH=SerSendCheck
+
+ID=kStr_SerLibTrapBase+12
+ENGLISH=SerSendFlush
+
+ID=kStr_SerLibTrapBase+13
+ENGLISH=SerReceive10
+
+ID=kStr_SerLibTrapBase+14
+ENGLISH=SerReceiveWait
+
+ID=kStr_SerLibTrapBase+15
+ENGLISH=SerReceiveCheck
+
+ID=kStr_SerLibTrapBase+16
+ENGLISH=SerReceiveFlush
+
+ID=kStr_SerLibTrapBase+17
+ENGLISH=SerSetReceiveBuffer
+
+ID=kStr_SerLibTrapBase+18
+ENGLISH=SerReceiveWindowOpen
+
+ID=kStr_SerLibTrapBase+19
+ENGLISH=SerReceiveWindowClose
+
+ID=kStr_SerLibTrapBase+20
+ENGLISH=SerSetWakeupHandler
+
+ID=kStr_SerLibTrapBase+21
+ENGLISH=SerPrimeWakeupHandler
+
+ID=kStr_SerLibTrapBase+22
+ENGLISH=SerControl
+
+ID=kStr_SerLibTrapBase+23
+ENGLISH=SerSend
+
+ID=kStr_SerLibTrapBase+24
+ENGLISH=SerReceive
+
+
+// --------------------
+// Web Library
+// --------------------
+
+ID=kStr_WebLibTrapBase+1
+ENGLISH=WebLibOpen
+
+ID=kStr_WebLibTrapBase+2
+ENGLISH=WebLibClose
+
+ID=kStr_WebLibTrapBase+3
+ENGLISH=WebLibSleep
+
+ID=kStr_WebLibTrapBase+4
+ENGLISH=WebLibWake
+
+ID=kStr_WebLibTrapBase+5
+ENGLISH=WebLibSettingGet
+
+ID=kStr_WebLibTrapBase+6
+ENGLISH=WebLibSettingSet
+
+ID=kStr_WebLibTrapBase+7
+ENGLISH=WebLibFormHandleEvent
+
+ID=kStr_WebLibTrapBase+8
+ENGLISH=WebLibHandleEvent
+
+ID=kStr_WebLibTrapBase+9
+ENGLISH=WebLibRender
+
+ID=kStr_WebLibTrapBase+10
+ENGLISH=WebLibRenderCache
+
+ID=kStr_WebLibTrapBase+11
+ENGLISH=WebLibRenderCancel
+
+ID=kStr_WebLibTrapBase+12
+ENGLISH=WebLibCopyToClipboard
+
+ID=kStr_WebLibTrapBase+13
+ENGLISH=WebLibGetScrollData
+
+ID=kStr_WebLibTrapBase+14
+ENGLISH=WebLibScroll
+
+ID=kStr_WebLibTrapBase+15
+ENGLISH=WebLibCMLToSimpleText
+
+ID=kStr_WebLibTrapBase+16
+ENGLISH=WebLibSimpleTextToCML
+
+ID=kStr_WebLibTrapBase+17
+ENGLISH=WebLibSelectAll
+
+ID=kStr_WebLibTrapBase+18
+ENGLISH=WebLibRedrawForm
+
+ID=kStr_WebLibTrapBase+19
+ENGLISH=WebLibRenderComplete
+
+ID=kStr_WebLibTrapBase+20
+ENGLISH=WebLibRenderData
+
+
+// --------------------------------------------------------------------------------
+// Template Parts -- Error descriptions
+// --------------------------------------------------------------------------------
+
+// NOTE: the following is commented with C++ comments instead of C comments
+// because the included MPW script contains a */ that prematurely closes
+// the comment.
+//
+// The following strings were generated as follows. First, the following
+// lines were selected in the MPW Shell and executed:
+//
+// Set root "Phantom:Palm:Projects:Palm:Viewer:dev:4.0:primary:Incs:"
+// for f in `files -f -s -r "{root}"`
+// continue if ("{f}" =~ /ÅCMServerÅ/) # duplicate cmp error codes with CMClient.h
+// continue if ("{f}" =~ /ÅDLClientÅ/) # duplicate dlk error codes with DLServer.h
+// continue if ("{f}" =~ /ÅPadServerÅ/) # duplicate pad error codes with PadWS.h
+// continue if ("{f}" =~ /ÅUDAMgrÅ/) # udaErrControl not formatted nicely
+// search -q -ns /¶#defineŶ(ÅErrorClassŶ|Å/ "{f}"
+// end
+//
+// Next, the output was selected and pasted into a new MPW window. Then
+// the following lines were selected in the MPW Shell and executed:
+//
+// # Put everthing into ID/ENGLISH format
+// find ¥
+// replace -c ° /¥¶#define[ ¶t]+([ ¶t]+)¨1Ŷ(([a-z0-9]+)¨2[ ¶t]*¶|[ ¶t]*([x0-9a-f]+)¨3¶)(Å)¨4/ "ID=kStr_PalmOSErrorBase+¨2+¨3¶nENGLISH=¨1¨4¶n"
+//
+// # Convert any trailing comments (C++ version)
+// find ¥
+// replace -c ° /[ ¶t]*¶/¶/[ ¶t]*/ " -- "
+//
+// # Convert any trialing comments (C version)
+// find ¥
+// replace -c ° /[ ¶t]*¶/¶*[ ¶t](Å)¨1[ ¶t]¶*¶// " -- ¨1"
+//
+// # Remove any trialing periods in comments
+// find ¥
+// replace -c ° /.°/ ""
+
+ID=kStr_PalmOSErrorBase+hwrErrorClass+1
+ENGLISH=hwrErrHwrCustomNotImplemented
+
+ID=kStr_PalmOSErrorBase+hwrErrorClass+2
+ENGLISH=hwrErrCreatorNotSupported
+
+ID=kStr_PalmOSErrorBase+hwrErrorClass+3
+ENGLISH=hwrErrSelectorNotSupported
+
+ID=kStr_PalmOSErrorBase+hwrErrorClass+4
+ENGLISH=hwrErrParamTooSmall
+
+ID=kStr_PalmOSErrorBase+almErrorClass+1
+ENGLISH=almErrMemory -- ran out of memory
+
+ID=kStr_PalmOSErrorBase+almErrorClass+2
+ENGLISH=almErrFull -- alarm table is full
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+1
+ENGLISH=cncErrAddProfileFailed -- Add profile attempt failed
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+2
+ENGLISH=cncErrProfileListFull -- Add attempt failed because the
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+3
+ENGLISH=cncErrGetProfileFailed -- Get profile attempt failed
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+4
+ENGLISH=cncErrConDBNotFound -- Connection database not found
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+5
+ENGLISH=cncErrGetProfileListFailed -- Could not get profile list
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+6
+ENGLISH=cncErrProfileReadOnly -- The profile can not be altered
+
+ID=kStr_PalmOSErrorBase+cncErrorClass+7
+ENGLISH=cncErrProfileNotFound -- The profile could not be found
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+1
+ENGLISH=dmErrMemError
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+2
+ENGLISH=dmErrIndexOutOfRange
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+3
+ENGLISH=dmErrInvalidParam
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+4
+ENGLISH=dmErrReadOnly
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+5
+ENGLISH=dmErrDatabaseOpen
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+6
+ENGLISH=dmErrCantOpen
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+7
+ENGLISH=dmErrCantFind
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+8
+ENGLISH=dmErrRecordInWrongCard
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+9
+ENGLISH=dmErrCorruptDatabase
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+10
+ENGLISH=dmErrRecordDeleted
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+11
+ENGLISH=dmErrRecordArchived
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+12
+ENGLISH=dmErrNotRecordDB
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+13
+ENGLISH=dmErrNotResourceDB
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+14
+ENGLISH=dmErrROMBased
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+15
+ENGLISH=dmErrRecordBusy
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+16
+ENGLISH=dmErrResourceNotFound
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+17
+ENGLISH=dmErrNoOpenDatabase
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+18
+ENGLISH=dmErrInvalidCategory
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+19
+ENGLISH=dmErrNotValidRecord
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+20
+ENGLISH=dmErrWriteOutOfBounds
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+21
+ENGLISH=dmErrSeekFailed
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+22
+ENGLISH=dmErrAlreadyOpenForWrites
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+23
+ENGLISH=dmErrOpenedByAnotherTask
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+24
+ENGLISH=dmErrUniqueIDNotFound
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+25
+ENGLISH=dmErrAlreadyExists
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+26
+ENGLISH=dmErrInvalidDatabaseName
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+27
+ENGLISH=dmErrDatabaseProtected
+
+ID=kStr_PalmOSErrorBase+dmErrorClass+28
+ENGLISH=dmErrDatabaseNotProtected
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+1
+ENGLISH=dlkErrParam -- invalid parameter
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+2
+ENGLISH=dlkErrMemory -- memory allocation error
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+3
+ENGLISH=dlkErrNoSession -- could not establish a session
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+4
+ENGLISH=dlkErrSizeErr -- reply length was too big
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+5
+ENGLISH=dlkErrLostConnection -- lost connection
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+6
+ENGLISH=dlkErrInterrupted -- sync was interrupted (see sync state)
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+7
+ENGLISH=dlkErrUserCan -- cancelled by user
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+8
+ENGLISH=dlkErrIncompatibleProducts -- incompatible desktop version
+
+ID=kStr_PalmOSErrorBase+dlkErrorClass+9
+ENGLISH=dlkErrNPOD -- New Password, Old Desktop
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+1
+ENGLISH=exgMemError
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+2
+ENGLISH=exgErrStackInit -- stack could not initialize
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+3
+ENGLISH=exgErrUserCancel
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+4
+ENGLISH=exgErrNoReceiver -- receiver device not found
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+5
+ENGLISH=exgErrNoKnownTarget -- can't find a target app
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+6
+ENGLISH=exgErrTargetMissing -- target app is known but missing
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+7
+ENGLISH=exgErrNotAllowed -- operation not allowed
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+8
+ENGLISH=exgErrBadData -- internal data was not valid
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+9
+ENGLISH=exgErrAppError -- generic application error
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+10
+ENGLISH=exgErrUnknown -- unknown general error
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+11
+ENGLISH=exgErrDeviceFull -- device is full
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+12
+ENGLISH=exgErrDisconnected -- link disconnected
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+13
+ENGLISH=exgErrNotFound -- requested object not found
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+14
+ENGLISH=exgErrBadParam -- bad parameter to call
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+15
+ENGLISH=exgErrNotSupported -- operation not supported by this library
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+16
+ENGLISH=exgErrDeviceBusy -- device is busy
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+17
+ENGLISH=exgErrBadLibrary -- bad or missing ExgLibrary
+
+ID=kStr_PalmOSErrorBase+exgErrorClass+18
+ENGLISH=exgErrNotEnoughPower -- Device has not enough power to perform the requested operation
+
+ID=kStr_PalmOSErrorBase+ftrErrorClass+1
+ENGLISH=ftrErrInvalidParam
+
+ID=kStr_PalmOSErrorBase+ftrErrorClass+2
+ENGLISH=ftrErrNoSuchFeature
+
+ID=kStr_PalmOSErrorBase+ftrErrorClass+3
+ENGLISH=ftrErrAlreadyExists
+
+ID=kStr_PalmOSErrorBase+ftrErrorClass+4
+ENGLISH=ftrErrROMBased
+
+ID=kStr_PalmOSErrorBase+ftrErrorClass+5
+ENGLISH=ftrErrInternalErr
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+1
+ENGLISH=fileErrMemError -- out of memory error
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+2
+ENGLISH=fileErrInvalidParam -- invalid parameter value passed
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+3
+ENGLISH=fileErrCorruptFile -- the file is corrupted/invalid/not a stream file
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+4
+ENGLISH=fileErrNotFound -- couldn't find the file
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+5
+ENGLISH=fileErrTypeCreatorMismatch -- file's type and creator didn't match those expected
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+6
+ENGLISH=fileErrReplaceError -- couldn't replace an existing file
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+7
+ENGLISH=fileErrCreateError -- couldn't create a new file
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+8
+ENGLISH=fileErrOpenError -- generic open error
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+9
+ENGLISH=fileErrInUse -- file couldn't be opened or deleted because it is in use
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+10
+ENGLISH=fileErrReadOnly -- couldn't open in write mode because db is read-only
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+11
+ENGLISH=fileErrInvalidDescriptor -- invalid file descriptor (FileHandle)
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+12
+ENGLISH=fileErrCloseError -- error closing the database
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+13
+ENGLISH=fileErrOutOfBounds -- attempted operation went out of bounds of the file
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+14
+ENGLISH=fileErrPermissionDenied -- couldn't write to a file open for read-only access
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+15
+ENGLISH=fileErrIOError -- general I/O error
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+16
+ENGLISH=fileErrEOF -- end-of-file error
+
+ID=kStr_PalmOSErrorBase+fileErrorClass+17
+ENGLISH=fileErrNotStream -- attempted to open a file that is not a stream
+
+ID=kStr_PalmOSErrorBase+flpErrorClass+1
+ENGLISH=flpErrOutOfRange
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+1
+ENGLISH=grfErrBadParam
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+2
+ENGLISH=grfErrPointBufferFull
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+3
+ENGLISH=grfErrNoGlyphTable
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+4
+ENGLISH=grfErrNoDictionary
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+5
+ENGLISH=grfErrNoMapping
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+6
+ENGLISH=grfErrMacroNotFound
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+7
+ENGLISH=grfErrDepthTooDeep
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+8
+ENGLISH=grfErrMacroPtrTooSmall
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+9
+ENGLISH=grfErrNoMacros
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+129
+ENGLISH=grfErrMacroIncomplete -- (grfWarningOffset+1)
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+130
+ENGLISH=grfErrBranchNotFound -- (grfWarningOffset+2)
+
+ID=kStr_PalmOSErrorBase+grfErrorClass+16
+ENGLISH=grfErrGenericHWRErrBase
+
+ID=kStr_PalmOSErrorBase+intlErrorClass+1
+ENGLISH=intlErrInvalidSelector
+
+ID=kStr_PalmOSErrorBase+lmErrorClass+1
+ENGLISH=lmErrUnknownLocale
+
+ID=kStr_PalmOSErrorBase+lmErrorClass+2
+ENGLISH=lmErrBadLocaleIndex
+
+ID=kStr_PalmOSErrorBase+lmErrorClass+3
+ENGLISH=lmErrBadLocaleSettingChoice
+
+ID=kStr_PalmOSErrorBase+lmErrorClass+4
+ENGLISH=lmErrSettingDataOverflow
+
+ID=kStr_PalmOSErrorBase+memErrorClass+1
+ENGLISH=memErrChunkLocked
+
+ID=kStr_PalmOSErrorBase+memErrorClass+2
+ENGLISH=memErrNotEnoughSpace
+
+ID=kStr_PalmOSErrorBase+memErrorClass+3
+ENGLISH=memErrInvalidParam -- invalid param or requested size is too big
+
+ID=kStr_PalmOSErrorBase+memErrorClass+4
+ENGLISH=memErrChunkNotLocked
+
+ID=kStr_PalmOSErrorBase+memErrorClass+5
+ENGLISH=memErrCardNotPresent
+
+ID=kStr_PalmOSErrorBase+memErrorClass+6
+ENGLISH=memErrNoCardHeader
+
+ID=kStr_PalmOSErrorBase+memErrorClass+7
+ENGLISH=memErrInvalidStoreHeader
+
+ID=kStr_PalmOSErrorBase+memErrorClass+8
+ENGLISH=memErrRAMOnlyCard
+
+ID=kStr_PalmOSErrorBase+memErrorClass+9
+ENGLISH=memErrWriteProtect
+
+ID=kStr_PalmOSErrorBase+memErrorClass+10
+ENGLISH=memErrNoRAMOnCard
+
+ID=kStr_PalmOSErrorBase+memErrorClass+11
+ENGLISH=memErrNoStore
+
+ID=kStr_PalmOSErrorBase+memErrorClass+12
+ENGLISH=memErrROMOnlyCard
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+1
+ENGLISH=mdmErrNoTone -- no dial tone
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+2
+ENGLISH=mdmErrNoDCD -- no carrier / timeout
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+3
+ENGLISH=mdmErrBusy -- busy signal heard
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+4
+ENGLISH=mdmErrUserCan -- cancelled by user
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+5
+ENGLISH=mdmErrCmdError -- command error
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+6
+ENGLISH=mdmErrNoModem -- no modem detected
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+7
+ENGLISH=mdmErrMemory -- not enough memory
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+8
+ENGLISH=mdmErrPrefs -- modem preferences have not been
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+9
+ENGLISH=mdmErrDial -- dial command error - most likely the dial
+
+ID=kStr_PalmOSErrorBase+mdmErrorClass+10
+ENGLISH=mdmErrNoPhoneNum -- No phone number and not "Direct Connect"
+
+ID=kStr_PalmOSErrorBase+netErrorClass+1
+ENGLISH=netErrAlreadyOpen
+
+ID=kStr_PalmOSErrorBase+netErrorClass+2
+ENGLISH=netErrNotOpen
+
+ID=kStr_PalmOSErrorBase+netErrorClass+3
+ENGLISH=netErrStillOpen
+
+ID=kStr_PalmOSErrorBase+netErrorClass+4
+ENGLISH=netErrParamErr
+
+ID=kStr_PalmOSErrorBase+netErrorClass+5
+ENGLISH=netErrNoMoreSockets
+
+ID=kStr_PalmOSErrorBase+netErrorClass+6
+ENGLISH=netErrOutOfResources
+
+ID=kStr_PalmOSErrorBase+netErrorClass+7
+ENGLISH=netErrOutOfMemory -- Might be because free heap space is <32K probably because handheld's RAM <2MB
+
+ID=kStr_PalmOSErrorBase+netErrorClass+8
+ENGLISH=netErrSocketNotOpen
+
+ID=kStr_PalmOSErrorBase+netErrorClass+9
+ENGLISH=netErrSocketBusy -- EINPROGRESS
+
+ID=kStr_PalmOSErrorBase+netErrorClass+10
+ENGLISH=netErrMessageTooBig
+
+ID=kStr_PalmOSErrorBase+netErrorClass+11
+ENGLISH=netErrSocketNotConnected
+
+ID=kStr_PalmOSErrorBase+netErrorClass+12
+ENGLISH=netErrNoInterfaces -- ENETUNREACH
+
+ID=kStr_PalmOSErrorBase+netErrorClass+13
+ENGLISH=netErrBufTooSmall
+
+ID=kStr_PalmOSErrorBase+netErrorClass+14
+ENGLISH=netErrUnimplemented
+
+ID=kStr_PalmOSErrorBase+netErrorClass+15
+ENGLISH=netErrPortInUse -- EADDRINUSE
+
+ID=kStr_PalmOSErrorBase+netErrorClass+16
+ENGLISH=netErrQuietTimeNotElapsed -- EADDRINUSE
+
+ID=kStr_PalmOSErrorBase+netErrorClass+17
+ENGLISH=netErrInternal
+
+ID=kStr_PalmOSErrorBase+netErrorClass+18
+ENGLISH=netErrTimeout -- ETIMEDOUT
+
+ID=kStr_PalmOSErrorBase+netErrorClass+19
+ENGLISH=netErrSocketAlreadyConnected -- EISCONN
+
+ID=kStr_PalmOSErrorBase+netErrorClass+20
+ENGLISH=netErrSocketClosedByRemote
+
+ID=kStr_PalmOSErrorBase+netErrorClass+21
+ENGLISH=netErrOutOfCmdBlocks
+
+ID=kStr_PalmOSErrorBase+netErrorClass+22
+ENGLISH=netErrWrongSocketType
+
+ID=kStr_PalmOSErrorBase+netErrorClass+23
+ENGLISH=netErrSocketNotListening
+
+ID=kStr_PalmOSErrorBase+netErrorClass+24
+ENGLISH=netErrUnknownSetting
+
+ID=kStr_PalmOSErrorBase+netErrorClass+25
+ENGLISH=netErrInvalidSettingSize
+
+ID=kStr_PalmOSErrorBase+netErrorClass+26
+ENGLISH=netErrPrefNotFound
+
+ID=kStr_PalmOSErrorBase+netErrorClass+27
+ENGLISH=netErrInvalidInterface
+
+ID=kStr_PalmOSErrorBase+netErrorClass+28
+ENGLISH=netErrInterfaceNotFound
+
+ID=kStr_PalmOSErrorBase+netErrorClass+29
+ENGLISH=netErrTooManyInterfaces
+
+ID=kStr_PalmOSErrorBase+netErrorClass+30
+ENGLISH=netErrBufWrongSize
+
+ID=kStr_PalmOSErrorBase+netErrorClass+31
+ENGLISH=netErrUserCancel
+
+ID=kStr_PalmOSErrorBase+netErrorClass+32
+ENGLISH=netErrBadScript
+
+ID=kStr_PalmOSErrorBase+netErrorClass+33
+ENGLISH=netErrNoSocket
+
+ID=kStr_PalmOSErrorBase+netErrorClass+34
+ENGLISH=netErrSocketRcvBufFull
+
+ID=kStr_PalmOSErrorBase+netErrorClass+35
+ENGLISH=netErrNoPendingConnect
+
+ID=kStr_PalmOSErrorBase+netErrorClass+36
+ENGLISH=netErrUnexpectedCmd
+
+ID=kStr_PalmOSErrorBase+netErrorClass+37
+ENGLISH=netErrNoTCB
+
+ID=kStr_PalmOSErrorBase+netErrorClass+38
+ENGLISH=netErrNilRemoteWindowSize
+
+ID=kStr_PalmOSErrorBase+netErrorClass+39
+ENGLISH=netErrNoTimerProc
+
+ID=kStr_PalmOSErrorBase+netErrorClass+40
+ENGLISH=netErrSocketInputShutdown -- EOF to sockets API
+
+ID=kStr_PalmOSErrorBase+netErrorClass+41
+ENGLISH=netErrCmdBlockNotCheckedOut
+
+ID=kStr_PalmOSErrorBase+netErrorClass+42
+ENGLISH=netErrCmdNotDone
+
+ID=kStr_PalmOSErrorBase+netErrorClass+43
+ENGLISH=netErrUnknownProtocol
+
+ID=kStr_PalmOSErrorBase+netErrorClass+44
+ENGLISH=netErrUnknownService
+
+ID=kStr_PalmOSErrorBase+netErrorClass+45
+ENGLISH=netErrUnreachableDest
+
+ID=kStr_PalmOSErrorBase+netErrorClass+46
+ENGLISH=netErrReadOnlySetting
+
+ID=kStr_PalmOSErrorBase+netErrorClass+47
+ENGLISH=netErrWouldBlock -- EWOULDBLOCK
+
+ID=kStr_PalmOSErrorBase+netErrorClass+48
+ENGLISH=netErrAlreadyInProgress -- EALREADY
+
+ID=kStr_PalmOSErrorBase+netErrorClass+49
+ENGLISH=netErrPPPTimeout
+
+ID=kStr_PalmOSErrorBase+netErrorClass+50
+ENGLISH=netErrPPPBroughtDown
+
+ID=kStr_PalmOSErrorBase+netErrorClass+51
+ENGLISH=netErrAuthFailure
+
+ID=kStr_PalmOSErrorBase+netErrorClass+52
+ENGLISH=netErrPPPAddressRefused
+
+ID=kStr_PalmOSErrorBase+netErrorClass+53
+ENGLISH=netErrDNSNameTooLong
+
+ID=kStr_PalmOSErrorBase+netErrorClass+54
+ENGLISH=netErrDNSBadName
+
+ID=kStr_PalmOSErrorBase+netErrorClass+55
+ENGLISH=netErrDNSBadArgs
+
+ID=kStr_PalmOSErrorBase+netErrorClass+56
+ENGLISH=netErrDNSLabelTooLong
+
+ID=kStr_PalmOSErrorBase+netErrorClass+57
+ENGLISH=netErrDNSAllocationFailure
+
+ID=kStr_PalmOSErrorBase+netErrorClass+58
+ENGLISH=netErrDNSTimeout
+
+ID=kStr_PalmOSErrorBase+netErrorClass+59
+ENGLISH=netErrDNSUnreachable
+
+ID=kStr_PalmOSErrorBase+netErrorClass+60
+ENGLISH=netErrDNSFormat
+
+ID=kStr_PalmOSErrorBase+netErrorClass+61
+ENGLISH=netErrDNSServerFailure
+
+ID=kStr_PalmOSErrorBase+netErrorClass+62
+ENGLISH=netErrDNSNonexistantName
+
+ID=kStr_PalmOSErrorBase+netErrorClass+63
+ENGLISH=netErrDNSNIY
+
+ID=kStr_PalmOSErrorBase+netErrorClass+64
+ENGLISH=netErrDNSRefused
+
+ID=kStr_PalmOSErrorBase+netErrorClass+65
+ENGLISH=netErrDNSImpossible
+
+ID=kStr_PalmOSErrorBase+netErrorClass+66
+ENGLISH=netErrDNSNoRRS
+
+ID=kStr_PalmOSErrorBase+netErrorClass+67
+ENGLISH=netErrDNSAborted
+
+ID=kStr_PalmOSErrorBase+netErrorClass+68
+ENGLISH=netErrDNSBadProtocol
+
+ID=kStr_PalmOSErrorBase+netErrorClass+69
+ENGLISH=netErrDNSTruncated
+
+ID=kStr_PalmOSErrorBase+netErrorClass+70
+ENGLISH=netErrDNSNoRecursion
+
+ID=kStr_PalmOSErrorBase+netErrorClass+71
+ENGLISH=netErrDNSIrrelevant
+
+ID=kStr_PalmOSErrorBase+netErrorClass+72
+ENGLISH=netErrDNSNotInLocalCache
+
+ID=kStr_PalmOSErrorBase+netErrorClass+73
+ENGLISH=netErrDNSNoPort
+
+ID=kStr_PalmOSErrorBase+netErrorClass+74
+ENGLISH=netErrIPCantFragment
+
+ID=kStr_PalmOSErrorBase+netErrorClass+75
+ENGLISH=netErrIPNoRoute
+
+ID=kStr_PalmOSErrorBase+netErrorClass+76
+ENGLISH=netErrIPNoSrc
+
+ID=kStr_PalmOSErrorBase+netErrorClass+77
+ENGLISH=netErrIPNoDst
+
+ID=kStr_PalmOSErrorBase+netErrorClass+78
+ENGLISH=netErrIPktOverflow
+
+ID=kStr_PalmOSErrorBase+netErrorClass+79
+ENGLISH=netErrTooManyTCPConnections
+
+ID=kStr_PalmOSErrorBase+netErrorClass+80
+ENGLISH=netErrNoDNSServers
+
+ID=kStr_PalmOSErrorBase+netErrorClass+81
+ENGLISH=netErrInterfaceDown
+
+ID=kStr_PalmOSErrorBase+netErrorClass+82
+ENGLISH=netErrNoChannel -- The datalink layer cannot acquire a channel
+
+ID=kStr_PalmOSErrorBase+netErrorClass+83
+ENGLISH=netErrDieState -- Mobitex network has issued a DIE command
+
+ID=kStr_PalmOSErrorBase+netErrorClass+84
+ENGLISH=netErrReturnedInMail -- The addressed of the transmitted packet was not available, and the message was placed in the network's mailbox
+
+ID=kStr_PalmOSErrorBase+netErrorClass+85
+ENGLISH=netErrReturnedNoTransfer -- This message cannot be transferred or put in the network mailbox
+
+ID=kStr_PalmOSErrorBase+netErrorClass+86
+ENGLISH=netErrReturnedIllegal -- The message could not be switched to the network
+
+ID=kStr_PalmOSErrorBase+netErrorClass+87
+ENGLISH=netErrReturnedCongest -- Line, radio channels, or network nodes are congested
+
+ID=kStr_PalmOSErrorBase+netErrorClass+88
+ENGLISH=netErrReturnedError -- Technical error in the network
+
+ID=kStr_PalmOSErrorBase+netErrorClass+89
+ENGLISH=netErrReturnedBusy -- The B-party is busy
+
+ID=kStr_PalmOSErrorBase+netErrorClass+90
+ENGLISH=netErrGMANState -- The modem has not registered with the network
+
+ID=kStr_PalmOSErrorBase+netErrorClass+91
+ENGLISH=netErrQuitOnTxFail -- Couldn't get packet through, shutdown
+
+ID=kStr_PalmOSErrorBase+netErrorClass+92
+ENGLISH=netErrFlexListFull -- raw IF error message: see Mobitex spec
+
+ID=kStr_PalmOSErrorBase+netErrorClass+93
+ENGLISH=netErrSenderMAN -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+94
+ENGLISH=netErrIllegalType -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+95
+ENGLISH=netErrIllegalState -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+96
+ENGLISH=netErrIllegalFlags -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+97
+ENGLISH=netErrIllegalSendlist -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+98
+ENGLISH=netErrIllegalMPAKLength -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+99
+ENGLISH=netErrIllegalAddressee -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+100
+ENGLISH=netErrIllegalPacketClass -- ditto
+
+ID=kStr_PalmOSErrorBase+netErrorClass+101
+ENGLISH=netErrBufferLength -- any
+
+ID=kStr_PalmOSErrorBase+netErrorClass+102
+ENGLISH=netErrNiCdLowBattery -- any
+
+ID=kStr_PalmOSErrorBase+netErrorClass+103
+ENGLISH=netErrRFinterfaceFatal -- any
+
+ID=kStr_PalmOSErrorBase+netErrorClass+104
+ENGLISH=netErrIllegalLogout -- raw IF error message
+
+ID=kStr_PalmOSErrorBase+netErrorClass+105
+ENGLISH=netErrAAARadioLoad -- 7/20/98 JB. If there is insufficient AAA
+
+ID=kStr_PalmOSErrorBase+netErrorClass+106
+ENGLISH=netErrAntennaDown
+
+ID=kStr_PalmOSErrorBase+netErrorClass+107
+ENGLISH=netErrNiCdCharging -- just for charging
+
+ID=kStr_PalmOSErrorBase+netErrorClass+108
+ENGLISH=netErrAntennaWentDown
+
+ID=kStr_PalmOSErrorBase+netErrorClass+109
+ENGLISH=netErrNotActivated -- The unit has not been FULLY activated. George and Morty completed
+
+ID=kStr_PalmOSErrorBase+netErrorClass+110
+ENGLISH=netErrRadioTemp -- Radio's temp is too high for FCC compliant TX
+
+ID=kStr_PalmOSErrorBase+netErrorClass+111
+ENGLISH=netErrNiCdChargeError -- Charging stopped due to NiCd charging characteristic
+
+ID=kStr_PalmOSErrorBase+netErrorClass+112
+ENGLISH=netErrNiCdSag -- the computed sag or actual sag indicates a NiCd with diminished capacity
+
+ID=kStr_PalmOSErrorBase+netErrorClass+113
+ENGLISH=netErrNiCdChargeSuspend -- Charging has been suspended due to low AAA batteries
+
+ID=kStr_PalmOSErrorBase+netErrorClass+115
+ENGLISH=netErrConfigNotFound
+
+ID=kStr_PalmOSErrorBase+netErrorClass+116
+ENGLISH=netErrConfigCantDelete
+
+ID=kStr_PalmOSErrorBase+netErrorClass+117
+ENGLISH=netErrConfigTooMany
+
+ID=kStr_PalmOSErrorBase+netErrorClass+118
+ENGLISH=netErrConfigBadName
+
+ID=kStr_PalmOSErrorBase+netErrorClass+119
+ENGLISH=netErrConfigNotAlias
+
+ID=kStr_PalmOSErrorBase+netErrorClass+120
+ENGLISH=netErrConfigCantPointToAlias
+
+ID=kStr_PalmOSErrorBase+netErrorClass+121
+ENGLISH=netErrConfigEmpty
+
+ID=kStr_PalmOSErrorBase+netErrorClass+122
+ENGLISH=netErrAlreadyOpenWithOtherConfig
+
+ID=kStr_PalmOSErrorBase+netErrorClass+123
+ENGLISH=netErrConfigAliasErr
+
+ID=kStr_PalmOSErrorBase+netErrorClass+124
+ENGLISH=netErrNoMultiPktAddr
+
+ID=kStr_PalmOSErrorBase+netErrorClass+125
+ENGLISH=netErrOutOfPackets
+
+ID=kStr_PalmOSErrorBase+netErrorClass+126
+ENGLISH=netErrMultiPktAddrReset
+
+ID=kStr_PalmOSErrorBase+netErrorClass+127
+ENGLISH=netErrStaleMultiPktAddr
+
+ID=kStr_PalmOSErrorBase+netErrorClass+128
+ENGLISH=netErrScptPluginMissing
+
+ID=kStr_PalmOSErrorBase+netErrorClass+129
+ENGLISH=netErrScptPluginLaunchFail
+
+ID=kStr_PalmOSErrorBase+netErrorClass+130
+ENGLISH=netErrScptPluginCmdFail
+
+ID=kStr_PalmOSErrorBase+netErrorClass+131
+ENGLISH=netErrScptPluginInvalidCmd
+
+ID=kStr_PalmOSErrorBase+netErrorClass+132
+ENGLISH=netErrTelMissingComponent
+
+ID=kStr_PalmOSErrorBase+netErrorClass+133
+ENGLISH=netErrTelErrorNotHandled
+
+ID=kStr_PalmOSErrorBase+omErrorClass+1
+ENGLISH=omErrBaseRequiresOverlay
+
+ID=kStr_PalmOSErrorBase+omErrorClass+2
+ENGLISH=omErrUnknownLocale
+
+ID=kStr_PalmOSErrorBase+omErrorClass+3
+ENGLISH=omErrBadOverlayDBName
+
+ID=kStr_PalmOSErrorBase+omErrorClass+4
+ENGLISH=omErrInvalidLocaleIndex
+
+ID=kStr_PalmOSErrorBase+omErrorClass+5
+ENGLISH=omErrInvalidLocale
+
+ID=kStr_PalmOSErrorBase+omErrorClass+6
+ENGLISH=omErrInvalidSystemOverlay
+
+ID=kStr_PalmOSErrorBase+omErrorClass+7
+ENGLISH=omErrNoNextSystemLocale
+
+ID=kStr_PalmOSErrorBase+penErrorClass+1
+ENGLISH=penErrBadParam
+
+ID=kStr_PalmOSErrorBase+penErrorClass+2
+ENGLISH=penErrIgnorePoint
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+1
+ENGLISH=slkErrChecksum
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+2
+ENGLISH=slkErrFormat
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+3
+ENGLISH=slkErrBuffer
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+4
+ENGLISH=slkErrTimeOut
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+5
+ENGLISH=slkErrHandle
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+6
+ENGLISH=slkErrBodyLimit
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+7
+ENGLISH=slkErrTransId
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+8
+ENGLISH=slkErrResponse
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+9
+ENGLISH=slkErrNoDefaultProc
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+10
+ENGLISH=slkErrWrongPacketType
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+11
+ENGLISH=slkErrBadParam
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+12
+ENGLISH=slkErrAlreadyOpen
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+13
+ENGLISH=slkErrOutOfSockets
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+14
+ENGLISH=slkErrSocketNotOpen
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+15
+ENGLISH=slkErrWrongDestSocket
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+16
+ENGLISH=slkErrWrongPktType
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+17
+ENGLISH=slkErrBusy -- called while sending a packet
+
+ID=kStr_PalmOSErrorBase+slkErrorClass+18
+ENGLISH=slkErrNotOpen
+
+ID=kStr_PalmOSErrorBase+serErrorClass+1
+ENGLISH=serErrBadParam
+
+ID=kStr_PalmOSErrorBase+serErrorClass+2
+ENGLISH=serErrBadPort
+
+ID=kStr_PalmOSErrorBase+serErrorClass+3
+ENGLISH=serErrNoMem
+
+ID=kStr_PalmOSErrorBase+serErrorClass+4
+ENGLISH=serErrBadConnID
+
+ID=kStr_PalmOSErrorBase+serErrorClass+5
+ENGLISH=serErrTimeOut
+
+ID=kStr_PalmOSErrorBase+serErrorClass+6
+ENGLISH=serErrLineErr
+
+ID=kStr_PalmOSErrorBase+serErrorClass+7
+ENGLISH=serErrAlreadyOpen
+
+ID=kStr_PalmOSErrorBase+serErrorClass+8
+ENGLISH=serErrStillOpen
+
+ID=kStr_PalmOSErrorBase+serErrorClass+9
+ENGLISH=serErrNotOpen
+
+ID=kStr_PalmOSErrorBase+serErrorClass+10
+ENGLISH=serErrNotSupported -- functionality not supported
+
+ID=kStr_PalmOSErrorBase+serErrorClass+11
+ENGLISH=serErrNoDevicesAvail -- No serial devices were loaded or are available
+
+ID=kStr_PalmOSErrorBase+serErrorClass+12
+ENGLISH=serErrConfigurationFailed
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+1
+ENGLISH=sndErrBadParam
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+2
+ENGLISH=sndErrBadChannel
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+3
+ENGLISH=sndErrMemory
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+4
+ENGLISH=sndErrOpen
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+5
+ENGLISH=sndErrQFull
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+6
+ENGLISH=sndErrQEmpty -- internal
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+7
+ENGLISH=sndErrFormat -- unsupported data format
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+8
+ENGLISH=sndErrBadStream -- invalid data stream
+
+ID=kStr_PalmOSErrorBase+sndErrorClass+9
+ENGLISH=sndErrInterrupted -- play was interrupted
+
+ID=kStr_PalmOSErrorBase+evtErrorClass+1
+ENGLISH=evtErrParamErr
+
+ID=kStr_PalmOSErrorBase+evtErrorClass+2
+ENGLISH=evtErrQueueFull
+
+ID=kStr_PalmOSErrorBase+evtErrorClass+3
+ENGLISH=evtErrQueueEmpty
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+1
+ENGLISH=sysErrTimeout
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+2
+ENGLISH=sysErrParamErr
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+3
+ENGLISH=sysErrNoFreeResource
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+4
+ENGLISH=sysErrNoFreeRAM
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+5
+ENGLISH=sysErrNotAllowed
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+6
+ENGLISH=sysErrSemInUse
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+7
+ENGLISH=sysErrInvalidID
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+8
+ENGLISH=sysErrOutOfOwnerIDs
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+9
+ENGLISH=sysErrNoFreeLibSlots
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+10
+ENGLISH=sysErrLibNotFound
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+11
+ENGLISH=sysErrDelayWakened -- SysTaskDelay wakened by SysTaskWake before delay completed
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+12
+ENGLISH=sysErrRomIncompatible
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+13
+ENGLISH=sysErrBufTooSmall
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+14
+ENGLISH=sysErrPrefNotFound
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+16
+ENGLISH=sysNotifyErrEntryNotFound -- could not find registration entry in the list
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+17
+ENGLISH=sysNotifyErrDuplicateEntry -- identical entry already exists
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+19
+ENGLISH=sysNotifyErrBroadcastBusy -- a broadcast is already in progress - try again later
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+20
+ENGLISH=sysNotifyErrBroadcastCancelled -- a handler cancelled the broadcast
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+21
+ENGLISH=sysErrMbId
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+22
+ENGLISH=sysErrMbNone
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+23
+ENGLISH=sysErrMbBusy
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+24
+ENGLISH=sysErrMbFull
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+25
+ENGLISH=sysErrMbDepth
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+26
+ENGLISH=sysErrMbEnv
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+27
+ENGLISH=sysNotifyErrQueueFull -- deferred queue is full
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+28
+ENGLISH=sysNotifyErrQueueEmpty -- deferred queue is empty
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+29
+ENGLISH=sysNotifyErrNoStackSpace -- not enough stack space for a broadcast
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+30
+ENGLISH=sysErrNotInitialized -- manager is not initialized
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+31
+ENGLISH=sysErrNotAsleep -- Task woken by SysTaskWake was not asleep, 1 wake pending
+
+ID=kStr_PalmOSErrorBase+sysErrorClass+32
+ENGLISH=sysErrNotAsleepN -- Task woken by SysTaskWake was not asleep, >1 wake pending
+
+ID=kStr_PalmOSErrorBase+pwrErrorClass+0
+ENGLISH=pwrErrNone
+
+ID=kStr_PalmOSErrorBase+pwrErrorClass+1
+ENGLISH=pwrErrBacklight
+
+ID=kStr_PalmOSErrorBase+pwrErrorClass+2
+ENGLISH=pwrErrRadio
+
+ID=kStr_PalmOSErrorBase+pwrErrorClass+3
+ENGLISH=pwrErrBeam
+
+ID=kStr_PalmOSErrorBase+pwrErrorClass+4
+ENGLISH=pwrErrGeneric
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+1
+ENGLISH=txtErrUknownTranslitOp
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+2
+ENGLISH=txtErrTranslitOverrun
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+3
+ENGLISH=txtErrTranslitOverflow
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+4
+ENGLISH=txtErrConvertOverflow
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+5
+ENGLISH=txtErrConvertUnderflow
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+6
+ENGLISH=txtErrUnknownEncoding
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+7
+ENGLISH=txtErrNoCharMapping
+
+ID=kStr_PalmOSErrorBase+txtErrorClass+8
+ENGLISH=txtErrTranslitUnderflow
+
+ID=kStr_PalmOSErrorBase+timErrorClass+1
+ENGLISH=timErrMemory
+
+ID=kStr_PalmOSErrorBase+winErrorClass+1
+ENGLISH=winErrPalette
+
+ID=kStr_PalmOSErrorBase+attnErrorClass+1
+ENGLISH=attnErrMemory -- ran out of memory
+
+ID=kStr_PalmOSErrorBase+menuErrorClass+1
+ENGLISH=menuErrNoMenu
+
+ID=kStr_PalmOSErrorBase+menuErrorClass+2
+ENGLISH=menuErrNotFound
+
+ID=kStr_PalmOSErrorBase+menuErrorClass+3
+ENGLISH=menuErrSameId
+
+ID=kStr_PalmOSErrorBase+menuErrorClass+4
+ENGLISH=menuErrTooManyItems
+
+ID=kStr_PalmOSErrorBase+menuErrorClass+5
+ENGLISH=menuErrOutOfMemory
+
+ID=kStr_PalmOSErrorBase+expErrorClass+1
+ENGLISH=expErrUnsupportedOperation -- unsupported or undefined opcode and/or creator
+
+ID=kStr_PalmOSErrorBase+expErrorClass+2
+ENGLISH=expErrNotEnoughPower -- the required power is not available
+
+ID=kStr_PalmOSErrorBase+expErrorClass+3
+ENGLISH=expErrCardNotPresent -- no card is present
+
+ID=kStr_PalmOSErrorBase+expErrorClass+4
+ENGLISH=expErrInvalidSlotRefNum -- slot reference number is bad
+
+ID=kStr_PalmOSErrorBase+expErrorClass+5
+ENGLISH=expErrSlotDeallocated -- slot reference number is within valid range, but has been deallocated
+
+ID=kStr_PalmOSErrorBase+expErrorClass+6
+ENGLISH=expErrCardNoSectorReadWrite -- the card does not support the
+
+ID=kStr_PalmOSErrorBase+expErrorClass+7
+ENGLISH=expErrCardReadOnly -- the card does support R/W API
+
+ID=kStr_PalmOSErrorBase+expErrorClass+8
+ENGLISH=expErrCardBadSector -- the card does support R/W API
+
+ID=kStr_PalmOSErrorBase+expErrorClass+9
+ENGLISH=expErrCardProtectedSector -- The card does support R/W API
+
+ID=kStr_PalmOSErrorBase+expErrorClass+10
+ENGLISH=expErrNotOpen -- slot driver library has not been opened
+
+ID=kStr_PalmOSErrorBase+expErrorClass+11
+ENGLISH=expErrStillOpen -- slot driver library is still open - maybe it was opened > once
+
+ID=kStr_PalmOSErrorBase+expErrorClass+12
+ENGLISH=expErrUnimplemented -- Call is unimplemented
+
+ID=kStr_PalmOSErrorBase+expErrorClass+13
+ENGLISH=expErrEnumerationEmpty -- No values remaining to enumerate
+
+ID=kStr_PalmOSErrorBase+expErrorClass+14
+ENGLISH=expErrIncompatibleAPIVer -- The API version of this slot driver is not supported by this version of ExpansionMgr
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+1
+ENGLISH=vfsErrBufferOverflow -- passed in buffer is too small
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+2
+ENGLISH=vfsErrFileGeneric -- Generic file error
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+3
+ENGLISH=vfsErrFileBadRef -- the fileref is invalid (has been closed, or was not obtained from VFSFileOpen())
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+4
+ENGLISH=vfsErrFileStillOpen -- returned from FSFileDelete if the file is still open
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+5
+ENGLISH=vfsErrFilePermissionDenied -- The file is read only
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+6
+ENGLISH=vfsErrFileAlreadyExists -- a file of this name exists already in this location
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+7
+ENGLISH=vfsErrFileEOF -- file pointer is at end of file
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+8
+ENGLISH=vfsErrFileNotFound -- file was not found at the path specified
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+9
+ENGLISH=vfsErrVolumeBadRef -- the volume refnum is invalid
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+10
+ENGLISH=vfsErrVolumeStillMounted -- returned from FSVolumeFormat if the volume is still mounted
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+11
+ENGLISH=vfsErrNoFileSystem -- no installed filesystem supports this operation
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+12
+ENGLISH=vfsErrBadData -- operation could not be completed because of invalid data (i.e., import DB from .PRC file)
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+13
+ENGLISH=vfsErrDirNotEmpty -- can't delete a non-empty directory
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+14
+ENGLISH=vfsErrBadName -- invalid filename, or path, or volume label or something..
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+15
+ENGLISH=vfsErrVolumeFull -- not enough space left on volume
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+16
+ENGLISH=vfsErrUnimplemented -- this call is not implemented
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+17
+ENGLISH=vfsErrNotADirectory -- This operation requires a directory
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+18
+ENGLISH=vfsErrIsADirectory -- This operation requires a regular file, not a directory
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+19
+ENGLISH=vfsErrDirectoryNotFound -- Returned from VFSFileCreate when the path leading up to the new file does not exist
+
+ID=kStr_PalmOSErrorBase+vfsErrorClass+20
+ENGLISH=vfsErrNameShortened -- A volume name or filename was automatically shortened to conform to filesystem spec
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+1
+ENGLISH=inetErrTooManyClients -- Too many clients already
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+2
+ENGLISH=inetErrHandleInvalid -- Invalid inetH or sockH
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+3
+ENGLISH=inetErrParamsInvalid --
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+4
+ENGLISH=inetErrURLVersionInvalid --
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+5
+ENGLISH=inetErrURLBufTooSmall --
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+6
+ENGLISH=inetErrURLInvalid --
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+7
+ENGLISH=inetErrTooManySockets --
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+8
+ENGLISH=inetErrNoRequestCreated
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+9
+ENGLISH=inetErrNotConnected
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+10
+ENGLISH=inetErrInvalidRequest
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+11
+ENGLISH=inetErrNeedTime
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+12
+ENGLISH=inetErrHostnameInvalid
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+13
+ENGLISH=inetErrInvalidPort
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+14
+ENGLISH=inetErrInvalidHostAddr
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+15
+ENGLISH=inetErrNilBuffer
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+16
+ENGLISH=inetErrConnectTimeout
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+17
+ENGLISH=inetErrResolveTimeout
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+18
+ENGLISH=inetErrSendReqTimeout
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+19
+ENGLISH=inetErrReadTimeout
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+20
+ENGLISH=inetErrBufTooSmall
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+21
+ENGLISH=inetErrSchemeNotSupported
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+22
+ENGLISH=inetErrInvalidResponse
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+25
+ENGLISH=inetErrSettingTooLarge
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+26
+ENGLISH=inetErrSettingSizeInvalid
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+27
+ENGLISH=inetErrRequestTooLong
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+28
+ENGLISH=inetErrSettingNotImplemented
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+29
+ENGLISH=inetErrConfigNotFound
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+30
+ENGLISH=inetErrConfigCantDelete
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+31
+ENGLISH=inetErrConfigTooMany
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+32
+ENGLISH=inetErrConfigBadName
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+33
+ENGLISH=inetErrConfigNotAlias
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+34
+ENGLISH=inetErrConfigCantPointToAlias
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+35
+ENGLISH=inetErrConfigEmpty
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+37
+ENGLISH=inetErrConfigAliasErr
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+38
+ENGLISH=inetErrNoWirelessInterface
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+39
+ENGLISH=inetErrEncryptionNotAvail
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+40
+ENGLISH=inetErrNeedRetryEncSeqNum
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+41
+ENGLISH=inetErrNeedRetryEncPublicKey
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+42
+ENGLISH=inetErrResponseTooShort
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+43
+ENGLISH=inetErrMobitexIllegalOKHost
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+44
+ENGLISH=inetErrMobitexIllegalBadHost
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+45
+ENGLISH=inetErrHTTPBadRequest
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+46
+ENGLISH=inetErrHTTPUnauthorized
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+47
+ENGLISH=inetErrHTTPForbidden
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+48
+ENGLISH=inetErrHTTPNotFound
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+49
+ENGLISH=inetErrHTTPMethodNotAllowed
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+50
+ENGLISH=inetErrHTTPNotAcceptable
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+51
+ENGLISH=inetErrHTTPProxyAuthRequired
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+52
+ENGLISH=inetErrHTTPRequestTimeout
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+53
+ENGLISH=inetErrHTTPConflict
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+54
+ENGLISH=inetErrHTTPGone
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+55
+ENGLISH=inetErrHTTPLengthRequired
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+56
+ENGLISH=inetErrHTTPPreconditionFailed
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+57
+ENGLISH=inetErrHTTPRequestTooLarge
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+58
+ENGLISH=inetErrHTTPRequestURITooLong
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+59
+ENGLISH=inetErrHTTPUnsupportedType
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+60
+ENGLISH=inetErrHTTPServerError
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+61
+ENGLISH=inetErrCTPServerError
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+62
+ENGLISH=inetErrTypeNotCached
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+63
+ENGLISH=inetErrCacheInvalid
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+64
+ENGLISH=inetErrURLDispatched
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+65
+ENGLISH=inetErrDatabaseNotFound
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+66
+ENGLISH=inetErrCTPMalformedRequest
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+67
+ENGLISH=inetErrCTPUnknownCommand
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+68
+ENGLISH=inetErrCTPTruncated
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+69
+ENGLISH=inetErrCTPUnknownError
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+70
+ENGLISH=inetErrCTPProxyError
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+71
+ENGLISH=inetErrCTPSocketErr
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+72
+ENGLISH=inetErrCTPInvalidURL
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+73
+ENGLISH=inetErrCTPReferringPageOutOfDate
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+74
+ENGLISH=inetErrCTPBadRequest
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+75
+ENGLISH=inetErrUNUSED
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+76
+ENGLISH=inetErrCTPMailServerDown
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+77
+ENGLISH=inetErrCTPHostNotFound
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+78
+ENGLISH=inetErrCTPContentInvalidTag
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+79
+ENGLISH=inetErrCTPContentInternal
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+80
+ENGLISH=inetErrCTPContentDataEnd
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+81
+ENGLISH=inetErrCTPContentResourceTooBig
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+82
+ENGLISH=inetErrCTPContentNoNoFrames
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+83
+ENGLISH=inetErrCTPContentUnsupportedContent
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+84
+ENGLISH=inetErrCTPContentUnsupportedEncoding
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+85
+ENGLISH=inetErrCTPContentBadForm
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+86
+ENGLISH=inetErrCTPContentBadFormMissingAction
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+87
+ENGLISH=inetErrCTPContentBadFormMissingMethod
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+88
+ENGLISH=inetErrCTPContentNoSourceData
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+89
+ENGLISH=inetErrCTPContentBadImage
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+90
+ENGLISH=inetErrCTPContentImageTooLarge
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+91
+ENGLISH=inetErrMobitexErrorHandled
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+92
+ENGLISH=inetErrProxyDownBadHost
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+93
+ENGLISH=inetErrHostConnectionLost
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+94
+ENGLISH=inetErrLinkNotFound
+
+ID=kStr_PalmOSErrorBase+inetErrorClass+95
+ENGLISH=inetErrCacheInvalidSort
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x00
+ENGLISH=lz77ErrNonFatalFirstErr
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x01
+ENGLISH=lz77ErrNonFatalInputBufferIncomplete
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x02
+ENGLISH=lz77ErrNonFatalOutputBufferFull
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x7F
+ENGLISH=lz77ErrNonFatalLastErr
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x80
+ENGLISH=lz77ErrFatalUnfinishedInputBuffer
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x81
+ENGLISH=lz77ErrFatalInputBufferIncomplete
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x82
+ENGLISH=lz77ErrFatalInputBufferInvalid
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x83
+ENGLISH=lz77ErrFatalMemAllocation
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x84
+ENGLISH=lz77ErrFatalHandleInvalid
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x85
+ENGLISH=lz77ErrFatalCantChangeToCompress
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x86
+ENGLISH=lz77ErrFatalUnknownVersion
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x87
+ENGLISH=lz77ErrFatalOutputBufferTooSmall
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0x88
+ENGLISH=lz77ErrFatalInvalidArgument
+
+ID=kStr_PalmOSErrorBase+lz77ErrorClass+0xFF
+ENGLISH=lz77ErrFatalLastErr
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+1
+ENGLISH=pdiErrRead
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+2
+ENGLISH=pdiErrWrite
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+3
+ENGLISH=pdiErrNoPropertyName
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+4
+ENGLISH=pdiErrNoPropertyValue
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+5
+ENGLISH=pdiErrMoreChars
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+6
+ENGLISH=pdiErrNoMoreFields
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+7
+ENGLISH=pdiErrOpenFailed
+
+ID=kStr_PalmOSErrorBase+pdiErrorClass+8
+ENGLISH=pdiErrCloseFailed
+
+ID=kStr_PalmOSErrorBase+smsErrorClass+0x01
+ENGLISH=kSmsErrMaxSizeExceeded -- Message exceeds maximum size supported by network
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x01
+ENGLISH=telErrMsgAllocation -- couldn't allocate message
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x02
+ENGLISH=telErrUnknown -- unknown Tel internal error
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x03
+ENGLISH=telErrMemAllocation -- memory allocation error
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x04
+ENGLISH=telErrResultTimeOut -- time-out was reached
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x05
+ENGLISH=telErrResultUserCancel -- user cancelled action
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x06
+ENGLISH=telErrResultBusyResource -- resource is busy
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x07
+ENGLISH=telErrInvalidAppId -- don't know that application
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x08
+ENGLISH=telErrTooManyApps -- applications table is full
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x09
+ENGLISH=telErrSecurity -- access to ME has not been granted
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0A
+ENGLISH=telErrBufferSize -- buffer used to retrieve data is too small
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0B
+ENGLISH=telErrFeatureNotSupported -- the feature is not supported by phone/network
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0C
+ENGLISH=telErrPhoneComm -- the communication link with the phone is down
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0D
+ENGLISH=telErrPhoneReply -- the phone reply syntax is incorrect, check the phone driver!
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0E
+ENGLISH=telErrCommandFailed -- the phone couldn't achieve the associated command, check the phone driver!
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x0F
+ENGLISH=telErrSpcLineIsBusy -- spc call failure events, error field values
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x10
+ENGLISH=telErrPhoneCodeRequired -- phone code required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x11
+ENGLISH=telErrNoSIMInserted -- no SIM inserted
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x12
+ENGLISH=telErrPINRequired -- PIN is required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x13
+ENGLISH=telErrPUKRequired -- PUK is required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x14
+ENGLISH=telErrSIMFailure -- the SIM is not working properly
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x15
+ENGLISH=telErrSIMBusy -- the SIM couldn't reply
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x16
+ENGLISH=telErrSIMWrong -- the SIM is not accepted by the phone
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x17
+ENGLISH=telErrPassword -- incorrect password
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x18
+ENGLISH=telErrPIN2Required -- PIN2 is required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x19
+ENGLISH=telErrPUK2Required -- PUK2 is required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1A
+ENGLISH=telErrPhoneMemAllocation -- phone memory is full
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1B
+ENGLISH=telErrInvalidIndex -- invalid index when accessing a storage
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1C
+ENGLISH=telErrEntryNotFound -- entry not found
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1D
+ENGLISH=telErrPhoneMemFailure -- the phone encountered a memory error
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1E
+ENGLISH=telErrInvalidString -- bad character in text string
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x1F
+ENGLISH=telErrInvalidDial -- bad character in dial string
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x20
+ENGLISH=telErrNoNetwork -- no network available
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x21
+ENGLISH=telErrNetworkTimeOut -- the network didn't reply within 'normal' time delay
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x22
+ENGLISH=telErrInvalidParameter -- bad parameter passed to an API
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x23
+ENGLISH=telErrValidityPeriod -- the specified short message validity period is invalid
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x24
+ENGLISH=telErrCodingScheme -- the specified short message coding scheme is invalid
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x25
+ENGLISH=telErrPhoneNumber -- the specified short message smsc or destination phone number is invalid
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x26
+ENGLISH=telErrValueStale -- information couldn't be retrieved, a copy of last retrieved value was returned
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x27
+ENGLISH=telErrTTaskNotRunning -- the Telephony Task is not running
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x28
+ENGLISH=telErrPhoneToSIMPINRequired -- Phone 2 SIM PIN is required
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x29
+ENGLISH=telErrSpecificDrvNotFound -- the specified driver was not found
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2A
+ENGLISH=telErrGenericDrvNotFound -- the generic driver was not found
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2B
+ENGLISH=telErrNoSpecificDrv -- no specific driver was specified
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2C
+ENGLISH=telErrSpcLineIsReleased -- the call has been released
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2D
+ENGLISH=telErrSpcCallError -- the call has encountered an error
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2E
+ENGLISH=telErrNotInstalled -- the shared lib couldn't be installed
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x2F
+ENGLISH=telErrVersion -- the shared lib version doesn't match the application one
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x30
+ENGLISH=telErrSettings -- bad telephony settings: Phone Panel Prefs doesn't exist or Telephony Profile not (correctly) set
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x31
+ENGLISH=telErrUnavailableValue -- the asked value can't be retrieved at that time (i.e.: TelSpcGetCallerNumber and no active line)
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x32
+ENGLISH=telErrLimitedCompatibility -- the current driver is partially compatible with the connected phone
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x33
+ENGLISH=telErrProfileConflict -- the currently used profile conflicts with the requested profile
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x34
+ENGLISH=telErrLibStillInUse -- the shared lib is currently being used by another app, don't unload it!
+
+ID=kStr_PalmOSErrorBase+telErrorClass+0x35
+ENGLISH=telErrTTaskNotFound -- couldn't find the specified (by phone driver) telephony task
+
+
+END
+
+#!/usr/bin/perl
+use Cwd;
+use File::Basename;
+
+$file = $0;
+$dir = dirname($file);
+if ($^O =~ /MacOS/i) {
+ @ARGV = ($file, "");
+ do $dir . "::Tools:Strings2Resource.pl";
+} else {
+ @ARGV = ($file, "");
+ do $dir . "/../Tools/Strings2Resource.pl";
+}
diff --git a/SrcShared/Switches.h b/SrcShared/Switches.h
new file mode 100644
index 0000000..0dc0ca8
--- /dev/null
+++ b/SrcShared/Switches.h
@@ -0,0 +1,267 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _SWITCHES_H_
+#define _SWITCHES_H_
+
+// Use convention: for the preprocessor symbols in this file used to
+// turn features on and off, we follow the "if 0 or not 0" convention,
+// not the "if defined or not defined" convention. Thus, to turn
+// off a feature, set the symbol to 0. To turn on a feature, set the
+// symbol to 1.
+
+// BYTESWAP is used by Byteswapping.h/.cpp to determine if
+// byteswapping should actually occur. If not, it's a NOP.
+
+#if PLATFORM_WINDOWS || defined (HAVE_ENDIAN_H)
+
+ #include <endian.h>
+
+#elif PLATFORM_MAC || defined (HAVE_MACHINE_ENDIAN_H)
+
+ #include <machine/endian.h>
+
+#elif defined(HAVE_SYS_ISA_DEFS_H)
+
+ // This should handle both Solaris/Sparc and Solaris/Intel
+ #include <sys/isa_defs.h> // Defines either _BIG_ENDIAN or _LITTLE_ENDIAN
+
+#else
+
+ #error "You need to define __BYTE_ORDER for this platform."
+
+ // You can either define __BYTE_ORDER here, or you can provide
+ // a file called endian.h. If you take the latter course, rerun
+ // the configure script so that it can rebuild the makefile with
+ // HAVE_ENDIAN_H defined.
+
+ #define __LITTLE_ENDIAN 1234
+ #define __BIG_ENDIAN 4321
+ #define __PDP_ENDIAN 3412
+ #define __BYTE_ORDER <one of the above>
+
+#endif
+
+// Settle on a canonical name.
+
+#if defined (__BYTE_ORDER)
+
+ #define EM_LITTLE_ENDIAN __LITTLE_ENDIAN
+ #define EM_BIG_ENDIAN __BIG_ENDIAN
+ #define EM_PDP_ENDIAN __PDP_ENDIAN
+ #define EM_HOST_BYTE_ORDER __BYTE_ORDER
+
+#elif defined (BYTE_ORDER)
+
+ #define EM_LITTLE_ENDIAN LITTLE_ENDIAN
+ #define EM_BIG_ENDIAN BIG_ENDIAN
+ #define EM_PDP_ENDIAN PDP_ENDIAN
+ #define EM_HOST_BYTE_ORDER BYTE_ORDER
+
+#elif defined (_BIG_ENDIAN) || defined (_LITTLE_ENDIAN)
+
+ #define EM_LITTLE_ENDIAN 1234
+ #define EM_BIG_ENDIAN 4321
+ #define EM_PDP_ENDIAN 3412
+
+ #if defined (_BIG_ENDIAN)
+ #define EM_HOST_BYTE_ORDER EM_BIG_ENDIAN
+ #else
+ #define EM_HOST_BYTE_ORDER EM_LITTLE_ENDIAN
+ #endif
+
+#else
+
+ #error "Neither BYTE_ORDER nor __BYTE_ORDER defined for this platform."
+
+#endif
+
+
+#if (EM_HOST_BYTE_ORDER == EM_LITTLE_ENDIAN)
+ #define BYTESWAP 1
+ #define WORDSWAP_MEMORY 1 // Gives us 12% speedup.
+
+ // (adam) When WORDSWAP_MEMORY is defined, a sequence of bytes which is stored in memory on
+ // the Pilot in the sequence A, B, C, D is stored in Windows memory in the sequence B, A, D, C.
+ // This means that if p is the address of a byte in Pilot memory, (p ^ 1) is its address in
+ // Windows memory. This is fast because we can load a 16-bit word from Windows memory without doing any
+ // byte swapping and without having to mutate its address, and because we can load a 32-bit int
+ // from Windows memory just by flipping the 16 high-order bits with the 16 low-order bits.
+ //
+ // I thought about whether we could store the above bytes in Windows memory in the "longswapped" sequence
+ // D, C, B, A, which would allow us to load a 32-bit int without doing any byte swapping at all;
+ // we would then have to mutate a pointer p to a 16-bit-word into (p ^ 2). That would probably
+ // be even better than word swapping if all 32-bit accesses were 32-bit aligned. Since the 68000
+ // allows 32-bit accesses on arbitrary 16-bit boundaries, however, this scheme won't work. For
+ // example, suppose that the 68000 contains a sequence of bytes starting at address 0x1000:
+ // 1, 2, 3, 4, 5, 6, 7, 8
+ // And suppose that we store these bytes in the emulator as
+ // 4, 3, 2, 1, 8, 7, 6, 5
+ // Now if we load a 32-bit int starting at 0x1000 simply by reading it from Intel memory, we get
+ // the value 0x01020304, which is correct.
+ // But if we load a 32-bit int starting at 0x1002, we get the value 0x07080102, whereas we wanted
+ // the value 0x03040506.
+ // We could still make this work if we checked for 32-bit accesses which were not aligned on
+ // 32-bit boundaries, but I'm not sure whether it would be worth the performance gain.
+ // I don't know whether the "12% speedup" listed above is a speedup over storing bytes in Windows
+ // memory exactly as they are stored in 68000 memory, or over storing bytes in this "longswapped" way.
+ //
+ // (keith) The former. I never implemented "longswapped" for the reasons you gave.
+#else
+ #define BYTESWAP 0
+ #define WORDSWAP_MEMORY 0
+#endif
+
+
+// Define UNALIGNED_LONG_ACCESS to 1 if the host processor can
+// access 32-bit values on all 16-bit boundaries. Setting it to
+// 0 will cause the emulator to fetch 32-bit values with two
+// 16-bit operations.
+
+#if defined (sparc)
+ #define UNALIGNED_LONG_ACCESS 0
+#else
+ #define UNALIGNED_LONG_ACCESS 1
+#endif
+
+// Define a utility symbol that is guaranteed to be one in debug mode
+// and zero in non-debug mode (I don't know what _DEBUG is actually
+// defined to, so I'm not going to make any assumptions...)
+
+#if defined (_DEBUG)
+ #define ON_IN_DEBUG_MODE 1
+#else
+ #define ON_IN_DEBUG_MODE 0
+#endif
+
+
+// Define PROFILE_MEMORY to 1 to turn on profiling of memory access.
+// Profiling means collecting how often various sections of memory
+// are accessed and how they are accessed (read vs. write, byte vs.
+// word vs. long.)
+
+#define PROFILE_MEMORY 0
+
+
+// Define REGISTER_HISTORY to 1 to keep a history of the last 512
+// register states.
+
+#define REGISTER_HISTORY ON_IN_DEBUG_MODE
+
+
+// Define EXCEPTION_HISTORY to 1 to keep a history of the last 512
+// exceptions encountered.
+
+#define EXCEPTION_HISTORY ON_IN_DEBUG_MODE
+
+
+// The number of ticks between calls to WaitNextEvent (Mac only).
+
+#define EVENT_THRESHHOLD 6
+
+
+// Define NATIVE_DISPATCHING to 1 to have the emulator manage
+// the dispatching of SYSTRAP functions. Otherwise, the ROM
+// handles the dispatching. The advantage of having the emulator
+// do the dispatching is that it's faster.
+
+#define NATIVE_DISPATCHING 1
+
+
+// Define HAS_TRACER to 1 to include Tracer facility.
+
+#if PLATFORM_MAC || PLATFORM_WINDOWS
+ #define HAS_TRACER 1
+#else
+ #define HAS_TRACER 0
+#endif
+
+
+// Define HAS_OMNI_THREAD 1 to if this platform uses that facility
+// for multi-threading.
+
+#if PLATFORM_UNIX || PLATFORM_WINDOWS
+ #define HAS_OMNI_THREAD 1
+#else
+ #define HAS_OMNI_THREAD 0
+#endif
+
+
+// Define sub-flags for specific internal features.
+
+
+
+// The emulator can optionally check all access to memory to flag questionable
+// or illegal accesses. There are two ways this checking can be controlled.
+//
+// At the first level, there are runtime variables that turn on and off
+// this checking. The variables control a fine-grain level of checking:
+// there are read and write flags for DRAM, SRAM, ROM, and "unmapped
+// memory" (for 8 flags in all). Additionally, we have flags for checking
+// for accesses to Dragonballs registers and low-memory, for 12 flags in
+// all.
+//
+// These flags can be turned on and off at runtime. However, there is
+// still the penalty of constantly checking these flags at runtime, even
+// if they are turned off. Therefore, we can opt to compile those checks
+// out for maximum performance. For each runtime flag, there is a
+// corresponding compile time flag that controls whether or not the
+// runtime check is made. If the compile time flag is true, the check
+// is made based on the value of the runtime flag. If the compile time
+// flag is false, then the code for the runtime check is removed.
+//
+// With the compile and runtime flags turned on, startup time on
+// my Mac is about 1622 msecs. With the compile-time flags turned
+// off, startup time is about 1407 msecs. With the compile-time flags
+// turned on, but the runtime flags turned off, startup time is
+// about 1508 msecs.
+
+#define VALIDATE_DUMMY_GET 1
+#define VALIDATE_DUMMY_SET 1
+#define VALIDATE_REGISTER_GET 0
+#define VALIDATE_REGISTER_SET 0
+#define VALIDATE_DRAM_GET 1
+#define VALIDATE_DRAM_SET 1
+#define VALIDATE_SRAM_GET 0
+#define VALIDATE_SRAM_SET 0
+#define VALIDATE_ROM_GET 0
+#define VALIDATE_ROM_SET 1
+
+#define PREVENT_USER_LOWMEM_GET 1
+#define PREVENT_USER_LOWMEM_SET 1
+#define PREVENT_USER_GLOBAL_GET 1
+#define PREVENT_USER_GLOBAL_SET 1
+#define PREVENT_USER_SCREEN_GET 1
+#define PREVENT_USER_SCREEN_SET 1
+#define PREVENT_USER_SRAM_GET 0
+#define PREVENT_USER_SRAM_SET 1
+#define PREVENT_USER_ROM_GET 0
+#define PREVENT_USER_ROM_SET 1
+#define PREVENT_USER_REGISTER_GET 1
+#define PREVENT_USER_REGISTER_SET 1
+
+#define PREVENT_SYSTEM_LOWMEM_GET 1
+#define PREVENT_SYSTEM_LOWMEM_SET 1
+#define PREVENT_SYSTEM_ROM_GET 0
+#define PREVENT_SYSTEM_ROM_SET 1
+
+#define CHECK_FOR_ADDRESS_ERROR 1
+#define CHECK_FOR_LOW_STACK_ACCESS 1
+#define CHECK_CHUNK_ACCESS 0
+
+#define MASTER_RUNTIME_VALIDATE_SWITCH 1
+#define MASTER_RUNTIME_PREVENT_SWITCH 1
+
+#endif /* _SWITCHES_H_ */
+
+
diff --git a/SrcShared/SystemPacket.cpp b/SrcShared/SystemPacket.cpp
new file mode 100644
index 0000000..8b1a104
--- /dev/null
+++ b/SrcShared/SystemPacket.cpp
@@ -0,0 +1,1282 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "SystemPacket.h"
+
+#include "ATraps.h" // ATrap
+#include "DebugMgr.h" // Debug::
+#include "EmBankMapped.h" // EmBankMapped::GetEmulatedAddress
+#include "EmCPU68K.h" // gCPU68K->UpdateRegistersFromSR
+#include "EmErrCodes.h" // kError_NoError
+#include "EmLowMem.h" // EmLowMem_GetGlobal
+#include "EmMemory.h" // EmMem_memcpy
+#include "EmPalmFunction.h" // FindFunctionName
+#include "EmPalmStructs.h" // EmSysPktRPCType, etc
+#include "EmRPC.h" // slkSocketRPC
+#include "EmSession.h" // EmSession::Reset
+#include "HostControl.h" // hostSelectorWaitForIdle
+#include "Logging.h" // LogAppendMsg
+#include "Platform.h" // Platform::ExitDebugger
+#include "SLP.h" // SLP
+
+#include <ctype.h> // isalpha
+
+
+/*
+ This module implements the handling of all "serial link" packets.
+
+ Serial Link packets can be sent to Poser via a number of mechanisms:
+
+ * serial connections
+ * TCP connections
+ * PPC Toolbox connections (Macintosh)
+ * Memory-mapped file connection (Windows)
+
+ Regardless of how they're received, they get processed by SLP::HandleNewPacket.
+ This function looks at the destination of the packet specified in the packet
+ header. Currently, there are three supported targets in Poser:
+
+ * Debugger socket (also supported by Palm OS debugger nub)
+ * Console socket (also supported by Palm OS debugger nub)
+ * RPC socket (Poser specific)
+
+ Before handing the packet off to a socket-specific packet handler,
+ SLP::HandleNewPacket (which is running in the UI thread) synchronizes
+ with the CPU thread. For the debugger socket, it halts the thread
+ at whatever spot it's in. For the other sockets, it halts the thread
+ the next time a system call is made.
+
+ Poser's Debugger sub-system handles packets targeted to the debugger
+ and console sockets. Poser's RPC sub-system handles packets targeted
+ to the RPC socket.
+
+ The three sockets handle the following packets:
+
+ Debugger
+ sysPktStateCmd
+ sysPktReadMemCmd
+ sysPktWriteMemCmd
+ sysPktGetRtnNameCmd
+ sysPktReadRegsCmd
+ sysPktWriteRegsCmd
+ sysPktContinueCmd
+ sysPktRPCCmd
+ sysPktSetBreakpointsCmd
+ sysPktDbgBreakToggleCmd
+ sysPktGetTrapBreaksCmd
+ sysPktSetTrapBreaksCmd
+ sysPktFindCmd
+ sysPktGetTrapConditionsCmd
+ sysPktSetTrapConditionsCmd
+
+ Console
+ sysPktRPCCmd
+
+ RPC
+ sysPktReadMemCmd
+ sysPktWriteMemCmd
+ sysPktRPCCmd
+ sysPktRPC2Cmd
+
+ The Console and RPC sockets will always handle the packet they receive
+ (assuming that the UI thread has first synchronized with the CPU thread
+ on a system call first). If the packet is sent to the Debugger socket,
+ then the CPU must first be in "debug mode". This debug mode is automatically
+ entered if an error or exception has occurred and Poser has sent a "state"
+ packet to the external debugger. After that point, the external debugger
+ can send any packet it wants, optionally exiting debug mode by sending
+ a "Continue" packet, or perhaps sending an RPC packet to invoke the
+ SysReset Palm OS function.
+
+ An external debugger can also force the entry into "debug mode" by sending
+ a "get state" request packet to the Debugger socket. If the CPU is not in
+ debug mode, Poser will enter debug mode as a courtesey. Note that this is
+ a Poser-specific extension to the way the Debugger socket works. The Palm
+ OS ROM doesn't work this way.
+
+ All other packets sent to the Debugger socket are silently ignored if the
+ CPU is not in "debug mode".
+
+ ------------------------------------------------------------------------------
+
+ Crib notes on the supported packets:
+
+ +- Called by Debugger
+ | +- Implemented
+ | | Command
+ | | Command name Number Sent to
+ ------- --------------------------- ----------- -----------------
+ * * sysPktStateCmd 0x00 slkSocketDebugger SysPktStateCmdType SysPktStateRspType
+ * * sysPktReadMemCmd 0x01 slkSocketDebugger SysPktReadMemCmdType SysPktReadMemRspType
+ * * sysPktWriteMemCmd 0x02 slkSocketDebugger SysPktWriteMemCmdType SysPktWriteMemRspType
+ * . sysPktSingleStepCmd 0x03
+ * * sysPktGetRtnNameCmd 0x04 slkSocketDebugger SysPktRtnNameCmdType SysPktRtnNameRspType
+ * * sysPktReadRegsCmd 0x05 slkSocketDebugger SysPktReadRegsCmdType SysPktReadRegsRspType
+ * * sysPktWriteRegsCmd 0x06 slkSocketDebugger SysPktWriteRegsCmdType SysPktWriteRegsRspType
+ * * sysPktContinueCmd 0x07 slkSocketDebugger SysPktContinueCmdType <no response>
+ * * sysPktRPCCmd 0x0A both* SysPktRPCType
+ * sysPktGetBreakpointsCmd 0x0B SysPktGetBreakpointsCmdType SysPktGetBreakpointsRspType
+ * * sysPktSetBreakpointsCmd 0x0C slkSocketDebugger SysPktSetBreakpointsCmdType SysPktSetBreakpointsRspType
+ . sysPktRemoteUIUpdCmd 0x0C SysPktRemoteUIUpdCmdType
+ . sysPktRemoteEvtCmd 0x0D SysPktRemoteEvtCmdType
+ * * sysPktDbgBreakToggleCmd 0x0D slkSocketDebugger SysPktDbgBreakToggleCmdType SysPktDbgBreakToggleRspType
+ * . sysPktFlashCmd 0x0E SysPktFlashWriteType
+ * . sysPktCommCmd 0x0F both* SysPktCommCmdType SysPktCommRspType
+ * * sysPktGetTrapBreaksCmd 0x10 slkSocketDebugger SysPktGetTrapBreaksCmdType SysPktGetTrapBreaksRspType
+ * * sysPktSetTrapBreaksCmd 0x11 slkSocketDebugger SysPktSetTrapBreaksCmdType SysPktSetTrapBreaksRspType
+ + sysPktGremlinsCmd 0x12 slkSocketConsole SysPktGremlinsCmdType
+ * * sysPktFindCmd 0x13 slkSocketDebugger SysPktFindCmdType SysPktFindRspType
+ * sysPktGetTrapConditionsCmd 0x14 slkSocketDebugger SysPktGetTrapConditionsCmdType SysPktGetTrapConditionsRspType
+ * sysPktSetTrapConditionsCmd 0x15 slkSocketDebugger SysPktSetTrapConditionsCmdType SysPktSetTrapConditionsRspType
+ . sysPktChecksumCmd 0x16 slkSocketDebugger SysPktChecksumType
+ . sysPktExecFlashCmd 0x17 slkSocketDebugger sysPktExecFlashType
+ * * sysPktRemoteMsgCmd 0x7f both SysPktRemoteMsgCmdType
+
+ "both*" = if attached, sent to slkSocketDebugger, else slkSocketConsole
+*/
+
+#define sysPktBadFormatRsp 0xFF
+
+
+#define ENTER_CODE(fnName, cmdType, rspType) \
+ PRINTF ("Entering SystemPacket::" fnName "."); \
+ EmAlias##cmdType<LAS> packet (slp.Body ().GetPtr ())
+
+
+#define ENTER_PACKET(fnName, cmdType, rspType) \
+ PRINTF ("Entering SystemPacket::" fnName "."); \
+ EmAlias##cmdType<LAS> packet (slp.Body ().GetPtr ()); \
+ EmProxy##rspType response
+
+
+#define EXIT_PACKET(fnName, code, bodySize) \
+ response.command = code; \
+ response._filler = 0; \
+ ErrCode result = SystemPacket::SendPacket (slp, response.GetPtr(), bodySize); \
+ PRINTF ("Exiting SystemPacket::" fnName "."); \
+ return result
+
+
+#define EXIT_CODE(fnName, code) \
+ ErrCode result = SystemPacket::SendResponse (slp, code); \
+ PRINTF ("Exiting SystemPacket::" fnName "."); \
+ return result
+
+
+#define PRINTF if (!LogHLDebugger ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendState
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendState (SLP& slp)
+{
+ // Do this function entry by hand instead of using the ENTER_PACKET macro.
+ // That macro will call SLP::Body, which returns a reference to the
+ // packet body that was sent to us. However, SendState (a) doesn't
+ // need the body reference, so there's no need to set it up, and (b)
+ // isn't necessarily called in response to a "SendState" command,
+ // and so the reference may be NULL.
+
+ PRINTF ("Entering SystemPacket::SendState.");
+ EmProxySysPktStateRspType response;
+
+ // Get the resetted boolean. This flag is true if the "device" has
+ // been resetted since the last time we sent a packet. The debugger
+ // needs to know this in order to update its notion of the device's
+ // state (like, for instance, if breakpoints are installed).
+
+ response.resetted = gDebuggerGlobals.firstEntrance;
+ gDebuggerGlobals.firstEntrance = false;
+
+ // Get the exception id.
+
+ response.exceptionId = gDebuggerGlobals.excType;
+
+ // Get the registers.
+
+ M68KRegsType reg;
+ SystemPacket::GetRegs (reg);
+
+ response.reg.d[0] = reg.d[0];
+ response.reg.d[1] = reg.d[1];
+ response.reg.d[2] = reg.d[2];
+ response.reg.d[3] = reg.d[3];
+ response.reg.d[4] = reg.d[4];
+ response.reg.d[5] = reg.d[5];
+ response.reg.d[6] = reg.d[6];
+ response.reg.d[7] = reg.d[7];
+ response.reg.a[0] = reg.a[0];
+ response.reg.a[1] = reg.a[1];
+ response.reg.a[2] = reg.a[2];
+ response.reg.a[3] = reg.a[3];
+ response.reg.a[4] = reg.a[4];
+ response.reg.a[5] = reg.a[5];
+ response.reg.a[6] = reg.a[6];
+ response.reg.usp = reg.usp;
+ response.reg.ssp = reg.ssp;
+ response.reg.pc = reg.pc;
+ response.reg.sr = reg.sr;
+
+ // Get the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ response.bp[ii].addr = gDebuggerGlobals.bp[ii].addr;
+ response.bp[ii].enabled = gDebuggerGlobals.bp[ii].enabled;
+ response.bp[ii].installed = gDebuggerGlobals.bp[ii].installed;
+ }
+
+ // Get some code beginning at PC.
+
+ emuptr pc = m68k_getpc ();
+ for (int jj = 0; jj < sysPktStateRspInstWords; ++jj)
+ {
+ // Do this as two fetches in case the PC is odd.
+ response.inst[jj] = EmMemGet8 (pc + 2 * jj + 0) * 256 +
+ EmMemGet8 (pc + 2 * jj + 1);
+ }
+
+
+ // Get the routine name and address range info.
+
+ void* startAddr;
+ void* endAddr;
+ memset (response.name.GetPtr (), 0, sysPktMaxNameLen);
+ ::FindFunctionName ( pc & 0xFFFFFFFE, // Protect against odd addresses.
+ (char*) response.name.GetPtr (),
+ (emuptr*) &startAddr,
+ (emuptr*) &endAddr);
+
+ response.startAddr = startAddr;
+ response.endAddr = endAddr;
+
+ // Send the rev of the trap table.
+
+ response.trapTableRev = EmLowMem_GetGlobal (sysDispatchTableRev);
+
+ EXIT_PACKET ("SendState", sysPktStateRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ReadMem
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ReadMem (SLP& slp)
+{
+ ENTER_PACKET ("ReadMem", SysPktReadMemCmdType, SysPktReadMemRspType);
+
+ void* dest = response.data.GetPtr ();
+ emuptr src = (emuptr) packet.address;
+ UInt16 len = packet.numBytes;
+
+ memset (dest, 0xFF, len); // Clear buffer in case of failure.
+
+ if (len > 0 && EmMemCheckAddress (src, 1) && EmMemCheckAddress (src + len - 1, 1))
+ {
+ EmMem_memcpy (dest, src, len);
+ }
+
+ EXIT_PACKET ("ReadMem", sysPktReadMemRsp,
+ EmProxySysPktEmptyRspType::GetSize () + packet.numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::WriteMem
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::WriteMem (SLP& slp)
+{
+ ENTER_CODE ("WriteMem", SysPktWriteMemCmdType, SysPktWriteMemRspType);
+
+ emuptr dest = (emuptr) packet.address;
+ const void* src = packet.data.GetPtr ();
+ UInt16 len = packet.numBytes;
+
+ if (len > 0 && EmMemCheckAddress (dest, 1) && EmMemCheckAddress (dest + len - 1, 1))
+ {
+ EmMem_memcpy (dest, src, len);
+ }
+
+ // If we just altered low memory, recalculate the low-memory checksum.
+ // Make sure we're on a ROM that has this field! Determine this by
+ // seeing that the address of sysLowMemChecksum is below the memCardInfo
+ // fields that come after the FixedGlobals.
+ //
+ // !!! This chunk of code should be in some more generally accessible location.
+
+ if (offsetof (LowMemType, fixed.globals.sysLowMemChecksum) < EmLowMem_GetGlobal (memCardInfoP))
+ {
+ if ((emuptr) packet.address < (emuptr) 0x100)
+ {
+ UInt32 checksum = 0;
+ emuptr csP = EmMemNULL;
+
+ // First, calculate the checksum
+
+ while (csP < (emuptr) 0x100)
+ {
+ UInt32 data = EmMemGet32 (csP);
+
+ // Don't do these trap vectors since they change whenever the
+ // debugger is set to break on any a-trap or breakpoint.
+
+ if (csP == offsetof (M68KExcTableType, trapN[sysDispatchTrapNum]))
+ data = 0;
+
+ if (csP == offsetof (M68KExcTableType, trapN[sysDbgBreakpointTrapNum]))
+ data = 0;
+
+ if (csP == offsetof (M68KExcTableType, trace))
+ data = 0;
+
+ checksum += data;
+ csP += 4;
+ }
+
+ // Save new checksum
+
+ EmLowMem_SetGlobal (sysLowMemChecksum, checksum);
+ }
+ }
+
+ EXIT_CODE ("WriteMem", sysPktWriteMemRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendRoutineName
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendRoutineName (SLP& slp)
+{
+ ENTER_PACKET ("SendRoutineName", SysPktRtnNameCmdType, SysPktRtnNameRspType);
+
+ emuptr pc = ((emuptr) packet.address) & ~1; // Protect against odd address.
+ void* startAddr;
+ void* endAddr;
+
+ ::FindFunctionName( pc, (char*) response.name.GetPtr (),
+ (emuptr*) &startAddr,
+ (emuptr*) &endAddr);
+
+ response.address = packet.address;
+ response.startAddr = startAddr;
+ response.endAddr = endAddr;
+
+ EXIT_PACKET ("SendRoutineName", sysPktGetRtnNameRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ReadRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ReadRegs (SLP& slp)
+{
+ ENTER_PACKET ("ReadRegs", SysPktReadRegsCmdType, SysPktReadRegsRspType);
+ UNUSED_PARAM (packet)
+
+ // Get the registers.
+
+ M68KRegsType reg;
+ SystemPacket::GetRegs (reg);
+
+ response.reg.d[0] = reg.d[0];
+ response.reg.d[1] = reg.d[1];
+ response.reg.d[2] = reg.d[2];
+ response.reg.d[3] = reg.d[3];
+ response.reg.d[4] = reg.d[4];
+ response.reg.d[5] = reg.d[5];
+ response.reg.d[6] = reg.d[6];
+ response.reg.d[7] = reg.d[7];
+ response.reg.a[0] = reg.a[0];
+ response.reg.a[1] = reg.a[1];
+ response.reg.a[2] = reg.a[2];
+ response.reg.a[3] = reg.a[3];
+ response.reg.a[4] = reg.a[4];
+ response.reg.a[5] = reg.a[5];
+ response.reg.a[6] = reg.a[6];
+ response.reg.usp = reg.usp;
+ response.reg.ssp = reg.ssp;
+ response.reg.pc = reg.pc;
+ response.reg.sr = reg.sr;
+
+ EXIT_PACKET ("ReadRegs", sysPktReadRegsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::WriteRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::WriteRegs (SLP& slp)
+{
+ ENTER_CODE ("WriteRegs", SysPktWriteRegsCmdType, SysPktWriteRegsRspType);
+
+ M68KRegsType reg;
+
+ reg.d[0] = packet.reg.d[0];
+ reg.d[1] = packet.reg.d[1];
+ reg.d[2] = packet.reg.d[2];
+ reg.d[3] = packet.reg.d[3];
+ reg.d[4] = packet.reg.d[4];
+ reg.d[5] = packet.reg.d[5];
+ reg.d[6] = packet.reg.d[6];
+ reg.d[7] = packet.reg.d[7];
+ reg.a[0] = packet.reg.a[0];
+ reg.a[1] = packet.reg.a[1];
+ reg.a[2] = packet.reg.a[2];
+ reg.a[3] = packet.reg.a[3];
+ reg.a[4] = packet.reg.a[4];
+ reg.a[5] = packet.reg.a[5];
+ reg.a[6] = packet.reg.a[6];
+ reg.usp = packet.reg.usp;
+ reg.ssp = packet.reg.ssp;
+ reg.pc = packet.reg.pc;
+ reg.sr = packet.reg.sr;
+
+ SystemPacket::SetRegs (reg);
+
+ EXIT_CODE ("ReadRegs", sysPktWriteRegsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::Continue
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::Continue (SLP& slp)
+{
+ ENTER_CODE ("Continue", SysPktContinueCmdType, SysPktContinueCmdType);
+
+ M68KRegsType reg;
+
+ reg.d[0] = packet.regs.d[0];
+ reg.d[1] = packet.regs.d[1];
+ reg.d[2] = packet.regs.d[2];
+ reg.d[3] = packet.regs.d[3];
+ reg.d[4] = packet.regs.d[4];
+ reg.d[5] = packet.regs.d[5];
+ reg.d[6] = packet.regs.d[6];
+ reg.d[7] = packet.regs.d[7];
+ reg.a[0] = packet.regs.a[0];
+ reg.a[1] = packet.regs.a[1];
+ reg.a[2] = packet.regs.a[2];
+ reg.a[3] = packet.regs.a[3];
+ reg.a[4] = packet.regs.a[4];
+ reg.a[5] = packet.regs.a[5];
+ reg.a[6] = packet.regs.a[6];
+ reg.usp = packet.regs.usp;
+ reg.ssp = packet.regs.ssp;
+ reg.pc = packet.regs.pc;
+ reg.sr = packet.regs.sr;
+
+ SystemPacket::SetRegs (reg);
+
+
+ gDebuggerGlobals.stepSpy = packet.stepSpy != 0;
+ gDebuggerGlobals.ssAddr = packet.ssAddr;
+ // ssCount is ignored?
+ gDebuggerGlobals.ssValue = packet.ssCheckSum;
+
+ ErrCode result = Debug::ExitDebugger ();
+
+ // Perform any platform-specific actions.
+
+ if (result == errNone)
+ {
+ Platform::ExitDebugger ();
+ }
+
+ // No reply...
+
+ PRINTF ("Exiting SystemPacket::Continue.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::RPC
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::RPC (SLP& slp)
+{
+ ENTER_PACKET ("RPC", SysPktRPCType, SysPktRPCType);
+
+ // Handle calls to SysReset specially, since that function never
+ // returns. Do this *before* creating the ATrap object, as that
+ // object's d'tor will attempt to restore the PC to what it was
+ // when the c'tor was run.
+
+ if (packet.trapWord == sysTrapSysReset)
+ {
+#if 0
+ emuptr sysResetAddr = EmLowMem::GetTrapAddress (sysTrapSysReset);
+ EmAssert (sysResetAddr);
+
+ m68k_setpc (sysResetAddr);
+
+ // Exit trace mode. On an actual device, debugger packets (including
+ // the final call to SysReset) are handled at interrupt time when
+ // trace mode is turned off. However, on Poser, trace mode may be
+ // left on by any previous single-step commands since we handle
+ // debugger packets "between cycles" and not at interrupt time.
+
+ regs.t1 = regs.t0 = regs.m = 0;
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+#else
+ // Call EmSession::Reset instead of doing the above in order
+ // to more cleanly exit not only trace mode, but debug mode
+ // and any other modes I didn't think of.
+ EmAssert (gSession);
+ gSession->Reset (kResetSoft);
+#endif
+
+ return kError_NoError;
+ }
+
+
+ ATrap trap;
+
+ // Map in the memory pointed to by the reference parameters
+ StMemoryMapper mapper (packet.GetPtr (), sysPktMaxBodySize);
+
+
+ void* paramStart = packet.param.GetPtr ();
+ void* paramPtr = paramStart;
+
+ for (UInt16 ii = 0; ii < packet.numParams; ++ii)
+ {
+ EmAliasSysPktRPCParamType<LAS> param (paramPtr);
+
+ if (param.byRef)
+ {
+ trap.PushLong (EmBankMapped::GetEmulatedAddress (param.asByte.GetPtr ()));
+ }
+ else
+ {
+ if (param.size == 1)
+ {
+ trap.PushByte (param.asByte);
+ }
+ else if (param.size == 2)
+ {
+ trap.PushWord (param.asShort);
+ }
+ else if (param.size == 4)
+ {
+ trap.PushLong (param.asLong);
+ }
+ }
+
+ paramPtr = ((char*) param.asByte.GetPtr ()) + ((param.size + 1) & ~1);
+ }
+
+
+ // Call the trap.
+
+ trap.Call (packet.trapWord);
+
+ memcpy (response.GetPtr (), packet.GetPtr (), sysPktMaxBodySize);
+
+ response.resultD0 = trap.GetD0 ();
+ response.resultA0 = trap.GetA0 ();
+
+ long numBytes = ((char*) paramPtr) - ((char*) packet.GetPtr ()); // or get from header...
+
+ EXIT_PACKET ("RPC", sysPktRPCRsp, numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::RPC2
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::RPC2 (SLP& slp)
+{
+ ENTER_PACKET ("RPC2", SysPktRPC2Type, SysPktRPC2Type);
+
+ // Handle calls to SysReset specially, since that function never
+ // returns. Do this *before* creating the ATrap object, as that
+ // object's d'tor will attempt to restore the PC to what it was
+ // when the c'tor was run.
+
+ if (packet.trapWord == sysTrapSysReset)
+ {
+#if 0
+ emuptr sysResetAddr = EmLowMem::GetTrapAddress (sysTrapSysReset);
+ EmAssert (sysResetAddr);
+
+ m68k_setpc (sysResetAddr);
+
+ // Exit trace mode. On an actual device, debugger packets (including
+ // the final call to SysReset) are handled at interrupt time when
+ // trace mode is turned off. However, on Poser, trace mode may be
+ // left on by any previous single-step commands since we handle
+ // debugger packets "between cycles" and not at interrupt time.
+
+ regs.t1 = regs.t0 = regs.m = 0;
+ regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
+#else
+ // Call EmSession::Reset instead of doing the above in order
+ // to more cleanly exit not only trace mode, but debug mode
+ // and any other modes I didn't think of.
+ EmAssert (gSession);
+ gSession->Reset (kResetSoft);
+#endif
+
+ return kError_NoError;
+ }
+
+
+ ATrap trap;
+
+ // Map in the memory pointed to by the reference parameters
+ StMemoryMapper mapper (packet.GetPtr (), sysPktMaxBodySize);
+
+
+ // Extract any D-registers from the packet.
+
+ UInt32* regsP = (UInt32*) packet.Regs.GetPtr ();
+ int mask = 0x01;
+ int regNum = 0;
+
+ while (mask < 0x100)
+ {
+ if ((mask & packet.DRegMask) != 0)
+ {
+ EmAliasUInt32<LAS> reg (regsP++);
+ trap.SetNewDReg (regNum, reg);
+ }
+
+ ++regNum;
+ mask <<= 1;
+ }
+
+ // Extract any A-registers from the packet.
+
+ mask = 0x01;
+ regNum = 0;
+
+ while (mask < 0x100)
+ {
+ if ((mask & packet.ARegMask) != 0)
+ {
+ EmAliasUInt32<LAS> reg (regsP++);
+ trap.SetNewAReg (regNum, reg);
+ }
+
+ ++regNum;
+ mask <<= 1;
+ }
+
+ // Extract any stack-based parameters from the packet.
+
+ EmAliasUInt16<LAS> numParamsP (regsP);
+ UInt16 numParams = numParamsP;
+
+ void* paramStart = ((char*) regsP) + sizeof (UInt16);
+ void* paramPtr = paramStart;
+
+ for (UInt16 ii = 0; ii < numParams; ++ii)
+ {
+ EmAliasSysPktRPCParamType<LAS> param (paramPtr);
+
+ if (param.byRef)
+ {
+ trap.PushLong (EmBankMapped::GetEmulatedAddress (param.asByte.GetPtr ()));
+ }
+ else
+ {
+ if (param.size == 1)
+ {
+ trap.PushByte (param.asByte);
+ }
+ else if (param.size == 2)
+ {
+ trap.PushWord (param.asShort);
+ }
+ else if (param.size == 4)
+ {
+ trap.PushLong (param.asLong);
+ }
+ }
+
+ paramPtr = ((char*) param.asByte.GetPtr ()) + ((param.size + 1) & ~1);
+ }
+
+
+ // Call the trap.
+
+ trap.Call (packet.trapWord);
+
+ memcpy (response.GetPtr (), packet.GetPtr (), sysPktMaxBodySize);
+
+ response.resultD0 = trap.GetD0 ();
+ response.resultA0 = trap.GetA0 ();
+ response.resultException = 0;
+
+ long numBytes = ((char*) paramPtr) - ((char*) packet.GetPtr ()); // or get from header...
+
+ EXIT_PACKET ("RPC2", sysPktRPC2Rsp, numBytes);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetBreakpoints
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetBreakpoints (SLP& slp)
+{
+ ENTER_PACKET ("GetBreakpoints", SysPktGetBreakpointsCmdType, SysPktGetBreakpointsRspType);
+ UNUSED_PARAM (packet)
+
+ // Get the breakpoints.
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ response.bp[ii].addr = gDebuggerGlobals.bp[ii].addr;
+ response.bp[ii].enabled = gDebuggerGlobals.bp[ii].enabled;
+ response.bp[ii].installed = gDebuggerGlobals.bp[ii].installed;
+ }
+
+ EXIT_PACKET ("GetBreakpoints", sysPktGetBreakpointsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetBreakpoints
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetBreakpoints (SLP& slp)
+{
+ ENTER_CODE ("SetBreakpoints", SysPktSetBreakpointsCmdType, SysPktSetBreakpointsRspType);
+
+ for (int ii = 0; ii < dbgTotalBreakpoints; ++ii)
+ {
+ if (packet.bp[ii].enabled)
+ {
+ Debug::SetBreakpoint (ii, (emuptr) packet.bp[ii].addr, NULL);
+ }
+ else
+ {
+ Debug::ClearBreakpoint (ii);
+ }
+ }
+
+ EXIT_CODE ("GetBreakpoints", sysPktSetBreakpointsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::ToggleBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::ToggleBreak (SLP& slp)
+{
+ ENTER_PACKET ("ToggleBreak", SysPktDbgBreakToggleCmdType, SysPktDbgBreakToggleRspType);
+ UNUSED_PARAM (packet)
+
+ gDebuggerGlobals.ignoreDbgBreaks = !gDebuggerGlobals.ignoreDbgBreaks;
+
+ response.newState = gDebuggerGlobals.ignoreDbgBreaks;
+
+ EXIT_PACKET ("ToggleBreak", sysPktDbgBreakToggleRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetTrapBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetTrapBreaks (SLP& slp)
+{
+ ENTER_PACKET ("GetTrapBreaks", SysPktGetTrapBreaksCmdType, SysPktGetTrapBreaksRspType);
+ UNUSED_PARAM (packet)
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ response.trapBP[ii] = gDebuggerGlobals.trapBreak[ii];
+ }
+
+ EXIT_PACKET ("GetTrapBreaks", sysPktGetTrapBreaksRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetTrapBreaks
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetTrapBreaks (SLP& slp)
+{
+ ENTER_CODE ("SetTrapBreaks", SysPktSetTrapBreaksCmdType, SysPktSetTrapBreaksRspType);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ gDebuggerGlobals.trapBreak[ii] = packet.trapBP[ii];
+ }
+
+ gDebuggerGlobals.breakingOnATrap = false;
+ for (int jj = 0; jj < dbgTotalTrapBreaks; ++jj)
+ {
+ if (gDebuggerGlobals.trapBreak[jj])
+ {
+ gDebuggerGlobals.breakingOnATrap = true;
+ break;
+ }
+ }
+
+ EXIT_CODE ("SetTrapBreaks", sysPktSetTrapBreaksRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::Find
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::Find (SLP& slp)
+{
+ ENTER_PACKET ("Find", SysPktFindCmdType, SysPktFindRspType);
+
+ response.addr = (UInt32) NULL;
+ response.found = false;
+
+ {
+ UInt8* dataP = (UInt8*) packet.data.GetPtr ();
+ UInt32 startP = packet.firstAddr;
+
+ while (startP <= packet.lastAddr)
+ {
+ UInt16 ii;
+
+ for (ii = 0; ii < packet.numBytes; ++ii)
+ {
+ UInt8 b1 = EmMemGet8 (startP + ii);
+ UInt8 b2 = dataP[ii];
+
+ // Handle caseless conversion
+
+ if (packet.caseInsensitive)
+ {
+ if (isalpha (b1))
+ b1 = tolower (b1);
+
+ if (isalpha (b2))
+ b2 = tolower (b2);
+ }
+
+ if (b1 != b2) // if different -->
+ break;
+ }
+
+ // Check if matched
+
+ if (ii >= packet.numBytes)
+ {
+ response.addr = startP;
+ response.found = true;
+ break;
+ }
+
+ startP++; // advance start of search pointer
+ }
+ }
+
+ EXIT_PACKET ("Find", sysPktFindRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetTrapConditions
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::GetTrapConditions (SLP& slp)
+{
+ ENTER_PACKET ("GetTrapConditions", SysPktGetTrapConditionsCmdType, SysPktGetTrapConditionsRspType);
+ UNUSED_PARAM (packet);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ response.trapParam[ii] = gDebuggerGlobals.trapParam[ii];
+ }
+
+ EXIT_PACKET ("GetTrapConditions", sysPktGetTrapConditionsRsp, response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SetTrapConditions
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SetTrapConditions (SLP& slp)
+{
+ ENTER_CODE ("SetTrapConditions", SysPktSetTrapConditionsCmdType, SysPktSetTrapConditionsRspType);
+
+ for (int ii = 0; ii < dbgTotalTrapBreaks; ++ii)
+ {
+ gDebuggerGlobals.trapParam[ii] = packet.trapParam[ii];
+ }
+
+ EXIT_CODE ("SetTrapConditions", sysPktSetTrapConditionsRsp);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendMessage
+ *
+ * DESCRIPTION: Sends a text string to the external client.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendMessage (SLP& slp, const char* msg)
+{
+// ENTER_PACKET ("SendMessage", SysPktBodyType, SysPktBodyType);
+
+ // Do this function entry by hand instead of using the ENTER_PACKET macro.
+ // That macro will call SLP::Body, which returns a reference to the
+ // packet body that was sent to us. However, SendMessage (a) doesn't
+ // need the body reference, so there's no need to set it up, and (b)
+ // isn't necessarily called in response to a "SendMessage" command,
+ // and so the reference may be NULL.
+
+ PRINTF ("Entering SystemPacket::SendMessage.");
+ EmProxySysPktBodyType response;
+
+ size_t len = strlen (msg) + 1;
+ strcpy ((char*) response.data.GetPtr (), msg);
+
+ EXIT_PACKET ("SendMessage", sysPktRemoteMsgCmd,
+ EmProxySysPktEmptyRspType::GetSize () + len);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendResponse
+ *
+ * DESCRIPTION: Sends a simple null-body message to the external debugger.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendResponse (SLP& slp, UInt8 code)
+{
+ EmProxySysPktEmptyRspType response;
+
+ response.command = code;
+ response._filler = 0;
+
+ return SystemPacket::SendPacket (slp, response.GetPtr (), response.GetSize ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::SendPacket
+ *
+ * DESCRIPTION: Sends the given packet to the external client.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+ErrCode SystemPacket::SendPacket (SLP& slp, const void* body, long bodySize)
+{
+ PRINTF ("Entering SystemPacket::SendPacket.");
+
+ ErrCode result = slp.SendPacket (body, bodySize);
+
+ PRINTF ("Exiting SystemPacket::SendPacket.");
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: SystemPacket::GetRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SystemPacket::GetRegs (M68KRegsType& debuggerRegs)
+{
+ debuggerRegs.d[0] = m68k_dreg (regs, 0);
+ debuggerRegs.d[1] = m68k_dreg (regs, 1);
+ debuggerRegs.d[2] = m68k_dreg (regs, 2);
+ debuggerRegs.d[3] = m68k_dreg (regs, 3);
+ debuggerRegs.d[4] = m68k_dreg (regs, 4);
+ debuggerRegs.d[5] = m68k_dreg (regs, 5);
+ debuggerRegs.d[6] = m68k_dreg (regs, 6);
+ debuggerRegs.d[7] = m68k_dreg (regs, 7);
+
+ debuggerRegs.a[0] = m68k_areg (regs, 0);
+ debuggerRegs.a[1] = m68k_areg (regs, 1);
+ debuggerRegs.a[2] = m68k_areg (regs, 2);
+ debuggerRegs.a[3] = m68k_areg (regs, 3);
+ debuggerRegs.a[4] = m68k_areg (regs, 4);
+ debuggerRegs.a[5] = m68k_areg (regs, 5);
+ debuggerRegs.a[6] = m68k_areg (regs, 6);
+// debuggerRegs.a[7] = m68k_areg (regs, 7);
+
+ // Update the usp, isp, and/or msp before returning it.
+ // (from m68k_dumpstate() in newcpu.c)
+
+ if (regs.s == 0)
+ regs.usp = m68k_areg (regs, 7);
+ else
+ regs.isp = m68k_areg (regs, 7);
+
+ // Make sure the Status Register is up-to-date before moving it
+ // into the debugger register set.
+
+ EmAssert (gCPU68K);
+ gCPU68K->UpdateSRFromRegisters ();
+
+ // Copy the remaining registers from the UAE register set to the
+ // debugger's register set.
+
+ debuggerRegs.usp = regs.usp;
+ debuggerRegs.ssp = regs.isp;
+ debuggerRegs.sr = regs.sr;
+ debuggerRegs.pc = m68k_getpc ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Debug::SetRegs
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void SystemPacket::SetRegs (const M68KRegsType& debuggerRegs)
+{
+ m68k_dreg (regs, 0) = debuggerRegs.d[0];
+ m68k_dreg (regs, 1) = debuggerRegs.d[1];
+ m68k_dreg (regs, 2) = debuggerRegs.d[2];
+ m68k_dreg (regs, 3) = debuggerRegs.d[3];
+ m68k_dreg (regs, 4) = debuggerRegs.d[4];
+ m68k_dreg (regs, 5) = debuggerRegs.d[5];
+ m68k_dreg (regs, 6) = debuggerRegs.d[6];
+ m68k_dreg (regs, 7) = debuggerRegs.d[7];
+
+ m68k_areg (regs, 0) = debuggerRegs.a[0];
+ m68k_areg (regs, 1) = debuggerRegs.a[1];
+ m68k_areg (regs, 2) = debuggerRegs.a[2];
+ m68k_areg (regs, 3) = debuggerRegs.a[3];
+ m68k_areg (regs, 4) = debuggerRegs.a[4];
+ m68k_areg (regs, 5) = debuggerRegs.a[5];
+ m68k_areg (regs, 6) = debuggerRegs.a[6];
+// m68k_areg (regs, 7) = debuggerRegs.a[7];
+
+ regs.usp = debuggerRegs.usp;
+ regs.isp = debuggerRegs.ssp;
+ regs.sr = debuggerRegs.sr;
+ m68k_setpc (debuggerRegs.pc);
+
+ // Make sure 's' bit is correct. This will also set SPCFLAG_INT, and
+ // if either the t0 or t1 bits are set, SPCFLAG_TRACE, too.
+
+ EmAssert (gCPU68K);
+ gCPU68K->UpdateRegistersFromSR ();
+
+ // I think we need to do a little extra handling here of the TRACE
+ // mode. If the TRACE mode bit is set, UpdateRegistersFromSR will
+ // set its SPCFLAG_TRACE flag, which tells the CPU loop to finish
+ // executing the current instruction, and then set the SPCFLAG_DOTRACE
+ // flag afterwards, which will then cause execution to stop after
+ // the NEXT instruction. We have a bit of an edge condition here
+ // when we set the SPCFLAG_TRACE flag BETWEEN instructions. Doing it
+ // this way will cause the next instruction to be treated as the
+ // "current" instruction, and so execution will stop after executing
+ // the second opcode. We want execution to stop with the first
+ // opcode, so fix up the flags here. This code is the same as in
+ // Emulator::ExecuteSpecial for managing this stuff.
+
+ if (regs.spcflags & SPCFLAG_TRACE)
+ {
+ regs.spcflags &= ~SPCFLAG_TRACE;
+ regs.spcflags |= SPCFLAG_DOTRACE;
+ }
+
+ // Finally, update the stack pointer from the usp or ssp,
+ // as appropriate.
+
+ if (regs.s == 0)
+ m68k_areg (regs, 7) = debuggerRegs.usp;
+ else
+ m68k_areg (regs, 7) = debuggerRegs.ssp;
+}
diff --git a/SrcShared/SystemPacket.h b/SrcShared/SystemPacket.h
new file mode 100644
index 0000000..9a6edac
--- /dev/null
+++ b/SrcShared/SystemPacket.h
@@ -0,0 +1,52 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef SYSTEMPACKET_H_
+#define SYSTEMPACKET_H_
+
+#include "EmTypes.h" // ErrCode
+
+class SLP;
+
+class SystemPacket
+{
+ public:
+ static ErrCode SendState (SLP&);
+ static ErrCode ReadMem (SLP&);
+ static ErrCode WriteMem (SLP&);
+ static ErrCode SendRoutineName (SLP&);
+ static ErrCode ReadRegs (SLP&);
+ static ErrCode WriteRegs (SLP&);
+ static ErrCode Continue (SLP&);
+ static ErrCode RPC (SLP&);
+ static ErrCode RPC2 (SLP&);
+ static ErrCode GetBreakpoints (SLP&);
+ static ErrCode SetBreakpoints (SLP&);
+ static ErrCode ToggleBreak (SLP&);
+ static ErrCode GetTrapBreaks (SLP&);
+ static ErrCode SetTrapBreaks (SLP&);
+ static ErrCode Find (SLP&);
+ static ErrCode GetTrapConditions (SLP&);
+ static ErrCode SetTrapConditions (SLP&);
+
+ static ErrCode SendMessage (SLP&, const char*);
+
+ private:
+ static ErrCode SendResponse (SLP&, UInt8 code);
+ static ErrCode SendPacket (SLP&, const void* body, long bodySize);
+
+ static void GetRegs (M68KRegsType&);
+ static void SetRegs (const M68KRegsType&);
+};
+
+#endif // SYSTEMPACKET_H_
diff --git a/SrcShared/TracerCommon.cpp b/SrcShared/TracerCommon.cpp
new file mode 100644
index 0000000..88f9e00
--- /dev/null
+++ b/SrcShared/TracerCommon.cpp
@@ -0,0 +1,310 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "TracerCommon.h"
+
+#include "PreferenceMgr.h"
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::TracerBase
+// ---------------------------------------------------------------------------
+
+TracerBase::TracerBase(void)
+{
+ tracerRefCounter = 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::~TracerBase
+// ---------------------------------------------------------------------------
+
+TracerBase::~TracerBase(void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::GetTracerTypeCount
+// ---------------------------------------------------------------------------
+
+unsigned short TracerBase::GetTracerTypeCount (void)
+{
+ return supportedTypesCount;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::GetTracerTypeInfo
+// ---------------------------------------------------------------------------
+
+TracerTypeInfo* TracerBase::GetTracerTypeInfo (unsigned short index)
+{
+ if (index < 1 || index > supportedTypesCount)
+ {
+ return 0;
+ }
+
+ return &supportedTypesTable[index-1]; // Types are numbered starting from 1
+}
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::GetCurrentTracerTypeInfo
+// ---------------------------------------------------------------------------
+
+TracerTypeInfo* TracerBase::GetCurrentTracerTypeInfo (void)
+{
+ return GetTracerTypeInfo (runningTracerType);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::GetCurrentTracerTypeIndex
+// ---------------------------------------------------------------------------
+
+unsigned short TracerBase::GetCurrentTracerTypeIndex (void)
+{
+ return runningTracerType;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::GetCapsToken
+// ---------------------------------------------------------------------------
+
+void TracerBase::GetCapsToken (char* src, char* tag, char* dst, size_t dstSize)
+{
+ int copiedBytes = 0;
+
+ src = strstr(src,tag);
+
+ if (!src)
+ {
+ *dst= 0;
+ return;
+ }
+
+ src += strlen(tag);
+
+ while (*src != ',' && *src != 0 && copiedBytes < dstSize-1)
+ {
+ *dst++ = *src++;
+ copiedBytes++;
+ }
+
+ *dst= 0;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::LoadTracerTypeList
+// ---------------------------------------------------------------------------
+
+void TracerBase::LoadTracerTypeList (void)
+{
+ char tracerCaps[4096];
+ size_t bufferLen = 4096;
+ char *cursor;
+ int i;
+ char buff[2];
+
+ // Get last used Type from prefs
+ Preference<string> prefLastTracerType (kPrefKeyLastTracerType);
+ string lastTypeName = *prefLastTracerType;
+
+ supportedTypesCount = 0;
+ supportedTypesTable = 0;
+
+ // Ask PalmTrace for supported tracer Types
+ // The expected result is a set of strings terminated by a double 0. Here is a possible one:
+ // "Type=tcp,name=Palm Reporter,paramdescr=Target:,paramdefval=localhost,autoconnect=1"
+ GetTracerCapabilities (tracerCaps, &bufferLen);
+
+ // The string can't be void
+ cursor = tracerCaps;
+ if (*cursor == 0)
+ {
+ return;
+ }
+
+ while (cursor && *cursor)
+ {
+ supportedTypesCount++;
+
+ // Seek next 0 ; the end marker is a double zero
+ cursor += strlen(cursor)+1;
+ }
+
+ if (supportedTypesCount > 0)
+ {
+ cursor = tracerCaps;
+ supportedTypesTable = new TracerTypeInfo [supportedTypesCount];
+
+ // Set up a tracer Type table in memory
+ for (i=0; i<supportedTypesCount; i++)
+ {
+ GetCapsToken (cursor, "kind=", supportedTypesTable[i].type, sizeof(supportedTypesTable[0].type));
+ GetCapsToken (cursor, "name=", supportedTypesTable[i].friendlyName,sizeof(supportedTypesTable[0].friendlyName));
+ GetCapsToken (cursor, "paramdescr=", supportedTypesTable[i].paramDescr, sizeof(supportedTypesTable[0].paramDescr));
+ GetCapsToken (cursor, "paramdefval=", supportedTypesTable[i].paramDefVal, sizeof(supportedTypesTable[0].paramDefVal));
+
+ GetCapsToken (cursor, "autoconnect=", buff, 2);
+ supportedTypesTable[i].autoConnectSupport = (buff[0] == '1');
+
+ strcpy (supportedTypesTable[i].paramCurVal, supportedTypesTable[i].paramDefVal);
+ supportedTypesTable[i].autoConnectCurState = supportedTypesTable[i].autoConnectSupport;
+
+ // Seek next string
+ cursor = strchr (cursor,0) +1;
+ }
+ }
+
+ // Set current tracer Type to the last used one
+ SetCurrentTracerTypeIndex (LoadTracerPrefs ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::LoadTracesPrefs
+// ---------------------------------------------------------------------------
+
+unsigned short TracerBase::LoadTracerPrefs (void)
+{
+ int i;
+ Preference<string> prefTracerTypes (kPrefKeyTracerTypes);
+ char Type[ sizeof(supportedTypesTable[0].type) ];
+ char paramCurVal[ sizeof(supportedTypesTable[0].paramCurVal) ];
+ bool autoConnect;
+ string s = *prefTracerTypes;
+ const char* p= s.c_str ();
+
+ p = strchr (p, '<');
+
+ while (p)
+ {
+ // Skip <
+ p++;
+
+ // Extract Type name
+ i = 0;
+ while (isalnum(*p))
+ {
+ Type[i++] = *p;
+ p++;
+ }
+
+ Type[i] = 0;
+
+ // Skip ,
+ p++;
+
+ autoConnect = (*p == '1');
+
+ // Skip value + ,
+ p++;
+ p++;
+
+ // Extract parameter value
+ i = 0;
+ while (*p != '>')
+ {
+ paramCurVal[i++] = *p;
+ p++;
+ }
+ paramCurVal[i] = 0;
+
+ // Search Type in supported Types list
+ for (i=0; i<supportedTypesCount; i++)
+ {
+ if (!strcmp (Type, supportedTypesTable[i].type))
+ {
+ strcpy(supportedTypesTable[i].paramCurVal, paramCurVal);
+ supportedTypesTable[i].autoConnectCurState = autoConnect;
+ }
+ }
+
+ p = strchr (p, '<');
+ }
+
+ // Try to find which is the index of the last used tracer Type
+ Preference<string> prefLastTracerType (kPrefKeyLastTracerType);
+ string lastTypeName = *prefLastTracerType;
+
+ for (i=0; i<supportedTypesCount; i++)
+ {
+ if (lastTypeName == supportedTypesTable[i].type)
+ {
+ return i+1;
+ }
+ }
+
+ // Use nil tracer Type
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::SaveTracerPrefs
+// ---------------------------------------------------------------------------
+
+void TracerBase::SaveTracerPrefs (void)
+{
+ Preference<string> prefTracerTypes (kPrefKeyTracerTypes);
+ Preference<string> prefLastTracerType (kPrefKeyLastTracerType);
+ string s;
+ TracerTypeInfo* t;
+ int i;
+
+ char buffer[ sizeof(supportedTypesTable[0].type) + sizeof(supportedTypesTable[0].paramCurVal) + 16 ];
+
+ // Set last used Type in prefs
+ if (TracerBase::GetCurrentTracerTypeIndex ())
+ {
+ s = TracerBase::GetCurrentTracerTypeInfo()->type;
+ }
+ else
+ {
+ s = "nil";
+ }
+
+ prefLastTracerType = s;
+
+ // Save the current configuration of the tracers
+ s = "";
+
+ for (i=1; i<=TracerBase::GetTracerTypeCount(); i++)
+ {
+ t = TracerBase::GetTracerTypeInfo (i);
+
+ sprintf (buffer, "<%s,%d,%s>", t->type, t->autoConnectCurState, t->paramCurVal);
+
+ s += buffer;
+ }
+
+ prefTracerTypes = s;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ TracerBase::DisposeTracerTypeList
+// ---------------------------------------------------------------------------
+
+void TracerBase::DisposeTracerTypeList (void)
+{
+ SaveTracerPrefs ();
+
+ delete supportedTypesTable;
+
+ supportedTypesTable = 0;
+ supportedTypesCount = 0;
+}
+
diff --git a/SrcShared/TracerCommon.h b/SrcShared/TracerCommon.h
new file mode 100644
index 0000000..f8ace3e
--- /dev/null
+++ b/SrcShared/TracerCommon.h
@@ -0,0 +1,88 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _TRACER_COMMON_H_
+#define _TRACER_COMMON_H_
+
+#include <stdarg.h> // va_list
+#include <stdlib.h> // size_t
+#include "SessionFile.h" // SessionFile
+
+
+// Structures kept in memory
+struct TracerTypeInfo
+{
+ char type [8];
+ char friendlyName [32];
+ char paramDescr [32];
+ char paramDefVal [16];
+ char paramCurVal [256];
+ char paramTmpVal [256];
+ bool autoConnectSupport;
+ bool autoConnectCurState;
+ bool autoConnectTmpState;
+};
+
+class TracerBase
+{
+public:
+ TracerBase (void);
+ virtual ~TracerBase (void);
+
+ // Tracing subsystem lifecycle
+ virtual void Initialize (void) = 0;
+ virtual void Dispose (void) = 0;
+
+ // Tracer Type control
+ virtual void SetCurrentTracerTypeIndex (unsigned short tracerType, Bool paramChange = false) = 0;
+ virtual TracerTypeInfo* GetCurrentTracerTypeInfo (void);
+ virtual TracerTypeInfo* GetTracerTypeInfo (unsigned short index);
+ virtual unsigned short GetTracerTypeCount (void);
+ virtual unsigned short GetCurrentTracerTypeIndex (void);
+
+ // HostTrace* counterparts
+ virtual void InitOutputPort (void) = 0;
+ virtual void CloseOutputPort (void) = 0;
+ virtual void OutputVT (unsigned short errModule, const char* formatString, va_list args) = 0;
+ virtual void OutputVTL (unsigned short errModule, const char* formatString, va_list args) = 0;
+ virtual void OutputB (unsigned short errModule, const void* buffer, size_t bufferLen) = 0;
+
+ // User feedback
+ virtual bool IsLibraryLoaded (void) = 0;
+ virtual void GetLibraryVersionString (char* buffer, size_t bufferLen) = 0;
+ virtual unsigned long GetLibraryVersionNumber (void) { return 0; };
+ virtual long GetConnectionStatus (void) = 0;
+
+ virtual void LoadTracerTypeList (void);
+ virtual void DisposeTracerTypeList (void);
+
+ virtual void StopTracer (void) = 0;
+
+ virtual void SaveTracerPrefs (void);
+ virtual unsigned short LoadTracerPrefs (void);
+
+ virtual void GetTracerCapabilities (char* buffer, size_t* bufferLen) = 0;
+ virtual void GetCapsToken (char* src, char* tag, char* dst, size_t dstSize);
+
+protected:
+ unsigned long tracerRefCounter; // Number of referenced subsystem users
+ unsigned short supportedTypesCount;
+ unsigned short runningTracerType;
+ unsigned short previousTracerType;
+ TracerTypeInfo* supportedTypesTable;
+};
+
+#endif // _TRACER_COMMON_H_
+
+
+
diff --git a/SrcShared/TracerPlatform.h b/SrcShared/TracerPlatform.h
new file mode 100644
index 0000000..48a688e
--- /dev/null
+++ b/SrcShared/TracerPlatform.h
@@ -0,0 +1,57 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef _TRACER_PLATFORM_H_
+#define _TRACER_PLATFORM_H_
+
+#include "EmCommon.h"
+#include "TracerCommon.h"
+
+class Tracer : public TracerBase
+{
+public:
+ Tracer (void);
+ virtual ~Tracer (void);
+
+ // Tracing subsystem lifecycle
+ virtual void Initialize (void);
+ virtual void Dispose (void);
+
+ // HostTrace* counterparts
+ virtual void InitOutputPort (void);
+ virtual void CloseOutputPort (void);
+ virtual void OutputVT (unsigned short errModule, const char* formatString, va_list args);
+ virtual void OutputVTL (unsigned short errModule, const char* formatString, va_list args);
+ virtual void OutputB (unsigned short errModule, const void* buffer, size_t bufferLen);
+
+ // User feedback
+ virtual void GetLibraryVersionString (char* buffer, size_t bufferLen);
+ virtual unsigned long GetLibraryVersionNumber (void);
+ virtual long GetConnectionStatus (void);
+ virtual bool IsLibraryLoaded (void);
+
+ // Connection control
+ virtual void StopTracer (void);
+ virtual void GetTracerCapabilities (char* buffer, size_t* bufferLen);
+ virtual void SetCurrentTracerTypeIndex (unsigned short tracerType, Bool paramChange = false);
+
+#if PLATFORM_WINDOWS
+ // Connection control
+ virtual void CheckPeerStatus (void);
+#endif
+
+};
+
+extern Tracer gTracer;
+
+#endif // _TRACER_PLATFORM_H_
diff --git a/SrcShared/UAE/UAE.h b/SrcShared/UAE/UAE.h
new file mode 100644
index 0000000..83307a7
--- /dev/null
+++ b/SrcShared/UAE/UAE.h
@@ -0,0 +1,21 @@
+#ifndef UAE_h
+#define UAE_h
+
+#include "sysconfig.h" // (should really be included by sysdeps.h ...)
+#include "sysdeps.h" // uae_u8, uae_u16, uae_u32, etc.
+#include "config.h"
+#include "options.h"
+#include "machdep_m68k.h"
+#include "memory_cpu.h"
+#include "custom.h"
+#include "readcpu.h"
+#include "newcpu.h"
+#include "compiler.h"
+#include "cputbl.h"
+
+// sysdeps.h brings in assert.h. However,
+// we don't want to use assert in our application
+// so undef it. Use EmAssert instead.
+#undef assert
+
+#endif /* UAE_h */
diff --git a/SrcShared/UAE/build68k.c b/SrcShared/UAE/build68k.c
new file mode 100644
index 0000000..d3fe88a
--- /dev/null
+++ b/SrcShared/UAE/build68k.c
@@ -0,0 +1,246 @@
+/*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Read 68000 CPU specs from file "table68k" and build table68k.c
+ *
+ * Copyright 1995,1996 Bernd Schmidt
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include <assert.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "options.h"
+#include "readcpu.h"
+
+static FILE *tablef;
+static int nextch = 0;
+
+static void getnextch(void)
+{
+ do {
+ nextch = fgetc(tablef);
+ if (nextch == '%') {
+ do {
+ nextch = fgetc(tablef);
+ } while (nextch != EOF && nextch != '\n');
+ }
+ } while (nextch != EOF && isspace(nextch));
+}
+
+static int nextchtohex(void)
+{
+ switch (isupper (nextch) ? tolower (nextch) : nextch) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a': return 10;
+ case 'b': return 11;
+ case 'c': return 12;
+ case 'd': return 13;
+ case 'e': return 14;
+ case 'f': return 15;
+ default: abort();
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int no_insns = 0;
+
+ printf ("#include \"sysconfig.h\"\n");
+ printf ("#include \"sysdeps.h\"\n");
+ printf ("#include \"config.h\"\n");
+ printf ("#include \"options.h\"\n");
+ printf ("#include \"readcpu.h\"\n");
+ printf ("struct instr_def defs68k[] = {\n");
+#if 0
+ tablef = fopen("table68k","r");
+ if (tablef == NULL) {
+ fprintf(stderr, "table68k not found\n");
+ exit(1);
+ }
+#else
+ tablef = stdin;
+#endif
+ getnextch();
+ while (nextch != EOF) {
+ int cpulevel, plevel, sduse;
+ int i;
+
+ char patbits[16];
+ char opcstr[256];
+ int bitpos[16];
+ int flagset[5], flaguse[5];
+
+ unsigned int bitmask,bitpattern;
+ int n_variable;
+
+ n_variable = 0;
+ bitmask = bitpattern = 0;
+ memset (bitpos, 0, sizeof(bitpos));
+ for(i=0; i<16; i++) {
+ int currbit;
+ bitmask <<= 1;
+ bitpattern <<= 1;
+
+ switch (nextch) {
+ case '0': currbit = bit0; bitmask |= 1; break;
+ case '1': currbit = bit1; bitmask |= 1; bitpattern |= 1; break;
+ case 'c': currbit = bitc; break;
+ case 'C': currbit = bitC; break;
+ case 'f': currbit = bitf; break;
+ case 'i': currbit = biti; break;
+ case 'I': currbit = bitI; break;
+ case 'j': currbit = bitj; break;
+ case 'J': currbit = bitJ; break;
+ case 'k': currbit = bitk; break;
+ case 'K': currbit = bitK; break;
+ case 's': currbit = bits; break;
+ case 'S': currbit = bitS; break;
+ case 'd': currbit = bitd; break;
+ case 'D': currbit = bitD; break;
+ case 'r': currbit = bitr; break;
+ case 'R': currbit = bitR; break;
+ case 'z': currbit = bitz; break;
+ default: abort();
+ }
+ if (!(bitmask & 1)) {
+ bitpos[n_variable] = currbit;
+ n_variable++;
+ }
+
+ if (nextch == '0' || nextch == '1')
+ bitmask |= 1;
+ if (nextch == '1')
+ bitpattern |= 1;
+ patbits[i] = nextch;
+ getnextch();
+ }
+
+ while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
+ getnextch();
+
+ switch (nextch) {
+ case '0': cpulevel = 0; break;
+ case '1': cpulevel = 1; break;
+ case '2': cpulevel = 2; break;
+ case '3': cpulevel = 3; break;
+ case '4': cpulevel = 4; break;
+ default: abort();
+ }
+ getnextch();
+
+ switch (nextch) {
+ case '0': plevel = 0; break;
+ case '1': plevel = 1; break;
+ case '2': plevel = 2; break;
+ case '3': plevel = 3; break;
+ default: abort();
+ }
+ getnextch();
+
+ while (isspace(nextch)) /* Get flag set information */
+ getnextch();
+
+ if (nextch != ':')
+ abort();
+
+ for(i = 0; i < 5; i++) {
+ getnextch();
+ switch(nextch){
+ case '-': flagset[i] = fa_unset; break;
+ case '/': flagset[i] = fa_isjmp; break;
+ case '0': flagset[i] = fa_zero; break;
+ case '1': flagset[i] = fa_one; break;
+ case 'x': flagset[i] = fa_dontcare; break;
+ case '?': flagset[i] = fa_unknown; break;
+ default: flagset[i] = fa_set; break;
+ }
+ }
+
+ getnextch();
+ while (isspace(nextch))
+ getnextch();
+
+ if (nextch != ':') /* Get flag used information */
+ abort();
+
+ for(i = 0; i < 5; i++) {
+ getnextch();
+ switch(nextch){
+ case '-': flaguse[i] = fu_unused; break;
+ case '/': flaguse[i] = fu_isjmp; break;
+ case '+': flaguse[i] = fu_maybecc; break;
+ case '?': flaguse[i] = fu_unknown; break;
+ default: flaguse[i] = fu_used; break;
+ }
+ }
+
+ getnextch();
+ while (isspace(nextch))
+ getnextch();
+
+ if (nextch != ':') /* Get source/dest usage information */
+ abort();
+
+ getnextch();
+ sduse = nextchtohex() << 4;
+ getnextch();
+ sduse |= nextchtohex();
+
+ getnextch();
+ while (isspace(nextch))
+ getnextch();
+
+ if (nextch != ':')
+ abort();
+
+ fgets(opcstr, 250, tablef);
+ getnextch();
+ {
+ int j;
+ /* Remove superfluous spaces from the string */
+ char *opstrp = opcstr, *osendp;
+ int slen = 0;
+
+ while (isspace(*opstrp))
+ opstrp++;
+
+ osendp = opstrp;
+ while (*osendp) {
+ if (!isspace (*osendp))
+ slen = osendp - opstrp + 1;
+ osendp++;
+ }
+ opstrp[slen] = 0;
+
+ if (no_insns > 0)
+ printf(",\n");
+ no_insns++;
+ printf("{ %d, %d, {", bitpattern, n_variable);
+ for (j = 0; j < 16; j++) {
+ printf("%d", bitpos[j]);
+ if (j < 15)
+ printf(",");
+ }
+ printf ("}, %d, %d, %d, { ", bitmask, cpulevel, plevel);
+ for(i = 0; i < 5; i++) {
+ printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ',');
+ }
+ printf("}, %d, \"%s\"}", sduse, opstrp);
+ }
+ }
+ printf("};\nint n_defs68k = %d;\n", no_insns);
+ return 0;
+}
diff --git a/SrcShared/UAE/compiler.h b/SrcShared/UAE/compiler.h
new file mode 100644
index 0000000..7d49f2e
--- /dev/null
+++ b/SrcShared/UAE/compiler.h
@@ -0,0 +1,106 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * m68k -> i386 compiler
+ *
+ * (c) 1995 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void Software_ProcessLINK (uae_s32 linkSize);
+extern int Software_ProcessRTS (uaecptr dest);
+extern int Software_ProcessRTE (uaecptr newpc);
+extern int Software_ProcessJSR (uaecptr oldpc, uaecptr dest);
+extern int Software_ProcessJSR_Ind (uaecptr oldpc, uaecptr dest);
+extern void Software_CheckNewPC (uaecptr newPC);
+
+extern void Software_CheckStackPointerAssignment (void);
+extern void Software_CheckStackPointerDecrement (void);
+extern void Software_CheckStackPointerIncrement (void);
+extern void Software_CheckKernelStack (void);
+
+extern uae_u32 gStackHigh;
+extern uae_u32 gStackLowWarn;
+extern uae_u32 gStackLow;
+extern uae_u32 gKernelStackOverflowed;
+
+#define CHECK_STACK_POINTER_ASSIGNMENT() \
+do { \
+ Software_CheckStackPointerAssignment (); \
+ if (gKernelStackOverflowed) \
+ Software_CheckKernelStack (); \
+} while (0)
+
+#define CHECK_STACK_POINTER_DECREMENT() \
+do { \
+ if (m68k_areg (regs, 7) < gStackLowWarn) \
+ Software_CheckStackPointerDecrement (); \
+ if (gKernelStackOverflowed) \
+ Software_CheckKernelStack (); \
+} while (0)
+
+#define CHECK_STACK_POINTER_INCREMENT() \
+do { \
+ if (m68k_areg (regs, 7) > gStackHigh) \
+ Software_CheckStackPointerIncrement (); \
+ if (gKernelStackOverflowed) \
+ Software_CheckKernelStack (); \
+} while (0)
+
+// Called in RTD handler
+#define compiler_flush_jsr_stack() do { ; } while (0)
+
+STATIC_INLINE void m68k_do_rts(void)
+{
+ uaecptr returnAddr = get_long (m68k_areg (regs, 7));
+ if (Software_ProcessRTS (returnAddr))
+ return;
+
+ m68k_setpc(returnAddr);
+ m68k_areg(regs, 7) += 4;
+}
+
+STATIC_INLINE void m68k_do_rte(uaecptr newpc)
+{
+ if (Software_ProcessRTE(newpc))
+ return;
+
+ m68k_setpc_rte(newpc);
+}
+
+STATIC_INLINE void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
+{
+ /* CHANGED BY B. CAMERON LESIUK
+ * 19 Jan 2001
+ * Made this modification so that BSRs cause the profiler to
+ * track function calls properly.
+ */
+// Software_CheckNewPC (m68k_getpc () + offset);
+
+ if (Software_ProcessJSR (oldpc, m68k_getpc () + offset))
+ return;
+
+ m68k_areg(regs, 7) -= 4;
+ Software_CheckStackPointerDecrement ();
+ put_long(m68k_areg(regs, 7), oldpc);
+ m68k_incpc(offset);
+}
+
+STATIC_INLINE void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
+{
+ if (Software_ProcessJSR (oldpc, dest))
+ return;
+
+ m68k_areg(regs, 7) -= 4;
+ Software_CheckStackPointerDecrement ();
+ put_long(m68k_areg(regs, 7), oldpc);
+ m68k_setpc(dest);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/SrcShared/UAE/config.h b/SrcShared/UAE/config.h
new file mode 100644
index 0000000..a1f0e04
--- /dev/null
+++ b/SrcShared/UAE/config.h
@@ -0,0 +1,77 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * User configuration options
+ *
+ * Copyright 1995 - 1998 Bernd Schmidt
+ */
+
+/*
+ * Please note: Many things are configurable with command line parameters,
+ * and you can put anything you can pass on the command line into a
+ * configuration file ~/.uaerc. Please read the documentation for more
+ * information.
+ *
+ * NOTE NOTE NOTE
+ * Whenever you change something in this file, you have to "make clean"
+ * afterwards.
+ * Don't remove the '#' signs. If you want to enable something, move it out
+ * of the C comment block, if you want to disable something, move it inside
+ * the block.
+ */
+
+/*
+ * When USE_COMPILER is defined, a m68k->i386 instruction compiler will be
+ * used. This is experimental. It has only been tested on a Linux/i386 ELF
+ * machine, although it might work on other i386 Unices.
+ * This is supposed to speed up application programs. It will not work very
+ * well for hardware bangers like games and demos, in fact it will be much
+ * slower. It can also be slower for some applications and/or benchmarks.
+ * It needs a lot of tuning. Please let me know your results with this.
+ * The second define, RELY_ON_LOADSEG_DETECTION, decides how the compiler
+ * tries to detect self-modifying code. If it is not set, the first bytes
+ * of every compiled routine are used as checksum before executing the
+ * routine. If it is set, the UAE filesystem will perform some checks to
+ * detect whether an executable is being loaded. This is less reliable
+ * (it won't work if you don't use the harddisk emulation, so don't try to
+ * use floppies or even the RAM disk), but much faster.
+ *
+ * @@@ NOTE: This option is unfortunately broken in this version. Don't
+ * try to use it. @@@
+ *
+#define USE_COMPILER
+#define RELY_ON_LOADSEG_DETECTION
+ */
+
+/*
+ * Set USER_PROGRAMS_BEHAVE to 1 or 2 to indicate that you are only running
+ * non-hardware banging programs which leave all the dirty work to the
+ * Kickstart. This affects the compiler. Any program that is _not_ in the ROM
+ * (i.e. everything but the Kickstart) will use faster memory access
+ * functions.
+ * There is of course the problem that the Amiga doesn't really distinguish
+ * between user programs and the kernel. Not all of the OS is in the ROM,
+ * e.g. the parallel.device is on the disk and gets loaded into RAM at least
+ * with Kickstart 1.3 (don't know about newer Kickstarts). So you probably
+ * can't print, and some other stuff may also fail to work.
+ * A useless option, really, given the way lots of Amiga software is written.
+#define USER_PROGRAMS_BEHAVE 0
+ */
+
+/***************************************************************************
+ * Operating system/machine specific options
+ * Configure these for your CPU. The default settings should work on any
+ * machine, but may not give optimal performance everywhere.
+ * (These don't do very much yet, except HAVE_RDTSC
+ */
+
+/*
+ * Define this on PPro's, K6's and maybe other non-x86 CPUs.
+#define MULTIPLICATION_PROFITABLE
+ */
+
+/*
+ * PPros don't like branches. With this option, UAE tries to avoid them in some
+ * places.
+#define BRANCHES_ARE_EXPENSIVE
+ */
diff --git a/SrcShared/UAE/cpudefs.c b/SrcShared/UAE/cpudefs.c
new file mode 100644
index 0000000..45d4b15
--- /dev/null
+++ b/SrcShared/UAE/cpudefs.c
@@ -0,0 +1,173 @@
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include "config.h"
+#include "options.h"
+#include "readcpu.h"
+struct instr_def defs68k[] = {
+{ 60, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 16, "ORSR.B #1"},
+{ 124, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "ORSR.W #1"},
+{ 192, 8, {17,17,11,11,11,12,12,12,0,0,0,0,0,0,0,0}, 63936, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]"},
+{ 0, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "OR.z #z,d[!Areg]"},
+{ 572, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 16, "ANDSR.B #1"},
+{ 636, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "ANDSR.W #1"},
+{ 512, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "AND.z #z,d[!Areg]"},
+{ 1024, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUB.z #z,d[!Areg]"},
+{ 1536, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADD.z #z,d[!Areg]"},
+{ 1728, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]"},
+{ 1728, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "RTM s[Dreg,Areg]"},
+{ 2048, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 17, "BTST #1,s[!Areg]"},
+{ 2112, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BCHG #1,s[!Areg,Immd]"},
+{ 2176, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BCLR #1,s[!Areg,Immd]"},
+{ 2240, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BSET #1,s[!Areg,Immd]"},
+{ 2620, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 16, "EORSR.B #1"},
+{ 2684, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "EORSR.W #1"},
+{ 2560, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "EOR.z #z,d[!Areg]"},
+{ 3072, 8, {17,17,11,11,11,12,12,12,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 17, "CMP.z #z,s[!Areg,Immd]"},
+{ 2752, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]"},
+{ 3264, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]"},
+{ 3324, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "CAS2.W #2"},
+{ 3584, 8, {17,17,11,11,11,12,12,12,0,0,0,0,0,0,0,0}, 65280, 2, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]"},
+{ 3776, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]"},
+{ 3836, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "CAS2.L #2"},
+{ 256, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MVPMR.W d[Areg-Ad16],Dr"},
+{ 320, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MVPMR.L d[Areg-Ad16],Dr"},
+{ 384, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MVPRM.W Dr,d[Areg-Ad16]"},
+{ 448, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MVPRM.L Dr,d[Areg-Ad16]"},
+{ 256, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 17, "BTST Dr,s[!Areg]"},
+{ 320, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BCHG Dr,s[!Areg,Immd]"},
+{ 384, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BCLR Dr,s[!Areg,Immd]"},
+{ 448, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 0 }, { 1, 1 }, { 1, 1 } }, 19, "BSET Dr,s[!Areg,Immd]"},
+{ 4096, 12, {14,14,14,13,13,13,11,11,11,12,12,12,0,0,0,0}, 61440, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 18, "MOVE.B s,d[!Areg]"},
+{ 8192, 12, {14,14,14,13,13,13,11,11,11,12,12,12,0,0,0,0}, 61440, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MOVEA.L s,d[Areg]"},
+{ 8192, 12, {14,14,14,13,13,13,11,11,11,12,12,12,0,0,0,0}, 61440, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 18, "MOVE.L s,d[!Areg]"},
+{ 12288, 12, {14,14,14,13,13,13,11,11,11,12,12,12,0,0,0,0}, 61440, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 18, "MOVEA.W s,d[Areg]"},
+{ 12288, 12, {14,14,14,13,13,13,11,11,11,12,12,12,0,0,0,0}, 61440, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 18, "MOVE.W s,d[!Areg]"},
+{ 16384, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 0 }, { 1, 4 }, { 1, 0 }, { 1, 4 }, { 1, 0 } }, 48, "NEGX.z d[!Areg]"},
+{ 16576, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 1, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "MVSR2.W d[!Areg]"},
+{ 16896, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 2 }, { 1, 2 } }, 32, "CLR.z d[!Areg]"},
+{ 17088, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 1, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "MVSR2.B d[!Areg]"},
+{ 17408, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 48, "NEG.z d[!Areg]"},
+{ 17600, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 16, "MV2SR.B s[!Areg]"},
+{ 17920, 8, {17,17,13,13,13,14,14,14,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 48, "NOT.z d[!Areg]"},
+{ 18112, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "MV2SR.W s[!Areg]"},
+{ 18440, 3, {15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 2, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 49, "LINK.L Ar,#2"},
+{ 18432, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 0, 0 }, { 1, 5 }, { 0, 0 }, { 1, 5 }, { 1, 0 } }, 48, "NBCD.B d[!Areg]"},
+{ 18504, 3, {9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "BKPT #k"},
+{ 18496, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 48, "SWAP.W s[Dreg]"},
+{ 18496, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 0, "PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]"},
+{ 18560, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 48, "EXT.W d[Dreg]"},
+{ 18560, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 2, "MVMLE.W #1,d[!Dreg,Areg,Aipi]"},
+{ 18624, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 48, "EXT.L d[Dreg]"},
+{ 18624, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 2, "MVMLE.L #1,d[!Dreg,Areg,Aipi]"},
+{ 18880, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 48, "EXT.B d[Dreg]"},
+{ 18944, 8, {17,17,11,11,11,12,12,12,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 16, "TST.z s"},
+{ 19136, 6, {13,13,13,14,14,14,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 48, "TAS.B d[!Areg]"},
+{ 19196, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 0, "ILLEGAL"},
+{ 19456, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "MULL.L #1,s[!Areg]"},
+{ 19520, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "DIVL.L #1,s[!Areg]"},
+{ 19584, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 1, "MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]"},
+{ 19648, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 1, "MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]"},
+{ 20032, 4, {8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0}, 65520, 0, 0, { { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 } }, 16, "TRAP #J"},
+{ 20048, 3, {15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 49, "LINK.W Ar,#1"},
+{ 20056, 3, {15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 48, "UNLK.L Ar"},
+{ 20064, 3, {15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 0, 2, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 16, "MVR2USP.L Ar"},
+{ 20072, 3, {15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65528, 0, 2, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 32, "MVUSP2R.L Ar"},
+{ 20080, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 0, "RESET"},
+{ 20081, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 0, "NOP"},
+{ 20082, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 16, "STOP #1"},
+{ 20083, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 2, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 0, "RTE"},
+{ 20084, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "RTD #1"},
+{ 20085, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 0, "RTS"},
+{ 20086, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 } }, 0, "TRAPV"},
+{ 20087, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 0, "RTR"},
+{ 20090, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 1, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "MOVEC2 #1"},
+{ 20091, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 1, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "MOVE2C #1"},
+{ 20096, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 } }, 128, "JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]"},
+{ 16640, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "CHK.L s[!Areg],Dr"},
+{ 16768, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "CHK.W s[!Areg],Dr"},
+{ 20160, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 0, 0, { { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 } }, 128, "JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]"},
+{ 16832, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 2, "LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar"},
+{ 20480, 11, {7,7,7,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "ADDA.z #j,d[Areg]"},
+{ 20480, 11, {7,7,7,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADD.z #j,d[!Areg]"},
+{ 20736, 11, {7,7,7,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "SUBA.z #j,d[Areg]"},
+{ 20736, 11, {7,7,7,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUB.z #j,d[!Areg]"},
+{ 20680, 7, {2,2,2,2,15,15,15,0,0,0,0,0,0,0,0,0}, 61688, 0, 0, { { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 } }, 49, "DBcc.W Dr,#1"},
+{ 20672, 10, {2,2,2,2,13,13,13,14,14,14,0,0,0,0,0,0}, 61632, 0, 0, { { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 } }, 32, "Scc.B d[!Areg]"},
+{ 20730, 4, {2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0}, 61695, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "TRAPcc #1"},
+{ 20731, 4, {2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0}, 61695, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "TRAPcc #2"},
+{ 20732, 4, {2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0}, 61695, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 0, "TRAPcc"},
+{ 24832, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 } }, 64, "BSR.W #1"},
+{ 24832, 8, {6,6,6,6,6,6,6,6,0,0,0,0,0,0,0,0}, 65280, 0, 0, { { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 } }, 64, "BSR.B #i"},
+{ 25087, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 0, 0, { { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 }, { 4, 6 } }, 64, "BSR.L #2"},
+{ 24576, 4, {3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0}, 61695, 0, 0, { { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 } }, 64, "Bcc.W #1"},
+{ 24576, 12, {3,3,3,3,6,6,6,6,6,6,6,6,0,0,0,0}, 61440, 0, 0, { { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 } }, 64, "Bcc.B #i"},
+{ 24831, 4, {3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0}, 61695, 0, 0, { { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 }, { 2, 1 } }, 64, "Bcc.L #2"},
+{ 28672, 11, {15,15,15,5,5,5,5,5,5,5,5,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 18, "MOVE.L #i,Dr"},
+{ 32768, 11, {15,15,15,17,17,11,11,11,12,12,12,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "OR.z s[!Areg],Dr"},
+{ 32960, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "DIVU.W s[!Areg],Dr"},
+{ 33024, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 0, 0 }, { 1, 4 }, { 0, 0 }, { 1, 4 }, { 1, 0 } }, 19, "SBCD.B d[Dreg],Dr"},
+{ 33024, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 0, 0 }, { 1, 4 }, { 0, 0 }, { 1, 4 }, { 1, 0 } }, 19, "SBCD.B d[Areg-Apdi],Arp"},
+{ 33024, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "OR.z Dr,d[!Areg,Dreg]"},
+{ 33088, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 18, "PACK d[Dreg],Dr"},
+{ 33088, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 18, "PACK d[Areg-Apdi],Arp"},
+{ 33152, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 18, "UNPK d[Dreg],Dr"},
+{ 33152, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 18, "UNPK d[Areg-Apdi],Arp"},
+{ 33216, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "DIVS.W s[!Areg],Dr"},
+{ 36864, 11, {15,15,15,17,17,11,11,11,12,12,12,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUB.z s,Dr"},
+{ 37056, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "SUBA.W s,Ar"},
+{ 37120, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUBX.z d[Dreg],Dr"},
+{ 37120, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUBX.z d[Areg-Apdi],Arp"},
+{ 37120, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "SUB.z Dr,d[!Areg,Dreg]"},
+{ 37312, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "SUBA.L s,Ar"},
+{ 45056, 11, {15,15,15,17,17,11,11,11,12,12,12,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 17, "CMP.z s,Dr"},
+{ 45248, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 17, "CMPA.W s,Ar"},
+{ 45504, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 17, "CMPA.L s,Ar"},
+{ 45312, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 17, "CMPM.z d[Areg-Aipi],ArP"},
+{ 45312, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "EOR.z Dr,d[!Areg]"},
+{ 49152, 11, {15,15,15,17,17,11,11,11,12,12,12,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "AND.z s[!Areg],Dr"},
+{ 49344, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "MULU.W s[!Areg],Dr"},
+{ 49408, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 0, 0 }, { 1, 4 }, { 0, 0 }, { 1, 4 }, { 1, 0 } }, 19, "ABCD.B d[Dreg],Dr"},
+{ 49408, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 0, 0 }, { 1, 4 }, { 0, 0 }, { 1, 4 }, { 1, 0 } }, 19, "ABCD.B d[Areg-Apdi],Arp"},
+{ 49408, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "AND.z Dr,d[!Areg,Dreg]"},
+{ 49472, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 51, "EXG.L Dr,d[Dreg]"},
+{ 49472, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 51, "EXG.L Ar,d[Areg]"},
+{ 49536, 9, {15,15,15,13,13,13,14,14,14,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 51, "EXG.L Dr,d[Areg]"},
+{ 49600, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 2 } }, 19, "MULS.W s[!Areg],Dr"},
+{ 53248, 11, {15,15,15,17,17,11,11,11,12,12,12,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADD.z s,Dr"},
+{ 53440, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "ADDA.W s,Ar"},
+{ 53504, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADDX.z d[Dreg],Dr"},
+{ 53504, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 0, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADDX.z d[Areg-Apdi],Arp"},
+{ 53504, 11, {15,15,15,17,17,13,13,13,14,14,14,0,0,0,0,0}, 61696, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ADD.z Dr,d[!Areg,Dreg]"},
+{ 53696, 9, {15,15,15,11,11,11,12,12,12,0,0,0,0,0,0,0}, 61888, 0, 0, { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, 19, "ADDA.L s,Ar"},
+{ 57344, 9, {7,7,7,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ASf.z #j,DR"},
+{ 57352, 9, {7,7,7,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "LSf.z #j,DR"},
+{ 57360, 9, {7,7,7,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 0, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROXf.z #j,DR"},
+{ 57368, 9, {7,7,7,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROf.z #j,DR"},
+{ 57376, 9, {15,15,15,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 0, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ASf.z Dr,DR"},
+{ 57384, 9, {15,15,15,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 0, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "LSf.z Dr,DR"},
+{ 57392, 9, {15,15,15,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 0, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROXf.z Dr,DR"},
+{ 57400, 9, {15,15,15,4,17,17,16,16,16,0,0,0,0,0,0,0}, 61496, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROf.z Dr,DR"},
+{ 57536, 7, {4,13,13,13,14,14,14,0,0,0,0,0,0,0,0,0}, 65216, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 0 } }, 19, "ASfW.W d[!Dreg,Areg]"},
+{ 58048, 7, {4,13,13,13,14,14,14,0,0,0,0,0,0,0,0,0}, 65216, 0, 0, { { 1, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "LSfW.W d[!Dreg,Areg]"},
+{ 58560, 7, {4,13,13,13,14,14,14,0,0,0,0,0,0,0,0,0}, 65216, 0, 0, { { 0, 0 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROXfW.W d[!Dreg,Areg]"},
+{ 59072, 7, {4,13,13,13,14,14,14,0,0,0,0,0,0,0,0,0}, 65216, 0, 0, { { 1, 1 }, { 1, 0 }, { 1, 0 }, { 1, 2 }, { 1, 0 } }, 19, "ROfW.W d[!Dreg,Areg]"},
+{ 59584, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "BFTST #1,s[!Areg,Apdi,Aipi,Immd]"},
+{ 59840, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]"},
+{ 60096, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]"},
+{ 60352, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]"},
+{ 60608, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]"},
+{ 60864, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "BFFFO #1,s[!Areg,Apdi,Aipi,Immd]"},
+{ 61120, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]"},
+{ 61376, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 2, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 19, "BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]"},
+{ 61952, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "FPP #1,s"},
+{ 62016, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "FDBcc #1,s[Areg-Dreg]"},
+{ 62016, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "FScc #1,s[!Areg,Immd,PC8r,PC16]"},
+{ 62074, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "FTRAPcc #1"},
+{ 62075, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "FTRAPcc #2"},
+{ 62076, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 65535, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 0, "FTRAPcc"},
+{ 62080, 6, {10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "FBcc #K,#1"},
+{ 62144, 6, {10,10,10,10,10,10,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "FBcc #K,#2"},
+{ 62208, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 32, "FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]"},
+{ 62272, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 3, 2, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 16, "FRESTORE s[!Dreg,Areg,Apdi,Immd]"},
+{ 61440, 6, {11,11,11,12,12,12,0,0,0,0,0,0,0,0,0,0}, 65472, 4, 0, { { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 }, { 3, 5 } }, 17, "MMUOP #1,s"}};
+int n_defs68k = 166;
diff --git a/SrcShared/UAE/cpuemu.c b/SrcShared/UAE/cpuemu.c
new file mode 100644
index 0000000..5274a15
--- /dev/null
+++ b/SrcShared/UAE/cpuemu.c
@@ -0,0 +1,24243 @@
+#include "UAE.h"
+#if HAS_PROFILING
+#include "Profiling.h"
+#endif
+
+#if !defined(PART_1) && !defined(PART_2) && !defined(PART_3) && !defined(PART_4) && !defined(PART_5) && !defined(PART_6) && !defined(PART_7) && !defined(PART_8)
+#define PART_1 1
+#define PART_2 1
+#define PART_3 1
+#define PART_4 1
+#define PART_5 1
+#define PART_6 1
+#define PART_7 1
+#define PART_8 1
+#endif
+
+#ifdef PART_1
+unsigned long REGPARAM2 op_0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_10_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_18_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_20_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_28_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_30_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_38_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_39_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_3c_3(uae_u32 opcode) /* ORSR */
+{
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ src &= 0xFF;
+ regs.sr |= src;
+ MakeFromSR();
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_40_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_50_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_58_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_60_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_68_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_70_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_78_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_79_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_7c_3(uae_u32 opcode) /* ORSR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel18; }
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ regs.sr |= src;
+ MakeFromSR();
+}}}m68k_incpc(4);
+endlabel18: ;
+return 4;
+}
+unsigned long REGPARAM2 op_80_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_90_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_98_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_a0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_a8_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_b0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_b8_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_b9_3(uae_u32 opcode) /* OR */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_100_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_108_3(uae_u32 opcode) /* MVPMR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_110_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_118_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_120_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_128_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_130_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_138_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_139_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_13a_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 2;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_getpc () + 2;
+ dsta += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_13b_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 3;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_13c_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = get_ibyte(2);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_140_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_148_3(uae_u32 opcode) /* MVPMR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)
+ + (get_byte(memp + 4) << 8) + get_byte(memp + 6);
+ m68k_dreg(regs, dstreg) = (val);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_150_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_158_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_160_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_168_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_170_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_178_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_179_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_17a_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 2;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_getpc () + 2;
+ dsta += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_17b_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 3;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_180_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_188_3(uae_u32 opcode) /* MVPRM */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+ uaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ put_byte(memp, src >> 8); put_byte(memp + 2, src);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_190_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_198_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1a0_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1a8_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1b0_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1b8_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1b9_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_1ba_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 2;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_getpc () + 2;
+ dsta += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1bb_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 3;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1c0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_1c8_3(uae_u32 opcode) /* MVPRM */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+ uaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ put_byte(memp, src >> 24); put_byte(memp + 2, src >> 16);
+ put_byte(memp + 4, src >> 8); put_byte(memp + 6, src);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_1d0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1d8_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1e0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1e8_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1f0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1f8_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1f9_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_1fa_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 2;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_getpc () + 2;
+ dsta += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1fb_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = 3;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_200_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_210_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_218_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_220_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_228_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_230_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_238_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_239_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_23c_3(uae_u32 opcode) /* ANDSR */
+{
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ src |= 0xFF00;
+ regs.sr &= src;
+ MakeFromSR();
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_240_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_250_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_258_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_260_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_268_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_270_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_278_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_279_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_27c_3(uae_u32 opcode) /* ANDSR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel89; }
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ regs.sr &= src;
+ MakeFromSR();
+}}}m68k_incpc(4);
+endlabel89: ;
+return 4;
+}
+unsigned long REGPARAM2 op_280_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_290_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_298_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_2a0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_2a8_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_2b0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_2b8_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_2b9_3(uae_u32 opcode) /* AND */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_400_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_410_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_418_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_420_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_428_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_430_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_438_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_439_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_440_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_450_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_458_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_460_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_468_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_470_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_478_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_479_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_480_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_490_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_498_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_4a0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_4a8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_4b0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_4b8_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_4b9_3(uae_u32 opcode) /* SUB */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_600_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_610_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_618_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_620_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_628_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_630_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_638_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_639_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_640_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_650_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_658_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_660_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_668_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_670_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_678_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_679_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_680_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_690_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_698_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_6a0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_6a8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_6b0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_6b8_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_6b9_3(uae_u32 opcode) /* ADD */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_800_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_810_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_818_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_820_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_828_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_830_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_838_3(uae_u32 opcode) /* BTST */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_839_3(uae_u32 opcode) /* BTST */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(8);
+return 10;
+}
+unsigned long REGPARAM2 op_83a_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_83b_3(uae_u32 opcode) /* BTST */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_83c_3(uae_u32 opcode) /* BTST */
+{
+{{ uae_s16 src = get_iword(2);
+{ uae_s8 dst = get_ibyte(4);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_840_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_850_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_858_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_860_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_868_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_870_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_878_3(uae_u32 opcode) /* BCHG */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_879_3(uae_u32 opcode) /* BCHG */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_87a_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_87b_3(uae_u32 opcode) /* BCHG */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ dst ^= (1 << src);
+ SET_ZFLG ((dst >> src) & 1);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_880_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_890_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_898_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8a0_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8a8_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8b0_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8b8_3(uae_u32 opcode) /* BCLR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8b9_3(uae_u32 opcode) /* BCLR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_8ba_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8bb_3(uae_u32 opcode) /* BCLR */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst &= ~(1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8c0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= 31;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ m68k_dreg(regs, dstreg) = (dst);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_8d0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8d8_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8e0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8e8_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8f0_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8f8_3(uae_u32 opcode) /* BSET */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8f9_3(uae_u32 opcode) /* BSET */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_8fa_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8fb_3(uae_u32 opcode) /* BSET */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src &= 7;
+ SET_ZFLG (1 ^ ((dst >> src) & 1));
+ dst |= (1 << src);
+ put_byte(dsta,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a00_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_a10_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a18_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a20_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a28_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a30_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a38_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a39_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_a3c_3(uae_u32 opcode) /* EORSR */
+{
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ src &= 0xFF;
+ regs.sr ^= src;
+ MakeFromSR();
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_a40_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_a50_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a58_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a60_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_a68_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a70_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+#endif
+
+#ifdef PART_2
+unsigned long REGPARAM2 op_a78_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_a79_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_a7c_3(uae_u32 opcode) /* EORSR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel204; }
+{ MakeSR();
+{ uae_s16 src = get_iword(2);
+ regs.sr ^= src;
+ MakeFromSR();
+}}}m68k_incpc(4);
+endlabel204: ;
+return 4;
+}
+unsigned long REGPARAM2 op_a80_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_a90_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_a98_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_aa0_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_aa8_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_ab0_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_ab8_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_ab9_3(uae_u32 opcode) /* EOR */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_c00_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_c10_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c18_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c20_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c28_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c30_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c38_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c39_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 10;
+}
+unsigned long REGPARAM2 op_c3a_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c3b_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c40_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_c50_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c58_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c60_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c68_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c70_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c78_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c79_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 10;
+}
+unsigned long REGPARAM2 op_c7a_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_getpc () + 4;
+ dsta += (uae_s32)(uae_s16)get_iword(4);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c7b_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(4));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c80_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_c90_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_c98_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_ca0_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_ca8_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_cb0_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_cb8_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_cb9_3(uae_u32 opcode) /* CMP */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(10);
+return 14;
+}
+unsigned long REGPARAM2 op_cba_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 2;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_getpc () + 6;
+ dsta += (uae_s32)(uae_s16)get_iword(6);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_cbb_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = 3;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr tmppc = m68k_getpc() + 6;
+ uaecptr dsta = get_disp_ea_000(tmppc, get_iword(6));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_1000_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_1010_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_1018_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_1020_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_1028_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1030_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1038_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1039_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_103a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_103b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_103c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_1080_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_1090_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1098_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_10a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_10a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_10ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_10c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_10d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_10d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_10e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_10e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10f8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10f9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_10fa_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10fb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_10fc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1100_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_1110_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1118_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1120_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_1128_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1130_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1138_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1139_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_113a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_113b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_113c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1140_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1150_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1158_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1160_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1168_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_1170_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_1178_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_1179_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_117a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_117b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_117c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_1180_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_1190_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_1198_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_11a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_11a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_11ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_11c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_11d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_11d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_11e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_11e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_11fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_11fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_13c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_13d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_13d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_13e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_13e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_13f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_13f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_13f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(10);
+return 14;
+}
+unsigned long REGPARAM2 op_13fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_13fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_13fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s8 src = get_ibyte(2);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}m68k_incpc(8);
+return 10;
+}
+unsigned long REGPARAM2 op_2000_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_2008_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_2010_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2018_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2020_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2028_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2030_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2038_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2039_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_203a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_203b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_203c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_2040_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_2048_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_2050_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2058_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2060_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2068_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2070_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2078_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2079_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_207a_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_207b_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_207c_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_u32 val = src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_2080_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2088_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2090_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_2098_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_20a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_20a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_20ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_20c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_20c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_20d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_20d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_20e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_20e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20f8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20f9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_20fa_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20fb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_20fc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_2100_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2108_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_2110_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_2118_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_2120_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_2128_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2130_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2138_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2139_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_213a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_213b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+#endif
+
+#ifdef PART_3
+unsigned long REGPARAM2 op_213c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_2140_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2148_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2150_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2158_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2160_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2168_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_2170_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_2178_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_2179_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_217a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_217b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_217c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_2180_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2188_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_2190_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_2198_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_21a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_21a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_21ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_21c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_21c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_21d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_21d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_21e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_21e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_21fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_21fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_23c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_23c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_23d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_23d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_23e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_23e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_23f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_23f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_23f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(10);
+return 18;
+}
+unsigned long REGPARAM2 op_23fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_23fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(8);
+return 16;
+}
+unsigned long REGPARAM2 op_23fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s32 src = get_ilong(2);
+{ uaecptr dsta = get_ilong(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}m68k_incpc(10);
+return 14;
+}
+unsigned long REGPARAM2 op_3000_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_3008_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_3010_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3018_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3020_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3028_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3030_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3038_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3039_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_303a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_303b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_303c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_3040_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_3048_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_3050_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3058_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3060_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3068_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3070_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3078_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3079_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_307a_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_307b_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_307c_3(uae_u32 opcode) /* MOVEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_u32 val = (uae_s32)(uae_s16)src;
+ m68k_areg(regs, dstreg) = (val);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_3080_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3088_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3090_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_3098_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_30a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_30a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_30ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_30c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_30c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_30d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_30d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_30e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_30e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30f8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30f9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_30fa_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30fb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_30fc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3100_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3108_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_3110_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_3118_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_3120_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_3128_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3130_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3138_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3139_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_313a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_313b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_313c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3140_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3148_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3150_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3158_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3160_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3168_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_3170_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_3178_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_3179_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_317a_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_317b_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_317c_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_3180_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3188_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_3190_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_3198_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_31a0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_31a8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31b0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31b8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31b9_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(6));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_31ba_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31bb_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31bc_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_31c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_31c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_31d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_31d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_31e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_31e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_31fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_31fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_33c0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_33c8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_33d0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_33d8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_33e0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_33e8_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_33f0_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_33f8_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_33f9_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(6);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(10);
+return 14;
+}
+unsigned long REGPARAM2 op_33fa_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_33fb_3(uae_u32 opcode) /* MOVE */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(8);
+return 12;
+}
+unsigned long REGPARAM2 op_33fc_3(uae_u32 opcode) /* MOVE */
+{
+{{ uae_s16 src = get_iword(2);
+{ uaecptr dsta = get_ilong(4);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}m68k_incpc(8);
+return 10;
+}
+unsigned long REGPARAM2 op_4000_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((newv) & 0xff);
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4010_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4018_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4020_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4028_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4030_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4038_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4039_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4040_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4050_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4058_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4060_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4068_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4070_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4078_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4079_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(srca,newv);
+}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4080_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, srcreg) = (newv);
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4090_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_4098_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_40a0_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_40a8_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_40b0_3(uae_u32 opcode) /* NEGX */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_40b8_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_40b9_3(uae_u32 opcode) /* NEGX */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(srca,newv);
+}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_40c0_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ MakeSR();
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((regs.sr) & 0xffff);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_40d0_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_40d8_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += 2;
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_40e0_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_40e8_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_40f0_3(uae_u32 opcode) /* MVSR2 */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_40f8_3(uae_u32 opcode) /* MVSR2 */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_40f9_3(uae_u32 opcode) /* MVSR2 */
+{
+{{ uaecptr srca = get_ilong(2);
+ MakeSR();
+ put_word(srca,regs.sr);
+}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_4100_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel579; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel579; }
+}}}m68k_incpc(2);
+endlabel579: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4110_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel580; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel580; }
+}}}}m68k_incpc(2);
+endlabel580: ;
+return 6;
+}
+unsigned long REGPARAM2 op_4118_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel581; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel581; }
+}}}}m68k_incpc(2);
+endlabel581: ;
+return 6;
+}
+unsigned long REGPARAM2 op_4120_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel582; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel582; }
+}}}}m68k_incpc(2);
+endlabel582: ;
+return 6;
+}
+unsigned long REGPARAM2 op_4128_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel583; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel583; }
+}}}}m68k_incpc(4);
+endlabel583: ;
+return 8;
+}
+unsigned long REGPARAM2 op_4130_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel584; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel584; }
+}}}}m68k_incpc(4);
+endlabel584: ;
+return 8;
+}
+unsigned long REGPARAM2 op_4138_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel585; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel585; }
+}}}}m68k_incpc(4);
+endlabel585: ;
+return 8;
+}
+unsigned long REGPARAM2 op_4139_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel586; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel586; }
+}}}}m68k_incpc(6);
+endlabel586: ;
+return 10;
+}
+unsigned long REGPARAM2 op_413a_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel587; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel587; }
+}}}}m68k_incpc(4);
+endlabel587: ;
+return 8;
+}
+unsigned long REGPARAM2 op_413b_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel588; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel588; }
+}}}}m68k_incpc(4);
+endlabel588: ;
+return 8;
+}
+unsigned long REGPARAM2 op_413c_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel589; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel589; }
+}}}m68k_incpc(6);
+endlabel589: ;
+return 6;
+}
+unsigned long REGPARAM2 op_4180_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel590; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel590; }
+}}}m68k_incpc(2);
+endlabel590: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4190_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel591; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel591; }
+}}}}m68k_incpc(2);
+endlabel591: ;
+return 4;
+}
+unsigned long REGPARAM2 op_4198_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel592; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel592; }
+}}}}m68k_incpc(2);
+endlabel592: ;
+return 4;
+}
+unsigned long REGPARAM2 op_41a0_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel593; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel593; }
+}}}}m68k_incpc(2);
+endlabel593: ;
+return 4;
+}
+unsigned long REGPARAM2 op_41a8_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel594; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel594; }
+}}}}m68k_incpc(4);
+endlabel594: ;
+return 6;
+}
+unsigned long REGPARAM2 op_41b0_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel595; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel595; }
+}}}}m68k_incpc(4);
+endlabel595: ;
+return 6;
+}
+unsigned long REGPARAM2 op_41b8_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel596; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel596; }
+}}}}m68k_incpc(4);
+endlabel596: ;
+return 6;
+}
+unsigned long REGPARAM2 op_41b9_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel597; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel597; }
+}}}}m68k_incpc(6);
+endlabel597: ;
+return 8;
+}
+unsigned long REGPARAM2 op_41ba_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel598; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel598; }
+}}}}m68k_incpc(4);
+endlabel598: ;
+return 6;
+}
+unsigned long REGPARAM2 op_41bb_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel599; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel599; }
+}}}}m68k_incpc(4);
+endlabel599: ;
+return 6;
+}
+unsigned long REGPARAM2 op_41bc_3(uae_u32 opcode) /* CHK */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ if ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto endlabel600; }
+ else if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto endlabel600; }
+}}}m68k_incpc(4);
+endlabel600: ;
+return 4;
+}
+unsigned long REGPARAM2 op_41d0_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{{ uaecptr prev_dstreg = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) {
+ if (srcreg == 7) {
+ if (prev_dstreg < (srca)) CHECK_STACK_POINTER_INCREMENT ();
+ if (prev_dstreg > (srca)) CHECK_STACK_POINTER_DECREMENT ();
+ } else {
+ CHECK_STACK_POINTER_ASSIGNMENT ();
+ }
+ }
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_41e8_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{{ uaecptr prev_dstreg = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) {
+ if (srcreg == 7) {
+ if (prev_dstreg < (srca)) CHECK_STACK_POINTER_INCREMENT ();
+ if (prev_dstreg > (srca)) CHECK_STACK_POINTER_DECREMENT ();
+ } else {
+ CHECK_STACK_POINTER_ASSIGNMENT ();
+ }
+ }
+}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_41f0_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{{ uaecptr prev_dstreg = m68k_areg(regs, dstreg);
+ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) {
+ if (srcreg == 7) {
+ if (prev_dstreg < (srca)) CHECK_STACK_POINTER_INCREMENT ();
+ if (prev_dstreg > (srca)) CHECK_STACK_POINTER_DECREMENT ();
+ } else {
+ CHECK_STACK_POINTER_ASSIGNMENT ();
+ }
+ }
+}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_41f8_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_41f9_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_41fa_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_41fb_3(uae_u32 opcode) /* LEA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ m68k_areg(regs, dstreg) = (srca);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4200_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((0) & 0xff);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4210_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4218_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4220_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4228_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4230_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4238_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4239_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(0)) == 0);
+ SET_NFLG (((uae_s8)(0)) < 0);
+ put_byte(srca,0);
+}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_4240_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((0) & 0xffff);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4250_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4258_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4260_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4268_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+#endif
+
+#ifdef PART_4
+unsigned long REGPARAM2 op_4270_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4278_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4279_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(0)) == 0);
+ SET_NFLG (((uae_s16)(0)) < 0);
+ put_word(srca,0);
+}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_4280_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ m68k_dreg(regs, srcreg) = (0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4290_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4298_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_42a0_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_42a8_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_42b0_3(uae_u32 opcode) /* CLR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_42b8_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_42b9_3(uae_u32 opcode) /* CLR */
+{
+{{ uaecptr srca = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(0)) == 0);
+ SET_NFLG (((uae_s32)(0)) < 0);
+ put_long(srca,0);
+}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4400_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((dst) & 0xff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4410_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4418_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4420_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4428_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4430_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4438_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4439_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{{uae_u32 dst = ((uae_s8)(0)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(0)) < 0;
+ int flgn = ((uae_s8)(dst)) < 0;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(srca,dst);
+}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4440_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((dst) & 0xffff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4450_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4458_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4460_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4468_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4470_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4478_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4479_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{{uae_u32 dst = ((uae_s16)(0)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(0)) < 0;
+ int flgn = ((uae_s16)(dst)) < 0;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(srca,dst);
+}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4480_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, srcreg) = (dst);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4490_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_4498_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_44a0_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_44a8_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_44b0_3(uae_u32 opcode) /* NEG */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_44b8_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_44b9_3(uae_u32 opcode) /* NEG */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{{uae_u32 dst = ((uae_s32)(0)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(0)) < 0;
+ int flgn = ((uae_s32)(dst)) < 0;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(0)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(srca,dst);
+}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_44c0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_44d0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_44d8_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_44e0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_44e8_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_44f0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_44f8_3(uae_u32 opcode) /* MV2SR */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_44f9_3(uae_u32 opcode) /* MV2SR */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_44fa_3(uae_u32 opcode) /* MV2SR */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_44fb_3(uae_u32 opcode) /* MV2SR */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_44fc_3(uae_u32 opcode) /* MV2SR */
+{
+{{ uae_s16 src = get_iword(2);
+ MakeSR();
+ regs.sr &= 0xFF00;
+ regs.sr |= src & 0xFF;
+ MakeFromSR();
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4600_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((dst) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4610_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4618_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4620_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4628_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4630_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4638_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4639_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(dst)) == 0);
+ SET_NFLG (((uae_s8)(dst)) < 0);
+ put_byte(srca,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4640_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((dst) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4650_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4658_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4660_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4668_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4670_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4678_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4679_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ put_word(srca,dst);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4680_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4690_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_4698_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_46a0_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_46a8_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_46b0_3(uae_u32 opcode) /* NOT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_46b8_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_46b9_3(uae_u32 opcode) /* NOT */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_u32 dst = ~src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ put_long(srca,dst);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_46c0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel691; }
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+ regs.sr = src;
+ MakeFromSR();
+}}}m68k_incpc(2);
+endlabel691: ;
+return 2;
+}
+unsigned long REGPARAM2 op_46d0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel692; }
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(2);
+endlabel692: ;
+return 4;
+}
+unsigned long REGPARAM2 op_46d8_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel693; }
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(2);
+endlabel693: ;
+return 4;
+}
+unsigned long REGPARAM2 op_46e0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel694; }
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(2);
+endlabel694: ;
+return 4;
+}
+unsigned long REGPARAM2 op_46e8_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel695; }
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(4);
+endlabel695: ;
+return 6;
+}
+unsigned long REGPARAM2 op_46f0_3(uae_u32 opcode) /* MV2SR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel696; }
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(4);
+endlabel696: ;
+return 6;
+}
+unsigned long REGPARAM2 op_46f8_3(uae_u32 opcode) /* MV2SR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel697; }
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(4);
+endlabel697: ;
+return 6;
+}
+unsigned long REGPARAM2 op_46f9_3(uae_u32 opcode) /* MV2SR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel698; }
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(6);
+endlabel698: ;
+return 8;
+}
+unsigned long REGPARAM2 op_46fa_3(uae_u32 opcode) /* MV2SR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel699; }
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(4);
+endlabel699: ;
+return 6;
+}
+unsigned long REGPARAM2 op_46fb_3(uae_u32 opcode) /* MV2SR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel700; }
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+ regs.sr = src;
+ MakeFromSR();
+}}}}m68k_incpc(4);
+endlabel700: ;
+return 6;
+}
+unsigned long REGPARAM2 op_46fc_3(uae_u32 opcode) /* MV2SR */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel701; }
+{{ uae_s16 src = get_iword(2);
+ regs.sr = src;
+ MakeFromSR();
+}}}m68k_incpc(4);
+endlabel701: ;
+return 4;
+}
+unsigned long REGPARAM2 op_4800_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((newv) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4810_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4818_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4820_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4828_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4830_3(uae_u32 opcode) /* NBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4838_3(uae_u32 opcode) /* NBCD */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4839_3(uae_u32 opcode) /* NBCD */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(srca,newv);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4840_3(uae_u32 opcode) /* SWAP */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4850_3(uae_u32 opcode) /* PEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4868_3(uae_u32 opcode) /* PEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4870_3(uae_u32 opcode) /* PEA */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4878_3(uae_u32 opcode) /* PEA */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4879_3(uae_u32 opcode) /* PEA */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_487a_3(uae_u32 opcode) /* PEA */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_487b_3(uae_u32 opcode) /* PEA */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uaecptr dsta = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = dsta;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+ put_long(dsta,srca);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4880_3(uae_u32 opcode) /* EXT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u16 dst = (uae_s16)(uae_s8)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(dst)) == 0);
+ SET_NFLG (((uae_s16)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | ((dst) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4890_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_word(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { put_word(srca, m68k_areg(regs, movem_index1[amask])); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_48a0_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg) - 0;
+{ uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;
+ m68k_areg(regs, dstreg) -= 16*2;
+ while (amask) { srca -= 2; put_word(srca, m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }
+ while (dmask) { srca -= 2; put_word(srca, m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }
+ m68k_areg(regs, dstreg) = srca;
+ CHECK_STACK_POINTER_DECREMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_48a8_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_word(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { put_word(srca, m68k_areg(regs, movem_index1[amask])); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48b0_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_word(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { put_word(srca, m68k_areg(regs, movem_index1[amask])); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48b8_3(uae_u32 opcode) /* MVMLE */
+{
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_word(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { put_word(srca, m68k_areg(regs, movem_index1[amask])); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48b9_3(uae_u32 opcode) /* MVMLE */
+{
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = get_ilong(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_word(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { put_word(srca, m68k_areg(regs, movem_index1[amask])); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(8);
+return 8;
+}
+unsigned long REGPARAM2 op_48c0_3(uae_u32 opcode) /* EXT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_48d0_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_long(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { put_long(srca, m68k_areg(regs, movem_index1[amask])); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_48e0_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg) - 0;
+{ uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;
+ m68k_areg(regs, dstreg) -= 16*4;
+ while (amask) { srca -= 4; put_long(srca, m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }
+ while (dmask) { srca -= 4; put_long(srca, m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }
+ m68k_areg(regs, dstreg) = srca;
+ CHECK_STACK_POINTER_DECREMENT ();
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_48e8_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_long(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { put_long(srca, m68k_areg(regs, movem_index1[amask])); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48f0_3(uae_u32 opcode) /* MVMLE */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_long(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { put_long(srca, m68k_areg(regs, movem_index1[amask])); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48f8_3(uae_u32 opcode) /* MVMLE */
+{
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_long(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { put_long(srca, m68k_areg(regs, movem_index1[amask])); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_48f9_3(uae_u32 opcode) /* MVMLE */
+{
+{ uae_u16 mask = get_iword(2);
+{ uaecptr srca = get_ilong(4);
+{ uae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+ while (dmask) { put_long(srca, m68k_dreg(regs, movem_index1[dmask])); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { put_long(srca, m68k_areg(regs, movem_index1[amask])); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(8);
+return 8;
+}
+unsigned long REGPARAM2 op_49c0_3(uae_u32 opcode) /* EXT */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_u32 dst = (uae_s32)(uae_s8)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(dst)) == 0);
+ SET_NFLG (((uae_s32)(dst)) < 0);
+ m68k_dreg(regs, srcreg) = (dst);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a00_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a10_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a18_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a20_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a28_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a30_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a38_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a39_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_4a3a_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a3b_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a3c_3(uae_u32 opcode) /* TST */
+{
+{{ uae_s8 src = get_ibyte(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4a40_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a48_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a50_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a58_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a60_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_4a68_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a70_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a78_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a79_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_4a7a_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a7b_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_4a7c_3(uae_u32 opcode) /* TST */
+{
+{{ uae_s16 src = get_iword(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4a80_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a88_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4a90_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4a98_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4aa0_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4aa8_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4ab0_3(uae_u32 opcode) /* TST */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4ab8_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4ab9_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4aba_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4abb_3(uae_u32 opcode) /* TST */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4abc_3(uae_u32 opcode) /* TST */
+{
+{{ uae_s32 src = get_ilong(2);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4ac0_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((src) & 0xff);
+}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4ad0_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4ad8_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4ae0_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4ae8_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4af0_3(uae_u32 opcode) /* TAS */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4af8_3(uae_u32 opcode) /* TAS */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4af9_3(uae_u32 opcode) /* TAS */
+{
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ src |= 0x80;
+ put_byte(srca,src);
+}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_4c90_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4c98_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+ m68k_areg(regs, dstreg) = srca;
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4ca8_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cb0_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cb8_3(uae_u32 opcode) /* MVMEL */
+{
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cb9_3(uae_u32 opcode) /* MVMEL */
+{
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = get_ilong(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(8);
+return 8;
+}
+unsigned long REGPARAM2 op_4cba_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = 2;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_getpc () + 4;
+ srca += (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cbb_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = 3;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(4));
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = (uae_s32)(uae_s16)get_word(srca); srca += 2; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cd0_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4cd8_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+ m68k_areg(regs, dstreg) = srca;
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_4ce8_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cf0_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = opcode & 7;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(4));
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cf8_3(uae_u32 opcode) /* MVMEL */
+{
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cf9_3(uae_u32 opcode) /* MVMEL */
+{
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = get_ilong(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(8);
+return 8;
+}
+unsigned long REGPARAM2 op_4cfa_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = 2;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr srca = m68k_getpc () + 4;
+ srca += (uae_s32)(uae_s16)get_iword(4);
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4cfb_3(uae_u32 opcode) /* MVMEL */
+{
+ uae_u32 dstreg = 3;
+{ uae_u16 mask = get_iword(2);
+ unsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;
+{ uaecptr tmppc = m68k_getpc() + 4;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(4));
+{ while (dmask) { m68k_dreg(regs, movem_index1[dmask]) = get_long(srca); srca += 4; dmask = movem_next[dmask]; }
+ while (amask) { m68k_areg(regs, movem_index1[amask]) = get_long(srca); srca += 4; amask = movem_next[amask]; }
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_4e40_3(uae_u32 opcode) /* TRAP */
+{
+ uae_u32 srcreg = (opcode & 15);
+{{ uae_u32 src = srcreg;
+m68k_incpc(2);
+ Exception(src+32,0);
+}}return 2;
+}
+unsigned long REGPARAM2 op_4e50_3(uae_u32 opcode) /* LINK */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr olda = m68k_areg(regs, 7) - 4;
+ m68k_areg (regs, 7) = olda;
+ if (7 == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 src = m68k_areg(regs, srcreg);
+ put_long(olda,src);
+ m68k_areg(regs, srcreg) = (m68k_areg(regs, 7));
+ if (srcreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+{ uae_s16 offs = get_iword(2);
+ m68k_areg(regs, 7) += offs;
+ CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_4e58_3(uae_u32 opcode) /* UNLK */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+ m68k_areg(regs, 7) = src;
+ CHECK_STACK_POINTER_INCREMENT ();
+{ uaecptr olda = m68k_areg(regs, 7);
+{ uae_s32 old = get_long(olda);
+ m68k_areg(regs, 7) += 4;
+ m68k_areg(regs, srcreg) = (old);
+ if (srcreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_4e60_3(uae_u32 opcode) /* MVR2USP */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel795; }
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+ regs.usp = src;
+}}}m68k_incpc(2);
+endlabel795: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4e68_3(uae_u32 opcode) /* MVUSP2R */
+{
+ uae_u32 srcreg = (opcode & 7);
+{if (!regs.s) { Exception(8,0); goto endlabel796; }
+{{ m68k_areg(regs, srcreg) = (regs.usp);
+ if (srcreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+endlabel796: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4e70_3(uae_u32 opcode) /* RESET */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel797; }
+{ customreset();
+}}m68k_incpc(2);
+endlabel797: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4e71_3(uae_u32 opcode) /* NOP */
+{
+{}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_4e72_3(uae_u32 opcode) /* STOP */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel799; }
+{{ uae_s16 src = get_iword(2);
+ regs.sr = src;
+ MakeFromSR();
+ m68k_setstopped(1);
+}}}m68k_incpc(4);
+endlabel799: ;
+return 4;
+}
+unsigned long REGPARAM2 op_4e73_3(uae_u32 opcode) /* RTE */
+{
+{if (!regs.s) { Exception(8,0); goto endlabel800; }
+{{ uaecptr sra = m68k_areg(regs, 7);
+{ uae_s16 sr = get_word(sra);
+ m68k_areg(regs, 7) += 2;
+{ uaecptr pca = m68k_areg(regs, 7);
+{ uae_s32 pc = get_long(pca);
+ m68k_areg(regs, 7) += 4;
+ regs.sr = sr; m68k_do_rte(pc);
+ MakeFromSR();
+}}}}}}endlabel800: ;
+return 8;
+}
+unsigned long REGPARAM2 op_4e74_3(uae_u32 opcode) /* RTD */
+{
+{ compiler_flush_jsr_stack();
+{ uaecptr pca = m68k_areg(regs, 7);
+{ uae_s32 pc = get_long(pca);
+ m68k_areg(regs, 7) += 4;
+{ uae_s16 offs = get_iword(2);
+ m68k_areg(regs, 7) += offs;
+ m68k_setpc_rte(pc);
+}}}}return 8;
+}
+unsigned long REGPARAM2 op_4e75_3(uae_u32 opcode) /* RTS */
+{
+{ m68k_do_rts();
+}return 2;
+}
+unsigned long REGPARAM2 op_4e76_3(uae_u32 opcode) /* TRAPV */
+{
+{m68k_incpc(2);
+ if (GET_VFLG) { Exception(7,m68k_getpc()); goto endlabel803; }
+}endlabel803: ;
+return 2;
+}
+unsigned long REGPARAM2 op_4e77_3(uae_u32 opcode) /* RTR */
+{
+{ compiler_flush_jsr_stack();
+ MakeSR();
+{ uaecptr sra = m68k_areg(regs, 7);
+{ uae_s16 sr = get_word(sra);
+ m68k_areg(regs, 7) += 2;
+{ uaecptr pca = m68k_areg(regs, 7);
+{ uae_s32 pc = get_long(pca);
+ m68k_areg(regs, 7) += 4;
+ regs.sr &= 0xFF00; sr &= 0xFF;
+ regs.sr |= sr; m68k_setpc(pc);
+ MakeFromSR();
+}}}}}return 8;
+}
+unsigned long REGPARAM2 op_4e90_3(uae_u32 opcode) /* JSR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+if (!Software_ProcessJSR_Ind (m68k_getpc(), srca))
+ m68k_do_jsr(m68k_getpc() + 2, srca);
+}}return 2;
+}
+unsigned long REGPARAM2 op_4ea8_3(uae_u32 opcode) /* JSR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ m68k_do_jsr(m68k_getpc() + 4, srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4eb0_3(uae_u32 opcode) /* JSR */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ m68k_do_jsr(m68k_getpc() + 4, srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4eb8_3(uae_u32 opcode) /* JSR */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ m68k_do_jsr(m68k_getpc() + 4, srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4eb9_3(uae_u32 opcode) /* JSR */
+{
+{{ uaecptr srca = get_ilong(2);
+ m68k_do_jsr(m68k_getpc() + 6, srca);
+}}return 6;
+}
+unsigned long REGPARAM2 op_4eba_3(uae_u32 opcode) /* JSR */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+ m68k_do_jsr(m68k_getpc() + 4, srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4ebb_3(uae_u32 opcode) /* JSR */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+ m68k_do_jsr(m68k_getpc() + 4, srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4ed0_3(uae_u32 opcode) /* JMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_setpc(srca);
+}}return 2;
+}
+unsigned long REGPARAM2 op_4ee8_3(uae_u32 opcode) /* JMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+ m68k_setpc(srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4ef0_3(uae_u32 opcode) /* JMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+ m68k_setpc(srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4ef8_3(uae_u32 opcode) /* JMP */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+ m68k_setpc(srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4ef9_3(uae_u32 opcode) /* JMP */
+{
+{{ uaecptr srca = get_ilong(2);
+ m68k_setpc(srca);
+}}return 6;
+}
+unsigned long REGPARAM2 op_4efa_3(uae_u32 opcode) /* JMP */
+{
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+ m68k_setpc(srca);
+}}return 4;
+}
+unsigned long REGPARAM2 op_4efb_3(uae_u32 opcode) /* JMP */
+{
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+ m68k_setpc(srca);
+}}return 4;
+}
+#endif
+
+#ifdef PART_5
+unsigned long REGPARAM2 op_5000_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5010_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5018_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5020_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5028_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5030_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5038_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5039_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_5040_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5048_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5050_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5058_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5060_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5068_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5070_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5078_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5079_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_5080_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5088_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5090_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_5098_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_50a0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_50a8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_50b0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_50b8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_50b9_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_50c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(0) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_50c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(0)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel846;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel846: ;
+return 4;
+}
+unsigned long REGPARAM2 op_50d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_50d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_50e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_50e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_50f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_50f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_50f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(0) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5100_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5110_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5118_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5120_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5128_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5130_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5138_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5139_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_5140_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5148_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5150_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5158_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5160_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_5168_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5170_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5178_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_5179_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_5180_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5188_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5190_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_5198_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_51a0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_51a8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_51b0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_51b8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_51b9_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+{{ uae_u32 src = srcreg;
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_51c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(1) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_51c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(1)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel881;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel881: ;
+return 4;
+}
+unsigned long REGPARAM2 op_51d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_51d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_51e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_51e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_51f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_51f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_51f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(1) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_52c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(2) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_52c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(2)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel890;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel890: ;
+return 4;
+}
+unsigned long REGPARAM2 op_52d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_52d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_52e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_52e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_52f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_52f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_52f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(2) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_53c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(3) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_53c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(3)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel899;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel899: ;
+return 4;
+}
+unsigned long REGPARAM2 op_53d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_53d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_53e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_53e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_53f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_53f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_53f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(3) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_54c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(4) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_54c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(4)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel908;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel908: ;
+return 4;
+}
+unsigned long REGPARAM2 op_54d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_54d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_54e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_54e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_54f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_54f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_54f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(4) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_55c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(5) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_55c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(5)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel917;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel917: ;
+return 4;
+}
+unsigned long REGPARAM2 op_55d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_55d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_55e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_55e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_55f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_55f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_55f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(5) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_56c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(6) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_56c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(6)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel926;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel926: ;
+return 4;
+}
+unsigned long REGPARAM2 op_56d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_56d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_56e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_56e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_56f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_56f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_56f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(6) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_57c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(7) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_57c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(7)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel935;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel935: ;
+return 4;
+}
+unsigned long REGPARAM2 op_57d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_57d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_57e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_57e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_57f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_57f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_57f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(7) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_58c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(8) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_58c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(8)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel944;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel944: ;
+return 4;
+}
+unsigned long REGPARAM2 op_58d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_58d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_58e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_58e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_58f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_58f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_58f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(8) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_59c0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(9) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_59c8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(9)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel953;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel953: ;
+return 4;
+}
+unsigned long REGPARAM2 op_59d0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_59d8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_59e0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_59e8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_59f0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_59f8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_59f9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(9) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5ac0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(10) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5ac8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(10)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel962;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel962: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5ad0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ad8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ae0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ae8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5af0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5af8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5af9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(10) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5bc0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(11) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5bc8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(11)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel971;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel971: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5bd0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5bd8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5be0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5be8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5bf0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5bf8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5bf9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(11) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5cc0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(12) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5cc8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(12)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel980;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel980: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5cd0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5cd8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ce0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ce8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5cf0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5cf8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5cf9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(12) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5dc0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(13) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5dc8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(13)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel989;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel989: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5dd0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5dd8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5de0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5de8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5df0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5df8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5df9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(13) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_5ec0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(14) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5ec8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(14)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel998;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel998: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5ed0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ed8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ee0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5ee8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ef0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ef8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ef9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(14) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+#endif
+
+#ifdef PART_6
+unsigned long REGPARAM2 op_5fc0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{{ int val = cctrue(15) ? 0xff : 0;
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xff) | ((val) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_5fc8_3(uae_u32 opcode) /* DBcc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 offs = get_iword(2);
+ if (!cctrue(15)) {
+ m68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src-1)) & 0xffff);
+ if (src) {
+ m68k_incpc((uae_s32)offs + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1007;
+ }
+ }
+}}}m68k_incpc(4);
+endlabel1007: ;
+return 4;
+}
+unsigned long REGPARAM2 op_5fd0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5fd8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5fe0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_5fe8_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ff0_3(uae_u32 opcode) /* Scc */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ff8_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_5ff9_3(uae_u32 opcode) /* Scc */
+{
+{{ uaecptr srca = get_ilong(2);
+{ int val = cctrue(15) ? 0xff : 0;
+ put_byte(srca,val);
+}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_6000_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(0)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1015;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1015: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6001_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(0)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1016;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1016: ;
+return 2;
+}
+unsigned long REGPARAM2 op_60ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(0)) goto endlabel1017;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1017;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(0)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1017;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1017: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6100_3(uae_u32 opcode) /* BSR */
+{
+{{ uae_s16 src = get_iword(2);
+ uae_s32 s = (uae_s32)src + 2;
+ m68k_do_bsr(m68k_getpc() + 4, s);
+}}return 4;
+}
+unsigned long REGPARAM2 op_6101_3(uae_u32 opcode) /* BSR */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ uae_s32 s = (uae_s32)src + 2;
+ m68k_do_bsr(m68k_getpc() + 2, s);
+}}return 2;
+}
+unsigned long REGPARAM2 op_61ff_3(uae_u32 opcode) /* BSR */
+{
+{{ uae_s32 src = get_ilong(2);
+ uae_s32 s = (uae_s32)src + 2;
+ m68k_do_bsr(m68k_getpc() + 6, s);
+}}return 6;
+}
+unsigned long REGPARAM2 op_6200_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(2)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1021;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1021: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6201_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(2)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1022;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1022: ;
+return 2;
+}
+unsigned long REGPARAM2 op_62ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(2)) goto endlabel1023;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1023;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(2)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1023;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1023: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6300_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(3)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1024;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1024: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6301_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(3)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1025;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1025: ;
+return 2;
+}
+unsigned long REGPARAM2 op_63ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(3)) goto endlabel1026;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1026;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(3)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1026;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1026: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6400_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(4)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1027;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1027: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6401_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(4)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1028;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1028: ;
+return 2;
+}
+unsigned long REGPARAM2 op_64ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(4)) goto endlabel1029;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1029;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(4)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1029;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1029: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6500_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(5)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1030;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1030: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6501_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(5)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1031;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1031: ;
+return 2;
+}
+unsigned long REGPARAM2 op_65ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(5)) goto endlabel1032;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1032;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(5)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1032;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1032: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6600_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(6)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1033;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1033: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6601_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(6)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1034;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1034: ;
+return 2;
+}
+unsigned long REGPARAM2 op_66ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(6)) goto endlabel1035;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1035;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(6)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1035;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1035: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6700_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(7)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1036;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1036: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6701_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(7)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1037;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1037: ;
+return 2;
+}
+unsigned long REGPARAM2 op_67ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(7)) goto endlabel1038;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1038;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(7)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1038;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1038: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6800_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(8)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1039;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1039: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6801_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(8)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1040;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1040: ;
+return 2;
+}
+unsigned long REGPARAM2 op_68ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(8)) goto endlabel1041;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1041;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(8)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1041;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1041: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6900_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(9)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1042;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1042: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6901_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(9)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1043;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1043: ;
+return 2;
+}
+unsigned long REGPARAM2 op_69ff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(9)) goto endlabel1044;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1044;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(9)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1044;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1044: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6a00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(10)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1045;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1045: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6a01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(10)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1046;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1046: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6aff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(10)) goto endlabel1047;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1047;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(10)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1047;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1047: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6b00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(11)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1048;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1048: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6b01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(11)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1049;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1049: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6bff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(11)) goto endlabel1050;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1050;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(11)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1050;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1050: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6c00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(12)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1051;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1051: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6c01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(12)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1052;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1052: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6cff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(12)) goto endlabel1053;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1053;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(12)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1053;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1053: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6d00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(13)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1054;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1054: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6d01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(13)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1055;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1055: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6dff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(13)) goto endlabel1056;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1056;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(13)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1056;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1056: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6e00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(14)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1057;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1057: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6e01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(14)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1058;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1058: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6eff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(14)) goto endlabel1059;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1059;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(14)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1059;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1059: ;
+return 6;
+}
+unsigned long REGPARAM2 op_6f00_3(uae_u32 opcode) /* Bcc */
+{
+{{ uae_s16 src = get_iword(2);
+ if (!cctrue(15)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1060;
+didnt_jump:;
+}}m68k_incpc(4);
+endlabel1060: ;
+return 4;
+}
+unsigned long REGPARAM2 op_6f01_3(uae_u32 opcode) /* Bcc */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+{{ uae_u32 src = srcreg;
+ if (!cctrue(15)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1061;
+didnt_jump:;
+}}m68k_incpc(2);
+endlabel1061: ;
+return 2;
+}
+unsigned long REGPARAM2 op_6fff_3(uae_u32 opcode) /* Bcc */
+{
+{ m68k_incpc(2);
+ if (!cctrue(15)) goto endlabel1062;
+ last_addr_for_exception_3 = m68k_getpc() + 2;
+ last_fault_for_exception_3 = m68k_getpc() + 1;
+ last_op_for_exception_3 = opcode; Exception(3,0); goto endlabel1062;
+{ uae_s32 src = get_ilong(2);
+ if (!cctrue(15)) goto didnt_jump;
+ m68k_incpc ((uae_s32)src + 2);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2);
+#endif
+ goto endlabel1062;
+didnt_jump:;
+}}m68k_incpc(6);
+endlabel1062: ;
+return 6;
+}
+unsigned long REGPARAM2 op_7000_3(uae_u32 opcode) /* MOVE */
+{
+ uae_u32 srcreg = (uae_s32)(uae_s8)(opcode & 255);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_u32 src = srcreg;
+{ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_8000_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_8010_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8018_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8020_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8028_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8030_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8038_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8039_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_803a_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_803b_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_803c_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_8040_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_8050_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8058_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8060_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_8068_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8070_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8078_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_8079_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_807a_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_807b_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_807c_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_8080_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_8090_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8098_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_80a0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_80a8_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_80b0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_80b8_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_80b9_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_80ba_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_80bb_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_80bc_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_80c0_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1097; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}m68k_incpc(2);
+endlabel1097: ;
+return 70;
+}
+unsigned long REGPARAM2 op_80d0_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1098; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1098: ;
+return 72;
+}
+unsigned long REGPARAM2 op_80d8_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1099; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1099: ;
+return 72;
+}
+unsigned long REGPARAM2 op_80e0_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1100; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1100: ;
+return 72;
+}
+unsigned long REGPARAM2 op_80e8_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1101; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1101: ;
+return 74;
+}
+unsigned long REGPARAM2 op_80f0_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1102; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1102: ;
+return 74;
+}
+unsigned long REGPARAM2 op_80f8_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1103; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1103: ;
+return 74;
+}
+unsigned long REGPARAM2 op_80f9_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1104; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(6);
+endlabel1104: ;
+return 76;
+}
+unsigned long REGPARAM2 op_80fa_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1105; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1105: ;
+return 74;
+}
+unsigned long REGPARAM2 op_80fb_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1106; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1106: ;
+return 74;
+}
+unsigned long REGPARAM2 op_80fc_3(uae_u32 opcode) /* DIVU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1107; } else {
+ uae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;
+ uae_u32 rem = (uae_u32)dst % (uae_u32)(uae_u16)src;
+ if (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}m68k_incpc(4);
+endlabel1107: ;
+return 72;
+}
+unsigned long REGPARAM2 op_8100_3(uae_u32 opcode) /* SBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{ uae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_8108_3(uae_u32 opcode) /* SBCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }
+ newv = newv_hi + (newv_lo & 0xF); SET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv -= 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_8110_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8118_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8120_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8128_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8130_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8138_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8139_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8150_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8158_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8160_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_8168_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8170_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8178_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_8179_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_8190_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_8198_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_81a0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_81a8_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_81b0_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_81b8_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_81b9_3(uae_u32 opcode) /* OR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+ src |= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_81c0_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1131; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}m68k_incpc(2);
+endlabel1131: ;
+return 74;
+}
+unsigned long REGPARAM2 op_81d0_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1132; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1132: ;
+return 76;
+}
+unsigned long REGPARAM2 op_81d8_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1133; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1133: ;
+return 76;
+}
+unsigned long REGPARAM2 op_81e0_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1134; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(2);
+endlabel1134: ;
+return 76;
+}
+unsigned long REGPARAM2 op_81e8_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1135; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1135: ;
+return 78;
+}
+unsigned long REGPARAM2 op_81f0_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1136; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1136: ;
+return 78;
+}
+unsigned long REGPARAM2 op_81f8_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1137; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1137: ;
+return 78;
+}
+unsigned long REGPARAM2 op_81f9_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1138; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(6);
+endlabel1138: ;
+return 80;
+}
+unsigned long REGPARAM2 op_81fa_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1139; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1139: ;
+return 78;
+}
+unsigned long REGPARAM2 op_81fb_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1140; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}}m68k_incpc(4);
+endlabel1140: ;
+return 78;
+}
+unsigned long REGPARAM2 op_81fc_3(uae_u32 opcode) /* DIVS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{ uaecptr oldpc = m68k_getpc();
+{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ if(src == 0) { Exception(5,oldpc); goto endlabel1141; } else {
+ uae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;
+ uae_u16 rem = (uae_s32)dst % (uae_s32)(uae_s16)src;
+ if ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else
+ {
+ if (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ newv = (newv & 0xffff) | ((uae_u32)rem << 16);
+ m68k_dreg(regs, dstreg) = (newv);
+ }
+ }
+}}}m68k_incpc(4);
+endlabel1141: ;
+return 76;
+}
+unsigned long REGPARAM2 op_9000_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9010_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9018_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9020_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9028_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9030_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9038_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9039_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_903a_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_903b_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_903c_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_9040_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9048_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9050_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9058_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9060_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_9068_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9070_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9078_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_9079_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_907a_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_907b_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_907c_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_9080_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9088_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9090_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9098_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_90a0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_90a8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_90b0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_90b8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_90b9_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_90ba_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_90bb_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_90bc_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_90c0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_90c8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_90d0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_90d8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_90e0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_90e8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_90f0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_90f8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_90f9_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_90fa_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_90fb_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_90fc_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_9100_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9108_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_9110_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9118_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9120_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9128_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9130_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9138_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9139_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_9140_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9148_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_9150_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9158_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9160_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_9168_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9170_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9178_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_9179_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_9180_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_9188_3(uae_u32 opcode) /* SUBX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 14;
+}
+unsigned long REGPARAM2 op_9190_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_9198_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_91a0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_91a8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_91b0_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_91b8_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_91b9_3(uae_u32 opcode) /* SUB */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_91c0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_91c8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_91d0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_91d8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_91e0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_91e8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_91f0_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_91f8_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_91f9_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_91fa_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_91fb_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_91fc_3(uae_u32 opcode) /* SUBA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst - src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_b000_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b010_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+#endif
+
+#ifdef PART_7
+unsigned long REGPARAM2 op_b018_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b020_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b028_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b030_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b038_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b039_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_b03a_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b03b_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b03c_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_b040_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b048_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b050_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b058_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b060_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b068_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b070_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b078_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b079_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_b07a_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b07b_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b07c_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_b080_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b088_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b090_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b098_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b0a0_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b0a8_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b0b0_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b0b8_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b0b9_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_b0ba_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b0bb_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b0bc_3(uae_u32 opcode) /* CMP */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_b0c0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b0c8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b0d0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b0d8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b0e0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_b0e8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b0f0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b0f8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b0f9_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_b0fa_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b0fb_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_b0fc_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_b100_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b108_3(uae_u32 opcode) /* CMPM */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) - ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u8)(src)) > ((uae_u8)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b110_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b118_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b120_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b128_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b130_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b138_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b139_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_b140_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b148_3(uae_u32 opcode) /* CMPM */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) - ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u16)(src)) > ((uae_u16)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b150_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b158_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b160_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b168_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b170_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b178_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b179_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_b180_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b188_3(uae_u32 opcode) /* CMPM */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_b190_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_b198_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_b1a0_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_b1a8_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_b1b0_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_b1b8_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_b1b9_3(uae_u32 opcode) /* EOR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+ src ^= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_b1c0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b1c8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_b1d0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b1d8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b1e0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_b1e8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b1f0_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b1f8_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b1f9_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_b1fa_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b1fb_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_b1fc_3(uae_u32 opcode) /* CMPA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) - ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs != flgo) && (flgn != flgo));
+ SET_CFLG (((uae_u32)(src)) > ((uae_u32)(dst)));
+ SET_NFLG (flgn != 0);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_c000_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c010_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c018_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c020_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c028_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c030_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c038_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c039_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c03a_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c03b_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c03c_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_c040_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c050_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c058_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c060_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_c068_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c070_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c078_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c079_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_c07a_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c07b_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_c07c_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((src) & 0xffff);
+}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_c080_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c090_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c098_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c0a0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c0a8_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c0b0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c0b8_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c0b9_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_c0ba_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c0bb_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c0bc_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_c0c0_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}m68k_incpc(2);
+return 34;
+}
+unsigned long REGPARAM2 op_c0d0_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c0d8_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c0e0_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c0e8_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c0f0_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c0f8_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c0f9_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(6);
+return 40;
+}
+unsigned long REGPARAM2 op_c0fa_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c0fb_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c0fc_3(uae_u32 opcode) /* MULU */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}m68k_incpc(4);
+return 36;
+}
+unsigned long REGPARAM2 op_c100_3(uae_u32 opcode) /* ABCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{ uae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo +=6; }
+ newv = newv_hi + newv_lo; SET_CFLG (cflg = (newv & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv += 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c108_3(uae_u32 opcode) /* ABCD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);
+ uae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);
+ uae_u16 newv;
+ int cflg;
+ if (newv_lo > 9) { newv_lo +=6; }
+ newv = newv_hi + newv_lo; SET_CFLG (cflg = (newv & 0x1F0) > 0x90);
+ COPY_CARRY;
+ if (cflg) newv += 0x60;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_c110_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c118_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c120_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c128_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c130_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c138_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c139_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s8)(src)) == 0);
+ SET_NFLG (((uae_s8)(src)) < 0);
+ put_byte(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_c140_3(uae_u32 opcode) /* EXG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+ m68k_dreg(regs, srcreg) = (dst);
+ m68k_dreg(regs, dstreg) = (src);
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c148_3(uae_u32 opcode) /* EXG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+ m68k_areg(regs, srcreg) = (dst);
+ if (srcreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+ m68k_areg(regs, dstreg) = (src);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c150_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c158_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c160_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_c168_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c170_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c178_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_c179_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(src)) == 0);
+ SET_NFLG (((uae_s16)(src)) < 0);
+ put_word(dsta,src);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_c188_3(uae_u32 opcode) /* EXG */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+ m68k_dreg(regs, srcreg) = (dst);
+ m68k_areg(regs, dstreg) = (src);
+ if (dstreg == 7) CHECK_STACK_POINTER_ASSIGNMENT ();
+}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_c190_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_c198_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_c1a0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_c1a8_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_c1b0_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_c1b8_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_c1b9_3(uae_u32 opcode) /* AND */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+ src &= dst;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(src)) == 0);
+ SET_NFLG (((uae_s32)(src)) < 0);
+ put_long(dsta,src);
+}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_c1c0_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}m68k_incpc(2);
+return 34;
+}
+unsigned long REGPARAM2 op_c1d0_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c1d8_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c1e0_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 36;
+}
+unsigned long REGPARAM2 op_c1e8_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c1f0_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c1f8_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c1f9_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(6);
+return 40;
+}
+unsigned long REGPARAM2 op_c1fa_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c1fb_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(4);
+return 38;
+}
+unsigned long REGPARAM2 op_c1fc_3(uae_u32 opcode) /* MULS */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}m68k_incpc(4);
+return 36;
+}
+unsigned long REGPARAM2 op_d000_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d010_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d018_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s8 src = get_byte(srca);
+ m68k_areg(regs, srcreg) += areg_byteinc[srcreg];
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d020_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d028_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d030_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d038_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d039_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_d03a_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d03b_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s8 src = get_byte(srca);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d03c_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = get_ibyte(2);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_d040_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d048_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d050_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d058_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d060_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d068_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d070_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d078_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d079_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_d07a_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d07b_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d07c_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_d080_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d088_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d090_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d098_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d0a0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d0a8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d0b0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d0b8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d0b9_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_d0ba_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d0bb_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d0bc_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_d0c0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d0c8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d0d0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d0d8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s16 src = get_word(srca);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d0e0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 4;
+}
+unsigned long REGPARAM2 op_d0e8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d0f0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d0f8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d0f9_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(6);
+return 8;
+}
+unsigned long REGPARAM2 op_d0fa_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d0fb_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s16 src = get_word(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 6;
+}
+unsigned long REGPARAM2 op_d0fc_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = get_iword(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(4);
+return 4;
+}
+unsigned long REGPARAM2 op_d100_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uae_s8 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((newv) & 0xff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d108_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - areg_byteinc[srcreg];
+{ uae_s8 src = get_byte(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s8)(newv)) == 0));
+ SET_NFLG (((uae_s8)(newv)) < 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_d110_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d118_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg(regs, dstreg) += areg_byteinc[dstreg];
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d120_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - areg_byteinc[dstreg];
+{ uae_s8 dst = get_byte(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d128_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d130_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d138_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d139_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s8 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s8 dst = get_byte(dsta);
+{{uae_u32 newv = ((uae_s8)(dst)) + ((uae_s8)(src));
+{ int flgs = ((uae_s8)(src)) < 0;
+ int flgo = ((uae_s8)(dst)) < 0;
+ int flgn = ((uae_s8)(newv)) < 0;
+ SET_ZFLG (((uae_s8)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u8)(~dst)) < ((uae_u8)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_byte(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_d140_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uae_s16 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((newv) & 0xffff);
+}}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d148_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 src = get_word(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s16)(newv)) == 0));
+ SET_NFLG (((uae_s16)(newv)) < 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 8;
+}
+unsigned long REGPARAM2 op_d150_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d158_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg(regs, dstreg) += 2;
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d160_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 2;
+{ uae_s16 dst = get_word(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d168_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d170_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d178_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d179_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s16 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s16 dst = get_word(dsta);
+{{uae_u32 newv = ((uae_s16)(dst)) + ((uae_s16)(src));
+{ int flgs = ((uae_s16)(src)) < 0;
+ int flgo = ((uae_s16)(dst)) < 0;
+ int flgn = ((uae_s16)(newv)) < 0;
+ SET_ZFLG (((uae_s16)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u16)(~dst)) < ((uae_u16)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_word(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_d180_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_dreg(regs, dstreg);
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ m68k_dreg(regs, dstreg) = (newv);
+}}}}}m68k_incpc(2);
+return 2;
+}
+#endif
+
+#ifdef PART_8
+unsigned long REGPARAM2 op_d188_3(uae_u32 opcode) /* ADDX */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));
+ COPY_CARRY;
+ SET_ZFLG (GET_ZFLG & (((uae_s32)(newv)) == 0));
+ SET_NFLG (((uae_s32)(newv)) < 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 14;
+}
+unsigned long REGPARAM2 op_d190_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_d198_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg);
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg(regs, dstreg) += 4;
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_d1a0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) - 4;
+{ uae_s32 dst = get_long(dsta);
+ m68k_areg (regs, dstreg) = dsta;
+ if (dstreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(2);
+return 10;
+}
+unsigned long REGPARAM2 op_d1a8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_d1b0_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_disp_ea_000(m68k_areg(regs, dstreg), get_iword(2));
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_d1b8_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(4);
+return 12;
+}
+unsigned long REGPARAM2 op_d1b9_3(uae_u32 opcode) /* ADD */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uaecptr dsta = get_ilong(2);
+{ uae_s32 dst = get_long(dsta);
+{{uae_u32 newv = ((uae_s32)(dst)) + ((uae_s32)(src));
+{ int flgs = ((uae_s32)(src)) < 0;
+ int flgo = ((uae_s32)(dst)) < 0;
+ int flgn = ((uae_s32)(newv)) < 0;
+ SET_ZFLG (((uae_s32)(newv)) == 0);
+ SET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));
+ SET_CFLG (((uae_u32)(~dst)) < ((uae_u32)(src)));
+ COPY_CARRY;
+ SET_NFLG (flgn != 0);
+ put_long(dsta,newv);
+}}}}}}}m68k_incpc(6);
+return 14;
+}
+unsigned long REGPARAM2 op_d1c0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_dreg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d1c8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = m68k_areg(regs, srcreg);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_d1d0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d1d8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg);
+{ uae_s32 src = get_long(srca);
+ m68k_areg(regs, srcreg) += 4;
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d1e0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) - 4;
+{ uae_s32 src = get_long(srca);
+ m68k_areg (regs, srcreg) = srca;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_d1e8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d1f0_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 srcreg = (opcode & 7);
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d1f8_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d1f9_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = get_ilong(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_d1fa_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr srca = m68k_getpc () + 2;
+ srca += (uae_s32)(uae_s16)get_iword(2);
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d1fb_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uaecptr tmppc = m68k_getpc() + 2;
+ uaecptr srca = get_disp_ea_000(tmppc, get_iword(2));
+{ uae_s32 src = get_long(srca);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_d1fc_3(uae_u32 opcode) /* ADDA */
+{
+ uae_u32 dstreg = (opcode >> 9) & 7;
+{{ uae_s32 src = get_ilong(2);
+{ uae_s32 dst = m68k_areg(regs, dstreg);
+{ uae_u32 newv = dst + src;
+ m68k_areg(regs, dstreg) = (newv);
+ if (dstreg == 7) CHECK_STACK_POINTER_INCREMENT ();
+}}}}m68k_incpc(6);
+return 6;
+}
+unsigned long REGPARAM2 op_e000_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ uae_u32 sign = (0x80 & val) >> 7;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ val = 0xff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xff << (8 - cnt)) & (uae_u32)-sign;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e008_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_CFLG ((cnt == 8) & (val >> 7));
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e010_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (7 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e018_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u8 val = data;
+ uae_u32 cmask = 0x80;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e020_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ uae_u32 sign = (0x80 & val) >> 7;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ val = 0xff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xff << (8 - cnt)) & (uae_u32)-sign;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e028_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_CFLG ((cnt == 8) & (val >> 7));
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e030_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 36) cnt -= 36;
+ if (cnt >= 18) cnt -= 18;
+ if (cnt >= 9) cnt -= 9;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (7 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e038_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u8 val = data;
+ uae_u32 cmask = 0x80;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e040_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = (0x8000 & val) >> 15;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ val = 0xffff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xffff << (16 - cnt)) & (uae_u32)-sign;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e048_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_CFLG ((cnt == 16) & (val >> 15));
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e050_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (15 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e058_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u16 val = data;
+ uae_u32 cmask = 0x8000;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e060_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = (0x8000 & val) >> 15;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ val = 0xffff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xffff << (16 - cnt)) & (uae_u32)-sign;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e068_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_CFLG ((cnt == 16) & (val >> 15));
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e070_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 34) cnt -= 34;
+ if (cnt >= 17) cnt -= 17;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (15 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e078_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u16 val = data;
+ uae_u32 cmask = 0x8000;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e080_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ uae_u32 sign = (0x80000000 & val) >> 31;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ val = 0xffffffff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xffffffff << (32 - cnt)) & (uae_u32)-sign;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e088_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_CFLG ((cnt == 32) & (val >> 31));
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e090_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (31 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xffffffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e098_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ uae_u32 cmask = 0x80000000;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e0a0_3(uae_u32 opcode) /* ASR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ uae_u32 sign = (0x80000000 & val) >> 31;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ val = 0xffffffff & (uae_u32)-sign;
+ SET_CFLG (sign);
+ COPY_CARRY;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ val |= (0xffffffff << (32 - cnt)) & (uae_u32)-sign;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e0a8_3(uae_u32 opcode) /* LSR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_CFLG ((cnt == 32) & (val >> 31));
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val >>= cnt - 1;
+ SET_CFLG (val & 1);
+ COPY_CARRY;
+ val >>= 1;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e0b0_3(uae_u32 opcode) /* ROXR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 33) cnt -= 33;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 hival = (val << 1) | GET_XFLG;
+ hival <<= (31 - cnt);
+ val >>= cnt;
+ carry = val & 1;
+ val >>= 1;
+ val |= hival;
+ SET_XFLG (carry);
+ val &= 0xffffffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e0b8_3(uae_u32 opcode) /* ROR */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ uae_u32 cmask = 0x80000000;
+ cnt &= 63;
+ if (!cnt) { CFLG = 0; } else { uae_u32 carry;
+ for(;cnt;--cnt){
+ carry=val&1; val = val >> 1;
+ if(carry) val |= cmask;
+ }
+ SET_CFLG (carry);
+}
+ SET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e0d0_3(uae_u32 opcode) /* ASRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e0d8_3(uae_u32 opcode) /* ASRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e0e0_3(uae_u32 opcode) /* ASRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e0e8_3(uae_u32 opcode) /* ASRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e0f0_3(uae_u32 opcode) /* ASRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e0f8_3(uae_u32 opcode) /* ASRW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e0f9_3(uae_u32 opcode) /* ASRW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 cflg = val & 1;
+ val = (val >> 1) | sign;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ SET_CFLG (cflg);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e100_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 8 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ uae_u32 mask = (0xff << (7 - cnt)) & 0xff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x80) >> 7);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e108_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_CFLG (cnt == 8 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x80) >> 7);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e110_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (7 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e118_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ uae_u32 loval;
+ cnt &= 7;
+ loval = val >> (8 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e120_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 8 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ uae_u32 mask = (0xff << (7 - cnt)) & 0xff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x80) >> 7);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e128_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 8) {
+ SET_CFLG (cnt == 8 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x80) >> 7);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xff;
+ }
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e130_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 36) cnt -= 36;
+ if (cnt >= 18) cnt -= 18;
+ if (cnt >= 9) cnt -= 9;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (7 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e138_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s8 cnt = m68k_dreg(regs, srcreg);
+{ uae_s8 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u8)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt > 0) {
+ uae_u32 loval;
+ cnt &= 7;
+ loval = val >> (8 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s8)(val)) == 0);
+ SET_NFLG (((uae_s8)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((val) & 0xff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e140_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 16 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ uae_u32 mask = (0xffff << (15 - cnt)) & 0xffff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x8000) >> 15);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e148_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_CFLG (cnt == 16 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x8000) >> 15);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e150_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (15 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e158_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ uae_u32 loval;
+ cnt &= 15;
+ loval = val >> (16 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xffff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e160_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 16 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ uae_u32 mask = (0xffff << (15 - cnt)) & 0xffff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x8000) >> 15);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e168_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 16) {
+ SET_CFLG (cnt == 16 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x8000) >> 15);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffff;
+ }
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e170_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 34) cnt -= 34;
+ if (cnt >= 17) cnt -= 17;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (15 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e178_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s16 cnt = m68k_dreg(regs, srcreg);
+{ uae_s16 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = (uae_u16)data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt > 0) {
+ uae_u32 loval;
+ cnt &= 15;
+ loval = val >> (16 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xffff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xffff) | ((val) & 0xffff);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e180_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 32 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ uae_u32 mask = (0xffffffff << (31 - cnt)) & 0xffffffff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x80000000) >> 31);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e188_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_CFLG (cnt == 32 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x80000000) >> 31);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e190_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (31 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xffffffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e198_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = imm8_table[((opcode >> 9) & 7)];
+ uae_u32 dstreg = opcode & 7;
+{{ uae_u32 cnt = srcreg;
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+{ uae_u32 loval;
+ cnt &= 31;
+ loval = val >> (32 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xffffffff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e1a0_3(uae_u32 opcode) /* ASL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_VFLG (val != 0);
+ SET_CFLG (cnt == 32 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ uae_u32 mask = (0xffffffff << (31 - cnt)) & 0xffffffff;
+ SET_VFLG ((val & mask) != mask && (val & mask) != 0);
+ val <<= cnt - 1;
+ SET_CFLG ((val & 0x80000000) >> 31);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e1a8_3(uae_u32 opcode) /* LSL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 32) {
+ SET_CFLG (cnt == 32 ? val & 1 : 0);
+ COPY_CARRY;
+ val = 0;
+ } else if (cnt > 0) {
+ val <<= (cnt - 1);
+ SET_CFLG ((val & 0x80000000) >> 31);
+ COPY_CARRY;
+ val <<= 1;
+ val &= 0xffffffff;
+ }
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e1b0_3(uae_u32 opcode) /* ROXL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt >= 33) cnt -= 33;
+ if (cnt > 0) {
+ cnt--;
+ {
+ uae_u32 carry;
+ uae_u32 loval = val >> (31 - cnt);
+ carry = loval & 1;
+ val = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);
+ SET_XFLG (carry);
+ val &= 0xffffffff;
+ } }
+ SET_CFLG (GET_XFLG);
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e1b8_3(uae_u32 opcode) /* ROL */
+{
+ uae_u32 srcreg = ((opcode >> 9) & 7);
+ uae_u32 dstreg = opcode & 7;
+{{ uae_s32 cnt = m68k_dreg(regs, srcreg);
+{ uae_s32 data = m68k_dreg(regs, dstreg);
+{ uae_u32 val = data;
+ cnt &= 63;
+ CLEAR_CZNV;
+ if (cnt > 0) {
+ uae_u32 loval;
+ cnt &= 31;
+ loval = val >> (32 - cnt);
+ val <<= cnt;
+ val |= loval;
+ val &= 0xffffffff;
+ SET_CFLG (val & 1);
+}
+ SET_ZFLG (((uae_s32)(val)) == 0);
+ SET_NFLG (((uae_s32)(val)) < 0);
+ m68k_dreg(regs, dstreg) = (val);
+#if HAS_PROFILING
+ if (gProfilingEnabled)
+ ProfileIncrementClock(2*cnt);
+#endif
+}}}}m68k_incpc(2);
+return 2;
+}
+unsigned long REGPARAM2 op_e1d0_3(uae_u32 opcode) /* ASLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e1d8_3(uae_u32 opcode) /* ASLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e1e0_3(uae_u32 opcode) /* ASLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e1e8_3(uae_u32 opcode) /* ASLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e1f0_3(uae_u32 opcode) /* ASLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e1f8_3(uae_u32 opcode) /* ASLW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e1f9_3(uae_u32 opcode) /* ASLW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 sign = 0x8000 & val;
+ uae_u32 sign2;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+ sign2 = 0x8000 & val;
+ SET_CFLG (sign != 0);
+ COPY_CARRY;
+ SET_VFLG (GET_VFLG | (sign2 != sign));
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e2d0_3(uae_u32 opcode) /* LSRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e2d8_3(uae_u32 opcode) /* LSRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e2e0_3(uae_u32 opcode) /* LSRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e2e8_3(uae_u32 opcode) /* LSRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e2f0_3(uae_u32 opcode) /* LSRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e2f8_3(uae_u32 opcode) /* LSRW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e2f9_3(uae_u32 opcode) /* LSRW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u32 val = (uae_u16)data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e3d0_3(uae_u32 opcode) /* LSLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e3d8_3(uae_u32 opcode) /* LSLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e3e0_3(uae_u32 opcode) /* LSLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e3e8_3(uae_u32 opcode) /* LSLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e3f0_3(uae_u32 opcode) /* LSLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e3f8_3(uae_u32 opcode) /* LSLW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e3f9_3(uae_u32 opcode) /* LSLW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e4d0_3(uae_u32 opcode) /* ROXRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e4d8_3(uae_u32 opcode) /* ROXRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e4e0_3(uae_u32 opcode) /* ROXRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e4e8_3(uae_u32 opcode) /* ROXRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e4f0_3(uae_u32 opcode) /* ROXRW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e4f8_3(uae_u32 opcode) /* ROXRW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e4f9_3(uae_u32 opcode) /* ROXRW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (GET_XFLG) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e5d0_3(uae_u32 opcode) /* ROXLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e5d8_3(uae_u32 opcode) /* ROXLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e5e0_3(uae_u32 opcode) /* ROXLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e5e8_3(uae_u32 opcode) /* ROXLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e5f0_3(uae_u32 opcode) /* ROXLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e5f8_3(uae_u32 opcode) /* ROXLW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e5f9_3(uae_u32 opcode) /* ROXLW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (GET_XFLG) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ COPY_CARRY;
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e6d0_3(uae_u32 opcode) /* RORW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e6d8_3(uae_u32 opcode) /* RORW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e6e0_3(uae_u32 opcode) /* RORW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e6e8_3(uae_u32 opcode) /* RORW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e6f0_3(uae_u32 opcode) /* RORW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e6f8_3(uae_u32 opcode) /* RORW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e6f9_3(uae_u32 opcode) /* RORW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 1;
+ val >>= 1;
+ if (carry) val |= 0x8000;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry);
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+unsigned long REGPARAM2 op_e7d0_3(uae_u32 opcode) /* ROLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e7d8_3(uae_u32 opcode) /* ROLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg);
+{ uae_s16 data = get_word(dataa);
+ m68k_areg(regs, srcreg) += 2;
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e7e0_3(uae_u32 opcode) /* ROLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) - 2;
+{ uae_s16 data = get_word(dataa);
+ m68k_areg (regs, srcreg) = dataa;
+ if (srcreg == 7) CHECK_STACK_POINTER_DECREMENT ();
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(2);
+return 6;
+}
+unsigned long REGPARAM2 op_e7e8_3(uae_u32 opcode) /* ROLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e7f0_3(uae_u32 opcode) /* ROLW */
+{
+ uae_u32 srcreg = (opcode & 7);
+{{ uaecptr dataa = get_disp_ea_000(m68k_areg(regs, srcreg), get_iword(2));
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e7f8_3(uae_u32 opcode) /* ROLW */
+{
+{{ uaecptr dataa = (uae_s32)(uae_s16)get_iword(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(4);
+return 8;
+}
+unsigned long REGPARAM2 op_e7f9_3(uae_u32 opcode) /* ROLW */
+{
+{{ uaecptr dataa = get_ilong(2);
+{ uae_s16 data = get_word(dataa);
+{ uae_u16 val = data;
+ uae_u32 carry = val & 0x8000;
+ val <<= 1;
+ if (carry) val |= 1;
+ CLEAR_CZNV;
+ SET_ZFLG (((uae_s16)(val)) == 0);
+ SET_NFLG (((uae_s16)(val)) < 0);
+SET_CFLG (carry >> 15);
+ put_word(dataa,val);
+}}}}m68k_incpc(6);
+return 10;
+}
+#endif
+
diff --git a/SrcShared/UAE/cpuemu1.c b/SrcShared/UAE/cpuemu1.c
new file mode 100644
index 0000000..bf64d54
--- /dev/null
+++ b/SrcShared/UAE/cpuemu1.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_1 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu2.c b/SrcShared/UAE/cpuemu2.c
new file mode 100644
index 0000000..ebe9c5e
--- /dev/null
+++ b/SrcShared/UAE/cpuemu2.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_2 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu3.c b/SrcShared/UAE/cpuemu3.c
new file mode 100644
index 0000000..f38fc67
--- /dev/null
+++ b/SrcShared/UAE/cpuemu3.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_3 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu4.c b/SrcShared/UAE/cpuemu4.c
new file mode 100644
index 0000000..34784e0
--- /dev/null
+++ b/SrcShared/UAE/cpuemu4.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_4 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu5.c b/SrcShared/UAE/cpuemu5.c
new file mode 100644
index 0000000..33e7a0b
--- /dev/null
+++ b/SrcShared/UAE/cpuemu5.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_5 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu6.c b/SrcShared/UAE/cpuemu6.c
new file mode 100644
index 0000000..d25d4bc
--- /dev/null
+++ b/SrcShared/UAE/cpuemu6.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_6 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu7.c b/SrcShared/UAE/cpuemu7.c
new file mode 100644
index 0000000..c8aa72f
--- /dev/null
+++ b/SrcShared/UAE/cpuemu7.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_7 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpuemu8.c b/SrcShared/UAE/cpuemu8.c
new file mode 100644
index 0000000..e75f26e
--- /dev/null
+++ b/SrcShared/UAE/cpuemu8.c
@@ -0,0 +1,53 @@
+/*********************************************************************
+ *
+ * Copyright (c) 1998
+ * 3Com/Palm Computing Division. All rights reserved.
+ *
+ * Portions copyright (c) 1995-1998
+ * Bernd Schmidt. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ *
+ * This product includes software developed by 3Com and its
+ * contributors.
+ *
+ * 4. Neither 3Com nor the names of its contributors may be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 3COM AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 3COM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ *******************************************************************/
+
+// CodeWarrior Pro 3 can compile the full cpuemu.c file OK, but has
+// occassional memory problems linking it. Sometimes it links OK, but
+// sometimes it puts up the generic "Link failed" message. So we break
+// up cpuemu.c to heap it out a little.
+
+#define PART_8 1
+
+#include "cpuemu.c"
diff --git a/SrcShared/UAE/cpustbl.c b/SrcShared/UAE/cpustbl.c
new file mode 100644
index 0000000..154cf36
--- /dev/null
+++ b/SrcShared/UAE/cpustbl.c
@@ -0,0 +1,1590 @@
+#include "UAE.h"
+#if HAS_PROFILING
+#include "Profiling.h"
+#endif
+struct cputbl op_smalltbl_3[] = {
+{ op_0_3, 0, 0, 0, 2, 0 }, /* OR */
+{ op_10_3, 0, 16, 0, 3, 1 }, /* OR */
+{ op_18_3, 0, 24, 0, 3, 1 }, /* OR */
+{ op_20_3, 0, 32, 2, 3, 1 }, /* OR */
+{ op_28_3, 0, 40, 0, 4, 1 }, /* OR */
+{ op_30_3, 0, 48, 2, 4, 1 }, /* OR */
+{ op_38_3, 0, 56, 0, 4, 1 }, /* OR */
+{ op_39_3, 0, 57, 0, 5, 1 }, /* OR */
+{ op_3c_3, 0, 60, 8, 4, 0 }, /* ORSR */
+{ op_40_3, 0, 64, 0, 2, 0 }, /* OR */
+{ op_50_3, 0, 80, 0, 3, 1 }, /* OR */
+{ op_58_3, 0, 88, 0, 3, 1 }, /* OR */
+{ op_60_3, 0, 96, 2, 3, 1 }, /* OR */
+{ op_68_3, 0, 104, 0, 4, 1 }, /* OR */
+{ op_70_3, 0, 112, 2, 4, 1 }, /* OR */
+{ op_78_3, 0, 120, 0, 4, 1 }, /* OR */
+{ op_79_3, 0, 121, 0, 5, 1 }, /* OR */
+{ op_7c_3, 0, 124, 8, 4, 0 }, /* ORSR */
+{ op_80_3, 0, 128, 2, 3, 0 }, /* OR */
+{ op_90_3, 0, 144, 0, 5, 2 }, /* OR */
+{ op_98_3, 0, 152, 0, 5, 2 }, /* OR */
+{ op_a0_3, 0, 160, 2, 5, 2 }, /* OR */
+{ op_a8_3, 0, 168, 0, 6, 2 }, /* OR */
+{ op_b0_3, 0, 176, 2, 6, 2 }, /* OR */
+{ op_b8_3, 0, 184, 0, 6, 2 }, /* OR */
+{ op_b9_3, 0, 185, 0, 7, 2 }, /* OR */
+{ op_100_3, 0, 256, 2, 1, 0 }, /* BTST */
+{ op_108_3, 0, 264, 0, 4, 0 }, /* MVPMR */
+{ op_110_3, 0, 272, 0, 2, 0 }, /* BTST */
+{ op_118_3, 0, 280, 0, 2, 0 }, /* BTST */
+{ op_120_3, 0, 288, 2, 2, 0 }, /* BTST */
+{ op_128_3, 0, 296, 0, 3, 0 }, /* BTST */
+{ op_130_3, 0, 304, 2, 3, 0 }, /* BTST */
+{ op_138_3, 0, 312, 0, 3, 0 }, /* BTST */
+{ op_139_3, 0, 313, 0, 4, 0 }, /* BTST */
+{ op_13a_3, 0, 314, 0, 3, 0 }, /* BTST */
+{ op_13b_3, 0, 315, 2, 3, 0 }, /* BTST */
+{ op_13c_3, 0, 316, 0, 2, 0 }, /* BTST */
+{ op_140_3, 0, 320, 4, 1, 0 }, /* BCHG */
+{ op_148_3, 0, 328, 0, 6, 0 }, /* MVPMR */
+{ op_150_3, 0, 336, 0, 2, 1 }, /* BCHG */
+{ op_158_3, 0, 344, 0, 2, 1 }, /* BCHG */
+{ op_160_3, 0, 352, 2, 2, 1 }, /* BCHG */
+{ op_168_3, 0, 360, 0, 3, 1 }, /* BCHG */
+{ op_170_3, 0, 368, 2, 3, 1 }, /* BCHG */
+{ op_178_3, 0, 376, 0, 3, 1 }, /* BCHG */
+{ op_179_3, 0, 377, 0, 4, 1 }, /* BCHG */
+{ op_17a_3, 0, 378, 0, 3, 1 }, /* BCHG */
+{ op_17b_3, 0, 379, 2, 3, 1 }, /* BCHG */
+{ op_180_3, 0, 384, 6, 1, 0 }, /* BCLR */
+{ op_188_3, 0, 392, 0, 2, 2 }, /* MVPRM */
+{ op_190_3, 0, 400, 0, 2, 1 }, /* BCLR */
+{ op_198_3, 0, 408, 0, 2, 1 }, /* BCLR */
+{ op_1a0_3, 0, 416, 2, 2, 1 }, /* BCLR */
+{ op_1a8_3, 0, 424, 0, 3, 1 }, /* BCLR */
+{ op_1b0_3, 0, 432, 2, 3, 1 }, /* BCLR */
+{ op_1b8_3, 0, 440, 0, 3, 1 }, /* BCLR */
+{ op_1b9_3, 0, 441, 0, 4, 1 }, /* BCLR */
+{ op_1ba_3, 0, 442, 0, 3, 1 }, /* BCLR */
+{ op_1bb_3, 0, 443, 2, 3, 1 }, /* BCLR */
+{ op_1c0_3, 0, 448, 4, 1, 0 }, /* BSET */
+{ op_1c8_3, 0, 456, 0, 2, 4 }, /* MVPRM */
+{ op_1d0_3, 0, 464, 0, 2, 1 }, /* BSET */
+{ op_1d8_3, 0, 472, 0, 2, 1 }, /* BSET */
+{ op_1e0_3, 0, 480, 2, 2, 1 }, /* BSET */
+{ op_1e8_3, 0, 488, 0, 3, 1 }, /* BSET */
+{ op_1f0_3, 0, 496, 2, 3, 1 }, /* BSET */
+{ op_1f8_3, 0, 504, 0, 3, 1 }, /* BSET */
+{ op_1f9_3, 0, 505, 0, 4, 1 }, /* BSET */
+{ op_1fa_3, 0, 506, 0, 3, 1 }, /* BSET */
+{ op_1fb_3, 0, 507, 2, 3, 1 }, /* BSET */
+{ op_200_3, 0, 512, 0, 2, 0 }, /* AND */
+{ op_210_3, 0, 528, 0, 3, 1 }, /* AND */
+{ op_218_3, 0, 536, 0, 3, 1 }, /* AND */
+{ op_220_3, 0, 544, 2, 3, 1 }, /* AND */
+{ op_228_3, 0, 552, 0, 4, 1 }, /* AND */
+{ op_230_3, 0, 560, 2, 4, 1 }, /* AND */
+{ op_238_3, 0, 568, 0, 4, 1 }, /* AND */
+{ op_239_3, 0, 569, 0, 5, 1 }, /* AND */
+{ op_23c_3, 0, 572, 8, 4, 0 }, /* ANDSR */
+{ op_240_3, 0, 576, 0, 2, 0 }, /* AND */
+{ op_250_3, 0, 592, 0, 3, 1 }, /* AND */
+{ op_258_3, 0, 600, 0, 3, 1 }, /* AND */
+{ op_260_3, 0, 608, 2, 3, 1 }, /* AND */
+{ op_268_3, 0, 616, 0, 4, 1 }, /* AND */
+{ op_270_3, 0, 624, 2, 4, 1 }, /* AND */
+{ op_278_3, 0, 632, 0, 4, 1 }, /* AND */
+{ op_279_3, 0, 633, 0, 5, 1 }, /* AND */
+{ op_27c_3, 0, 636, 8, 4, 0 }, /* ANDSR */
+{ op_280_3, 0, 640, 2, 3, 0 }, /* AND */
+{ op_290_3, 0, 656, 0, 5, 2 }, /* AND */
+{ op_298_3, 0, 664, 0, 5, 2 }, /* AND */
+{ op_2a0_3, 0, 672, 2, 5, 2 }, /* AND */
+{ op_2a8_3, 0, 680, 0, 6, 2 }, /* AND */
+{ op_2b0_3, 0, 688, 2, 6, 2 }, /* AND */
+{ op_2b8_3, 0, 696, 0, 6, 2 }, /* AND */
+{ op_2b9_3, 0, 697, 0, 7, 2 }, /* AND */
+{ op_400_3, 0, 1024, 0, 2, 0 }, /* SUB */
+{ op_410_3, 0, 1040, 0, 3, 1 }, /* SUB */
+{ op_418_3, 0, 1048, 0, 3, 1 }, /* SUB */
+{ op_420_3, 0, 1056, 2, 3, 1 }, /* SUB */
+{ op_428_3, 0, 1064, 0, 4, 1 }, /* SUB */
+{ op_430_3, 0, 1072, 2, 4, 1 }, /* SUB */
+{ op_438_3, 0, 1080, 0, 4, 1 }, /* SUB */
+{ op_439_3, 0, 1081, 0, 5, 1 }, /* SUB */
+{ op_440_3, 0, 1088, 0, 2, 0 }, /* SUB */
+{ op_450_3, 0, 1104, 0, 3, 1 }, /* SUB */
+{ op_458_3, 0, 1112, 0, 3, 1 }, /* SUB */
+{ op_460_3, 0, 1120, 2, 3, 1 }, /* SUB */
+{ op_468_3, 0, 1128, 0, 4, 1 }, /* SUB */
+{ op_470_3, 0, 1136, 2, 4, 1 }, /* SUB */
+{ op_478_3, 0, 1144, 0, 4, 1 }, /* SUB */
+{ op_479_3, 0, 1145, 0, 5, 1 }, /* SUB */
+{ op_480_3, 0, 1152, 4, 3, 0 }, /* SUB */
+{ op_490_3, 0, 1168, 0, 5, 2 }, /* SUB */
+{ op_498_3, 0, 1176, 0, 5, 2 }, /* SUB */
+{ op_4a0_3, 0, 1184, 2, 5, 2 }, /* SUB */
+{ op_4a8_3, 0, 1192, 0, 6, 2 }, /* SUB */
+{ op_4b0_3, 0, 1200, 2, 6, 2 }, /* SUB */
+{ op_4b8_3, 0, 1208, 0, 6, 2 }, /* SUB */
+{ op_4b9_3, 0, 1209, 0, 7, 2 }, /* SUB */
+{ op_600_3, 0, 1536, 0, 2, 0 }, /* ADD */
+{ op_610_3, 0, 1552, 0, 3, 1 }, /* ADD */
+{ op_618_3, 0, 1560, 0, 3, 1 }, /* ADD */
+{ op_620_3, 0, 1568, 2, 3, 1 }, /* ADD */
+{ op_628_3, 0, 1576, 0, 4, 1 }, /* ADD */
+{ op_630_3, 0, 1584, 2, 4, 1 }, /* ADD */
+{ op_638_3, 0, 1592, 0, 4, 1 }, /* ADD */
+{ op_639_3, 0, 1593, 0, 5, 1 }, /* ADD */
+{ op_640_3, 0, 1600, 0, 2, 0 }, /* ADD */
+{ op_650_3, 0, 1616, 0, 3, 1 }, /* ADD */
+{ op_658_3, 0, 1624, 0, 3, 1 }, /* ADD */
+{ op_660_3, 0, 1632, 2, 3, 1 }, /* ADD */
+{ op_668_3, 0, 1640, 0, 4, 1 }, /* ADD */
+{ op_670_3, 0, 1648, 2, 4, 1 }, /* ADD */
+{ op_678_3, 0, 1656, 0, 4, 1 }, /* ADD */
+{ op_679_3, 0, 1657, 0, 5, 1 }, /* ADD */
+{ op_680_3, 0, 1664, 4, 3, 0 }, /* ADD */
+{ op_690_3, 0, 1680, 0, 5, 2 }, /* ADD */
+{ op_698_3, 0, 1688, 0, 5, 2 }, /* ADD */
+{ op_6a0_3, 0, 1696, 2, 5, 2 }, /* ADD */
+{ op_6a8_3, 0, 1704, 0, 6, 2 }, /* ADD */
+{ op_6b0_3, 0, 1712, 2, 6, 2 }, /* ADD */
+{ op_6b8_3, 0, 1720, 0, 6, 2 }, /* ADD */
+{ op_6b9_3, 0, 1721, 0, 7, 2 }, /* ADD */
+{ op_800_3, 0, 2048, 2, 2, 0 }, /* BTST */
+{ op_810_3, 0, 2064, 0, 3, 0 }, /* BTST */
+{ op_818_3, 0, 2072, 0, 3, 0 }, /* BTST */
+{ op_820_3, 0, 2080, 2, 3, 0 }, /* BTST */
+{ op_828_3, 0, 2088, 0, 4, 0 }, /* BTST */
+{ op_830_3, 0, 2096, 2, 4, 0 }, /* BTST */
+{ op_838_3, 0, 2104, 0, 4, 0 }, /* BTST */
+{ op_839_3, 0, 2105, 0, 5, 0 }, /* BTST */
+{ op_83a_3, 0, 2106, 0, 4, 0 }, /* BTST */
+{ op_83b_3, 0, 2107, 2, 4, 0 }, /* BTST */
+{ op_83c_3, 0, 2108, 0, 3, 0 }, /* BTST */
+{ op_840_3, 0, 2112, 4, 2, 0 }, /* BCHG */
+{ op_850_3, 0, 2128, 0, 3, 1 }, /* BCHG */
+{ op_858_3, 0, 2136, 0, 3, 1 }, /* BCHG */
+{ op_860_3, 0, 2144, 2, 3, 1 }, /* BCHG */
+{ op_868_3, 0, 2152, 0, 4, 1 }, /* BCHG */
+{ op_870_3, 0, 2160, 2, 4, 1 }, /* BCHG */
+{ op_878_3, 0, 2168, 0, 4, 1 }, /* BCHG */
+{ op_879_3, 0, 2169, 0, 5, 1 }, /* BCHG */
+{ op_87a_3, 0, 2170, 0, 4, 1 }, /* BCHG */
+{ op_87b_3, 0, 2171, 2, 4, 1 }, /* BCHG */
+{ op_880_3, 0, 2176, 6, 2, 0 }, /* BCLR */
+{ op_890_3, 0, 2192, 0, 3, 1 }, /* BCLR */
+{ op_898_3, 0, 2200, 0, 3, 1 }, /* BCLR */
+{ op_8a0_3, 0, 2208, 2, 3, 1 }, /* BCLR */
+{ op_8a8_3, 0, 2216, 0, 4, 1 }, /* BCLR */
+{ op_8b0_3, 0, 2224, 2, 4, 1 }, /* BCLR */
+{ op_8b8_3, 0, 2232, 0, 4, 1 }, /* BCLR */
+{ op_8b9_3, 0, 2233, 0, 5, 1 }, /* BCLR */
+{ op_8ba_3, 0, 2234, 0, 4, 1 }, /* BCLR */
+{ op_8bb_3, 0, 2235, 2, 4, 1 }, /* BCLR */
+{ op_8c0_3, 0, 2240, 4, 2, 0 }, /* BSET */
+{ op_8d0_3, 0, 2256, 0, 3, 1 }, /* BSET */
+{ op_8d8_3, 0, 2264, 0, 3, 1 }, /* BSET */
+{ op_8e0_3, 0, 2272, 2, 3, 1 }, /* BSET */
+{ op_8e8_3, 0, 2280, 0, 4, 1 }, /* BSET */
+{ op_8f0_3, 0, 2288, 2, 4, 1 }, /* BSET */
+{ op_8f8_3, 0, 2296, 0, 4, 1 }, /* BSET */
+{ op_8f9_3, 0, 2297, 0, 5, 1 }, /* BSET */
+{ op_8fa_3, 0, 2298, 0, 4, 1 }, /* BSET */
+{ op_8fb_3, 0, 2299, 2, 4, 1 }, /* BSET */
+{ op_a00_3, 0, 2560, 0, 2, 0 }, /* EOR */
+{ op_a10_3, 0, 2576, 0, 3, 1 }, /* EOR */
+{ op_a18_3, 0, 2584, 0, 3, 1 }, /* EOR */
+{ op_a20_3, 0, 2592, 2, 3, 1 }, /* EOR */
+{ op_a28_3, 0, 2600, 0, 4, 1 }, /* EOR */
+{ op_a30_3, 0, 2608, 2, 4, 1 }, /* EOR */
+{ op_a38_3, 0, 2616, 0, 4, 1 }, /* EOR */
+{ op_a39_3, 0, 2617, 0, 5, 1 }, /* EOR */
+{ op_a3c_3, 0, 2620, 8, 4, 0 }, /* EORSR */
+{ op_a40_3, 0, 2624, 0, 2, 0 }, /* EOR */
+{ op_a50_3, 0, 2640, 0, 3, 1 }, /* EOR */
+{ op_a58_3, 0, 2648, 0, 3, 1 }, /* EOR */
+{ op_a60_3, 0, 2656, 2, 3, 1 }, /* EOR */
+{ op_a68_3, 0, 2664, 0, 4, 1 }, /* EOR */
+{ op_a70_3, 0, 2672, 2, 4, 1 }, /* EOR */
+{ op_a78_3, 0, 2680, 0, 4, 1 }, /* EOR */
+{ op_a79_3, 0, 2681, 0, 5, 1 }, /* EOR */
+{ op_a7c_3, 0, 2684, 8, 4, 0 }, /* EORSR */
+{ op_a80_3, 0, 2688, 4, 3, 0 }, /* EOR */
+{ op_a90_3, 0, 2704, 0, 5, 2 }, /* EOR */
+{ op_a98_3, 0, 2712, 0, 5, 2 }, /* EOR */
+{ op_aa0_3, 0, 2720, 2, 5, 2 }, /* EOR */
+{ op_aa8_3, 0, 2728, 0, 6, 2 }, /* EOR */
+{ op_ab0_3, 0, 2736, 2, 6, 2 }, /* EOR */
+{ op_ab8_3, 0, 2744, 0, 6, 2 }, /* EOR */
+{ op_ab9_3, 0, 2745, 0, 7, 2 }, /* EOR */
+{ op_c00_3, 0, 3072, 0, 2, 0 }, /* CMP */
+{ op_c10_3, 0, 3088, 0, 3, 0 }, /* CMP */
+{ op_c18_3, 0, 3096, 0, 3, 0 }, /* CMP */
+{ op_c20_3, 0, 3104, 2, 3, 0 }, /* CMP */
+{ op_c28_3, 0, 3112, 0, 4, 0 }, /* CMP */
+{ op_c30_3, 0, 3120, 2, 4, 0 }, /* CMP */
+{ op_c38_3, 0, 3128, 0, 4, 0 }, /* CMP */
+{ op_c39_3, 0, 3129, 0, 5, 0 }, /* CMP */
+{ op_c3a_3, 0, 3130, 0, 4, 0 }, /* CMP */
+{ op_c3b_3, 0, 3131, 2, 4, 0 }, /* CMP */
+{ op_c40_3, 0, 3136, 0, 2, 0 }, /* CMP */
+{ op_c50_3, 0, 3152, 0, 3, 0 }, /* CMP */
+{ op_c58_3, 0, 3160, 0, 3, 0 }, /* CMP */
+{ op_c60_3, 0, 3168, 2, 3, 0 }, /* CMP */
+{ op_c68_3, 0, 3176, 0, 4, 0 }, /* CMP */
+{ op_c70_3, 0, 3184, 2, 4, 0 }, /* CMP */
+{ op_c78_3, 0, 3192, 0, 4, 0 }, /* CMP */
+{ op_c79_3, 0, 3193, 0, 5, 0 }, /* CMP */
+{ op_c7a_3, 0, 3194, 0, 4, 0 }, /* CMP */
+{ op_c7b_3, 0, 3195, 2, 4, 0 }, /* CMP */
+{ op_c80_3, 0, 3200, 2, 3, 0 }, /* CMP */
+{ op_c90_3, 0, 3216, 0, 5, 0 }, /* CMP */
+{ op_c98_3, 0, 3224, 0, 5, 0 }, /* CMP */
+{ op_ca0_3, 0, 3232, 2, 5, 0 }, /* CMP */
+{ op_ca8_3, 0, 3240, 0, 6, 0 }, /* CMP */
+{ op_cb0_3, 0, 3248, 2, 6, 0 }, /* CMP */
+{ op_cb8_3, 0, 3256, 0, 6, 0 }, /* CMP */
+{ op_cb9_3, 0, 3257, 0, 7, 0 }, /* CMP */
+{ op_cba_3, 0, 3258, 0, 6, 0 }, /* CMP */
+{ op_cbb_3, 0, 3259, 2, 6, 0 }, /* CMP */
+{ op_1000_3, 0, 4096, 0, 1, 0 }, /* MOVE */
+{ op_1010_3, 0, 4112, 0, 2, 0 }, /* MOVE */
+{ op_1018_3, 0, 4120, 0, 2, 0 }, /* MOVE */
+{ op_1020_3, 0, 4128, 2, 2, 0 }, /* MOVE */
+{ op_1028_3, 0, 4136, 0, 3, 0 }, /* MOVE */
+{ op_1030_3, 0, 4144, 2, 3, 0 }, /* MOVE */
+{ op_1038_3, 0, 4152, 0, 3, 0 }, /* MOVE */
+{ op_1039_3, 0, 4153, 0, 4, 0 }, /* MOVE */
+{ op_103a_3, 0, 4154, 0, 3, 0 }, /* MOVE */
+{ op_103b_3, 0, 4155, 2, 3, 0 }, /* MOVE */
+{ op_103c_3, 0, 4156, 0, 2, 0 }, /* MOVE */
+{ op_1080_3, 0, 4224, 0, 1, 1 }, /* MOVE */
+{ op_1090_3, 0, 4240, 0, 2, 1 }, /* MOVE */
+{ op_1098_3, 0, 4248, 0, 2, 1 }, /* MOVE */
+{ op_10a0_3, 0, 4256, 2, 2, 1 }, /* MOVE */
+{ op_10a8_3, 0, 4264, 0, 3, 1 }, /* MOVE */
+{ op_10b0_3, 0, 4272, 2, 3, 1 }, /* MOVE */
+{ op_10b8_3, 0, 4280, 0, 3, 1 }, /* MOVE */
+{ op_10b9_3, 0, 4281, 0, 4, 1 }, /* MOVE */
+{ op_10ba_3, 0, 4282, 0, 3, 1 }, /* MOVE */
+{ op_10bb_3, 0, 4283, 2, 3, 1 }, /* MOVE */
+{ op_10bc_3, 0, 4284, 0, 2, 1 }, /* MOVE */
+{ op_10c0_3, 0, 4288, 0, 1, 1 }, /* MOVE */
+{ op_10d0_3, 0, 4304, 0, 2, 1 }, /* MOVE */
+{ op_10d8_3, 0, 4312, 0, 2, 1 }, /* MOVE */
+{ op_10e0_3, 0, 4320, 2, 2, 1 }, /* MOVE */
+{ op_10e8_3, 0, 4328, 0, 3, 1 }, /* MOVE */
+{ op_10f0_3, 0, 4336, 2, 3, 1 }, /* MOVE */
+{ op_10f8_3, 0, 4344, 0, 3, 1 }, /* MOVE */
+{ op_10f9_3, 0, 4345, 0, 4, 1 }, /* MOVE */
+{ op_10fa_3, 0, 4346, 0, 3, 1 }, /* MOVE */
+{ op_10fb_3, 0, 4347, 2, 3, 1 }, /* MOVE */
+{ op_10fc_3, 0, 4348, 0, 2, 1 }, /* MOVE */
+{ op_1100_3, 0, 4352, 2, 1, 1 }, /* MOVE */
+{ op_1110_3, 0, 4368, 2, 2, 1 }, /* MOVE */
+{ op_1118_3, 0, 4376, 2, 2, 1 }, /* MOVE */
+{ op_1120_3, 0, 4384, 4, 2, 1 }, /* MOVE */
+{ op_1128_3, 0, 4392, 2, 3, 1 }, /* MOVE */
+{ op_1130_3, 0, 4400, 4, 3, 1 }, /* MOVE */
+{ op_1138_3, 0, 4408, 2, 3, 1 }, /* MOVE */
+{ op_1139_3, 0, 4409, 2, 4, 1 }, /* MOVE */
+{ op_113a_3, 0, 4410, 2, 3, 1 }, /* MOVE */
+{ op_113b_3, 0, 4411, 4, 3, 1 }, /* MOVE */
+{ op_113c_3, 0, 4412, 2, 2, 1 }, /* MOVE */
+{ op_1140_3, 0, 4416, 0, 2, 1 }, /* MOVE */
+{ op_1150_3, 0, 4432, 0, 3, 1 }, /* MOVE */
+{ op_1158_3, 0, 4440, 0, 3, 1 }, /* MOVE */
+{ op_1160_3, 0, 4448, 2, 3, 1 }, /* MOVE */
+{ op_1168_3, 0, 4456, 0, 4, 1 }, /* MOVE */
+{ op_1170_3, 0, 4464, 2, 4, 1 }, /* MOVE */
+{ op_1178_3, 0, 4472, 0, 4, 1 }, /* MOVE */
+{ op_1179_3, 0, 4473, 0, 5, 1 }, /* MOVE */
+{ op_117a_3, 0, 4474, 0, 4, 1 }, /* MOVE */
+{ op_117b_3, 0, 4475, 2, 4, 1 }, /* MOVE */
+{ op_117c_3, 0, 4476, 0, 3, 1 }, /* MOVE */
+{ op_1180_3, 0, 4480, 2, 2, 1 }, /* MOVE */
+{ op_1190_3, 0, 4496, 2, 3, 1 }, /* MOVE */
+{ op_1198_3, 0, 4504, 2, 3, 1 }, /* MOVE */
+{ op_11a0_3, 0, 4512, 4, 3, 1 }, /* MOVE */
+{ op_11a8_3, 0, 4520, 2, 4, 1 }, /* MOVE */
+{ op_11b0_3, 0, 4528, 4, 4, 1 }, /* MOVE */
+{ op_11b8_3, 0, 4536, 2, 4, 1 }, /* MOVE */
+{ op_11b9_3, 0, 4537, 2, 5, 1 }, /* MOVE */
+{ op_11ba_3, 0, 4538, 2, 4, 1 }, /* MOVE */
+{ op_11bb_3, 0, 4539, 4, 4, 1 }, /* MOVE */
+{ op_11bc_3, 0, 4540, 2, 3, 1 }, /* MOVE */
+{ op_11c0_3, 0, 4544, 0, 2, 1 }, /* MOVE */
+{ op_11d0_3, 0, 4560, 0, 3, 1 }, /* MOVE */
+{ op_11d8_3, 0, 4568, 0, 3, 1 }, /* MOVE */
+{ op_11e0_3, 0, 4576, 2, 3, 1 }, /* MOVE */
+{ op_11e8_3, 0, 4584, 0, 4, 1 }, /* MOVE */
+{ op_11f0_3, 0, 4592, 2, 4, 1 }, /* MOVE */
+{ op_11f8_3, 0, 4600, 0, 4, 1 }, /* MOVE */
+{ op_11f9_3, 0, 4601, 0, 5, 1 }, /* MOVE */
+{ op_11fa_3, 0, 4602, 0, 4, 1 }, /* MOVE */
+{ op_11fb_3, 0, 4603, 2, 4, 1 }, /* MOVE */
+{ op_11fc_3, 0, 4604, 0, 3, 1 }, /* MOVE */
+{ op_13c0_3, 0, 5056, 0, 3, 1 }, /* MOVE */
+{ op_13d0_3, 0, 5072, 0, 4, 1 }, /* MOVE */
+{ op_13d8_3, 0, 5080, 0, 4, 1 }, /* MOVE */
+{ op_13e0_3, 0, 5088, 2, 4, 1 }, /* MOVE */
+{ op_13e8_3, 0, 5096, 0, 5, 1 }, /* MOVE */
+{ op_13f0_3, 0, 5104, 2, 5, 1 }, /* MOVE */
+{ op_13f8_3, 0, 5112, 0, 5, 1 }, /* MOVE */
+{ op_13f9_3, 0, 5113, 0, 6, 1 }, /* MOVE */
+{ op_13fa_3, 0, 5114, 0, 5, 1 }, /* MOVE */
+{ op_13fb_3, 0, 5115, 2, 5, 1 }, /* MOVE */
+{ op_13fc_3, 0, 5116, 0, 4, 1 }, /* MOVE */
+{ op_2000_3, 0, 8192, 0, 1, 0 }, /* MOVE */
+{ op_2008_3, 0, 8200, 0, 1, 0 }, /* MOVE */
+{ op_2010_3, 0, 8208, 0, 3, 0 }, /* MOVE */
+{ op_2018_3, 0, 8216, 0, 3, 0 }, /* MOVE */
+{ op_2020_3, 0, 8224, 2, 3, 0 }, /* MOVE */
+{ op_2028_3, 0, 8232, 0, 4, 0 }, /* MOVE */
+{ op_2030_3, 0, 8240, 2, 4, 0 }, /* MOVE */
+{ op_2038_3, 0, 8248, 0, 4, 0 }, /* MOVE */
+{ op_2039_3, 0, 8249, 0, 5, 0 }, /* MOVE */
+{ op_203a_3, 0, 8250, 0, 4, 0 }, /* MOVE */
+{ op_203b_3, 0, 8251, 2, 4, 0 }, /* MOVE */
+{ op_203c_3, 0, 8252, 0, 3, 0 }, /* MOVE */
+{ op_2040_3, 0, 8256, 0, 1, 0 }, /* MOVEA */
+{ op_2048_3, 0, 8264, 0, 1, 0 }, /* MOVEA */
+{ op_2050_3, 0, 8272, 0, 3, 0 }, /* MOVEA */
+{ op_2058_3, 0, 8280, 0, 3, 0 }, /* MOVEA */
+{ op_2060_3, 0, 8288, 2, 3, 0 }, /* MOVEA */
+{ op_2068_3, 0, 8296, 0, 4, 0 }, /* MOVEA */
+{ op_2070_3, 0, 8304, 2, 4, 0 }, /* MOVEA */
+{ op_2078_3, 0, 8312, 0, 4, 0 }, /* MOVEA */
+{ op_2079_3, 0, 8313, 0, 5, 0 }, /* MOVEA */
+{ op_207a_3, 0, 8314, 0, 4, 0 }, /* MOVEA */
+{ op_207b_3, 0, 8315, 2, 4, 0 }, /* MOVEA */
+{ op_207c_3, 0, 8316, 0, 3, 0 }, /* MOVEA */
+{ op_2080_3, 0, 8320, 0, 1, 2 }, /* MOVE */
+{ op_2088_3, 0, 8328, 0, 1, 2 }, /* MOVE */
+{ op_2090_3, 0, 8336, 0, 3, 2 }, /* MOVE */
+{ op_2098_3, 0, 8344, 0, 3, 2 }, /* MOVE */
+{ op_20a0_3, 0, 8352, 2, 3, 2 }, /* MOVE */
+{ op_20a8_3, 0, 8360, 0, 4, 2 }, /* MOVE */
+{ op_20b0_3, 0, 8368, 2, 4, 2 }, /* MOVE */
+{ op_20b8_3, 0, 8376, 0, 4, 2 }, /* MOVE */
+{ op_20b9_3, 0, 8377, 0, 5, 2 }, /* MOVE */
+{ op_20ba_3, 0, 8378, 0, 4, 2 }, /* MOVE */
+{ op_20bb_3, 0, 8379, 2, 4, 2 }, /* MOVE */
+{ op_20bc_3, 0, 8380, 0, 3, 2 }, /* MOVE */
+{ op_20c0_3, 0, 8384, 0, 1, 2 }, /* MOVE */
+{ op_20c8_3, 0, 8392, 0, 1, 2 }, /* MOVE */
+{ op_20d0_3, 0, 8400, 0, 3, 2 }, /* MOVE */
+{ op_20d8_3, 0, 8408, 0, 3, 2 }, /* MOVE */
+{ op_20e0_3, 0, 8416, 2, 3, 2 }, /* MOVE */
+{ op_20e8_3, 0, 8424, 0, 4, 2 }, /* MOVE */
+{ op_20f0_3, 0, 8432, 2, 4, 2 }, /* MOVE */
+{ op_20f8_3, 0, 8440, 0, 4, 2 }, /* MOVE */
+{ op_20f9_3, 0, 8441, 0, 5, 2 }, /* MOVE */
+{ op_20fa_3, 0, 8442, 0, 4, 2 }, /* MOVE */
+{ op_20fb_3, 0, 8443, 2, 4, 2 }, /* MOVE */
+{ op_20fc_3, 0, 8444, 0, 3, 2 }, /* MOVE */
+{ op_2100_3, 0, 8448, 2, 1, 2 }, /* MOVE */
+{ op_2108_3, 0, 8456, 2, 1, 2 }, /* MOVE */
+{ op_2110_3, 0, 8464, 2, 3, 2 }, /* MOVE */
+{ op_2118_3, 0, 8472, 2, 3, 2 }, /* MOVE */
+{ op_2120_3, 0, 8480, 4, 3, 2 }, /* MOVE */
+{ op_2128_3, 0, 8488, 2, 4, 2 }, /* MOVE */
+{ op_2130_3, 0, 8496, 4, 4, 2 }, /* MOVE */
+{ op_2138_3, 0, 8504, 2, 4, 2 }, /* MOVE */
+{ op_2139_3, 0, 8505, 2, 5, 2 }, /* MOVE */
+{ op_213a_3, 0, 8506, 2, 4, 2 }, /* MOVE */
+{ op_213b_3, 0, 8507, 4, 4, 2 }, /* MOVE */
+{ op_213c_3, 0, 8508, 2, 3, 2 }, /* MOVE */
+{ op_2140_3, 0, 8512, 0, 2, 2 }, /* MOVE */
+{ op_2148_3, 0, 8520, 0, 2, 2 }, /* MOVE */
+{ op_2150_3, 0, 8528, 0, 4, 2 }, /* MOVE */
+{ op_2158_3, 0, 8536, 0, 4, 2 }, /* MOVE */
+{ op_2160_3, 0, 8544, 2, 4, 2 }, /* MOVE */
+{ op_2168_3, 0, 8552, 0, 5, 2 }, /* MOVE */
+{ op_2170_3, 0, 8560, 2, 5, 2 }, /* MOVE */
+{ op_2178_3, 0, 8568, 0, 5, 2 }, /* MOVE */
+{ op_2179_3, 0, 8569, 0, 6, 2 }, /* MOVE */
+{ op_217a_3, 0, 8570, 0, 5, 2 }, /* MOVE */
+{ op_217b_3, 0, 8571, 2, 5, 2 }, /* MOVE */
+{ op_217c_3, 0, 8572, 0, 4, 2 }, /* MOVE */
+{ op_2180_3, 0, 8576, 2, 2, 2 }, /* MOVE */
+{ op_2188_3, 0, 8584, 2, 2, 2 }, /* MOVE */
+{ op_2190_3, 0, 8592, 2, 4, 2 }, /* MOVE */
+{ op_2198_3, 0, 8600, 2, 4, 2 }, /* MOVE */
+{ op_21a0_3, 0, 8608, 4, 4, 2 }, /* MOVE */
+{ op_21a8_3, 0, 8616, 2, 5, 2 }, /* MOVE */
+{ op_21b0_3, 0, 8624, 4, 5, 2 }, /* MOVE */
+{ op_21b8_3, 0, 8632, 2, 5, 2 }, /* MOVE */
+{ op_21b9_3, 0, 8633, 2, 6, 2 }, /* MOVE */
+{ op_21ba_3, 0, 8634, 2, 5, 2 }, /* MOVE */
+{ op_21bb_3, 0, 8635, 4, 5, 2 }, /* MOVE */
+{ op_21bc_3, 0, 8636, 2, 4, 2 }, /* MOVE */
+{ op_21c0_3, 0, 8640, 0, 2, 2 }, /* MOVE */
+{ op_21c8_3, 0, 8648, 0, 2, 2 }, /* MOVE */
+{ op_21d0_3, 0, 8656, 0, 4, 2 }, /* MOVE */
+{ op_21d8_3, 0, 8664, 0, 4, 2 }, /* MOVE */
+{ op_21e0_3, 0, 8672, 2, 4, 2 }, /* MOVE */
+{ op_21e8_3, 0, 8680, 0, 5, 2 }, /* MOVE */
+{ op_21f0_3, 0, 8688, 2, 5, 2 }, /* MOVE */
+{ op_21f8_3, 0, 8696, 0, 5, 2 }, /* MOVE */
+{ op_21f9_3, 0, 8697, 0, 6, 2 }, /* MOVE */
+{ op_21fa_3, 0, 8698, 0, 5, 2 }, /* MOVE */
+{ op_21fb_3, 0, 8699, 2, 5, 2 }, /* MOVE */
+{ op_21fc_3, 0, 8700, 0, 4, 2 }, /* MOVE */
+{ op_23c0_3, 0, 9152, 0, 3, 2 }, /* MOVE */
+{ op_23c8_3, 0, 9160, 0, 3, 2 }, /* MOVE */
+{ op_23d0_3, 0, 9168, 0, 5, 2 }, /* MOVE */
+{ op_23d8_3, 0, 9176, 0, 5, 2 }, /* MOVE */
+{ op_23e0_3, 0, 9184, 2, 5, 2 }, /* MOVE */
+{ op_23e8_3, 0, 9192, 0, 6, 2 }, /* MOVE */
+{ op_23f0_3, 0, 9200, 2, 6, 2 }, /* MOVE */
+{ op_23f8_3, 0, 9208, 0, 6, 2 }, /* MOVE */
+{ op_23f9_3, 0, 9209, 0, 7, 2 }, /* MOVE */
+{ op_23fa_3, 0, 9210, 0, 6, 2 }, /* MOVE */
+{ op_23fb_3, 0, 9211, 2, 6, 2 }, /* MOVE */
+{ op_23fc_3, 0, 9212, 0, 5, 2 }, /* MOVE */
+{ op_3000_3, 0, 12288, 0, 1, 0 }, /* MOVE */
+{ op_3008_3, 0, 12296, 0, 1, 0 }, /* MOVE */
+{ op_3010_3, 0, 12304, 0, 2, 0 }, /* MOVE */
+{ op_3018_3, 0, 12312, 0, 2, 0 }, /* MOVE */
+{ op_3020_3, 0, 12320, 2, 2, 0 }, /* MOVE */
+{ op_3028_3, 0, 12328, 0, 3, 0 }, /* MOVE */
+{ op_3030_3, 0, 12336, 2, 3, 0 }, /* MOVE */
+{ op_3038_3, 0, 12344, 0, 3, 0 }, /* MOVE */
+{ op_3039_3, 0, 12345, 0, 4, 0 }, /* MOVE */
+{ op_303a_3, 0, 12346, 0, 3, 0 }, /* MOVE */
+{ op_303b_3, 0, 12347, 2, 3, 0 }, /* MOVE */
+{ op_303c_3, 0, 12348, 0, 2, 0 }, /* MOVE */
+{ op_3040_3, 0, 12352, 0, 1, 0 }, /* MOVEA */
+{ op_3048_3, 0, 12360, 0, 1, 0 }, /* MOVEA */
+{ op_3050_3, 0, 12368, 0, 2, 0 }, /* MOVEA */
+{ op_3058_3, 0, 12376, 0, 2, 0 }, /* MOVEA */
+{ op_3060_3, 0, 12384, 2, 2, 0 }, /* MOVEA */
+{ op_3068_3, 0, 12392, 0, 3, 0 }, /* MOVEA */
+{ op_3070_3, 0, 12400, 2, 3, 0 }, /* MOVEA */
+{ op_3078_3, 0, 12408, 0, 3, 0 }, /* MOVEA */
+{ op_3079_3, 0, 12409, 0, 4, 0 }, /* MOVEA */
+{ op_307a_3, 0, 12410, 0, 3, 0 }, /* MOVEA */
+{ op_307b_3, 0, 12411, 2, 3, 0 }, /* MOVEA */
+{ op_307c_3, 0, 12412, 0, 2, 0 }, /* MOVEA */
+{ op_3080_3, 0, 12416, 0, 1, 1 }, /* MOVE */
+{ op_3088_3, 0, 12424, 0, 1, 1 }, /* MOVE */
+{ op_3090_3, 0, 12432, 0, 2, 1 }, /* MOVE */
+{ op_3098_3, 0, 12440, 0, 2, 1 }, /* MOVE */
+{ op_30a0_3, 0, 12448, 2, 2, 1 }, /* MOVE */
+{ op_30a8_3, 0, 12456, 0, 3, 1 }, /* MOVE */
+{ op_30b0_3, 0, 12464, 2, 3, 1 }, /* MOVE */
+{ op_30b8_3, 0, 12472, 0, 3, 1 }, /* MOVE */
+{ op_30b9_3, 0, 12473, 0, 4, 1 }, /* MOVE */
+{ op_30ba_3, 0, 12474, 0, 3, 1 }, /* MOVE */
+{ op_30bb_3, 0, 12475, 2, 3, 1 }, /* MOVE */
+{ op_30bc_3, 0, 12476, 0, 2, 1 }, /* MOVE */
+{ op_30c0_3, 0, 12480, 0, 1, 1 }, /* MOVE */
+{ op_30c8_3, 0, 12488, 0, 1, 1 }, /* MOVE */
+{ op_30d0_3, 0, 12496, 0, 2, 1 }, /* MOVE */
+{ op_30d8_3, 0, 12504, 0, 2, 1 }, /* MOVE */
+{ op_30e0_3, 0, 12512, 2, 2, 1 }, /* MOVE */
+{ op_30e8_3, 0, 12520, 0, 3, 1 }, /* MOVE */
+{ op_30f0_3, 0, 12528, 2, 3, 1 }, /* MOVE */
+{ op_30f8_3, 0, 12536, 0, 3, 1 }, /* MOVE */
+{ op_30f9_3, 0, 12537, 0, 4, 1 }, /* MOVE */
+{ op_30fa_3, 0, 12538, 0, 3, 1 }, /* MOVE */
+{ op_30fb_3, 0, 12539, 2, 3, 1 }, /* MOVE */
+{ op_30fc_3, 0, 12540, 0, 2, 1 }, /* MOVE */
+{ op_3100_3, 0, 12544, 2, 1, 1 }, /* MOVE */
+{ op_3108_3, 0, 12552, 2, 1, 1 }, /* MOVE */
+{ op_3110_3, 0, 12560, 2, 2, 1 }, /* MOVE */
+{ op_3118_3, 0, 12568, 2, 2, 1 }, /* MOVE */
+{ op_3120_3, 0, 12576, 4, 2, 1 }, /* MOVE */
+{ op_3128_3, 0, 12584, 2, 3, 1 }, /* MOVE */
+{ op_3130_3, 0, 12592, 4, 3, 1 }, /* MOVE */
+{ op_3138_3, 0, 12600, 2, 3, 1 }, /* MOVE */
+{ op_3139_3, 0, 12601, 2, 4, 1 }, /* MOVE */
+{ op_313a_3, 0, 12602, 2, 3, 1 }, /* MOVE */
+{ op_313b_3, 0, 12603, 4, 3, 1 }, /* MOVE */
+{ op_313c_3, 0, 12604, 2, 2, 1 }, /* MOVE */
+{ op_3140_3, 0, 12608, 0, 2, 1 }, /* MOVE */
+{ op_3148_3, 0, 12616, 0, 2, 1 }, /* MOVE */
+{ op_3150_3, 0, 12624, 0, 3, 1 }, /* MOVE */
+{ op_3158_3, 0, 12632, 0, 3, 1 }, /* MOVE */
+{ op_3160_3, 0, 12640, 2, 3, 1 }, /* MOVE */
+{ op_3168_3, 0, 12648, 0, 4, 1 }, /* MOVE */
+{ op_3170_3, 0, 12656, 2, 4, 1 }, /* MOVE */
+{ op_3178_3, 0, 12664, 0, 4, 1 }, /* MOVE */
+{ op_3179_3, 0, 12665, 0, 5, 1 }, /* MOVE */
+{ op_317a_3, 0, 12666, 0, 4, 1 }, /* MOVE */
+{ op_317b_3, 0, 12667, 2, 4, 1 }, /* MOVE */
+{ op_317c_3, 0, 12668, 0, 3, 1 }, /* MOVE */
+{ op_3180_3, 0, 12672, 2, 2, 1 }, /* MOVE */
+{ op_3188_3, 0, 12680, 2, 2, 1 }, /* MOVE */
+{ op_3190_3, 0, 12688, 2, 3, 1 }, /* MOVE */
+{ op_3198_3, 0, 12696, 2, 3, 1 }, /* MOVE */
+{ op_31a0_3, 0, 12704, 4, 3, 1 }, /* MOVE */
+{ op_31a8_3, 0, 12712, 2, 4, 1 }, /* MOVE */
+{ op_31b0_3, 0, 12720, 4, 4, 1 }, /* MOVE */
+{ op_31b8_3, 0, 12728, 2, 4, 1 }, /* MOVE */
+{ op_31b9_3, 0, 12729, 2, 5, 1 }, /* MOVE */
+{ op_31ba_3, 0, 12730, 2, 4, 1 }, /* MOVE */
+{ op_31bb_3, 0, 12731, 4, 4, 1 }, /* MOVE */
+{ op_31bc_3, 0, 12732, 2, 3, 1 }, /* MOVE */
+{ op_31c0_3, 0, 12736, 0, 2, 1 }, /* MOVE */
+{ op_31c8_3, 0, 12744, 0, 2, 1 }, /* MOVE */
+{ op_31d0_3, 0, 12752, 0, 3, 1 }, /* MOVE */
+{ op_31d8_3, 0, 12760, 0, 3, 1 }, /* MOVE */
+{ op_31e0_3, 0, 12768, 2, 3, 1 }, /* MOVE */
+{ op_31e8_3, 0, 12776, 0, 4, 1 }, /* MOVE */
+{ op_31f0_3, 0, 12784, 2, 4, 1 }, /* MOVE */
+{ op_31f8_3, 0, 12792, 0, 4, 1 }, /* MOVE */
+{ op_31f9_3, 0, 12793, 0, 5, 1 }, /* MOVE */
+{ op_31fa_3, 0, 12794, 0, 4, 1 }, /* MOVE */
+{ op_31fb_3, 0, 12795, 2, 4, 1 }, /* MOVE */
+{ op_31fc_3, 0, 12796, 0, 3, 1 }, /* MOVE */
+{ op_33c0_3, 0, 13248, 0, 3, 1 }, /* MOVE */
+{ op_33c8_3, 0, 13256, 0, 3, 1 }, /* MOVE */
+{ op_33d0_3, 0, 13264, 0, 4, 1 }, /* MOVE */
+{ op_33d8_3, 0, 13272, 0, 4, 1 }, /* MOVE */
+{ op_33e0_3, 0, 13280, 2, 4, 1 }, /* MOVE */
+{ op_33e8_3, 0, 13288, 0, 5, 1 }, /* MOVE */
+{ op_33f0_3, 0, 13296, 2, 5, 1 }, /* MOVE */
+{ op_33f8_3, 0, 13304, 0, 5, 1 }, /* MOVE */
+{ op_33f9_3, 0, 13305, 0, 6, 1 }, /* MOVE */
+{ op_33fa_3, 0, 13306, 0, 5, 1 }, /* MOVE */
+{ op_33fb_3, 0, 13307, 2, 5, 1 }, /* MOVE */
+{ op_33fc_3, 0, 13308, 0, 4, 1 }, /* MOVE */
+{ op_4000_3, 0, 16384, 0, 1, 0 }, /* NEGX */
+{ op_4010_3, 0, 16400, 0, 2, 1 }, /* NEGX */
+{ op_4018_3, 0, 16408, 0, 2, 1 }, /* NEGX */
+{ op_4020_3, 0, 16416, 2, 2, 1 }, /* NEGX */
+{ op_4028_3, 0, 16424, 0, 3, 1 }, /* NEGX */
+{ op_4030_3, 0, 16432, 2, 3, 1 }, /* NEGX */
+{ op_4038_3, 0, 16440, 0, 3, 1 }, /* NEGX */
+{ op_4039_3, 0, 16441, 0, 4, 1 }, /* NEGX */
+{ op_4040_3, 0, 16448, 0, 1, 0 }, /* NEGX */
+{ op_4050_3, 0, 16464, 0, 2, 1 }, /* NEGX */
+{ op_4058_3, 0, 16472, 0, 2, 1 }, /* NEGX */
+{ op_4060_3, 0, 16480, 2, 2, 1 }, /* NEGX */
+{ op_4068_3, 0, 16488, 0, 3, 1 }, /* NEGX */
+{ op_4070_3, 0, 16496, 2, 3, 1 }, /* NEGX */
+{ op_4078_3, 0, 16504, 0, 3, 1 }, /* NEGX */
+{ op_4079_3, 0, 16505, 0, 4, 1 }, /* NEGX */
+{ op_4080_3, 0, 16512, 2, 1, 0 }, /* NEGX */
+{ op_4090_3, 0, 16528, 0, 3, 2 }, /* NEGX */
+{ op_4098_3, 0, 16536, 0, 3, 2 }, /* NEGX */
+{ op_40a0_3, 0, 16544, 2, 3, 2 }, /* NEGX */
+{ op_40a8_3, 0, 16552, 0, 4, 2 }, /* NEGX */
+{ op_40b0_3, 0, 16560, 2, 4, 2 }, /* NEGX */
+{ op_40b8_3, 0, 16568, 0, 4, 2 }, /* NEGX */
+{ op_40b9_3, 0, 16569, 0, 5, 2 }, /* NEGX */
+{ op_40c0_3, 0, 16576, 2, 1, 0 }, /* MVSR2 */
+{ op_40d0_3, 0, 16592, 0, 1, 1 }, /* MVSR2 */
+{ op_40d8_3, 0, 16600, 0, 1, 1 }, /* MVSR2 */
+{ op_40e0_3, 0, 16608, 2, 1, 1 }, /* MVSR2 */
+{ op_40e8_3, 0, 16616, 0, 2, 1 }, /* MVSR2 */
+{ op_40f0_3, 0, 16624, 2, 2, 1 }, /* MVSR2 */
+{ op_40f8_3, 0, 16632, 0, 2, 1 }, /* MVSR2 */
+{ op_40f9_3, 0, 16633, 0, 3, 1 }, /* MVSR2 */
+{ op_4100_3, 0, 16640, 6, 1, 0 }, /* CHK */
+{ op_4110_3, 0, 16656, 6, 3, 0 }, /* CHK */
+{ op_4118_3, 0, 16664, 6, 3, 0 }, /* CHK */
+{ op_4120_3, 0, 16672, 8, 3, 0 }, /* CHK */
+{ op_4128_3, 0, 16680, 6, 4, 0 }, /* CHK */
+{ op_4130_3, 0, 16688, 8, 4, 0 }, /* CHK */
+{ op_4138_3, 0, 16696, 6, 4, 0 }, /* CHK */
+{ op_4139_3, 0, 16697, 6, 5, 0 }, /* CHK */
+{ op_413a_3, 0, 16698, 6, 4, 0 }, /* CHK */
+{ op_413b_3, 0, 16699, 8, 4, 0 }, /* CHK */
+{ op_413c_3, 0, 16700, 6, 3, 0 }, /* CHK */
+{ op_4180_3, 0, 16768, 6, 1, 0 }, /* CHK */
+{ op_4190_3, 0, 16784, 6, 2, 0 }, /* CHK */
+{ op_4198_3, 0, 16792, 6, 2, 0 }, /* CHK */
+{ op_41a0_3, 0, 16800, 8, 2, 0 }, /* CHK */
+{ op_41a8_3, 0, 16808, 6, 3, 0 }, /* CHK */
+{ op_41b0_3, 0, 16816, 8, 3, 0 }, /* CHK */
+{ op_41b8_3, 0, 16824, 6, 3, 0 }, /* CHK */
+{ op_41b9_3, 0, 16825, 6, 4, 0 }, /* CHK */
+{ op_41ba_3, 0, 16826, 6, 3, 0 }, /* CHK */
+{ op_41bb_3, 0, 16827, 8, 3, 0 }, /* CHK */
+{ op_41bc_3, 0, 16828, 6, 2, 0 }, /* CHK */
+{ op_41d0_3, 0, 16848, 0, 1, 0 }, /* LEA */
+{ op_41e8_3, 0, 16872, 0, 2, 0 }, /* LEA */
+{ op_41f0_3, 0, 16880, 4, 2, 0 }, /* LEA */
+{ op_41f8_3, 0, 16888, 0, 2, 0 }, /* LEA */
+{ op_41f9_3, 0, 16889, 0, 3, 0 }, /* LEA */
+{ op_41fa_3, 0, 16890, 0, 2, 0 }, /* LEA */
+{ op_41fb_3, 0, 16891, 4, 2, 0 }, /* LEA */
+{ op_4200_3, 0, 16896, 0, 1, 0 }, /* CLR */
+{ op_4210_3, 0, 16912, 0, 1, 1 }, /* CLR */
+{ op_4218_3, 0, 16920, 0, 1, 1 }, /* CLR */
+{ op_4220_3, 0, 16928, 2, 1, 1 }, /* CLR */
+{ op_4228_3, 0, 16936, 0, 2, 1 }, /* CLR */
+{ op_4230_3, 0, 16944, 2, 2, 1 }, /* CLR */
+{ op_4238_3, 0, 16952, 0, 2, 1 }, /* CLR */
+{ op_4239_3, 0, 16953, 0, 3, 1 }, /* CLR */
+{ op_4240_3, 0, 16960, 0, 1, 0 }, /* CLR */
+{ op_4250_3, 0, 16976, 0, 1, 1 }, /* CLR */
+{ op_4258_3, 0, 16984, 0, 1, 1 }, /* CLR */
+{ op_4260_3, 0, 16992, 2, 1, 1 }, /* CLR */
+{ op_4268_3, 0, 17000, 0, 2, 1 }, /* CLR */
+{ op_4270_3, 0, 17008, 2, 2, 1 }, /* CLR */
+{ op_4278_3, 0, 17016, 0, 2, 1 }, /* CLR */
+{ op_4279_3, 0, 17017, 0, 3, 1 }, /* CLR */
+{ op_4280_3, 0, 17024, 2, 1, 0 }, /* CLR */
+{ op_4290_3, 0, 17040, 0, 1, 2 }, /* CLR */
+{ op_4298_3, 0, 17048, 0, 1, 2 }, /* CLR */
+{ op_42a0_3, 0, 17056, 2, 1, 2 }, /* CLR */
+{ op_42a8_3, 0, 17064, 0, 2, 2 }, /* CLR */
+{ op_42b0_3, 0, 17072, 2, 2, 2 }, /* CLR */
+{ op_42b8_3, 0, 17080, 0, 2, 2 }, /* CLR */
+{ op_42b9_3, 0, 17081, 0, 3, 2 }, /* CLR */
+{ op_4400_3, 0, 17408, 0, 1, 0 }, /* NEG */
+{ op_4410_3, 0, 17424, 0, 2, 1 }, /* NEG */
+{ op_4418_3, 0, 17432, 0, 2, 1 }, /* NEG */
+{ op_4420_3, 0, 17440, 2, 2, 1 }, /* NEG */
+{ op_4428_3, 0, 17448, 0, 3, 1 }, /* NEG */
+{ op_4430_3, 0, 17456, 2, 3, 1 }, /* NEG */
+{ op_4438_3, 0, 17464, 0, 3, 1 }, /* NEG */
+{ op_4439_3, 0, 17465, 0, 4, 1 }, /* NEG */
+{ op_4440_3, 0, 17472, 0, 1, 0 }, /* NEG */
+{ op_4450_3, 0, 17488, 0, 2, 1 }, /* NEG */
+{ op_4458_3, 0, 17496, 0, 2, 1 }, /* NEG */
+{ op_4460_3, 0, 17504, 2, 2, 1 }, /* NEG */
+{ op_4468_3, 0, 17512, 0, 3, 1 }, /* NEG */
+{ op_4470_3, 0, 17520, 2, 3, 1 }, /* NEG */
+{ op_4478_3, 0, 17528, 0, 3, 1 }, /* NEG */
+{ op_4479_3, 0, 17529, 0, 4, 1 }, /* NEG */
+{ op_4480_3, 0, 17536, 2, 1, 0 }, /* NEG */
+{ op_4490_3, 0, 17552, 0, 3, 2 }, /* NEG */
+{ op_4498_3, 0, 17560, 0, 3, 2 }, /* NEG */
+{ op_44a0_3, 0, 17568, 2, 3, 2 }, /* NEG */
+{ op_44a8_3, 0, 17576, 0, 4, 2 }, /* NEG */
+{ op_44b0_3, 0, 17584, 2, 4, 2 }, /* NEG */
+{ op_44b8_3, 0, 17592, 0, 4, 2 }, /* NEG */
+{ op_44b9_3, 0, 17593, 0, 5, 2 }, /* NEG */
+{ op_44c0_3, 0, 17600, 4, 2, 0 }, /* MV2SR */
+{ op_44d0_3, 0, 17616, 4, 3, 0 }, /* MV2SR */
+{ op_44d8_3, 0, 17624, 4, 3, 0 }, /* MV2SR */
+{ op_44e0_3, 0, 17632, 6, 3, 0 }, /* MV2SR */
+{ op_44e8_3, 0, 17640, 4, 4, 0 }, /* MV2SR */
+{ op_44f0_3, 0, 17648, 6, 4, 0 }, /* MV2SR */
+{ op_44f8_3, 0, 17656, 4, 4, 0 }, /* MV2SR */
+{ op_44f9_3, 0, 17657, 4, 5, 0 }, /* MV2SR */
+{ op_44fa_3, 0, 17658, 4, 4, 0 }, /* MV2SR */
+{ op_44fb_3, 0, 17659, 6, 4, 0 }, /* MV2SR */
+{ op_44fc_3, 0, 17660, 4, 3, 0 }, /* MV2SR */
+{ op_4600_3, 0, 17920, 0, 1, 0 }, /* NOT */
+{ op_4610_3, 0, 17936, 0, 2, 1 }, /* NOT */
+{ op_4618_3, 0, 17944, 0, 2, 1 }, /* NOT */
+{ op_4620_3, 0, 17952, 2, 2, 1 }, /* NOT */
+{ op_4628_3, 0, 17960, 0, 3, 1 }, /* NOT */
+{ op_4630_3, 0, 17968, 2, 3, 1 }, /* NOT */
+{ op_4638_3, 0, 17976, 0, 3, 1 }, /* NOT */
+{ op_4639_3, 0, 17977, 0, 4, 1 }, /* NOT */
+{ op_4640_3, 0, 17984, 0, 1, 0 }, /* NOT */
+{ op_4650_3, 0, 18000, 0, 2, 1 }, /* NOT */
+{ op_4658_3, 0, 18008, 0, 2, 1 }, /* NOT */
+{ op_4660_3, 0, 18016, 2, 2, 1 }, /* NOT */
+{ op_4668_3, 0, 18024, 0, 3, 1 }, /* NOT */
+{ op_4670_3, 0, 18032, 2, 3, 1 }, /* NOT */
+{ op_4678_3, 0, 18040, 0, 3, 1 }, /* NOT */
+{ op_4679_3, 0, 18041, 0, 4, 1 }, /* NOT */
+{ op_4680_3, 0, 18048, 2, 1, 0 }, /* NOT */
+{ op_4690_3, 0, 18064, 0, 3, 2 }, /* NOT */
+{ op_4698_3, 0, 18072, 0, 3, 2 }, /* NOT */
+{ op_46a0_3, 0, 18080, 2, 3, 2 }, /* NOT */
+{ op_46a8_3, 0, 18088, 0, 4, 2 }, /* NOT */
+{ op_46b0_3, 0, 18096, 2, 4, 2 }, /* NOT */
+{ op_46b8_3, 0, 18104, 0, 4, 2 }, /* NOT */
+{ op_46b9_3, 0, 18105, 0, 5, 2 }, /* NOT */
+{ op_46c0_3, 0, 18112, 4, 2, 0 }, /* MV2SR */
+{ op_46d0_3, 0, 18128, 4, 3, 0 }, /* MV2SR */
+{ op_46d8_3, 0, 18136, 4, 3, 0 }, /* MV2SR */
+{ op_46e0_3, 0, 18144, 6, 3, 0 }, /* MV2SR */
+{ op_46e8_3, 0, 18152, 4, 4, 0 }, /* MV2SR */
+{ op_46f0_3, 0, 18160, 6, 4, 0 }, /* MV2SR */
+{ op_46f8_3, 0, 18168, 4, 4, 0 }, /* MV2SR */
+{ op_46f9_3, 0, 18169, 4, 5, 0 }, /* MV2SR */
+{ op_46fa_3, 0, 18170, 4, 4, 0 }, /* MV2SR */
+{ op_46fb_3, 0, 18171, 6, 4, 0 }, /* MV2SR */
+{ op_46fc_3, 0, 18172, 4, 3, 0 }, /* MV2SR */
+{ op_4800_3, 0, 18432, 2, 1, 0 }, /* NBCD */
+{ op_4810_3, 0, 18448, 0, 2, 1 }, /* NBCD */
+{ op_4818_3, 0, 18456, 0, 2, 1 }, /* NBCD */
+{ op_4820_3, 0, 18464, 2, 2, 1 }, /* NBCD */
+{ op_4828_3, 0, 18472, 0, 3, 1 }, /* NBCD */
+{ op_4830_3, 0, 18480, 2, 3, 1 }, /* NBCD */
+{ op_4838_3, 0, 18488, 0, 3, 1 }, /* NBCD */
+{ op_4839_3, 0, 18489, 0, 4, 1 }, /* NBCD */
+{ op_4840_3, 0, 18496, 0, 1, 0 }, /* SWAP */
+{ op_4850_3, 0, 18512, 2, 1, 2 }, /* PEA */
+{ op_4868_3, 0, 18536, 2, 2, 2 }, /* PEA */
+{ op_4870_3, 0, 18544, 5, 2, 2 }, /* PEA */
+{ op_4878_3, 0, 18552, 2, 2, 2 }, /* PEA */
+{ op_4879_3, 0, 18553, 2, 3, 2 }, /* PEA */
+{ op_487a_3, 0, 18554, 2, 2, 2 }, /* PEA */
+{ op_487b_3, 0, 18555, 5, 2, 2 }, /* PEA */
+{ op_4880_3, 0, 18560, 0, 1, 0 }, /* EXT */
+{ op_4890_3, 0, 18576, 0, 2, 255 }, /* MVMLE */
+{ op_48a0_3, 0, 18592, 2, 2, 255 }, /* MVMLE */
+{ op_48a8_3, 0, 18600, 0, 3, 255 }, /* MVMLE */
+{ op_48b0_3, 0, 18608, 2, 3, 255 }, /* MVMLE */
+{ op_48b8_3, 0, 18616, 0, 3, 255 }, /* MVMLE */
+{ op_48b9_3, 0, 18617, 0, 4, 255 }, /* MVMLE */
+{ op_48c0_3, 0, 18624, 0, 1, 0 }, /* EXT */
+{ op_48d0_3, 0, 18640, 0, 2, 255 }, /* MVMLE */
+{ op_48e0_3, 0, 18656, 2, 2, 255 }, /* MVMLE */
+{ op_48e8_3, 0, 18664, 0, 3, 255 }, /* MVMLE */
+{ op_48f0_3, 0, 18672, 2, 3, 255 }, /* MVMLE */
+{ op_48f8_3, 0, 18680, 0, 3, 255 }, /* MVMLE */
+{ op_48f9_3, 0, 18681, 0, 4, 255 }, /* MVMLE */
+{ op_49c0_3, 0, 18880, 0, 1, 0 }, /* EXT */
+{ op_4a00_3, 0, 18944, 0, 1, 0 }, /* TST */
+{ op_4a10_3, 0, 18960, 0, 2, 0 }, /* TST */
+{ op_4a18_3, 0, 18968, 0, 2, 0 }, /* TST */
+{ op_4a20_3, 0, 18976, 2, 2, 0 }, /* TST */
+{ op_4a28_3, 0, 18984, 0, 3, 0 }, /* TST */
+{ op_4a30_3, 0, 18992, 2, 3, 0 }, /* TST */
+{ op_4a38_3, 0, 19000, 0, 3, 0 }, /* TST */
+{ op_4a39_3, 0, 19001, 0, 4, 0 }, /* TST */
+{ op_4a3a_3, 0, 19002, 0, 3, 0 }, /* TST */
+{ op_4a3b_3, 0, 19003, 2, 3, 0 }, /* TST */
+{ op_4a3c_3, 0, 19004, 0, 2, 0 }, /* TST */
+{ op_4a40_3, 0, 19008, 0, 1, 0 }, /* TST */
+{ op_4a48_3, 0, 19016, 0, 1, 0 }, /* TST */
+{ op_4a50_3, 0, 19024, 0, 2, 0 }, /* TST */
+{ op_4a58_3, 0, 19032, 0, 2, 0 }, /* TST */
+{ op_4a60_3, 0, 19040, 2, 2, 0 }, /* TST */
+{ op_4a68_3, 0, 19048, 0, 3, 0 }, /* TST */
+{ op_4a70_3, 0, 19056, 2, 3, 0 }, /* TST */
+{ op_4a78_3, 0, 19064, 0, 3, 0 }, /* TST */
+{ op_4a79_3, 0, 19065, 0, 4, 0 }, /* TST */
+{ op_4a7a_3, 0, 19066, 0, 3, 0 }, /* TST */
+{ op_4a7b_3, 0, 19067, 2, 3, 0 }, /* TST */
+{ op_4a7c_3, 0, 19068, 0, 2, 0 }, /* TST */
+{ op_4a80_3, 0, 19072, 0, 1, 0 }, /* TST */
+{ op_4a88_3, 0, 19080, 0, 1, 0 }, /* TST */
+{ op_4a90_3, 0, 19088, 0, 3, 0 }, /* TST */
+{ op_4a98_3, 0, 19096, 0, 3, 0 }, /* TST */
+{ op_4aa0_3, 0, 19104, 2, 3, 0 }, /* TST */
+{ op_4aa8_3, 0, 19112, 0, 4, 0 }, /* TST */
+{ op_4ab0_3, 0, 19120, 2, 4, 0 }, /* TST */
+{ op_4ab8_3, 0, 19128, 0, 4, 0 }, /* TST */
+{ op_4ab9_3, 0, 19129, 0, 5, 0 }, /* TST */
+{ op_4aba_3, 0, 19130, 0, 4, 0 }, /* TST */
+{ op_4abb_3, 0, 19131, 2, 4, 0 }, /* TST */
+{ op_4abc_3, 0, 19132, 0, 3, 0 }, /* TST */
+{ op_4ac0_3, 0, 19136, 0, 1, 0 }, /* TAS */
+{ op_4ad0_3, 0, 19152, 2, 2, 1 }, /* TAS */
+{ op_4ad8_3, 0, 19160, 2, 2, 1 }, /* TAS */
+{ op_4ae0_3, 0, 19168, 4, 2, 1 }, /* TAS */
+{ op_4ae8_3, 0, 19176, 2, 3, 1 }, /* TAS */
+{ op_4af0_3, 0, 19184, 4, 3, 1 }, /* TAS */
+{ op_4af8_3, 0, 19192, 2, 3, 1 }, /* TAS */
+{ op_4af9_3, 0, 19193, 2, 4, 1 }, /* TAS */
+{ op_4c90_3, 0, 19600, 0, 255, 0 }, /* MVMEL */
+{ op_4c98_3, 0, 19608, 0, 255, 0 }, /* MVMEL */
+{ op_4ca8_3, 0, 19624, 0, 255, 0 }, /* MVMEL */
+{ op_4cb0_3, 0, 19632, 2, 255, 0 }, /* MVMEL */
+{ op_4cb8_3, 0, 19640, 0, 255, 0 }, /* MVMEL */
+{ op_4cb9_3, 0, 19641, 0, 255, 0 }, /* MVMEL */
+{ op_4cba_3, 0, 19642, 0, 255, 0 }, /* MVMEL */
+{ op_4cbb_3, 0, 19643, 2, 255, 0 }, /* MVMEL */
+{ op_4cd0_3, 0, 19664, 0, 255, 0 }, /* MVMEL */
+{ op_4cd8_3, 0, 19672, 0, 255, 0 }, /* MVMEL */
+{ op_4ce8_3, 0, 19688, 0, 255, 0 }, /* MVMEL */
+{ op_4cf0_3, 0, 19696, 2, 255, 0 }, /* MVMEL */
+{ op_4cf8_3, 0, 19704, 0, 255, 0 }, /* MVMEL */
+{ op_4cf9_3, 0, 19705, 0, 255, 0 }, /* MVMEL */
+{ op_4cfa_3, 0, 19706, 0, 255, 0 }, /* MVMEL */
+{ op_4cfb_3, 0, 19707, 2, 255, 0 }, /* MVMEL */
+{ op_4e40_3, 0, 20032, 6, 255, 255 }, /* TRAP */
+{ op_4e50_3, 0, 20048, 2, 2, 2 }, /* LINK */
+{ op_4e58_3, 0, 20056, 0, 3, 0 }, /* UNLK */
+{ op_4e60_3, 0, 20064, 0, 1, 0 }, /* MVR2USP */
+{ op_4e68_3, 0, 20072, 0, 1, 0 }, /* MVUSP2R */
+{ op_4e70_3, 0, 20080, 128, 1, 0 }, /* RESET */
+{ op_4e71_3, 0, 20081, 0, 1, 0 }, /* NOP */
+{ op_4e72_3, 0, 20082, 4, 1, 0 }, /* STOP */
+{ op_4e73_3, 0, 20083, 0, 5, 0 }, /* RTE */
+{ op_4e74_3, 0, 20084, 0, 3, 0 }, /* RTD */
+{ op_4e75_3, 0, 20085, 0, 4, 0 }, /* RTS */
+{ op_4e76_3, 0, 20086, 0, 255, 255 }, /* TRAPV */
+{ op_4e77_3, 0, 20087, 12, 2, 0 }, /* RTR */
+{ op_4e90_3, 0, 20112, 0, 2, 2 }, /* JSR */
+{ op_4ea8_3, 0, 20136, 2, 2, 2 }, /* JSR */
+{ op_4eb0_3, 0, 20144, 6, 2, 2 }, /* JSR */
+{ op_4eb8_3, 0, 20152, 2, 2, 2 }, /* JSR */
+{ op_4eb9_3, 0, 20153, 0, 3, 2 }, /* JSR */
+{ op_4eba_3, 0, 20154, 2, 2, 2 }, /* JSR */
+{ op_4ebb_3, 0, 20155, 6, 2, 2 }, /* JSR */
+{ op_4ed0_3, 0, 20176, 0, 2, 0 }, /* JMP */
+{ op_4ee8_3, 0, 20200, 2, 2, 0 }, /* JMP */
+{ op_4ef0_3, 0, 20208, 2, 3, 0 }, /* JMP */
+{ op_4ef8_3, 0, 20216, 2, 2, 0 }, /* JMP */
+{ op_4ef9_3, 0, 20217, 0, 3, 0 }, /* JMP */
+{ op_4efa_3, 0, 20218, 2, 2, 0 }, /* JMP */
+{ op_4efb_3, 0, 20219, 2, 3, 0 }, /* JMP */
+{ op_5000_3, 0, 20480, 0, 1, 0 }, /* ADD */
+{ op_5010_3, 0, 20496, 0, 2, 1 }, /* ADD */
+{ op_5018_3, 0, 20504, 0, 2, 1 }, /* ADD */
+{ op_5020_3, 0, 20512, 2, 2, 1 }, /* ADD */
+{ op_5028_3, 0, 20520, 0, 3, 1 }, /* ADD */
+{ op_5030_3, 0, 20528, 2, 3, 1 }, /* ADD */
+{ op_5038_3, 0, 20536, 0, 3, 1 }, /* ADD */
+{ op_5039_3, 0, 20537, 0, 4, 1 }, /* ADD */
+{ op_5040_3, 0, 20544, 0, 1, 0 }, /* ADD */
+{ op_5048_3, 0, 20552, 4, 1, 0 }, /* ADDA */
+{ op_5050_3, 0, 20560, 0, 2, 1 }, /* ADD */
+{ op_5058_3, 0, 20568, 0, 2, 1 }, /* ADD */
+{ op_5060_3, 0, 20576, 2, 2, 1 }, /* ADD */
+{ op_5068_3, 0, 20584, 0, 3, 1 }, /* ADD */
+{ op_5070_3, 0, 20592, 2, 3, 1 }, /* ADD */
+{ op_5078_3, 0, 20600, 0, 3, 1 }, /* ADD */
+{ op_5079_3, 0, 20601, 0, 4, 1 }, /* ADD */
+{ op_5080_3, 0, 20608, 4, 1, 0 }, /* ADD */
+{ op_5088_3, 0, 20616, 4, 1, 0 }, /* ADDA */
+{ op_5090_3, 0, 20624, 0, 3, 2 }, /* ADD */
+{ op_5098_3, 0, 20632, 0, 3, 2 }, /* ADD */
+{ op_50a0_3, 0, 20640, 2, 3, 2 }, /* ADD */
+{ op_50a8_3, 0, 20648, 0, 4, 2 }, /* ADD */
+{ op_50b0_3, 0, 20656, 2, 4, 2 }, /* ADD */
+{ op_50b8_3, 0, 20664, 0, 4, 2 }, /* ADD */
+{ op_50b9_3, 0, 20665, 0, 5, 2 }, /* ADD */
+{ op_50c0_3, 0, 20672, 0, 1, 0 }, /* Scc */
+{ op_50c8_3, 0, 20680, 2, 2, 0 }, /* DBcc */
+{ op_50d0_3, 0, 20688, 0, 1, 1 }, /* Scc */
+{ op_50d8_3, 0, 20696, 0, 1, 1 }, /* Scc */
+{ op_50e0_3, 0, 20704, 2, 1, 1 }, /* Scc */
+{ op_50e8_3, 0, 20712, 0, 2, 1 }, /* Scc */
+{ op_50f0_3, 0, 20720, 2, 2, 1 }, /* Scc */
+{ op_50f8_3, 0, 20728, 0, 2, 1 }, /* Scc */
+{ op_50f9_3, 0, 20729, 0, 3, 1 }, /* Scc */
+{ op_5100_3, 0, 20736, 0, 1, 0 }, /* SUB */
+{ op_5110_3, 0, 20752, 0, 2, 1 }, /* SUB */
+{ op_5118_3, 0, 20760, 0, 2, 1 }, /* SUB */
+{ op_5120_3, 0, 20768, 2, 2, 1 }, /* SUB */
+{ op_5128_3, 0, 20776, 0, 3, 1 }, /* SUB */
+{ op_5130_3, 0, 20784, 2, 3, 1 }, /* SUB */
+{ op_5138_3, 0, 20792, 0, 3, 1 }, /* SUB */
+{ op_5139_3, 0, 20793, 0, 4, 1 }, /* SUB */
+{ op_5140_3, 0, 20800, 0, 1, 0 }, /* SUB */
+{ op_5148_3, 0, 20808, 4, 1, 0 }, /* SUBA */
+{ op_5150_3, 0, 20816, 0, 2, 1 }, /* SUB */
+{ op_5158_3, 0, 20824, 0, 2, 1 }, /* SUB */
+{ op_5160_3, 0, 20832, 2, 2, 1 }, /* SUB */
+{ op_5168_3, 0, 20840, 0, 3, 1 }, /* SUB */
+{ op_5170_3, 0, 20848, 2, 3, 1 }, /* SUB */
+{ op_5178_3, 0, 20856, 0, 3, 1 }, /* SUB */
+{ op_5179_3, 0, 20857, 0, 4, 1 }, /* SUB */
+{ op_5180_3, 0, 20864, 4, 1, 0 }, /* SUB */
+{ op_5188_3, 0, 20872, 4, 1, 0 }, /* SUBA */
+{ op_5190_3, 0, 20880, 0, 3, 2 }, /* SUB */
+{ op_5198_3, 0, 20888, 0, 3, 2 }, /* SUB */
+{ op_51a0_3, 0, 20896, 2, 3, 2 }, /* SUB */
+{ op_51a8_3, 0, 20904, 0, 4, 2 }, /* SUB */
+{ op_51b0_3, 0, 20912, 2, 4, 2 }, /* SUB */
+{ op_51b8_3, 0, 20920, 0, 4, 2 }, /* SUB */
+{ op_51b9_3, 0, 20921, 0, 5, 2 }, /* SUB */
+{ op_51c0_3, 0, 20928, 0, 1, 0 }, /* Scc */
+{ op_51c8_3, 0, 20936, 2, 2, 0 }, /* DBcc */
+{ op_51d0_3, 0, 20944, 0, 1, 1 }, /* Scc */
+{ op_51d8_3, 0, 20952, 0, 1, 1 }, /* Scc */
+{ op_51e0_3, 0, 20960, 2, 1, 1 }, /* Scc */
+{ op_51e8_3, 0, 20968, 0, 2, 1 }, /* Scc */
+{ op_51f0_3, 0, 20976, 2, 2, 1 }, /* Scc */
+{ op_51f8_3, 0, 20984, 0, 2, 1 }, /* Scc */
+{ op_51f9_3, 0, 20985, 0, 3, 1 }, /* Scc */
+{ op_52c0_3, 0, 21184, 0, 1, 0 }, /* Scc */
+{ op_52c8_3, 0, 21192, 2, 2, 0 }, /* DBcc */
+{ op_52d0_3, 0, 21200, 0, 1, 1 }, /* Scc */
+{ op_52d8_3, 0, 21208, 0, 1, 1 }, /* Scc */
+{ op_52e0_3, 0, 21216, 2, 1, 1 }, /* Scc */
+{ op_52e8_3, 0, 21224, 0, 2, 1 }, /* Scc */
+{ op_52f0_3, 0, 21232, 2, 2, 1 }, /* Scc */
+{ op_52f8_3, 0, 21240, 0, 2, 1 }, /* Scc */
+{ op_52f9_3, 0, 21241, 0, 3, 1 }, /* Scc */
+{ op_53c0_3, 0, 21440, 0, 1, 0 }, /* Scc */
+{ op_53c8_3, 0, 21448, 2, 2, 0 }, /* DBcc */
+{ op_53d0_3, 0, 21456, 0, 1, 1 }, /* Scc */
+{ op_53d8_3, 0, 21464, 0, 1, 1 }, /* Scc */
+{ op_53e0_3, 0, 21472, 2, 1, 1 }, /* Scc */
+{ op_53e8_3, 0, 21480, 0, 2, 1 }, /* Scc */
+{ op_53f0_3, 0, 21488, 2, 2, 1 }, /* Scc */
+{ op_53f8_3, 0, 21496, 0, 2, 1 }, /* Scc */
+{ op_53f9_3, 0, 21497, 0, 3, 1 }, /* Scc */
+{ op_54c0_3, 0, 21696, 0, 1, 0 }, /* Scc */
+{ op_54c8_3, 0, 21704, 2, 2, 0 }, /* DBcc */
+{ op_54d0_3, 0, 21712, 0, 1, 1 }, /* Scc */
+{ op_54d8_3, 0, 21720, 0, 1, 1 }, /* Scc */
+{ op_54e0_3, 0, 21728, 2, 1, 1 }, /* Scc */
+{ op_54e8_3, 0, 21736, 0, 2, 1 }, /* Scc */
+{ op_54f0_3, 0, 21744, 2, 2, 1 }, /* Scc */
+{ op_54f8_3, 0, 21752, 0, 2, 1 }, /* Scc */
+{ op_54f9_3, 0, 21753, 0, 3, 1 }, /* Scc */
+{ op_55c0_3, 0, 21952, 0, 1, 0 }, /* Scc */
+{ op_55c8_3, 0, 21960, 2, 2, 0 }, /* DBcc */
+{ op_55d0_3, 0, 21968, 0, 1, 1 }, /* Scc */
+{ op_55d8_3, 0, 21976, 0, 1, 1 }, /* Scc */
+{ op_55e0_3, 0, 21984, 2, 1, 1 }, /* Scc */
+{ op_55e8_3, 0, 21992, 0, 2, 1 }, /* Scc */
+{ op_55f0_3, 0, 22000, 2, 2, 1 }, /* Scc */
+{ op_55f8_3, 0, 22008, 0, 2, 1 }, /* Scc */
+{ op_55f9_3, 0, 22009, 0, 3, 1 }, /* Scc */
+{ op_56c0_3, 0, 22208, 0, 1, 0 }, /* Scc */
+{ op_56c8_3, 0, 22216, 2, 2, 0 }, /* DBcc */
+{ op_56d0_3, 0, 22224, 0, 1, 1 }, /* Scc */
+{ op_56d8_3, 0, 22232, 0, 1, 1 }, /* Scc */
+{ op_56e0_3, 0, 22240, 2, 1, 1 }, /* Scc */
+{ op_56e8_3, 0, 22248, 0, 2, 1 }, /* Scc */
+{ op_56f0_3, 0, 22256, 2, 2, 1 }, /* Scc */
+{ op_56f8_3, 0, 22264, 0, 2, 1 }, /* Scc */
+{ op_56f9_3, 0, 22265, 0, 3, 1 }, /* Scc */
+{ op_57c0_3, 0, 22464, 0, 1, 0 }, /* Scc */
+{ op_57c8_3, 0, 22472, 2, 2, 0 }, /* DBcc */
+{ op_57d0_3, 0, 22480, 0, 1, 1 }, /* Scc */
+{ op_57d8_3, 0, 22488, 0, 1, 1 }, /* Scc */
+{ op_57e0_3, 0, 22496, 2, 1, 1 }, /* Scc */
+{ op_57e8_3, 0, 22504, 0, 2, 1 }, /* Scc */
+{ op_57f0_3, 0, 22512, 2, 2, 1 }, /* Scc */
+{ op_57f8_3, 0, 22520, 0, 2, 1 }, /* Scc */
+{ op_57f9_3, 0, 22521, 0, 3, 1 }, /* Scc */
+{ op_58c0_3, 0, 22720, 0, 1, 0 }, /* Scc */
+{ op_58c8_3, 0, 22728, 2, 2, 0 }, /* DBcc */
+{ op_58d0_3, 0, 22736, 0, 1, 1 }, /* Scc */
+{ op_58d8_3, 0, 22744, 0, 1, 1 }, /* Scc */
+{ op_58e0_3, 0, 22752, 2, 1, 1 }, /* Scc */
+{ op_58e8_3, 0, 22760, 0, 2, 1 }, /* Scc */
+{ op_58f0_3, 0, 22768, 2, 2, 1 }, /* Scc */
+{ op_58f8_3, 0, 22776, 0, 2, 1 }, /* Scc */
+{ op_58f9_3, 0, 22777, 0, 3, 1 }, /* Scc */
+{ op_59c0_3, 0, 22976, 0, 1, 0 }, /* Scc */
+{ op_59c8_3, 0, 22984, 2, 2, 0 }, /* DBcc */
+{ op_59d0_3, 0, 22992, 0, 1, 1 }, /* Scc */
+{ op_59d8_3, 0, 23000, 0, 1, 1 }, /* Scc */
+{ op_59e0_3, 0, 23008, 2, 1, 1 }, /* Scc */
+{ op_59e8_3, 0, 23016, 0, 2, 1 }, /* Scc */
+{ op_59f0_3, 0, 23024, 2, 2, 1 }, /* Scc */
+{ op_59f8_3, 0, 23032, 0, 2, 1 }, /* Scc */
+{ op_59f9_3, 0, 23033, 0, 3, 1 }, /* Scc */
+{ op_5ac0_3, 0, 23232, 0, 1, 0 }, /* Scc */
+{ op_5ac8_3, 0, 23240, 2, 2, 0 }, /* DBcc */
+{ op_5ad0_3, 0, 23248, 0, 1, 1 }, /* Scc */
+{ op_5ad8_3, 0, 23256, 0, 1, 1 }, /* Scc */
+{ op_5ae0_3, 0, 23264, 2, 1, 1 }, /* Scc */
+{ op_5ae8_3, 0, 23272, 0, 2, 1 }, /* Scc */
+{ op_5af0_3, 0, 23280, 2, 2, 1 }, /* Scc */
+{ op_5af8_3, 0, 23288, 0, 2, 1 }, /* Scc */
+{ op_5af9_3, 0, 23289, 0, 3, 1 }, /* Scc */
+{ op_5bc0_3, 0, 23488, 0, 1, 0 }, /* Scc */
+{ op_5bc8_3, 0, 23496, 2, 2, 0 }, /* DBcc */
+{ op_5bd0_3, 0, 23504, 0, 1, 1 }, /* Scc */
+{ op_5bd8_3, 0, 23512, 0, 1, 1 }, /* Scc */
+{ op_5be0_3, 0, 23520, 2, 1, 1 }, /* Scc */
+{ op_5be8_3, 0, 23528, 0, 2, 1 }, /* Scc */
+{ op_5bf0_3, 0, 23536, 2, 2, 1 }, /* Scc */
+{ op_5bf8_3, 0, 23544, 0, 2, 1 }, /* Scc */
+{ op_5bf9_3, 0, 23545, 0, 3, 1 }, /* Scc */
+{ op_5cc0_3, 0, 23744, 0, 1, 0 }, /* Scc */
+{ op_5cc8_3, 0, 23752, 2, 2, 0 }, /* DBcc */
+{ op_5cd0_3, 0, 23760, 0, 1, 1 }, /* Scc */
+{ op_5cd8_3, 0, 23768, 0, 1, 1 }, /* Scc */
+{ op_5ce0_3, 0, 23776, 2, 1, 1 }, /* Scc */
+{ op_5ce8_3, 0, 23784, 0, 2, 1 }, /* Scc */
+{ op_5cf0_3, 0, 23792, 2, 2, 1 }, /* Scc */
+{ op_5cf8_3, 0, 23800, 0, 2, 1 }, /* Scc */
+{ op_5cf9_3, 0, 23801, 0, 3, 1 }, /* Scc */
+{ op_5dc0_3, 0, 24000, 0, 1, 0 }, /* Scc */
+{ op_5dc8_3, 0, 24008, 2, 2, 0 }, /* DBcc */
+{ op_5dd0_3, 0, 24016, 0, 1, 1 }, /* Scc */
+{ op_5dd8_3, 0, 24024, 0, 1, 1 }, /* Scc */
+{ op_5de0_3, 0, 24032, 2, 1, 1 }, /* Scc */
+{ op_5de8_3, 0, 24040, 0, 2, 1 }, /* Scc */
+{ op_5df0_3, 0, 24048, 2, 2, 1 }, /* Scc */
+{ op_5df8_3, 0, 24056, 0, 2, 1 }, /* Scc */
+{ op_5df9_3, 0, 24057, 0, 3, 1 }, /* Scc */
+{ op_5ec0_3, 0, 24256, 0, 1, 0 }, /* Scc */
+{ op_5ec8_3, 0, 24264, 2, 2, 0 }, /* DBcc */
+{ op_5ed0_3, 0, 24272, 0, 1, 1 }, /* Scc */
+{ op_5ed8_3, 0, 24280, 0, 1, 1 }, /* Scc */
+{ op_5ee0_3, 0, 24288, 2, 1, 1 }, /* Scc */
+{ op_5ee8_3, 0, 24296, 0, 2, 1 }, /* Scc */
+{ op_5ef0_3, 0, 24304, 2, 2, 1 }, /* Scc */
+{ op_5ef8_3, 0, 24312, 0, 2, 1 }, /* Scc */
+{ op_5ef9_3, 0, 24313, 0, 3, 1 }, /* Scc */
+{ op_5fc0_3, 0, 24512, 0, 1, 0 }, /* Scc */
+{ op_5fc8_3, 0, 24520, 2, 2, 0 }, /* DBcc */
+{ op_5fd0_3, 0, 24528, 0, 1, 1 }, /* Scc */
+{ op_5fd8_3, 0, 24536, 0, 1, 1 }, /* Scc */
+{ op_5fe0_3, 0, 24544, 2, 1, 1 }, /* Scc */
+{ op_5fe8_3, 0, 24552, 0, 2, 1 }, /* Scc */
+{ op_5ff0_3, 0, 24560, 2, 2, 1 }, /* Scc */
+{ op_5ff8_3, 0, 24568, 0, 2, 1 }, /* Scc */
+{ op_5ff9_3, 0, 24569, 0, 3, 1 }, /* Scc */
+{ op_6000_3, 0, 24576, 2, 255, 0 }, /* Bcc */
+{ op_6001_3, 0, 24577, 2, 255, 0 }, /* Bcc */
+{ op_60ff_3, 0, 24831, 2, 255, 0 }, /* Bcc */
+{ op_6100_3, 0, 24832, 2, 2, 2 }, /* BSR */
+{ op_6101_3, 0, 24833, 2, 2, 2 }, /* BSR */
+{ op_61ff_3, 0, 25087, 2, 2, 2 }, /* BSR */
+{ op_6200_3, 0, 25088, 2, 255, 0 }, /* Bcc */
+{ op_6201_3, 0, 25089, 2, 255, 0 }, /* Bcc */
+{ op_62ff_3, 0, 25343, 2, 255, 0 }, /* Bcc */
+{ op_6300_3, 0, 25344, 2, 255, 0 }, /* Bcc */
+{ op_6301_3, 0, 25345, 2, 255, 0 }, /* Bcc */
+{ op_63ff_3, 0, 25599, 2, 255, 0 }, /* Bcc */
+{ op_6400_3, 0, 25600, 2, 255, 0 }, /* Bcc */
+{ op_6401_3, 0, 25601, 2, 255, 0 }, /* Bcc */
+{ op_64ff_3, 0, 25855, 2, 255, 0 }, /* Bcc */
+{ op_6500_3, 0, 25856, 2, 255, 0 }, /* Bcc */
+{ op_6501_3, 0, 25857, 2, 255, 0 }, /* Bcc */
+{ op_65ff_3, 0, 26111, 2, 255, 0 }, /* Bcc */
+{ op_6600_3, 0, 26112, 2, 255, 0 }, /* Bcc */
+{ op_6601_3, 0, 26113, 2, 255, 0 }, /* Bcc */
+{ op_66ff_3, 0, 26367, 2, 255, 0 }, /* Bcc */
+{ op_6700_3, 0, 26368, 2, 255, 0 }, /* Bcc */
+{ op_6701_3, 0, 26369, 2, 255, 0 }, /* Bcc */
+{ op_67ff_3, 0, 26623, 2, 255, 0 }, /* Bcc */
+{ op_6800_3, 0, 26624, 2, 255, 0 }, /* Bcc */
+{ op_6801_3, 0, 26625, 2, 255, 0 }, /* Bcc */
+{ op_68ff_3, 0, 26879, 2, 255, 0 }, /* Bcc */
+{ op_6900_3, 0, 26880, 2, 255, 0 }, /* Bcc */
+{ op_6901_3, 0, 26881, 2, 255, 0 }, /* Bcc */
+{ op_69ff_3, 0, 27135, 2, 255, 0 }, /* Bcc */
+{ op_6a00_3, 0, 27136, 2, 255, 0 }, /* Bcc */
+{ op_6a01_3, 0, 27137, 2, 255, 0 }, /* Bcc */
+{ op_6aff_3, 0, 27391, 2, 255, 0 }, /* Bcc */
+{ op_6b00_3, 0, 27392, 2, 255, 0 }, /* Bcc */
+{ op_6b01_3, 0, 27393, 2, 255, 0 }, /* Bcc */
+{ op_6bff_3, 0, 27647, 2, 255, 0 }, /* Bcc */
+{ op_6c00_3, 0, 27648, 2, 255, 0 }, /* Bcc */
+{ op_6c01_3, 0, 27649, 2, 255, 0 }, /* Bcc */
+{ op_6cff_3, 0, 27903, 2, 255, 0 }, /* Bcc */
+{ op_6d00_3, 0, 27904, 2, 255, 0 }, /* Bcc */
+{ op_6d01_3, 0, 27905, 2, 255, 0 }, /* Bcc */
+{ op_6dff_3, 0, 28159, 2, 255, 0 }, /* Bcc */
+{ op_6e00_3, 0, 28160, 2, 255, 0 }, /* Bcc */
+{ op_6e01_3, 0, 28161, 2, 255, 0 }, /* Bcc */
+{ op_6eff_3, 0, 28415, 2, 255, 0 }, /* Bcc */
+{ op_6f00_3, 0, 28416, 2, 255, 0 }, /* Bcc */
+{ op_6f01_3, 0, 28417, 2, 255, 0 }, /* Bcc */
+{ op_6fff_3, 0, 28671, 2, 255, 0 }, /* Bcc */
+{ op_7000_3, 0, 28672, 0, 1, 0 }, /* MOVE */
+{ op_8000_3, 0, 32768, 0, 1, 0 }, /* OR */
+{ op_8010_3, 0, 32784, 0, 2, 0 }, /* OR */
+{ op_8018_3, 0, 32792, 0, 2, 0 }, /* OR */
+{ op_8020_3, 0, 32800, 2, 2, 0 }, /* OR */
+{ op_8028_3, 0, 32808, 0, 3, 0 }, /* OR */
+{ op_8030_3, 0, 32816, 2, 3, 0 }, /* OR */
+{ op_8038_3, 0, 32824, 0, 3, 0 }, /* OR */
+{ op_8039_3, 0, 32825, 0, 4, 0 }, /* OR */
+{ op_803a_3, 0, 32826, 0, 3, 0 }, /* OR */
+{ op_803b_3, 0, 32827, 2, 3, 0 }, /* OR */
+{ op_803c_3, 0, 32828, 0, 2, 0 }, /* OR */
+{ op_8040_3, 0, 32832, 0, 1, 0 }, /* OR */
+{ op_8050_3, 0, 32848, 0, 2, 0 }, /* OR */
+{ op_8058_3, 0, 32856, 0, 2, 0 }, /* OR */
+{ op_8060_3, 0, 32864, 2, 2, 0 }, /* OR */
+{ op_8068_3, 0, 32872, 0, 3, 0 }, /* OR */
+{ op_8070_3, 0, 32880, 2, 3, 0 }, /* OR */
+{ op_8078_3, 0, 32888, 0, 3, 0 }, /* OR */
+{ op_8079_3, 0, 32889, 0, 4, 0 }, /* OR */
+{ op_807a_3, 0, 32890, 0, 3, 0 }, /* OR */
+{ op_807b_3, 0, 32891, 2, 3, 0 }, /* OR */
+{ op_807c_3, 0, 32892, 0, 2, 0 }, /* OR */
+{ op_8080_3, 0, 32896, 2, 1, 0 }, /* OR */
+{ op_8090_3, 0, 32912, 2, 3, 0 }, /* OR */
+{ op_8098_3, 0, 32920, 2, 3, 0 }, /* OR */
+{ op_80a0_3, 0, 32928, 4, 3, 0 }, /* OR */
+{ op_80a8_3, 0, 32936, 2, 4, 0 }, /* OR */
+{ op_80b0_3, 0, 32944, 4, 4, 0 }, /* OR */
+{ op_80b8_3, 0, 32952, 2, 4, 0 }, /* OR */
+{ op_80b9_3, 0, 32953, 2, 5, 0 }, /* OR */
+{ op_80ba_3, 0, 32954, 2, 4, 0 }, /* OR */
+{ op_80bb_3, 0, 32955, 4, 4, 0 }, /* OR */
+{ op_80bc_3, 0, 32956, 2, 3, 0 }, /* OR */
+{ op_80c0_3, 0, 32960, 136, 1, 0 }, /* DIVU */
+{ op_80d0_3, 0, 32976, 136, 2, 0 }, /* DIVU */
+{ op_80d8_3, 0, 32984, 136, 2, 0 }, /* DIVU */
+{ op_80e0_3, 0, 32992, 138, 2, 0 }, /* DIVU */
+{ op_80e8_3, 0, 33000, 136, 3, 0 }, /* DIVU */
+{ op_80f0_3, 0, 33008, 138, 3, 0 }, /* DIVU */
+{ op_80f8_3, 0, 33016, 136, 3, 0 }, /* DIVU */
+{ op_80f9_3, 0, 33017, 136, 4, 0 }, /* DIVU */
+{ op_80fa_3, 0, 33018, 136, 3, 0 }, /* DIVU */
+{ op_80fb_3, 0, 33019, 138, 3, 0 }, /* DIVU */
+{ op_80fc_3, 0, 33020, 136, 2, 0 }, /* DIVU */
+{ op_8100_3, 0, 33024, 2, 1, 0 }, /* SBCD */
+{ op_8108_3, 0, 33032, 2, 3, 1 }, /* SBCD */
+{ op_8110_3, 0, 33040, 0, 2, 1 }, /* OR */
+{ op_8118_3, 0, 33048, 0, 2, 1 }, /* OR */
+{ op_8120_3, 0, 33056, 2, 2, 1 }, /* OR */
+{ op_8128_3, 0, 33064, 0, 3, 1 }, /* OR */
+{ op_8130_3, 0, 33072, 2, 3, 1 }, /* OR */
+{ op_8138_3, 0, 33080, 0, 3, 1 }, /* OR */
+{ op_8139_3, 0, 33081, 0, 4, 1 }, /* OR */
+{ op_8150_3, 0, 33104, 0, 2, 1 }, /* OR */
+{ op_8158_3, 0, 33112, 0, 2, 1 }, /* OR */
+{ op_8160_3, 0, 33120, 2, 2, 1 }, /* OR */
+{ op_8168_3, 0, 33128, 0, 3, 1 }, /* OR */
+{ op_8170_3, 0, 33136, 2, 3, 1 }, /* OR */
+{ op_8178_3, 0, 33144, 0, 3, 1 }, /* OR */
+{ op_8179_3, 0, 33145, 0, 4, 1 }, /* OR */
+{ op_8190_3, 0, 33168, 0, 3, 2 }, /* OR */
+{ op_8198_3, 0, 33176, 0, 3, 2 }, /* OR */
+{ op_81a0_3, 0, 33184, 2, 3, 2 }, /* OR */
+{ op_81a8_3, 0, 33192, 0, 4, 2 }, /* OR */
+{ op_81b0_3, 0, 33200, 2, 4, 2 }, /* OR */
+{ op_81b8_3, 0, 33208, 0, 4, 2 }, /* OR */
+{ op_81b9_3, 0, 33209, 0, 5, 2 }, /* OR */
+{ op_81c0_3, 0, 33216, 154, 1, 0 }, /* DIVS */
+{ op_81d0_3, 0, 33232, 154, 2, 0 }, /* DIVS */
+{ op_81d8_3, 0, 33240, 154, 2, 0 }, /* DIVS */
+{ op_81e0_3, 0, 33248, 156, 2, 0 }, /* DIVS */
+{ op_81e8_3, 0, 33256, 154, 3, 0 }, /* DIVS */
+{ op_81f0_3, 0, 33264, 156, 3, 0 }, /* DIVS */
+{ op_81f8_3, 0, 33272, 154, 3, 0 }, /* DIVS */
+{ op_81f9_3, 0, 33273, 154, 4, 0 }, /* DIVS */
+{ op_81fa_3, 0, 33274, 154, 3, 0 }, /* DIVS */
+{ op_81fb_3, 0, 33275, 156, 3, 0 }, /* DIVS */
+{ op_81fc_3, 0, 33276, 154, 2, 0 }, /* DIVS */
+{ op_9000_3, 0, 36864, 0, 1, 0 }, /* SUB */
+{ op_9010_3, 0, 36880, 0, 2, 0 }, /* SUB */
+{ op_9018_3, 0, 36888, 0, 2, 0 }, /* SUB */
+{ op_9020_3, 0, 36896, 2, 2, 0 }, /* SUB */
+{ op_9028_3, 0, 36904, 0, 3, 0 }, /* SUB */
+{ op_9030_3, 0, 36912, 2, 3, 0 }, /* SUB */
+{ op_9038_3, 0, 36920, 0, 3, 0 }, /* SUB */
+{ op_9039_3, 0, 36921, 0, 4, 0 }, /* SUB */
+{ op_903a_3, 0, 36922, 0, 3, 0 }, /* SUB */
+{ op_903b_3, 0, 36923, 2, 3, 0 }, /* SUB */
+{ op_903c_3, 0, 36924, 0, 2, 0 }, /* SUB */
+{ op_9040_3, 0, 36928, 0, 1, 0 }, /* SUB */
+{ op_9048_3, 0, 36936, 0, 1, 0 }, /* SUB */
+{ op_9050_3, 0, 36944, 0, 2, 0 }, /* SUB */
+{ op_9058_3, 0, 36952, 0, 2, 0 }, /* SUB */
+{ op_9060_3, 0, 36960, 2, 2, 0 }, /* SUB */
+{ op_9068_3, 0, 36968, 0, 3, 0 }, /* SUB */
+{ op_9070_3, 0, 36976, 2, 3, 0 }, /* SUB */
+{ op_9078_3, 0, 36984, 0, 3, 0 }, /* SUB */
+{ op_9079_3, 0, 36985, 0, 4, 0 }, /* SUB */
+{ op_907a_3, 0, 36986, 0, 3, 0 }, /* SUB */
+{ op_907b_3, 0, 36987, 2, 3, 0 }, /* SUB */
+{ op_907c_3, 0, 36988, 0, 2, 0 }, /* SUB */
+{ op_9080_3, 0, 36992, 4, 1, 0 }, /* SUB */
+{ op_9088_3, 0, 37000, 4, 1, 0 }, /* SUB */
+{ op_9090_3, 0, 37008, 2, 3, 0 }, /* SUB */
+{ op_9098_3, 0, 37016, 2, 3, 0 }, /* SUB */
+{ op_90a0_3, 0, 37024, 4, 3, 0 }, /* SUB */
+{ op_90a8_3, 0, 37032, 2, 4, 0 }, /* SUB */
+{ op_90b0_3, 0, 37040, 4, 4, 0 }, /* SUB */
+{ op_90b8_3, 0, 37048, 2, 4, 0 }, /* SUB */
+{ op_90b9_3, 0, 37049, 2, 5, 0 }, /* SUB */
+{ op_90ba_3, 0, 37050, 2, 4, 0 }, /* SUB */
+{ op_90bb_3, 0, 37051, 4, 4, 0 }, /* SUB */
+{ op_90bc_3, 0, 37052, 4, 3, 0 }, /* SUB */
+{ op_90c0_3, 0, 37056, 4, 1, 0 }, /* SUBA */
+{ op_90c8_3, 0, 37064, 4, 1, 0 }, /* SUBA */
+{ op_90d0_3, 0, 37072, 4, 2, 0 }, /* SUBA */
+{ op_90d8_3, 0, 37080, 4, 2, 0 }, /* SUBA */
+{ op_90e0_3, 0, 37088, 6, 2, 0 }, /* SUBA */
+{ op_90e8_3, 0, 37096, 4, 3, 0 }, /* SUBA */
+{ op_90f0_3, 0, 37104, 6, 3, 0 }, /* SUBA */
+{ op_90f8_3, 0, 37112, 4, 3, 0 }, /* SUBA */
+{ op_90f9_3, 0, 37113, 4, 4, 0 }, /* SUBA */
+{ op_90fa_3, 0, 37114, 4, 3, 0 }, /* SUBA */
+{ op_90fb_3, 0, 37115, 6, 3, 0 }, /* SUBA */
+{ op_90fc_3, 0, 37116, 4, 2, 0 }, /* SUBA */
+{ op_9100_3, 0, 37120, 0, 1, 0 }, /* SUBX */
+{ op_9108_3, 0, 37128, 2, 3, 1 }, /* SUBX */
+{ op_9110_3, 0, 37136, 0, 2, 1 }, /* SUB */
+{ op_9118_3, 0, 37144, 0, 2, 1 }, /* SUB */
+{ op_9120_3, 0, 37152, 2, 2, 1 }, /* SUB */
+{ op_9128_3, 0, 37160, 0, 3, 1 }, /* SUB */
+{ op_9130_3, 0, 37168, 2, 3, 1 }, /* SUB */
+{ op_9138_3, 0, 37176, 0, 3, 1 }, /* SUB */
+{ op_9139_3, 0, 37177, 0, 4, 1 }, /* SUB */
+{ op_9140_3, 0, 37184, 0, 1, 0 }, /* SUBX */
+{ op_9148_3, 0, 37192, 2, 3, 1 }, /* SUBX */
+{ op_9150_3, 0, 37200, 0, 2, 1 }, /* SUB */
+{ op_9158_3, 0, 37208, 0, 2, 1 }, /* SUB */
+{ op_9160_3, 0, 37216, 2, 2, 1 }, /* SUB */
+{ op_9168_3, 0, 37224, 0, 3, 1 }, /* SUB */
+{ op_9170_3, 0, 37232, 2, 3, 1 }, /* SUB */
+{ op_9178_3, 0, 37240, 0, 3, 1 }, /* SUB */
+{ op_9179_3, 0, 37241, 0, 4, 1 }, /* SUB */
+{ op_9180_3, 0, 37248, 4, 1, 0 }, /* SUBX */
+{ op_9188_3, 0, 37256, 2, 5, 2 }, /* SUBX */
+{ op_9190_3, 0, 37264, 0, 3, 2 }, /* SUB */
+{ op_9198_3, 0, 37272, 0, 3, 2 }, /* SUB */
+{ op_91a0_3, 0, 37280, 2, 3, 2 }, /* SUB */
+{ op_91a8_3, 0, 37288, 0, 4, 2 }, /* SUB */
+{ op_91b0_3, 0, 37296, 2, 4, 2 }, /* SUB */
+{ op_91b8_3, 0, 37304, 0, 4, 2 }, /* SUB */
+{ op_91b9_3, 0, 37305, 0, 5, 2 }, /* SUB */
+{ op_91c0_3, 0, 37312, 4, 1, 0 }, /* SUBA */
+{ op_91c8_3, 0, 37320, 4, 1, 0 }, /* SUBA */
+{ op_91d0_3, 0, 37328, 2, 3, 0 }, /* SUBA */
+{ op_91d8_3, 0, 37336, 2, 3, 0 }, /* SUBA */
+{ op_91e0_3, 0, 37344, 4, 3, 0 }, /* SUBA */
+{ op_91e8_3, 0, 37352, 2, 4, 0 }, /* SUBA */
+{ op_91f0_3, 0, 37360, 4, 4, 0 }, /* SUBA */
+{ op_91f8_3, 0, 37368, 2, 4, 0 }, /* SUBA */
+{ op_91f9_3, 0, 37369, 2, 5, 0 }, /* SUBA */
+{ op_91fa_3, 0, 37370, 2, 4, 0 }, /* SUBA */
+{ op_91fb_3, 0, 37371, 4, 4, 0 }, /* SUBA */
+{ op_91fc_3, 0, 37372, 4, 3, 0 }, /* SUBA */
+{ op_b000_3, 0, 45056, 0, 1, 0 }, /* CMP */
+{ op_b010_3, 0, 45072, 0, 2, 0 }, /* CMP */
+{ op_b018_3, 0, 45080, 0, 2, 0 }, /* CMP */
+{ op_b020_3, 0, 45088, 2, 2, 0 }, /* CMP */
+{ op_b028_3, 0, 45096, 0, 3, 0 }, /* CMP */
+{ op_b030_3, 0, 45104, 2, 3, 0 }, /* CMP */
+{ op_b038_3, 0, 45112, 0, 3, 0 }, /* CMP */
+{ op_b039_3, 0, 45113, 0, 4, 0 }, /* CMP */
+{ op_b03a_3, 0, 45114, 0, 3, 0 }, /* CMP */
+{ op_b03b_3, 0, 45115, 2, 3, 0 }, /* CMP */
+{ op_b03c_3, 0, 45116, 0, 2, 0 }, /* CMP */
+{ op_b040_3, 0, 45120, 0, 1, 0 }, /* CMP */
+{ op_b048_3, 0, 45128, 0, 1, 0 }, /* CMP */
+{ op_b050_3, 0, 45136, 0, 2, 0 }, /* CMP */
+{ op_b058_3, 0, 45144, 0, 2, 0 }, /* CMP */
+{ op_b060_3, 0, 45152, 2, 2, 0 }, /* CMP */
+{ op_b068_3, 0, 45160, 0, 3, 0 }, /* CMP */
+{ op_b070_3, 0, 45168, 2, 3, 0 }, /* CMP */
+{ op_b078_3, 0, 45176, 0, 3, 0 }, /* CMP */
+{ op_b079_3, 0, 45177, 0, 4, 0 }, /* CMP */
+{ op_b07a_3, 0, 45178, 0, 3, 0 }, /* CMP */
+{ op_b07b_3, 0, 45179, 2, 3, 0 }, /* CMP */
+{ op_b07c_3, 0, 45180, 0, 2, 0 }, /* CMP */
+{ op_b080_3, 0, 45184, 2, 1, 0 }, /* CMP */
+{ op_b088_3, 0, 45192, 2, 1, 0 }, /* CMP */
+{ op_b090_3, 0, 45200, 2, 3, 0 }, /* CMP */
+{ op_b098_3, 0, 45208, 2, 3, 0 }, /* CMP */
+{ op_b0a0_3, 0, 45216, 4, 3, 0 }, /* CMP */
+{ op_b0a8_3, 0, 45224, 2, 4, 0 }, /* CMP */
+{ op_b0b0_3, 0, 45232, 4, 4, 0 }, /* CMP */
+{ op_b0b8_3, 0, 45240, 2, 4, 0 }, /* CMP */
+{ op_b0b9_3, 0, 45241, 2, 5, 0 }, /* CMP */
+{ op_b0ba_3, 0, 45242, 2, 4, 0 }, /* CMP */
+{ op_b0bb_3, 0, 45243, 4, 4, 0 }, /* CMP */
+{ op_b0bc_3, 0, 45244, 2, 3, 0 }, /* CMP */
+{ op_b0c0_3, 0, 45248, 2, 1, 0 }, /* CMPA */
+{ op_b0c8_3, 0, 45256, 2, 1, 0 }, /* CMPA */
+{ op_b0d0_3, 0, 45264, 2, 2, 0 }, /* CMPA */
+{ op_b0d8_3, 0, 45272, 2, 2, 0 }, /* CMPA */
+{ op_b0e0_3, 0, 45280, 4, 2, 0 }, /* CMPA */
+{ op_b0e8_3, 0, 45288, 2, 3, 0 }, /* CMPA */
+{ op_b0f0_3, 0, 45296, 4, 3, 0 }, /* CMPA */
+{ op_b0f8_3, 0, 45304, 2, 3, 0 }, /* CMPA */
+{ op_b0f9_3, 0, 45305, 2, 4, 0 }, /* CMPA */
+{ op_b0fa_3, 0, 45306, 2, 3, 0 }, /* CMPA */
+{ op_b0fb_3, 0, 45307, 4, 3, 0 }, /* CMPA */
+{ op_b0fc_3, 0, 45308, 2, 2, 0 }, /* CMPA */
+{ op_b100_3, 0, 45312, 0, 1, 0 }, /* EOR */
+{ op_b108_3, 0, 45320, 0, 3, 0 }, /* CMPM */
+{ op_b110_3, 0, 45328, 0, 2, 1 }, /* EOR */
+{ op_b118_3, 0, 45336, 0, 2, 1 }, /* EOR */
+{ op_b120_3, 0, 45344, 2, 2, 1 }, /* EOR */
+{ op_b128_3, 0, 45352, 0, 3, 1 }, /* EOR */
+{ op_b130_3, 0, 45360, 2, 3, 1 }, /* EOR */
+{ op_b138_3, 0, 45368, 0, 3, 1 }, /* EOR */
+{ op_b139_3, 0, 45369, 0, 4, 1 }, /* EOR */
+{ op_b140_3, 0, 45376, 0, 1, 0 }, /* EOR */
+{ op_b148_3, 0, 45384, 0, 3, 0 }, /* CMPM */
+{ op_b150_3, 0, 45392, 0, 2, 1 }, /* EOR */
+{ op_b158_3, 0, 45400, 0, 2, 1 }, /* EOR */
+{ op_b160_3, 0, 45408, 2, 2, 1 }, /* EOR */
+{ op_b168_3, 0, 45416, 0, 3, 1 }, /* EOR */
+{ op_b170_3, 0, 45424, 2, 3, 1 }, /* EOR */
+{ op_b178_3, 0, 45432, 0, 3, 1 }, /* EOR */
+{ op_b179_3, 0, 45433, 0, 4, 1 }, /* EOR */
+{ op_b180_3, 0, 45440, 4, 1, 0 }, /* EOR */
+{ op_b188_3, 0, 45448, 0, 5, 0 }, /* CMPM */
+{ op_b190_3, 0, 45456, 0, 3, 2 }, /* EOR */
+{ op_b198_3, 0, 45464, 0, 3, 2 }, /* EOR */
+{ op_b1a0_3, 0, 45472, 2, 3, 2 }, /* EOR */
+{ op_b1a8_3, 0, 45480, 0, 4, 2 }, /* EOR */
+{ op_b1b0_3, 0, 45488, 2, 4, 2 }, /* EOR */
+{ op_b1b8_3, 0, 45496, 0, 4, 2 }, /* EOR */
+{ op_b1b9_3, 0, 45497, 0, 5, 2 }, /* EOR */
+{ op_b1c0_3, 0, 45504, 2, 1, 0 }, /* CMPA */
+{ op_b1c8_3, 0, 45512, 2, 1, 0 }, /* CMPA */
+{ op_b1d0_3, 0, 45520, 2, 3, 0 }, /* CMPA */
+{ op_b1d8_3, 0, 45528, 2, 3, 0 }, /* CMPA */
+{ op_b1e0_3, 0, 45536, 4, 3, 0 }, /* CMPA */
+{ op_b1e8_3, 0, 45544, 2, 4, 0 }, /* CMPA */
+{ op_b1f0_3, 0, 45552, 4, 4, 0 }, /* CMPA */
+{ op_b1f8_3, 0, 45560, 2, 4, 0 }, /* CMPA */
+{ op_b1f9_3, 0, 45561, 2, 5, 0 }, /* CMPA */
+{ op_b1fa_3, 0, 45562, 2, 4, 0 }, /* CMPA */
+{ op_b1fb_3, 0, 45563, 4, 4, 0 }, /* CMPA */
+{ op_b1fc_3, 0, 45564, 2, 3, 0 }, /* CMPA */
+{ op_c000_3, 0, 49152, 0, 1, 0 }, /* AND */
+{ op_c010_3, 0, 49168, 0, 2, 0 }, /* AND */
+{ op_c018_3, 0, 49176, 0, 2, 0 }, /* AND */
+{ op_c020_3, 0, 49184, 2, 2, 0 }, /* AND */
+{ op_c028_3, 0, 49192, 0, 3, 0 }, /* AND */
+{ op_c030_3, 0, 49200, 2, 3, 0 }, /* AND */
+{ op_c038_3, 0, 49208, 0, 3, 0 }, /* AND */
+{ op_c039_3, 0, 49209, 0, 4, 0 }, /* AND */
+{ op_c03a_3, 0, 49210, 0, 3, 0 }, /* AND */
+{ op_c03b_3, 0, 49211, 2, 3, 0 }, /* AND */
+{ op_c03c_3, 0, 49212, 0, 2, 0 }, /* AND */
+{ op_c040_3, 0, 49216, 0, 1, 0 }, /* AND */
+{ op_c050_3, 0, 49232, 0, 2, 0 }, /* AND */
+{ op_c058_3, 0, 49240, 0, 2, 0 }, /* AND */
+{ op_c060_3, 0, 49248, 2, 2, 0 }, /* AND */
+{ op_c068_3, 0, 49256, 0, 3, 0 }, /* AND */
+{ op_c070_3, 0, 49264, 2, 3, 0 }, /* AND */
+{ op_c078_3, 0, 49272, 0, 3, 0 }, /* AND */
+{ op_c079_3, 0, 49273, 0, 4, 0 }, /* AND */
+{ op_c07a_3, 0, 49274, 0, 3, 0 }, /* AND */
+{ op_c07b_3, 0, 49275, 2, 3, 0 }, /* AND */
+{ op_c07c_3, 0, 49276, 0, 2, 0 }, /* AND */
+{ op_c080_3, 0, 49280, 2, 1, 0 }, /* AND */
+{ op_c090_3, 0, 49296, 2, 3, 0 }, /* AND */
+{ op_c098_3, 0, 49304, 2, 3, 0 }, /* AND */
+{ op_c0a0_3, 0, 49312, 4, 3, 0 }, /* AND */
+{ op_c0a8_3, 0, 49320, 2, 4, 0 }, /* AND */
+{ op_c0b0_3, 0, 49328, 4, 4, 0 }, /* AND */
+{ op_c0b8_3, 0, 49336, 2, 4, 0 }, /* AND */
+{ op_c0b9_3, 0, 49337, 2, 5, 0 }, /* AND */
+{ op_c0ba_3, 0, 49338, 2, 4, 0 }, /* AND */
+{ op_c0bb_3, 0, 49339, 4, 4, 0 }, /* AND */
+{ op_c0bc_3, 0, 49340, 2, 3, 0 }, /* AND */
+{ op_c0c0_3, 0, 49344, 66, 1, 0 }, /* MULU */
+{ op_c0d0_3, 0, 49360, 66, 2, 0 }, /* MULU */
+{ op_c0d8_3, 0, 49368, 66, 2, 0 }, /* MULU */
+{ op_c0e0_3, 0, 49376, 68, 2, 0 }, /* MULU */
+{ op_c0e8_3, 0, 49384, 66, 3, 0 }, /* MULU */
+{ op_c0f0_3, 0, 49392, 68, 3, 0 }, /* MULU */
+{ op_c0f8_3, 0, 49400, 66, 3, 0 }, /* MULU */
+{ op_c0f9_3, 0, 49401, 66, 4, 0 }, /* MULU */
+{ op_c0fa_3, 0, 49402, 66, 3, 0 }, /* MULU */
+{ op_c0fb_3, 0, 49403, 68, 3, 0 }, /* MULU */
+{ op_c0fc_3, 0, 49404, 66, 2, 0 }, /* MULU */
+{ op_c100_3, 0, 49408, 2, 1, 0 }, /* ABCD */
+{ op_c108_3, 0, 49416, 2, 3, 1 }, /* ABCD */
+{ op_c110_3, 0, 49424, 0, 2, 1 }, /* AND */
+{ op_c118_3, 0, 49432, 0, 2, 1 }, /* AND */
+{ op_c120_3, 0, 49440, 2, 2, 1 }, /* AND */
+{ op_c128_3, 0, 49448, 0, 3, 1 }, /* AND */
+{ op_c130_3, 0, 49456, 2, 3, 1 }, /* AND */
+{ op_c138_3, 0, 49464, 0, 3, 1 }, /* AND */
+{ op_c139_3, 0, 49465, 0, 4, 1 }, /* AND */
+{ op_c140_3, 0, 49472, 2, 1, 0 }, /* EXG */
+{ op_c148_3, 0, 49480, 2, 1, 0 }, /* EXG */
+{ op_c150_3, 0, 49488, 0, 2, 1 }, /* AND */
+{ op_c158_3, 0, 49496, 0, 2, 1 }, /* AND */
+{ op_c160_3, 0, 49504, 2, 2, 1 }, /* AND */
+{ op_c168_3, 0, 49512, 0, 3, 1 }, /* AND */
+{ op_c170_3, 0, 49520, 2, 3, 1 }, /* AND */
+{ op_c178_3, 0, 49528, 0, 3, 1 }, /* AND */
+{ op_c179_3, 0, 49529, 0, 4, 1 }, /* AND */
+{ op_c188_3, 0, 49544, 2, 1, 0 }, /* EXG */
+{ op_c190_3, 0, 49552, 0, 3, 2 }, /* AND */
+{ op_c198_3, 0, 49560, 0, 3, 2 }, /* AND */
+{ op_c1a0_3, 0, 49568, 2, 3, 2 }, /* AND */
+{ op_c1a8_3, 0, 49576, 0, 4, 2 }, /* AND */
+{ op_c1b0_3, 0, 49584, 2, 4, 2 }, /* AND */
+{ op_c1b8_3, 0, 49592, 0, 4, 2 }, /* AND */
+{ op_c1b9_3, 0, 49593, 0, 5, 2 }, /* AND */
+{ op_c1c0_3, 0, 49600, 66, 1, 0 }, /* MULS */
+{ op_c1d0_3, 0, 49616, 66, 2, 0 }, /* MULS */
+{ op_c1d8_3, 0, 49624, 66, 2, 0 }, /* MULS */
+{ op_c1e0_3, 0, 49632, 68, 2, 0 }, /* MULS */
+{ op_c1e8_3, 0, 49640, 66, 3, 0 }, /* MULS */
+{ op_c1f0_3, 0, 49648, 68, 3, 0 }, /* MULS */
+{ op_c1f8_3, 0, 49656, 66, 3, 0 }, /* MULS */
+{ op_c1f9_3, 0, 49657, 66, 4, 0 }, /* MULS */
+{ op_c1fa_3, 0, 49658, 66, 3, 0 }, /* MULS */
+{ op_c1fb_3, 0, 49659, 68, 3, 0 }, /* MULS */
+{ op_c1fc_3, 0, 49660, 66, 2, 0 }, /* MULS */
+{ op_d000_3, 0, 53248, 0, 1, 0 }, /* ADD */
+{ op_d010_3, 0, 53264, 0, 2, 0 }, /* ADD */
+{ op_d018_3, 0, 53272, 0, 2, 0 }, /* ADD */
+{ op_d020_3, 0, 53280, 2, 2, 0 }, /* ADD */
+{ op_d028_3, 0, 53288, 0, 3, 0 }, /* ADD */
+{ op_d030_3, 0, 53296, 2, 3, 0 }, /* ADD */
+{ op_d038_3, 0, 53304, 0, 3, 0 }, /* ADD */
+{ op_d039_3, 0, 53305, 0, 4, 0 }, /* ADD */
+{ op_d03a_3, 0, 53306, 0, 3, 0 }, /* ADD */
+{ op_d03b_3, 0, 53307, 2, 3, 0 }, /* ADD */
+{ op_d03c_3, 0, 53308, 0, 2, 0 }, /* ADD */
+{ op_d040_3, 0, 53312, 0, 1, 0 }, /* ADD */
+{ op_d048_3, 0, 53320, 0, 1, 0 }, /* ADD */
+{ op_d050_3, 0, 53328, 0, 2, 0 }, /* ADD */
+{ op_d058_3, 0, 53336, 0, 2, 0 }, /* ADD */
+{ op_d060_3, 0, 53344, 2, 2, 0 }, /* ADD */
+{ op_d068_3, 0, 53352, 0, 3, 0 }, /* ADD */
+{ op_d070_3, 0, 53360, 2, 3, 0 }, /* ADD */
+{ op_d078_3, 0, 53368, 0, 3, 0 }, /* ADD */
+{ op_d079_3, 0, 53369, 0, 4, 0 }, /* ADD */
+{ op_d07a_3, 0, 53370, 0, 3, 0 }, /* ADD */
+{ op_d07b_3, 0, 53371, 2, 3, 0 }, /* ADD */
+{ op_d07c_3, 0, 53372, 0, 2, 0 }, /* ADD */
+{ op_d080_3, 0, 53376, 4, 1, 0 }, /* ADD */
+{ op_d088_3, 0, 53384, 4, 1, 0 }, /* ADD */
+{ op_d090_3, 0, 53392, 2, 3, 0 }, /* ADD */
+{ op_d098_3, 0, 53400, 2, 3, 0 }, /* ADD */
+{ op_d0a0_3, 0, 53408, 4, 3, 0 }, /* ADD */
+{ op_d0a8_3, 0, 53416, 2, 4, 0 }, /* ADD */
+{ op_d0b0_3, 0, 53424, 4, 4, 0 }, /* ADD */
+{ op_d0b8_3, 0, 53432, 2, 4, 0 }, /* ADD */
+{ op_d0b9_3, 0, 53433, 2, 5, 0 }, /* ADD */
+{ op_d0ba_3, 0, 53434, 2, 4, 0 }, /* ADD */
+{ op_d0bb_3, 0, 53435, 4, 4, 0 }, /* ADD */
+{ op_d0bc_3, 0, 53436, 4, 3, 0 }, /* ADD */
+{ op_d0c0_3, 0, 53440, 4, 1, 0 }, /* ADDA */
+{ op_d0c8_3, 0, 53448, 4, 1, 0 }, /* ADDA */
+{ op_d0d0_3, 0, 53456, 4, 2, 0 }, /* ADDA */
+{ op_d0d8_3, 0, 53464, 4, 2, 0 }, /* ADDA */
+{ op_d0e0_3, 0, 53472, 6, 2, 0 }, /* ADDA */
+{ op_d0e8_3, 0, 53480, 4, 3, 0 }, /* ADDA */
+{ op_d0f0_3, 0, 53488, 6, 3, 0 }, /* ADDA */
+{ op_d0f8_3, 0, 53496, 4, 3, 0 }, /* ADDA */
+{ op_d0f9_3, 0, 53497, 4, 4, 0 }, /* ADDA */
+{ op_d0fa_3, 0, 53498, 4, 3, 0 }, /* ADDA */
+{ op_d0fb_3, 0, 53499, 6, 3, 0 }, /* ADDA */
+{ op_d0fc_3, 0, 53500, 4, 2, 0 }, /* ADDA */
+{ op_d100_3, 0, 53504, 0, 1, 0 }, /* ADDX */
+{ op_d108_3, 0, 53512, 2, 3, 1 }, /* ADDX */
+{ op_d110_3, 0, 53520, 0, 2, 1 }, /* ADD */
+{ op_d118_3, 0, 53528, 0, 2, 1 }, /* ADD */
+{ op_d120_3, 0, 53536, 2, 2, 1 }, /* ADD */
+{ op_d128_3, 0, 53544, 0, 3, 1 }, /* ADD */
+{ op_d130_3, 0, 53552, 2, 3, 1 }, /* ADD */
+{ op_d138_3, 0, 53560, 0, 3, 1 }, /* ADD */
+{ op_d139_3, 0, 53561, 0, 4, 1 }, /* ADD */
+{ op_d140_3, 0, 53568, 0, 1, 0 }, /* ADDX */
+{ op_d148_3, 0, 53576, 2, 3, 1 }, /* ADDX */
+{ op_d150_3, 0, 53584, 0, 2, 1 }, /* ADD */
+{ op_d158_3, 0, 53592, 0, 2, 1 }, /* ADD */
+{ op_d160_3, 0, 53600, 2, 2, 1 }, /* ADD */
+{ op_d168_3, 0, 53608, 0, 3, 1 }, /* ADD */
+{ op_d170_3, 0, 53616, 2, 3, 1 }, /* ADD */
+{ op_d178_3, 0, 53624, 0, 3, 1 }, /* ADD */
+{ op_d179_3, 0, 53625, 0, 4, 1 }, /* ADD */
+{ op_d180_3, 0, 53632, 4, 1, 0 }, /* ADDX */
+{ op_d188_3, 0, 53640, 2, 5, 2 }, /* ADDX */
+{ op_d190_3, 0, 53648, 0, 3, 2 }, /* ADD */
+{ op_d198_3, 0, 53656, 0, 3, 2 }, /* ADD */
+{ op_d1a0_3, 0, 53664, 2, 3, 2 }, /* ADD */
+{ op_d1a8_3, 0, 53672, 0, 4, 2 }, /* ADD */
+{ op_d1b0_3, 0, 53680, 2, 4, 2 }, /* ADD */
+{ op_d1b8_3, 0, 53688, 0, 4, 2 }, /* ADD */
+{ op_d1b9_3, 0, 53689, 0, 5, 2 }, /* ADD */
+{ op_d1c0_3, 0, 53696, 4, 1, 0 }, /* ADDA */
+{ op_d1c8_3, 0, 53704, 4, 1, 0 }, /* ADDA */
+{ op_d1d0_3, 0, 53712, 2, 3, 0 }, /* ADDA */
+{ op_d1d8_3, 0, 53720, 2, 3, 0 }, /* ADDA */
+{ op_d1e0_3, 0, 53728, 4, 3, 0 }, /* ADDA */
+{ op_d1e8_3, 0, 53736, 2, 4, 0 }, /* ADDA */
+{ op_d1f0_3, 0, 53744, 4, 4, 0 }, /* ADDA */
+{ op_d1f8_3, 0, 53752, 2, 4, 0 }, /* ADDA */
+{ op_d1f9_3, 0, 53753, 2, 5, 0 }, /* ADDA */
+{ op_d1fa_3, 0, 53754, 2, 4, 0 }, /* ADDA */
+{ op_d1fb_3, 0, 53755, 4, 4, 0 }, /* ADDA */
+{ op_d1fc_3, 0, 53756, 4, 3, 0 }, /* ADDA */
+{ op_e000_3, 0, 57344, 2, 1, 0 }, /* ASR */
+{ op_e008_3, 0, 57352, 2, 1, 0 }, /* LSR */
+{ op_e010_3, 0, 57360, 2, 1, 0 }, /* ROXR */
+{ op_e018_3, 0, 57368, 2, 1, 0 }, /* ROR */
+{ op_e020_3, 0, 57376, 2, 1, 0 }, /* ASR */
+{ op_e028_3, 0, 57384, 2, 1, 0 }, /* LSR */
+{ op_e030_3, 0, 57392, 2, 1, 0 }, /* ROXR */
+{ op_e038_3, 0, 57400, 2, 1, 0 }, /* ROR */
+{ op_e040_3, 0, 57408, 2, 1, 0 }, /* ASR */
+{ op_e048_3, 0, 57416, 2, 1, 0 }, /* LSR */
+{ op_e050_3, 0, 57424, 2, 1, 0 }, /* ROXR */
+{ op_e058_3, 0, 57432, 2, 1, 0 }, /* ROR */
+{ op_e060_3, 0, 57440, 2, 1, 0 }, /* ASR */
+{ op_e068_3, 0, 57448, 2, 1, 0 }, /* LSR */
+{ op_e070_3, 0, 57456, 2, 1, 0 }, /* ROXR */
+{ op_e078_3, 0, 57464, 2, 1, 0 }, /* ROR */
+{ op_e080_3, 0, 57472, 4, 1, 0 }, /* ASR */
+{ op_e088_3, 0, 57480, 4, 1, 0 }, /* LSR */
+{ op_e090_3, 0, 57488, 4, 1, 0 }, /* ROXR */
+{ op_e098_3, 0, 57496, 4, 1, 0 }, /* ROR */
+{ op_e0a0_3, 0, 57504, 4, 1, 0 }, /* ASR */
+{ op_e0a8_3, 0, 57512, 4, 1, 0 }, /* LSR */
+{ op_e0b0_3, 0, 57520, 4, 1, 0 }, /* ROXR */
+{ op_e0b8_3, 0, 57528, 4, 1, 0 }, /* ROR */
+{ op_e0d0_3, 0, 57552, 0, 2, 1 }, /* ASRW */
+{ op_e0d8_3, 0, 57560, 0, 2, 1 }, /* ASRW */
+{ op_e0e0_3, 0, 57568, 2, 2, 1 }, /* ASRW */
+{ op_e0e8_3, 0, 57576, 0, 3, 1 }, /* ASRW */
+{ op_e0f0_3, 0, 57584, 2, 3, 1 }, /* ASRW */
+{ op_e0f8_3, 0, 57592, 0, 3, 1 }, /* ASRW */
+{ op_e0f9_3, 0, 57593, 0, 4, 1 }, /* ASRW */
+{ op_e100_3, 0, 57600, 2, 1, 0 }, /* ASL */
+{ op_e108_3, 0, 57608, 2, 1, 0 }, /* LSL */
+{ op_e110_3, 0, 57616, 2, 1, 0 }, /* ROXL */
+{ op_e118_3, 0, 57624, 2, 1, 0 }, /* ROL */
+{ op_e120_3, 0, 57632, 2, 1, 0 }, /* ASL */
+{ op_e128_3, 0, 57640, 2, 1, 0 }, /* LSL */
+{ op_e130_3, 0, 57648, 2, 1, 0 }, /* ROXL */
+{ op_e138_3, 0, 57656, 2, 1, 0 }, /* ROL */
+{ op_e140_3, 0, 57664, 2, 1, 0 }, /* ASL */
+{ op_e148_3, 0, 57672, 2, 1, 0 }, /* LSL */
+{ op_e150_3, 0, 57680, 2, 1, 0 }, /* ROXL */
+{ op_e158_3, 0, 57688, 2, 1, 0 }, /* ROL */
+{ op_e160_3, 0, 57696, 2, 1, 0 }, /* ASL */
+{ op_e168_3, 0, 57704, 2, 1, 0 }, /* LSL */
+{ op_e170_3, 0, 57712, 2, 1, 0 }, /* ROXL */
+{ op_e178_3, 0, 57720, 2, 1, 0 }, /* ROL */
+{ op_e180_3, 0, 57728, 4, 1, 0 }, /* ASL */
+{ op_e188_3, 0, 57736, 4, 1, 0 }, /* LSL */
+{ op_e190_3, 0, 57744, 4, 1, 0 }, /* ROXL */
+{ op_e198_3, 0, 57752, 4, 1, 0 }, /* ROL */
+{ op_e1a0_3, 0, 57760, 4, 1, 0 }, /* ASL */
+{ op_e1a8_3, 0, 57768, 4, 1, 0 }, /* LSL */
+{ op_e1b0_3, 0, 57776, 4, 1, 0 }, /* ROXL */
+{ op_e1b8_3, 0, 57784, 4, 1, 0 }, /* ROL */
+{ op_e1d0_3, 0, 57808, 0, 2, 1 }, /* ASLW */
+{ op_e1d8_3, 0, 57816, 0, 2, 1 }, /* ASLW */
+{ op_e1e0_3, 0, 57824, 2, 2, 1 }, /* ASLW */
+{ op_e1e8_3, 0, 57832, 0, 3, 1 }, /* ASLW */
+{ op_e1f0_3, 0, 57840, 2, 3, 1 }, /* ASLW */
+{ op_e1f8_3, 0, 57848, 0, 3, 1 }, /* ASLW */
+{ op_e1f9_3, 0, 57849, 0, 4, 1 }, /* ASLW */
+{ op_e2d0_3, 0, 58064, 0, 2, 1 }, /* LSRW */
+{ op_e2d8_3, 0, 58072, 0, 2, 1 }, /* LSRW */
+{ op_e2e0_3, 0, 58080, 2, 2, 1 }, /* LSRW */
+{ op_e2e8_3, 0, 58088, 0, 3, 1 }, /* LSRW */
+{ op_e2f0_3, 0, 58096, 2, 3, 1 }, /* LSRW */
+{ op_e2f8_3, 0, 58104, 0, 3, 1 }, /* LSRW */
+{ op_e2f9_3, 0, 58105, 0, 4, 1 }, /* LSRW */
+{ op_e3d0_3, 0, 58320, 0, 2, 1 }, /* LSLW */
+{ op_e3d8_3, 0, 58328, 0, 2, 1 }, /* LSLW */
+{ op_e3e0_3, 0, 58336, 2, 2, 1 }, /* LSLW */
+{ op_e3e8_3, 0, 58344, 0, 3, 1 }, /* LSLW */
+{ op_e3f0_3, 0, 58352, 2, 3, 1 }, /* LSLW */
+{ op_e3f8_3, 0, 58360, 0, 3, 1 }, /* LSLW */
+{ op_e3f9_3, 0, 58361, 0, 4, 1 }, /* LSLW */
+{ op_e4d0_3, 0, 58576, 0, 2, 1 }, /* ROXRW */
+{ op_e4d8_3, 0, 58584, 0, 2, 1 }, /* ROXRW */
+{ op_e4e0_3, 0, 58592, 2, 2, 1 }, /* ROXRW */
+{ op_e4e8_3, 0, 58600, 0, 3, 1 }, /* ROXRW */
+{ op_e4f0_3, 0, 58608, 2, 3, 1 }, /* ROXRW */
+{ op_e4f8_3, 0, 58616, 0, 3, 1 }, /* ROXRW */
+{ op_e4f9_3, 0, 58617, 0, 4, 1 }, /* ROXRW */
+{ op_e5d0_3, 0, 58832, 0, 2, 1 }, /* ROXLW */
+{ op_e5d8_3, 0, 58840, 0, 2, 1 }, /* ROXLW */
+{ op_e5e0_3, 0, 58848, 2, 2, 1 }, /* ROXLW */
+{ op_e5e8_3, 0, 58856, 0, 3, 1 }, /* ROXLW */
+{ op_e5f0_3, 0, 58864, 2, 3, 1 }, /* ROXLW */
+{ op_e5f8_3, 0, 58872, 0, 3, 1 }, /* ROXLW */
+{ op_e5f9_3, 0, 58873, 0, 4, 1 }, /* ROXLW */
+{ op_e6d0_3, 0, 59088, 0, 2, 1 }, /* RORW */
+{ op_e6d8_3, 0, 59096, 0, 2, 1 }, /* RORW */
+{ op_e6e0_3, 0, 59104, 2, 2, 1 }, /* RORW */
+{ op_e6e8_3, 0, 59112, 0, 3, 1 }, /* RORW */
+{ op_e6f0_3, 0, 59120, 2, 3, 1 }, /* RORW */
+{ op_e6f8_3, 0, 59128, 0, 3, 1 }, /* RORW */
+{ op_e6f9_3, 0, 59129, 0, 4, 1 }, /* RORW */
+{ op_e7d0_3, 0, 59344, 0, 2, 1 }, /* ROLW */
+{ op_e7d8_3, 0, 59352, 0, 2, 1 }, /* ROLW */
+{ op_e7e0_3, 0, 59360, 2, 2, 1 }, /* ROLW */
+{ op_e7e8_3, 0, 59368, 0, 3, 1 }, /* ROLW */
+{ op_e7f0_3, 0, 59376, 2, 3, 1 }, /* ROLW */
+{ op_e7f8_3, 0, 59384, 0, 3, 1 }, /* ROLW */
+{ op_e7f9_3, 0, 59385, 0, 4, 1 }, /* ROLW */
+{ 0, 0, 0 }};
diff --git a/SrcShared/UAE/cputbl.h b/SrcShared/UAE/cputbl.h
new file mode 100644
index 0000000..c13d061
--- /dev/null
+++ b/SrcShared/UAE/cputbl.h
@@ -0,0 +1,1584 @@
+extern cpuop_func op_0_3;
+extern cpuop_func op_10_3;
+extern cpuop_func op_18_3;
+extern cpuop_func op_20_3;
+extern cpuop_func op_28_3;
+extern cpuop_func op_30_3;
+extern cpuop_func op_38_3;
+extern cpuop_func op_39_3;
+extern cpuop_func op_3c_3;
+extern cpuop_func op_40_3;
+extern cpuop_func op_50_3;
+extern cpuop_func op_58_3;
+extern cpuop_func op_60_3;
+extern cpuop_func op_68_3;
+extern cpuop_func op_70_3;
+extern cpuop_func op_78_3;
+extern cpuop_func op_79_3;
+extern cpuop_func op_7c_3;
+extern cpuop_func op_80_3;
+extern cpuop_func op_90_3;
+extern cpuop_func op_98_3;
+extern cpuop_func op_a0_3;
+extern cpuop_func op_a8_3;
+extern cpuop_func op_b0_3;
+extern cpuop_func op_b8_3;
+extern cpuop_func op_b9_3;
+extern cpuop_func op_100_3;
+extern cpuop_func op_108_3;
+extern cpuop_func op_110_3;
+extern cpuop_func op_118_3;
+extern cpuop_func op_120_3;
+extern cpuop_func op_128_3;
+extern cpuop_func op_130_3;
+extern cpuop_func op_138_3;
+extern cpuop_func op_139_3;
+extern cpuop_func op_13a_3;
+extern cpuop_func op_13b_3;
+extern cpuop_func op_13c_3;
+extern cpuop_func op_140_3;
+extern cpuop_func op_148_3;
+extern cpuop_func op_150_3;
+extern cpuop_func op_158_3;
+extern cpuop_func op_160_3;
+extern cpuop_func op_168_3;
+extern cpuop_func op_170_3;
+extern cpuop_func op_178_3;
+extern cpuop_func op_179_3;
+extern cpuop_func op_17a_3;
+extern cpuop_func op_17b_3;
+extern cpuop_func op_180_3;
+extern cpuop_func op_188_3;
+extern cpuop_func op_190_3;
+extern cpuop_func op_198_3;
+extern cpuop_func op_1a0_3;
+extern cpuop_func op_1a8_3;
+extern cpuop_func op_1b0_3;
+extern cpuop_func op_1b8_3;
+extern cpuop_func op_1b9_3;
+extern cpuop_func op_1ba_3;
+extern cpuop_func op_1bb_3;
+extern cpuop_func op_1c0_3;
+extern cpuop_func op_1c8_3;
+extern cpuop_func op_1d0_3;
+extern cpuop_func op_1d8_3;
+extern cpuop_func op_1e0_3;
+extern cpuop_func op_1e8_3;
+extern cpuop_func op_1f0_3;
+extern cpuop_func op_1f8_3;
+extern cpuop_func op_1f9_3;
+extern cpuop_func op_1fa_3;
+extern cpuop_func op_1fb_3;
+extern cpuop_func op_200_3;
+extern cpuop_func op_210_3;
+extern cpuop_func op_218_3;
+extern cpuop_func op_220_3;
+extern cpuop_func op_228_3;
+extern cpuop_func op_230_3;
+extern cpuop_func op_238_3;
+extern cpuop_func op_239_3;
+extern cpuop_func op_23c_3;
+extern cpuop_func op_240_3;
+extern cpuop_func op_250_3;
+extern cpuop_func op_258_3;
+extern cpuop_func op_260_3;
+extern cpuop_func op_268_3;
+extern cpuop_func op_270_3;
+extern cpuop_func op_278_3;
+extern cpuop_func op_279_3;
+extern cpuop_func op_27c_3;
+extern cpuop_func op_280_3;
+extern cpuop_func op_290_3;
+extern cpuop_func op_298_3;
+extern cpuop_func op_2a0_3;
+extern cpuop_func op_2a8_3;
+extern cpuop_func op_2b0_3;
+extern cpuop_func op_2b8_3;
+extern cpuop_func op_2b9_3;
+extern cpuop_func op_400_3;
+extern cpuop_func op_410_3;
+extern cpuop_func op_418_3;
+extern cpuop_func op_420_3;
+extern cpuop_func op_428_3;
+extern cpuop_func op_430_3;
+extern cpuop_func op_438_3;
+extern cpuop_func op_439_3;
+extern cpuop_func op_440_3;
+extern cpuop_func op_450_3;
+extern cpuop_func op_458_3;
+extern cpuop_func op_460_3;
+extern cpuop_func op_468_3;
+extern cpuop_func op_470_3;
+extern cpuop_func op_478_3;
+extern cpuop_func op_479_3;
+extern cpuop_func op_480_3;
+extern cpuop_func op_490_3;
+extern cpuop_func op_498_3;
+extern cpuop_func op_4a0_3;
+extern cpuop_func op_4a8_3;
+extern cpuop_func op_4b0_3;
+extern cpuop_func op_4b8_3;
+extern cpuop_func op_4b9_3;
+extern cpuop_func op_600_3;
+extern cpuop_func op_610_3;
+extern cpuop_func op_618_3;
+extern cpuop_func op_620_3;
+extern cpuop_func op_628_3;
+extern cpuop_func op_630_3;
+extern cpuop_func op_638_3;
+extern cpuop_func op_639_3;
+extern cpuop_func op_640_3;
+extern cpuop_func op_650_3;
+extern cpuop_func op_658_3;
+extern cpuop_func op_660_3;
+extern cpuop_func op_668_3;
+extern cpuop_func op_670_3;
+extern cpuop_func op_678_3;
+extern cpuop_func op_679_3;
+extern cpuop_func op_680_3;
+extern cpuop_func op_690_3;
+extern cpuop_func op_698_3;
+extern cpuop_func op_6a0_3;
+extern cpuop_func op_6a8_3;
+extern cpuop_func op_6b0_3;
+extern cpuop_func op_6b8_3;
+extern cpuop_func op_6b9_3;
+extern cpuop_func op_800_3;
+extern cpuop_func op_810_3;
+extern cpuop_func op_818_3;
+extern cpuop_func op_820_3;
+extern cpuop_func op_828_3;
+extern cpuop_func op_830_3;
+extern cpuop_func op_838_3;
+extern cpuop_func op_839_3;
+extern cpuop_func op_83a_3;
+extern cpuop_func op_83b_3;
+extern cpuop_func op_83c_3;
+extern cpuop_func op_840_3;
+extern cpuop_func op_850_3;
+extern cpuop_func op_858_3;
+extern cpuop_func op_860_3;
+extern cpuop_func op_868_3;
+extern cpuop_func op_870_3;
+extern cpuop_func op_878_3;
+extern cpuop_func op_879_3;
+extern cpuop_func op_87a_3;
+extern cpuop_func op_87b_3;
+extern cpuop_func op_880_3;
+extern cpuop_func op_890_3;
+extern cpuop_func op_898_3;
+extern cpuop_func op_8a0_3;
+extern cpuop_func op_8a8_3;
+extern cpuop_func op_8b0_3;
+extern cpuop_func op_8b8_3;
+extern cpuop_func op_8b9_3;
+extern cpuop_func op_8ba_3;
+extern cpuop_func op_8bb_3;
+extern cpuop_func op_8c0_3;
+extern cpuop_func op_8d0_3;
+extern cpuop_func op_8d8_3;
+extern cpuop_func op_8e0_3;
+extern cpuop_func op_8e8_3;
+extern cpuop_func op_8f0_3;
+extern cpuop_func op_8f8_3;
+extern cpuop_func op_8f9_3;
+extern cpuop_func op_8fa_3;
+extern cpuop_func op_8fb_3;
+extern cpuop_func op_a00_3;
+extern cpuop_func op_a10_3;
+extern cpuop_func op_a18_3;
+extern cpuop_func op_a20_3;
+extern cpuop_func op_a28_3;
+extern cpuop_func op_a30_3;
+extern cpuop_func op_a38_3;
+extern cpuop_func op_a39_3;
+extern cpuop_func op_a3c_3;
+extern cpuop_func op_a40_3;
+extern cpuop_func op_a50_3;
+extern cpuop_func op_a58_3;
+extern cpuop_func op_a60_3;
+extern cpuop_func op_a68_3;
+extern cpuop_func op_a70_3;
+extern cpuop_func op_a78_3;
+extern cpuop_func op_a79_3;
+extern cpuop_func op_a7c_3;
+extern cpuop_func op_a80_3;
+extern cpuop_func op_a90_3;
+extern cpuop_func op_a98_3;
+extern cpuop_func op_aa0_3;
+extern cpuop_func op_aa8_3;
+extern cpuop_func op_ab0_3;
+extern cpuop_func op_ab8_3;
+extern cpuop_func op_ab9_3;
+extern cpuop_func op_c00_3;
+extern cpuop_func op_c10_3;
+extern cpuop_func op_c18_3;
+extern cpuop_func op_c20_3;
+extern cpuop_func op_c28_3;
+extern cpuop_func op_c30_3;
+extern cpuop_func op_c38_3;
+extern cpuop_func op_c39_3;
+extern cpuop_func op_c3a_3;
+extern cpuop_func op_c3b_3;
+extern cpuop_func op_c40_3;
+extern cpuop_func op_c50_3;
+extern cpuop_func op_c58_3;
+extern cpuop_func op_c60_3;
+extern cpuop_func op_c68_3;
+extern cpuop_func op_c70_3;
+extern cpuop_func op_c78_3;
+extern cpuop_func op_c79_3;
+extern cpuop_func op_c7a_3;
+extern cpuop_func op_c7b_3;
+extern cpuop_func op_c80_3;
+extern cpuop_func op_c90_3;
+extern cpuop_func op_c98_3;
+extern cpuop_func op_ca0_3;
+extern cpuop_func op_ca8_3;
+extern cpuop_func op_cb0_3;
+extern cpuop_func op_cb8_3;
+extern cpuop_func op_cb9_3;
+extern cpuop_func op_cba_3;
+extern cpuop_func op_cbb_3;
+extern cpuop_func op_1000_3;
+extern cpuop_func op_1010_3;
+extern cpuop_func op_1018_3;
+extern cpuop_func op_1020_3;
+extern cpuop_func op_1028_3;
+extern cpuop_func op_1030_3;
+extern cpuop_func op_1038_3;
+extern cpuop_func op_1039_3;
+extern cpuop_func op_103a_3;
+extern cpuop_func op_103b_3;
+extern cpuop_func op_103c_3;
+extern cpuop_func op_1080_3;
+extern cpuop_func op_1090_3;
+extern cpuop_func op_1098_3;
+extern cpuop_func op_10a0_3;
+extern cpuop_func op_10a8_3;
+extern cpuop_func op_10b0_3;
+extern cpuop_func op_10b8_3;
+extern cpuop_func op_10b9_3;
+extern cpuop_func op_10ba_3;
+extern cpuop_func op_10bb_3;
+extern cpuop_func op_10bc_3;
+extern cpuop_func op_10c0_3;
+extern cpuop_func op_10d0_3;
+extern cpuop_func op_10d8_3;
+extern cpuop_func op_10e0_3;
+extern cpuop_func op_10e8_3;
+extern cpuop_func op_10f0_3;
+extern cpuop_func op_10f8_3;
+extern cpuop_func op_10f9_3;
+extern cpuop_func op_10fa_3;
+extern cpuop_func op_10fb_3;
+extern cpuop_func op_10fc_3;
+extern cpuop_func op_1100_3;
+extern cpuop_func op_1110_3;
+extern cpuop_func op_1118_3;
+extern cpuop_func op_1120_3;
+extern cpuop_func op_1128_3;
+extern cpuop_func op_1130_3;
+extern cpuop_func op_1138_3;
+extern cpuop_func op_1139_3;
+extern cpuop_func op_113a_3;
+extern cpuop_func op_113b_3;
+extern cpuop_func op_113c_3;
+extern cpuop_func op_1140_3;
+extern cpuop_func op_1150_3;
+extern cpuop_func op_1158_3;
+extern cpuop_func op_1160_3;
+extern cpuop_func op_1168_3;
+extern cpuop_func op_1170_3;
+extern cpuop_func op_1178_3;
+extern cpuop_func op_1179_3;
+extern cpuop_func op_117a_3;
+extern cpuop_func op_117b_3;
+extern cpuop_func op_117c_3;
+extern cpuop_func op_1180_3;
+extern cpuop_func op_1190_3;
+extern cpuop_func op_1198_3;
+extern cpuop_func op_11a0_3;
+extern cpuop_func op_11a8_3;
+extern cpuop_func op_11b0_3;
+extern cpuop_func op_11b8_3;
+extern cpuop_func op_11b9_3;
+extern cpuop_func op_11ba_3;
+extern cpuop_func op_11bb_3;
+extern cpuop_func op_11bc_3;
+extern cpuop_func op_11c0_3;
+extern cpuop_func op_11d0_3;
+extern cpuop_func op_11d8_3;
+extern cpuop_func op_11e0_3;
+extern cpuop_func op_11e8_3;
+extern cpuop_func op_11f0_3;
+extern cpuop_func op_11f8_3;
+extern cpuop_func op_11f9_3;
+extern cpuop_func op_11fa_3;
+extern cpuop_func op_11fb_3;
+extern cpuop_func op_11fc_3;
+extern cpuop_func op_13c0_3;
+extern cpuop_func op_13d0_3;
+extern cpuop_func op_13d8_3;
+extern cpuop_func op_13e0_3;
+extern cpuop_func op_13e8_3;
+extern cpuop_func op_13f0_3;
+extern cpuop_func op_13f8_3;
+extern cpuop_func op_13f9_3;
+extern cpuop_func op_13fa_3;
+extern cpuop_func op_13fb_3;
+extern cpuop_func op_13fc_3;
+extern cpuop_func op_2000_3;
+extern cpuop_func op_2008_3;
+extern cpuop_func op_2010_3;
+extern cpuop_func op_2018_3;
+extern cpuop_func op_2020_3;
+extern cpuop_func op_2028_3;
+extern cpuop_func op_2030_3;
+extern cpuop_func op_2038_3;
+extern cpuop_func op_2039_3;
+extern cpuop_func op_203a_3;
+extern cpuop_func op_203b_3;
+extern cpuop_func op_203c_3;
+extern cpuop_func op_2040_3;
+extern cpuop_func op_2048_3;
+extern cpuop_func op_2050_3;
+extern cpuop_func op_2058_3;
+extern cpuop_func op_2060_3;
+extern cpuop_func op_2068_3;
+extern cpuop_func op_2070_3;
+extern cpuop_func op_2078_3;
+extern cpuop_func op_2079_3;
+extern cpuop_func op_207a_3;
+extern cpuop_func op_207b_3;
+extern cpuop_func op_207c_3;
+extern cpuop_func op_2080_3;
+extern cpuop_func op_2088_3;
+extern cpuop_func op_2090_3;
+extern cpuop_func op_2098_3;
+extern cpuop_func op_20a0_3;
+extern cpuop_func op_20a8_3;
+extern cpuop_func op_20b0_3;
+extern cpuop_func op_20b8_3;
+extern cpuop_func op_20b9_3;
+extern cpuop_func op_20ba_3;
+extern cpuop_func op_20bb_3;
+extern cpuop_func op_20bc_3;
+extern cpuop_func op_20c0_3;
+extern cpuop_func op_20c8_3;
+extern cpuop_func op_20d0_3;
+extern cpuop_func op_20d8_3;
+extern cpuop_func op_20e0_3;
+extern cpuop_func op_20e8_3;
+extern cpuop_func op_20f0_3;
+extern cpuop_func op_20f8_3;
+extern cpuop_func op_20f9_3;
+extern cpuop_func op_20fa_3;
+extern cpuop_func op_20fb_3;
+extern cpuop_func op_20fc_3;
+extern cpuop_func op_2100_3;
+extern cpuop_func op_2108_3;
+extern cpuop_func op_2110_3;
+extern cpuop_func op_2118_3;
+extern cpuop_func op_2120_3;
+extern cpuop_func op_2128_3;
+extern cpuop_func op_2130_3;
+extern cpuop_func op_2138_3;
+extern cpuop_func op_2139_3;
+extern cpuop_func op_213a_3;
+extern cpuop_func op_213b_3;
+extern cpuop_func op_213c_3;
+extern cpuop_func op_2140_3;
+extern cpuop_func op_2148_3;
+extern cpuop_func op_2150_3;
+extern cpuop_func op_2158_3;
+extern cpuop_func op_2160_3;
+extern cpuop_func op_2168_3;
+extern cpuop_func op_2170_3;
+extern cpuop_func op_2178_3;
+extern cpuop_func op_2179_3;
+extern cpuop_func op_217a_3;
+extern cpuop_func op_217b_3;
+extern cpuop_func op_217c_3;
+extern cpuop_func op_2180_3;
+extern cpuop_func op_2188_3;
+extern cpuop_func op_2190_3;
+extern cpuop_func op_2198_3;
+extern cpuop_func op_21a0_3;
+extern cpuop_func op_21a8_3;
+extern cpuop_func op_21b0_3;
+extern cpuop_func op_21b8_3;
+extern cpuop_func op_21b9_3;
+extern cpuop_func op_21ba_3;
+extern cpuop_func op_21bb_3;
+extern cpuop_func op_21bc_3;
+extern cpuop_func op_21c0_3;
+extern cpuop_func op_21c8_3;
+extern cpuop_func op_21d0_3;
+extern cpuop_func op_21d8_3;
+extern cpuop_func op_21e0_3;
+extern cpuop_func op_21e8_3;
+extern cpuop_func op_21f0_3;
+extern cpuop_func op_21f8_3;
+extern cpuop_func op_21f9_3;
+extern cpuop_func op_21fa_3;
+extern cpuop_func op_21fb_3;
+extern cpuop_func op_21fc_3;
+extern cpuop_func op_23c0_3;
+extern cpuop_func op_23c8_3;
+extern cpuop_func op_23d0_3;
+extern cpuop_func op_23d8_3;
+extern cpuop_func op_23e0_3;
+extern cpuop_func op_23e8_3;
+extern cpuop_func op_23f0_3;
+extern cpuop_func op_23f8_3;
+extern cpuop_func op_23f9_3;
+extern cpuop_func op_23fa_3;
+extern cpuop_func op_23fb_3;
+extern cpuop_func op_23fc_3;
+extern cpuop_func op_3000_3;
+extern cpuop_func op_3008_3;
+extern cpuop_func op_3010_3;
+extern cpuop_func op_3018_3;
+extern cpuop_func op_3020_3;
+extern cpuop_func op_3028_3;
+extern cpuop_func op_3030_3;
+extern cpuop_func op_3038_3;
+extern cpuop_func op_3039_3;
+extern cpuop_func op_303a_3;
+extern cpuop_func op_303b_3;
+extern cpuop_func op_303c_3;
+extern cpuop_func op_3040_3;
+extern cpuop_func op_3048_3;
+extern cpuop_func op_3050_3;
+extern cpuop_func op_3058_3;
+extern cpuop_func op_3060_3;
+extern cpuop_func op_3068_3;
+extern cpuop_func op_3070_3;
+extern cpuop_func op_3078_3;
+extern cpuop_func op_3079_3;
+extern cpuop_func op_307a_3;
+extern cpuop_func op_307b_3;
+extern cpuop_func op_307c_3;
+extern cpuop_func op_3080_3;
+extern cpuop_func op_3088_3;
+extern cpuop_func op_3090_3;
+extern cpuop_func op_3098_3;
+extern cpuop_func op_30a0_3;
+extern cpuop_func op_30a8_3;
+extern cpuop_func op_30b0_3;
+extern cpuop_func op_30b8_3;
+extern cpuop_func op_30b9_3;
+extern cpuop_func op_30ba_3;
+extern cpuop_func op_30bb_3;
+extern cpuop_func op_30bc_3;
+extern cpuop_func op_30c0_3;
+extern cpuop_func op_30c8_3;
+extern cpuop_func op_30d0_3;
+extern cpuop_func op_30d8_3;
+extern cpuop_func op_30e0_3;
+extern cpuop_func op_30e8_3;
+extern cpuop_func op_30f0_3;
+extern cpuop_func op_30f8_3;
+extern cpuop_func op_30f9_3;
+extern cpuop_func op_30fa_3;
+extern cpuop_func op_30fb_3;
+extern cpuop_func op_30fc_3;
+extern cpuop_func op_3100_3;
+extern cpuop_func op_3108_3;
+extern cpuop_func op_3110_3;
+extern cpuop_func op_3118_3;
+extern cpuop_func op_3120_3;
+extern cpuop_func op_3128_3;
+extern cpuop_func op_3130_3;
+extern cpuop_func op_3138_3;
+extern cpuop_func op_3139_3;
+extern cpuop_func op_313a_3;
+extern cpuop_func op_313b_3;
+extern cpuop_func op_313c_3;
+extern cpuop_func op_3140_3;
+extern cpuop_func op_3148_3;
+extern cpuop_func op_3150_3;
+extern cpuop_func op_3158_3;
+extern cpuop_func op_3160_3;
+extern cpuop_func op_3168_3;
+extern cpuop_func op_3170_3;
+extern cpuop_func op_3178_3;
+extern cpuop_func op_3179_3;
+extern cpuop_func op_317a_3;
+extern cpuop_func op_317b_3;
+extern cpuop_func op_317c_3;
+extern cpuop_func op_3180_3;
+extern cpuop_func op_3188_3;
+extern cpuop_func op_3190_3;
+extern cpuop_func op_3198_3;
+extern cpuop_func op_31a0_3;
+extern cpuop_func op_31a8_3;
+extern cpuop_func op_31b0_3;
+extern cpuop_func op_31b8_3;
+extern cpuop_func op_31b9_3;
+extern cpuop_func op_31ba_3;
+extern cpuop_func op_31bb_3;
+extern cpuop_func op_31bc_3;
+extern cpuop_func op_31c0_3;
+extern cpuop_func op_31c8_3;
+extern cpuop_func op_31d0_3;
+extern cpuop_func op_31d8_3;
+extern cpuop_func op_31e0_3;
+extern cpuop_func op_31e8_3;
+extern cpuop_func op_31f0_3;
+extern cpuop_func op_31f8_3;
+extern cpuop_func op_31f9_3;
+extern cpuop_func op_31fa_3;
+extern cpuop_func op_31fb_3;
+extern cpuop_func op_31fc_3;
+extern cpuop_func op_33c0_3;
+extern cpuop_func op_33c8_3;
+extern cpuop_func op_33d0_3;
+extern cpuop_func op_33d8_3;
+extern cpuop_func op_33e0_3;
+extern cpuop_func op_33e8_3;
+extern cpuop_func op_33f0_3;
+extern cpuop_func op_33f8_3;
+extern cpuop_func op_33f9_3;
+extern cpuop_func op_33fa_3;
+extern cpuop_func op_33fb_3;
+extern cpuop_func op_33fc_3;
+extern cpuop_func op_4000_3;
+extern cpuop_func op_4010_3;
+extern cpuop_func op_4018_3;
+extern cpuop_func op_4020_3;
+extern cpuop_func op_4028_3;
+extern cpuop_func op_4030_3;
+extern cpuop_func op_4038_3;
+extern cpuop_func op_4039_3;
+extern cpuop_func op_4040_3;
+extern cpuop_func op_4050_3;
+extern cpuop_func op_4058_3;
+extern cpuop_func op_4060_3;
+extern cpuop_func op_4068_3;
+extern cpuop_func op_4070_3;
+extern cpuop_func op_4078_3;
+extern cpuop_func op_4079_3;
+extern cpuop_func op_4080_3;
+extern cpuop_func op_4090_3;
+extern cpuop_func op_4098_3;
+extern cpuop_func op_40a0_3;
+extern cpuop_func op_40a8_3;
+extern cpuop_func op_40b0_3;
+extern cpuop_func op_40b8_3;
+extern cpuop_func op_40b9_3;
+extern cpuop_func op_40c0_3;
+extern cpuop_func op_40d0_3;
+extern cpuop_func op_40d8_3;
+extern cpuop_func op_40e0_3;
+extern cpuop_func op_40e8_3;
+extern cpuop_func op_40f0_3;
+extern cpuop_func op_40f8_3;
+extern cpuop_func op_40f9_3;
+extern cpuop_func op_4100_3;
+extern cpuop_func op_4110_3;
+extern cpuop_func op_4118_3;
+extern cpuop_func op_4120_3;
+extern cpuop_func op_4128_3;
+extern cpuop_func op_4130_3;
+extern cpuop_func op_4138_3;
+extern cpuop_func op_4139_3;
+extern cpuop_func op_413a_3;
+extern cpuop_func op_413b_3;
+extern cpuop_func op_413c_3;
+extern cpuop_func op_4180_3;
+extern cpuop_func op_4190_3;
+extern cpuop_func op_4198_3;
+extern cpuop_func op_41a0_3;
+extern cpuop_func op_41a8_3;
+extern cpuop_func op_41b0_3;
+extern cpuop_func op_41b8_3;
+extern cpuop_func op_41b9_3;
+extern cpuop_func op_41ba_3;
+extern cpuop_func op_41bb_3;
+extern cpuop_func op_41bc_3;
+extern cpuop_func op_41d0_3;
+extern cpuop_func op_41e8_3;
+extern cpuop_func op_41f0_3;
+extern cpuop_func op_41f8_3;
+extern cpuop_func op_41f9_3;
+extern cpuop_func op_41fa_3;
+extern cpuop_func op_41fb_3;
+extern cpuop_func op_4200_3;
+extern cpuop_func op_4210_3;
+extern cpuop_func op_4218_3;
+extern cpuop_func op_4220_3;
+extern cpuop_func op_4228_3;
+extern cpuop_func op_4230_3;
+extern cpuop_func op_4238_3;
+extern cpuop_func op_4239_3;
+extern cpuop_func op_4240_3;
+extern cpuop_func op_4250_3;
+extern cpuop_func op_4258_3;
+extern cpuop_func op_4260_3;
+extern cpuop_func op_4268_3;
+extern cpuop_func op_4270_3;
+extern cpuop_func op_4278_3;
+extern cpuop_func op_4279_3;
+extern cpuop_func op_4280_3;
+extern cpuop_func op_4290_3;
+extern cpuop_func op_4298_3;
+extern cpuop_func op_42a0_3;
+extern cpuop_func op_42a8_3;
+extern cpuop_func op_42b0_3;
+extern cpuop_func op_42b8_3;
+extern cpuop_func op_42b9_3;
+extern cpuop_func op_4400_3;
+extern cpuop_func op_4410_3;
+extern cpuop_func op_4418_3;
+extern cpuop_func op_4420_3;
+extern cpuop_func op_4428_3;
+extern cpuop_func op_4430_3;
+extern cpuop_func op_4438_3;
+extern cpuop_func op_4439_3;
+extern cpuop_func op_4440_3;
+extern cpuop_func op_4450_3;
+extern cpuop_func op_4458_3;
+extern cpuop_func op_4460_3;
+extern cpuop_func op_4468_3;
+extern cpuop_func op_4470_3;
+extern cpuop_func op_4478_3;
+extern cpuop_func op_4479_3;
+extern cpuop_func op_4480_3;
+extern cpuop_func op_4490_3;
+extern cpuop_func op_4498_3;
+extern cpuop_func op_44a0_3;
+extern cpuop_func op_44a8_3;
+extern cpuop_func op_44b0_3;
+extern cpuop_func op_44b8_3;
+extern cpuop_func op_44b9_3;
+extern cpuop_func op_44c0_3;
+extern cpuop_func op_44d0_3;
+extern cpuop_func op_44d8_3;
+extern cpuop_func op_44e0_3;
+extern cpuop_func op_44e8_3;
+extern cpuop_func op_44f0_3;
+extern cpuop_func op_44f8_3;
+extern cpuop_func op_44f9_3;
+extern cpuop_func op_44fa_3;
+extern cpuop_func op_44fb_3;
+extern cpuop_func op_44fc_3;
+extern cpuop_func op_4600_3;
+extern cpuop_func op_4610_3;
+extern cpuop_func op_4618_3;
+extern cpuop_func op_4620_3;
+extern cpuop_func op_4628_3;
+extern cpuop_func op_4630_3;
+extern cpuop_func op_4638_3;
+extern cpuop_func op_4639_3;
+extern cpuop_func op_4640_3;
+extern cpuop_func op_4650_3;
+extern cpuop_func op_4658_3;
+extern cpuop_func op_4660_3;
+extern cpuop_func op_4668_3;
+extern cpuop_func op_4670_3;
+extern cpuop_func op_4678_3;
+extern cpuop_func op_4679_3;
+extern cpuop_func op_4680_3;
+extern cpuop_func op_4690_3;
+extern cpuop_func op_4698_3;
+extern cpuop_func op_46a0_3;
+extern cpuop_func op_46a8_3;
+extern cpuop_func op_46b0_3;
+extern cpuop_func op_46b8_3;
+extern cpuop_func op_46b9_3;
+extern cpuop_func op_46c0_3;
+extern cpuop_func op_46d0_3;
+extern cpuop_func op_46d8_3;
+extern cpuop_func op_46e0_3;
+extern cpuop_func op_46e8_3;
+extern cpuop_func op_46f0_3;
+extern cpuop_func op_46f8_3;
+extern cpuop_func op_46f9_3;
+extern cpuop_func op_46fa_3;
+extern cpuop_func op_46fb_3;
+extern cpuop_func op_46fc_3;
+extern cpuop_func op_4800_3;
+extern cpuop_func op_4810_3;
+extern cpuop_func op_4818_3;
+extern cpuop_func op_4820_3;
+extern cpuop_func op_4828_3;
+extern cpuop_func op_4830_3;
+extern cpuop_func op_4838_3;
+extern cpuop_func op_4839_3;
+extern cpuop_func op_4840_3;
+extern cpuop_func op_4850_3;
+extern cpuop_func op_4868_3;
+extern cpuop_func op_4870_3;
+extern cpuop_func op_4878_3;
+extern cpuop_func op_4879_3;
+extern cpuop_func op_487a_3;
+extern cpuop_func op_487b_3;
+extern cpuop_func op_4880_3;
+extern cpuop_func op_4890_3;
+extern cpuop_func op_48a0_3;
+extern cpuop_func op_48a8_3;
+extern cpuop_func op_48b0_3;
+extern cpuop_func op_48b8_3;
+extern cpuop_func op_48b9_3;
+extern cpuop_func op_48c0_3;
+extern cpuop_func op_48d0_3;
+extern cpuop_func op_48e0_3;
+extern cpuop_func op_48e8_3;
+extern cpuop_func op_48f0_3;
+extern cpuop_func op_48f8_3;
+extern cpuop_func op_48f9_3;
+extern cpuop_func op_49c0_3;
+extern cpuop_func op_4a00_3;
+extern cpuop_func op_4a10_3;
+extern cpuop_func op_4a18_3;
+extern cpuop_func op_4a20_3;
+extern cpuop_func op_4a28_3;
+extern cpuop_func op_4a30_3;
+extern cpuop_func op_4a38_3;
+extern cpuop_func op_4a39_3;
+extern cpuop_func op_4a3a_3;
+extern cpuop_func op_4a3b_3;
+extern cpuop_func op_4a3c_3;
+extern cpuop_func op_4a40_3;
+extern cpuop_func op_4a48_3;
+extern cpuop_func op_4a50_3;
+extern cpuop_func op_4a58_3;
+extern cpuop_func op_4a60_3;
+extern cpuop_func op_4a68_3;
+extern cpuop_func op_4a70_3;
+extern cpuop_func op_4a78_3;
+extern cpuop_func op_4a79_3;
+extern cpuop_func op_4a7a_3;
+extern cpuop_func op_4a7b_3;
+extern cpuop_func op_4a7c_3;
+extern cpuop_func op_4a80_3;
+extern cpuop_func op_4a88_3;
+extern cpuop_func op_4a90_3;
+extern cpuop_func op_4a98_3;
+extern cpuop_func op_4aa0_3;
+extern cpuop_func op_4aa8_3;
+extern cpuop_func op_4ab0_3;
+extern cpuop_func op_4ab8_3;
+extern cpuop_func op_4ab9_3;
+extern cpuop_func op_4aba_3;
+extern cpuop_func op_4abb_3;
+extern cpuop_func op_4abc_3;
+extern cpuop_func op_4ac0_3;
+extern cpuop_func op_4ad0_3;
+extern cpuop_func op_4ad8_3;
+extern cpuop_func op_4ae0_3;
+extern cpuop_func op_4ae8_3;
+extern cpuop_func op_4af0_3;
+extern cpuop_func op_4af8_3;
+extern cpuop_func op_4af9_3;
+extern cpuop_func op_4c90_3;
+extern cpuop_func op_4c98_3;
+extern cpuop_func op_4ca8_3;
+extern cpuop_func op_4cb0_3;
+extern cpuop_func op_4cb8_3;
+extern cpuop_func op_4cb9_3;
+extern cpuop_func op_4cba_3;
+extern cpuop_func op_4cbb_3;
+extern cpuop_func op_4cd0_3;
+extern cpuop_func op_4cd8_3;
+extern cpuop_func op_4ce8_3;
+extern cpuop_func op_4cf0_3;
+extern cpuop_func op_4cf8_3;
+extern cpuop_func op_4cf9_3;
+extern cpuop_func op_4cfa_3;
+extern cpuop_func op_4cfb_3;
+extern cpuop_func op_4e40_3;
+extern cpuop_func op_4e50_3;
+extern cpuop_func op_4e58_3;
+extern cpuop_func op_4e60_3;
+extern cpuop_func op_4e68_3;
+extern cpuop_func op_4e70_3;
+extern cpuop_func op_4e71_3;
+extern cpuop_func op_4e72_3;
+extern cpuop_func op_4e73_3;
+extern cpuop_func op_4e74_3;
+extern cpuop_func op_4e75_3;
+extern cpuop_func op_4e76_3;
+extern cpuop_func op_4e77_3;
+extern cpuop_func op_4e90_3;
+extern cpuop_func op_4ea8_3;
+extern cpuop_func op_4eb0_3;
+extern cpuop_func op_4eb8_3;
+extern cpuop_func op_4eb9_3;
+extern cpuop_func op_4eba_3;
+extern cpuop_func op_4ebb_3;
+extern cpuop_func op_4ed0_3;
+extern cpuop_func op_4ee8_3;
+extern cpuop_func op_4ef0_3;
+extern cpuop_func op_4ef8_3;
+extern cpuop_func op_4ef9_3;
+extern cpuop_func op_4efa_3;
+extern cpuop_func op_4efb_3;
+extern cpuop_func op_5000_3;
+extern cpuop_func op_5010_3;
+extern cpuop_func op_5018_3;
+extern cpuop_func op_5020_3;
+extern cpuop_func op_5028_3;
+extern cpuop_func op_5030_3;
+extern cpuop_func op_5038_3;
+extern cpuop_func op_5039_3;
+extern cpuop_func op_5040_3;
+extern cpuop_func op_5048_3;
+extern cpuop_func op_5050_3;
+extern cpuop_func op_5058_3;
+extern cpuop_func op_5060_3;
+extern cpuop_func op_5068_3;
+extern cpuop_func op_5070_3;
+extern cpuop_func op_5078_3;
+extern cpuop_func op_5079_3;
+extern cpuop_func op_5080_3;
+extern cpuop_func op_5088_3;
+extern cpuop_func op_5090_3;
+extern cpuop_func op_5098_3;
+extern cpuop_func op_50a0_3;
+extern cpuop_func op_50a8_3;
+extern cpuop_func op_50b0_3;
+extern cpuop_func op_50b8_3;
+extern cpuop_func op_50b9_3;
+extern cpuop_func op_50c0_3;
+extern cpuop_func op_50c8_3;
+extern cpuop_func op_50d0_3;
+extern cpuop_func op_50d8_3;
+extern cpuop_func op_50e0_3;
+extern cpuop_func op_50e8_3;
+extern cpuop_func op_50f0_3;
+extern cpuop_func op_50f8_3;
+extern cpuop_func op_50f9_3;
+extern cpuop_func op_5100_3;
+extern cpuop_func op_5110_3;
+extern cpuop_func op_5118_3;
+extern cpuop_func op_5120_3;
+extern cpuop_func op_5128_3;
+extern cpuop_func op_5130_3;
+extern cpuop_func op_5138_3;
+extern cpuop_func op_5139_3;
+extern cpuop_func op_5140_3;
+extern cpuop_func op_5148_3;
+extern cpuop_func op_5150_3;
+extern cpuop_func op_5158_3;
+extern cpuop_func op_5160_3;
+extern cpuop_func op_5168_3;
+extern cpuop_func op_5170_3;
+extern cpuop_func op_5178_3;
+extern cpuop_func op_5179_3;
+extern cpuop_func op_5180_3;
+extern cpuop_func op_5188_3;
+extern cpuop_func op_5190_3;
+extern cpuop_func op_5198_3;
+extern cpuop_func op_51a0_3;
+extern cpuop_func op_51a8_3;
+extern cpuop_func op_51b0_3;
+extern cpuop_func op_51b8_3;
+extern cpuop_func op_51b9_3;
+extern cpuop_func op_51c0_3;
+extern cpuop_func op_51c8_3;
+extern cpuop_func op_51d0_3;
+extern cpuop_func op_51d8_3;
+extern cpuop_func op_51e0_3;
+extern cpuop_func op_51e8_3;
+extern cpuop_func op_51f0_3;
+extern cpuop_func op_51f8_3;
+extern cpuop_func op_51f9_3;
+extern cpuop_func op_52c0_3;
+extern cpuop_func op_52c8_3;
+extern cpuop_func op_52d0_3;
+extern cpuop_func op_52d8_3;
+extern cpuop_func op_52e0_3;
+extern cpuop_func op_52e8_3;
+extern cpuop_func op_52f0_3;
+extern cpuop_func op_52f8_3;
+extern cpuop_func op_52f9_3;
+extern cpuop_func op_53c0_3;
+extern cpuop_func op_53c8_3;
+extern cpuop_func op_53d0_3;
+extern cpuop_func op_53d8_3;
+extern cpuop_func op_53e0_3;
+extern cpuop_func op_53e8_3;
+extern cpuop_func op_53f0_3;
+extern cpuop_func op_53f8_3;
+extern cpuop_func op_53f9_3;
+extern cpuop_func op_54c0_3;
+extern cpuop_func op_54c8_3;
+extern cpuop_func op_54d0_3;
+extern cpuop_func op_54d8_3;
+extern cpuop_func op_54e0_3;
+extern cpuop_func op_54e8_3;
+extern cpuop_func op_54f0_3;
+extern cpuop_func op_54f8_3;
+extern cpuop_func op_54f9_3;
+extern cpuop_func op_55c0_3;
+extern cpuop_func op_55c8_3;
+extern cpuop_func op_55d0_3;
+extern cpuop_func op_55d8_3;
+extern cpuop_func op_55e0_3;
+extern cpuop_func op_55e8_3;
+extern cpuop_func op_55f0_3;
+extern cpuop_func op_55f8_3;
+extern cpuop_func op_55f9_3;
+extern cpuop_func op_56c0_3;
+extern cpuop_func op_56c8_3;
+extern cpuop_func op_56d0_3;
+extern cpuop_func op_56d8_3;
+extern cpuop_func op_56e0_3;
+extern cpuop_func op_56e8_3;
+extern cpuop_func op_56f0_3;
+extern cpuop_func op_56f8_3;
+extern cpuop_func op_56f9_3;
+extern cpuop_func op_57c0_3;
+extern cpuop_func op_57c8_3;
+extern cpuop_func op_57d0_3;
+extern cpuop_func op_57d8_3;
+extern cpuop_func op_57e0_3;
+extern cpuop_func op_57e8_3;
+extern cpuop_func op_57f0_3;
+extern cpuop_func op_57f8_3;
+extern cpuop_func op_57f9_3;
+extern cpuop_func op_58c0_3;
+extern cpuop_func op_58c8_3;
+extern cpuop_func op_58d0_3;
+extern cpuop_func op_58d8_3;
+extern cpuop_func op_58e0_3;
+extern cpuop_func op_58e8_3;
+extern cpuop_func op_58f0_3;
+extern cpuop_func op_58f8_3;
+extern cpuop_func op_58f9_3;
+extern cpuop_func op_59c0_3;
+extern cpuop_func op_59c8_3;
+extern cpuop_func op_59d0_3;
+extern cpuop_func op_59d8_3;
+extern cpuop_func op_59e0_3;
+extern cpuop_func op_59e8_3;
+extern cpuop_func op_59f0_3;
+extern cpuop_func op_59f8_3;
+extern cpuop_func op_59f9_3;
+extern cpuop_func op_5ac0_3;
+extern cpuop_func op_5ac8_3;
+extern cpuop_func op_5ad0_3;
+extern cpuop_func op_5ad8_3;
+extern cpuop_func op_5ae0_3;
+extern cpuop_func op_5ae8_3;
+extern cpuop_func op_5af0_3;
+extern cpuop_func op_5af8_3;
+extern cpuop_func op_5af9_3;
+extern cpuop_func op_5bc0_3;
+extern cpuop_func op_5bc8_3;
+extern cpuop_func op_5bd0_3;
+extern cpuop_func op_5bd8_3;
+extern cpuop_func op_5be0_3;
+extern cpuop_func op_5be8_3;
+extern cpuop_func op_5bf0_3;
+extern cpuop_func op_5bf8_3;
+extern cpuop_func op_5bf9_3;
+extern cpuop_func op_5cc0_3;
+extern cpuop_func op_5cc8_3;
+extern cpuop_func op_5cd0_3;
+extern cpuop_func op_5cd8_3;
+extern cpuop_func op_5ce0_3;
+extern cpuop_func op_5ce8_3;
+extern cpuop_func op_5cf0_3;
+extern cpuop_func op_5cf8_3;
+extern cpuop_func op_5cf9_3;
+extern cpuop_func op_5dc0_3;
+extern cpuop_func op_5dc8_3;
+extern cpuop_func op_5dd0_3;
+extern cpuop_func op_5dd8_3;
+extern cpuop_func op_5de0_3;
+extern cpuop_func op_5de8_3;
+extern cpuop_func op_5df0_3;
+extern cpuop_func op_5df8_3;
+extern cpuop_func op_5df9_3;
+extern cpuop_func op_5ec0_3;
+extern cpuop_func op_5ec8_3;
+extern cpuop_func op_5ed0_3;
+extern cpuop_func op_5ed8_3;
+extern cpuop_func op_5ee0_3;
+extern cpuop_func op_5ee8_3;
+extern cpuop_func op_5ef0_3;
+extern cpuop_func op_5ef8_3;
+extern cpuop_func op_5ef9_3;
+extern cpuop_func op_5fc0_3;
+extern cpuop_func op_5fc8_3;
+extern cpuop_func op_5fd0_3;
+extern cpuop_func op_5fd8_3;
+extern cpuop_func op_5fe0_3;
+extern cpuop_func op_5fe8_3;
+extern cpuop_func op_5ff0_3;
+extern cpuop_func op_5ff8_3;
+extern cpuop_func op_5ff9_3;
+extern cpuop_func op_6000_3;
+extern cpuop_func op_6001_3;
+extern cpuop_func op_60ff_3;
+extern cpuop_func op_6100_3;
+extern cpuop_func op_6101_3;
+extern cpuop_func op_61ff_3;
+extern cpuop_func op_6200_3;
+extern cpuop_func op_6201_3;
+extern cpuop_func op_62ff_3;
+extern cpuop_func op_6300_3;
+extern cpuop_func op_6301_3;
+extern cpuop_func op_63ff_3;
+extern cpuop_func op_6400_3;
+extern cpuop_func op_6401_3;
+extern cpuop_func op_64ff_3;
+extern cpuop_func op_6500_3;
+extern cpuop_func op_6501_3;
+extern cpuop_func op_65ff_3;
+extern cpuop_func op_6600_3;
+extern cpuop_func op_6601_3;
+extern cpuop_func op_66ff_3;
+extern cpuop_func op_6700_3;
+extern cpuop_func op_6701_3;
+extern cpuop_func op_67ff_3;
+extern cpuop_func op_6800_3;
+extern cpuop_func op_6801_3;
+extern cpuop_func op_68ff_3;
+extern cpuop_func op_6900_3;
+extern cpuop_func op_6901_3;
+extern cpuop_func op_69ff_3;
+extern cpuop_func op_6a00_3;
+extern cpuop_func op_6a01_3;
+extern cpuop_func op_6aff_3;
+extern cpuop_func op_6b00_3;
+extern cpuop_func op_6b01_3;
+extern cpuop_func op_6bff_3;
+extern cpuop_func op_6c00_3;
+extern cpuop_func op_6c01_3;
+extern cpuop_func op_6cff_3;
+extern cpuop_func op_6d00_3;
+extern cpuop_func op_6d01_3;
+extern cpuop_func op_6dff_3;
+extern cpuop_func op_6e00_3;
+extern cpuop_func op_6e01_3;
+extern cpuop_func op_6eff_3;
+extern cpuop_func op_6f00_3;
+extern cpuop_func op_6f01_3;
+extern cpuop_func op_6fff_3;
+extern cpuop_func op_7000_3;
+extern cpuop_func op_8000_3;
+extern cpuop_func op_8010_3;
+extern cpuop_func op_8018_3;
+extern cpuop_func op_8020_3;
+extern cpuop_func op_8028_3;
+extern cpuop_func op_8030_3;
+extern cpuop_func op_8038_3;
+extern cpuop_func op_8039_3;
+extern cpuop_func op_803a_3;
+extern cpuop_func op_803b_3;
+extern cpuop_func op_803c_3;
+extern cpuop_func op_8040_3;
+extern cpuop_func op_8050_3;
+extern cpuop_func op_8058_3;
+extern cpuop_func op_8060_3;
+extern cpuop_func op_8068_3;
+extern cpuop_func op_8070_3;
+extern cpuop_func op_8078_3;
+extern cpuop_func op_8079_3;
+extern cpuop_func op_807a_3;
+extern cpuop_func op_807b_3;
+extern cpuop_func op_807c_3;
+extern cpuop_func op_8080_3;
+extern cpuop_func op_8090_3;
+extern cpuop_func op_8098_3;
+extern cpuop_func op_80a0_3;
+extern cpuop_func op_80a8_3;
+extern cpuop_func op_80b0_3;
+extern cpuop_func op_80b8_3;
+extern cpuop_func op_80b9_3;
+extern cpuop_func op_80ba_3;
+extern cpuop_func op_80bb_3;
+extern cpuop_func op_80bc_3;
+extern cpuop_func op_80c0_3;
+extern cpuop_func op_80d0_3;
+extern cpuop_func op_80d8_3;
+extern cpuop_func op_80e0_3;
+extern cpuop_func op_80e8_3;
+extern cpuop_func op_80f0_3;
+extern cpuop_func op_80f8_3;
+extern cpuop_func op_80f9_3;
+extern cpuop_func op_80fa_3;
+extern cpuop_func op_80fb_3;
+extern cpuop_func op_80fc_3;
+extern cpuop_func op_8100_3;
+extern cpuop_func op_8108_3;
+extern cpuop_func op_8110_3;
+extern cpuop_func op_8118_3;
+extern cpuop_func op_8120_3;
+extern cpuop_func op_8128_3;
+extern cpuop_func op_8130_3;
+extern cpuop_func op_8138_3;
+extern cpuop_func op_8139_3;
+extern cpuop_func op_8150_3;
+extern cpuop_func op_8158_3;
+extern cpuop_func op_8160_3;
+extern cpuop_func op_8168_3;
+extern cpuop_func op_8170_3;
+extern cpuop_func op_8178_3;
+extern cpuop_func op_8179_3;
+extern cpuop_func op_8190_3;
+extern cpuop_func op_8198_3;
+extern cpuop_func op_81a0_3;
+extern cpuop_func op_81a8_3;
+extern cpuop_func op_81b0_3;
+extern cpuop_func op_81b8_3;
+extern cpuop_func op_81b9_3;
+extern cpuop_func op_81c0_3;
+extern cpuop_func op_81d0_3;
+extern cpuop_func op_81d8_3;
+extern cpuop_func op_81e0_3;
+extern cpuop_func op_81e8_3;
+extern cpuop_func op_81f0_3;
+extern cpuop_func op_81f8_3;
+extern cpuop_func op_81f9_3;
+extern cpuop_func op_81fa_3;
+extern cpuop_func op_81fb_3;
+extern cpuop_func op_81fc_3;
+extern cpuop_func op_9000_3;
+extern cpuop_func op_9010_3;
+extern cpuop_func op_9018_3;
+extern cpuop_func op_9020_3;
+extern cpuop_func op_9028_3;
+extern cpuop_func op_9030_3;
+extern cpuop_func op_9038_3;
+extern cpuop_func op_9039_3;
+extern cpuop_func op_903a_3;
+extern cpuop_func op_903b_3;
+extern cpuop_func op_903c_3;
+extern cpuop_func op_9040_3;
+extern cpuop_func op_9048_3;
+extern cpuop_func op_9050_3;
+extern cpuop_func op_9058_3;
+extern cpuop_func op_9060_3;
+extern cpuop_func op_9068_3;
+extern cpuop_func op_9070_3;
+extern cpuop_func op_9078_3;
+extern cpuop_func op_9079_3;
+extern cpuop_func op_907a_3;
+extern cpuop_func op_907b_3;
+extern cpuop_func op_907c_3;
+extern cpuop_func op_9080_3;
+extern cpuop_func op_9088_3;
+extern cpuop_func op_9090_3;
+extern cpuop_func op_9098_3;
+extern cpuop_func op_90a0_3;
+extern cpuop_func op_90a8_3;
+extern cpuop_func op_90b0_3;
+extern cpuop_func op_90b8_3;
+extern cpuop_func op_90b9_3;
+extern cpuop_func op_90ba_3;
+extern cpuop_func op_90bb_3;
+extern cpuop_func op_90bc_3;
+extern cpuop_func op_90c0_3;
+extern cpuop_func op_90c8_3;
+extern cpuop_func op_90d0_3;
+extern cpuop_func op_90d8_3;
+extern cpuop_func op_90e0_3;
+extern cpuop_func op_90e8_3;
+extern cpuop_func op_90f0_3;
+extern cpuop_func op_90f8_3;
+extern cpuop_func op_90f9_3;
+extern cpuop_func op_90fa_3;
+extern cpuop_func op_90fb_3;
+extern cpuop_func op_90fc_3;
+extern cpuop_func op_9100_3;
+extern cpuop_func op_9108_3;
+extern cpuop_func op_9110_3;
+extern cpuop_func op_9118_3;
+extern cpuop_func op_9120_3;
+extern cpuop_func op_9128_3;
+extern cpuop_func op_9130_3;
+extern cpuop_func op_9138_3;
+extern cpuop_func op_9139_3;
+extern cpuop_func op_9140_3;
+extern cpuop_func op_9148_3;
+extern cpuop_func op_9150_3;
+extern cpuop_func op_9158_3;
+extern cpuop_func op_9160_3;
+extern cpuop_func op_9168_3;
+extern cpuop_func op_9170_3;
+extern cpuop_func op_9178_3;
+extern cpuop_func op_9179_3;
+extern cpuop_func op_9180_3;
+extern cpuop_func op_9188_3;
+extern cpuop_func op_9190_3;
+extern cpuop_func op_9198_3;
+extern cpuop_func op_91a0_3;
+extern cpuop_func op_91a8_3;
+extern cpuop_func op_91b0_3;
+extern cpuop_func op_91b8_3;
+extern cpuop_func op_91b9_3;
+extern cpuop_func op_91c0_3;
+extern cpuop_func op_91c8_3;
+extern cpuop_func op_91d0_3;
+extern cpuop_func op_91d8_3;
+extern cpuop_func op_91e0_3;
+extern cpuop_func op_91e8_3;
+extern cpuop_func op_91f0_3;
+extern cpuop_func op_91f8_3;
+extern cpuop_func op_91f9_3;
+extern cpuop_func op_91fa_3;
+extern cpuop_func op_91fb_3;
+extern cpuop_func op_91fc_3;
+extern cpuop_func op_b000_3;
+extern cpuop_func op_b010_3;
+extern cpuop_func op_b018_3;
+extern cpuop_func op_b020_3;
+extern cpuop_func op_b028_3;
+extern cpuop_func op_b030_3;
+extern cpuop_func op_b038_3;
+extern cpuop_func op_b039_3;
+extern cpuop_func op_b03a_3;
+extern cpuop_func op_b03b_3;
+extern cpuop_func op_b03c_3;
+extern cpuop_func op_b040_3;
+extern cpuop_func op_b048_3;
+extern cpuop_func op_b050_3;
+extern cpuop_func op_b058_3;
+extern cpuop_func op_b060_3;
+extern cpuop_func op_b068_3;
+extern cpuop_func op_b070_3;
+extern cpuop_func op_b078_3;
+extern cpuop_func op_b079_3;
+extern cpuop_func op_b07a_3;
+extern cpuop_func op_b07b_3;
+extern cpuop_func op_b07c_3;
+extern cpuop_func op_b080_3;
+extern cpuop_func op_b088_3;
+extern cpuop_func op_b090_3;
+extern cpuop_func op_b098_3;
+extern cpuop_func op_b0a0_3;
+extern cpuop_func op_b0a8_3;
+extern cpuop_func op_b0b0_3;
+extern cpuop_func op_b0b8_3;
+extern cpuop_func op_b0b9_3;
+extern cpuop_func op_b0ba_3;
+extern cpuop_func op_b0bb_3;
+extern cpuop_func op_b0bc_3;
+extern cpuop_func op_b0c0_3;
+extern cpuop_func op_b0c8_3;
+extern cpuop_func op_b0d0_3;
+extern cpuop_func op_b0d8_3;
+extern cpuop_func op_b0e0_3;
+extern cpuop_func op_b0e8_3;
+extern cpuop_func op_b0f0_3;
+extern cpuop_func op_b0f8_3;
+extern cpuop_func op_b0f9_3;
+extern cpuop_func op_b0fa_3;
+extern cpuop_func op_b0fb_3;
+extern cpuop_func op_b0fc_3;
+extern cpuop_func op_b100_3;
+extern cpuop_func op_b108_3;
+extern cpuop_func op_b110_3;
+extern cpuop_func op_b118_3;
+extern cpuop_func op_b120_3;
+extern cpuop_func op_b128_3;
+extern cpuop_func op_b130_3;
+extern cpuop_func op_b138_3;
+extern cpuop_func op_b139_3;
+extern cpuop_func op_b140_3;
+extern cpuop_func op_b148_3;
+extern cpuop_func op_b150_3;
+extern cpuop_func op_b158_3;
+extern cpuop_func op_b160_3;
+extern cpuop_func op_b168_3;
+extern cpuop_func op_b170_3;
+extern cpuop_func op_b178_3;
+extern cpuop_func op_b179_3;
+extern cpuop_func op_b180_3;
+extern cpuop_func op_b188_3;
+extern cpuop_func op_b190_3;
+extern cpuop_func op_b198_3;
+extern cpuop_func op_b1a0_3;
+extern cpuop_func op_b1a8_3;
+extern cpuop_func op_b1b0_3;
+extern cpuop_func op_b1b8_3;
+extern cpuop_func op_b1b9_3;
+extern cpuop_func op_b1c0_3;
+extern cpuop_func op_b1c8_3;
+extern cpuop_func op_b1d0_3;
+extern cpuop_func op_b1d8_3;
+extern cpuop_func op_b1e0_3;
+extern cpuop_func op_b1e8_3;
+extern cpuop_func op_b1f0_3;
+extern cpuop_func op_b1f8_3;
+extern cpuop_func op_b1f9_3;
+extern cpuop_func op_b1fa_3;
+extern cpuop_func op_b1fb_3;
+extern cpuop_func op_b1fc_3;
+extern cpuop_func op_c000_3;
+extern cpuop_func op_c010_3;
+extern cpuop_func op_c018_3;
+extern cpuop_func op_c020_3;
+extern cpuop_func op_c028_3;
+extern cpuop_func op_c030_3;
+extern cpuop_func op_c038_3;
+extern cpuop_func op_c039_3;
+extern cpuop_func op_c03a_3;
+extern cpuop_func op_c03b_3;
+extern cpuop_func op_c03c_3;
+extern cpuop_func op_c040_3;
+extern cpuop_func op_c050_3;
+extern cpuop_func op_c058_3;
+extern cpuop_func op_c060_3;
+extern cpuop_func op_c068_3;
+extern cpuop_func op_c070_3;
+extern cpuop_func op_c078_3;
+extern cpuop_func op_c079_3;
+extern cpuop_func op_c07a_3;
+extern cpuop_func op_c07b_3;
+extern cpuop_func op_c07c_3;
+extern cpuop_func op_c080_3;
+extern cpuop_func op_c090_3;
+extern cpuop_func op_c098_3;
+extern cpuop_func op_c0a0_3;
+extern cpuop_func op_c0a8_3;
+extern cpuop_func op_c0b0_3;
+extern cpuop_func op_c0b8_3;
+extern cpuop_func op_c0b9_3;
+extern cpuop_func op_c0ba_3;
+extern cpuop_func op_c0bb_3;
+extern cpuop_func op_c0bc_3;
+extern cpuop_func op_c0c0_3;
+extern cpuop_func op_c0d0_3;
+extern cpuop_func op_c0d8_3;
+extern cpuop_func op_c0e0_3;
+extern cpuop_func op_c0e8_3;
+extern cpuop_func op_c0f0_3;
+extern cpuop_func op_c0f8_3;
+extern cpuop_func op_c0f9_3;
+extern cpuop_func op_c0fa_3;
+extern cpuop_func op_c0fb_3;
+extern cpuop_func op_c0fc_3;
+extern cpuop_func op_c100_3;
+extern cpuop_func op_c108_3;
+extern cpuop_func op_c110_3;
+extern cpuop_func op_c118_3;
+extern cpuop_func op_c120_3;
+extern cpuop_func op_c128_3;
+extern cpuop_func op_c130_3;
+extern cpuop_func op_c138_3;
+extern cpuop_func op_c139_3;
+extern cpuop_func op_c140_3;
+extern cpuop_func op_c148_3;
+extern cpuop_func op_c150_3;
+extern cpuop_func op_c158_3;
+extern cpuop_func op_c160_3;
+extern cpuop_func op_c168_3;
+extern cpuop_func op_c170_3;
+extern cpuop_func op_c178_3;
+extern cpuop_func op_c179_3;
+extern cpuop_func op_c188_3;
+extern cpuop_func op_c190_3;
+extern cpuop_func op_c198_3;
+extern cpuop_func op_c1a0_3;
+extern cpuop_func op_c1a8_3;
+extern cpuop_func op_c1b0_3;
+extern cpuop_func op_c1b8_3;
+extern cpuop_func op_c1b9_3;
+extern cpuop_func op_c1c0_3;
+extern cpuop_func op_c1d0_3;
+extern cpuop_func op_c1d8_3;
+extern cpuop_func op_c1e0_3;
+extern cpuop_func op_c1e8_3;
+extern cpuop_func op_c1f0_3;
+extern cpuop_func op_c1f8_3;
+extern cpuop_func op_c1f9_3;
+extern cpuop_func op_c1fa_3;
+extern cpuop_func op_c1fb_3;
+extern cpuop_func op_c1fc_3;
+extern cpuop_func op_d000_3;
+extern cpuop_func op_d010_3;
+extern cpuop_func op_d018_3;
+extern cpuop_func op_d020_3;
+extern cpuop_func op_d028_3;
+extern cpuop_func op_d030_3;
+extern cpuop_func op_d038_3;
+extern cpuop_func op_d039_3;
+extern cpuop_func op_d03a_3;
+extern cpuop_func op_d03b_3;
+extern cpuop_func op_d03c_3;
+extern cpuop_func op_d040_3;
+extern cpuop_func op_d048_3;
+extern cpuop_func op_d050_3;
+extern cpuop_func op_d058_3;
+extern cpuop_func op_d060_3;
+extern cpuop_func op_d068_3;
+extern cpuop_func op_d070_3;
+extern cpuop_func op_d078_3;
+extern cpuop_func op_d079_3;
+extern cpuop_func op_d07a_3;
+extern cpuop_func op_d07b_3;
+extern cpuop_func op_d07c_3;
+extern cpuop_func op_d080_3;
+extern cpuop_func op_d088_3;
+extern cpuop_func op_d090_3;
+extern cpuop_func op_d098_3;
+extern cpuop_func op_d0a0_3;
+extern cpuop_func op_d0a8_3;
+extern cpuop_func op_d0b0_3;
+extern cpuop_func op_d0b8_3;
+extern cpuop_func op_d0b9_3;
+extern cpuop_func op_d0ba_3;
+extern cpuop_func op_d0bb_3;
+extern cpuop_func op_d0bc_3;
+extern cpuop_func op_d0c0_3;
+extern cpuop_func op_d0c8_3;
+extern cpuop_func op_d0d0_3;
+extern cpuop_func op_d0d8_3;
+extern cpuop_func op_d0e0_3;
+extern cpuop_func op_d0e8_3;
+extern cpuop_func op_d0f0_3;
+extern cpuop_func op_d0f8_3;
+extern cpuop_func op_d0f9_3;
+extern cpuop_func op_d0fa_3;
+extern cpuop_func op_d0fb_3;
+extern cpuop_func op_d0fc_3;
+extern cpuop_func op_d100_3;
+extern cpuop_func op_d108_3;
+extern cpuop_func op_d110_3;
+extern cpuop_func op_d118_3;
+extern cpuop_func op_d120_3;
+extern cpuop_func op_d128_3;
+extern cpuop_func op_d130_3;
+extern cpuop_func op_d138_3;
+extern cpuop_func op_d139_3;
+extern cpuop_func op_d140_3;
+extern cpuop_func op_d148_3;
+extern cpuop_func op_d150_3;
+extern cpuop_func op_d158_3;
+extern cpuop_func op_d160_3;
+extern cpuop_func op_d168_3;
+extern cpuop_func op_d170_3;
+extern cpuop_func op_d178_3;
+extern cpuop_func op_d179_3;
+extern cpuop_func op_d180_3;
+extern cpuop_func op_d188_3;
+extern cpuop_func op_d190_3;
+extern cpuop_func op_d198_3;
+extern cpuop_func op_d1a0_3;
+extern cpuop_func op_d1a8_3;
+extern cpuop_func op_d1b0_3;
+extern cpuop_func op_d1b8_3;
+extern cpuop_func op_d1b9_3;
+extern cpuop_func op_d1c0_3;
+extern cpuop_func op_d1c8_3;
+extern cpuop_func op_d1d0_3;
+extern cpuop_func op_d1d8_3;
+extern cpuop_func op_d1e0_3;
+extern cpuop_func op_d1e8_3;
+extern cpuop_func op_d1f0_3;
+extern cpuop_func op_d1f8_3;
+extern cpuop_func op_d1f9_3;
+extern cpuop_func op_d1fa_3;
+extern cpuop_func op_d1fb_3;
+extern cpuop_func op_d1fc_3;
+extern cpuop_func op_e000_3;
+extern cpuop_func op_e008_3;
+extern cpuop_func op_e010_3;
+extern cpuop_func op_e018_3;
+extern cpuop_func op_e020_3;
+extern cpuop_func op_e028_3;
+extern cpuop_func op_e030_3;
+extern cpuop_func op_e038_3;
+extern cpuop_func op_e040_3;
+extern cpuop_func op_e048_3;
+extern cpuop_func op_e050_3;
+extern cpuop_func op_e058_3;
+extern cpuop_func op_e060_3;
+extern cpuop_func op_e068_3;
+extern cpuop_func op_e070_3;
+extern cpuop_func op_e078_3;
+extern cpuop_func op_e080_3;
+extern cpuop_func op_e088_3;
+extern cpuop_func op_e090_3;
+extern cpuop_func op_e098_3;
+extern cpuop_func op_e0a0_3;
+extern cpuop_func op_e0a8_3;
+extern cpuop_func op_e0b0_3;
+extern cpuop_func op_e0b8_3;
+extern cpuop_func op_e0d0_3;
+extern cpuop_func op_e0d8_3;
+extern cpuop_func op_e0e0_3;
+extern cpuop_func op_e0e8_3;
+extern cpuop_func op_e0f0_3;
+extern cpuop_func op_e0f8_3;
+extern cpuop_func op_e0f9_3;
+extern cpuop_func op_e100_3;
+extern cpuop_func op_e108_3;
+extern cpuop_func op_e110_3;
+extern cpuop_func op_e118_3;
+extern cpuop_func op_e120_3;
+extern cpuop_func op_e128_3;
+extern cpuop_func op_e130_3;
+extern cpuop_func op_e138_3;
+extern cpuop_func op_e140_3;
+extern cpuop_func op_e148_3;
+extern cpuop_func op_e150_3;
+extern cpuop_func op_e158_3;
+extern cpuop_func op_e160_3;
+extern cpuop_func op_e168_3;
+extern cpuop_func op_e170_3;
+extern cpuop_func op_e178_3;
+extern cpuop_func op_e180_3;
+extern cpuop_func op_e188_3;
+extern cpuop_func op_e190_3;
+extern cpuop_func op_e198_3;
+extern cpuop_func op_e1a0_3;
+extern cpuop_func op_e1a8_3;
+extern cpuop_func op_e1b0_3;
+extern cpuop_func op_e1b8_3;
+extern cpuop_func op_e1d0_3;
+extern cpuop_func op_e1d8_3;
+extern cpuop_func op_e1e0_3;
+extern cpuop_func op_e1e8_3;
+extern cpuop_func op_e1f0_3;
+extern cpuop_func op_e1f8_3;
+extern cpuop_func op_e1f9_3;
+extern cpuop_func op_e2d0_3;
+extern cpuop_func op_e2d8_3;
+extern cpuop_func op_e2e0_3;
+extern cpuop_func op_e2e8_3;
+extern cpuop_func op_e2f0_3;
+extern cpuop_func op_e2f8_3;
+extern cpuop_func op_e2f9_3;
+extern cpuop_func op_e3d0_3;
+extern cpuop_func op_e3d8_3;
+extern cpuop_func op_e3e0_3;
+extern cpuop_func op_e3e8_3;
+extern cpuop_func op_e3f0_3;
+extern cpuop_func op_e3f8_3;
+extern cpuop_func op_e3f9_3;
+extern cpuop_func op_e4d0_3;
+extern cpuop_func op_e4d8_3;
+extern cpuop_func op_e4e0_3;
+extern cpuop_func op_e4e8_3;
+extern cpuop_func op_e4f0_3;
+extern cpuop_func op_e4f8_3;
+extern cpuop_func op_e4f9_3;
+extern cpuop_func op_e5d0_3;
+extern cpuop_func op_e5d8_3;
+extern cpuop_func op_e5e0_3;
+extern cpuop_func op_e5e8_3;
+extern cpuop_func op_e5f0_3;
+extern cpuop_func op_e5f8_3;
+extern cpuop_func op_e5f9_3;
+extern cpuop_func op_e6d0_3;
+extern cpuop_func op_e6d8_3;
+extern cpuop_func op_e6e0_3;
+extern cpuop_func op_e6e8_3;
+extern cpuop_func op_e6f0_3;
+extern cpuop_func op_e6f8_3;
+extern cpuop_func op_e6f9_3;
+extern cpuop_func op_e7d0_3;
+extern cpuop_func op_e7d8_3;
+extern cpuop_func op_e7e0_3;
+extern cpuop_func op_e7e8_3;
+extern cpuop_func op_e7f0_3;
+extern cpuop_func op_e7f8_3;
+extern cpuop_func op_e7f9_3;
diff --git a/SrcShared/UAE/custom.h b/SrcShared/UAE/custom.h
new file mode 100644
index 0000000..7b5241b
--- /dev/null
+++ b/SrcShared/UAE/custom.h
@@ -0,0 +1,30 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * custom chip support
+ *
+ * (c) 1995 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void customreset (void);
+
+#define SPCFLAG_STOP 2
+#define SPCFLAG_DISK 4
+#define SPCFLAG_INT 8
+#define SPCFLAG_BRK 16
+#define SPCFLAG_EXTRA_CYCLES 32
+#define SPCFLAG_TRACE 64
+#define SPCFLAG_DOTRACE 128
+#define SPCFLAG_DOINT 256
+#define SPCFLAG_BLTNASTY 512
+#define SPCFLAG_EXEC 1024
+#define SPCFLAG_MODE_CHANGE 8192
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/SrcShared/UAE/gencpu.c b/SrcShared/UAE/gencpu.c
new file mode 100644
index 0000000..b7004a4
--- /dev/null
+++ b/SrcShared/UAE/gencpu.c
@@ -0,0 +1,3346 @@
+/*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * MC68000 emulation generator
+ *
+ * This is a fairly stupid program that generates a lot of case labels that
+ * can be #included in a switch statement.
+ * As an alternative, it can generate functions that handle specific
+ * MC68000 instructions, plus a prototype header file and a function pointer
+ * array to look up the function for an opcode.
+ * Error checking is bad, an illegal table68k file will cause the program to
+ * call abort().
+ * The generated code is sometimes sub-optimal, an optimizing compiler should
+ * take care of this.
+ *
+ * Copyright 1995, 1996 Bernd Schmidt
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include <ctype.h>
+
+#include "config.h"
+#include "options.h"
+#include "readcpu.h"
+
+#define BOOL_TYPE "int"
+
+static FILE *headerfile;
+static FILE *stblfile;
+
+static int using_prefetch;
+static int using_exception_3;
+static int cpu_level;
+
+#define PALM_PERF 1 // Changes made to profile Palm applications
+#define PALM_STACK 1 // Changes made to track stack overflows
+#define PALM_MIN 1 // Changes made to minimize size of cpuemu.c
+#define PALM_CODEGEN_BUG 1 // Changes made to workaround code generation bugs
+#define PALM_HEADERS 1 // Changes made to accounts for Poser's header structures
+#define PALM_BUG_FIX 1 // Changes made to fix UAE bugs.
+#define PALM_SYSTEM_CALL 1 // Changes made to track system calls
+
+#if PALM_STACK
+int adda_hack = 0;
+int suba_hack = 0;
+int lea_hack = 0;
+#endif // PALM_STACK
+
+#if PALM_PERF
+static int extraCycles; // number of clock cycles to do reads+writes+op
+static int readCycles; // number of read cycles to do something
+static int writeCycles; // number of write cycles to do something
+
+static int *opcode_last_extra;
+static int *opcode_last_read;
+static int *opcode_last_write;
+
+//#define PERF_COMMENT(x) printf("\t// perf" x)
+#define PERF_COMMENT(x) ((void*)0)
+#endif // PALM_PERF
+
+/* For the current opcode, the next lower level that will have different code.
+ * Initialized to -1 for each opcode. If it remains unchanged, indicates we
+ * are done with that opcode. */
+static int next_cpu_level;
+
+void write_log (const char *s, ...)
+{
+ fprintf (stderr, "%s", s);
+}
+
+static int *opcode_map;
+static int *opcode_next_clev;
+static int *opcode_last_postfix;
+static unsigned long *counts;
+
+static void read_counts (void)
+{
+ FILE *file;
+ unsigned long opcode, count, total;
+ char name[20];
+ int nr = 0;
+ memset (counts, 0, 65536 * sizeof *counts);
+
+ file = fopen ("frequent.68k", "r");
+ if (file) {
+ fscanf (file, "Total: %lu\n", &total);
+ while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
+ opcode_next_clev[nr] = 3;
+ opcode_last_postfix[nr] = -1;
+ opcode_map[nr++] = opcode;
+ counts[opcode] = count;
+ }
+ fclose (file);
+ }
+ if (nr == nr_cpuop_funcs)
+ return;
+ for (opcode = 0; opcode < 0x10000; opcode++) {
+ if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
+ && counts[opcode] == 0)
+ {
+ opcode_next_clev[nr] = 3;
+ opcode_last_postfix[nr] = -1;
+ opcode_map[nr++] = opcode;
+ counts[opcode] = count;
+ }
+ }
+ if (nr != nr_cpuop_funcs)
+ abort ();
+}
+
+static char endlabelstr[80];
+static int endlabelno = 0;
+static int need_endlabel;
+
+static int n_braces = 0;
+static int m68k_pc_offset = 0;
+static int insn_n_cycles;
+
+static void start_brace (void)
+{
+ n_braces++;
+ printf ("{");
+}
+
+static void close_brace (void)
+{
+ assert (n_braces > 0);
+ n_braces--;
+ printf ("}");
+}
+
+static void finish_braces (void)
+{
+ while (n_braces > 0)
+ close_brace ();
+}
+
+static void pop_braces (int to)
+{
+ while (n_braces > to)
+ close_brace ();
+}
+
+static int bit_size (int size)
+{
+ switch (size) {
+ case sz_byte: return 8;
+ case sz_word: return 16;
+ case sz_long: return 32;
+ default: abort ();
+ }
+ return 0;
+}
+
+static const char *bit_mask (int size)
+{
+ switch (size) {
+ case sz_byte: return "0xff";
+ case sz_word: return "0xffff";
+ case sz_long: return "0xffffffff";
+ default: abort ();
+ }
+ return 0;
+}
+
+static const char *gen_nextilong (void)
+{
+ static char buffer[80];
+ int r = m68k_pc_offset;
+ m68k_pc_offset += 4;
+
+ insn_n_cycles += 4;
+
+ if (using_prefetch)
+ sprintf (buffer, "get_ilong_prefetch(%d)", r);
+ else
+ sprintf (buffer, "get_ilong(%d)", r);
+ return buffer;
+}
+
+static const char *gen_nextiword (void)
+{
+ static char buffer[80];
+ int r = m68k_pc_offset;
+ m68k_pc_offset += 2;
+
+ insn_n_cycles += 2;
+
+ if (using_prefetch)
+ sprintf (buffer, "get_iword_prefetch(%d)", r);
+ else
+ sprintf (buffer, "get_iword(%d)", r);
+ return buffer;
+}
+
+static const char *gen_nextibyte (void)
+{
+ static char buffer[80];
+ int r = m68k_pc_offset;
+ m68k_pc_offset += 2;
+
+ insn_n_cycles += 2;
+
+ if (using_prefetch)
+ sprintf (buffer, "get_ibyte_prefetch(%d)", r);
+ else
+ sprintf (buffer, "get_ibyte(%d)", r);
+ return buffer;
+}
+
+static void fill_prefetch_0 (void)
+{
+ if (using_prefetch)
+ printf ("fill_prefetch_0 ();\n");
+}
+
+static void fill_prefetch_2 (void)
+{
+ if (using_prefetch)
+ printf ("fill_prefetch_2 ();\n");
+}
+
+static void sync_m68k_pc (void)
+{
+ if (m68k_pc_offset == 0)
+ return;
+ printf ("m68k_incpc(%d);\n", m68k_pc_offset);
+ switch (m68k_pc_offset) {
+ case 0:
+ /*fprintf (stderr, "refilling prefetch at 0\n"); */
+ break;
+ case 2:
+ fill_prefetch_2 ();
+ break;
+ default:
+ fill_prefetch_0 ();
+ break;
+ }
+ m68k_pc_offset = 0;
+}
+
+/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
+ * the calling routine handles Apdi and Aipi modes. */
+static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem)
+{
+ start_brace ();
+ switch (mode) {
+ case Dreg:
+ if (movem)
+ abort ();
+ if (getv == 1)
+#if PALM_PERF
+ {
+#endif // PALM_PERF
+ switch (size) {
+ case sz_byte:
+#if defined(AMIGA) && !defined(WARPUP)
+ /* sam: I don't know why gcc.2.7.2.1 produces a code worse */
+ /* if it is not done like that: */
+ printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg);
+#else
+ printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg);
+#endif
+ break;
+ case sz_word:
+#if defined(AMIGA) && !defined(WARPUP)
+ printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg);
+#else
+ printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg);
+#endif
+ break;
+ case sz_long:
+ printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg);
+ break;
+ default:
+ abort ();
+ }
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 0; PERF_COMMENT("read: Dn 0(0/0)\n");}
+ }
+#endif // PALM_PERF
+ return;
+ case Areg:
+ if (movem)
+ abort ();
+ if (getv == 1)
+#if PALM_PERF
+ {
+#endif // PALM_PERF
+ switch (size) {
+ case sz_word:
+ printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
+ break;
+ case sz_long:
+ printf ("\tuae_s32 %s = m68k_areg(regs, %s);\n", name, reg);
+ break;
+ default:
+ abort ();
+ }
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 0; PERF_COMMENT("read: An 0(0/0)\n");}
+ }
+#endif // PALM_PERF
+ return;
+ case Aind:
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
+ break;
+ case Aipi:
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
+ break;
+ case Apdi:
+#if PALM_PERF
+ if (getv) {extraCycles += 2; readCycles += 0; PERF_COMMENT("read: -(An) x 6(1/0)\n");}
+#endif // PALM_PERF
+ switch (size) {
+ case sz_byte:
+ if (movem)
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
+ else
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
+ break;
+ case sz_word:
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
+ break;
+ case sz_long:
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case Ad16:
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("eff addr: (d16, An) 4(1/0)\n");}
+#endif // PALM_PERF
+ printf ("\tuaecptr %sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword ());
+ break;
+ case Ad8r:
+ if (cpu_level > 1) {
+ if (next_cpu_level < 1)
+ next_cpu_level = 1;
+ sync_m68k_pc ();
+ start_brace ();
+ printf ("\tuaecptr %sa = get_disp_ea_020(m68k_areg(regs, %s), next_iword());\n", name, reg);
+ } else
+#if PALM_PERF
+ {
+#endif // PALM_PERF
+ printf ("\tuaecptr %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ());
+
+#if PALM_PERF
+ {extraCycles += 2; readCycles += 1; PERF_COMMENT("eff addr: (d8, An, Xn) 6(1/0)\n");}
+ }
+#endif // PALM_PERF
+ break;
+ case PC16:
+ printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
+ printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("eff addr: (d16, PC) 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case PC8r:
+ if (cpu_level > 1) {
+ if (next_cpu_level < 1)
+ next_cpu_level = 1;
+ sync_m68k_pc ();
+ start_brace ();
+ printf ("\tuaecptr tmppc = m68k_getpc();\n");
+ printf ("\tuaecptr %sa = get_disp_ea_020(tmppc, next_iword());\n", name);
+ } else {
+ printf ("\tuaecptr tmppc = m68k_getpc() + %d;\n", m68k_pc_offset);
+ printf ("\tuaecptr %sa = get_disp_ea_000(tmppc, %s);\n", name, gen_nextiword ());
+#if PALM_PERF
+ {extraCycles += 2; readCycles += 1; PERF_COMMENT("eff addr: (d8, PC, Xn) B 6(1/0)\n");}
+#endif // PALM_PERF
+ }
+
+ break;
+ case absw:
+ printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT(" eff addr: (xxx).W 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case absl:
+ printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 2; PERF_COMMENT(" eff addr: (xxx).L 8(2/0)\n");}
+#endif // PALM_PERF
+ break;
+ case imm:
+ if (getv != 1)
+ abort ();
+ switch (size) {
+ case sz_byte:
+ printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: #<data> B 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case sz_word:
+ printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: #<data> W 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case sz_long:
+ printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 2; PERF_COMMENT("read: #<data> L 8(2/0)\n");}
+#endif // PALM_PERF
+ break;
+ default:
+ abort ();
+ }
+ return;
+ case imm0:
+ if (getv != 1)
+ abort ();
+ printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: imm0 #<data> B 4(1/0)\n");}
+#endif // PALM_PERF
+ return;
+ case imm1:
+ if (getv != 1)
+ abort ();
+ printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: imm1 #<data> W 4(1/0)\n");}
+#endif // PALM_PERF
+ return;
+ case imm2:
+ if (getv != 1)
+ abort ();
+ printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 2; PERF_COMMENT("read: imm2 #<data> L 8(2/0)\n");}
+#endif // PALM_PERF
+ return;
+ case immi:
+ if (getv != 1)
+ abort ();
+ printf ("\tuae_u32 %s = %s;\n", name, reg);
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 0; PERF_COMMENT("read: immi #<data> L 0(0/0)\n");}
+#endif // PALM_PERF
+ return;
+ default:
+ abort ();
+ }
+
+ /* We get here for all non-reg non-immediate addressing modes to
+ * actually fetch the value. */
+
+ if (using_exception_3 && getv != 0 && size != sz_byte) {
+ printf ("\tif ((%sa & 1) != 0) {\n", name);
+ printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name);
+ printf ("\t\tlast_op_for_exception_3 = opcode;\n");
+ printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n", m68k_pc_offset);
+ printf ("\t\tException(3, 0);\n");
+ printf ("\t\tgoto %s;\n", endlabelstr);
+ printf ("\t}\n");
+ need_endlabel = 1;
+ start_brace ();
+ }
+
+ if (getv == 1) {
+#if PALM_PERF
+ switch(size)
+ {
+ case sz_byte:
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: ??? B 4(1/0)\n");}
+ break;
+ case sz_word:
+ {extraCycles += 0; readCycles += 1; PERF_COMMENT("read: ??? W 4(1/0)\n");}
+ break;
+ case sz_long:
+ {extraCycles += 0; readCycles += 2; PERF_COMMENT("read: ??? L 8(2/0)\n");}
+ break;
+ default:
+ abort();
+ }
+#endif // PALM_PERF
+ switch (size) {
+ case sz_byte: insn_n_cycles += 2; break;
+ case sz_word: insn_n_cycles += 2; break;
+ case sz_long: insn_n_cycles += 4; break;
+ default: abort ();
+ }
+ start_brace ();
+ switch (size) {
+ case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break;
+ case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break;
+ case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break;
+ default: abort ();
+ }
+ }
+
+ /* We now might have to fix up the register for pre-dec or post-inc
+ * addressing modes. */
+ if (!movem)
+ switch (mode) {
+ case Aipi:
+ switch (size) {
+ case sz_byte:
+ printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
+ break;
+ case sz_word:
+ printf ("\tm68k_areg(regs, %s) += 2;\n", reg);
+ break;
+ case sz_long:
+ printf ("\tm68k_areg(regs, %s) += 4;\n", reg);
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case Apdi:
+ printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
+#if PALM_STACK
+ printf ("\tif (%s == 7) CHECK_STACK_POINTER_DECREMENT ();\n",
+ reg, name, name);
+#endif // PALM_STACK
+ break;
+ default:
+ break;
+ }
+}
+
+static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to)
+{
+ switch (mode) {
+ case Dreg:
+ switch (size) {
+ case sz_byte:
+ printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
+ break;
+ case sz_word:
+ printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
+ break;
+ case sz_long:
+ printf ("\tm68k_dreg(regs, %s) = (%s);\n", reg, from);
+ break;
+ default:
+ abort ();
+ }
+#if PALM_PERF
+ extraCycles += 0; writeCycles += 0; PERF_COMMENT("write: Dn 0(0/0)\n");
+#endif // PALM_PERF
+ break;
+ case Areg:
+ switch (size) {
+ case sz_word:
+ fprintf (stderr, "Foo\n");
+ printf ("\tm68k_areg(regs, %s) = (uae_s32)(uae_s16)(%s);\n", reg, from);
+ break;
+ case sz_long:
+#if PALM_STACK
+ if (lea_hack)
+ {
+ start_brace ();
+ printf ("\tuaecptr prev_%s = m68k_areg(regs, %s);\n", reg, reg);
+ }
+#endif // PALM_STACK
+ printf ("\tm68k_areg(regs, %s) = (%s);\n", reg, from);
+#if PALM_STACK
+ if (adda_hack)
+ printf ("\tif (%s == 7) CHECK_STACK_POINTER_INCREMENT ();\n",
+ reg, reg, from);
+ else if (suba_hack)
+ printf ("\tif (%s == 7) CHECK_STACK_POINTER_DECREMENT ();\n",
+ reg, reg, from);
+ else if (lea_hack)
+ {
+ printf ("\tif (dstreg == 7) {\n");
+ printf ("\t\tif (srcreg == 7) {\n");
+ printf ("\t\t\tif (prev_dstreg < (%s)) CHECK_STACK_POINTER_INCREMENT ();\n", from);
+ printf ("\t\t\tif (prev_dstreg > (%s)) CHECK_STACK_POINTER_DECREMENT ();\n", from);
+ printf ("\t\t} else {\n");
+ printf ("\t\t\tCHECK_STACK_POINTER_ASSIGNMENT ();\n", from);
+ printf ("\t\t}\n");
+ printf ("\t}\n");
+ }
+ else
+ printf ("\tif (%s == 7) CHECK_STACK_POINTER_ASSIGNMENT ();\n",
+ reg, reg, from, reg);
+#endif // PALM_STACK
+ break;
+ default:
+ abort ();
+ }
+#if PALM_PERF
+ extraCycles += 0; writeCycles += 0; PERF_COMMENT("write: An 0(0/0)\n");
+#endif // PALM_PERF
+ break;
+ case Aind:
+ case Aipi:
+ case Apdi:
+ case Ad16:
+ case Ad8r:
+ case absw:
+ case absl:
+ case PC16:
+ case PC8r:
+ if (using_prefetch)
+ sync_m68k_pc ();
+ switch (size) {
+ case sz_byte:
+ insn_n_cycles += 2;
+ printf ("\tput_byte(%sa,%s);\n", to, from);
+#if PALM_PERF
+ extraCycles += 0; writeCycles += 1; PERF_COMMENT("write: to, from B 4(0/1)\n");
+#endif // PALM_PERF
+ break;
+ case sz_word:
+ insn_n_cycles += 2;
+ if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+ abort ();
+ printf ("\tput_word(%sa,%s);\n", to, from);
+#if PALM_PERF
+ extraCycles += 0; writeCycles += 1; PERF_COMMENT("write: to, from W 4(0/1)\n");
+#endif // PALM_PERF
+ break;
+ case sz_long:
+ insn_n_cycles += 4;
+ if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+ abort ();
+ printf ("\tput_long(%sa,%s);\n", to, from);
+#if PALM_PERF
+ extraCycles += 0; writeCycles += 2; PERF_COMMENT("write: to, from L 8(0/2)\n");
+#endif // PALM_PERF
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case imm:
+ case imm0:
+ case imm1:
+ case imm2:
+ case immi:
+ abort ();
+ break;
+ default:
+ abort ();
+ }
+}
+
+static void genmovemel (uae_u16 opcode)
+{
+ char getcode[100];
+ int size = table68k[opcode].size == sz_long ? 4 : 2;
+
+ if (table68k[opcode].size == sz_long) {
+ strcpy (getcode, "get_long(srca)");
+ } else {
+ strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)");
+ }
+
+ printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
+ printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
+ genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+ start_brace ();
+#if PALM_STACK
+ // Might want to add a check here. But it's not likely for A7 to get messed
+ // up during this operation. First, the stack (if that's what's being used
+ // as the source here) is being incremented, not decremented, so there's no
+ // chance of an overflow. Second, the chance that A7 is in the destination
+ // set of registers is very unlikely, so we don't need to check for that, either.
+ // I suppose A7 *could* be in the dest set if MOVEM is used for a task switch.
+ // Something to think about...
+#endif // PALM_STACK
+ printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n",
+ getcode, size);
+ printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n",
+ getcode, size);
+
+ if (table68k[opcode].dmode == Aipi)
+ printf ("\tm68k_areg(regs, dstreg) = srca;\n");
+#if PALM_PERF
+ {extraCycles += 0; readCycles = 0xFF; writeCycles += 0; PERF_COMMENT("MOVEM M, R 12+4n(3+n/0) + eff addr\n");}
+ // ¥¥¥ DOLATER this doesnt quite generate the right number of reads, I dont know what the extra is for!
+#endif // PALM_PERF
+}
+
+static void genmovemle (uae_u16 opcode)
+{
+ char putcode[100];
+ int size = table68k[opcode].size == sz_long ? 4 : 2;
+ if (table68k[opcode].size == sz_long) {
+ strcpy (putcode, "put_long(srca,");
+ } else {
+ strcpy (putcode, "put_word(srca,");
+ }
+
+ printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
+ genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+ if (using_prefetch)
+ sync_m68k_pc ();
+
+ start_brace ();
+ if (table68k[opcode].dmode == Apdi) {
+ printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
+#if PALM_STACK
+ // Pre-decrement the dest pointer by the maximum amount it could possibly
+ // move. Doing this prevents our "did they access the area below the stack
+ // pointer" sniffer from going off in the middle of this opcode.
+ printf ("\tm68k_areg (regs, dstreg) -= 16 * %d;\n", size);
+#endif // PALM_STACK
+ printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n",
+ size, putcode);
+ printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n",
+ size, putcode);
+ printf ("\tm68k_areg(regs, dstreg) = srca;\n");
+#if PALM_STACK
+ printf ("\tCHECK_STACK_POINTER_DECREMENT ();\n");
+#endif // PALM_STACK
+ } else {
+ printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
+ printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n",
+ putcode, size);
+ printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n",
+ putcode, size);
+ }
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 2; writeCycles = 0xFF; PERF_COMMENT("MOVEM R, M 8+4n(2/n) + eff addr\n");}
+#endif // PALM_PERF
+}
+
+static void duplicate_carry (void)
+{
+ printf ("\tCOPY_CARRY;\n");
+}
+
+typedef enum {
+ flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn,
+ flag_av, flag_sv
+} flagtypes;
+
+static void genflags_normal (flagtypes type, wordsizes size, char *value, char *src, char *dst)
+{
+ char vstr[100], sstr[100], dstr[100];
+ char usstr[100], udstr[100];
+ char unsstr[100], undstr[100];
+
+ switch (size) {
+ case sz_byte:
+ strcpy (vstr, "((uae_s8)(");
+ strcpy (usstr, "((uae_u8)(");
+ break;
+ case sz_word:
+ strcpy (vstr, "((uae_s16)(");
+ strcpy (usstr, "((uae_u16)(");
+ break;
+ case sz_long:
+ strcpy (vstr, "((uae_s32)(");
+ strcpy (usstr, "((uae_u32)(");
+ break;
+ default:
+ abort ();
+ }
+ strcpy (unsstr, usstr);
+
+ strcpy (sstr, vstr);
+ strcpy (dstr, vstr);
+ strcat (vstr, value);
+ strcat (vstr, "))");
+ strcat (dstr, dst);
+ strcat (dstr, "))");
+ strcat (sstr, src);
+ strcat (sstr, "))");
+
+ strcpy (udstr, usstr);
+ strcat (udstr, dst);
+ strcat (udstr, "))");
+ strcat (usstr, src);
+ strcat (usstr, "))");
+
+ strcpy (undstr, unsstr);
+ strcat (unsstr, "-");
+ strcat (undstr, "~");
+ strcat (undstr, dst);
+ strcat (undstr, "))");
+ strcat (unsstr, src);
+ strcat (unsstr, "))");
+
+ switch (type) {
+ case flag_logical_noclobber:
+ case flag_logical:
+ case flag_zn:
+ case flag_av:
+ case flag_sv:
+ case flag_addx:
+ case flag_subx:
+ break;
+
+ case flag_add:
+ start_brace ();
+ printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr);
+ break;
+ case flag_sub:
+ case flag_cmp:
+ start_brace ();
+ printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr);
+ break;
+ }
+
+ switch (type) {
+ case flag_logical_noclobber:
+ case flag_logical:
+ case flag_zn:
+ break;
+
+ case flag_add:
+ case flag_sub:
+ case flag_addx:
+ case flag_subx:
+ case flag_cmp:
+ case flag_av:
+ case flag_sv:
+ start_brace ();
+ printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr);
+ printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr);
+ printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr);
+ break;
+ }
+
+ switch (type) {
+ case flag_logical:
+ printf ("\tCLEAR_CZNV;\n");
+ printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+ printf ("\tSET_NFLG (%s < 0);\n", vstr);
+ break;
+ case flag_logical_noclobber:
+ printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+ printf ("\tSET_NFLG (%s < 0);\n", vstr);
+ break;
+ case flag_av:
+ printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
+ break;
+ case flag_sv:
+ printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
+ break;
+ case flag_zn:
+ printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr);
+ printf ("\tSET_NFLG (%s < 0);\n", vstr);
+ break;
+ case flag_add:
+ printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+ printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
+ printf ("\tSET_CFLG (%s < %s);\n", undstr, usstr);
+ duplicate_carry ();
+ printf ("\tSET_NFLG (flgn != 0);\n");
+ break;
+ case flag_sub:
+ printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+ printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
+ printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
+ duplicate_carry ();
+ printf ("\tSET_NFLG (flgn != 0);\n");
+ break;
+ case flag_addx:
+ printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n"); /* minterm SON: 0x42 */
+ printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));\n"); /* minterm SON: 0xD4 */
+ duplicate_carry ();
+ break;
+ case flag_subx:
+ printf ("\tSET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));\n"); /* minterm SON: 0x24 */
+ printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));\n"); /* minterm SON: 0xB2 */
+ duplicate_carry ();
+ break;
+ case flag_cmp:
+ printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+ printf ("\tSET_VFLG ((flgs != flgo) && (flgn != flgo));\n");
+ printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
+ printf ("\tSET_NFLG (flgn != 0);\n");
+ break;
+ }
+}
+
+static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst)
+{
+#ifdef X86_ASSEMBLY
+ switch (type) {
+ case flag_add:
+ case flag_sub:
+ start_brace ();
+ printf ("\tuae_u32 %s;\n", value);
+ break;
+
+ default:
+ break;
+ }
+
+ /* At least some of those casts are fairly important! */
+ switch (type) {
+ case flag_logical_noclobber:
+ printf ("\t{uae_u32 oldcznv = regflags.cznv & ~0xC0;\n");
+ if (strcmp (value, "0") == 0) {
+ printf ("\tregflags.cznv = olcznv | 64;\n");
+ } else {
+ switch (size) {
+ case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break;
+ case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break;
+ case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break;
+ }
+ printf ("\tregflags.cznv |= oldcznv;\n");
+ }
+ printf ("\t}\n");
+ return;
+ case flag_logical:
+ if (strcmp (value, "0") == 0) {
+ printf ("\tregflags.cznv = 64;\n");
+ } else {
+ switch (size) {
+ case sz_byte: printf ("\tx86_flag_testb ((uae_s8)(%s));\n", value); break;
+ case sz_word: printf ("\tx86_flag_testw ((uae_s16)(%s));\n", value); break;
+ case sz_long: printf ("\tx86_flag_testl ((uae_s32)(%s));\n", value); break;
+ }
+ }
+ return;
+
+ case flag_add:
+ switch (size) {
+ case sz_byte: printf ("\tx86_flag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
+ case sz_word: printf ("\tx86_flag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
+ case sz_long: printf ("\tx86_flag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
+ }
+ return;
+
+ case flag_sub:
+ switch (size) {
+ case sz_byte: printf ("\tx86_flag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
+ case sz_word: printf ("\tx86_flag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
+ case sz_long: printf ("\tx86_flag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
+ }
+ return;
+
+ case flag_cmp:
+ switch (size) {
+ case sz_byte: printf ("\tx86_flag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break;
+ case sz_word: printf ("\tx86_flag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break;
+ case sz_long: printf ("\tx86_flag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break;
+ }
+ return;
+
+ default:
+ break;
+ }
+#elif defined(M68K_FLAG_OPT)
+ /* sam: here I'm cloning what X86_ASSEMBLY does */
+#define EXT(size) (size==sz_byte?"b":(size==sz_word?"w":"l"))
+#define CAST(size) (size==sz_byte?"uae_s8":(size==sz_word?"uae_s16":"uae_s32"))
+ switch (type) {
+ case flag_add:
+ case flag_sub:
+ start_brace ();
+ printf ("\tuae_u32 %s;\n", value);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (type) {
+ case flag_logical:
+ if (strcmp (value, "0") == 0) {
+ printf ("\t*(uae_u16 *)&regflags = 4;\n"); /* Z = 1 */
+ } else {
+ printf ("\tm68k_flag_tst (%s, (%s)(%s));\n",
+ EXT (size), CAST (size), value);
+ }
+ return;
+
+ case flag_add:
+ printf ("\t{uae_u16 ccr;\n");
+ printf ("\tm68k_flag_add (%s, (%s)%s, (%s)(%s), (%s)(%s));\n",
+ EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst);
+ printf ("\t((uae_u16*)&regflags)[1]=((uae_u16*)&regflags)[0]=ccr;}\n");
+ return;
+
+ case flag_sub:
+ printf ("\t{uae_u16 ccr;\n");
+ printf ("\tm68k_flag_sub (%s, (%s)%s, (%s)(%s), (%s)(%s));\n",
+ EXT (size), CAST (size), value, CAST (size), src, CAST (size), dst);
+ printf ("\t((uae_u16*)&regflags)[1]=((uae_u16*)&regflags)[0]=ccr;}\n");
+ return;
+
+ case flag_cmp:
+ printf ("\tm68k_flag_cmp (%s, (%s)(%s), (%s)(%s));\n",
+ EXT (size), CAST (size), src, CAST (size), dst);
+ return;
+
+ default:
+ break;
+ }
+#elif defined(ACORN_FLAG_OPT) && defined(__GNUC_MINOR__)
+/*
+ * This is new. Might be quite buggy.
+ */
+ switch (type) {
+ case flag_av:
+ case flag_sv:
+ case flag_zn:
+ case flag_addx:
+ case flag_subx:
+ break;
+
+ case flag_logical:
+ if (strcmp (value, "0") == 0) {
+ /* v=c=n=0 z=1 */
+ printf ("\t*(ULONG*)&regflags = 0x40000000;\n");
+ return;
+ } else {
+ start_brace ();
+ switch (size) {
+ case sz_byte:
+ printf ("\tUBYTE ccr;\n");
+ printf ("\tULONG shift;\n");
+ printf ("\t__asm__(\"mov %%2,%%1,lsl#24\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n"
+ "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ return;
+ case sz_word:
+ printf ("\tUBYTE ccr;\n");
+ printf ("\tULONG shift;\n");
+ printf ("\t__asm__(\"mov %%2,%%1,lsl#16\n\ttst %%2,%%2\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n"
+ "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ return;
+ case sz_long:
+ printf ("\tUBYTE ccr;\n");
+ printf ("\t__asm__(\"tst %%1,%%1\n\tmov %%0,r15,lsr#24\n\tbic %%0,%%0,#0x30\"\n"
+ "\t: \"=r\" (ccr) : \"r\" ((LONG)%s) : \"cc\" );\n", value);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ return;
+ }
+ }
+ break;
+ case flag_add:
+ if (strcmp (dst, "0") == 0) {
+ printf ("/* Error! Hier muss Peter noch was machen !!! (ADD-Flags) */");
+ } else {
+ start_brace ();
+ switch (size) {
+ case sz_byte:
+ printf ("\tULONG ccr, shift, %s;\n", value);
+ printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tadds %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ case sz_word:
+ printf ("\tULONG ccr, shift, %s;\n", value);
+ printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tadds %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ case sz_long:
+ printf ("\tULONG ccr, %s;\n", value);
+ printf ("\t__asm__(\"adds %%0,%%3,%%2\n\tmov %%1,r15\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ }
+ }
+ break;
+ case flag_sub:
+ if (strcmp (dst, "0") == 0) {
+ printf ("/* Error! Hier muss Peter noch was machen !!! (SUB-Flags) */");
+ } else {
+ start_brace ();
+ switch (size) {
+ case sz_byte:
+ printf ("\tULONG ccr, shift, %s;\n", value);
+ printf ("\t__asm__(\"mov %%4,%%3,lsl#24\n\tsubs %%0,%%4,%%2,lsl#24\n\tmov %%0,%%0,asr#24\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ case sz_word:
+ printf ("\tULONG ccr, shift, %s;\n", value);
+ printf ("\t__asm__(\"mov %%4,%%3,lsl#16\n\tsubs %%0,%%4,%%2,lsl#16\n\tmov %%0,%%0,asr#16\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ case sz_long:
+ printf ("\tULONG ccr, %s;\n", value);
+ printf ("\t__asm__(\"subs %%0,%%3,%%2\n\tmov %%1,r15\n\teor %%1,%%1,#0x20000000\n\torr %%1,%%1,%%1,lsr#29\"\n"
+ "\t: \"=r\" (%s), \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", value, src, dst);
+ printf ("\t*(ULONG*)&regflags = ccr;\n");
+ return;
+ }
+ }
+ break;
+ case flag_cmp:
+ if (strcmp (dst, "0") == 0) {
+ printf ("/*Error! Hier muss Peter noch was machen !!! (CMP-Flags)*/");
+ } else {
+ start_brace ();
+ switch (size) {
+ case sz_byte:
+ printf ("\tULONG shift, ccr;\n");
+ printf ("\t__asm__(\"mov %%3,%%2,lsl#24\n\tcmp %%3,%%1,lsl#24\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n"
+ "\t: \"=r\" (ccr) : \"r\" (%s), \"r\" (%s), \"r\" (shift) : \"cc\" );\n", src, dst);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ return;
+ case sz_word:
+ printf ("\tULONG shift, ccr;\n");
+ printf ("\t__asm__(\"mov %%3,%%2,lsl#16\n\tcmp %%3,%%1,lsl#16\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n"
+ "\t: \"=r\" (ccr) : \"r\" ((WORD)%s), \"r\" ((WORD)%s), \"r\" (shift) : \"cc\" );\n", src, dst);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ return;
+ case sz_long:
+ printf ("\tULONG ccr;\n");
+ printf ("\t__asm__(\"cmp %%2,%%1\n\tmov %%0,r15,lsr#24\n\teor %%0,%%0,#0x20\"\n"
+ "\t: \"=r\" (ccr) : \"r\" ((LONG)%s), \"r\" ((LONG)%s) : \"cc\" );\n", src, dst);
+ printf ("\t*((UBYTE*)&regflags+3) = ccr;\n");
+ /*printf ("\tprintf (\"%%08x %%08x %%08x\\n\", %s, %s, *((ULONG*)&regflags));\n", src, dst); */
+ return;
+ }
+ }
+ break;
+ }
+#endif
+ genflags_normal (type, size, value, src, dst);
+}
+
+static void force_range_for_rox (const char *var, wordsizes size)
+{
+ /* Could do a modulo operation here... which one is faster? */
+ switch (size) {
+ case sz_long:
+ printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
+ break;
+ case sz_word:
+ printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
+ printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
+ break;
+ case sz_byte:
+ printf ("\tif (%s >= 36) %s -= 36;\n", var, var);
+ printf ("\tif (%s >= 18) %s -= 18;\n", var, var);
+ printf ("\tif (%s >= 9) %s -= 9;\n", var, var);
+ break;
+ }
+}
+
+static const char *cmask (wordsizes size)
+{
+ switch (size) {
+ case sz_byte: return "0x80";
+ case sz_word: return "0x8000";
+ case sz_long: return "0x80000000";
+ default: abort ();
+ }
+}
+
+static int source_is_imm1_8 (struct instr *i)
+{
+ return i->stype == 3;
+}
+
+static void gen_opcode (unsigned long int opcode)
+{
+ struct instr *curi = table68k + opcode;
+#if PALM_PERF
+ extraCycles = readCycles = writeCycles = 0;
+#endif // PALM_PERF
+ insn_n_cycles = 2;
+
+ start_brace ();
+#if 0
+ printf ("uae_u8 *m68k_pc = regs.pc_p;\n");
+#endif
+ m68k_pc_offset = 2;
+ switch (curi->plev) {
+ case 0: /* not privileged */
+ break;
+ case 1: /* unprivileged only on 68000 */
+ if (cpu_level == 0)
+ break;
+ if (next_cpu_level < 0)
+ next_cpu_level = 0;
+
+ /* fall through */
+ case 2: /* priviledged */
+ printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
+ need_endlabel = 1;
+ start_brace ();
+ break;
+ case 3: /* privileged if size == word */
+ if (curi->size == sz_byte)
+ break;
+ printf ("if (!regs.s) { Exception(8,0); goto %s; }\n", endlabelstr);
+ need_endlabel = 1;
+ start_brace ();
+ break;
+ }
+ switch (curi->mnemo) {
+ case i_OR:
+ case i_AND:
+ case i_EOR:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
+ genflags (flag_logical, curi->size, "src", "", "");
+ genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->mnemo == i_OR)
+ {
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("OR.B/W M, Dn 4(1/0)+ Dn, M 8(1/1)+\n");}
+ else
+ if (curi->dmode == Dreg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("OR.L <ea>, Dn 6(1/0)+**\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("OR.L Dn, M 12(1/2)+**\n");}
+ }
+ else if (curi->mnemo == i_AND)
+ {
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("AND.B/W M, Dn 4(1/0)+ Dn, M 8(1/1)+\n");}
+ else
+ if (curi->dmode == Dreg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("AND.L <ea>, Dn 6(1/0)+**\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("AND.L Dn, M 12(1/2)+**\n");}
+ }
+ else
+ {
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("EOR.B/W M, Dn 4(1/0)+, Dn, M 8(1/1)+\n");}
+ else
+ if (curi->dmode == Dreg)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("EOR.L M, Dn 8(1/0)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("EOR.L Dn, M 12(1/2)+\n");}
+ }
+#endif // PALM_PERF
+ break;
+ case i_ORSR:
+ case i_EORSR:
+ printf ("\tMakeSR();\n");
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ if (curi->size == sz_byte) {
+ printf ("\tsrc &= 0xFF;\n");
+ }
+ printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
+ printf ("\tMakeFromSR();\n");
+#if PALM_PERF
+ if (curi->mnemo == i_EORSR)
+ {
+ if (curi->size <= sz_word)
+ {extraCycles += 8; readCycles += 3; writeCycles += 0; PERF_COMMENT("EORSR.B/W 20(3/0)\n");}
+ }
+ else
+ {
+ if (curi->size <= sz_word)
+ {extraCycles += 8; readCycles += 3; writeCycles += 0; PERF_COMMENT("ORSR.B/W 20(3/0)\n");}
+ }
+#endif // PALM_PERF
+ break;
+ case i_ANDSR:
+ printf ("\tMakeSR();\n");
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ if (curi->size == sz_byte) {
+ printf ("\tsrc |= 0xFF00;\n");
+ }
+ printf ("\tregs.sr &= src;\n");
+ printf ("\tMakeFromSR();\n");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 8; readCycles += 3; writeCycles += 0; PERF_COMMENT("ANDSR.B/W 20(3/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_SUB:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ genflags (flag_sub, curi->size, "newv", "src", "dst");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ if (curi->dmode == Areg)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUB.B/W, An 8(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUB.B/W Dn 4(1/0), <M> 8(1/1)\n");}
+ else
+ if (curi->dmode <= Areg)
+ if (curi->smode <= Areg || curi->smode >= imm)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUB.L {An, Dn, imm}, {An, Dn} 8(1/0)+\n");}
+ else
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUB.L <M>, {An, Dn} 6(1/0)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUB.L Dn, <M> 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_SUBA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = dst - src;\n");
+#if PALM_STACK
+ suba_hack = 1;
+#endif // PALM_STACK
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+#if PALM_STACK
+ suba_hack = 0;
+#endif // PALM_STACK
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBA.W, An 8(1/0)\n");}
+ else
+ if (curi->smode <= Areg || curi->smode >= imm)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBA.L {An, Dn, imm}, {An, Dn} 8(1/0)+\n");}
+ else
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBA.L <M>, {An, Dn} 6(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_SUBX:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n");
+ genflags (flag_subx, curi->size, "newv", "src", "dst");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ if (curi->smode == Dreg)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBX.B/W Dn, Dn 4(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBX.B/W -(Ax), -(Ay) 18(3/1)\n");}
+ else // sz_long
+ if (curi->smode == Dreg)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBX.L Dn, Dn 8(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SUBX.L -(Ax), -(Ay) 30(5/2)\n");}
+#endif // PALM_PERF
+ break;
+ case i_SBCD:
+ /* Let's hope this works... */
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
+ printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
+ printf ("\tuae_u16 newv;\n");
+ printf ("\tint cflg;\n");
+ printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n");
+ printf ("\tnewv = newv_hi + (newv_lo & 0xF);");
+ printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n");
+ duplicate_carry ();
+ printf ("\tif (cflg) newv -= 0x60;\n");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genflags (flag_sv, curi->size, "newv", "src", "dst");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size == sz_byte)
+ if (curi->smode == Dreg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SBCD.B Dn, Dn 6(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("SBCD.B -(Ax), -(Ay) 18(3/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ADD:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ genflags (flag_add, curi->size, "newv", "src", "dst");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ if (curi->dmode == Areg)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.W 8(1/0)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.B/W <ea>, Dn 4(1/0)+, <M> 8(1/1)+\n");}
+ else // sz_long
+ if (curi->dmode <= Areg)
+ if (curi->smode <= Areg || curi->smode >= imm)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.L {Rn, imm}, Rn 8(1/0)+\n");}
+ else
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.L <M>, Rn 6(1/0)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.L Dn, <M> 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ADDA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = dst + src;\n");
+#if PALM_STACK
+ adda_hack = 1;
+#endif // PALM_STACK
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+#if PALM_STACK
+ adda_hack = 0;
+#endif // PALM_STACK
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.W, An 8(1/0)\n");}
+ else
+ if (curi->smode <= Areg || curi->smode >= imm)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.L {An, Dn, imm}, {An, Dn} 8(1/0)+\n");}
+ else
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADD.L <M>, {An, Dn} 6(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ADDX:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n");
+ genflags (flag_addx, curi->size, "newv", "src", "dst");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ if (curi->smode == Dreg)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADDX.B/W Dn, Dn 4(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADDX.B/W -(Ax), -(Ay) 18(3/1)\n");}
+ else // sz_long
+ if (curi->smode == Dreg)
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADDX.L Dn, Dn 8(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ADDX.L -(Ax), -(Ay) 30(5/2)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ABCD:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n");
+ printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
+ printf ("\tuae_u16 newv;\n");
+ printf ("\tint cflg;\n");
+ printf ("\tif (newv_lo > 9) { newv_lo +=6; }\n");
+ printf ("\tnewv = newv_hi + newv_lo;");
+ printf ("\tSET_CFLG (cflg = (newv & 0x1F0) > 0x90);\n");
+ duplicate_carry ();
+ printf ("\tif (cflg) newv += 0x60;\n");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genflags (flag_sv, curi->size, "newv", "src", "dst");
+ genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size == sz_byte)
+ if (curi->smode == Dreg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ABCD.B Dn, Dn 6(1/0)\n");}
+ else
+ {extraCycles += -2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ABCD.B -(Ax), -(Ay) 18(3/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_NEG:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ genflags (flag_sub, curi->size, "dst", "src", "0");
+ genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEG.B/W Rn 4(1/0) M 8(1/1)+\n");}
+ else // sz_word, sz_long
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEG.L Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEG.B/W M 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_NEGX:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n");
+ genflags (flag_subx, curi->size, "newv", "src", "0");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genastore ("newv", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEGX.B/W Rn 4(1/0) M 8(1/1)+\n");}
+ else // sz_word, sz_long
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEGX.L Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NEGX.L M 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_NBCD:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
+ printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
+ printf ("\tuae_u16 newv;\n");
+ printf ("\tint cflg;\n");
+ printf ("\tif (newv_lo > 9) { newv_lo-=6; newv_hi-=0x10; }\n");
+ printf ("\tnewv = newv_hi + (newv_lo & 0xF);");
+ printf ("\tSET_CFLG (cflg = (newv_hi & 0x1F0) > 0x90);\n");
+ duplicate_carry();
+ printf ("\tif (cflg) newv -= 0x60;\n");
+ genflags (flag_zn, curi->size, "newv", "", "");
+ genastore ("newv", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ // !!! Does the call to genflags need to be moved below this?
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("NBCD.B Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NBCD.B <M> 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_CLR:
+ genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+ genflags (flag_logical, curi->size, "0", "", "");
+ genastore ("0", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CLR.B/W Rn 4(1/0) M 8(1/1)+\n");}
+ else // sz_long
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("CLR.L Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CLR.L M 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_NOT:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 dst = ~src;\n");
+ genflags (flag_logical, curi->size, "dst", "", "");
+ genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NOT.B/W Rn 4(1/0) M 8(1/1)+\n");}
+ else // sz_long
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("NOT.L Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NOT.L M 12(1/2)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_TST:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genflags (flag_logical, curi->size, "src", "", "");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("TST Rn 4(1/0) M 4(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_BTST:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ if (curi->size == sz_byte)
+ printf ("\tsrc &= 7;\n");
+ else
+ printf ("\tsrc &= 31;\n");
+ printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+#if PALM_PERF
+ if (curi->size <= sz_byte)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("BTST.B M Dyn 4(1/0)+ Stat 8(2/0)+\n");}
+ else // sz_long
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("BTST.L Dn Dyn 6(1/0) Stat 10(2/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_BCHG:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ if (curi->size == sz_byte)
+ printf ("\tsrc &= 7;\n");
+ else
+ printf ("\tsrc &= 31;\n");
+ printf ("\tdst ^= (1 << src);\n");
+#if PALM_BUG_FIX
+ printf ("\tSET_ZFLG ((dst >> src) & 1);\n");
+#else // PALM_BUG_FIX
+ printf ("\tSET_ZFLG ((dst & (1 << src)) >> src);\n");
+#endif // PALM_BUG_FIX
+ genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_byte)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("BCHG.B M Dyn 8(1/1)+ Stat 12(2/1)+\n");}
+ else // sz_long
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("BCHG.L Dn Dyn 8(1/0)* Stat 12(2/0)*\n");}
+#endif // PALM_PERF
+ break;
+ case i_BCLR:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ if (curi->size == sz_byte)
+ printf ("\tsrc &= 7;\n");
+ else
+ printf ("\tsrc &= 31;\n");
+ printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+ printf ("\tdst &= ~(1 << src);\n");
+ genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_byte)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("BCLR.B M Dyn 8(1/1)+ Stat 12(2/1)+\n");}
+ else // sz_long
+ {extraCycles += 6; readCycles += 1; writeCycles += 0; PERF_COMMENT("BCLR.L Dn Dyn 10(1/0)* Stat 14(2/0)*\n");}
+#endif // PALM_PERF
+ break;
+ case i_BSET:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ if (curi->size == sz_byte)
+ printf ("\tsrc &= 7;\n");
+ else
+ printf ("\tsrc &= 31;\n");
+ printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+ printf ("\tdst |= (1 << src);\n");
+ genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ if (curi->size <= sz_byte)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("BSET.B M Dyn 8(1/1)+ Stat 12(2/1)+\n");}
+ else // sz_long
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("BSET.L Dn Dyn 8(1/0)* Stat 12(2/0)*\n");}
+#endif // PALM_PERF
+ break;
+ case i_CMPM:
+ case i_CMP:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ genflags (flag_cmp, curi->size, "newv", "src", "dst");
+#if PALM_PERF
+ if (curi->dmode == Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMP <ea>, An 6(1/0)+\n");}
+ else if (curi->dmode == Dreg)
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMP.B/W <ea>, Dn 4(1/0)+\n");}
+ else // sz_long
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMP.L <ea>, Dn 6(1/0)+\n");}
+ else if (curi->smode >= imm)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMPI #, M B/W 8(2/0)+, L 12(3/0)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMPM M, M B/W 12(3/0), L 20(5/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_CMPA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+ start_brace ();
+ genflags (flag_cmp, sz_long, "newv", "src", "dst");
+#if PALM_PERF
+ if (curi->dmode == Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMPA <ea>, An 6(1/0)+\n");}
+ else if (curi->dmode == Dreg)
+ if (curi->size <= sz_word)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMPA.B/W <ea>, Dn 4(1/0)+\n");}
+ else // sz_long
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("CMPA.L <ea>, Dn 6(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ /* The next two are coded a little unconventional, but they are doing
+ * weird things... */
+ case i_MVPRM:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+
+ printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
+ if (curi->size == sz_word) {
+ printf ("\tput_byte(memp, src >> 8); put_byte(memp + 2, src);\n");
+ } else {
+ printf ("\tput_byte(memp, src >> 24); put_byte(memp + 2, src >> 16);\n");
+ printf ("\tput_byte(memp + 4, src >> 8); put_byte(memp + 6, src);\n");
+ }
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("read: (d16, Ay) 4(1/0)\n");}
+ if (curi->size == sz_word) {
+ {extraCycles += 0; readCycles += 0; writeCycles += 2; PERF_COMMENT("writes: 8(0/2)\n");}
+ } else {
+ {extraCycles += 0; readCycles += 0; writeCycles += 4; PERF_COMMENT("writes: 16(0/4)\n");}
+ }
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVEP Rn, M W 16(2/2) L 24(2/4)\n");}
+#endif // PALM_PERF
+ break;
+ case i_MVPMR:
+ printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+ if (curi->size == sz_word) {
+ printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n");
+ } else {
+ printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n");
+ printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n");
+ }
+ genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("read: (d16, Ay) 4(1/0)\n");}
+ if (curi->size == sz_word) {
+ {extraCycles += 0; readCycles += 2; writeCycles += 0; PERF_COMMENT("reads: 8(2/0)\n");}
+ } else {
+ {extraCycles += 0; readCycles += 4; writeCycles += 0; PERF_COMMENT("reads: 16(4/0)\n");}
+ }
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVEP M, Rn W 16(4/0) L 24(6/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_MOVE:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+ genflags (flag_logical, curi->size, "src", "", "");
+ genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVE 4(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_MOVEA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+ if (curi->size == sz_word) {
+ printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n");
+ } else {
+ printf ("\tuae_u32 val = src;\n");
+ }
+ genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVEA 4(1/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_MVSR2:
+ genamode (curi->smode, "srcreg", sz_word, "src", 2, 0);
+ printf ("\tMakeSR();\n");
+ if (curi->size == sz_byte)
+ genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
+ else
+ genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
+#if PALM_PERF
+ if (curi->smode <= Areg)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVE SR, Rn 6(1/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVE SR, M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_MV2SR:
+ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+ if (curi->size == sz_byte)
+ printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
+ else {
+ printf ("\tregs.sr = src;\n");
+ }
+ printf ("\tMakeFromSR();\n");
+#if PALM_PERF
+ {extraCycles += 4; readCycles += 2; writeCycles += 0; PERF_COMMENT("MOVE <ea>, SR 12(2/0)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_SWAP:
+ genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
+ genflags (flag_logical, sz_long, "dst", "", "");
+ genastore ("dst", curi->smode, "srcreg", sz_long, "src");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("SWAP 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_EXG:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+ genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_PERF
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("EXG 6(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_EXT:
+ genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
+ case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break;
+ case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break;
+ default: abort ();
+ }
+ genflags (flag_logical,
+ curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
+ genastore ("dst", curi->smode, "srcreg",
+ curi->size == sz_word ? sz_word : sz_long, "src");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("EXT 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_MVMEL:
+ genmovemel (opcode);
+ break;
+ case i_MVMLE:
+ genmovemle (opcode);
+ break;
+ case i_TRAP:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tException(src+32,0);\n");
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles += 6; readCycles = 0xFF; writeCycles = 0xFF; PERF_COMMENT("TRAP 34(4/3)\n");}
+#endif // PALM_PERF
+ break;
+ case i_MVR2USP:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ printf ("\tregs.usp = src;\n");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVE to USP 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_MVUSP2R:
+ genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+ genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("MOVE from USP 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_RESET:
+ printf ("\tcustomreset();\n");
+#if PALM_PERF
+ {extraCycles += 128; readCycles += 1; writeCycles += 0; PERF_COMMENT("RESET 132(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_NOP:
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("NOP 4(1/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_STOP:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ printf ("\tregs.sr = src;\n");
+ printf ("\tMakeFromSR();\n");
+ printf ("\tm68k_setstopped(1);\n");
+#if PALM_PERF
+ {extraCycles += 4; readCycles += 0; writeCycles += 0; PERF_COMMENT("STOP 4(0/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_RTE:
+ if (cpu_level == 0) {
+ genamode (Aipi, "7", sz_word, "sr", 1, 0);
+ genamode (Aipi, "7", sz_long, "pc", 1, 0);
+#if PALM_PERF
+ printf ("\tregs.sr = sr; m68k_do_rte(pc);\n");
+#else // PALM_PERF
+ printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
+#endif // PALM_PERF
+ fill_prefetch_0 ();
+ printf ("\tMakeFromSR();\n");
+ } else {
+ int old_brace_level = n_braces;
+ if (next_cpu_level < 0)
+ next_cpu_level = 0;
+ printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n");
+ genamode (Aipi, "7", sz_word, "sr", 1, 0);
+ genamode (Aipi, "7", sz_long, "pc", 1, 0);
+ genamode (Aipi, "7", sz_word, "format", 1, 0);
+ printf ("\tnewsr = sr; newpc = pc;\n");
+ printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n");
+ printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n");
+ printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n");
+ printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
+ printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
+ printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
+ printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n");
+ printf ("\telse { Exception(14,0); goto %s; }\n", endlabelstr);
+ printf ("\tregs.sr = newsr; MakeFromSR();\n}\n");
+ pop_braces (old_brace_level);
+ printf ("\tregs.sr = newsr; MakeFromSR();\n");
+ printf ("\tm68k_setpc_rte(newpc);\n");
+ fill_prefetch_0 ();
+ need_endlabel = 1;
+ }
+ /* PC is set and prefetch filled. */
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 2; writeCycles += 0; PERF_COMMENT("RTE 20(5/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_RTD:
+ printf ("\tcompiler_flush_jsr_stack();\n");
+ genamode (Aipi, "7", sz_long, "pc", 1, 0);
+ genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
+ printf ("\tm68k_areg(regs, 7) += offs;\n");
+#if PALM_STACK
+ printf ("\tCHECK_STACK_POINTER_INCREMENT ();\n");
+#endif // PALM_STACK
+ printf ("\tm68k_setpc_rte(pc);\n");
+ fill_prefetch_0 ();
+ /* PC is set and prefetch filled. */
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 0; writeCycles += 0; PERF_COMMENT("RTD ?(?/?)\n");}
+#endif // PALM_PERF
+ break;
+ case i_LINK:
+ genamode (Apdi, "7", sz_long, "old", 2, 0);
+ genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+ genastore ("src", Apdi, "7", sz_long, "old");
+ genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
+ genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
+ printf ("\tm68k_areg(regs, 7) += offs;\n");
+#if PALM_STACK
+ printf ("\tCHECK_STACK_POINTER_DECREMENT ();\n");
+#endif // PALM_STACK
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LINK 16(2/2)\n");}
+#endif // PALM_PERF
+ break;
+ case i_UNLK:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ printf ("\tm68k_areg(regs, 7) = src;\n");
+#if PALM_STACK
+ printf ("\tCHECK_STACK_POINTER_INCREMENT ();\n");
+#endif // PALM_STACK
+ genamode (Aipi, "7", sz_long, "old", 1, 0);
+ genastore ("old", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("UNLK 12(3/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_RTS:
+ printf ("\tm68k_do_rts();\n");
+ fill_prefetch_0 ();
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 4; writeCycles += 0; PERF_COMMENT("RTS 16(4/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_TRAPV:
+ sync_m68k_pc ();
+ printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr);
+ need_endlabel = 1;
+#if PALM_PERF
+ {extraCycles += 0; readCycles = 0xFF; writeCycles = 0xFF; PERF_COMMENT("TRAPV 4(1/0) OR 34(5/3)\n");}
+#endif // PALM_PERF
+ break;
+ case i_RTR:
+ printf ("\tcompiler_flush_jsr_stack();\n");
+ printf ("\tMakeSR();\n");
+ genamode (Aipi, "7", sz_word, "sr", 1, 0);
+ genamode (Aipi, "7", sz_long, "pc", 1, 0);
+ printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
+ printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
+ fill_prefetch_0 ();
+ printf ("\tMakeFromSR();\n");
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles += 12; readCycles += -1; writeCycles += 0; PERF_COMMENT("RTR 20(2/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_JSR:
+ genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+#if PALM_SYSTEM_CALL
+ if (curi->smode == Aind)
+ printf ("if (!Software_ProcessJSR_Ind (m68k_getpc(), srca))\n");
+#endif // PALM_SYSTEM_CALL
+ printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
+ fill_prefetch_0 ();
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ switch (curi->smode) {
+ case Ad16:
+ case absw:
+ case PC16:
+ {extraCycles = 2; readCycles = 2; writeCycles = 2; PERF_COMMENT("JSR {(d16, An), (xxx).W, (d16 PC)} 18(2/2)\n");}
+ break;
+ case Aind:
+ {extraCycles = 0; readCycles = 2; writeCycles = 2; PERF_COMMENT("JSR (An) 16(2/2)\n");}
+ break;
+ case Ad8r:
+ case PC8r:
+ {extraCycles = 6; readCycles = 2; writeCycles = 2; PERF_COMMENT("JSR {(d8,An,Xn)+, (d8,PC,Xn)} 22(2/2)\n");}
+ break;
+ case absl:
+ {extraCycles = 0; readCycles = 3; writeCycles = 2; PERF_COMMENT("JSR (xxx).L 20(3/2)\n");}
+ break;
+ }
+#endif // PALM_PERF
+ break;
+ case i_JMP:
+ genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+ printf ("\tm68k_setpc(srca);\n");
+ fill_prefetch_0 ();
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ if (curi->smode == absl)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("JMP (xxx).L 12(3/0)\n");}
+ else if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("JMP {(d16, An), (xxx).W, (d16 PC)} 10(2/0)\n");}
+ else
+ {extraCycles += 0; readCycles += 2; writeCycles += 0; PERF_COMMENT("JMP (An) 8(2/0) (d8,An,Xn) 14(3/0), (d8,PC,Xn) 14(3/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_BSR:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ printf ("\tuae_s32 s = (uae_s32)src + 2;\n");
+ if (using_exception_3) {
+ printf ("\tif (src & 1) {\n");
+ printf ("\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
+ printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n");
+ printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
+ printf ("\t}\n");
+ need_endlabel = 1;
+ }
+ printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
+ fill_prefetch_0 ();
+ m68k_pc_offset = 0;
+#if PALM_PERF
+ {extraCycles = 2; readCycles = 2; writeCycles = 2; PERF_COMMENT("BSR 18(2/2)\n");}
+#endif // PALM_PERF
+ break;
+ case i_Bcc:
+ if (curi->size == sz_long) {
+ if (cpu_level < 2) {
+ printf ("\tm68k_incpc(2);\n");
+ printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr);
+ printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
+ printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n");
+ printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
+ need_endlabel = 1;
+ } else {
+ if (next_cpu_level < 1)
+ next_cpu_level = 1;
+ }
+ }
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
+ if (using_exception_3) {
+ printf ("\tif (src & 1) {\n");
+ printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
+ printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)src;\n");
+ printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
+ printf ("\t}\n");
+ need_endlabel = 1;
+ }
+#ifdef USE_COMPILER
+ printf ("\tm68k_setpc_bcc(m68k_getpc() + 2 + (uae_s32)src);\n");
+#else
+ printf ("\tm68k_incpc ((uae_s32)src + 2);\n");
+#endif
+ fill_prefetch_0 ();
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+ printf ("\tgoto %s;\n", endlabelstr);
+ printf ("didnt_jump:;\n");
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥Êstill missing a read cycle sometimes. Weird. Don't know the address read from, so can't compute waits...
+ // ¥¥¥ readcycles should be 2, setting to 0xFF to disable breaking
+ if (curi->size == sz_byte)
+ {extraCycles += 2; readCycles = 0xFF; writeCycles += 0; PERF_COMMENT("Bcc.B 10(2/0) if taken, 8(1/0) if not\n");}
+ else
+ {extraCycles += 2; readCycles = 0xFF; writeCycles += 0; PERF_COMMENT("Bcc.W 10(2/0) if taken, 12(2/0) if not\n");}
+#endif // PALM_PERF
+ break;
+ case i_LEA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+#if PALM_STACK
+ if (curi->smode == Areg ||
+ curi->smode == Aind ||
+ curi->smode == Aipi ||
+ curi->smode == Apdi ||
+ curi->smode == Ad16 ||
+ curi->smode == Ad8r)
+ lea_hack = 1;
+#endif // PALM_STACK
+ genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
+#if PALM_STACK
+ lea_hack = 0;
+#endif // PALM_STACK
+#if PALM_PERF
+ if (curi->smode == Ad8r || curi->smode == PC8r)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("LEA {(d8,An,Xn)+,(d8,PC,Xn)} 12(2/0) \n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LEA (An) 4(1/0) {(d16,An), (xxx).W, (d16,PC)} 8(2/0) (xxx).L 12(3/0)\n");}
+#endif // PALM_PERF
+ break;
+ case i_PEA:
+ genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+ genamode (Apdi, "7", sz_long, "dst", 2, 0);
+ genastore ("srca", Apdi, "7", sz_long, "dst");
+#if PALM_PERF
+ if (curi->smode == Ad8r || curi->smode == PC8r)
+ {extraCycles += 1; readCycles += 1; writeCycles += 0; PERF_COMMENT("PEA(d8,An,Xn)+, (d8,PC,Xn) 20(2/2)\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("PEA (An) 12(1/2) {(d16,An), (xxx).W, (d16,PC)} 16(2/2) (xxx).L 20(3/2)\n");}
+#endif // PALM_PERF
+ break;
+ case i_DBcc:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
+
+ printf ("\tif (!cctrue(%d)) {\n", curi->cc);
+ genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src");
+
+ printf ("\t\tif (src) {\n");
+ if (using_exception_3) {
+ printf ("\t\t\tif (offs & 1) {\n");
+ printf ("\t\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
+ printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)offs + 2;\n");
+ printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0); goto %s;\n", endlabelstr);
+ printf ("\t\t}\n");
+ need_endlabel = 1;
+ }
+#ifdef USE_COMPILER
+ printf ("\t\t\tm68k_setpc_bcc(m68k_getpc() + (uae_s32)offs + 2);\n");
+#else
+ printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n");
+#endif
+ fill_prefetch_0 ();
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+ printf ("\t\tgoto %s;\n", endlabelstr);
+ printf ("\t\t}\n");
+ printf ("\t}\n");
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥Êstill missing a read cycle somewhere, when counter expires
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("DBcc 12(2/0) if cc, 10(2/0) if not -1, 14(3/0) if -1\n");}
+#endif // PALM_PERF
+ break;
+ case i_Scc:
+ genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+ start_brace ();
+ printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
+#if PALM_PERF
+ if (curi->smode <= Areg)
+ {
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2);\n");
+ printf ("#endif\n");
+ }
+#endif // PALM_PERF
+ genastore ("val", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->smode > Areg)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("Scc <M> 8(1/1)+\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("Scc Rn 4(1/0) if false, 6(1/0) if true\n");}
+#endif // PALM_PERF
+ break;
+ case i_DIVU:
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+ printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr);
+ printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
+ printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
+ /* The N flag appears to be set each time there is an overflow.
+ * Weird. */
+ printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
+ genflags (flag_logical, sz_word, "newv", "", "");
+ printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+ printf ("\t}\n");
+ printf ("\t}\n");
+ insn_n_cycles += 68;
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥ DOLATER less than 10% diff between best/worst times, this is worst
+ {extraCycles += 136; readCycles += 1; writeCycles += 0; PERF_COMMENT("DIVU 140(1/0)+*\n");}
+#endif // PALM_PERF
+ break;
+ case i_DIVS:
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+ printf ("\tif(src == 0) { Exception(5,oldpc); goto %s; } else {\n", endlabelstr);
+ printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
+ printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
+ printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
+ printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
+ genflags (flag_logical, sz_word, "newv", "", "");
+ printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+ printf ("\t}\n");
+ printf ("\t}\n");
+ insn_n_cycles += 72;
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥ DOLATER less than 10% diff between best/worst times, this is worst
+ {extraCycles += 154; readCycles += 1; writeCycles += 0; PERF_COMMENT("DIVS 158(1/0)+*\n");}
+#endif // PALM_PERF
+ break;
+ case i_MULU:
+ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
+ genflags (flag_logical, sz_long, "newv", "", "");
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+ insn_n_cycles += 32;
+#if PALM_PERF
+ // ¥¥¥ DOLATER 38+2n extra cycles, where n = number of 1s in the <ea>
+ {extraCycles += 66; readCycles += 1; writeCycles += 0; PERF_COMMENT("MULU 70(1/0)+*\n");}
+#endif // PALM_PERF
+ break;
+ case i_MULS:
+ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
+ start_brace ();
+ printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
+ genflags (flag_logical, sz_long, "newv", "", "");
+ genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+ insn_n_cycles += 32;
+#if PALM_PERF
+ // ¥¥¥ DOLATER 38+2n extra cycles, where n = number of 01 or 10 patterns in <ea>w/0 at end. $5555 is worst case
+ {extraCycles += 66; readCycles += 1; writeCycles += 0; PERF_COMMENT("MULS 70(1/0)+*\n");}
+#endif // PALM_PERF
+ break;
+ case i_CHK:
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr);
+ printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr);
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥ DOLATER handle extra work if exception happens
+ {extraCycles += 6; readCycles += 1; writeCycles += 0; PERF_COMMENT("CHK 10(1/0)+ if no trap, 40(4/3)+ if trap\n");}
+#endif // PALM_PERF
+ break;
+
+ case i_CHK2:
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+ printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
+ switch (curi->size) {
+ case sz_byte:
+ printf ("\tlower=(uae_s32)(uae_s8)get_byte(dsta); upper = (uae_s32)(uae_s8)get_byte(dsta+1);\n");
+ printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s8)reg;\n");
+ break;
+ case sz_word:
+ printf ("\tlower=(uae_s32)(uae_s16)get_word(dsta); upper = (uae_s32)(uae_s16)get_word(dsta+2);\n");
+ printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s16)reg;\n");
+ break;
+ case sz_long:
+ printf ("\tlower=get_long(dsta); upper = get_long(dsta+4);\n");
+ break;
+ default:
+ abort ();
+ }
+ printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
+ printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
+ printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr);
+ need_endlabel = 1;
+#if PALM_PERF
+ // ¥¥¥ DOLATER handle extra work if exception happens
+ {extraCycles += 6; readCycles += 1; writeCycles += 0; PERF_COMMENT("CHK2 10(1/0)+ if no trap, 40(4/3)+ if trap\n");}
+#endif // PALM_PERF
+ break;
+
+ case i_ASR:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+ printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
+ printf ("\t\tSET_CFLG (sign);\n");
+ duplicate_carry ();
+ if (source_is_imm1_8 (curi))
+ printf ("\t} else {\n");
+ else
+ printf ("\t} else if (cnt > 0) {\n");
+ printf ("\t\tval >>= cnt - 1;\n");
+ printf ("\t\tSET_CFLG (val & 1);\n");
+ duplicate_carry ();
+ printf ("\t\tval >>= 1;\n");
+ printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
+ bit_mask (curi->size),
+ bit_size (curi->size));
+ printf ("\t\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\t}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASR M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ASL:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+ printf ("\t\tSET_VFLG (val != 0);\n");
+ printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
+ bit_size (curi->size));
+ duplicate_carry ();
+ printf ("\t\tval = 0;\n");
+ if (source_is_imm1_8 (curi))
+ printf ("\t} else {\n");
+ else
+ printf ("\t} else if (cnt > 0) {\n");
+ printf ("\t\tuae_u32 mask = (%s << (%d - cnt)) & %s;\n",
+ bit_mask (curi->size),
+ bit_size (curi->size) - 1,
+ bit_mask (curi->size));
+ printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
+ printf ("\t\tval <<= cnt - 1;\n");
+ printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+ duplicate_carry ();
+ printf ("\t\tval <<= 1;\n");
+ printf ("\t\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\t}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASL M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_LSR:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+ printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
+ bit_size (curi->size), bit_size (curi->size) - 1);
+ duplicate_carry ();
+ printf ("\t\tval = 0;\n");
+ if (source_is_imm1_8 (curi))
+ printf ("\t} else {\n");
+ else
+ printf ("\t} else if (cnt > 0) {\n");
+ printf ("\t\tval >>= cnt - 1;\n");
+ printf ("\t\tSET_CFLG (val & 1);\n");
+ duplicate_carry ();
+ printf ("\t\tval >>= 1;\n");
+ printf ("\t}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSR M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_LSL:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+ printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
+ bit_size (curi->size));
+ duplicate_carry ();
+ printf ("\t\tval = 0;\n");
+ if (source_is_imm1_8 (curi))
+ printf ("\t} else {\n");
+ else
+ printf ("\t} else if (cnt > 0) {\n");
+ printf ("\t\tval <<= (cnt - 1);\n");
+ printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+ duplicate_carry ();
+ printf ("\t\tval <<= 1;\n");
+ printf ("\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\t}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSL M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROL:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ if (source_is_imm1_8 (curi))
+ printf ("{");
+ else
+ printf ("\tif (cnt > 0) {\n");
+ printf ("\tuae_u32 loval;\n");
+ printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
+ printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
+ printf ("\tval <<= cnt;\n");
+ printf ("\tval |= loval;\n");
+ printf ("\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\tSET_CFLG (val & 1);\n");
+ printf ("}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROL M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROR:
+#if PALM_CODEGEN_BUG
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 cmask = 0x80;\n"); break;
+ case sz_word: printf ("\tuae_u32 cmask = 0x8000;\n"); break;
+ case sz_long: printf ("\tuae_u32 cmask = 0x80000000;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tif (!cnt) { CFLG = 0; } else {");
+ printf ("\tuae_u32 carry;\n");
+ printf ("\tfor(;cnt;--cnt){\n");
+ printf ("\tcarry=val&1; val = val >> 1;\n");
+ printf ("\tif(carry) val |= cmask;\n");
+ printf ("\t}\n");
+ printf ("\tSET_CFLG (carry);\n}\n");
+ printf ("\tSET_NFLG ((val & cmask) != 0); SET_ZFLG (val == 0); SET_VFLG (0);\n");
+#else // PALM_CODEGEN_BUG -- Doing it this way runs afoul of a codegen bug in MWPPC 2.3.1 (in CW 5.2)
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ if (source_is_imm1_8 (curi))
+ printf ("{");
+ else
+ printf ("\tif (cnt > 0) {");
+ printf ("\tuae_u32 hival;\n");
+ printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
+ printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
+ printf ("\tval >>= cnt;\n");
+ printf ("\tval |= hival;\n");
+ printf ("\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+ printf ("\t}\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+#endif // PALM_CODEGEN_BUG
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROR M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROXL:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ if (! source_is_imm1_8 (curi))
+ force_range_for_rox ("cnt", curi->size);
+ if (source_is_imm1_8 (curi))
+ printf ("{");
+ else
+ printf ("\tif (cnt > 0) {\n");
+ printf ("\tcnt--;\n");
+ printf ("\t{\n\tuae_u32 carry;\n");
+ printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
+ printf ("\tcarry = loval & 1;\n");
+ printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n");
+ printf ("\tSET_XFLG (carry);\n");
+ printf ("\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\t} }\n");
+ printf ("\tSET_CFLG (GET_XFLG);\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXL 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXL M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROXR:
+ genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tcnt &= 63;\n");
+ printf ("\tCLEAR_CZNV;\n");
+ if (! source_is_imm1_8 (curi))
+ force_range_for_rox ("cnt", curi->size);
+ if (source_is_imm1_8 (curi))
+ printf ("{");
+ else
+ printf ("\tif (cnt > 0) {\n");
+ printf ("\tcnt--;\n");
+ printf ("\t{\n\tuae_u32 carry;\n");
+ printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n");
+ printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
+ printf ("\tval >>= cnt;\n");
+ printf ("\tcarry = val & 1;\n");
+ printf ("\tval >>= 1;\n");
+ printf ("\tval |= hival;\n");
+ printf ("\tSET_XFLG (carry);\n");
+ printf ("\tval &= %s;\n", bit_mask (curi->size));
+ printf ("\t} }\n");
+ printf ("\tSET_CFLG (GET_XFLG);\n");
+ genflags (flag_logical_noclobber, curi->size, "val", "", "");
+ genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+#if PALM_PERF
+ printf ("#if HAS_PROFILING\n");
+ printf (" if (gProfilingEnabled)\n");
+ printf (" ProfileIncrementClock(2*cnt);\n");
+ printf ("#endif\n");
+#endif // PALM_PERF
+#if PALM_PERF
+ if (curi->dmode < Areg)
+ if (curi->size <= sz_word)
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 4; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXR 6+2n(1/0), n=shifts\n");}
+ else
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXR M 8(1/1)\n");}
+#endif // PALM_PERF
+ break;
+ case i_ASRW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
+ printf ("\tuae_u32 cflg = val & 1;\n");
+ printf ("\tval = (val >> 1) | sign;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("\tSET_CFLG (cflg);\n");
+ duplicate_carry ();
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASR M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ASLW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
+ printf ("\tuae_u32 sign2;\n");
+ printf ("\tval <<= 1;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("\tsign2 = %s & val;\n", cmask (curi->size));
+ printf ("\tSET_CFLG (sign != 0);\n");
+ duplicate_carry ();
+
+ printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ASL M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_LSRW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
+ case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & 1;\n");
+ printf ("\tval >>= 1;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry);\n");
+ duplicate_carry ();
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSR M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_LSLW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
+ printf ("\tval <<= 1;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+ duplicate_carry ();
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("LSL M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROLW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
+ printf ("\tval <<= 1;\n");
+ printf ("\tif (carry) val |= 1;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROL M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_RORW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & 1;\n");
+ printf ("\tval >>= 1;\n");
+ printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry);\n");
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROR M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROXLW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
+ printf ("\tval <<= 1;\n");
+ printf ("\tif (GET_XFLG) val |= 1;\n");
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+ duplicate_carry ();
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXL M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_ROXRW:
+ genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+ start_brace ();
+ switch (curi->size) {
+ case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
+ case sz_word: printf ("\tuae_u16 val = data;\n"); break;
+ case sz_long: printf ("\tuae_u32 val = data;\n"); break;
+ default: abort ();
+ }
+ printf ("\tuae_u32 carry = val & 1;\n");
+ printf ("\tval >>= 1;\n");
+ printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size));
+ genflags (flag_logical, curi->size, "val", "", "");
+ printf ("SET_CFLG (carry);\n");
+ duplicate_carry ();
+ genastore ("val", curi->smode, "srcreg", curi->size, "data");
+#if PALM_PERF
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("ROXR M 8(1/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_MOVEC2:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ printf ("\tint regno = (src >> 12) & 15;\n");
+ printf ("\tuae_u32 *regp = regs.regs + regno;\n");
+ printf ("\tm68k_movec2(src & 0xFFF, regp);\n");
+ break;
+ case i_MOVE2C:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ start_brace ();
+ printf ("\tint regno = (src >> 12) & 15;\n");
+ printf ("\tuae_u32 *regp = regs.regs + regno;\n");
+ printf ("\tm68k_move2c(src & 0xFFF, regp);\n");
+ break;
+ case i_CAS:
+ {
+ int old_brace_level;
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ start_brace ();
+ printf ("\tint ru = (src >> 6) & 7;\n");
+ printf ("\tint rc = src & 7;\n");
+ genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst");
+ printf ("\tif (GET_ZFLG)");
+ old_brace_level = n_braces;
+ start_brace ();
+ genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
+ pop_braces (old_brace_level);
+ printf ("else");
+ start_brace ();
+ printf ("m68k_dreg(regs, rc) = dst;\n");
+ pop_braces (old_brace_level);
+ }
+ break;
+ case i_CAS2:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
+ printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
+ if (curi->size == sz_word) {
+ int old_brace_level = n_braces;
+ printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n");
+ genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
+ printf ("\tif (GET_ZFLG) {\n");
+ genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
+ printf ("\tif (GET_ZFLG) {\n");
+ printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
+ printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
+ printf ("\t}}\n");
+ pop_braces (old_brace_level);
+ printf ("\tif (! GET_ZFLG) {\n");
+ printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
+ printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
+ printf ("\t}\n");
+ } else {
+ int old_brace_level = n_braces;
+ printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n");
+ genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
+ printf ("\tif (GET_ZFLG) {\n");
+ genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
+ printf ("\tif (GET_ZFLG) {\n");
+ printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
+ printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
+ printf ("\t}}\n");
+ pop_braces (old_brace_level);
+ printf ("\tif (! GET_ZFLG) {\n");
+ printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n");
+ printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n");
+ printf ("\t}\n");
+ }
+ break;
+ case i_MOVES: /* ignore DFC and SFC because we have no MMU */
+ {
+ int old_brace_level;
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ printf ("\tif (extra & 0x800)\n");
+ old_brace_level = n_braces;
+ start_brace ();
+ printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+ genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+ pop_braces (old_brace_level);
+ printf ("else");
+ start_brace ();
+ genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0);
+ printf ("\tif (extra & 0x8000) {\n");
+ switch (curi->size) {
+ case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
+ case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
+ case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
+ default: abort ();
+ }
+ printf ("\t} else {\n");
+ genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
+ printf ("\t}\n");
+ pop_braces (old_brace_level);
+ }
+ break;
+ case i_BKPT: /* only needed for hardware emulators */
+ sync_m68k_pc ();
+ printf ("\top_illg(opcode);\n");
+ break;
+ case i_CALLM: /* not present in 68030 */
+ sync_m68k_pc ();
+ printf ("\top_illg(opcode);\n");
+ break;
+ case i_RTM: /* not present in 68030 */
+ sync_m68k_pc ();
+ printf ("\top_illg(opcode);\n");
+ break;
+ case i_TRAPcc:
+ if (curi->smode != am_unknown && curi->smode != am_illg)
+ genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
+ printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr);
+ need_endlabel = 1;
+ break;
+ case i_DIVL:
+ sync_m68k_pc ();
+ start_brace ();
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
+ break;
+ case i_MULL:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tm68k_mull(opcode, dst, extra);\n");
+ break;
+ case i_BFTST:
+ case i_BFEXTU:
+ case i_BFCHG:
+ case i_BFEXTS:
+ case i_BFCLR:
+ case i_BFFFO:
+ case i_BFSET:
+ case i_BFINS:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0);
+ start_brace ();
+ printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
+ printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
+ if (curi->dmode == Dreg) {
+ printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n");
+ } else {
+ printf ("\tuae_u32 tmp,bf0,bf1;\n");
+ printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n");
+ printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n");
+ printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n");
+ }
+ printf ("\ttmp >>= (32 - width);\n");
+ printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n");
+ printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
+ switch (curi->mnemo) {
+ case i_BFTST:
+ break;
+ case i_BFEXTU:
+ printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
+ break;
+ case i_BFCHG:
+ printf ("\ttmp = ~tmp;\n");
+ break;
+ case i_BFEXTS:
+ printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
+ printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
+ break;
+ case i_BFCLR:
+ printf ("\ttmp = 0;\n");
+ break;
+ case i_BFFFO:
+ printf ("\t{ uae_u32 mask = 1 << (width-1);\n");
+ printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset++; }}\n");
+ printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n");
+ break;
+ case i_BFSET:
+ printf ("\ttmp = 0xffffffff;\n");
+ break;
+ case i_BFINS:
+ printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n");
+ break;
+ default:
+ break;
+ }
+ if (curi->mnemo == i_BFCHG
+ || curi->mnemo == i_BFCLR
+ || curi->mnemo == i_BFSET
+ || curi->mnemo == i_BFINS)
+ {
+ printf ("\ttmp <<= (32 - width);\n");
+ if (curi->dmode == Dreg) {
+ printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n");
+ printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n");
+ printf ("\t\t(tmp >> (offset & 0x1f)) |\n");
+ printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n");
+ printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n");
+ } else {
+ printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n");
+ printf ("\t\t(tmp >> (offset & 7)) |\n");
+ printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n");
+ printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n");
+ printf ("\tput_long(dsta,bf0 );\n");
+ printf ("\tif (((offset & 7) + width) > 32) {\n");
+ printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n");
+ printf ("\t\t\t(tmp << (8 - (offset & 7)));\n");
+ printf ("\t\tput_byte(dsta+4,bf1);\n");
+ printf ("\t}\n");
+ }
+ }
+ break;
+ case i_PACK:
+ if (curi->smode == Dreg) {
+ printf ("\tuae_u16 val = m68k_dreg(regs, srcreg) + %s;\n", gen_nextiword ());
+ printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
+ } else {
+ printf ("\tuae_u16 val;\n");
+ printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+ printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
+ printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+ printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ());
+ printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+ printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n");
+ }
+ break;
+ case i_UNPK:
+ if (curi->smode == Dreg) {
+ printf ("\tuae_u16 val = m68k_dreg(regs, srcreg);\n");
+ printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
+ printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
+ } else {
+ printf ("\tuae_u16 val;\n");
+ printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+ printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
+ printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
+ printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+ printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n");
+ printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+ printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n");
+ }
+ break;
+ case i_TAS:
+ genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+ genflags (flag_logical, curi->size, "src", "", "");
+ printf ("\tsrc |= 0x80;\n");
+ genastore ("src", curi->smode, "srcreg", curi->size, "src");
+#if PALM_PERF
+ if (curi->smode <= Areg)
+ {extraCycles += 0; readCycles += 1; writeCycles += 0; PERF_COMMENT("TAS R 4(1/0)\n");}
+ else
+ {extraCycles += 2; readCycles += 1; writeCycles += 0; PERF_COMMENT("TAS M 14(2/1)+\n");}
+#endif // PALM_PERF
+ break;
+ case i_FPP:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tfpp_opp(opcode,extra);\n");
+ break;
+ case i_FDBcc:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tfdbcc_opp(opcode,extra);\n");
+ break;
+ case i_FScc:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tfscc_opp(opcode,extra);\n");
+ break;
+ case i_FTRAPcc:
+ sync_m68k_pc ();
+ start_brace ();
+ printf ("\tuaecptr oldpc = m68k_getpc();\n");
+ if (curi->smode != am_unknown && curi->smode != am_illg)
+ genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tftrapcc_opp(opcode,oldpc);\n");
+ break;
+ case i_FBcc:
+ sync_m68k_pc ();
+ start_brace ();
+ printf ("\tuaecptr pc = m68k_getpc();\n");
+ genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tfbcc_opp(opcode,pc,extra);\n");
+ break;
+ case i_FSAVE:
+ sync_m68k_pc ();
+ printf ("\tfsave_opp(opcode);\n");
+ break;
+ case i_FRESTORE:
+ sync_m68k_pc ();
+ printf ("\tfrestore_opp(opcode);\n");
+ break;
+ case i_MMUOP:
+ genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+ sync_m68k_pc ();
+ printf ("\tmmu_op(opcode,extra);\n");
+ break;
+ default:
+ abort ();
+ break;
+ }
+ finish_braces ();
+ sync_m68k_pc ();
+}
+
+static void generate_includes (FILE * f)
+{
+#if PALM_HEADERS
+ fprintf (f, "#include \"UAE.h\"\n");
+ fprintf (f, "#if HAS_PROFILING\n");
+ fprintf (f, "#include \"Profiling.h\"\n");
+ fprintf (f, "#endif\n");
+#else // PALM_HEADERS
+ fprintf (f, "#include \"sysconfig.h\"\n");
+ fprintf (f, "#include \"sysdeps.h\"\n");
+ fprintf (f, "#include \"config.h\"\n");
+ fprintf (f, "#include \"options.h\"\n");
+ fprintf (f, "#include \"memory.h\"\n");
+ fprintf (f, "#include \"custom.h\"\n");
+ fprintf (f, "#include \"readcpu.h\"\n");
+ fprintf (f, "#include \"newcpu.h\"\n");
+ fprintf (f, "#include \"compiler.h\"\n");
+ fprintf (f, "#include \"cputbl.h\"\n");
+#endif // PALM_HEADERS
+}
+
+static int postfix;
+
+static void generate_one_opcode (int rp)
+{
+ int i;
+ uae_u16 smsk, dmsk;
+ long int opcode = opcode_map[rp];
+
+ if (table68k[opcode].mnemo == i_ILLG
+ || table68k[opcode].clev > cpu_level)
+ return;
+
+ for (i = 0; lookuptab[i].name[0]; i++) {
+ if (table68k[opcode].mnemo == lookuptab[i].mnemo)
+ break;
+ }
+
+ if (table68k[opcode].handler != -1)
+ return;
+
+#if PALM_PERF
+ if (opcode_next_clev[rp] != cpu_level) {
+ fprintf (stblfile, "{ op_%lx_%d, 0, %ld, %d, %d, %d }, /* %s */\n", opcode, opcode_last_postfix[rp],
+ opcode, opcode_last_extra[rp], opcode_last_read[rp], opcode_last_write[rp], lookuptab[i].name);
+ return;
+ }
+#else // PALM_PERF
+ if (opcode_next_clev[rp] != cpu_level) {
+ fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp],
+ opcode, lookuptab[i].name);
+ return;
+ }
+ fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name);
+#endif // PALM_PERF
+ fprintf (headerfile, "extern cpuop_func op_%lx_%d;\n", opcode, postfix);
+ printf ("unsigned long REGPARAM2 op_%lx_%d(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name);
+
+ switch (table68k[opcode].stype) {
+ case 0: smsk = 7; break;
+ case 1: smsk = 255; break;
+ case 2: smsk = 15; break;
+ case 3: smsk = 7; break;
+ case 4: smsk = 7; break;
+ case 5: smsk = 63; break;
+ default: abort ();
+ }
+ dmsk = 7;
+
+ next_cpu_level = -1;
+ if (table68k[opcode].suse
+ && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
+ && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
+ && table68k[opcode].smode != absw && table68k[opcode].smode != absl
+ && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
+ {
+ if (table68k[opcode].spos == -1) {
+ if (((int) table68k[opcode].sreg) >= 128)
+ printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
+ else
+ printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
+ } else {
+ char source[100];
+ int pos = table68k[opcode].spos;
+
+#if 0
+ /* Check that we can do the little endian optimization safely. */
+ if (pos < 8 && (smsk >> (8 - pos)) != 0)
+ abort ();
+#endif
+ if (pos)
+ sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
+ else
+ sprintf (source, "(opcode & %d)", smsk);
+
+ if (table68k[opcode].stype == 3)
+ printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
+ else if (table68k[opcode].stype == 1)
+ printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
+ else
+ printf ("\tuae_u32 srcreg = %s;\n", source);
+ }
+ }
+ if (table68k[opcode].duse
+ /* Yes, the dmode can be imm, in case of LINK or DBcc */
+ && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
+ && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
+ && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
+ {
+ if (table68k[opcode].dpos == -1) {
+ if (((int) table68k[opcode].dreg) >= 128)
+ printf ("\tuae_u32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
+ else
+ printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
+ } else {
+ int pos = table68k[opcode].dpos;
+#if 0
+ /* Check that we can do the little endian optimization safely. */
+ if (pos < 8 && (dmsk >> (8 - pos)) != 0)
+ abort ();
+#endif
+ if (pos)
+ printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
+ pos, dmsk);
+ else
+ printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
+ }
+ }
+ need_endlabel = 0;
+ endlabelno++;
+ sprintf (endlabelstr, "endlabel%d", endlabelno);
+ gen_opcode (opcode);
+ if (need_endlabel)
+ printf ("%s: ;\n", endlabelstr);
+ printf ("return %d;\n", insn_n_cycles);
+ printf ("}\n");
+ opcode_next_clev[rp] = next_cpu_level;
+ opcode_last_postfix[rp] = postfix;
+#if PALM_PERF
+ opcode_last_extra[rp] = extraCycles;
+ opcode_last_read[rp] = readCycles;
+ opcode_last_write[rp] = writeCycles;
+ fprintf (stblfile, "{ op_%lx_%d, 0, %ld, %d, %d, %d }, /* %s */\n",
+ opcode, postfix, opcode, extraCycles,
+ readCycles, writeCycles, lookuptab[i].name);
+#endif // PALM_PERF
+}
+
+static void generate_func (void)
+{
+ int i, j, rp;
+
+ using_prefetch = 0;
+ using_exception_3 = 0;
+#if PALM_MIN
+ {
+ i = 3;
+ cpu_level = 0;
+ for (rp = 0; rp < nr_cpuop_funcs; rp++)
+ opcode_next_clev[rp] = 0;
+#else // PALM_MIN
+ for (i = 0; i < 5; i++) {
+ cpu_level = 3 - i;
+ if (i == 4) {
+ cpu_level = 0;
+ using_prefetch = 1;
+ using_exception_3 = 1;
+ for (rp = 0; rp < nr_cpuop_funcs; rp++)
+ opcode_next_clev[rp] = 0;
+ }
+#endif // PALM_MIN
+ postfix = i;
+ fprintf (stblfile, "struct cputbl op_smalltbl_%d[] = {\n", postfix);
+
+ /* sam: this is for people with low memory (eg. me :)) */
+ printf ("\n"
+ "#if !defined(PART_1) && !defined(PART_2) && "
+ "!defined(PART_3) && !defined(PART_4) && "
+ "!defined(PART_5) && !defined(PART_6) && "
+ "!defined(PART_7) && !defined(PART_8)"
+ "\n"
+ "#define PART_1 1\n"
+ "#define PART_2 1\n"
+ "#define PART_3 1\n"
+ "#define PART_4 1\n"
+ "#define PART_5 1\n"
+ "#define PART_6 1\n"
+ "#define PART_7 1\n"
+ "#define PART_8 1\n"
+ "#endif\n\n");
+
+ rp = 0;
+ for(j=1;j<=8;++j) {
+ int k = (j*nr_cpuop_funcs)/8;
+ printf ("#ifdef PART_%d\n",j);
+ for (; rp < k; rp++)
+ generate_one_opcode (rp);
+ printf ("#endif\n\n");
+ }
+
+ fprintf (stblfile, "{ 0, 0, 0 }};\n");
+ }
+
+}
+
+int main (int argc, char **argv)
+{
+ read_table68k ();
+ do_merges ();
+
+ opcode_map = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+ opcode_last_postfix = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+#if PALM_PERF
+ opcode_last_extra = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+ opcode_last_read = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+ opcode_last_write = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+#endif // PALM_PERF
+ opcode_next_clev = (int *) xmalloc (sizeof (int) * nr_cpuop_funcs);
+ counts = (unsigned long *) xmalloc (65536 * sizeof (unsigned long));
+ read_counts ();
+
+ /* It would be a lot nicer to put all in one file (we'd also get rid of
+ * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
+ * I don't dare to touch the 68k version. */
+
+ headerfile = fopen ("cputbl.h", "wb");
+ stblfile = fopen ("cpustbl.c", "wb");
+ freopen ("cpuemu.c", "wb", stdout);
+
+ generate_includes (stdout);
+ generate_includes (stblfile);
+
+ generate_func ();
+
+ free (table68k);
+ return 0;
+}
diff --git a/SrcShared/UAE/machdep_m68k.h b/SrcShared/UAE/machdep_m68k.h
new file mode 100644
index 0000000..15f740a
--- /dev/null
+++ b/SrcShared/UAE/machdep_m68k.h
@@ -0,0 +1,56 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * MC68000 emulation - machine dependent bits
+ *
+ * Copyright 1996 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct flag_struct {
+ unsigned int c;
+ unsigned int z;
+ unsigned int n;
+ unsigned int v;
+ unsigned int x;
+};
+
+extern struct flag_struct regflags;
+
+#define ZFLG (regflags.z)
+#define NFLG (regflags.n)
+#define CFLG (regflags.c)
+#define VFLG (regflags.v)
+#define XFLG (regflags.x)
+
+STATIC_INLINE int cctrue(const int cc)
+{
+ switch(cc){
+ case 0: return 1; /* T */
+ case 1: return 0; /* F */
+ case 2: return !CFLG && !ZFLG; /* HI */
+ case 3: return CFLG || ZFLG; /* LS */
+ case 4: return !CFLG; /* CC */
+ case 5: return CFLG; /* CS */
+ case 6: return !ZFLG; /* NE */
+ case 7: return ZFLG; /* EQ */
+ case 8: return !VFLG; /* VC */
+ case 9: return VFLG; /* VS */
+ case 10:return !NFLG; /* PL */
+ case 11:return NFLG; /* MI */
+ case 12:return NFLG == VFLG; /* GE */
+ case 13:return NFLG != VFLG; /* LT */
+ case 14:return !ZFLG && (NFLG == VFLG); /* GT */
+ case 15:return ZFLG || (NFLG != VFLG); /* LE */
+ }
+ abort();
+ return 0;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/SrcShared/UAE/machdep_maccess.h b/SrcShared/UAE/machdep_maccess.h
new file mode 100644
index 0000000..928abee
--- /dev/null
+++ b/SrcShared/UAE/machdep_maccess.h
@@ -0,0 +1,27 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Memory access functions
+ *
+ * Copyright 1996 Bernd Schmidt
+ */
+
+#include "EmMemory.h"
+
+#define do_get_mem_long EmMemDoGet32
+#define do_get_mem_word EmMemDoGet16
+#define do_get_mem_byte EmMemDoGet8
+
+#define do_put_mem_long EmMemDoPut32
+#define do_put_mem_word EmMemDoPut16
+#define do_put_mem_byte EmMemDoPut8
+
+#define get_long EmMemGet32
+#define get_word EmMemGet16
+#define get_byte EmMemGet8
+
+#define put_long EmMemPut32
+#define put_word EmMemPut16
+#define put_byte EmMemPut8
+
+#define get_real_address EmMemGetRealAddress
diff --git a/SrcShared/UAE/memory_cpu.h b/SrcShared/UAE/memory_cpu.h
new file mode 100644
index 0000000..af2137e
--- /dev/null
+++ b/SrcShared/UAE/memory_cpu.h
@@ -0,0 +1,13 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * memory management
+ *
+ * Copyright 1995 Bernd Schmidt
+ */
+
+#include "machdep_maccess.h"
+
+typedef EmAddressBank addrbank;
+
+#define get_mem_bank EmMemGetBank
diff --git a/SrcShared/UAE/missing.c b/SrcShared/UAE/missing.c
new file mode 100644
index 0000000..9ebe4a5
--- /dev/null
+++ b/SrcShared/UAE/missing.c
@@ -0,0 +1,36 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Various stuff missing in some OSes.
+ *
+ * Copyright 1997 Bernd Schmidt
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "config.h"
+#include "options.h"
+//#include "uae.h"
+
+#ifndef HAVE_STRDUP
+
+char *my_strdup (const char *s)
+{
+ /* The casts to char * are there to shut up the compiler on HPUX */
+ char *x = (char*)xmalloc(strlen((char *)s) + 1);
+ strcpy(x, (char *)s);
+ return x;
+}
+
+#endif
+
+void *xmalloc(size_t n)
+{
+ void *a = malloc (n);
+ if (a == NULL) {
+ fprintf (stderr, "virtual memory exhausted\n");
+ abort ();
+ }
+ return a;
+}
diff --git a/SrcShared/UAE/newcpu.h b/SrcShared/UAE/newcpu.h
new file mode 100644
index 0000000..25f8836
--- /dev/null
+++ b/SrcShared/UAE/newcpu.h
@@ -0,0 +1,230 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * MC68000 emulation
+ *
+ * Copyright 1995 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if HAS_PROFILING
+#include "Profiling.h"
+#endif
+
+//#include <machdep/m68k.h>
+
+#ifndef SET_CFLG
+
+#define SET_CFLG(x) (CFLG = (x))
+#define SET_NFLG(x) (NFLG = (x))
+#define SET_VFLG(x) (VFLG = (x))
+#define SET_ZFLG(x) (ZFLG = (x))
+#define SET_XFLG(x) (XFLG = (x))
+
+#define GET_CFLG CFLG
+#define GET_NFLG NFLG
+#define GET_VFLG VFLG
+#define GET_ZFLG ZFLG
+#define GET_XFLG XFLG
+
+#define CLEAR_CZNV do { \
+ SET_CFLG (0); \
+ SET_ZFLG (0); \
+ SET_NFLG (0); \
+ SET_VFLG (0); \
+} while (0)
+
+#define COPY_CARRY (SET_XFLG (GET_CFLG))
+#endif
+
+extern int areg_byteinc[];
+extern int imm8_table[];
+
+extern int movem_index1[256];
+extern int movem_index2[256];
+extern int movem_next[256];
+
+extern int fpp_movem_index1[256];
+extern int fpp_movem_index2[256];
+extern int fpp_movem_next[256];
+
+extern int broken_in;
+
+typedef unsigned long cpuop_func (uae_u32) REGPARAM;
+
+struct cputbl {
+ cpuop_func *handler;
+ int specific;
+ uae_u16 opcode;
+ struct perfRec perf;
+};
+
+extern unsigned long op_illg (uae_u32) REGPARAM;
+
+typedef char flagtype;
+
+typedef struct regstruct
+{
+ uae_u32 regs[16];
+ uaecptr usp,isp,msp;
+ uae_u16 sr;
+ flagtype t1;
+ flagtype t0;
+ flagtype s;
+ flagtype m;
+ flagtype x;
+ flagtype stopped;
+ int intmask;
+
+ uae_u32 pc;
+ uae_u8 *pc_p;
+ uae_u8 *pc_oldp;
+
+ uae_u8 *pc_meta_oldp;
+
+ uae_u32 vbr,sfc,dfc;
+
+ double fp[8];
+ uae_u32 fpcr,fpsr,fpiar;
+
+ uae_u32 spcflags;
+ uae_u32 kick_mask;
+
+ /* Fellow sources say this is 4 longwords. That's impossible. It needs
+ * to be at least a longword. The HRM has some cryptic comment about two
+ * instructions being on the same longword boundary.
+ * The way this is implemented now seems like a good compromise.
+ */
+ uae_u32 prefetch;
+} regstruct;
+
+#ifndef __ECM_DYNAMIC_PATCH
+
+extern regstruct regs;
+extern regstruct lastint_regs;
+
+#define gRegs regs
+#define gLastint_regs lastint_regs
+
+#else //__ECM_DYNAMIC_PATCH
+
+extern regstruct *gDynRegsP;
+
+#define gRegs (*gDynRegsP)
+
+#endif //__ECM_DYNAMIC_PATCH
+
+
+
+#define m68k_dreg(r,num) ((r).regs[(num)])
+#define m68k_areg(r,num) (((r).regs + 8)[(num)])
+
+ // If we're profiling, go through the real work so we can count
+ // read cycles. Note that we don't want to actually return the
+ // value returned by get_foo. That function doesn't always word-
+ // swap on little-endian machines (e.g., the DummyBank function).
+ // However, the rest of the emulator is positioned to always
+ // expect that opcode should be word-swapped on little-endian
+ // machines (e.g., ATrap::DoCall). Therefore, always fetch opcodes
+ // with do_get_mem_foo, which will do that swapping.
+
+#if HAS_PROFILING
+
+ #define M68K_GETPC() (regs.pc+((char*)regs.pc_p-(char*)regs.pc_oldp))
+
+ STATIC_INLINE uae_u8 get_ibyte (uae_s32 o) {
+ if (gProfilingEnabled) get_byte(M68K_GETPC());
+ return do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1)); }
+
+ STATIC_INLINE uae_u16 get_iword (uae_s32 o) {
+ if (gProfilingEnabled) get_word(M68K_GETPC());
+ return do_get_mem_word((uae_u16 *)(regs.pc_p + (o))); }
+
+ STATIC_INLINE uae_u32 get_ilong (uae_s32 o) {
+ if (gProfilingEnabled) get_long(M68K_GETPC());
+ return do_get_mem_long((uae_u32 *)(regs.pc_p + (o))); }
+
+#else
+
+ #define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
+ #define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
+ #define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
+
+#endif
+
+
+#define m68k_incpc(o) (regs.pc_p += (o))
+
+extern void Software_CheckNewPC (uaecptr newPC);
+
+STATIC_INLINE void m68k_setpc (uaecptr newpc)
+{
+ Software_CheckNewPC (newpc);
+
+ {
+ addrbank* bank = &(get_mem_bank(newpc));
+ regs.pc_p = regs.pc_oldp = (bank->xlateaddr)(newpc);
+ regs.pc = newpc;
+ regs.pc_meta_oldp = (bank->xlatemetaaddr)(newpc);
+ }
+}
+
+STATIC_INLINE uaecptr m68k_getpc (void)
+{
+ return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
+}
+
+STATIC_INLINE uaecptr m68k_getpc_p (uae_u8 *p)
+{
+ return regs.pc + ((char *)p - (char *)regs.pc_oldp);
+}
+
+#define m68k_setpc_fast m68k_setpc
+#define m68k_setpc_bcc m68k_setpc
+#define m68k_setpc_rte m68k_setpc
+
+STATIC_INLINE void m68k_setstopped (int stop)
+{
+ regs.stopped = stop;
+ if (stop)
+ regs.spcflags |= SPCFLAG_STOP;
+}
+
+extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
+extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
+
+extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
+
+extern void MakeSR (void);
+extern void MakeFromSR (void);
+extern void Exception (int, uaecptr);
+
+/* Opcode of faulting instruction */
+extern uae_u16 last_op_for_exception_3;
+/* PC at fault time */
+extern uaecptr last_addr_for_exception_3;
+/* Address that generated the exception */
+extern uaecptr last_fault_for_exception_3;
+
+#define CPU_OP_NAME(a) op ## a
+
+/* 68020 + 68881 */
+extern struct cputbl op_smalltbl_0[];
+/* 68020 */
+extern struct cputbl op_smalltbl_1[];
+/* 68010 */
+extern struct cputbl op_smalltbl_2[];
+/* 68000 */
+extern struct cputbl op_smalltbl_3[];
+/* 68000 slow but compatible. */
+extern struct cputbl op_smalltbl_4[];
+
+extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl");
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/SrcShared/UAE/options.h b/SrcShared/UAE/options.h
new file mode 100644
index 0000000..be229fc
--- /dev/null
+++ b/SrcShared/UAE/options.h
@@ -0,0 +1,30 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Stuff
+ *
+ * Copyright 1995, 1996 Ed Hanway
+ * Copyright 1995-98 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UAEMAJOR 0
+#define UAEMINOR 8
+#define UAESUBREV 10
+
+
+/*
+ * You can specify numbers from 0 to 5 here. It is possible that higher
+ * numbers will make the CPU emulation slightly faster, but if the setting
+ * is too high, you will run out of memory while compiling.
+ * Best to leave this as it is.
+ */
+#define CPU_EMU_SIZE 0
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/SrcShared/UAE/readcpu.cpp b/SrcShared/UAE/readcpu.cpp
new file mode 100644
index 0000000..45949a4
--- /dev/null
+++ b/SrcShared/UAE/readcpu.cpp
@@ -0,0 +1,808 @@
+/*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Read 68000 CPU specs from file "table68k"
+ *
+ * Copyright 1995,1996 Bernd Schmidt
+ */
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+#include <ctype.h>
+
+#include "config.h"
+#include "options.h"
+#include "readcpu.h"
+
+int nr_cpuop_funcs;
+
+struct mnemolookup lookuptab[] = {
+ { i_ILLG, "ILLEGAL" },
+ { i_OR, "OR" },
+ { i_CHK, "CHK" },
+ { i_CHK2, "CHK2" },
+ { i_AND, "AND" },
+ { i_EOR, "EOR" },
+ { i_ORSR, "ORSR" },
+ { i_ANDSR, "ANDSR" },
+ { i_EORSR, "EORSR" },
+ { i_SUB, "SUB" },
+ { i_SUBA, "SUBA" },
+ { i_SUBX, "SUBX" },
+ { i_SBCD, "SBCD" },
+ { i_ADD, "ADD" },
+ { i_ADDA, "ADDA" },
+ { i_ADDX, "ADDX" },
+ { i_ABCD, "ABCD" },
+ { i_NEG, "NEG" },
+ { i_NEGX, "NEGX" },
+ { i_NBCD, "NBCD" },
+ { i_CLR, "CLR" },
+ { i_NOT, "NOT" },
+ { i_TST, "TST" },
+ { i_BTST, "BTST" },
+ { i_BCHG, "BCHG" },
+ { i_BCLR, "BCLR" },
+ { i_BSET, "BSET" },
+ { i_CMP, "CMP" },
+ { i_CMPM, "CMPM" },
+ { i_CMPA, "CMPA" },
+ { i_MVPRM, "MVPRM" },
+ { i_MVPMR, "MVPMR" },
+ { i_MOVE, "MOVE" },
+ { i_MOVEA, "MOVEA" },
+ { i_MVSR2, "MVSR2" },
+ { i_MV2SR, "MV2SR" },
+ { i_SWAP, "SWAP" },
+ { i_EXG, "EXG" },
+ { i_EXT, "EXT" },
+ { i_MVMEL, "MVMEL" },
+ { i_MVMLE, "MVMLE" },
+ { i_TRAP, "TRAP" },
+ { i_MVR2USP, "MVR2USP" },
+ { i_MVUSP2R, "MVUSP2R" },
+ { i_NOP, "NOP" },
+ { i_RESET, "RESET" },
+ { i_RTE, "RTE" },
+ { i_RTD, "RTD" },
+ { i_LINK, "LINK" },
+ { i_UNLK, "UNLK" },
+ { i_RTS, "RTS" },
+ { i_STOP, "STOP" },
+ { i_TRAPV, "TRAPV" },
+ { i_RTR, "RTR" },
+ { i_JSR, "JSR" },
+ { i_JMP, "JMP" },
+ { i_BSR, "BSR" },
+ { i_Bcc, "Bcc" },
+ { i_LEA, "LEA" },
+ { i_PEA, "PEA" },
+ { i_DBcc, "DBcc" },
+ { i_Scc, "Scc" },
+ { i_DIVU, "DIVU" },
+ { i_DIVS, "DIVS" },
+ { i_MULU, "MULU" },
+ { i_MULS, "MULS" },
+ { i_ASR, "ASR" },
+ { i_ASL, "ASL" },
+ { i_LSR, "LSR" },
+ { i_LSL, "LSL" },
+ { i_ROL, "ROL" },
+ { i_ROR, "ROR" },
+ { i_ROXL, "ROXL" },
+ { i_ROXR, "ROXR" },
+ { i_ASRW, "ASRW" },
+ { i_ASLW, "ASLW" },
+ { i_LSRW, "LSRW" },
+ { i_LSLW, "LSLW" },
+ { i_ROLW, "ROLW" },
+ { i_RORW, "RORW" },
+ { i_ROXLW, "ROXLW" },
+ { i_ROXRW, "ROXRW" },
+
+ { i_MOVE2C, "MOVE2C" },
+ { i_MOVEC2, "MOVEC2" },
+ { i_CAS, "CAS" },
+ { i_CAS2, "CAS2" },
+ { i_MULL, "MULL" },
+ { i_DIVL, "DIVL" },
+ { i_BFTST, "BFTST" },
+ { i_BFEXTU, "BFEXTU" },
+ { i_BFCHG, "BFCHG" },
+ { i_BFEXTS, "BFEXTS" },
+ { i_BFCLR, "BFCLR" },
+ { i_BFFFO, "BFFFO" },
+ { i_BFSET, "BFSET" },
+ { i_BFINS, "BFINS" },
+ { i_PACK, "PACK" },
+ { i_UNPK, "UNPK" },
+ { i_TAS, "TAS" },
+ { i_BKPT, "BKPT" },
+ { i_CALLM, "CALLM" },
+ { i_RTM, "RTM" },
+ { i_TRAPcc, "TRAPcc" },
+ { i_MOVES, "MOVES" },
+ { i_FPP, "FPP" },
+ { i_FDBcc, "FDBcc" },
+ { i_FScc, "FScc" },
+ { i_FTRAPcc, "FTRAPcc" },
+ { i_FBcc, "FBcc" },
+ { i_FBcc, "FBcc" },
+ { i_FSAVE, "FSAVE" },
+ { i_FRESTORE, "FRESTORE" },
+ { i_MMUOP, "MMUOP" },
+ { i_ILLG, "" },
+};
+
+struct instr *table68k;
+
+STATIC_INLINE amodes mode_from_str (const char *str)
+{
+ if (strncmp (str, "Dreg", 4) == 0) return Dreg;
+ if (strncmp (str, "Areg", 4) == 0) return Areg;
+ if (strncmp (str, "Aind", 4) == 0) return Aind;
+ if (strncmp (str, "Apdi", 4) == 0) return Apdi;
+ if (strncmp (str, "Aipi", 4) == 0) return Aipi;
+ if (strncmp (str, "Ad16", 4) == 0) return Ad16;
+ if (strncmp (str, "Ad8r", 4) == 0) return Ad8r;
+ if (strncmp (str, "absw", 4) == 0) return absw;
+ if (strncmp (str, "absl", 4) == 0) return absl;
+ if (strncmp (str, "PC16", 4) == 0) return PC16;
+ if (strncmp (str, "PC8r", 4) == 0) return PC8r;
+ if (strncmp (str, "Immd", 4) == 0) return imm;
+ abort ();
+ return ((amodes) 0);
+}
+
+STATIC_INLINE amodes mode_from_mr (int mode, int reg)
+{
+ switch (mode) {
+ case 0: return Dreg;
+ case 1: return Areg;
+ case 2: return Aind;
+ case 3: return Aipi;
+ case 4: return Apdi;
+ case 5: return Ad16;
+ case 6: return Ad8r;
+ case 7:
+ switch (reg) {
+ case 0: return absw;
+ case 1: return absl;
+ case 2: return PC16;
+ case 3: return PC8r;
+ case 4: return imm;
+ case 5:
+ case 6:
+ case 7: return am_illg;
+ }
+ }
+ abort ();
+ return ((amodes) 0);
+}
+
+static void build_insn (int insn)
+{
+ int find = -1;
+ int variants;
+ struct instr_def id;
+ const char *opcstr;
+ int i;
+
+ int flaglive = 0, flagdead = 0;
+
+ id = defs68k[insn];
+
+ for (i = 0; i < 5; i++) {
+ switch (id.flaginfo[i].flagset){
+ case fa_unset: break;
+ case fa_isjmp: break;
+ case fa_zero: flagdead |= 1 << i; break;
+ case fa_one: flagdead |= 1 << i; break;
+ case fa_dontcare: flagdead |= 1 << i; break;
+ case fa_unknown: flagdead = -1; goto out1;
+ case fa_set: flagdead |= 1 << i; break;
+ }
+ }
+
+ out1:
+ for (i = 0; i < 5; i++) {
+ switch (id.flaginfo[i].flaguse) {
+ case fu_unused: break;
+ case fu_isjmp: flaglive |= 1 << i; break;
+ case fu_maybecc: flaglive |= 1 << i; break;
+ case fu_unknown: flaglive = -1; goto out2;
+ case fu_used: flaglive |= 1 << i; break;
+ }
+ }
+ out2:
+
+ opcstr = id.opcstr;
+ for (variants = 0; variants < (1 << id.n_variable); variants++) {
+ int bitcnt[lastbit];
+ int bitval[lastbit];
+ int bitpos[lastbit];
+ int i;
+ uae_u16 opc = id.bits;
+ uae_u16 msk, vmsk;
+ int pos = 0;
+ int mnp = 0;
+ int bitno = 0;
+ char mnemonic[10];
+
+ wordsizes sz = sz_long;
+ int srcgather = 0, dstgather = 0;
+ int usesrc = 0, usedst = 0;
+ int srctype = 0;
+ int srcpos = -1, dstpos = -1;
+
+ amodes srcmode = am_unknown, destmode = am_unknown;
+ int srcreg = -1, destreg = -1;
+
+ for (i = 0; i < lastbit; i++)
+ bitcnt[i] = bitval[i] = 0;
+
+ vmsk = 1 << id.n_variable;
+
+ for (i = 0, msk = 0x8000; i < 16; i++, msk >>= 1) {
+ if (!(msk & id.mask)) {
+ int currbit = id.bitpos[bitno++];
+ int bit_set;
+ vmsk >>= 1;
+ bit_set = variants & vmsk ? 1 : 0;
+ if (bit_set)
+ opc |= msk;
+ bitpos[currbit] = 15 - i;
+ bitcnt[currbit]++;
+ bitval[currbit] <<= 1;
+ bitval[currbit] |= bit_set;
+ }
+ }
+
+ if (bitval[bitj] == 0) bitval[bitj] = 8;
+ /* first check whether this one does not match after all */
+ if (bitval[bitz] == 3 || bitval[bitC] == 1)
+ continue;
+ if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
+ continue;
+
+ /* bitI and bitC get copied to biti and bitc */
+ if (bitcnt[bitI]) {
+ bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
+ }
+ if (bitcnt[bitC])
+ bitval[bitc] = bitval[bitC];
+
+ pos = 0;
+ while (opcstr[pos] && !isspace(opcstr[pos])) {
+ if (opcstr[pos] == '.') {
+ pos++;
+ switch (opcstr[pos]) {
+
+ case 'B': sz = sz_byte; break;
+ case 'W': sz = sz_word; break;
+ case 'L': sz = sz_long; break;
+ case 'z':
+ switch (bitval[bitz]) {
+ case 0: sz = sz_byte; break;
+ case 1: sz = sz_word; break;
+ case 2: sz = sz_long; break;
+ default: abort();
+ }
+ break;
+ default: abort();
+ }
+ } else {
+ mnemonic[mnp] = opcstr[pos];
+ if (mnemonic[mnp] == 'f') {
+ find = -1;
+ switch (bitval[bitf]) {
+ case 0: mnemonic[mnp] = 'R'; break;
+ case 1: mnemonic[mnp] = 'L'; break;
+ default: abort();
+ }
+ }
+ mnp++;
+ }
+ pos++;
+ }
+ mnemonic[mnp] = 0;
+
+ /* now, we have read the mnemonic and the size */
+ while (opcstr[pos] && isspace(opcstr[pos]))
+ pos++;
+
+ /* A goto a day keeps the D******a away. */
+ if (opcstr[pos] == 0)
+ goto endofline;
+
+ /* parse the source address */
+ usesrc = 1;
+ switch (opcstr[pos++]) {
+ case 'D':
+ srcmode = Dreg;
+ switch (opcstr[pos++]) {
+ case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
+ case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
+ default: abort();
+ }
+
+ break;
+ case 'A':
+ srcmode = Areg;
+ switch (opcstr[pos++]) {
+ case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
+ case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
+ default: abort();
+ }
+ switch (opcstr[pos]) {
+ case 'p': srcmode = Apdi; pos++; break;
+ case 'P': srcmode = Aipi; pos++; break;
+ }
+ break;
+ case '#':
+ switch (opcstr[pos++]) {
+ case 'z': srcmode = imm; break;
+ case '0': srcmode = imm0; break;
+ case '1': srcmode = imm1; break;
+ case '2': srcmode = imm2; break;
+ case 'i': srcmode = immi; srcreg = (uae_s32)(uae_s8)bitval[biti];
+ if (CPU_EMU_SIZE < 4) {
+ /* Used for branch instructions */
+ srctype = 1;
+ srcgather = 1;
+ srcpos = bitpos[biti];
+ }
+ break;
+ case 'j': srcmode = immi; srcreg = bitval[bitj];
+ if (CPU_EMU_SIZE < 3) {
+ /* 1..8 for ADDQ/SUBQ and rotshi insns */
+ srcgather = 1;
+ srctype = 3;
+ srcpos = bitpos[bitj];
+ }
+ break;
+ case 'J': srcmode = immi; srcreg = bitval[bitJ];
+ if (CPU_EMU_SIZE < 5) {
+ /* 0..15 */
+ srcgather = 1;
+ srctype = 2;
+ srcpos = bitpos[bitJ];
+ }
+ break;
+ case 'k': srcmode = immi; srcreg = bitval[bitk];
+ if (CPU_EMU_SIZE < 3) {
+ srcgather = 1;
+ srctype = 4;
+ srcpos = bitpos[bitk];
+ }
+ break;
+ case 'K': srcmode = immi; srcreg = bitval[bitK];
+ if (CPU_EMU_SIZE < 5) {
+ /* 0..15 */
+ srcgather = 1;
+ srctype = 5;
+ srcpos = bitpos[bitK];
+ }
+ break;
+ default: abort();
+ }
+ break;
+ case 'd':
+ srcreg = bitval[bitD];
+ srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
+ if (srcmode == am_illg)
+ continue;
+ if (CPU_EMU_SIZE < 2 &&
+ (srcmode == Areg || srcmode == Dreg || srcmode == Aind
+ || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
+ || srcmode == Apdi))
+ {
+ srcgather = 1; srcpos = bitpos[bitD];
+ }
+ if (opcstr[pos] == '[') {
+ pos++;
+ if (opcstr[pos] == '!') {
+ /* exclusion */
+ do {
+ pos++;
+ if (mode_from_str(opcstr+pos) == srcmode)
+ goto nomatch;
+ pos += 4;
+ } while (opcstr[pos] == ',');
+ pos++;
+ } else {
+ if (opcstr[pos+4] == '-') {
+ /* replacement */
+ if (mode_from_str(opcstr+pos) == srcmode)
+ srcmode = mode_from_str(opcstr+pos+5);
+ else
+ goto nomatch;
+ pos += 10;
+ } else {
+ /* normal */
+ while(mode_from_str(opcstr+pos) != srcmode) {
+ pos += 4;
+ if (opcstr[pos] == ']')
+ goto nomatch;
+ pos++;
+ }
+ while(opcstr[pos] != ']') pos++;
+ pos++;
+ break;
+ }
+ }
+ }
+ /* Some addressing modes are invalid as destination */
+ if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
+ goto nomatch;
+ break;
+ case 's':
+ srcreg = bitval[bitS];
+ srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
+
+ if (srcmode == am_illg)
+ continue;
+ if (CPU_EMU_SIZE < 2 &&
+ (srcmode == Areg || srcmode == Dreg || srcmode == Aind
+ || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
+ || srcmode == Apdi))
+ {
+ srcgather = 1; srcpos = bitpos[bitS];
+ }
+ if (opcstr[pos] == '[') {
+ pos++;
+ if (opcstr[pos] == '!') {
+ /* exclusion */
+ do {
+ pos++;
+ if (mode_from_str(opcstr+pos) == srcmode)
+ goto nomatch;
+ pos += 4;
+ } while (opcstr[pos] == ',');
+ pos++;
+ } else {
+ if (opcstr[pos+4] == '-') {
+ /* replacement */
+ if (mode_from_str(opcstr+pos) == srcmode)
+ srcmode = mode_from_str(opcstr+pos+5);
+ else
+ goto nomatch;
+ pos += 10;
+ } else {
+ /* normal */
+ while(mode_from_str(opcstr+pos) != srcmode) {
+ pos += 4;
+ if (opcstr[pos] == ']')
+ goto nomatch;
+ pos++;
+ }
+ while(opcstr[pos] != ']') pos++;
+ pos++;
+ }
+ }
+ }
+ break;
+ default: abort();
+ }
+ /* safety check - might have changed */
+ if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
+ && srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi
+ && srcmode != Apdi && srcmode != immi)
+ {
+ srcgather = 0;
+ }
+ if (srcmode == Areg && sz == sz_byte)
+ goto nomatch;
+
+ if (opcstr[pos] != ',')
+ goto endofline;
+ pos++;
+
+ /* parse the destination address */
+ usedst = 1;
+ switch (opcstr[pos++]) {
+ case 'D':
+ destmode = Dreg;
+ switch (opcstr[pos++]) {
+ case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
+ case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
+ default: abort();
+ }
+ break;
+ case 'A':
+ destmode = Areg;
+ switch (opcstr[pos++]) {
+ case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
+ case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
+ default: abort();
+ }
+ switch (opcstr[pos]) {
+ case 'p': destmode = Apdi; pos++; break;
+ case 'P': destmode = Aipi; pos++; break;
+ }
+ break;
+ case '#':
+ switch (opcstr[pos++]) {
+ case 'z': destmode = imm; break;
+ case '0': destmode = imm0; break;
+ case '1': destmode = imm1; break;
+ case '2': destmode = imm2; break;
+ case 'i': destmode = immi; destreg = (uae_s32)(uae_s8)bitval[biti]; break;
+ case 'j': destmode = immi; destreg = bitval[bitj]; break;
+ case 'J': destmode = immi; destreg = bitval[bitJ]; break;
+ case 'k': destmode = immi; destreg = bitval[bitk]; break;
+ case 'K': destmode = immi; destreg = bitval[bitK]; break;
+ default: abort();
+ }
+ break;
+ case 'd':
+ destreg = bitval[bitD];
+ destmode = mode_from_mr(bitval[bitd],bitval[bitD]);
+ if (destmode == am_illg)
+ continue;
+ if (CPU_EMU_SIZE < 1 &&
+ (destmode == Areg || destmode == Dreg || destmode == Aind
+ || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
+ || destmode == Apdi))
+ {
+ dstgather = 1; dstpos = bitpos[bitD];
+ }
+
+ if (opcstr[pos] == '[') {
+ pos++;
+ if (opcstr[pos] == '!') {
+ /* exclusion */
+ do {
+ pos++;
+ if (mode_from_str(opcstr+pos) == destmode)
+ goto nomatch;
+ pos += 4;
+ } while (opcstr[pos] == ',');
+ pos++;
+ } else {
+ if (opcstr[pos+4] == '-') {
+ /* replacement */
+ if (mode_from_str(opcstr+pos) == destmode)
+ destmode = mode_from_str(opcstr+pos+5);
+ else
+ goto nomatch;
+ pos += 10;
+ } else {
+ /* normal */
+ while(mode_from_str(opcstr+pos) != destmode) {
+ pos += 4;
+ if (opcstr[pos] == ']')
+ goto nomatch;
+ pos++;
+ }
+ while(opcstr[pos] != ']') pos++;
+ pos++;
+ break;
+ }
+ }
+ }
+ /* Some addressing modes are invalid as destination */
+ if (destmode == imm || destmode == PC16 || destmode == PC8r)
+ goto nomatch;
+ break;
+ case 's':
+ destreg = bitval[bitS];
+ destmode = mode_from_mr(bitval[bits],bitval[bitS]);
+
+ if (destmode == am_illg)
+ continue;
+ if (CPU_EMU_SIZE < 1 &&
+ (destmode == Areg || destmode == Dreg || destmode == Aind
+ || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
+ || destmode == Apdi))
+ {
+ dstgather = 1; dstpos = bitpos[bitS];
+ }
+
+ if (opcstr[pos] == '[') {
+ pos++;
+ if (opcstr[pos] == '!') {
+ /* exclusion */
+ do {
+ pos++;
+ if (mode_from_str(opcstr+pos) == destmode)
+ goto nomatch;
+ pos += 4;
+ } while (opcstr[pos] == ',');
+ pos++;
+ } else {
+ if (opcstr[pos+4] == '-') {
+ /* replacement */
+ if (mode_from_str(opcstr+pos) == destmode)
+ destmode = mode_from_str(opcstr+pos+5);
+ else
+ goto nomatch;
+ pos += 10;
+ } else {
+ /* normal */
+ while(mode_from_str(opcstr+pos) != destmode) {
+ pos += 4;
+ if (opcstr[pos] == ']')
+ goto nomatch;
+ pos++;
+ }
+ while(opcstr[pos] != ']') pos++;
+ pos++;
+ }
+ }
+ }
+ break;
+ default: abort();
+ }
+ /* safety check - might have changed */
+ if (destmode != Areg && destmode != Dreg && destmode != Aind
+ && destmode != Ad16 && destmode != Ad8r && destmode != Aipi
+ && destmode != Apdi)
+ {
+ dstgather = 0;
+ }
+
+ if (destmode == Areg && sz == sz_byte)
+ goto nomatch;
+#if 0
+ if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) {
+ dstgather = 0;
+ }
+#endif
+ endofline:
+ /* now, we have a match */
+ if (table68k[opc].mnemo != i_ILLG)
+ fprintf(stderr, "Double match: %x: %s\n", opc, opcstr);
+ if (find == -1) {
+ for (find = 0;; find++) {
+ if (strcmp(mnemonic, lookuptab[find].name) == 0) {
+ table68k[opc].mnemo = lookuptab[find].mnemo;
+ break;
+ }
+ if (strlen(lookuptab[find].name) == 0) abort();
+ }
+ }
+ else {
+ table68k[opc].mnemo = lookuptab[find].mnemo;
+ }
+ table68k[opc].cc = bitval[bitc];
+ if (table68k[opc].mnemo == i_BTST
+ || table68k[opc].mnemo == i_BSET
+ || table68k[opc].mnemo == i_BCLR
+ || table68k[opc].mnemo == i_BCHG)
+ {
+ sz = destmode == Dreg ? sz_long : sz_byte;
+ }
+ table68k[opc].size = sz;
+ table68k[opc].sreg = srcreg;
+ table68k[opc].dreg = destreg;
+ table68k[opc].smode = srcmode;
+ table68k[opc].dmode = destmode;
+ table68k[opc].spos = srcgather ? srcpos : -1;
+ table68k[opc].dpos = dstgather ? dstpos : -1;
+ table68k[opc].suse = usesrc;
+ table68k[opc].duse = usedst;
+ table68k[opc].stype = srctype;
+ table68k[opc].plev = id.plevel;
+ table68k[opc].clev = id.cpulevel;
+#if 0
+ for (i = 0; i < 5; i++) {
+ table68k[opc].flaginfo[i].flagset = id.flaginfo[i].flagset;
+ table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
+ }
+#endif
+ table68k[opc].flagdead = flagdead;
+ table68k[opc].flaglive = flaglive;
+ nomatch:
+ /* FOO! */;
+ }
+}
+
+
+void read_table68k (void)
+{
+ int i;
+
+ table68k = (struct instr *)xmalloc (65536 * sizeof (struct instr));
+ for (i = 0; i < 65536; i++) {
+ table68k[i].mnemo = i_ILLG;
+ table68k[i].handler = -1;
+ }
+ for (i = 0; i < n_defs68k; i++) {
+ build_insn (i);
+ }
+}
+
+static int mismatch;
+
+static void handle_merges (long int opcode)
+{
+ uae_u16 smsk;
+ uae_u16 dmsk;
+ int sbitdst, dstend;
+ int srcreg, dstreg;
+
+ if (table68k[opcode].spos == -1) {
+ sbitdst = 1; smsk = 0;
+ } else {
+ switch (table68k[opcode].stype) {
+ case 0:
+ smsk = 7; sbitdst = 8; break;
+ case 1:
+ smsk = 255; sbitdst = 256; break;
+ case 2:
+ smsk = 15; sbitdst = 16; break;
+ case 3:
+ smsk = 7; sbitdst = 8; break;
+ case 4:
+ smsk = 7; sbitdst = 8; break;
+ case 5:
+ smsk = 63; sbitdst = 64; break;
+ default:
+ smsk = 0; sbitdst = 0;
+ abort();
+ break;
+ }
+ smsk <<= table68k[opcode].spos;
+ }
+ if (table68k[opcode].dpos == -1) {
+ dstend = 1; dmsk = 0;
+ } else {
+ dmsk = 7 << table68k[opcode].dpos;
+ dstend = 8;
+ }
+ for (srcreg=0; srcreg < sbitdst; srcreg++) {
+ for (dstreg=0; dstreg < dstend; dstreg++) {
+ uae_u16 code = opcode;
+
+ code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
+ code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
+
+ /* Check whether this is in fact the same instruction.
+ * The instructions should never differ, except for the
+ * Bcc.(BW) case. */
+ if (table68k[code].mnemo != table68k[opcode].mnemo
+ || table68k[code].size != table68k[opcode].size
+ || table68k[code].suse != table68k[opcode].suse
+ || table68k[code].duse != table68k[opcode].duse)
+ {
+ mismatch++; continue;
+ }
+ if (table68k[opcode].suse
+ && (table68k[opcode].spos != table68k[code].spos
+ || table68k[opcode].smode != table68k[code].smode
+ || table68k[opcode].stype != table68k[code].stype))
+ {
+ mismatch++; continue;
+ }
+ if (table68k[opcode].duse
+ && (table68k[opcode].dpos != table68k[code].dpos
+ || table68k[opcode].dmode != table68k[code].dmode))
+ {
+ mismatch++; continue;
+ }
+
+ if (code != opcode)
+ table68k[code].handler = opcode;
+ }
+ }
+}
+
+void do_merges (void)
+{
+ long int opcode;
+ int nr = 0;
+ mismatch = 0;
+ for (opcode = 0; opcode < 65536; opcode++) {
+ if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
+ continue;
+ nr++;
+ handle_merges (opcode);
+ }
+ nr_cpuop_funcs = nr;
+}
+
+int get_no_mismatches (void)
+{
+ return mismatch;
+}
diff --git a/SrcShared/UAE/readcpu.h b/SrcShared/UAE/readcpu.h
new file mode 100644
index 0000000..f277187
--- /dev/null
+++ b/SrcShared/UAE/readcpu.h
@@ -0,0 +1,113 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ENUMDECL {
+ Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
+ absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
+} ENUMNAME (amodes);
+
+ENUMDECL {
+ i_ILLG,
+
+ i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
+ i_SUB, i_SUBA, i_SUBX, i_SBCD,
+ i_ADD, i_ADDA, i_ADDX, i_ABCD,
+ i_NEG, i_NEGX, i_NBCD, i_CLR, i_NOT, i_TST,
+ i_BTST, i_BCHG, i_BCLR, i_BSET,
+ i_CMP, i_CMPM, i_CMPA,
+ i_MVPRM, i_MVPMR, i_MOVE, i_MOVEA, i_MVSR2, i_MV2SR,
+ i_SWAP, i_EXG, i_EXT, i_MVMEL, i_MVMLE,
+ i_TRAP, i_MVR2USP, i_MVUSP2R, i_RESET, i_NOP, i_STOP, i_RTE, i_RTD,
+ i_LINK, i_UNLK,
+ i_RTS, i_TRAPV, i_RTR,
+ i_JSR, i_JMP, i_BSR, i_Bcc,
+ i_LEA, i_PEA, i_DBcc, i_Scc,
+ i_DIVU, i_DIVS, i_MULU, i_MULS,
+ i_ASR, i_ASL, i_LSR, i_LSL, i_ROL, i_ROR, i_ROXL, i_ROXR,
+ i_ASRW, i_ASLW, i_LSRW, i_LSLW, i_ROLW, i_RORW, i_ROXLW, i_ROXRW,
+ i_CHK,i_CHK2,
+ i_MOVEC2, i_MOVE2C, i_CAS, i_CAS2, i_DIVL, i_MULL,
+ i_BFTST,i_BFEXTU,i_BFCHG,i_BFEXTS,i_BFCLR,i_BFFFO,i_BFSET,i_BFINS,
+ i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
+ i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
+ i_MMUOP
+} ENUMNAME (instrmnem);
+
+extern struct mnemolookup {
+ instrmnem mnemo;
+ const char *name;
+} lookuptab[];
+
+ENUMDECL {
+ sz_byte, sz_word, sz_long
+} ENUMNAME (wordsizes);
+
+ENUMDECL {
+ fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
+} ENUMNAME (flagaffect);
+
+ENUMDECL {
+ fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
+} ENUMNAME (flaguse);
+
+ENUMDECL {
+ bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
+ bits, bitS, bitd, bitD, bitr, bitR, bitz, lastbit
+} ENUMNAME (bitvals);
+
+struct instr_def {
+ unsigned int bits;
+ int n_variable;
+ char bitpos[16];
+ unsigned int mask;
+ int cpulevel;
+ int plevel;
+ struct {
+ unsigned int flaguse:3;
+ unsigned int flagset:3;
+ } flaginfo[5];
+ unsigned char sduse;
+ const char *opcstr;
+};
+
+extern struct instr_def defs68k[];
+extern int n_defs68k;
+
+extern struct instr {
+ long int handler;
+ unsigned char dreg;
+ unsigned char sreg;
+ signed char dpos;
+ signed char spos;
+ unsigned char sduse;
+ int flagdead:8, flaglive:8;
+ unsigned int mnemo:8;
+ unsigned int cc:4;
+ unsigned int plev:2;
+ unsigned int size:2;
+ unsigned int smode:5;
+ unsigned int stype:3;
+ unsigned int dmode:5;
+ unsigned int suse:1;
+ unsigned int duse:1;
+ unsigned int unused1:1;
+ unsigned int clev:3;
+ unsigned int unused2:5;
+} *table68k;
+
+extern void read_table68k (void);
+extern void do_merges (void);
+extern int get_no_mismatches (void);
+extern int nr_cpuop_funcs;
+
+struct perfRec {
+ unsigned char extraCycles;
+ unsigned char readCycles;
+ unsigned char writeCycles;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/SrcShared/UAE/sysconfig.h b/SrcShared/UAE/sysconfig.h
new file mode 100644
index 0000000..17de33a
--- /dev/null
+++ b/SrcShared/UAE/sysconfig.h
@@ -0,0 +1,33 @@
+#define SIZEOF_CHAR 1
+#define SIZEOF_SHORT 2
+#define SIZEOF_INT 0 // Goofy, but it gets us what we want: shorts
+ // for 2-byte types and longs for 4-byte types
+#define SIZEOF_LONG 4
+
+#ifdef _MSC_VER
+ #define SIZEOF___INT64 8
+#else
+ #define SIZEOF_LONG_LONG 8
+#endif
+
+#define REGPARAM
+#define DONT_HAVE_REAL_POSIX
+#define EXEC_TYPES_H
+
+#include <string.h>
+
+#ifdef _MSC_VER
+ #pragma warning( disable : 4244 ) // warning C4244: initializing : conversion from unsigned long to unsigned short, possible loss of data
+ #pragma warning( disable : 4786 ) // warning C4786: '<foo>' : identifier was truncated to '255' characters in the browser information
+#endif
+
+
+#ifdef _MSC_VER
+ #define __inline__ __inline
+#else
+ #define __inline__ inline
+#endif
+
+#ifndef STATIC_INLINE
+#define STATIC_INLINE static __inline__
+#endif
diff --git a/SrcShared/UAE/sysdeps.h b/SrcShared/UAE/sysdeps.h
new file mode 100644
index 0000000..ab682fa
--- /dev/null
+++ b/SrcShared/UAE/sysdeps.h
@@ -0,0 +1,348 @@
+ /*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * Try to include the right system headers and get other system-specific
+ * stuff right & other collected kludges.
+ *
+ * If you think about modifying this, think twice. Some systems rely on
+ * the exact order of the #include statements. That's also the reason
+ * why everything gets included unconditionally regardless of whether
+ * it's actually needed by the .c file.
+ *
+ * Copyright 1996, 1997 Bernd Schmidt
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "EmTypes.h" // int8, int16, etc.
+
+#ifndef __STDC__
+#define __STDC__ 1
+#endif
+#ifndef __STDC__
+#error "Your compiler is not ANSI. Get a real one."
+#endif
+
+#include <stdarg.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifdef HAVE_SYS_UTIME_H
+# include <sys/utime.h>
+#endif
+
+#include <errno.h>
+#include <assert.h>
+
+#if EEXIST == ENOTEMPTY
+#define BROKEN_OS_PROBABLY_AIX
+#endif
+
+#ifdef __NeXT__
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXEC
+#define S_ISDIR(val) (S_IFDIR & val)
+struct utimbuf
+{
+ time_t actime;
+ time_t modtime;
+};
+#endif
+
+#if defined(__GNUC__) && defined(AMIGA)
+/* gcc on the amiga need that __attribute((regparm)) must */
+/* be defined in function prototypes as well as in */
+/* function definitions ! */
+#define REGPARAM2 REGPARAM
+#else /* not(GCC & AMIGA) */
+#define REGPARAM2
+#endif
+
+/* sam: some definitions so that SAS/C can compile UAE */
+#if defined(__SASC) && defined(AMIGA)
+#define REGPARAM2
+#define REGPARAM
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXECUTE
+#define S_ISDIR(val) (S_IFDIR & val)
+#define mkdir(x,y) mkdir(x)
+#define truncate(x,y) 0
+#define creat(x,y) open("T:creat",O_CREAT|O_TEMP|O_RDWR) /* sam: for zfile.c */
+#define strcasecmp stricmp
+#define utime(file,time) 0
+struct utimbuf
+{
+ time_t actime;
+ time_t modtime;
+};
+#endif
+
+#if defined(WARPUP)
+#include "devices/timer.h"
+#include "osdep/posixemu.h"
+#define REGPARAM
+#define REGPARAM2
+#define RETSIGTYPE
+#define USE_ZFILE
+#define strcasecmp stricmp
+#define memcpy q_memcpy
+#define memset q_memset
+#define strdup my_strdup
+#define random rand
+#define creat(x,y) open("T:creat",O_CREAT|O_RDWR,777)
+extern void* q_memset(void*,int,size_t);
+extern void* q_memcpy(void*,const void*,size_t);
+#endif
+
+#ifdef __DOS__
+#include <pc.h>
+#include <io.h>
+#endif
+
+/* Acorn specific stuff */
+#ifdef ACORN
+
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXEC
+
+#define strcasecmp stricmp
+
+#endif
+
+#ifndef L_tmpnam
+#define L_tmpnam 128 /* ought to be safe */
+#endif
+
+/* If char has more then 8 bits, good night. */
+
+typedef int8 uae_s8;
+typedef int16 uae_s16;
+typedef int32 uae_s32;
+typedef int64 uae_s64;
+
+typedef uint8 uae_u8;
+typedef uint16 uae_u16;
+typedef uint32 uae_u32;
+typedef uint64 uae_u64;
+
+typedef emuptr uaecptr;
+
+
+#ifdef HAVE_STRDUP
+#define my_strdup strdup
+#else
+extern char *my_strdup (const char*s);
+#endif
+
+extern void *xmalloc(size_t);
+
+/* We can only rely on GNU C getting enums right. Mickeysoft VSC++ is known
+ * to have problems, and it's likely that other compilers choke too. */
+#ifdef __GNUC__
+#define ENUMDECL typedef enum
+#define ENUMNAME(name) name
+#else
+#define ENUMDECL enum
+#define ENUMNAME(name) ; typedef int name
+#endif
+
+/*
+ * Porters to weird systems, look! This is the preferred way to get
+ * filesys.c (and other stuff) running on your system. Define the
+ * appropriate macros and implement wrappers in a machine-specific file.
+ *
+ * I guess the Mac port could use this (Ernesto?)
+ */
+
+//#undef DONT_HAVE_POSIX
+//#undef DONT_HAVE_REAL_POSIX /* define if open+delete doesn't do what it should */
+//#undef DONT_HAVE_STDIO
+//#undef DONT_HAVE_MALLOC
+
+#if defined(WARPUP)
+#define DONT_HAVE_POSIX
+#endif
+
+#if defined _WIN32
+
+#if defined __WATCOMC__
+
+#define O_NDELAY 0
+#include <direct.h>
+#define dirent direct
+#define mkdir(a,b) mkdir(a)
+#define strcasecmp stricmp
+
+#elif defined __MINGW32__
+
+#define O_NDELAY 0
+#define mkdir(a,b) mkdir(a)
+
+#endif
+
+#endif /* _WIN32 */
+
+#ifdef DONT_HAVE_POSIX
+
+#define access posixemu_access
+extern int posixemu_access (const char *, int);
+#define open posixemu_open
+extern int posixemu_open (const char *, int, int);
+#define close posixemu_close
+extern void posixemu_close (int);
+#define read posixemu_read
+extern int posixemu_read (int, char *, int);
+#define write posixemu_write
+extern int posixemu_write (int, const char *, int);
+#undef lseek
+#define lseek posixemu_seek
+extern int posixemu_seek (int, int, int);
+#define stat(a,b) posixemu_stat ((a), (b))
+extern int posixemu_stat (const char *, STAT *);
+#define mkdir posixemu_mkdir
+extern int mkdir (const char *, int);
+#define rmdir posixemu_rmdir
+extern int posixemu_rmdir (const char *);
+#define unlink posixemu_unlink
+extern int posixemu_unlink (const char *);
+#define truncate posixemu_truncate
+extern int posixemu_truncate (const char *, long int);
+#define rename posixemu_rename
+extern int posixemu_rename (const char *, const char *);
+#define chmod posixemu_chmod
+extern int posixemu_chmod (const char *, int);
+#define tmpnam posixemu_tmpnam
+extern void posixemu_tmpnam (char *);
+#define utime posixemu_utime
+extern int posixemu_utime (const char *, struct utimbuf *);
+#define opendir posixemu_opendir
+extern DIR * posixemu_opendir (const char *);
+#define readdir posixemu_readdir
+extern struct dirent* readdir (DIR *);
+#define closedir posixemu_closedir
+extern void closedir (DIR *);
+
+/* This isn't the best place for this, but it fits reasonably well. The logic
+ * is that you probably don't have POSIX errnos if you don't have the above
+ * functions. */
+extern long dos_errno (void);
+
+#endif
+
+#ifdef DONT_HAVE_STDIO
+
+extern FILE *stdioemu_fopen (const char *, const char *);
+#define fopen(a,b) stdioemu_fopen(a, b)
+extern int stdioemu_fseek (FILE *, int, int);
+#define fseek(a,b,c) stdioemu_fseek(a, b, c)
+extern int stdioemu_fread (char *, int, int, FILE *);
+#define fread(a,b,c,d) stdioemu_fread(a, b, c, d)
+extern int stdioemu_fwrite (const char *, int, int, FILE *);
+#define fwrite(a,b,c,d) stdioemu_fwrite(a, b, c, d)
+extern int stdioemu_ftell (FILE *);
+#define ftell(a) stdioemu_ftell(a)
+extern int stdioemu_fclose (FILE *);
+#define fclose(a) stdioemu_fclose(a)
+
+#endif
+
+#ifdef DONT_HAVE_MALLOC
+
+#define malloc(a) mallocemu_malloc(a)
+extern void *mallocemu_malloc (int size);
+#define free(a) mallocemu_free(a)
+extern void mallocemu_free (void *ptr);
+
+#endif
+
+#ifdef X86_ASSEMBLY
+#define ASM_SYM_FOR_FUNC(a) __asm__(a)
+#else
+#define ASM_SYM_FOR_FUNC(a)
+#endif
+
+#if defined USE_COMPILER
+#undef NO_PREFETCH_BUFFER
+#undef NO_EXCEPTION_3
+#define NO_EXCEPTION_3
+#define NO_PREFETCH_BUFFER
+#endif
+
+#include "target.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef STATIC_INLINE
+#define STATIC_INLINE static __inline__
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/SrcShared/UAE/table68k b/SrcShared/UAE/table68k
new file mode 100644
index 0000000..0e8de35
--- /dev/null
+++ b/SrcShared/UAE/table68k
@@ -0,0 +1,242 @@
+% 0: bit 0
+% 1: bit 1
+% c: condition code
+% C: condition codes, except F
+% f: direction
+% i: immediate
+% I: immediate, except 00 and ff
+% j: immediate 1..8
+% J: immediate 0..15
+% k: immediate 0..7
+% K: immediate 0..63
+% s: source mode
+% S: source reg
+% d: dest mode
+% D: dest reg
+% r: reg
+% z: size
+%
+% Actually, a sssSSS may appear as a destination, and
+% vice versa. The only difference between sssSSS and
+% dddDDD are the valid addressing modes. There is
+% no match for immediate and pc-rel. addressing modes
+% in case of dddDDD.
+%
+% Arp: --> -(Ar)
+% ArP: --> (Ar)+
+%
+% Fields on a line:
+% 16 chars bitpattern :
+% CPU level / privildge level :
+% CPU level 0: 68000
+% 1: 68010
+% 2: 68020
+% privilege level 0: not privileged
+% 1: unprivileged only on 68000 (check regs.s)
+% 2: privileged (check regs.s)
+% 3: privileged if size == word (check regs.s)
+% Flags set by instruction: XNZVC :
+% Flags used by instruction: XNZVC :
+% - means flag unaffected / unused
+% 0 means flag reset
+% 1 means flag set
+% ? means programmer was too lazy to check or instruction may trap
+% + means instruction is conditional branch
+% everything else means flag set/used
+% / means instruction is unconditional branch/call
+% x means flag is unknown and well-behaved programs shouldn't check it
+% srcaddr status destaddr status :
+% bitmasks of
+% 1 means fetched
+% 2 means stored
+% 4 means jump offset
+% 8 means jump address
+% instruction
+%
+
+0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1
+0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1
+0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
+0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg]
+0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1
+0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1
+0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg]
+0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg]
+0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg]
+0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
+0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg]
+0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg]
+0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd]
+0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd]
+0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd]
+0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1
+0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1
+0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg]
+0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd]
+
+0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
+0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
+0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2
+0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
+0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
+0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2
+
+0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr
+0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr
+0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16]
+0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16]
+0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg]
+0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd]
+0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd]
+0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd]
+
+0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg]
+0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg]
+0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg]
+0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg]
+0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg]
+
+0100 0000 zzdd dDDD:00:XxZxC:-----:30: NEGX.z d[!Areg]
+0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg]
+0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg]
+0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg]
+0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg]
+0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg]
+0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg]
+0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg]
+0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2
+0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg]
+0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k
+0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg]
+0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
+0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg]
+0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
+0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg]
+0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
+0100 1001 11dd dDDD:00:-NZ00:-----:30: EXT.B d[Dreg]
+0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s
+0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg]
+0100 1010 1111 1100:00:?????:?????:00: ILLEGAL
+0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg]
+0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg]
+0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
+0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
+0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J
+0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1
+0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar
+0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar
+0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar
+0100 1110 0111 0000:02:-----:-----:00: RESET
+0100 1110 0111 0001:00:-----:-----:00: NOP
+0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1
+0100 1110 0111 0011:02:XNZVC:-----:00: RTE
+0100 1110 0111 0100:00:?????:?????:10: RTD #1
+0100 1110 0111 0101:00:-----:-----:00: RTS
+0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV
+0100 1110 0111 0111:00:XNZVC:-----:00: RTR
+0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1
+0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1
+0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
+0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr
+0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr
+0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
+0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
+
+0101 jjj0 zzdd dDDD:00:-----:-----:13: ADDA.z #j,d[Areg]
+0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg]
+0101 jjj1 zzdd dDDD:00:-----:-----:13: SUBA.z #j,d[Areg]
+0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg]
+0101 cccc 1100 1rrr:00:-----:+++++:31: DBcc.W Dr,#1
+0101 cccc 11dd dDDD:00:-----:+++++:20: Scc.B d[!Areg]
+0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1
+0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2
+0101 cccc 1111 1100:20:?????:?????:00: TRAPcc
+
+% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
+% instruction exceptions when compiling a 68000 only emulation, which isn't
+% what we want either.
+0110 0001 0000 0000:00://///://///:40: BSR.W #1
+0110 0001 IIII IIII:00://///://///:40: BSR.B #i
+0110 0001 1111 1111:00://///://///:40: BSR.L #2
+0110 CCCC 0000 0000:00:-----:+++++:40: Bcc.W #1
+0110 CCCC IIII IIII:00:-----:+++++:40: Bcc.B #i
+0110 CCCC 1111 1111:00:-----:+++++:40: Bcc.L #2
+
+0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr
+
+1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr
+1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr
+1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr
+1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp
+1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg]
+1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr
+1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp
+1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr
+1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp
+1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr
+
+1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr
+1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar
+1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr
+1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp
+1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg]
+1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar
+
+1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr
+1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar
+1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar
+1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP
+1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg]
+
+1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr
+1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr
+1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Dreg],Dr
+1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Areg-Apdi],Arp
+1100 rrr1 zzdd dDDD:00:-NZ00:-----:13: AND.z Dr,d[!Areg,Dreg]
+1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Dr,d[Dreg]
+1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Ar,d[Areg]
+1100 rrr1 10dd dDDD:00:-----:-----:33: EXG.L Dr,d[Areg]
+1100 rrr1 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr
+
+1101 rrr0 zzss sSSS:00:XNZVC:-----:13: ADD.z s,Dr
+1101 rrr0 11ss sSSS:00:-----:-----:13: ADDA.W s,Ar
+1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Dreg],Dr
+1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Areg-Apdi],Arp
+1101 rrr1 zzdd dDDD:00:XNZVC:-----:13: ADD.z Dr,d[!Areg,Dreg]
+1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar
+
+1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR
+1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR
+1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR
+1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR
+1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR
+1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR
+1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR
+1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR
+1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg]
+1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg]
+1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg]
+1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg]
+
+1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
+1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
+1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
+1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
+1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
+1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
+1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
+1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
+
+% floating point co processor
+1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s
+1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg]
+1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
+1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1
+1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2
+1111 0010 0111 1100:30:?????:?????:00: FTRAPcc
+1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1
+1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2
+1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
+1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
+
+1111 0000 00ss sSSS:40:?????:?????:11: MMUOP #1,s
diff --git a/SrcShared/UAE/target.h b/SrcShared/UAE/target.h
new file mode 100644
index 0000000..45c9ce2
--- /dev/null
+++ b/SrcShared/UAE/target.h
@@ -0,0 +1,4 @@
+#define OPTIONSFILENAME .uaerc
+#define UNSUPPORTED_OPTION_p
+#define UNSUPPORTED_OPTION_I
+
diff --git a/SrcShared/jpeg/cderror.h b/SrcShared/jpeg/cderror.h
new file mode 100644
index 0000000..70435e1
--- /dev/null
+++ b/SrcShared/jpeg/cderror.h
@@ -0,0 +1,132 @@
+/*
+ * cderror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the cjpeg/djpeg
+ * applications. These strings are not needed as part of the JPEG library
+ * proper.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef CDERROR_H
+#define CDERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* CDERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
+
+#ifdef BMP_SUPPORTED
+JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
+JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
+JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
+JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
+JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
+JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
+JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
+JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
+JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
+JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
+JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
+#endif /* BMP_SUPPORTED */
+
+#ifdef GIF_SUPPORTED
+JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
+JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
+JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
+JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
+JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
+JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
+JMESSAGE(JTRC_GIF_BADVERSION,
+ "Warning: unexpected GIF version number '%c%c%c'")
+JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
+JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
+JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
+JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
+JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
+JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
+#endif /* GIF_SUPPORTED */
+
+#ifdef PPM_SUPPORTED
+JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
+JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
+JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
+JMESSAGE(JTRC_PGM, "%ux%u PGM image")
+JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
+JMESSAGE(JTRC_PPM, "%ux%u PPM image")
+JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
+#endif /* PPM_SUPPORTED */
+
+#ifdef RLE_SUPPORTED
+JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
+JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
+JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
+JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
+JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
+JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
+JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
+JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
+JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
+JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
+JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
+JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
+#endif /* RLE_SUPPORTED */
+
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
+JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
+JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
+JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
+JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
+JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
+#else
+JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
+#endif /* TARGA_SUPPORTED */
+
+JMESSAGE(JERR_BAD_CMAP_FILE,
+ "Color map file is invalid or of unsupported format")
+JMESSAGE(JERR_TOO_MANY_COLORS,
+ "Output file format cannot handle %d colormap entries")
+JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_UNKNOWN_FORMAT,
+ "Unrecognized input file format --- perhaps you need -targa")
+#else
+JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
+#endif
+JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTADDONCODE
+} ADDON_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
diff --git a/SrcShared/jpeg/jcapimin.c b/SrcShared/jpeg/jcapimin.c
new file mode 100644
index 0000000..54fb8c5
--- /dev/null
+++ b/SrcShared/jpeg/jcapimin.c
@@ -0,0 +1,280 @@
+/*
+ * jcapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-compression case or the transcoding-only
+ * case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jcapistd.c. But also see jcparam.c for
+ * parameter-setup helper routines, jcomapi.c for routines shared by
+ * compression and decompression, and jctrans.c for the transcoding case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG compression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_compress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = FALSE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->dest = NULL;
+
+ cinfo->comp_info = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++)
+ cinfo->quant_tbl_ptrs[i] = NULL;
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ cinfo->script_space = NULL;
+
+ cinfo->input_gamma = 1.0; /* in case application forgets */
+
+ /* OK, I'm ready */
+ cinfo->global_state = CSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG compression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_compress (j_compress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG compression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_compress (j_compress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Forcibly suppress or un-suppress all quantization and Huffman tables.
+ * Marks all currently defined tables as already written (if suppress)
+ * or not written (if !suppress). This will control whether they get emitted
+ * by a subsequent jpeg_start_compress call.
+ *
+ * This routine is exported for use by applications that want to produce
+ * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
+ * since it is called by jpeg_start_compress, we put it here --- otherwise
+ * jcparam.o would be linked whether the application used it or not.
+ */
+
+GLOBAL(void)
+jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+{
+ int i;
+ JQUANT_TBL * qtbl;
+ JHUFF_TBL * htbl;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
+ qtbl->sent_table = suppress;
+ }
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ }
+}
+
+
+/*
+ * Finish JPEG compression.
+ *
+ * If a multipass operating mode was selected, this may do a great deal of
+ * work including most of the actual output.
+ */
+
+GLOBAL(void)
+jpeg_finish_compress (j_compress_ptr cinfo)
+{
+ JDIMENSION iMCU_row;
+
+ if (cinfo->global_state == CSTATE_SCANNING ||
+ cinfo->global_state == CSTATE_RAW_OK) {
+ /* Terminate first pass */
+ if (cinfo->next_scanline < cinfo->image_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_pass) (cinfo);
+ } else if (cinfo->global_state != CSTATE_WRCOEFS)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any remaining passes */
+ while (! cinfo->master->is_last_pass) {
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) iMCU_row;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* We bypass the main controller and invoke coef controller directly;
+ * all work is being done from the coefficient buffer.
+ */
+ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+ (*cinfo->master->finish_pass) (cinfo);
+ }
+ /* Write EOI, do final cleanup */
+ (*cinfo->marker->write_file_trailer) (cinfo);
+ (*cinfo->dest->term_destination) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+}
+
+
+/*
+ * Write a special marker.
+ * This is only recommended for writing COM or APPn markers.
+ * Must be called after jpeg_start_compress() and before
+ * first call to jpeg_write_scanlines() or jpeg_write_raw_data().
+ */
+
+GLOBAL(void)
+jpeg_write_marker (j_compress_ptr cinfo, int marker,
+ const JOCTET *dataptr, unsigned int datalen)
+{
+ JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
+
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+ write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
+ while (datalen--) {
+ (*write_marker_byte) (cinfo, *dataptr);
+ dataptr++;
+ }
+}
+
+/* Same, but piecemeal. */
+
+GLOBAL(void)
+jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+{
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+}
+
+GLOBAL(void)
+jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+{
+ (*cinfo->marker->write_marker_byte) (cinfo, val);
+}
+
+
+/*
+ * Alternate compression function: just write an abbreviated table file.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * To produce a pair of files containing abbreviated tables and abbreviated
+ * image data, one would proceed as follows:
+ *
+ * initialize JPEG object
+ * set JPEG parameters
+ * set destination to table file
+ * jpeg_write_tables(cinfo);
+ * set destination to image file
+ * jpeg_start_compress(cinfo, FALSE);
+ * write data...
+ * jpeg_finish_compress(cinfo);
+ *
+ * jpeg_write_tables has the side effect of marking all tables written
+ * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
+ * will not re-emit the tables unless it is passed write_all_tables=TRUE.
+ */
+
+GLOBAL(void)
+jpeg_write_tables (j_compress_ptr cinfo)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Initialize the marker writer ... bit of a crock to do it here. */
+ jinit_marker_writer(cinfo);
+ /* Write them tables! */
+ (*cinfo->marker->write_tables_only) (cinfo);
+ /* And clean up. */
+ (*cinfo->dest->term_destination) (cinfo);
+ /*
+ * In library releases up through v6a, we called jpeg_abort() here to free
+ * any working memory allocated by the destination manager and marker
+ * writer. Some applications had a problem with that: they allocated space
+ * of their own from the library memory manager, and didn't want it to go
+ * away during write_tables. So now we do nothing. This will cause a
+ * memory leak if an app calls write_tables repeatedly without doing a full
+ * compression cycle or otherwise resetting the JPEG object. However, that
+ * seems less bad than unexpectedly freeing memory in the normal case.
+ * An app that prefers the old behavior can call jpeg_abort for itself after
+ * each call to jpeg_write_tables().
+ */
+}
diff --git a/SrcShared/jpeg/jcapistd.c b/SrcShared/jpeg/jcapistd.c
new file mode 100644
index 0000000..c0320b1
--- /dev/null
+++ b/SrcShared/jpeg/jcapistd.c
@@ -0,0 +1,161 @@
+/*
+ * jcapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-compression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_compress, it will end up linking in the entire compressor.
+ * We thus must separate this file from jcapimin.c to avoid linking the
+ * whole compression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Compression initialization.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * We require a write_all_tables parameter as a failsafe check when writing
+ * multiple datastreams from the same compression object. Since prior runs
+ * will have left all the tables marked sent_table=TRUE, a subsequent run
+ * would emit an abbreviated stream (no tables) by default. This may be what
+ * is wanted, but for safety's sake it should not be the default behavior:
+ * programmers should have to make a deliberate choice to emit abbreviated
+ * images. Therefore the documentation and examples should encourage people
+ * to pass write_all_tables=TRUE; then it will take active thought to do the
+ * wrong thing.
+ */
+
+GLOBAL(void)
+jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (write_all_tables)
+ jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ jinit_compress_master(cinfo);
+ /* Set up for the first pass */
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ /* Ready for application to drive first pass through jpeg_write_scanlines
+ * or jpeg_write_raw_data.
+ */
+ cinfo->next_scanline = 0;
+ cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
+}
+
+
+/*
+ * Write some scanlines of data to the JPEG compressor.
+ *
+ * The return value will be the number of lines actually written.
+ * This should be less than the supplied num_lines only in case that
+ * the data destination module has requested suspension of the compressor,
+ * or if more than image_height scanlines are passed in.
+ *
+ * Note: we warn about excess calls to jpeg_write_scanlines() since
+ * this likely signals an application programmer error. However,
+ * excess scanlines passed in the last valid call are *silently* ignored,
+ * so that the application need not adjust num_lines for end-of-image
+ * when using a multiple-scanline buffer.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION num_lines)
+{
+ JDIMENSION row_ctr, rows_left;
+
+ if (cinfo->global_state != CSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height)
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_scanlines. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_scanlines.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Ignore any extra scanlines at bottom of image. */
+ rows_left = cinfo->image_height - cinfo->next_scanline;
+ if (num_lines > rows_left)
+ num_lines = rows_left;
+
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
+ cinfo->next_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to write raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != CSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_raw_data. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_raw_data.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Verify that at least one iMCU row has been passed. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
+ if (num_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Directly compress the row. */
+ if (! (*cinfo->coef->compress_data) (cinfo, data)) {
+ /* If compressor did not consume the whole row, suspend processing. */
+ return 0;
+ }
+
+ /* OK, we processed one iMCU row. */
+ cinfo->next_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
diff --git a/SrcShared/jpeg/jccoefct.c b/SrcShared/jpeg/jccoefct.c
new file mode 100644
index 0000000..1963ddb
--- /dev/null
+++ b/SrcShared/jpeg/jccoefct.c
@@ -0,0 +1,449 @@
+/*
+ * jccoefct.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for compression.
+ * This controller is the top level of the JPEG compressor proper.
+ * The coefficient buffer lies between forward-DCT and entropy encoding steps.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* We use a full-image coefficient buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files. In all cases, the DCT
+ * step is run during the first pass, and subsequent passes need only read
+ * the buffered coefficients.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_coef_controller pub; /* public fields */
+
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* For single-pass compression, it's sufficient to buffer just one MCU
+ * (although this may prove a bit slow in practice). We allocate a
+ * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
+ * MCU constructed and sent. (On 80x86, the workspace is FAR even though
+ * it's not really very big; this is to keep the module interfaces unchanged
+ * when a large coefficient buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays.
+ */
+ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
+
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (coef->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_data;
+ break;
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_first_pass;
+ break;
+ case JBUF_CRANK_DEST:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_output;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, bi, ci, yindex, yoffset, blockcnt;
+ JDIMENSION ypos, xpos;
+ jpeg_component_info *compptr;
+
+ /* Loop to write as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Determine where data comes from in input_buf and do the DCT thing.
+ * Each call on forward_DCT processes a horizontal row of DCT blocks
+ * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
+ * sequentially. Dummy blocks at the right or bottom edge are filled in
+ * specially. The data in them does not matter for image reconstruction,
+ * so we fill them with values that will encode to the smallest amount of
+ * data, viz: all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. (Thanks to Thomas Kinsman for this idea.)
+ */
+ blkn = 0;
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ xpos = MCU_col_num * compptr->MCU_sample_width;
+ ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ (*cinfo->fdct->forward_DCT) (cinfo, compptr,
+ input_buf[compptr->component_index],
+ coef->MCU_buffer[blkn],
+ ypos, xpos, (JDIMENSION) blockcnt);
+ if (blockcnt < compptr->MCU_width) {
+ /* Create some dummy blocks at the right edge of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
+ (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
+ for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+ }
+ }
+ } else {
+ /* Create a row of dummy blocks at the bottom of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn],
+ compptr->MCU_width * SIZEOF(JBLOCK));
+ for (bi = 0; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+ }
+ }
+ blkn += compptr->MCU_width;
+ ypos += DCTSIZE;
+ }
+ }
+ /* Try to write the MCU. In event of a suspension failure, we will
+ * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
+ */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * This amount of data is read from the source buffer, DCT'd and quantized,
+ * and saved into the virtual arrays. We also generate suitable dummy blocks
+ * as needed at the right and lower edges. (The dummy blocks are constructed
+ * in the virtual arrays, which have been padded appropriately.) This makes
+ * it possible for subsequent passes not to worry about real vs. dummy blocks.
+ *
+ * We must also emit the data to the entropy encoder. This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image. All
+ * components are DCT'd and loaded into the virtual arrays in this pass.
+ * However, it may be that only a subset of the components are emitted to
+ * the entropy encoder during this first pass; be careful about looking
+ * at the scan-dependent variables (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION blocks_across, MCUs_across, MCUindex;
+ int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
+ JCOEF lastDC;
+ jpeg_component_info *compptr;
+ JBLOCKARRAY buffer;
+ JBLOCKROW thisblockrow, lastblockrow;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (coef->iMCU_row_num < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here, since may not be set! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ blocks_across = compptr->width_in_blocks;
+ h_samp_factor = compptr->h_samp_factor;
+ /* Count number of dummy blocks to be added at the right margin. */
+ ndummy = (int) (blocks_across % h_samp_factor);
+ if (ndummy > 0)
+ ndummy = h_samp_factor - ndummy;
+ /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
+ * on forward_DCT processes a complete horizontal row of DCT blocks.
+ */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ thisblockrow = buffer[block_row];
+ (*cinfo->fdct->forward_DCT) (cinfo, compptr,
+ input_buf[ci], thisblockrow,
+ (JDIMENSION) (block_row * DCTSIZE),
+ (JDIMENSION) 0, blocks_across);
+ if (ndummy > 0) {
+ /* Create dummy blocks at the right edge of the image. */
+ thisblockrow += blocks_across; /* => first dummy block */
+ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
+ lastDC = thisblockrow[-1][0];
+ for (bi = 0; bi < ndummy; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ }
+ }
+ /* If at end of image, create dummy block rows as needed.
+ * The tricky part here is that within each MCU, we want the DC values
+ * of the dummy blocks to match the last real block's DC value.
+ * This squeezes a few more bytes out of the resulting file...
+ */
+ if (coef->iMCU_row_num == last_iMCU_row) {
+ blocks_across += ndummy; /* include lower right corner */
+ MCUs_across = blocks_across / h_samp_factor;
+ for (block_row = block_rows; block_row < compptr->v_samp_factor;
+ block_row++) {
+ thisblockrow = buffer[block_row];
+ lastblockrow = buffer[block_row-1];
+ jzero_far((void FAR *) thisblockrow,
+ (size_t) (blocks_across * SIZEOF(JBLOCK)));
+ for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
+ lastDC = lastblockrow[h_samp_factor-1][0];
+ for (bi = 0; bi < h_samp_factor; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ thisblockrow += h_samp_factor; /* advance to next MCU in row */
+ lastblockrow += h_samp_factor;
+ }
+ }
+ }
+ }
+ /* NB: compress_output will increment iMCU_row_num if successful.
+ * A suspension return will result in redoing all the work above next time.
+ */
+
+ /* Emit data to the entropy encoder, sharing code with subsequent passes */
+ return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan.
+ * NB: during first pass, this is safe only because the buffers will
+ * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+#endif /* FULL_COEF_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_coef_ptr coef;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ coef->pub.start_pass = start_pass_coef;
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ int ci;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ coef->whole_image[0] = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/SrcShared/jpeg/jccolor.c b/SrcShared/jpeg/jccolor.c
new file mode 100644
index 0000000..0a8a4b5
--- /dev/null
+++ b/SrcShared/jpeg/jccolor.c
@@ -0,0 +1,459 @@
+/*
+ * jccolor.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_converter pub; /* public fields */
+
+ /* Private state for RGB->YCC conversion */
+ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
+} my_color_converter;
+
+typedef my_color_converter * my_cconvert_ptr;
+
+
+/**************** RGB -> YCbCr conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
+ * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
+ * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
+ * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
+ * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
+ * were not represented exactly. Now we sacrifice exact representation of
+ * maximum red and maximum blue in order to get exact grayscales.
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times R,G,B for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
+ * in the tables to save adding them separately in the inner loop.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+/* We allocate one big table and divide it up into eight parts, instead of
+ * doing eight alloc_small requests. This lets us use a single table base
+ * address, which can be held in a register in the inner loops on many
+ * machines (more than can hold all eight addresses, anyway).
+ */
+
+#define R_Y_OFF 0 /* offset to R => Y section */
+#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
+#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
+#define R_CB_OFF (3*(MAXJSAMPLE+1))
+#define G_CB_OFF (4*(MAXJSAMPLE+1))
+#define B_CB_OFF (5*(MAXJSAMPLE+1))
+#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
+#define G_CR_OFF (6*(MAXJSAMPLE+1))
+#define B_CR_OFF (7*(MAXJSAMPLE+1))
+#define TABLE_SIZE (8*(MAXJSAMPLE+1))
+
+
+/*
+ * Initialize for RGB->YCC colorspace conversion.
+ */
+
+METHODDEF(void)
+rgb_ycc_start (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ INT32 * rgb_ycc_tab;
+ INT32 i;
+
+ /* Allocate and fill in the conversion tables. */
+ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (TABLE_SIZE * SIZEOF(INT32)));
+
+ for (i = 0; i <= MAXJSAMPLE; i++) {
+ rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
+ rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
+ rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
+ rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
+ /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
+ * This ensures that the maximum output will round to MAXJSAMPLE
+ * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
+ */
+ rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+/* B=>Cb and R=>Cr tables are the same
+ rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+*/
+ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
+ rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ *
+ * Note that we change from the application's interleaved-pixel format
+ * to our internal noninterleaved, one-plane-per-component format.
+ * The input buffer is therefore three times as wide as the output buffer.
+ *
+ * A starting row offset is provided only for the output buffer. The caller
+ * can easily adjust the passed input_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+rgb_ycc_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/**************** Cases other than RGB -> YCbCr **************/
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles RGB->grayscale conversion, which is the same
+ * as the RGB->Y portion of RGB->YCbCr.
+ * We assume rgb_ycc_start has been called (we only use the Y tables).
+ */
+
+METHODDEF(void)
+rgb_gray_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* Y */
+ outptr[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles Adobe-style CMYK->YCCK conversion,
+ * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume rgb_ycc_start has been called.
+ */
+
+METHODDEF(void)
+cmyk_ycck_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2, outptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ outptr3 = output_buf[3][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
+ g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
+ b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
+ /* K passes through as-is */
+ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
+ inptr += 4;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles grayscale output with no conversion.
+ * The source can be either plain grayscale or YCbCr (since Y == gray).
+ */
+
+METHODDEF(void)
+grayscale_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+ int instride = cinfo->input_components;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
+ inptr += instride;
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles multi-component colorspaces without conversion.
+ * We assume input_components == num_components.
+ */
+
+METHODDEF(void)
+null_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ register int ci;
+ int nc = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ /* It seems fastest to make a separate pass for each component. */
+ for (ci = 0; ci < nc; ci++) {
+ inptr = *input_buf;
+ outptr = output_buf[ci][output_row];
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
+ inptr += nc;
+ }
+ }
+ input_buf++;
+ output_row++;
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+null_method (j_compress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for input colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_converter (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_converter));
+ cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+ /* set start_pass to null method until we find out differently */
+ cconvert->pub.start_pass = null_method;
+
+ /* Make sure input_components agrees with in_color_space */
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->input_components != 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ if (cinfo->input_components != RGB_PIXELSIZE)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+#endif /* else share code with YCbCr */
+
+ case JCS_YCbCr:
+ if (cinfo->input_components != 3)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->input_components != 4)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->input_components < 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+ }
+
+ /* Check num_components, set conversion method based on requested space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_GRAYSCALE)
+ cconvert->pub.color_convert = grayscale_convert;
+ else if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_gray_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = grayscale_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_ycc_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = cmyk_ycck_convert;
+ } else if (cinfo->in_color_space == JCS_YCCK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default: /* allow null conversion of JCS_UNKNOWN */
+ if (cinfo->jpeg_color_space != cinfo->in_color_space ||
+ cinfo->num_components != cinfo->input_components)
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ cconvert->pub.color_convert = null_convert;
+ break;
+ }
+}
diff --git a/SrcShared/jpeg/jcdctmgr.c b/SrcShared/jpeg/jcdctmgr.c
new file mode 100644
index 0000000..61fa79b
--- /dev/null
+++ b/SrcShared/jpeg/jcdctmgr.c
@@ -0,0 +1,387 @@
+/*
+ * jcdctmgr.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the forward-DCT management logic.
+ * This code selects a particular DCT implementation to be used,
+ * and it performs related housekeeping chores including coefficient
+ * quantization.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ struct jpeg_forward_dct pub; /* public fields */
+
+ /* Pointer to the DCT routine actually in use */
+ forward_DCT_method_ptr do_dct;
+
+ /* The actual post-DCT divisors --- not identical to the quant table
+ * entries, because of scaling (especially for an unnormalized DCT).
+ * Each table is given in normal array order.
+ */
+ DCTELEM * divisors[NUM_QUANT_TBLS];
+
+#ifdef DCT_FLOAT_SUPPORTED
+ /* Same as above for the floating-point case. */
+ float_DCT_method_ptr do_float_dct;
+ FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
+#endif
+} my_fdct_controller;
+
+typedef my_fdct_controller * my_fdct_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ * Verify that all referenced Q-tables are present, and set up
+ * the divisor table for each one.
+ * In the current implementation, DCT of all components is done during
+ * the first pass, even if only some components will be output in the
+ * first scan. Hence all components should be examined here.
+ */
+
+METHODDEF(void)
+start_pass_fdctmgr (j_compress_ptr cinfo)
+{
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ int ci, qtblno, i;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtbl;
+ DCTELEM * dtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ qtblno = compptr->quant_tbl_no;
+ /* Make sure specified quantization table is present */
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ qtbl = cinfo->quant_tbl_ptrs[qtblno];
+ /* Compute divisors for this quant table */
+ /* We may do this more than once for same table, but it's not a big deal */
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ /* For LL&M IDCT method, divisors are equal to raw quantization
+ * coefficients multiplied by 8 (to counteract scaling).
+ */
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ }
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ */
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = (DCTELEM)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-3);
+ }
+ }
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ * What's actually stored is 1/divisor so that the inner loop can
+ * use a multiplication rather than a division.
+ */
+ FAST_FLOAT * fdtbl;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ if (fdct->float_divisors[qtblno] == NULL) {
+ fdct->float_divisors[qtblno] = (FAST_FLOAT *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(FAST_FLOAT));
+ }
+ fdtbl = fdct->float_divisors[qtblno];
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fdtbl[i] = (FAST_FLOAT)
+ (1.0 / (((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col] * 8.0)));
+ i++;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Perform forward DCT on one or more blocks of a component.
+ *
+ * The input samples are taken from the sample_data[] array starting at
+ * position start_row/start_col, and moving to the right for any additional
+ * blocks. The quantized coefficients are returned in coef_blocks[].
+ */
+
+METHODDEF(void)
+forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for integer DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ forward_DCT_method_ptr do_dct = fdct->do_dct;
+ DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
+ DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+ /* Load data into workspace, applying unsigned->signed conversion */
+ { register DCTELEM *workspaceptr;
+ register JSAMPROW elemptr;
+ register int elemr;
+
+ workspaceptr = workspace;
+ for (elemr = 0; elemr < DCTSIZE; elemr++) {
+ elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8 /* unroll the inner loop */
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+#else
+ { register int elemc;
+ for (elemc = DCTSIZE; elemc > 0; elemc--) {
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Perform the DCT */
+ (*do_dct) (workspace);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register DCTELEM temp, qval;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ qval = divisors[i];
+ temp = workspace[i];
+ /* Divide the coefficient value by qval, ensuring proper rounding.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ *
+ * In most files, at least half of the output values will be zero
+ * (at default quantization settings, more like three-quarters...)
+ * so we should ensure that this case is fast. On many machines,
+ * a comparison is enough cheaper than a divide to make a special test
+ * a win. Since both inputs will be nonnegative, we need only test
+ * for a < b to discover whether a/b is 0.
+ * If your machine's division is fast enough, define FAST_DIVIDE.
+ */
+#ifdef FAST_DIVIDE
+#define DIVIDE_BY(a,b) a /= b
+#else
+#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
+#endif
+ if (temp < 0) {
+ temp = -temp;
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ temp = -temp;
+ } else {
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ }
+ output_ptr[i] = (JCOEF) temp;
+ }
+ }
+ }
+}
+
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+METHODDEF(void)
+forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for floating-point DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ float_DCT_method_ptr do_dct = fdct->do_float_dct;
+ FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
+ FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+ /* Load data into workspace, applying unsigned->signed conversion */
+ { register FAST_FLOAT *workspaceptr;
+ register JSAMPROW elemptr;
+ register int elemr;
+
+ workspaceptr = workspace;
+ for (elemr = 0; elemr < DCTSIZE; elemr++) {
+ elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8 /* unroll the inner loop */
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+#else
+ { register int elemc;
+ for (elemc = DCTSIZE; elemc > 0; elemc--) {
+ *workspaceptr++ = (FAST_FLOAT)
+ (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ }
+ }
+#endif
+ }
+ }
+
+ /* Perform the DCT */
+ (*do_dct) (workspace);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register FAST_FLOAT temp;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* Apply the quantization and scaling factor */
+ temp = workspace[i] * divisors[i];
+ /* Round to nearest integer.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ * The maximum coefficient size is +-16K (for 12-bit data), so this
+ * code should work for either 16-bit or 32-bit ints.
+ */
+ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+ }
+ }
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
+
+
+/*
+ * Initialize FDCT manager.
+ */
+
+GLOBAL(void)
+jinit_forward_dct (j_compress_ptr cinfo)
+{
+ my_fdct_ptr fdct;
+ int i;
+
+ fdct = (my_fdct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_fdct_controller));
+ cinfo->fdct = (struct jpeg_forward_dct *) fdct;
+ fdct->pub.start_pass = start_pass_fdctmgr;
+
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ fdct->pub.forward_DCT = forward_DCT;
+ fdct->do_dct = jpeg_fdct_islow;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ fdct->pub.forward_DCT = forward_DCT;
+ fdct->do_dct = jpeg_fdct_ifast;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ fdct->pub.forward_DCT = forward_DCT_float;
+ fdct->do_float_dct = jpeg_fdct_float;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+
+ /* Mark divisor tables unallocated */
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ fdct->divisors[i] = NULL;
+#ifdef DCT_FLOAT_SUPPORTED
+ fdct->float_divisors[i] = NULL;
+#endif
+ }
+}
diff --git a/SrcShared/jpeg/jchuff.c b/SrcShared/jpeg/jchuff.c
new file mode 100644
index 0000000..f235250
--- /dev/null
+++ b/SrcShared/jpeg/jchuff.c
@@ -0,0 +1,909 @@
+/*
+ * jchuff.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU. To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jchuff.h" /* Declarations shared with jcphuff.c */
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).put_buffer = (src).put_buffer, \
+ (dest).put_bits = (src).put_bits, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ struct jpeg_entropy_encoder pub; /* public fields */
+
+ savable_state saved; /* Bit buffer & DC state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
+ long * dc_count_ptrs[NUM_HUFF_TBLS];
+ long * ac_count_ptrs[NUM_HUFF_TBLS];
+#endif
+} huff_entropy_encoder;
+
+typedef huff_entropy_encoder * huff_entropy_ptr;
+
+/* Working state while writing an MCU.
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ savable_state cur; /* Current bit buffer & DC state */
+ j_compress_ptr cinfo; /* dump_buffer needs access to this */
+} working_state;
+
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
+#ifdef ENTROPY_OPT_SUPPORTED
+METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
+#endif
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, dctbl, actbl;
+ jpeg_component_info * compptr;
+
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ entropy->pub.encode_mcu = encode_mcu_gather;
+ entropy->pub.finish_pass = finish_pass_gather;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ entropy->pub.encode_mcu = encode_mcu_huff;
+ entropy->pub.finish_pass = finish_pass_huff;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ /* Check for invalid table indexes */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+ if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->dc_count_ptrs[dctbl] == NULL)
+ entropy->dc_count_ptrs[dctbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
+ if (entropy->ac_count_ptrs[actbl] == NULL)
+ entropy->ac_count_ptrs[actbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
+#endif
+ } else {
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Initialize bit buffer to empty */
+ entropy->saved.put_buffer = 0;
+ entropy->saved.put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ *
+ * Note this is also used by jcphuff.c.
+ */
+
+GLOBAL(void)
+jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ c_derived_tbl *dtbl;
+ int p, i, l, lastp, si, maxsymbol;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (c_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_derived_tbl));
+ dtbl = *pdtbl;
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ lastp = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure C.3: generate encoding tables */
+ /* These are code and size indexed by symbol value */
+
+ /* Set all codeless symbols to have code length 0;
+ * this lets us detect duplicate VAL entries here, and later
+ * allows emit_bits to detect any attempt to emit such symbols.
+ */
+ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
+
+ /* This is also a convenient place to check for out-of-range
+ * and duplicated VAL entries. We allow 0..255 for AC symbols
+ * but only 0..15 for DC. (We could constrain them further
+ * based on data depth and mode, but this seems enough.)
+ */
+ maxsymbol = isDC ? 15 : 255;
+
+ for (p = 0; p < lastp; p++) {
+ i = htbl->huffval[p];
+ if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ dtbl->ehufco[i] = huffcode[p];
+ dtbl->ehufsi[i] = huffsize[p];
+ }
+}
+
+
+/* Outputting bytes to the file */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte(state,val,action) \
+ { *(state)->next_output_byte++ = (JOCTET) (val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (! dump_buffer(state)) \
+ { action; } }
+
+
+LOCAL(boolean)
+dump_buffer (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+ struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (state->cinfo))
+ return FALSE;
+ /* After a successful buffer dump, must reset buffer pointers */
+ state->next_output_byte = dest->next_output_byte;
+ state->free_in_buffer = dest->free_in_buffer;
+ return TRUE;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = state->cur.put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte(state, c, return FALSE);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte(state, 0, return FALSE);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ state->cur.put_buffer = put_buffer; /* update state variables */
+ state->cur.put_bits = put_bits;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+flush_bits (working_state * state)
+{
+ if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
+ return FALSE;
+ state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
+ state->cur.put_bits = 0;
+ return TRUE;
+}
+
+
+/* Encode a single block's worth of coefficients */
+
+LOCAL(boolean)
+encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl, c_derived_tbl *actbl)
+{
+ register int temp, temp2;
+ register int nbits;
+ register int k, r, i;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = temp2 = block[0] - last_dc_val;
+
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit the Huffman-coded symbol for the number of bits */
+ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ if (! emit_bits(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
+ return FALSE;
+ r -= 16;
+ }
+
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit Huffman symbol for run length / number of bits */
+ i = (r << 4) + nbits;
+ if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (! emit_bits(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart (working_state * state, int restart_num)
+{
+ int ci;
+
+ if (! flush_bits(state))
+ return FALSE;
+
+ emit_byte(state, 0xFF, return FALSE);
+ emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
+ state->cur.last_dc_val[ci] = 0;
+
+ /* The restart counter is not updated until we successfully write the MCU. */
+
+ return TRUE;
+}
+
+
+/*
+ * Encode and output one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ working_state state;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Load up working state */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! emit_restart(&state, entropy->next_restart_num))
+ return FALSE;
+ }
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ if (! encode_one_block(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ return FALSE;
+ /* Update last_dc_val */
+ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ /* Completed MCU, so update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ working_state state;
+
+ /* Load up working state ... flush_bits needs it */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Flush out the last data */
+ if (! flush_bits(&state))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+ /* Update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+
+/* Process a single block's worth of coefficients */
+
+LOCAL(void)
+htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+ long dc_counts[], long ac_counts[])
+{
+ register int temp;
+ register int nbits;
+ register int k, r;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = block[0] - last_dc_val;
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count the Huffman symbol for the number of bits */
+ dc_counts[nbits]++;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ ac_counts[0xF0]++;
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count Huffman symbol for run length / number of bits */
+ ac_counts[(r << 4) + nbits]++;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ ac_counts[0]++;
+}
+
+
+/*
+ * Trial-encode one MCU's worth of Huffman-compressed coefficients.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(boolean)
+encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Take care of restart intervals if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Update restart state */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
+ entropy->dc_count_ptrs[compptr->dc_tbl_no],
+ entropy->ac_count_ptrs[compptr->ac_tbl_no]);
+ entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Generate the best Huffman code table for the given counts, fill htbl.
+ * Note this is also used by jcphuff.c.
+ *
+ * The JPEG standard requires that no symbol be assigned a codeword of all
+ * one bits (so that padding bits added at the end of a compressed segment
+ * can't look like a valid code). Because of the canonical ordering of
+ * codewords, this just means that there must be an unused slot in the
+ * longest codeword length category. Section K.2 of the JPEG spec suggests
+ * reserving such a slot by pretending that symbol 256 is a valid symbol
+ * with count 1. In theory that's not optimal; giving it count zero but
+ * including it in the symbol set anyway should give a better Huffman code.
+ * But the theoretically better code actually seems to come out worse in
+ * practice, because it produces more all-ones bytes (which incur stuffed
+ * zero bytes in the final file). In any case the difference is tiny.
+ *
+ * The JPEG standard requires Huffman codes to be no more than 16 bits long.
+ * If some symbols have a very small but nonzero probability, the Huffman tree
+ * must be adjusted to meet the code length restriction. We currently use
+ * the adjustment method suggested in JPEG section K.2. This method is *not*
+ * optimal; it may not choose the best possible limited-length code. But
+ * typically only very-low-frequency symbols will be given less-than-optimal
+ * lengths, so the code is almost optimal. Experimental comparisons against
+ * an optimal limited-length-code algorithm indicate that the difference is
+ * microscopic --- usually less than a hundredth of a percent of total size.
+ * So the extra complexity of an optimal algorithm doesn't seem worthwhile.
+ */
+
+GLOBAL(void)
+jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
+{
+#define MAX_CLEN 32 /* assumed maximum initial code length */
+ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
+ int codesize[257]; /* codesize[k] = code length of symbol k */
+ int others[257]; /* next symbol in current branch of tree */
+ int c1, c2;
+ int p, i, j;
+ long v;
+
+ /* This algorithm is explained in section K.2 of the JPEG standard */
+
+ MEMZERO(bits, SIZEOF(bits));
+ MEMZERO(codesize, SIZEOF(codesize));
+ for (i = 0; i < 257; i++)
+ others[i] = -1; /* init links to empty */
+
+ freq[256] = 1; /* make sure 256 has a nonzero count */
+ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
+ * that no real symbol is given code-value of all ones, because 256
+ * will be placed last in the largest codeword category.
+ */
+
+ /* Huffman's basic algorithm to assign optimal code lengths to symbols */
+
+ for (;;) {
+ /* Find the smallest nonzero frequency, set c1 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c1 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v) {
+ v = freq[i];
+ c1 = i;
+ }
+ }
+
+ /* Find the next smallest nonzero frequency, set c2 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c2 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v && i != c1) {
+ v = freq[i];
+ c2 = i;
+ }
+ }
+
+ /* Done if we've merged everything into one frequency */
+ if (c2 < 0)
+ break;
+
+ /* Else merge the two counts/trees */
+ freq[c1] += freq[c2];
+ freq[c2] = 0;
+
+ /* Increment the codesize of everything in c1's tree branch */
+ codesize[c1]++;
+ while (others[c1] >= 0) {
+ c1 = others[c1];
+ codesize[c1]++;
+ }
+
+ others[c1] = c2; /* chain c2 onto c1's tree branch */
+
+ /* Increment the codesize of everything in c2's tree branch */
+ codesize[c2]++;
+ while (others[c2] >= 0) {
+ c2 = others[c2];
+ codesize[c2]++;
+ }
+ }
+
+ /* Now count the number of symbols of each code length */
+ for (i = 0; i <= 256; i++) {
+ if (codesize[i]) {
+ /* The JPEG standard seems to think that this can't happen, */
+ /* but I'm paranoid... */
+ if (codesize[i] > MAX_CLEN)
+ ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
+
+ bits[codesize[i]]++;
+ }
+ }
+
+ /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+ * Huffman procedure assigned any such lengths, we must adjust the coding.
+ * Here is what the JPEG spec says about how this next bit works:
+ * Since symbols are paired for the longest Huffman code, the symbols are
+ * removed from this length category two at a time. The prefix for the pair
+ * (which is one bit shorter) is allocated to one of the pair; then,
+ * skipping the BITS entry for that prefix length, a code word from the next
+ * shortest nonzero BITS entry is converted into a prefix for two code words
+ * one bit longer.
+ */
+
+ for (i = MAX_CLEN; i > 16; i--) {
+ while (bits[i] > 0) {
+ j = i - 2; /* find length of new prefix to be used */
+ while (bits[j] == 0)
+ j--;
+
+ bits[i] -= 2; /* remove two symbols */
+ bits[i-1]++; /* one goes in this length */
+ bits[j+1] += 2; /* two new symbols in this length */
+ bits[j]--; /* symbol of this length is now a prefix */
+ }
+ }
+
+ /* Remove the count for the pseudo-symbol 256 from the largest codelength */
+ while (bits[i] == 0) /* find largest codelength still in use */
+ i--;
+ bits[i]--;
+
+ /* Return final symbol counts (only for lengths 0..16) */
+ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
+
+ /* Return a list of the symbols sorted by code length */
+ /* It's not real clear to me why we don't need to consider the codelength
+ * changes made above, but the JPEG spec seems to think this works.
+ */
+ p = 0;
+ for (i = 1; i <= MAX_CLEN; i++) {
+ for (j = 0; j <= 255; j++) {
+ if (codesize[j] == i) {
+ htbl->huffval[p] = (UINT8) j;
+ p++;
+ }
+ }
+ }
+
+ /* Set sent_table FALSE so updated table will be written to JPEG file. */
+ htbl->sent_table = FALSE;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, dctbl, actbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did_dc[NUM_HUFF_TBLS];
+ boolean did_ac[NUM_HUFF_TBLS];
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ MEMZERO(did_dc, SIZEOF(did_dc));
+ MEMZERO(did_ac, SIZEOF(did_ac));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (! did_dc[dctbl]) {
+ htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
+ did_dc[dctbl] = TRUE;
+ }
+ if (! did_ac[actbl]) {
+ htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
+ did_ac[actbl] = TRUE;
+ }
+ }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_huff_encoder (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy;
+ int i;
+
+ entropy = (huff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(huff_entropy_encoder));
+ cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ entropy->pub.start_pass = start_pass_huff;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+#ifdef ENTROPY_OPT_SUPPORTED
+ entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
+#endif
+ }
+}
diff --git a/SrcShared/jpeg/jchuff.h b/SrcShared/jpeg/jchuff.h
new file mode 100644
index 0000000..a9599fc
--- /dev/null
+++ b/SrcShared/jpeg/jchuff.h
@@ -0,0 +1,47 @@
+/*
+ * jchuff.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy encoding routines
+ * that are shared between the sequential encoder (jchuff.c) and the
+ * progressive encoder (jcphuff.c). No other modules need to see these.
+ */
+
+/* The legal range of a DCT coefficient is
+ * -1024 .. +1023 for 8-bit data;
+ * -16384 .. +16383 for 12-bit data.
+ * Hence the magnitude should always fit in 10 or 14 bits respectively.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MAX_COEF_BITS 10
+#else
+#define MAX_COEF_BITS 14
+#endif
+
+/* Derived data constructed for each Huffman table */
+
+typedef struct {
+ unsigned int ehufco[256]; /* code for each symbol */
+ char ehufsi[256]; /* length of code for each symbol */
+ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
+} c_derived_tbl;
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_c_derived_tbl jMkCDerived
+#define jpeg_gen_optimal_table jGenOptTbl
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_c_derived_tbl
+ JPP((j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl ** pdtbl));
+
+/* Generate an optimal table definition given the specified counts */
+EXTERN(void) jpeg_gen_optimal_table
+ JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
diff --git a/SrcShared/jpeg/jcinit.c b/SrcShared/jpeg/jcinit.c
new file mode 100644
index 0000000..5efffe3
--- /dev/null
+++ b/SrcShared/jpeg/jcinit.c
@@ -0,0 +1,72 @@
+/*
+ * jcinit.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains initialization logic for the JPEG compressor.
+ * This routine is in charge of selecting the modules to be executed and
+ * making an initialization call to each one.
+ *
+ * Logically, this code belongs in jcmaster.c. It's split out because
+ * linking this routine implies linking the entire compression library.
+ * For a transcoding-only application, we want to be able to use jcmaster.c
+ * without linking in the whole library.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Master selection of compression modules.
+ * This is done once at the start of processing an image. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ */
+
+GLOBAL(void)
+jinit_compress_master (j_compress_ptr cinfo)
+{
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, FALSE /* full compression */);
+
+ /* Preprocessing */
+ if (! cinfo->raw_data_in) {
+ jinit_color_converter(cinfo);
+ jinit_downsampler(cinfo);
+ jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
+ }
+ /* Forward DCT */
+ jinit_forward_dct(cinfo);
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ jinit_phuff_encoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_huff_encoder(cinfo);
+ }
+
+ /* Need a full-image coefficient buffer in any multi-pass mode. */
+ jinit_c_coef_controller(cinfo,
+ (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
+ jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
diff --git a/SrcShared/jpeg/jcmainct.c b/SrcShared/jpeg/jcmainct.c
new file mode 100644
index 0000000..e0279a7
--- /dev/null
+++ b/SrcShared/jpeg/jcmainct.c
@@ -0,0 +1,293 @@
+/*
+ * jcmainct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for compression.
+ * The main buffer lies between the pre-processor and the JPEG
+ * compressor proper; it holds downsampled data in the JPEG colorspace.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Note: currently, there is no operating mode in which a full-image buffer
+ * is needed at this step. If there were, that mode could not be used with
+ * "raw data" input, since this module is bypassed in that case. However,
+ * we've left the code here for possible use in special applications.
+ */
+#undef FULL_MAIN_BUFFER_SUPPORTED
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_main_controller pub; /* public fields */
+
+ JDIMENSION cur_iMCU_row; /* number of current iMCU row */
+ JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
+ boolean suspended; /* remember if we suspended output */
+ J_BUF_MODE pass_mode; /* current operating mode */
+
+ /* If using just a strip buffer, this points to the entire set of buffers
+ * (we allocate one for each component). In the full-image case, this
+ * points to the currently accessible strips of the virtual arrays.
+ */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* If using full-image storage, this array holds pointers to virtual-array
+ * control blocks for each component. Unused if not full-image storage.
+ */
+ jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+METHODDEF(void) process_data_buffer_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Do nothing in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ main->cur_iMCU_row = 0; /* initialize counters */
+ main->rowgroup_ctr = 0;
+ main->suspended = FALSE;
+ main->pass_mode = pass_mode; /* save mode for use by process_data */
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ if (main->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ main->pub.process_data = process_data_simple_main;
+ break;
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ case JBUF_SAVE_SOURCE:
+ case JBUF_CRANK_DEST:
+ case JBUF_SAVE_AND_PASS:
+ if (main->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ main->pub.process_data = process_data_buffer_main;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This routine handles the simple pass-through mode,
+ * where we have only a strip buffer.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Read input data if we haven't filled the main buffer yet */
+ if (main->rowgroup_ctr < DCTSIZE)
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) DCTSIZE);
+
+ /* If we don't have a full iMCU row buffered, return to application for
+ * more data. Note that preprocessor will always pad to fill the iMCU row
+ * at the bottom of the image.
+ */
+ if (main->rowgroup_ctr != DCTSIZE)
+ return;
+
+ /* Send the completed row to the compressor */
+ if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+
+/*
+ * Process some data.
+ * This routine handles all of the modes that use a full-size buffer.
+ */
+
+METHODDEF(void)
+process_data_buffer_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci;
+ jpeg_component_info *compptr;
+ boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Realign the virtual buffers if at the start of an iMCU row. */
+ if (main->rowgroup_ctr == 0) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, main->whole_image[ci],
+ main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE),
+ (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing);
+ }
+ /* In a read pass, pretend we just read some source data. */
+ if (! writing) {
+ *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
+ main->rowgroup_ctr = DCTSIZE;
+ }
+ }
+
+ /* If a write pass, read input data until the current iMCU row is full. */
+ /* Note: preprocessor will pad if necessary to fill the last iMCU row. */
+ if (writing) {
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) DCTSIZE);
+ /* Return to application if we need more data to fill the iMCU row. */
+ if (main->rowgroup_ctr < DCTSIZE)
+ return;
+ }
+
+ /* Emit data, unless this is a sink-only pass. */
+ if (main->pass_mode != JBUF_SAVE_SOURCE) {
+ if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ }
+
+ /* If get here, we are done with this iMCU row. Mark buffer empty. */
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+#endif /* FULL_MAIN_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci;
+ jpeg_component_info *compptr;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_c_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ /* We don't need to create a buffer in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ /* Create the buffer. It holds downsampled data, so each component
+ * may be of a different size.
+ */
+ if (need_full_buffer) {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component */
+ /* Note we pad the bottom to a multiple of the iMCU height */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ compptr->width_in_blocks * DCTSIZE,
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor) * DCTSIZE,
+ (JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ main->whole_image[0] = NULL; /* flag for no virtual arrays */
+#endif
+ /* Allocate a strip buffer for each component */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_blocks * DCTSIZE,
+ (JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
+ }
+ }
+}
diff --git a/SrcShared/jpeg/jcmarker.c b/SrcShared/jpeg/jcmarker.c
new file mode 100644
index 0000000..3d1e6c6
--- /dev/null
+++ b/SrcShared/jpeg/jcmarker.c
@@ -0,0 +1,664 @@
+/*
+ * jcmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write JPEG datastream markers.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_writer pub; /* public fields */
+
+ unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
+} my_marker_writer;
+
+typedef my_marker_writer * my_marker_ptr;
+
+
+/*
+ * Basic output routines.
+ *
+ * Note that we do not support suspension while writing a marker.
+ * Therefore, an application using suspension must ensure that there is
+ * enough buffer space for the initial markers (typ. 600-700 bytes) before
+ * calling jpeg_start_compress, and enough space to write the trailing EOI
+ * (a few bytes) before calling jpeg_finish_compress. Multipass compression
+ * modes are not supported at all with suspension, so those two are the only
+ * points where markers will be written.
+ */
+
+LOCAL(void)
+emit_byte (j_compress_ptr cinfo, int val)
+/* Emit a byte */
+{
+ struct jpeg_destination_mgr * dest = cinfo->dest;
+
+ *(dest->next_output_byte)++ = (JOCTET) val;
+ if (--dest->free_in_buffer == 0) {
+ if (! (*dest->empty_output_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+}
+
+
+LOCAL(void)
+emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+/* Emit a marker code */
+{
+ emit_byte(cinfo, 0xFF);
+ emit_byte(cinfo, (int) mark);
+}
+
+
+LOCAL(void)
+emit_2bytes (j_compress_ptr cinfo, int value)
+/* Emit a 2-byte integer; these are always MSB first in JPEG files */
+{
+ emit_byte(cinfo, (value >> 8) & 0xFF);
+ emit_byte(cinfo, value & 0xFF);
+}
+
+
+/*
+ * Routines to write specific marker types.
+ */
+
+LOCAL(int)
+emit_dqt (j_compress_ptr cinfo, int index)
+/* Emit a DQT marker */
+/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
+{
+ JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+ int prec;
+ int i;
+
+ if (qtbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
+
+ prec = 0;
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (qtbl->quantval[i] > 255)
+ prec = 1;
+ }
+
+ if (! qtbl->sent_table) {
+ emit_marker(cinfo, M_DQT);
+
+ emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+
+ emit_byte(cinfo, index + (prec<<4));
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* The table entries must be emitted in zigzag order. */
+ unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
+ if (prec)
+ emit_byte(cinfo, (int) (qval >> 8));
+ emit_byte(cinfo, (int) (qval & 0xFF));
+ }
+
+ qtbl->sent_table = TRUE;
+ }
+
+ return prec;
+}
+
+
+LOCAL(void)
+emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+/* Emit a DHT marker */
+{
+ JHUFF_TBL * htbl;
+ int length, i;
+
+ if (is_ac) {
+ htbl = cinfo->ac_huff_tbl_ptrs[index];
+ index += 0x10; /* output index has AC bit set */
+ } else {
+ htbl = cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
+
+ if (! htbl->sent_table) {
+ emit_marker(cinfo, M_DHT);
+
+ length = 0;
+ for (i = 1; i <= 16; i++)
+ length += htbl->bits[i];
+
+ emit_2bytes(cinfo, length + 2 + 1 + 16);
+ emit_byte(cinfo, index);
+
+ for (i = 1; i <= 16; i++)
+ emit_byte(cinfo, htbl->bits[i]);
+
+ for (i = 0; i < length; i++)
+ emit_byte(cinfo, htbl->huffval[i]);
+
+ htbl->sent_table = TRUE;
+ }
+}
+
+
+LOCAL(void)
+emit_dac (j_compress_ptr cinfo)
+/* Emit a DAC marker */
+/* Since the useful info is so small, we want to emit all the tables in */
+/* one DAC marker. Therefore this routine does its own scan of the table. */
+{
+#ifdef C_ARITH_CODING_SUPPORTED
+ char dc_in_use[NUM_ARITH_TBLS];
+ char ac_in_use[NUM_ARITH_TBLS];
+ int length, i;
+ jpeg_component_info *compptr;
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ dc_in_use[i] = ac_in_use[i] = 0;
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ dc_in_use[compptr->dc_tbl_no] = 1;
+ ac_in_use[compptr->ac_tbl_no] = 1;
+ }
+
+ length = 0;
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ length += dc_in_use[i] + ac_in_use[i];
+
+ emit_marker(cinfo, M_DAC);
+
+ emit_2bytes(cinfo, length*2 + 2);
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ if (dc_in_use[i]) {
+ emit_byte(cinfo, i);
+ emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+ }
+ if (ac_in_use[i]) {
+ emit_byte(cinfo, i + 0x10);
+ emit_byte(cinfo, cinfo->arith_ac_K[i]);
+ }
+ }
+#endif /* C_ARITH_CODING_SUPPORTED */
+}
+
+
+LOCAL(void)
+emit_dri (j_compress_ptr cinfo)
+/* Emit a DRI marker */
+{
+ emit_marker(cinfo, M_DRI);
+
+ emit_2bytes(cinfo, 4); /* fixed length */
+
+ emit_2bytes(cinfo, (int) cinfo->restart_interval);
+}
+
+
+LOCAL(void)
+emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+/* Emit a SOF marker */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, code);
+
+ emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
+
+ /* Make sure image isn't bigger than SOF field can handle */
+ if ((long) cinfo->image_height > 65535L ||
+ (long) cinfo->image_width > 65535L)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+
+ emit_byte(cinfo, cinfo->data_precision);
+ emit_2bytes(cinfo, (int) cinfo->image_height);
+ emit_2bytes(cinfo, (int) cinfo->image_width);
+
+ emit_byte(cinfo, cinfo->num_components);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ emit_byte(cinfo, compptr->component_id);
+ emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
+ emit_byte(cinfo, compptr->quant_tbl_no);
+ }
+}
+
+
+LOCAL(void)
+emit_sos (j_compress_ptr cinfo)
+/* Emit a SOS marker */
+{
+ int i, td, ta;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, M_SOS);
+
+ emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
+
+ emit_byte(cinfo, cinfo->comps_in_scan);
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ emit_byte(cinfo, compptr->component_id);
+ td = compptr->dc_tbl_no;
+ ta = compptr->ac_tbl_no;
+ if (cinfo->progressive_mode) {
+ /* Progressive mode: only DC or only AC tables are used in one scan;
+ * furthermore, Huffman coding of DC refinement uses no table at all.
+ * We emit 0 for unused field(s); this is recommended by the P&M text
+ * but does not seem to be specified in the standard.
+ */
+ if (cinfo->Ss == 0) {
+ ta = 0; /* DC scan */
+ if (cinfo->Ah != 0 && !cinfo->arith_code)
+ td = 0; /* no DC table either */
+ } else {
+ td = 0; /* AC scan */
+ }
+ }
+ emit_byte(cinfo, (td << 4) + ta);
+ }
+
+ emit_byte(cinfo, cinfo->Ss);
+ emit_byte(cinfo, cinfo->Se);
+ emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
+}
+
+
+LOCAL(void)
+emit_jfif_app0 (j_compress_ptr cinfo)
+/* Emit a JFIF-compliant APP0 marker */
+{
+ /*
+ * Length of APP0 block (2 bytes)
+ * Block ID (4 bytes - ASCII "JFIF")
+ * Zero byte (1 byte to terminate the ID string)
+ * Version Major, Minor (2 bytes - major first)
+ * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
+ * Xdpu (2 bytes - dots per unit horizontal)
+ * Ydpu (2 bytes - dots per unit vertical)
+ * Thumbnail X size (1 byte)
+ * Thumbnail Y size (1 byte)
+ */
+
+ emit_marker(cinfo, M_APP0);
+
+ emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
+
+ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0x49);
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0);
+ emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
+ emit_byte(cinfo, cinfo->JFIF_minor_version);
+ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
+ emit_2bytes(cinfo, (int) cinfo->X_density);
+ emit_2bytes(cinfo, (int) cinfo->Y_density);
+ emit_byte(cinfo, 0); /* No thumbnail image */
+ emit_byte(cinfo, 0);
+}
+
+
+LOCAL(void)
+emit_adobe_app14 (j_compress_ptr cinfo)
+/* Emit an Adobe APP14 marker */
+{
+ /*
+ * Length of APP14 block (2 bytes)
+ * Block ID (5 bytes - ASCII "Adobe")
+ * Version Number (2 bytes - currently 100)
+ * Flags0 (2 bytes - currently 0)
+ * Flags1 (2 bytes - currently 0)
+ * Color transform (1 byte)
+ *
+ * Although Adobe TN 5116 mentions Version = 101, all the Adobe files
+ * now in circulation seem to use Version = 100, so that's what we write.
+ *
+ * We write the color transform byte as 1 if the JPEG color space is
+ * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
+ * whether the encoder performed a transformation, which is pretty useless.
+ */
+
+ emit_marker(cinfo, M_APP14);
+
+ emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
+
+ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
+ emit_byte(cinfo, 0x64);
+ emit_byte(cinfo, 0x6F);
+ emit_byte(cinfo, 0x62);
+ emit_byte(cinfo, 0x65);
+ emit_2bytes(cinfo, 100); /* Version */
+ emit_2bytes(cinfo, 0); /* Flags0 */
+ emit_2bytes(cinfo, 0); /* Flags1 */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_YCbCr:
+ emit_byte(cinfo, 1); /* Color transform = 1 */
+ break;
+ case JCS_YCCK:
+ emit_byte(cinfo, 2); /* Color transform = 2 */
+ break;
+ default:
+ emit_byte(cinfo, 0); /* Color transform = 0 */
+ break;
+ }
+}
+
+
+/*
+ * These routines allow writing an arbitrary marker with parameters.
+ * The only intended use is to emit COM or APPn markers after calling
+ * write_file_header and before calling write_frame_header.
+ * Other uses are not guaranteed to produce desirable results.
+ * Counting the parameter bytes properly is the caller's responsibility.
+ */
+
+METHODDEF(void)
+write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+/* Emit an arbitrary marker header */
+{
+ if (datalen > (unsigned int) 65533) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ emit_marker(cinfo, (JPEG_MARKER) marker);
+
+ emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
+}
+
+METHODDEF(void)
+write_marker_byte (j_compress_ptr cinfo, int val)
+/* Emit one byte of marker parameters following write_marker_header */
+{
+ emit_byte(cinfo, val);
+}
+
+
+/*
+ * Write datastream header.
+ * This consists of an SOI and optional APPn markers.
+ * We recommend use of the JFIF marker, but not the Adobe marker,
+ * when using YCbCr or grayscale data. The JFIF marker should NOT
+ * be used for any other JPEG colorspace. The Adobe marker is helpful
+ * to distinguish RGB, CMYK, and YCCK colorspaces.
+ * Note that an application can write additional header markers after
+ * jpeg_start_compress returns.
+ */
+
+METHODDEF(void)
+write_file_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ emit_marker(cinfo, M_SOI); /* first the SOI */
+
+ /* SOI is defined to reset restart interval to 0 */
+ marker->last_restart_interval = 0;
+
+ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
+ emit_jfif_app0(cinfo);
+ if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
+ emit_adobe_app14(cinfo);
+}
+
+
+/*
+ * Write frame header.
+ * This consists of DQT and SOFn markers.
+ * Note that we do not emit the SOF until we have emitted the DQT(s).
+ * This avoids compatibility problems with incorrect implementations that
+ * try to error-check the quant table numbers as soon as they see the SOF.
+ */
+
+METHODDEF(void)
+write_frame_header (j_compress_ptr cinfo)
+{
+ int ci, prec;
+ boolean is_baseline;
+ jpeg_component_info *compptr;
+
+ /* Emit DQT for each quantization table.
+ * Note that emit_dqt() suppresses any duplicate tables.
+ */
+ prec = 0;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prec += emit_dqt(cinfo, compptr->quant_tbl_no);
+ }
+ /* now prec is nonzero iff there are any 16-bit quant tables. */
+
+ /* Check for a non-baseline specification.
+ * Note we assume that Huffman table numbers won't be changed later.
+ */
+ if (cinfo->arith_code || cinfo->progressive_mode ||
+ cinfo->data_precision != 8) {
+ is_baseline = FALSE;
+ } else {
+ is_baseline = TRUE;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+ is_baseline = FALSE;
+ }
+ if (prec && is_baseline) {
+ is_baseline = FALSE;
+ /* If it's baseline except for quantizer size, warn the user */
+ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+ }
+ }
+
+ /* Emit the proper SOF marker */
+ if (cinfo->arith_code) {
+ emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
+ } else {
+ if (cinfo->progressive_mode)
+ emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
+ else if (is_baseline)
+ emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
+ else
+ emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
+ }
+}
+
+
+/*
+ * Write scan header.
+ * This consists of DHT or DAC markers, optional DRI, and SOS.
+ * Compressed data will be written following the SOS.
+ */
+
+METHODDEF(void)
+write_scan_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ int i;
+ jpeg_component_info *compptr;
+
+ if (cinfo->arith_code) {
+ /* Emit arith conditioning info. We may have some duplication
+ * if the file has multiple scans, but it's so small it's hardly
+ * worth worrying about.
+ */
+ emit_dac(cinfo);
+ } else {
+ /* Emit Huffman tables.
+ * Note that emit_dht() suppresses any duplicate tables.
+ */
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ if (cinfo->progressive_mode) {
+ /* Progressive mode: only DC or only AC tables are used in one scan */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ } else {
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ } else {
+ /* Sequential mode: need both DC and AC tables */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ }
+ }
+
+ /* Emit DRI if required --- note that DRI value could change for each scan.
+ * We avoid wasting space with unnecessary DRIs, however.
+ */
+ if (cinfo->restart_interval != marker->last_restart_interval) {
+ emit_dri(cinfo);
+ marker->last_restart_interval = cinfo->restart_interval;
+ }
+
+ emit_sos(cinfo);
+}
+
+
+/*
+ * Write datastream trailer.
+ */
+
+METHODDEF(void)
+write_file_trailer (j_compress_ptr cinfo)
+{
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Write an abbreviated table-specification datastream.
+ * This consists of SOI, DQT and DHT tables, and EOI.
+ * Any table that is defined and not marked sent_table = TRUE will be
+ * emitted. Note that all tables will be marked sent_table = TRUE at exit.
+ */
+
+METHODDEF(void)
+write_tables_only (j_compress_ptr cinfo)
+{
+ int i;
+
+ emit_marker(cinfo, M_SOI);
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if (cinfo->quant_tbl_ptrs[i] != NULL)
+ (void) emit_dqt(cinfo, i);
+ }
+
+ if (! cinfo->arith_code) {
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, FALSE);
+ if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, TRUE);
+ }
+ }
+
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Initialize the marker writer module.
+ */
+
+GLOBAL(void)
+jinit_marker_writer (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker;
+
+ /* Create the subobject */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_marker_writer));
+ cinfo->marker = (struct jpeg_marker_writer *) marker;
+ /* Initialize method pointers */
+ marker->pub.write_file_header = write_file_header;
+ marker->pub.write_frame_header = write_frame_header;
+ marker->pub.write_scan_header = write_scan_header;
+ marker->pub.write_file_trailer = write_file_trailer;
+ marker->pub.write_tables_only = write_tables_only;
+ marker->pub.write_marker_header = write_marker_header;
+ marker->pub.write_marker_byte = write_marker_byte;
+ /* Initialize private state */
+ marker->last_restart_interval = 0;
+}
diff --git a/SrcShared/jpeg/jcmaster.c b/SrcShared/jpeg/jcmaster.c
new file mode 100644
index 0000000..aab4020
--- /dev/null
+++ b/SrcShared/jpeg/jcmaster.c
@@ -0,0 +1,590 @@
+/*
+ * jcmaster.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG compressor.
+ * These routines are concerned with parameter validation, initial setup,
+ * and inter-pass control (determining the number of passes and the work
+ * to be done in each pass).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef enum {
+ main_pass, /* input data, also do first output step */
+ huff_opt_pass, /* Huffman code optimization pass */
+ output_pass /* data output pass */
+} c_pass_type;
+
+typedef struct {
+ struct jpeg_comp_master pub; /* public fields */
+
+ c_pass_type pass_type; /* the type of the current pass */
+
+ int pass_number; /* # of passes completed */
+ int total_passes; /* total # of passes needed */
+
+ int scan_number; /* current index in scan_info[] */
+} my_comp_master;
+
+typedef my_comp_master * my_master_ptr;
+
+
+/*
+ * Support routines that do various essential calculations.
+ */
+
+LOCAL(void)
+initial_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+ int ci;
+ jpeg_component_info *compptr;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ /* Sanity check on image dimensions */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+ || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ /* Width of an input scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Fill in the correct component_index value; don't rely on application */
+ compptr->component_index = ci;
+ /* For compression, we never do DCT scaling. */
+ compptr->DCT_scaled_size = DCTSIZE;
+ /* Size in DCT blocks */
+ compptr->width_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->height_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) cinfo->max_h_samp_factor);
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) cinfo->max_v_samp_factor);
+ /* Mark component needed (this flag isn't actually used for compression) */
+ compptr->component_needed = TRUE;
+ }
+
+ /* Compute number of fully interleaved MCU rows (number of times that
+ * main controller will call coefficient controller).
+ */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+}
+
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+
+LOCAL(void)
+validate_script (j_compress_ptr cinfo)
+/* Verify that the scan script in cinfo->scan_info[] is valid; also
+ * determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
+ */
+{
+ const jpeg_scan_info * scanptr;
+ int scanno, ncomps, ci, coefi, thisi;
+ int Ss, Se, Ah, Al;
+ boolean component_sent[MAX_COMPONENTS];
+#ifdef C_PROGRESSIVE_SUPPORTED
+ int * last_bitpos_ptr;
+ int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
+ /* -1 until that coefficient has been seen; then last Al for it */
+#endif
+
+ if (cinfo->num_scans <= 0)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
+
+ /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
+ * for progressive JPEG, no scan can have this.
+ */
+ scanptr = cinfo->scan_info;
+ if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ cinfo->progressive_mode = TRUE;
+ last_bitpos_ptr = & last_bitpos[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (coefi = 0; coefi < DCTSIZE2; coefi++)
+ *last_bitpos_ptr++ = -1;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->progressive_mode = FALSE;
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ component_sent[ci] = FALSE;
+ }
+
+ for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
+ /* Validate component indexes */
+ ncomps = scanptr->comps_in_scan;
+ if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (thisi < 0 || thisi >= cinfo->num_components)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ /* Components must appear in SOF order within each scan */
+ if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ }
+ /* Validate progression parameters */
+ Ss = scanptr->Ss;
+ Se = scanptr->Se;
+ Ah = scanptr->Ah;
+ Al = scanptr->Al;
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
+ * seems wrong: the upper bound ought to depend on data precision.
+ * Perhaps they really meant 0..N+1 for N-bit precision.
+ * Here we allow 0..10 for 8-bit data; Al larger than 10 results in
+ * out-of-range reconstructed DC values during the first DC scan,
+ * which might cause problems for some decoders.
+ */
+#if BITS_IN_JSAMPLE == 8
+#define MAX_AH_AL 10
+#else
+#define MAX_AH_AL 13
+#endif
+ if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
+ Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ if (Ss == 0) {
+ if (Se != 0) /* DC and AC together not OK */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ if (ncomps != 1) /* AC scans must be for only one component */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ for (ci = 0; ci < ncomps; ci++) {
+ last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+ if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ for (coefi = Ss; coefi <= Se; coefi++) {
+ if (last_bitpos_ptr[coefi] < 0) {
+ /* first scan of this coefficient */
+ if (Ah != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ /* not first scan */
+ if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ last_bitpos_ptr[coefi] = Al;
+ }
+ }
+#endif
+ } else {
+ /* For sequential JPEG, all progression parameters must be these: */
+ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ /* Make sure components are not sent twice */
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (component_sent[thisi])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ component_sent[thisi] = TRUE;
+ }
+ }
+ }
+
+ /* Now verify that everything got sent. */
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* For progressive mode, we only check that at least some DC data
+ * got sent for each component; the spec does not require that all bits
+ * of all coefficients be transmitted. Would it be wiser to enforce
+ * transmission of all coefficient bits??
+ */
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (last_bitpos[ci][0] < 0)
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+#endif
+ } else {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (! component_sent[ci])
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+ }
+}
+
+#endif /* C_MULTISCAN_FILES_SUPPORTED */
+
+
+LOCAL(void)
+select_scan_parameters (j_compress_ptr cinfo)
+/* Set up the scan parameters for the current scan */
+{
+ int ci;
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (cinfo->scan_info != NULL) {
+ /* Prepare for current scan --- the script is already validated */
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
+
+ cinfo->comps_in_scan = scanptr->comps_in_scan;
+ for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
+ cinfo->cur_comp_info[ci] =
+ &cinfo->comp_info[scanptr->component_index[ci]];
+ }
+ cinfo->Ss = scanptr->Ss;
+ cinfo->Se = scanptr->Se;
+ cinfo->Ah = scanptr->Ah;
+ cinfo->Al = scanptr->Al;
+ }
+ else
+#endif
+ {
+ /* Prepare for single sequential-JPEG scan containing all components */
+ if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPS_IN_SCAN);
+ cinfo->comps_in_scan = cinfo->num_components;
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+ }
+ cinfo->Ss = 0;
+ cinfo->Se = DCTSIZE2-1;
+ cinfo->Ah = 0;
+ cinfo->Al = 0;
+ }
+}
+
+
+LOCAL(void)
+per_scan_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_blocks;
+ cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
+
+ /* For noninterleaved scan, always one block per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_blocks = 1;
+ compptr->MCU_sample_width = DCTSIZE;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of block rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->blocks_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width,
+ (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ cinfo->blocks_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of blocks of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
+ /* Figure number of non-dummy blocks in last MCU column & row */
+ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_blocks;
+ if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+ }
+ }
+
+ }
+
+ /* Convert restart specified in rows to actual MCU count. */
+ /* Note that count must fit in 16 bits, so we provide limiting. */
+ if (cinfo->restart_in_rows > 0) {
+ long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
+ cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+ }
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each pass. We determine which modules
+ * will be active during this pass and give them appropriate start_pass calls.
+ * We also set is_last_pass to indicate whether any more passes will be
+ * required.
+ */
+
+METHODDEF(void)
+prepare_for_pass (j_compress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ switch (master->pass_type) {
+ case main_pass:
+ /* Initial pass: will collect input data, and do either Huffman
+ * optimization or data output for the first scan.
+ */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if (! cinfo->raw_data_in) {
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->downsample->start_pass) (cinfo);
+ (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ (*cinfo->fdct->start_pass) (cinfo);
+ (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
+ (*cinfo->coef->start_pass) (cinfo,
+ (master->total_passes > 1 ?
+ JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ if (cinfo->optimize_coding) {
+ /* No immediate data output; postpone writing frame/scan headers */
+ master->pub.call_pass_startup = FALSE;
+ } else {
+ /* Will write frame/scan headers at first jpeg_write_scanlines call */
+ master->pub.call_pass_startup = TRUE;
+ }
+ break;
+#ifdef ENTROPY_OPT_SUPPORTED
+ case huff_opt_pass:
+ /* Do Huffman optimization for a scan after the first one. */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
+ (*cinfo->entropy->start_pass) (cinfo, TRUE);
+ (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ }
+ /* Special case: Huffman DC refinement scans need no Huffman table
+ * and therefore we can skip the optimization pass for them.
+ */
+ master->pass_type = output_pass;
+ master->pass_number++;
+ /*FALLTHROUGH*/
+#endif
+ case output_pass:
+ /* Do a data-output pass. */
+ /* We need not repeat per-scan setup if prior optimization pass did it. */
+ if (! cinfo->optimize_coding) {
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ }
+ (*cinfo->entropy->start_pass) (cinfo, FALSE);
+ (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
+ /* We emit frame/scan headers now */
+ if (master->scan_number == 0)
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ }
+
+ master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->total_passes;
+ }
+}
+
+
+/*
+ * Special start-of-pass hook.
+ * This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
+ * In single-pass processing, we need this hook because we don't want to
+ * write frame/scan headers during jpeg_start_compress; we want to let the
+ * application write COM markers etc. between jpeg_start_compress and the
+ * jpeg_write_scanlines loop.
+ * In multi-pass processing, this routine is not used.
+ */
+
+METHODDEF(void)
+pass_startup (j_compress_ptr cinfo)
+{
+ cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
+
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+}
+
+
+/*
+ * Finish up at end of pass.
+ */
+
+METHODDEF(void)
+finish_pass_master (j_compress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* The entropy coder always needs an end-of-pass call,
+ * either to analyze statistics or to flush its output buffer.
+ */
+ (*cinfo->entropy->finish_pass) (cinfo);
+
+ /* Update state for next pass */
+ switch (master->pass_type) {
+ case main_pass:
+ /* next pass is either output of scan 0 (after optimization)
+ * or output of scan 1 (if no optimization).
+ */
+ master->pass_type = output_pass;
+ if (! cinfo->optimize_coding)
+ master->scan_number++;
+ break;
+ case huff_opt_pass:
+ /* next pass is always output of current scan */
+ master->pass_type = output_pass;
+ break;
+ case output_pass:
+ /* next pass is either optimization or output of next scan */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ master->scan_number++;
+ break;
+ }
+
+ master->pass_number++;
+}
+
+
+/*
+ * Initialize master compression control.
+ */
+
+GLOBAL(void)
+jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_comp_master));
+ cinfo->master = (struct jpeg_comp_master *) master;
+ master->pub.prepare_for_pass = prepare_for_pass;
+ master->pub.pass_startup = pass_startup;
+ master->pub.finish_pass = finish_pass_master;
+ master->pub.is_last_pass = FALSE;
+
+ /* Validate parameters, determine derived values */
+ initial_setup(cinfo);
+
+ if (cinfo->scan_info != NULL) {
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ validate_script(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->progressive_mode = FALSE;
+ cinfo->num_scans = 1;
+ }
+
+ if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */
+ cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
+
+ /* Initialize my private state */
+ if (transcode_only) {
+ /* no main pass in transcoding */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ else
+ master->pass_type = output_pass;
+ } else {
+ /* for normal compression, first pass is always this type: */
+ master->pass_type = main_pass;
+ }
+ master->scan_number = 0;
+ master->pass_number = 0;
+ if (cinfo->optimize_coding)
+ master->total_passes = cinfo->num_scans * 2;
+ else
+ master->total_passes = cinfo->num_scans;
+}
diff --git a/SrcShared/jpeg/jcomapi.c b/SrcShared/jpeg/jcomapi.c
new file mode 100644
index 0000000..9b1fa75
--- /dev/null
+++ b/SrcShared/jpeg/jcomapi.c
@@ -0,0 +1,106 @@
+/*
+ * jcomapi.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface routines that are used for both
+ * compression and decompression.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Abort processing of a JPEG compression or decompression operation,
+ * but don't destroy the object itself.
+ *
+ * For this, we merely clean up all the nonpermanent memory pools.
+ * Note that temp files (virtual arrays) are not allowed to belong to
+ * the permanent pool, so we will be able to close all temp files here.
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_abort (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Do nothing if called on a not-initialized or destroyed JPEG object. */
+ if (cinfo->mem == NULL)
+ return;
+
+ /* Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+ (*cinfo->mem->free_pool) (cinfo, pool);
+ }
+
+ /* Reset overall state for possible reuse of object */
+ if (cinfo->is_decompressor) {
+ cinfo->global_state = DSTATE_START;
+ /* Try to keep application from accessing now-deleted marker list.
+ * A bit kludgy to do it here, but this is the most central place.
+ */
+ ((j_decompress_ptr) cinfo)->marker_list = NULL;
+ } else {
+ cinfo->global_state = CSTATE_START;
+ }
+}
+
+
+/*
+ * Destruction of a JPEG object.
+ *
+ * Everything gets deallocated except the master jpeg_compress_struct itself
+ * and the error manager struct. Both of these are supplied by the application
+ * and must be freed, if necessary, by the application. (Often they are on
+ * the stack and so don't need to be freed anyway.)
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_destroy (j_common_ptr cinfo)
+{
+ /* We need only tell the memory manager to release everything. */
+ /* NB: mem pointer is NULL if memory mgr failed to initialize. */
+ if (cinfo->mem != NULL)
+ (*cinfo->mem->self_destruct) (cinfo);
+ cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
+ cinfo->global_state = 0; /* mark it destroyed */
+}
+
+
+/*
+ * Convenience routines for allocating quantization and Huffman tables.
+ * (Would jutils.c be a more reasonable place to put these?)
+ */
+
+GLOBAL(JQUANT_TBL *)
+jpeg_alloc_quant_table (j_common_ptr cinfo)
+{
+ JQUANT_TBL *tbl;
+
+ tbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
+
+
+GLOBAL(JHUFF_TBL *)
+jpeg_alloc_huff_table (j_common_ptr cinfo)
+{
+ JHUFF_TBL *tbl;
+
+ tbl = (JHUFF_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
diff --git a/SrcShared/jpeg/jcparam.c b/SrcShared/jpeg/jcparam.c
new file mode 100644
index 0000000..6fc48f5
--- /dev/null
+++ b/SrcShared/jpeg/jcparam.c
@@ -0,0 +1,610 @@
+/*
+ * jcparam.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains optional default-setting code for the JPEG compressor.
+ * Applications do not have to use this file, but those that don't use it
+ * must know a lot more about the innards of the JPEG code.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Quantization table setup routines
+ */
+
+GLOBAL(void)
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline)
+/* Define a quantization table equal to the basic_table times
+ * a scale factor (given as a percentage).
+ * If force_baseline is TRUE, the computed quantization table entries
+ * are limited to 1..255 for JPEG baseline compatibility.
+ */
+{
+ JQUANT_TBL ** qtblptr;
+ int i;
+ long temp;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
+
+ qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+ /* limit the values to the valid range */
+ if (temp <= 0L) temp = 1L;
+ if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
+ if (force_baseline && temp > 255L)
+ temp = 255L; /* limit to baseline range if requested */
+ (*qtblptr)->quantval[i] = (UINT16) temp;
+ }
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*qtblptr)->sent_table = FALSE;
+}
+
+
+GLOBAL(void)
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables
+ * and a straight percentage-scaling quality scale. In most cases it's better
+ * to use jpeg_set_quality (below); this entry point is provided for
+ * applications that insist on a linear percentage scaling.
+ */
+{
+ /* These are the sample quantization tables given in JPEG spec section K.1.
+ * The spec says that the values given produce "good" quality, and
+ * when divided by 2, "very good" quality.
+ */
+ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+ };
+ static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+ };
+
+ /* Set up two quantization tables using the specified scaling */
+ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
+ scale_factor, force_baseline);
+ jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
+ scale_factor, force_baseline);
+}
+
+
+GLOBAL(int)
+jpeg_quality_scaling (int quality)
+/* Convert a user-specified quality rating to a percentage scaling factor
+ * for an underlying quantization table, using our recommended scaling curve.
+ * The input 'quality' factor should be 0 (terrible) to 100 (very good).
+ */
+{
+ /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
+ if (quality <= 0) quality = 1;
+ if (quality > 100) quality = 100;
+
+ /* The basic table is used as-is (scaling 100) for a quality of 50.
+ * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
+ * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
+ * to make all the table entries 1 (hence, minimum quantization loss).
+ * Qualities 1..50 are converted to scaling percentage 5000/Q.
+ */
+ if (quality < 50)
+ quality = 5000 / quality;
+ else
+ quality = 200 - quality*2;
+
+ return quality;
+}
+
+
+GLOBAL(void)
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables.
+ * This is the standard quality-adjusting entry point for typical user
+ * interfaces; only those who want detailed control over quantization tables
+ * would use the preceding three routines directly.
+ */
+{
+ /* Convert user 0-100 rating to percentage scaling */
+ quality = jpeg_quality_scaling(quality);
+
+ /* Set up standard quality tables */
+ jpeg_set_linear_quality(cinfo, quality, force_baseline);
+}
+
+
+/*
+ * Huffman table setup routines
+ */
+
+LOCAL(void)
+add_huff_table (j_compress_ptr cinfo,
+ JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+ int nsymbols, len;
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ /* Copy the number-of-symbols-of-each-code-length counts */
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+
+ /* Validate the counts. We do this here mainly so we can copy the right
+ * number of symbols from the val[] array, without risking marching off
+ * the end of memory. jchuff.c will do a more thorough test later.
+ */
+ nsymbols = 0;
+ for (len = 1; len <= 16; len++)
+ nsymbols += bits[len];
+ if (nsymbols < 1 || nsymbols > 256)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*htblptr)->sent_table = FALSE;
+}
+
+
+LOCAL(void)
+std_huff_tables (j_compress_ptr cinfo)
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+ static const UINT8 bits_dc_luminance[17] =
+ { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_luminance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_dc_chrominance[17] =
+ { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_chrominance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_ac_luminance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+ static const UINT8 val_ac_luminance[] =
+ { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ static const UINT8 bits_ac_chrominance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+ static const UINT8 val_ac_chrominance[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+ bits_dc_luminance, val_dc_luminance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+ bits_ac_luminance, val_ac_luminance);
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+ bits_dc_chrominance, val_dc_chrominance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+ bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+/*
+ * Default parameter setup for compression.
+ *
+ * Applications that don't choose to use this routine must do their
+ * own setup of all these parameters. Alternately, you can call this
+ * to establish defaults and then alter parameters selectively. This
+ * is the recommended approach since, if we add any new parameters,
+ * your code will still work (they'll be set to reasonable defaults).
+ */
+
+GLOBAL(void)
+jpeg_set_defaults (j_compress_ptr cinfo)
+{
+ int i;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Allocate comp_info array large enough for maximum component count.
+ * Array is made permanent in case application wants to compress
+ * multiple images at same param settings.
+ */
+ if (cinfo->comp_info == NULL)
+ cinfo->comp_info = (jpeg_component_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ MAX_COMPONENTS * SIZEOF(jpeg_component_info));
+
+ /* Initialize everything not dependent on the color space */
+
+ cinfo->data_precision = BITS_IN_JSAMPLE;
+ /* Set up two quantization tables using default quality of 75 */
+ jpeg_set_quality(cinfo, 75, TRUE);
+ /* Set up two Huffman tables */
+ std_huff_tables(cinfo);
+
+ /* Initialize default arithmetic coding conditioning */
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+
+ /* Default is no multiple-scan output */
+ cinfo->scan_info = NULL;
+ cinfo->num_scans = 0;
+
+ /* Expect normal source image, not raw downsampled data */
+ cinfo->raw_data_in = FALSE;
+
+ /* Use Huffman coding, not arithmetic coding, by default */
+ cinfo->arith_code = FALSE;
+
+ /* By default, don't do extra passes to optimize entropy coding */
+ cinfo->optimize_coding = FALSE;
+ /* The standard Huffman tables are only valid for 8-bit data precision.
+ * If the precision is higher, force optimization on so that usable
+ * tables will be computed. This test can be removed if default tables
+ * are supplied that are valid for the desired precision.
+ */
+ if (cinfo->data_precision > 8)
+ cinfo->optimize_coding = TRUE;
+
+ /* By default, use the simpler non-cosited sampling alignment */
+ cinfo->CCIR601_sampling = FALSE;
+
+ /* No input smoothing */
+ cinfo->smoothing_factor = 0;
+
+ /* DCT algorithm preference */
+ cinfo->dct_method = JDCT_DEFAULT;
+
+ /* No restart markers */
+ cinfo->restart_interval = 0;
+ cinfo->restart_in_rows = 0;
+
+ /* Fill in default JFIF marker parameters. Note that whether the marker
+ * will actually be written is determined by jpeg_set_colorspace.
+ *
+ * By default, the library emits JFIF version code 1.01.
+ * An application that wants to emit JFIF 1.02 extension markers should set
+ * JFIF_minor_version to 2. We could probably get away with just defaulting
+ * to 1.02, but there may still be some decoders in use that will complain
+ * about that; saying 1.01 should minimize compatibility problems.
+ */
+ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0; /* Pixel size is unknown by default */
+ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
+ cinfo->Y_density = 1;
+
+ /* Choose JPEG colorspace based on input space, set defaults accordingly */
+
+ jpeg_default_colorspace(cinfo);
+}
+
+
+/*
+ * Select an appropriate JPEG colorspace for in_color_space.
+ */
+
+GLOBAL(void)
+jpeg_default_colorspace (j_compress_ptr cinfo)
+{
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+ break;
+ case JCS_RGB:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_YCbCr:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_CMYK:
+ jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
+ break;
+ case JCS_YCCK:
+ jpeg_set_colorspace(cinfo, JCS_YCCK);
+ break;
+ case JCS_UNKNOWN:
+ jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ }
+}
+
+
+/*
+ * Set the JPEG colorspace, and choose colorspace-dependent default values.
+ */
+
+GLOBAL(void)
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+{
+ jpeg_component_info * compptr;
+ int ci;
+
+#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
+ (compptr = &cinfo->comp_info[index], \
+ compptr->component_id = (id), \
+ compptr->h_samp_factor = (hsamp), \
+ compptr->v_samp_factor = (vsamp), \
+ compptr->quant_tbl_no = (quant), \
+ compptr->dc_tbl_no = (dctbl), \
+ compptr->ac_tbl_no = (actbl) )
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* For all colorspaces, we use Q and Huff tables 0 for luminance components,
+ * tables 1 for chrominance components.
+ */
+
+ cinfo->jpeg_color_space = colorspace;
+
+ cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
+ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
+
+ switch (colorspace) {
+ case JCS_GRAYSCALE:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 1;
+ /* JFIF specifies component ID 1 */
+ SET_COMP(0, 1, 1,1, 0, 0,0);
+ break;
+ case JCS_RGB:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
+ cinfo->num_components = 3;
+ SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCbCr:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 3;
+ /* JFIF specifies component IDs 1,2,3 */
+ /* We default to 2x2 subsamples of chrominance */
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ break;
+ case JCS_CMYK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
+ cinfo->num_components = 4;
+ SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
+ SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCCK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
+ cinfo->num_components = 4;
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(3, 4, 2,2, 0, 0,0);
+ break;
+ case JCS_UNKNOWN:
+ cinfo->num_components = cinfo->input_components;
+ if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ SET_COMP(ci, ci, 1,1, 0, 0,0);
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ }
+}
+
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+LOCAL(jpeg_scan_info *)
+fill_a_scan (jpeg_scan_info * scanptr, int ci,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for specified component */
+{
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_scans (jpeg_scan_info * scanptr, int ncomps,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for each component */
+{
+ int ci;
+
+ for (ci = 0; ci < ncomps; ci++) {
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ }
+ return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
+/* Support routine: generate interleaved DC scan if possible, else N scans */
+{
+ int ci;
+
+ if (ncomps <= MAX_COMPS_IN_SCAN) {
+ /* Single interleaved DC scan */
+ scanptr->comps_in_scan = ncomps;
+ for (ci = 0; ci < ncomps; ci++)
+ scanptr->component_index[ci] = ci;
+ scanptr->Ss = scanptr->Se = 0;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ } else {
+ /* Noninterleaved DC scan for each component */
+ scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
+ }
+ return scanptr;
+}
+
+
+/*
+ * Create a recommended progressive-JPEG script.
+ * cinfo->num_components and cinfo->jpeg_color_space must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_progression (j_compress_ptr cinfo)
+{
+ int ncomps = cinfo->num_components;
+ int nscans;
+ jpeg_scan_info * scanptr;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Figure space needed for script. Calculation must match code below! */
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ nscans = 10;
+ } else {
+ /* All-purpose script for other color spaces. */
+ if (ncomps > MAX_COMPS_IN_SCAN)
+ nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
+ else
+ nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
+ }
+
+ /* Allocate space for script.
+ * We need to put it in the permanent pool in case the application performs
+ * multiple compressions without changing the settings. To avoid a memory
+ * leak if jpeg_simple_progression is called repeatedly for the same JPEG
+ * object, we try to re-use previously allocated space, and we allocate
+ * enough space to handle YCbCr even if initially asked for grayscale.
+ */
+ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+ cinfo->script_space_size = MAX(nscans, 10);
+ cinfo->script_space = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+ }
+ scanptr = cinfo->script_space;
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = nscans;
+
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ /* Initial DC scan */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ /* Initial AC scan: get some luma data out in a hurry */
+ scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
+ /* Chroma data is too small to be worth expending many scans on */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
+ /* Complete spectral selection for luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
+ /* Refine next bit of luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
+ /* Finish DC successive approximation */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ /* Finish AC successive approximation */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
+ /* Luma bottom bit comes last since it's usually largest scan */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
+ } else {
+ /* All-purpose script for other color spaces. */
+ /* Successive approximation first pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
+ scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
+ /* Successive approximation second pass */
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
+ /* Successive approximation final pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
+ }
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
diff --git a/SrcShared/jpeg/jcphuff.c b/SrcShared/jpeg/jcphuff.c
new file mode 100644
index 0000000..07f9178
--- /dev/null
+++ b/SrcShared/jpeg/jcphuff.c
@@ -0,0 +1,833 @@
+/*
+ * jcphuff.c
+ *
+ * Copyright (C) 1995-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for progressive JPEG.
+ *
+ * We do not support output suspension in this module, since the library
+ * currently does not allow multiple-scan files to be written with output
+ * suspension.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jchuff.h" /* Declarations shared with jchuff.c */
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+/* Expanded entropy encoder object for progressive Huffman encoding. */
+
+typedef struct {
+ struct jpeg_entropy_encoder pub; /* public fields */
+
+ /* Mode flag: TRUE for optimization, FALSE for actual data output */
+ boolean gather_statistics;
+
+ /* Bit-level coding status.
+ * next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
+ */
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */
+
+ /* Coding status for DC components */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+
+ /* Coding status for AC components */
+ int ac_tbl_no; /* the table number of the single component */
+ unsigned int EOBRUN; /* run length of EOBs */
+ unsigned int BE; /* # of buffered correction bits before MCU */
+ char * bit_buffer; /* buffer for correction bits (1 per char) */
+ /* packing correction bits tightly would save some space but cost time... */
+
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to derived tables (these workspaces have image lifespan).
+ * Since any one scan codes only DC or only AC, we only need one set
+ * of tables, not one for DC and one for AC.
+ */
+ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ /* Statistics tables for optimization; again, one set is enough */
+ long * count_ptrs[NUM_HUFF_TBLS];
+} phuff_entropy_encoder;
+
+typedef phuff_entropy_encoder * phuff_entropy_ptr;
+
+/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
+ * buffer can hold. Larger sizes may slightly improve compression, but
+ * 1000 is already well into the realm of overkill.
+ * The minimum safe size is 64 bits.
+ */
+
+#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */
+
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
+ * We assume that int right shift is unsigned if INT32 right shift is,
+ * which should be safe.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS int ishift_temp;
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
+METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
+
+
+/*
+ * Initialize for a Huffman-compressed scan using progressive JPEG.
+ */
+
+METHODDEF(void)
+start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ boolean is_DC_band;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+
+ entropy->cinfo = cinfo;
+ entropy->gather_statistics = gather_statistics;
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* We assume jcmaster.c already validated the scan parameters. */
+
+ /* Select execution routines */
+ if (cinfo->Ah == 0) {
+ if (is_DC_band)
+ entropy->pub.encode_mcu = encode_mcu_DC_first;
+ else
+ entropy->pub.encode_mcu = encode_mcu_AC_first;
+ } else {
+ if (is_DC_band)
+ entropy->pub.encode_mcu = encode_mcu_DC_refine;
+ else {
+ entropy->pub.encode_mcu = encode_mcu_AC_refine;
+ /* AC refinement needs a correction bit buffer */
+ if (entropy->bit_buffer == NULL)
+ entropy->bit_buffer = (char *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ MAX_CORR_BITS * SIZEOF(char));
+ }
+ }
+ if (gather_statistics)
+ entropy->pub.finish_pass = finish_pass_gather_phuff;
+ else
+ entropy->pub.finish_pass = finish_pass_phuff;
+
+ /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
+ * for AC coefficients.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Initialize DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ /* Get table index */
+ if (is_DC_band) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
+ }
+ if (gather_statistics) {
+ /* Check for invalid table index */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->count_ptrs[tbl] == NULL)
+ entropy->count_ptrs[tbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
+ } else {
+ /* Compute derived values for Huffman table */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
+ & entropy->derived_tbls[tbl]);
+ }
+ }
+
+ /* Initialize AC stuff */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+
+ /* Initialize bit buffer to empty */
+ entropy->put_buffer = 0;
+ entropy->put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file.
+ * NB: these must be called only when actually outputting,
+ * that is, entropy->gather_statistics == FALSE.
+ */
+
+/* Emit a byte */
+#define emit_byte(entropy,val) \
+ { *(entropy)->next_output_byte++ = (JOCTET) (val); \
+ if (--(entropy)->free_in_buffer == 0) \
+ dump_buffer(entropy); }
+
+
+LOCAL(void)
+dump_buffer (phuff_entropy_ptr entropy)
+/* Empty the output buffer; we do not support suspension in this module. */
+{
+ struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (entropy->cinfo))
+ ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
+ /* After a successful buffer dump, must reset buffer pointers */
+ entropy->next_output_byte = dest->next_output_byte;
+ entropy->free_in_buffer = dest->free_in_buffer;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(void)
+emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
+/* Emit some bits, unless we are in gather mode */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = entropy->put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ if (entropy->gather_statistics)
+ return; /* do nothing if we're only getting stats */
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte(entropy, c);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte(entropy, 0);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ entropy->put_buffer = put_buffer; /* update variables */
+ entropy->put_bits = put_bits;
+}
+
+
+LOCAL(void)
+flush_bits (phuff_entropy_ptr entropy)
+{
+ emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
+ entropy->put_buffer = 0; /* and reset bit-buffer to empty */
+ entropy->put_bits = 0;
+}
+
+
+/*
+ * Emit (or just count) a Huffman symbol.
+ */
+
+INLINE
+LOCAL(void)
+emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
+{
+ if (entropy->gather_statistics)
+ entropy->count_ptrs[tbl_no][symbol]++;
+ else {
+ c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
+ emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
+ }
+}
+
+
+/*
+ * Emit bits from a correction bit buffer.
+ */
+
+LOCAL(void)
+emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
+ unsigned int nbits)
+{
+ if (entropy->gather_statistics)
+ return; /* no real work */
+
+ while (nbits > 0) {
+ emit_bits(entropy, (unsigned int) (*bufstart), 1);
+ bufstart++;
+ nbits--;
+ }
+}
+
+
+/*
+ * Emit any pending EOBRUN symbol.
+ */
+
+LOCAL(void)
+emit_eobrun (phuff_entropy_ptr entropy)
+{
+ register int temp, nbits;
+
+ if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
+ temp = entropy->EOBRUN;
+ nbits = 0;
+ while ((temp >>= 1))
+ nbits++;
+ /* safety check: shouldn't happen given limited correction-bit buffer */
+ if (nbits > 14)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
+ if (nbits)
+ emit_bits(entropy, entropy->EOBRUN, nbits);
+
+ entropy->EOBRUN = 0;
+
+ /* Emit any buffered correction bits */
+ emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(void)
+emit_restart (phuff_entropy_ptr entropy, int restart_num)
+{
+ int ci;
+
+ emit_eobrun(entropy);
+
+ if (! entropy->gather_statistics) {
+ flush_bits(entropy);
+ emit_byte(entropy, 0xFF);
+ emit_byte(entropy, JPEG_RST0 + restart_num);
+ }
+
+ if (entropy->cinfo->Ss == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
+ entropy->last_dc_val[ci] = 0;
+ } else {
+ /* Re-initialize all AC-related fields to 0 */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * MCU encoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ register int temp, temp2;
+ register int nbits;
+ int blkn, ci;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ jpeg_component_info * compptr;
+ ISHIFT_TEMPS
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+
+ /* Compute the DC value after the required point transform by Al.
+ * This is simply an arithmetic right shift.
+ */
+ temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+
+ /* DC differences are figured on the point-transformed values. */
+ temp = temp2 - entropy->last_dc_val[ci];
+ entropy->last_dc_val[ci] = temp2;
+
+ /* Encode the DC coefficient difference per section G.1.2.1 */
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit the Huffman-coded symbol for the number of bits */
+ emit_symbol(entropy, compptr->dc_tbl_no, nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ emit_bits(entropy, (unsigned int) temp2, nbits);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ register int temp, temp2;
+ register int nbits;
+ register int r, k;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
+ r++;
+ continue;
+ }
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value; so the code is
+ * interwoven with finding the abs value (temp) and output bits (temp2).
+ */
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
+ temp2 = ~temp;
+ } else {
+ temp >>= Al; /* apply the point transform */
+ temp2 = temp;
+ }
+ /* Watch out for case that nonzero coef is zero after point transform */
+ if (temp == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any pending EOBRUN */
+ if (entropy->EOBRUN > 0)
+ emit_eobrun(entropy);
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ emit_bits(entropy, (unsigned int) temp2, nbits);
+
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ if (entropy->EOBRUN == 0x7FFF)
+ emit_eobrun(entropy); /* force it out to avoid overflow */
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ register int temp;
+ int blkn;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* We simply emit the Al'th bit of the DC coefficient value. */
+ temp = (*block)[0];
+ emit_bits(entropy, (unsigned int) (temp >> Al), 1);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ register int temp;
+ register int r, k;
+ int EOB;
+ char *BR_buffer;
+ unsigned int BR;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ int absvalues[DCTSIZE2];
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* It is convenient to make a pre-pass to determine the transformed
+ * coefficients' absolute values and the EOB position.
+ */
+ EOB = 0;
+ for (k = cinfo->Ss; k <= Se; k++) {
+ temp = (*block)[jpeg_natural_order[k]];
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value.
+ */
+ if (temp < 0)
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ absvalues[k] = temp; /* save abs value for main pass */
+ if (temp == 1)
+ EOB = k; /* EOB = index of last newly-nonzero coef */
+ }
+
+ /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
+
+ r = 0; /* r = run length of zeros */
+ BR = 0; /* BR = count of buffered bits added now */
+ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = absvalues[k]) == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any required ZRLs, but not if they can be folded into EOB */
+ while (r > 15 && k <= EOB) {
+ /* emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+ /* Emit ZRL */
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ /* Emit buffered correction bits that must be associated with ZRL */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ }
+
+ /* If the coef was previously nonzero, it only needs a correction bit.
+ * NOTE: a straight translation of the spec's figure G.7 would suggest
+ * that we also need to test r > 15. But if r > 15, we can only get here
+ * if k > EOB, which implies that this coefficient is not 1.
+ */
+ if (temp > 1) {
+ /* The correction bit is the next bit of the absolute value. */
+ BR_buffer[BR++] = (char) (temp & 1);
+ continue;
+ }
+
+ /* Emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+
+ /* Emit output bit for newly-nonzero coef */
+ temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
+ emit_bits(entropy, (unsigned int) temp, 1);
+
+ /* Emit buffered correction bits that must be associated with this code */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ entropy->BE += BR; /* concat my correction bits to older ones */
+ /* We force out the EOB if we risk either:
+ * 1. overflow of the EOB counter;
+ * 2. overflow of the correction bit buffer during the next MCU.
+ */
+ if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+ emit_eobrun(entropy);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed progressive scan.
+ */
+
+METHODDEF(void)
+finish_pass_phuff (j_compress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Flush out any buffered data */
+ emit_eobrun(entropy);
+ flush_bits(entropy);
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather_phuff (j_compress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ boolean is_DC_band;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did[NUM_HUFF_TBLS];
+
+ /* Flush out buffered data (all we care about is counting the EOB symbol) */
+ emit_eobrun(entropy);
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ MEMZERO(did, SIZEOF(did));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ if (is_DC_band) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ tbl = compptr->ac_tbl_no;
+ }
+ if (! did[tbl]) {
+ if (is_DC_band)
+ htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+ else
+ htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
+ did[tbl] = TRUE;
+ }
+ }
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_encoder (j_compress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (phuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(phuff_entropy_encoder));
+ cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ entropy->pub.start_pass = start_pass_phuff;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ entropy->count_ptrs[i] = NULL;
+ }
+ entropy->bit_buffer = NULL; /* needed only in AC refinement scan */
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
diff --git a/SrcShared/jpeg/jcprepct.c b/SrcShared/jpeg/jcprepct.c
new file mode 100644
index 0000000..fa93333
--- /dev/null
+++ b/SrcShared/jpeg/jcprepct.c
@@ -0,0 +1,354 @@
+/*
+ * jcprepct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the compression preprocessing controller.
+ * This controller manages the color conversion, downsampling,
+ * and edge expansion steps.
+ *
+ * Most of the complexity here is associated with buffering input rows
+ * as required by the downsampler. See the comments at the head of
+ * jcsample.c for the downsampler's needs.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* At present, jcsample.c can request context rows only for smoothing.
+ * In the future, we might also need context rows for CCIR601 sampling
+ * or other more-complex downsampling procedures. The code to support
+ * context rows should be compiled only if needed.
+ */
+#ifdef INPUT_SMOOTHING_SUPPORTED
+#define CONTEXT_ROWS_SUPPORTED
+#endif
+
+
+/*
+ * For the simple (no-context-row) case, we just need to buffer one
+ * row group's worth of pixels for the downsampling step. At the bottom of
+ * the image, we pad to a full row group by replicating the last pixel row.
+ * The downsampler's last output row is then replicated if needed to pad
+ * out to a full iMCU row.
+ *
+ * When providing context rows, we must buffer three row groups' worth of
+ * pixels. Three row groups are physically allocated, but the row pointer
+ * arrays are made five row groups high, with the extra pointers above and
+ * below "wrapping around" to point to the last and first real row groups.
+ * This allows the downsampler to access the proper context rows.
+ * At the top and bottom of the image, we create dummy context rows by
+ * copying the first or last real pixel row. This copying could be avoided
+ * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
+ * trouble on the compression side.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_prep_controller pub; /* public fields */
+
+ /* Downsampling input buffer. This buffer holds color-converted data
+ * until we have enough to do a downsample step.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ JDIMENSION rows_to_go; /* counts rows remaining in source image */
+ int next_buf_row; /* index of next row to store in color_buf */
+
+#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
+ int this_row_group; /* starting row index of group to process */
+ int next_buf_stop; /* downsample when we reach this index */
+#endif
+} my_prep_controller;
+
+typedef my_prep_controller * my_prep_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+
+ if (pass_mode != JBUF_PASS_THRU)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Initialize total-height counter for detecting bottom of image */
+ prep->rows_to_go = cinfo->image_height;
+ /* Mark the conversion buffer empty */
+ prep->next_buf_row = 0;
+#ifdef CONTEXT_ROWS_SUPPORTED
+ /* Preset additional state variables for context mode.
+ * These aren't used in non-context mode, so we needn't test which mode.
+ */
+ prep->this_row_group = 0;
+ /* Set next_buf_stop to stop after two row groups have been read in. */
+ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
+#endif
+}
+
+
+/*
+ * Expand an image vertically from height input_rows to height output_rows,
+ * by duplicating the bottom row.
+ */
+
+LOCAL(void)
+expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
+ int input_rows, int output_rows)
+{
+ register int row;
+
+ for (row = input_rows; row < output_rows; row++) {
+ jcopy_sample_rows(image_data, input_rows-1, image_data, row,
+ 1, num_cols);
+ }
+}
+
+
+/*
+ * Process some data in the simple no-context case.
+ *
+ * Preprocessor output data is counted in "row groups". A row group
+ * is defined to be v_samp_factor sample rows of each component.
+ * Downsampling will produce this much data from each max_v_samp_factor
+ * input rows.
+ */
+
+METHODDEF(void)
+pre_process_data (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ JDIMENSION inrows;
+ jpeg_component_info * compptr;
+
+ while (*in_row_ctr < in_rows_avail &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ /* If at bottom of image, pad to fill the conversion buffer. */
+ if (prep->rows_to_go == 0 &&
+ prep->next_buf_row < cinfo->max_v_samp_factor) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, cinfo->max_v_samp_factor);
+ }
+ prep->next_buf_row = cinfo->max_v_samp_factor;
+ }
+ /* If we've filled the conversion buffer, empty it. */
+ if (prep->next_buf_row == cinfo->max_v_samp_factor) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf, (JDIMENSION) 0,
+ output_buf, *out_row_group_ctr);
+ prep->next_buf_row = 0;
+ (*out_row_group_ctr)++;
+ }
+ /* If at bottom of image, pad the output to a full iMCU height.
+ * Note we assume the caller is providing a one-iMCU-height output buffer!
+ */
+ if (prep->rows_to_go == 0 &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ expand_bottom_edge(output_buf[ci],
+ compptr->width_in_blocks * DCTSIZE,
+ (int) (*out_row_group_ctr * compptr->v_samp_factor),
+ (int) (out_row_groups_avail * compptr->v_samp_factor));
+ }
+ *out_row_group_ctr = out_row_groups_avail;
+ break; /* can exit outer loop without test */
+ }
+ }
+}
+
+
+#ifdef CONTEXT_ROWS_SUPPORTED
+
+/*
+ * Process some data in the context case.
+ */
+
+METHODDEF(void)
+pre_process_context (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ int buf_height = cinfo->max_v_samp_factor * 3;
+ JDIMENSION inrows;
+
+ while (*out_row_group_ctr < out_row_groups_avail) {
+ if (*in_row_ctr < in_rows_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = prep->next_buf_stop - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ /* Pad at top of image, if first time through */
+ if (prep->rows_to_go == cinfo->image_height) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ int row;
+ for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
+ jcopy_sample_rows(prep->color_buf[ci], 0,
+ prep->color_buf[ci], -row,
+ 1, cinfo->image_width);
+ }
+ }
+ }
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ } else {
+ /* Return for more data, unless we are at the bottom of the image. */
+ if (prep->rows_to_go != 0)
+ break;
+ /* When at bottom of image, pad to fill the conversion buffer. */
+ if (prep->next_buf_row < prep->next_buf_stop) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, prep->next_buf_stop);
+ }
+ prep->next_buf_row = prep->next_buf_stop;
+ }
+ }
+ /* If we've gotten enough data, downsample a row group. */
+ if (prep->next_buf_row == prep->next_buf_stop) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf,
+ (JDIMENSION) prep->this_row_group,
+ output_buf, *out_row_group_ctr);
+ (*out_row_group_ctr)++;
+ /* Advance pointers with wraparound as necessary. */
+ prep->this_row_group += cinfo->max_v_samp_factor;
+ if (prep->this_row_group >= buf_height)
+ prep->this_row_group = 0;
+ if (prep->next_buf_row >= buf_height)
+ prep->next_buf_row = 0;
+ prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
+ }
+ }
+}
+
+
+/*
+ * Create the wrapped-around downsampling input buffer needed for context mode.
+ */
+
+LOCAL(void)
+create_context_buffer (j_compress_ptr cinfo)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int rgroup_height = cinfo->max_v_samp_factor;
+ int ci, i;
+ jpeg_component_info * compptr;
+ JSAMPARRAY true_buffer, fake_buffer;
+
+ /* Grab enough space for fake row pointers for all the components;
+ * we need five row groups' worth of pointers for each component.
+ */
+ fake_buffer = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (cinfo->num_components * 5 * rgroup_height) *
+ SIZEOF(JSAMPROW));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate the actual buffer space (3 row groups) for this component.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ true_buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) (3 * rgroup_height));
+ /* Copy true buffer row pointers into the middle of the fake row array */
+ MEMCOPY(fake_buffer + rgroup_height, true_buffer,
+ 3 * rgroup_height * SIZEOF(JSAMPROW));
+ /* Fill in the above and below wraparound pointers */
+ for (i = 0; i < rgroup_height; i++) {
+ fake_buffer[i] = true_buffer[2 * rgroup_height + i];
+ fake_buffer[4 * rgroup_height + i] = true_buffer[i];
+ }
+ prep->color_buf[ci] = fake_buffer + rgroup_height;
+ fake_buffer += 5 * rgroup_height; /* point to space for next component */
+ }
+}
+
+#endif /* CONTEXT_ROWS_SUPPORTED */
+
+
+/*
+ * Initialize preprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_prep_ptr prep;
+ int ci;
+ jpeg_component_info * compptr;
+
+ if (need_full_buffer) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ prep = (my_prep_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_prep_controller));
+ cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+ prep->pub.start_pass = start_pass_prep;
+
+ /* Allocate the color conversion buffer.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ if (cinfo->downsample->need_context_rows) {
+ /* Set up to provide context rows */
+#ifdef CONTEXT_ROWS_SUPPORTED
+ prep->pub.pre_process_data = pre_process_context;
+ create_context_buffer(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* No context, just make it tall enough for one row group */
+ prep->pub.pre_process_data = pre_process_data;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/SrcShared/jpeg/jcsample.c b/SrcShared/jpeg/jcsample.c
new file mode 100644
index 0000000..212ec87
--- /dev/null
+++ b/SrcShared/jpeg/jcsample.c
@@ -0,0 +1,519 @@
+/*
+ * jcsample.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains downsampling routines.
+ *
+ * Downsampling input data is counted in "row groups". A row group
+ * is defined to be max_v_samp_factor pixel rows of each component,
+ * from which the downsampler produces v_samp_factor sample rows.
+ * A single row group is processed in each call to the downsampler module.
+ *
+ * The downsampler is responsible for edge-expansion of its output data
+ * to fill an integral number of DCT blocks horizontally. The source buffer
+ * may be modified if it is helpful for this purpose (the source buffer is
+ * allocated wide enough to correspond to the desired output width).
+ * The caller (the prep controller) is responsible for vertical padding.
+ *
+ * The downsampler may request "context rows" by setting need_context_rows
+ * during startup. In this case, the input arrays will contain at least
+ * one row group's worth of pixels above and below the passed-in data;
+ * the caller will create dummy rows at image top and bottom by replicating
+ * the first or last real pixel row.
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ *
+ * The downsampling algorithm used here is a simple average of the source
+ * pixels covered by the output pixel. The hi-falutin sampling literature
+ * refers to this as a "box filter". In general the characteristics of a box
+ * filter are not very good, but for the specific cases we normally use (1:1
+ * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
+ * nearly so bad. If you intend to use other sampling ratios, you'd be well
+ * advised to improve this code.
+ *
+ * A simple input-smoothing capability is provided. This is mainly intended
+ * for cleaning up color-dithered GIF input files (if you find it inadequate,
+ * we suggest using an external filtering program such as pnmconvol). When
+ * enabled, each input pixel P is replaced by a weighted sum of itself and its
+ * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
+ * where SF = (smoothing_factor / 1024).
+ * Currently, smoothing is only supported for 2h2v sampling factors.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to downsample a single component */
+typedef JMETHOD(void, downsample1_ptr,
+ (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_downsampler pub; /* public fields */
+
+ /* Downsampling method pointers, one per component */
+ downsample1_ptr methods[MAX_COMPONENTS];
+} my_downsampler;
+
+typedef my_downsampler * my_downsample_ptr;
+
+
+/*
+ * Initialize for a downsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_downsample (j_compress_ptr cinfo)
+{
+ /* no work for now */
+}
+
+
+/*
+ * Expand a component horizontally from width input_cols to width output_cols,
+ * by duplicating the rightmost samples.
+ */
+
+LOCAL(void)
+expand_right_edge (JSAMPARRAY image_data, int num_rows,
+ JDIMENSION input_cols, JDIMENSION output_cols)
+{
+ register JSAMPROW ptr;
+ register JSAMPLE pixval;
+ register int count;
+ int row;
+ int numcols = (int) (output_cols - input_cols);
+
+ if (numcols > 0) {
+ for (row = 0; row < num_rows; row++) {
+ ptr = image_data[row] + input_cols;
+ pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
+ for (count = numcols; count > 0; count--)
+ *ptr++ = pixval;
+ }
+ }
+}
+
+
+/*
+ * Do downsampling for a whole row group (all components).
+ *
+ * In this version we simply downsample each component independently.
+ */
+
+METHODDEF(void)
+sep_downsample (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+{
+ my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JSAMPARRAY in_ptr, out_ptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ in_ptr = input_buf[ci] + in_row_index;
+ out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
+ (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * One row group is processed per call.
+ * This version handles arbitrary integral sampling ratios, without smoothing.
+ * Note that this version is not actually used for customary sampling ratios.
+ */
+
+METHODDEF(void)
+int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
+ JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
+ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
+ JSAMPROW inptr, outptr;
+ INT32 outvalue;
+
+ h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
+ v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
+ numpix = h_expand * v_expand;
+ numpix2 = numpix/2;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * h_expand);
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ for (outcol = 0, outcol_h = 0; outcol < output_cols;
+ outcol++, outcol_h += h_expand) {
+ outvalue = 0;
+ for (v = 0; v < v_expand; v++) {
+ inptr = input_data[inrow+v] + outcol_h;
+ for (h = 0; h < h_expand; h++) {
+ outvalue += (INT32) GETJSAMPLE(*inptr++);
+ }
+ }
+ *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+ }
+ inrow += v_expand;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ /* Copy the data */
+ jcopy_sample_rows(input_data, 0, output_data, 0,
+ cinfo->max_v_samp_factor, cinfo->image_width);
+ /* Edge-expand */
+ expand_right_edge(output_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the common case of 2:1 horizontal and 1:1 vertical,
+ * without smoothing.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int outrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
+ register JSAMPROW inptr, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr = input_data[outrow];
+ bias = 0; /* bias = 0,1,0,1,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ + bias) >> 1);
+ bias ^= 1; /* 0=>1, 1=>0 */
+ inptr += 2;
+ }
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
+ register JSAMPROW inptr0, inptr1, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ bias = 1; /* bias = 1,2,1,2,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ + bias) >> 2);
+ bias ^= 3; /* 1=>2, 2=>1 */
+ inptr0 += 2; inptr1 += 2;
+ }
+ inrow += 2;
+ }
+}
+
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
+ register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols * 2);
+
+ /* We don't bother to form the individual "smoothed" input pixel values;
+ * we can directly compute the output which is the average of the four
+ * smoothed values. Each of the four member pixels contributes a fraction
+ * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
+ * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
+ * output. The four corner-adjacent neighbor pixels contribute a fraction
+ * SF to just one smoothed pixel, or SF/4 to the final output; while the
+ * eight edge-adjacent neighbors contribute SF to each of two smoothed
+ * pixels, or SF/2 overall. In order to use integer arithmetic, these
+ * factors are scaled by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
+ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ above_ptr = input_data[inrow-1];
+ below_ptr = input_data[inrow+2];
+
+ /* Special case for first column: pretend column -1 is same as column 0 */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ /* sum of pixels directly mapped to this output element */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ /* sum of edge-neighbor pixels */
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
+ /* The edge-neighbors count twice as much as corner-neighbors */
+ neighsum += neighsum;
+ /* Add in the corner-neighbors */
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
+ /* form final output scaled up by 2^16 */
+ membersum = membersum * memberscale + neighsum * neighscale;
+ /* round, descale and output it */
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ inrow += 2;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int outrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
+ register JSAMPROW inptr, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+ int colsum, lastcolsum, nextcolsum;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols);
+
+ /* Each of the eight neighbor pixels contributes a fraction SF to the
+ * smoothed pixel, while the main pixel contributes (1-8*SF). In order
+ * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
+ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
+
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr = input_data[outrow];
+ above_ptr = input_data[outrow-1];
+ below_ptr = input_data[outrow+1];
+
+ /* Special case for first column */
+ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
+ GETJSAMPLE(*inptr);
+ membersum = GETJSAMPLE(*inptr++);
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = colsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ membersum = GETJSAMPLE(*inptr++);
+ above_ptr++; below_ptr++;
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + colsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ }
+}
+
+#endif /* INPUT_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Module initialization routine for downsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL(void)
+jinit_downsampler (j_compress_ptr cinfo)
+{
+ my_downsample_ptr downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean smoothok = TRUE;
+
+ downsample = (my_downsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_downsampler));
+ cinfo->downsample = (struct jpeg_downsampler *) downsample;
+ downsample->pub.start_pass = start_pass_downsample;
+ downsample->pub.downsample = sep_downsample;
+ downsample->pub.need_context_rows = FALSE;
+
+ if (cinfo->CCIR601_sampling)
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* Verify we can handle the sampling factors, and set up method pointers */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = fullsize_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = fullsize_downsample;
+ } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+ smoothok = FALSE;
+ downsample->methods[ci] = h2v1_downsample;
+ } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = h2v2_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = h2v2_downsample;
+ } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
+ (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
+ smoothok = FALSE;
+ downsample->methods[ci] = int_downsample;
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ }
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor && !smoothok)
+ TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
+#endif
+}
diff --git a/SrcShared/jpeg/jctrans.c b/SrcShared/jpeg/jctrans.c
new file mode 100644
index 0000000..0e6d707
--- /dev/null
+++ b/SrcShared/jpeg/jctrans.c
@@ -0,0 +1,388 @@
+/*
+ * jctrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding compression,
+ * that is, writing raw DCT coefficient arrays to an output JPEG file.
+ * The routines in jcapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(void) transencode_master_selection
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_coef_controller
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+
+
+/*
+ * Compression initialization for writing raw-coefficient data.
+ * Before calling this, all parameters and a data destination must be set up.
+ * Call jpeg_finish_compress() to actually write the data.
+ *
+ * The number of passed virtual arrays must match cinfo->num_components.
+ * Note that the virtual arrays need not be filled or even realized at
+ * the time write_coefficients is called; indeed, if the virtual arrays
+ * were requested from this compression object's memory manager, they
+ * typically will be realized during this routine and filled afterwards.
+ */
+
+GLOBAL(void)
+jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Mark all tables to be written */
+ jpeg_suppress_tables(cinfo, FALSE);
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ transencode_master_selection(cinfo, coef_arrays);
+ /* Wait for jpeg_finish_compress() call */
+ cinfo->next_scanline = 0; /* so jpeg_write_marker works */
+ cinfo->global_state = CSTATE_WRCOEFS;
+}
+
+
+/*
+ * Initialize the compression object with default parameters,
+ * then copy from the source object all parameters needed for lossless
+ * transcoding. Parameters that can be varied without loss (such as
+ * scan script and Huffman optimization) are left in their default states.
+ */
+
+GLOBAL(void)
+jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo)
+{
+ JQUANT_TBL ** qtblptr;
+ jpeg_component_info *incomp, *outcomp;
+ JQUANT_TBL *c_quant, *slot_quant;
+ int tblno, ci, coefi;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (dstinfo->global_state != CSTATE_START)
+ ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
+ /* Copy fundamental image dimensions */
+ dstinfo->image_width = srcinfo->image_width;
+ dstinfo->image_height = srcinfo->image_height;
+ dstinfo->input_components = srcinfo->num_components;
+ dstinfo->in_color_space = srcinfo->jpeg_color_space;
+ /* Initialize all parameters to default values */
+ jpeg_set_defaults(dstinfo);
+ /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
+ * Fix it to get the right header markers for the image colorspace.
+ */
+ jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
+ dstinfo->data_precision = srcinfo->data_precision;
+ dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
+ /* Copy the source's quantization tables. */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
+ qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
+ MEMCOPY((*qtblptr)->quantval,
+ srcinfo->quant_tbl_ptrs[tblno]->quantval,
+ SIZEOF((*qtblptr)->quantval));
+ (*qtblptr)->sent_table = FALSE;
+ }
+ }
+ /* Copy the source's per-component info.
+ * Note we assume jpeg_set_defaults has allocated the dest comp_info array.
+ */
+ dstinfo->num_components = srcinfo->num_components;
+ if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
+ ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
+ outcomp->component_id = incomp->component_id;
+ outcomp->h_samp_factor = incomp->h_samp_factor;
+ outcomp->v_samp_factor = incomp->v_samp_factor;
+ outcomp->quant_tbl_no = incomp->quant_tbl_no;
+ /* Make sure saved quantization table for component matches the qtable
+ * slot. If not, the input file re-used this qtable slot.
+ * IJG encoder currently cannot duplicate this.
+ */
+ tblno = outcomp->quant_tbl_no;
+ if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
+ srcinfo->quant_tbl_ptrs[tblno] == NULL)
+ ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
+ slot_quant = srcinfo->quant_tbl_ptrs[tblno];
+ c_quant = incomp->quant_table;
+ if (c_quant != NULL) {
+ for (coefi = 0; coefi < DCTSIZE2; coefi++) {
+ if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
+ ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
+ }
+ }
+ /* Note: we do not copy the source's Huffman table assignments;
+ * instead we rely on jpeg_set_colorspace to have made a suitable choice.
+ */
+ }
+ /* Also copy JFIF version and resolution information, if available.
+ * Strictly speaking this isn't "critical" info, but it's nearly
+ * always appropriate to copy it if available. In particular,
+ * if the application chooses to copy JFIF 1.02 extension markers from
+ * the source file, we need to copy the version to make sure we don't
+ * emit a file that has 1.02 extensions but a claimed version of 1.01.
+ * We will *not*, however, copy version info from mislabeled "2.01" files.
+ */
+ if (srcinfo->saw_JFIF_marker) {
+ if (srcinfo->JFIF_major_version == 1) {
+ dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
+ dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
+ }
+ dstinfo->density_unit = srcinfo->density_unit;
+ dstinfo->X_density = srcinfo->X_density;
+ dstinfo->Y_density = srcinfo->Y_density;
+ }
+}
+
+
+/*
+ * Master selection of compression modules for transcoding.
+ * This substitutes for jcinit.c's initialization of the full compressor.
+ */
+
+LOCAL(void)
+transencode_master_selection (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ /* Although we don't actually use input_components for transcoding,
+ * jcmaster.c's initial_setup will complain if input_components is 0.
+ */
+ cinfo->input_components = 1;
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, TRUE /* transcode only */);
+
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ jinit_phuff_encoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_huff_encoder(cinfo);
+ }
+
+ /* We need a special coefficient buffer controller. */
+ transencode_coef_controller(cinfo, coef_arrays);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI, JFIF) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
+
+
+/*
+ * The rest of this file is a special implementation of the coefficient
+ * buffer controller. This is similar to jccoefct.c, but it handles only
+ * output from presupplied virtual arrays. Furthermore, we generate any
+ * dummy padding blocks on-the-fly rather than expecting them to be present
+ * in the arrays.
+ */
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_coef_controller pub; /* public fields */
+
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* Virtual block array for each component. */
+ jvirt_barray_ptr * whole_image;
+
+ /* Workspace for constructing dummy blocks at right/bottom edges. */
+ JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ if (pass_mode != JBUF_CRANK_DEST)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Process some data.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, blockcnt;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yindex+yoffset < compptr->last_row_height) {
+ /* Fill in pointers to real blocks in this row */
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < blockcnt; xindex++)
+ MCU_buffer[blkn++] = buffer_ptr++;
+ } else {
+ /* At bottom of image, need a whole row of dummy blocks */
+ xindex = 0;
+ }
+ /* Fill in any dummy blocks needed in this row.
+ * Dummy blocks are filled in the same way as in jccoefct.c:
+ * all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. The init routine has already zeroed the
+ * AC entries, so we need only set the DC entries correctly.
+ */
+ for (; xindex < compptr->MCU_width; xindex++) {
+ MCU_buffer[blkn] = coef->dummy_buffer[blkn];
+ MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+ blkn++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Initialize coefficient buffer controller.
+ *
+ * Each passed coefficient array must be the right size for that
+ * coefficient: width_in_blocks wide and height_in_blocks high,
+ * with unitheight at least v_samp_factor.
+ */
+
+LOCAL(void)
+transencode_coef_controller (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ my_coef_ptr coef;
+ JBLOCKROW buffer;
+ int i;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ coef->pub.start_pass = start_pass_coef;
+ coef->pub.compress_data = compress_output;
+
+ /* Save pointer to virtual arrays */
+ coef->whole_image = coef_arrays;
+
+ /* Allocate and pre-zero space for dummy DCT blocks. */
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
+ coef->dummy_buffer[i] = buffer + i;
+ }
+}
diff --git a/SrcShared/jpeg/jdapimin.c b/SrcShared/jpeg/jdapimin.c
new file mode 100644
index 0000000..cadb59f
--- /dev/null
+++ b/SrcShared/jpeg/jdapimin.c
@@ -0,0 +1,395 @@
+/*
+ * jdapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-decompression case or the
+ * transcoding-only case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jdapistd.c. But also see jcomapi.c for routines
+ * shared by compression and decompression, and jdtrans.c for the transcoding
+ * case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG decompression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_decompress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = TRUE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->src = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++)
+ cinfo->quant_tbl_ptrs[i] = NULL;
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ /* Initialize marker processor so application can override methods
+ * for COM, APPn markers before calling jpeg_read_header.
+ */
+ cinfo->marker_list = NULL;
+ jinit_marker_reader(cinfo);
+
+ /* And initialize the overall input controller. */
+ jinit_input_controller(cinfo);
+
+ /* OK, I'm ready */
+ cinfo->global_state = DSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG decompression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG decompression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Set default decompression parameters.
+ */
+
+LOCAL(void)
+default_decompress_parms (j_decompress_ptr cinfo)
+{
+ /* Guess the input colorspace, and set output colorspace accordingly. */
+ /* (Wish JPEG committee had provided a real way to specify this...) */
+ /* Note application may override our guesses. */
+ switch (cinfo->num_components) {
+ case 1:
+ cinfo->jpeg_color_space = JCS_GRAYSCALE;
+ cinfo->out_color_space = JCS_GRAYSCALE;
+ break;
+
+ case 3:
+ if (cinfo->saw_JFIF_marker) {
+ cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
+ } else if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_RGB;
+ break;
+ case 1:
+ cinfo->jpeg_color_space = JCS_YCbCr;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ break;
+ }
+ } else {
+ /* Saw no special markers, try to guess from the component IDs */
+ int cid0 = cinfo->comp_info[0].component_id;
+ int cid1 = cinfo->comp_info[1].component_id;
+ int cid2 = cinfo->comp_info[2].component_id;
+
+ if (cid0 == 1 && cid1 == 2 && cid2 == 3)
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+ else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
+ cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+ else {
+ TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ }
+ }
+ /* Always guess RGB is proper output colorspace. */
+ cinfo->out_color_space = JCS_RGB;
+ break;
+
+ case 4:
+ if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_CMYK;
+ break;
+ case 2:
+ cinfo->jpeg_color_space = JCS_YCCK;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+ break;
+ }
+ } else {
+ /* No special markers, assume straight CMYK. */
+ cinfo->jpeg_color_space = JCS_CMYK;
+ }
+ cinfo->out_color_space = JCS_CMYK;
+ break;
+
+ default:
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->out_color_space = JCS_UNKNOWN;
+ break;
+ }
+
+ /* Set defaults for other decompression parameters. */
+ cinfo->scale_num = 1; /* 1:1 scaling */
+ cinfo->scale_denom = 1;
+ cinfo->output_gamma = 1.0;
+ cinfo->buffered_image = FALSE;
+ cinfo->raw_data_out = FALSE;
+ cinfo->dct_method = JDCT_DEFAULT;
+ cinfo->do_fancy_upsampling = TRUE;
+ cinfo->do_block_smoothing = TRUE;
+ cinfo->quantize_colors = FALSE;
+ /* We set these in case application only sets quantize_colors. */
+ cinfo->dither_mode = JDITHER_FS;
+#ifdef QUANT_2PASS_SUPPORTED
+ cinfo->two_pass_quantize = TRUE;
+#else
+ cinfo->two_pass_quantize = FALSE;
+#endif
+ cinfo->desired_number_of_colors = 256;
+ cinfo->colormap = NULL;
+ /* Initialize for no mode change in buffered-image mode. */
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+}
+
+
+/*
+ * Decompression startup: read start of JPEG datastream to see what's there.
+ * Need only initialize JPEG object and supply a data source before calling.
+ *
+ * This routine will read as far as the first SOS marker (ie, actual start of
+ * compressed data), and will save all tables and parameters in the JPEG
+ * object. It will also initialize the decompression parameters to default
+ * values, and finally return JPEG_HEADER_OK. On return, the application may
+ * adjust the decompression parameters and then call jpeg_start_decompress.
+ * (Or, if the application only wanted to determine the image parameters,
+ * the data need not be decompressed. In that case, call jpeg_abort or
+ * jpeg_destroy to release any temporary space.)
+ * If an abbreviated (tables only) datastream is presented, the routine will
+ * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
+ * re-use the JPEG object to read the abbreviated image datastream(s).
+ * It is unnecessary (but OK) to call jpeg_abort in this case.
+ * The JPEG_SUSPENDED return code only occurs if the data source module
+ * requests suspension of the decompressor. In this case the application
+ * should load more source data and then re-call jpeg_read_header to resume
+ * processing.
+ * If a non-suspending data source is used and require_image is TRUE, then the
+ * return code need not be inspected since only JPEG_HEADER_OK is possible.
+ *
+ * This routine is now just a front end to jpeg_consume_input, with some
+ * extra error checking.
+ */
+
+GLOBAL(int)
+jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+{
+ int retcode;
+
+ if (cinfo->global_state != DSTATE_START &&
+ cinfo->global_state != DSTATE_INHEADER)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ retcode = jpeg_consume_input(cinfo);
+
+ switch (retcode) {
+ case JPEG_REACHED_SOS:
+ retcode = JPEG_HEADER_OK;
+ break;
+ case JPEG_REACHED_EOI:
+ if (require_image) /* Complain if application wanted an image */
+ ERREXIT(cinfo, JERR_NO_IMAGE);
+ /* Reset to start state; it would be safer to require the application to
+ * call jpeg_abort, but we can't change it now for compatibility reasons.
+ * A side effect is to free any temporary memory (there shouldn't be any).
+ */
+ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+ retcode = JPEG_HEADER_TABLES_ONLY;
+ break;
+ case JPEG_SUSPENDED:
+ /* no work */
+ break;
+ }
+
+ return retcode;
+}
+
+
+/*
+ * Consume data in advance of what the decompressor requires.
+ * This can be called at any time once the decompressor object has
+ * been created and a data source has been set up.
+ *
+ * This routine is essentially a state machine that handles a couple
+ * of critical state-transition actions, namely initial setup and
+ * transition from header scanning to ready-for-start_decompress.
+ * All the actual input is done via the input controller's consume_input
+ * method.
+ */
+
+GLOBAL(int)
+jpeg_consume_input (j_decompress_ptr cinfo)
+{
+ int retcode = JPEG_SUSPENDED;
+
+ /* NB: every possible DSTATE value should be listed in this switch */
+ switch (cinfo->global_state) {
+ case DSTATE_START:
+ /* Start-of-datastream actions: reset appropriate modules */
+ (*cinfo->inputctl->reset_input_controller) (cinfo);
+ /* Initialize application's data source module */
+ (*cinfo->src->init_source) (cinfo);
+ cinfo->global_state = DSTATE_INHEADER;
+ /*FALLTHROUGH*/
+ case DSTATE_INHEADER:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
+ /* Set up default parameters based on header data */
+ default_decompress_parms(cinfo);
+ /* Set global state: ready for start_decompress */
+ cinfo->global_state = DSTATE_READY;
+ }
+ break;
+ case DSTATE_READY:
+ /* Can't advance past first SOS until start_decompress is called */
+ retcode = JPEG_REACHED_SOS;
+ break;
+ case DSTATE_PRELOAD:
+ case DSTATE_PRESCAN:
+ case DSTATE_SCANNING:
+ case DSTATE_RAW_OK:
+ case DSTATE_BUFIMAGE:
+ case DSTATE_BUFPOST:
+ case DSTATE_STOPPING:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ break;
+ default:
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ return retcode;
+}
+
+
+/*
+ * Have we finished reading the input file?
+ */
+
+GLOBAL(boolean)
+jpeg_input_complete (j_decompress_ptr cinfo)
+{
+ /* Check for valid jpeg object */
+ if (cinfo->global_state < DSTATE_START ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->eoi_reached;
+}
+
+
+/*
+ * Is there more than one scan?
+ */
+
+GLOBAL(boolean)
+jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+{
+ /* Only valid after jpeg_read_header completes */
+ if (cinfo->global_state < DSTATE_READY ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->has_multiple_scans;
+}
+
+
+/*
+ * Finish JPEG decompression.
+ *
+ * This will normally just verify the file trailer and release temp storage.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_decompress (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+ /* Terminate final pass of non-buffered mode */
+ if (cinfo->output_scanline < cinfo->output_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state == DSTATE_BUFIMAGE) {
+ /* Finishing after a buffered-image operation */
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state != DSTATE_STOPPING) {
+ /* STOPPING = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read until EOI */
+ while (! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ /* Do final cleanup */
+ (*cinfo->src->term_source) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+ return TRUE;
+}
diff --git a/SrcShared/jpeg/jdapistd.c b/SrcShared/jpeg/jdapistd.c
new file mode 100644
index 0000000..c8e3fa0
--- /dev/null
+++ b/SrcShared/jpeg/jdapistd.c
@@ -0,0 +1,275 @@
+/*
+ * jdapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-decompression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_decompress, it will end up linking in the entire decompressor.
+ * We thus must separate this file from jdapimin.c to avoid linking the
+ * whole decompression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Decompression initialization.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * If a multipass operating mode was selected, this will do all but the
+ * last pass, and thus may take a great deal of time.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_start_decompress (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize master control, select active modules */
+ jinit_master_decompress(cinfo);
+ if (cinfo->buffered_image) {
+ /* No more work here; expecting jpeg_start_output next */
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+ }
+ cinfo->global_state = DSTATE_PRELOAD;
+ }
+ if (cinfo->global_state == DSTATE_PRELOAD) {
+ /* If file has multiple scans, absorb them all into the coef buffer */
+ if (cinfo->inputctl->has_multiple_scans) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return FALSE;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* jdmaster underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+ }
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ } else if (cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any dummy output passes, and set up for the final pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Set up for an output pass, and perform any dummy pass(es) needed.
+ * Common subroutine for jpeg_start_decompress and jpeg_start_output.
+ * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
+ * Exit: If done, returns TRUE and sets global_state for proper output mode.
+ * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
+ */
+
+LOCAL(boolean)
+output_pass_setup (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state != DSTATE_PRESCAN) {
+ /* First call: do pass setup */
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+ cinfo->global_state = DSTATE_PRESCAN;
+ }
+ /* Loop over any required dummy passes */
+ while (cinfo->master->is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Crank through the dummy pass */
+ while (cinfo->output_scanline < cinfo->output_height) {
+ JDIMENSION last_scanline;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* Process some data */
+ last_scanline = cinfo->output_scanline;
+ (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
+ &cinfo->output_scanline, (JDIMENSION) 0);
+ if (cinfo->output_scanline == last_scanline)
+ return FALSE; /* No progress made, must suspend */
+ }
+ /* Finish up dummy pass, and set up for another one */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ }
+ /* Ready for application to drive output pass through
+ * jpeg_read_scanlines or jpeg_read_raw_data.
+ */
+ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
+ return TRUE;
+}
+
+
+/*
+ * Read some scanlines of data from the JPEG decompressor.
+ *
+ * The return value will be the number of lines actually read.
+ * This may be less than the number requested in several cases,
+ * including bottom of image, data source suspension, and operating
+ * modes that emit multiple scanlines at a time.
+ *
+ * Note: we warn about excess calls to jpeg_read_scanlines() since
+ * this likely signals an application programmer error. However,
+ * an oversize buffer (max_lines > scanlines remaining) is not an error.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION max_lines)
+{
+ JDIMENSION row_ctr;
+
+ if (cinfo->global_state != DSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Process some data */
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
+ cinfo->output_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to read raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != DSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Verify that at least one iMCU row can be returned. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
+ if (max_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Decompress directly into user's buffer. */
+ if (! (*cinfo->coef->decompress_data) (cinfo, data))
+ return 0; /* suspension forced, can do nothing more */
+
+ /* OK, we processed one iMCU row. */
+ cinfo->output_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
+
+
+/* Additional entry points for buffered-image mode. */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Initialize for an output pass in buffered-image mode.
+ */
+
+GLOBAL(boolean)
+jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+{
+ if (cinfo->global_state != DSTATE_BUFIMAGE &&
+ cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Limit scan number to valid range */
+ if (scan_number <= 0)
+ scan_number = 1;
+ if (cinfo->inputctl->eoi_reached &&
+ scan_number > cinfo->input_scan_number)
+ scan_number = cinfo->input_scan_number;
+ cinfo->output_scan_number = scan_number;
+ /* Perform any dummy output passes, and set up for the real pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Finish up after an output pass in buffered-image mode.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_output (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
+ /* Terminate this pass. */
+ /* We do not require the whole pass to have been completed. */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_BUFPOST;
+ } else if (cinfo->global_state != DSTATE_BUFPOST) {
+ /* BUFPOST = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read markers looking for SOS or EOI */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
diff --git a/SrcShared/jpeg/jdatadst.c b/SrcShared/jpeg/jdatadst.c
new file mode 100644
index 0000000..a8f6fb0
--- /dev/null
+++ b/SrcShared/jpeg/jdatadst.c
@@ -0,0 +1,151 @@
+/*
+ * jdatadst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression data destination routines for the case of
+ * emitting JPEG data to a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * destination manager.
+ * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
+ * JOCTETs into 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data destination object for stdio output */
+
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ FILE * outfile; /* target stream */
+ JOCTET * buffer; /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines). The
+ * application should resume compression after it has made more room in the
+ * output buffer. Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
+ (size_t) OUTPUT_BUF_SIZE)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written. Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ fflush(dest->outfile);
+ /* Make sure we wrote the output file OK */
+ if (ferror(dest->outfile))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
+{
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+}
diff --git a/SrcShared/jpeg/jdatasrc.c b/SrcShared/jpeg/jdatasrc.c
new file mode 100644
index 0000000..edc752b
--- /dev/null
+++ b/SrcShared/jpeg/jdatasrc.c
@@ -0,0 +1,212 @@
+/*
+ * jdatasrc.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression data source routines for the case of
+ * reading JPEG data from a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * source manager.
+ * IMPORTANT: we assume that fread() will correctly transcribe an array of
+ * JOCTETs from 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ FILE * infile; /* source stream */
+ JOCTET * buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
+
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = TRUE;
+}
+
+
+/*
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded. It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return. If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer. In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there. However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later. In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any). The application should resume
+ * decompression after it has loaded more data into the input buffer. Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ */
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return. If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ */
+
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ /* note we assume that fill_input_buffer will never return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+
+/*
+ * An additional method that can be provided by data source modules is the
+ * resync_to_restart method for error recovery in the presence of RST markers.
+ * For the moment, this source module just uses the default resync method
+ * provided by the JPEG library. That method assumes that no backtracking
+ * is possible.
+ */
+
+
+/*
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read. Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo)
+{
+ /* no work necessary here */
+}
+
+
+/*
+ * Prepare for input from a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing decompression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
+{
+ my_src_ptr src;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ INPUT_BUF_SIZE * SIZEOF(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
diff --git a/SrcShared/jpeg/jdcoefct.c b/SrcShared/jpeg/jdcoefct.c
new file mode 100644
index 0000000..4938d20
--- /dev/null
+++ b/SrcShared/jpeg/jdcoefct.c
@@ -0,0 +1,736 @@
+/*
+ * jdcoefct.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for decompression.
+ * This controller is the top level of the JPEG decompressor proper.
+ * The coefficient buffer lies between entropy decoding and inverse-DCT steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ * Also, the input side (only) is used when reading a file for transcoding.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+/* Block smoothing is only applicable for progressive JPEG, so: */
+#ifndef D_PROGRESSIVE_SUPPORTED
+#undef BLOCK_SMOOTHING_SUPPORTED
+#endif
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_coef_controller pub; /* public fields */
+
+ /* These variables keep track of the current location of the input side. */
+ /* cinfo->input_iMCU_row is also used for this. */
+ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+ /* In single-pass modes, it's sufficient to buffer just one MCU.
+ * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
+ * and let the entropy decoder write into that workspace each time.
+ * (On 80x86, the workspace is FAR even though it's not really very big;
+ * this is to keep the module interfaces unchanged when a large coefficient
+ * buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays; it is used only by the input side.
+ */
+ JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+#endif
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* When doing block smoothing, we latch coefficient Al values here */
+ int * coef_bits_latch;
+#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
+#endif
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_onepass
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) decompress_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
+METHODDEF(int) decompress_smooth_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->MCU_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->input_iMCU_row = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* If multipass, check to see whether to use block smoothing on this pass */
+ if (coef->pub.coef_arrays != NULL) {
+ if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
+ coef->pub.decompress_data = decompress_smooth_data;
+ else
+ coef->pub.decompress_data = decompress_data;
+ }
+#endif
+ cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the single-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, useful_width;
+ JSAMPARRAY output_ptr;
+ JDIMENSION start_col, output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Loop to process as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
+ jzero_far((void FAR *) coef->MCU_buffer[0],
+ (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
+ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ /* Determine where data should go in output_buf and do the IDCT thing.
+ * We skip dummy blocks at the right and bottom edges (but blkn gets
+ * incremented past them!). Note the inner loop relies on having
+ * allocated the MCU_buffer[] blocks sequentially.
+ */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed) {
+ blkn += compptr->MCU_blocks;
+ continue;
+ }
+ inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
+ useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ output_ptr = output_buf[compptr->component_index] +
+ yoffset * compptr->DCT_scaled_size;
+ start_col = MCU_col_num * compptr->MCU_sample_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (cinfo->input_iMCU_row < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ output_col = start_col;
+ for (xindex = 0; xindex < useful_width; xindex++) {
+ (*inverse_DCT) (cinfo, compptr,
+ (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ output_ptr, output_col);
+ output_col += compptr->DCT_scaled_size;
+ }
+ }
+ blkn += compptr->MCU_width;
+ output_ptr += compptr->DCT_scaled_size;
+ }
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ cinfo->output_iMCU_row++;
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+ return JPEG_SUSPENDED; /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image coefficient buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor block rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ cinfo->input_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Note: entropy decoder expects buffer to be zeroed,
+ * but this is handled automatically by the memory manager
+ * because we requested a pre-zeroed array.
+ */
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to fetch the MCU. */
+ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Decompress and return some data in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num;
+ int ci, block_row, block_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number < cinfo->output_scan_number ||
+ (cinfo->input_scan_number == cinfo->output_scan_number &&
+ cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ cinfo->output_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ inverse_DCT = cinfo->idct->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ output_col = 0;
+ for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
+ output_ptr, output_col);
+ buffer_ptr++;
+ output_col += compptr->DCT_scaled_size;
+ }
+ output_ptr += compptr->DCT_scaled_size;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+/*
+ * This code applies interblock smoothing as described by section K.8
+ * of the JPEG standard: the first 5 AC coefficients are estimated from
+ * the DC values of a DCT block and its 8 neighboring blocks.
+ * We apply smoothing only for progressive JPEG decoding, and only if
+ * the coefficients it can estimate are not yet known to full precision.
+ */
+
+/* Natural-order array positions of the first 5 zigzag-order coefficients */
+#define Q01_POS 1
+#define Q10_POS 8
+#define Q20_POS 16
+#define Q11_POS 9
+#define Q02_POS 2
+
+/*
+ * Determine whether block smoothing is applicable and safe.
+ * We also latch the current states of the coef_bits[] entries for the
+ * AC coefficients; otherwise, if the input side of the decompressor
+ * advances into a new scan, we might think the coefficients are known
+ * more accurately than they really are.
+ */
+
+LOCAL(boolean)
+smoothing_ok (j_decompress_ptr cinfo)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ boolean smoothing_useful = FALSE;
+ int ci, coefi;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtable;
+ int * coef_bits;
+ int * coef_bits_latch;
+
+ if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
+ return FALSE;
+
+ /* Allocate latch area if not already done */
+ if (coef->coef_bits_latch == NULL)
+ coef->coef_bits_latch = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components *
+ (SAVED_COEFS * SIZEOF(int)));
+ coef_bits_latch = coef->coef_bits_latch;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* All components' quantization values must already be latched. */
+ if ((qtable = compptr->quant_table) == NULL)
+ return FALSE;
+ /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+ if (qtable->quantval[0] == 0 ||
+ qtable->quantval[Q01_POS] == 0 ||
+ qtable->quantval[Q10_POS] == 0 ||
+ qtable->quantval[Q20_POS] == 0 ||
+ qtable->quantval[Q11_POS] == 0 ||
+ qtable->quantval[Q02_POS] == 0)
+ return FALSE;
+ /* DC values must be at least partly known for all components. */
+ coef_bits = cinfo->coef_bits[ci];
+ if (coef_bits[0] < 0)
+ return FALSE;
+ /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
+ for (coefi = 1; coefi <= 5; coefi++) {
+ coef_bits_latch[coefi] = coef_bits[coefi];
+ if (coef_bits[coefi] != 0)
+ smoothing_useful = TRUE;
+ }
+ coef_bits_latch += SAVED_COEFS;
+ }
+
+ return smoothing_useful;
+}
+
+
+/*
+ * Variant of decompress_data for use when doing block smoothing.
+ */
+
+METHODDEF(int)
+decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num, last_block_column;
+ int ci, block_row, block_rows, access_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+ boolean first_row, last_row;
+ JBLOCK workspace;
+ int *coef_bits;
+ JQUANT_TBL *quanttbl;
+ INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
+ int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+ int Al, pred;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if (cinfo->input_scan_number == cinfo->output_scan_number) {
+ /* If input is working on current scan, we ordinarily want it to
+ * have completed the current row. But if input scan is DC,
+ * we want it to keep one row ahead so that next block row's DC
+ * values are up to date.
+ */
+ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
+ if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+ break;
+ }
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row) {
+ block_rows = compptr->v_samp_factor;
+ access_rows = block_rows * 2; /* this and next iMCU row */
+ last_row = FALSE;
+ } else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ access_rows = block_rows; /* this iMCU row only */
+ last_row = TRUE;
+ }
+ /* Align the virtual buffer for this component. */
+ if (cinfo->output_iMCU_row > 0) {
+ access_rows += compptr->v_samp_factor; /* prior iMCU row too */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
+ (JDIMENSION) access_rows, FALSE);
+ buffer += compptr->v_samp_factor; /* point to current iMCU row */
+ first_row = FALSE;
+ } else {
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
+ first_row = TRUE;
+ }
+ /* Fetch component-dependent info */
+ coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
+ quanttbl = compptr->quant_table;
+ Q00 = quanttbl->quantval[0];
+ Q01 = quanttbl->quantval[Q01_POS];
+ Q10 = quanttbl->quantval[Q10_POS];
+ Q20 = quanttbl->quantval[Q20_POS];
+ Q11 = quanttbl->quantval[Q11_POS];
+ Q02 = quanttbl->quantval[Q02_POS];
+ inverse_DCT = cinfo->idct->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ if (first_row && block_row == 0)
+ prev_block_row = buffer_ptr;
+ else
+ prev_block_row = buffer[block_row-1];
+ if (last_row && block_row == block_rows-1)
+ next_block_row = buffer_ptr;
+ else
+ next_block_row = buffer[block_row+1];
+ /* We fetch the surrounding DC values using a sliding-register approach.
+ * Initialize all nine here so as to do the right thing on narrow pics.
+ */
+ DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
+ DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
+ DC7 = DC8 = DC9 = (int) next_block_row[0][0];
+ output_col = 0;
+ last_block_column = compptr->width_in_blocks - 1;
+ for (block_num = 0; block_num <= last_block_column; block_num++) {
+ /* Fetch current DCT block into workspace so we can modify it. */
+ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+ /* Update DC values */
+ if (block_num < last_block_column) {
+ DC3 = (int) prev_block_row[1][0];
+ DC6 = (int) buffer_ptr[1][0];
+ DC9 = (int) next_block_row[1][0];
+ }
+ /* Compute coefficient estimates per K.8.
+ * An estimate is applied only if coefficient is still zero,
+ * and is not known to be fully accurate.
+ */
+ /* AC01 */
+ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+ num = 36 * Q00 * (DC4 - DC6);
+ if (num >= 0) {
+ pred = (int) (((Q01<<7) + num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q01<<7) - num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[1] = (JCOEF) pred;
+ }
+ /* AC10 */
+ if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+ num = 36 * Q00 * (DC2 - DC8);
+ if (num >= 0) {
+ pred = (int) (((Q10<<7) + num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q10<<7) - num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[8] = (JCOEF) pred;
+ }
+ /* AC20 */
+ if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
+ num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q20<<7) + num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q20<<7) - num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[16] = (JCOEF) pred;
+ }
+ /* AC11 */
+ if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+ num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
+ if (num >= 0) {
+ pred = (int) (((Q11<<7) + num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q11<<7) - num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[9] = (JCOEF) pred;
+ }
+ /* AC02 */
+ if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
+ num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q02<<7) + num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q02<<7) - num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[2] = (JCOEF) pred;
+ }
+ /* OK, do the IDCT */
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
+ output_ptr, output_col);
+ /* Advance for next column */
+ DC1 = DC2; DC2 = DC3;
+ DC4 = DC5; DC5 = DC6;
+ DC7 = DC8; DC8 = DC9;
+ buffer_ptr++, prev_block_row++, next_block_row++;
+ output_col += compptr->DCT_scaled_size;
+ }
+ output_ptr += compptr->DCT_scaled_size;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_coef_ptr coef;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_d_coef_controller *) coef;
+ coef->pub.start_input_pass = start_input_pass;
+ coef->pub.start_output_pass = start_output_pass;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ coef->coef_bits_latch = NULL;
+#endif
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ /* Note we ask for a pre-zeroed array. */
+ int ci, access_rows;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ access_rows = compptr->v_samp_factor;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* If block smoothing could be used, need a bigger window */
+ if (cinfo->progressive_mode)
+ access_rows *= 3;
+#endif
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) access_rows);
+ }
+ coef->pub.consume_data = consume_data;
+ coef->pub.decompress_data = decompress_data;
+ coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ coef->pub.consume_data = dummy_consume_data;
+ coef->pub.decompress_data = decompress_onepass;
+ coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/SrcShared/jpeg/jdcolor.c b/SrcShared/jpeg/jdcolor.c
new file mode 100644
index 0000000..6c04dfe
--- /dev/null
+++ b/SrcShared/jpeg/jdcolor.c
@@ -0,0 +1,396 @@
+/*
+ * jdcolor.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains output colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_deconverter pub; /* public fields */
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+} my_color_deconverter;
+
+typedef my_color_deconverter * my_cconvert_ptr;
+
+
+/**************** YCbCr -> RGB conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * R = Y + 1.40200 * Cr
+ * G = Y - 0.34414 * Cb - 0.71414 * Cr
+ * B = Y + 1.77200 * Cb
+ * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ * Notice that Y, being an integral input, does not contribute any fraction
+ * so it need not participate in the rounding.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times Cb and Cr for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+ * values for the G calculation are left scaled up, since we must add them
+ * together before rounding.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ cconvert->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ cconvert->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ cconvert->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ cconvert->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the output colorspace.
+ *
+ * Note that we change from noninterleaved, one-plane-per-component format
+ * to interleaved-pixel format. The output buffer is therefore three times
+ * as wide as the input buffer.
+ * A starting row offset is provided only for the input buffer. The caller
+ * can easily adjust the passed output_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+ycc_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
+ outptr[RGB_GREEN] = range_limit[y +
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS))];
+ outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/**************** Cases other than YCbCr -> RGB **************/
+
+
+/*
+ * Color conversion for no colorspace change: just copy the data,
+ * converting from separate-planes to interleaved representation.
+ */
+
+METHODDEF(void)
+null_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION count;
+ register int num_components = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->output_width;
+ int ci;
+
+ while (--num_rows >= 0) {
+ for (ci = 0; ci < num_components; ci++) {
+ inptr = input_buf[ci][input_row];
+ outptr = output_buf[0] + ci;
+ for (count = num_cols; count > 0; count--) {
+ *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
+ outptr += num_components;
+ }
+ }
+ input_row++;
+ output_buf++;
+ }
+}
+
+
+/*
+ * Color conversion for grayscale: just copy the data.
+ * This also works for YCbCr -> grayscale conversion, in which
+ * we just copy the Y (luminance) component and ignore chrominance.
+ */
+
+METHODDEF(void)
+grayscale_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
+ num_rows, cinfo->output_width);
+}
+
+
+/*
+ * Convert grayscale to RGB: just duplicate the graylevel three times.
+ * This is provided to support applications that don't want to cope
+ * with grayscale as a separate case.
+ */
+
+METHODDEF(void)
+gray_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+
+ while (--num_rows >= 0) {
+ inptr = input_buf[0][input_row++];
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ /* We can dispense with GETJSAMPLE() here */
+ outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/*
+ * Adobe-style YCCK->CMYK conversion.
+ * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume build_ycc_rgb_table has been called.
+ */
+
+METHODDEF(void)
+ycck_cmyk_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2, inptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ inptr3 = input_buf[3][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
+ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS)))];
+ outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
+ /* K passes through unchanged */
+ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
+ outptr += 4;
+ }
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+start_pass_dcolor (j_decompress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for output colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_deconverter (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+ int ci;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_deconverter));
+ cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+ cconvert->pub.start_pass = start_pass_dcolor;
+
+ /* Make sure num_components agrees with jpeg_color_space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->num_components < 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+ }
+
+ /* Set out_color_components and conversion method based on requested space.
+ * Also clear the component_needed flags for any unused components,
+ * so that earlier pipeline stages can avoid useless computation.
+ */
+
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+ cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = grayscale_convert;
+ /* For color->grayscale conversion, only the Y (0) component is needed */
+ for (ci = 1; ci < cinfo->num_components; ci++)
+ cinfo->comp_info[ci].component_needed = FALSE;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ if (cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = ycc_rgb_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
+ cconvert->pub.color_convert = gray_rgb_convert;
+ } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ cinfo->out_color_components = 4;
+ if (cinfo->jpeg_color_space == JCS_YCCK) {
+ cconvert->pub.color_convert = ycck_cmyk_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_CMYK) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default:
+ /* Permit null conversion to same output space */
+ if (cinfo->out_color_space == cinfo->jpeg_color_space) {
+ cinfo->out_color_components = cinfo->num_components;
+ cconvert->pub.color_convert = null_convert;
+ } else /* unsupported non-null conversion */
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+ }
+
+ if (cinfo->quantize_colors)
+ cinfo->output_components = 1; /* single colormapped output component */
+ else
+ cinfo->output_components = cinfo->out_color_components;
+}
diff --git a/SrcShared/jpeg/jdct.h b/SrcShared/jpeg/jdct.h
new file mode 100644
index 0000000..04192a2
--- /dev/null
+++ b/SrcShared/jpeg/jdct.h
@@ -0,0 +1,176 @@
+/*
+ * jdct.h
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the forward and
+ * inverse DCT modules. These declarations are private to the DCT managers
+ * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
+ * The individual DCT algorithms are kept in separate files to ease
+ * machine-dependent tuning (e.g., assembly coding).
+ */
+
+
+/*
+ * A forward DCT routine is given a pointer to a work area of type DCTELEM[];
+ * the DCT is to be performed in-place in that buffer. Type DCTELEM is int
+ * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
+ * implementations use an array of type FAST_FLOAT, instead.)
+ * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
+ * The DCT outputs are returned scaled up by a factor of 8; they therefore
+ * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
+ * convention improves accuracy in integer implementations and saves some
+ * work in floating-point ones.
+ * Quantization of the output coefficients is done by jcdctmgr.c.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef int DCTELEM; /* 16 or 32 bits is fine */
+#else
+typedef INT32 DCTELEM; /* must have 32 bits */
+#endif
+
+typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
+typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
+
+
+/*
+ * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
+ * to an output sample array. The routine must dequantize the input data as
+ * well as perform the IDCT; for dequantization, it uses the multiplier table
+ * pointed to by compptr->dct_table. The output data is to be placed into the
+ * sample array starting at a specified column. (Any row offset needed will
+ * be applied to the array pointer before it is passed to the IDCT code.)
+ * Note that the number of samples emitted by the IDCT routine is
+ * DCT_scaled_size * DCT_scaled_size.
+ */
+
+/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
+
+/*
+ * Each IDCT routine has its own ideas about the best dct_table element type.
+ */
+
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+#if BITS_IN_JSAMPLE == 8
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
+#else
+typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
+#endif
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+
+
+/*
+ * Each IDCT routine is responsible for range-limiting its results and
+ * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
+ * be quite far out of range if the input data is corrupt, so a bulletproof
+ * range-limiting step is required. We use a mask-and-table-lookup method
+ * to do the combined operations quickly. See the comments with
+ * prepare_range_limit_table (in jdmaster.c) for more info.
+ */
+
+#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
+
+#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_fdct_islow jFDislow
+#define jpeg_fdct_ifast jFDifast
+#define jpeg_fdct_float jFDfloat
+#define jpeg_idct_islow jRDislow
+#define jpeg_idct_ifast jRDifast
+#define jpeg_idct_float jRDfloat
+#define jpeg_idct_4x4 jRD4x4
+#define jpeg_idct_2x2 jRD2x2
+#define jpeg_idct_1x1 jRD1x1
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Extern declarations for the forward and inverse DCT routines. */
+
+EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
+
+EXTERN(void) jpeg_idct_islow
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_ifast
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_float
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x4
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x2
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_1x1
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+
+
+/*
+ * Macros for handling fixed-point arithmetic; these are used by many
+ * but not all of the DCT/IDCT modules.
+ *
+ * All values are expected to be of type INT32.
+ * Fractional constants are scaled left by CONST_BITS bits.
+ * CONST_BITS is defined within each module using these macros,
+ * and may differ from one module to the next.
+ */
+
+#define ONE ((INT32) 1)
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
+ * thus causing a lot of useless floating-point operations at run time.
+ */
+
+#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * This macro is used only when the two inputs will actually be no more than
+ * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
+ * full 32x32 multiply. This provides a useful speedup on many machines.
+ * Unfortunately there is no way to specify a 16x16->32 multiply portably
+ * in C, but some C compilers will do the right thing if you provide the
+ * correct combination of casts.
+ */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
+#endif
+
+#ifndef MULTIPLY16C16 /* default definition */
+#define MULTIPLY16C16(var,const) ((var) * (const))
+#endif
+
+/* Same except both inputs are variables. */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
+#endif
+
+#ifndef MULTIPLY16V16 /* default definition */
+#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
+#endif
diff --git a/SrcShared/jpeg/jddctmgr.c b/SrcShared/jpeg/jddctmgr.c
new file mode 100644
index 0000000..bbf8d0e
--- /dev/null
+++ b/SrcShared/jpeg/jddctmgr.c
@@ -0,0 +1,269 @@
+/*
+ * jddctmgr.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the inverse-DCT management logic.
+ * This code selects a particular IDCT implementation to be used,
+ * and it performs related housekeeping chores. No code in this file
+ * is executed per IDCT step, only during output pass setup.
+ *
+ * Note that the IDCT routines are responsible for performing coefficient
+ * dequantization as well as the IDCT proper. This module sets up the
+ * dequantization multiplier table needed by the IDCT routine.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/*
+ * The decompressor input side (jdinput.c) saves away the appropriate
+ * quantization table for each component at the start of the first scan
+ * involving that component. (This is necessary in order to correctly
+ * decode files that reuse Q-table slots.)
+ * When we are ready to make an output pass, the saved Q-table is converted
+ * to a multiplier table that will actually be used by the IDCT routine.
+ * The multiplier table contents are IDCT-method-dependent. To support
+ * application changes in IDCT method between scans, we can remake the
+ * multiplier tables if necessary.
+ * In buffered-image mode, the first output pass may occur before any data
+ * has been seen for some components, and thus before their Q-tables have
+ * been saved away. To handle this case, multiplier tables are preset
+ * to zeroes; the result of the IDCT will be a neutral gray level.
+ */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ struct jpeg_inverse_dct pub; /* public fields */
+
+ /* This array contains the IDCT method code that each multiplier table
+ * is currently set up for, or -1 if it's not yet set up.
+ * The actual multiplier tables are pointed to by dct_table in the
+ * per-component comp_info structures.
+ */
+ int cur_method[MAX_COMPONENTS];
+} my_idct_controller;
+
+typedef my_idct_controller * my_idct_ptr;
+
+
+/* Allocated multiplier tables: big enough for any supported variant */
+
+typedef union {
+ ISLOW_MULT_TYPE islow_array[DCTSIZE2];
+#ifdef DCT_IFAST_SUPPORTED
+ IFAST_MULT_TYPE ifast_array[DCTSIZE2];
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ FLOAT_MULT_TYPE float_array[DCTSIZE2];
+#endif
+} multiplier_table;
+
+
+/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
+ * so be sure to compile that code if either ISLOW or SCALING is requested.
+ */
+#ifdef DCT_ISLOW_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#else
+#ifdef IDCT_SCALING_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#endif
+#endif
+
+
+/*
+ * Prepare for an output pass.
+ * Here we select the proper IDCT routine for each component and build
+ * a matching multiplier table.
+ */
+
+METHODDEF(void)
+start_pass (j_decompress_ptr cinfo)
+{
+ my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
+ int ci, i;
+ jpeg_component_info *compptr;
+ int method = 0;
+ inverse_DCT_method_ptr method_ptr = NULL;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Select the proper IDCT routine for this component's scaling */
+ switch (compptr->DCT_scaled_size) {
+#ifdef IDCT_SCALING_SUPPORTED
+ case 1:
+ method_ptr = jpeg_idct_1x1;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+ case 2:
+ method_ptr = jpeg_idct_2x2;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+ case 4:
+ method_ptr = jpeg_idct_4x4;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+#endif
+ case DCTSIZE:
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ method_ptr = jpeg_idct_islow;
+ method = JDCT_ISLOW;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ method_ptr = jpeg_idct_ifast;
+ method = JDCT_IFAST;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ method_ptr = jpeg_idct_float;
+ method = JDCT_FLOAT;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ break;
+ default:
+ ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
+ break;
+ }
+ idct->pub.inverse_DCT[ci] = method_ptr;
+ /* Create multiplier table from quant table.
+ * However, we can skip this if the component is uninteresting
+ * or if we already built the table. Also, if no quant table
+ * has yet been saved for the component, we leave the
+ * multiplier table all-zero; we'll be reading zeroes from the
+ * coefficient controller's buffer anyway.
+ */
+ if (! compptr->component_needed || idct->cur_method[ci] == method)
+ continue;
+ qtbl = compptr->quant_table;
+ if (qtbl == NULL) /* happens if no data yet for component */
+ continue;
+ idct->cur_method[ci] = method;
+ switch (method) {
+#ifdef PROVIDE_ISLOW_TABLES
+ case JDCT_ISLOW:
+ {
+ /* For LL&M IDCT method, multipliers are equal to raw quantization
+ * coefficients, but are stored as ints to ensure access efficiency.
+ */
+ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ for (i = 0; i < DCTSIZE2; i++) {
+ ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+ }
+ }
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * For integer operation, the multiplier table is to be scaled by
+ * IFAST_SCALE_BITS.
+ */
+ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ ifmtbl[i] = (IFAST_MULT_TYPE)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-IFAST_SCALE_BITS);
+ }
+ }
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ */
+ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fmtbl[i] = (FLOAT_MULT_TYPE)
+ ((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col]);
+ i++;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Initialize IDCT manager.
+ */
+
+GLOBAL(void)
+jinit_inverse_dct (j_decompress_ptr cinfo)
+{
+ my_idct_ptr idct;
+ int ci;
+ jpeg_component_info *compptr;
+
+ idct = (my_idct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_idct_controller));
+ cinfo->idct = (struct jpeg_inverse_dct *) idct;
+ idct->pub.start_pass = start_pass;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate and pre-zero a multiplier table for each component */
+ compptr->dct_table =
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(multiplier_table));
+ MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
+ /* Mark multiplier table not yet set up for any method */
+ idct->cur_method[ci] = -1;
+ }
+}
diff --git a/SrcShared/jpeg/jdhuff.c b/SrcShared/jpeg/jdhuff.c
new file mode 100644
index 0000000..b5ba39f
--- /dev/null
+++ b/SrcShared/jpeg/jdhuff.c
@@ -0,0 +1,651 @@
+/*
+ * jdhuff.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdhuff.h" /* Declarations shared with jdphuff.c */
+
+
+/*
+ * Expanded entropy decoder object for Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ struct jpeg_entropy_decoder pub; /* public fields */
+
+ /* These fields are loaded into local variables at start of each MCU.
+ * In case of suspension, we exit WITHOUT updating them.
+ */
+ bitread_perm_state bitstate; /* Bit buffer at start of MCU */
+ savable_state saved; /* Other state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+ /* Precalculated info set up by start_pass for use in decode_mcu: */
+
+ /* Pointers to derived tables to be used for each block within an MCU */
+ d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+ d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+ /* Whether we care about the DC and AC coefficient values for each block */
+ boolean dc_needed[D_MAX_BLOCKS_IN_MCU];
+ boolean ac_needed[D_MAX_BLOCKS_IN_MCU];
+} huff_entropy_decoder;
+
+typedef huff_entropy_decoder * huff_entropy_ptr;
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_huff_decoder (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, blkn, dctbl, actbl;
+ jpeg_component_info * compptr;
+
+ /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+ * This ought to be an error condition, but we make it a warning because
+ * there are some baseline files out there with all zeroes in these bytes.
+ */
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ cinfo->Ah != 0 || cinfo->Al != 0)
+ WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Precalculate decoding info for each block in an MCU of this scan */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ /* Precalculate which table to use for each block */
+ entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
+ entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
+ /* Decide whether we really care about the coefficient values */
+ if (compptr->component_needed) {
+ entropy->dc_needed[blkn] = TRUE;
+ /* we don't need the ACs if producing a 1/8th-size image */
+ entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1);
+ } else {
+ entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
+ }
+ }
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->pub.insufficient_data = FALSE;
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ *
+ * Note this is also used by jdphuff.c.
+ */
+
+GLOBAL(void)
+jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ d_derived_tbl *dtbl;
+ int p, i, l, si, numsymbols;
+ int lookbits, ctr;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (d_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(d_derived_tbl));
+ dtbl = *pdtbl;
+ dtbl->pub = htbl; /* fill in back link */
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ numsymbols = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure F.15: generate decoding tables for bit-sequential decoding */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ if (htbl->bits[l]) {
+ /* valoffset[l] = huffval[] index of 1st symbol of code length l,
+ * minus the minimum code of length l
+ */
+ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
+ p += htbl->bits[l];
+ dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+ } else {
+ dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
+ }
+ }
+ dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
+
+ /* Compute lookahead tables to speed up decoding.
+ * First we set all the table entries to 0, indicating "too long";
+ * then we iterate through the Huffman codes that are short enough and
+ * fill in all the entries that correspond to bit sequences starting
+ * with that code.
+ */
+
+ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
+
+ p = 0;
+ for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
+ for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+ /* l = current code's length, p = its index in huffcode[] & huffval[]. */
+ /* Generate left-justified code followed by all possible bit sequences */
+ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
+ for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+ dtbl->look_nbits[lookbits] = l;
+ dtbl->look_sym[lookbits] = htbl->huffval[p];
+ lookbits++;
+ }
+ }
+ }
+
+ /* Validate symbols as being reasonable.
+ * For AC tables, we make no check, but accept all byte values 0..255.
+ * For DC tables, we require the symbols to be in range 0..15.
+ * (Tighter bounds could be applied depending on the data depth and mode,
+ * but this is sufficient to ensure safe decoding.)
+ */
+ if (isDC) {
+ for (i = 0; i < numsymbols; i++) {
+ int sym = htbl->huffval[i];
+ if (sym < 0 || sym > 15)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ }
+ }
+}
+
+
+/*
+ * Out-of-line code for bit fetching (shared with jdphuff.c).
+ * See jdhuff.h for info about usage.
+ * Note: current values of get_buffer and bits_left are passed as parameters,
+ * but are returned in the corresponding fields of the state struct.
+ *
+ * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
+ * of get_buffer to be used. (On machines with wider words, an even larger
+ * buffer could be used.) However, on some machines 32-bit shifts are
+ * quite slow and take time proportional to the number of places shifted.
+ * (This is true with most PC compilers, for instance.) In this case it may
+ * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
+ * average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
+ */
+
+#ifdef SLOW_SHIFT_32
+#define MIN_GET_BITS 15 /* minimum allowable value */
+#else
+#define MIN_GET_BITS (BIT_BUF_SIZE-7)
+#endif
+
+
+GLOBAL(boolean)
+jpeg_fill_bit_buffer (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ int nbits)
+/* Load up the bit buffer to a depth of at least nbits */
+{
+ /* Copy heavily used state fields into locals (hopefully registers) */
+ register const JOCTET * next_input_byte = state->next_input_byte;
+ register size_t bytes_in_buffer = state->bytes_in_buffer;
+ j_decompress_ptr cinfo = state->cinfo;
+
+ /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
+ /* (It is assumed that no request will be for more than that many bits.) */
+ /* We fail to do so only if we hit a marker or are forced to suspend. */
+
+ if (cinfo->unread_marker == 0) { /* cannot advance past a marker */
+ while (bits_left < MIN_GET_BITS) {
+ register int c;
+
+ /* Attempt to read a byte */
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+
+ /* If it's 0xFF, check and discard stuffed zero byte */
+ if (c == 0xFF) {
+ /* Loop here to discard any padding FF's on terminating marker,
+ * so that we can save a valid unread_marker value. NOTE: we will
+ * accept multiple FF's followed by a 0 as meaning a single FF data
+ * byte. This data pattern is not valid according to the standard.
+ */
+ do {
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+ } while (c == 0xFF);
+
+ if (c == 0) {
+ /* Found FF/00, which represents an FF data byte */
+ c = 0xFF;
+ } else {
+ /* Oops, it's actually a marker indicating end of compressed data.
+ * Save the marker code for later use.
+ * Fine point: it might appear that we should save the marker into
+ * bitread working state, not straight into permanent state. But
+ * once we have hit a marker, we cannot need to suspend within the
+ * current MCU, because we will read no more bytes from the data
+ * source. So it is OK to update permanent state right away.
+ */
+ cinfo->unread_marker = c;
+ /* See if we need to insert some fake zero bits. */
+ goto no_more_bytes;
+ }
+ }
+
+ /* OK, load c into get_buffer */
+ get_buffer = (get_buffer << 8) | c;
+ bits_left += 8;
+ } /* end while */
+ } else {
+ no_more_bytes:
+ /* We get here if we've read the marker that terminates the compressed
+ * data segment. There should be enough bits in the buffer register
+ * to satisfy the request; if so, no problem.
+ */
+ if (nbits > bits_left) {
+ /* Uh-oh. Report corrupted data to user and stuff zeroes into
+ * the data stream, so that we can produce some kind of image.
+ * We use a nonvolatile flag to ensure that only one warning message
+ * appears per data segment.
+ */
+ if (! cinfo->entropy->insufficient_data) {
+ WARNMS(cinfo, JWRN_HIT_MARKER);
+ cinfo->entropy->insufficient_data = TRUE;
+ }
+ /* Fill the buffer with zero bits */
+ get_buffer <<= MIN_GET_BITS - bits_left;
+ bits_left = MIN_GET_BITS;
+ }
+ }
+
+ /* Unload the local registers */
+ state->next_input_byte = next_input_byte;
+ state->bytes_in_buffer = bytes_in_buffer;
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ return TRUE;
+}
+
+
+/*
+ * Out-of-line code for Huffman code decoding.
+ * See jdhuff.h for info about usage.
+ */
+
+GLOBAL(int)
+jpeg_huff_decode (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ d_derived_tbl * htbl, int min_bits)
+{
+ register int l = min_bits;
+ register INT32 code;
+
+ /* HUFF_DECODE has determined that the code is at least min_bits */
+ /* bits long, so fetch that many bits in one swoop. */
+
+ CHECK_BIT_BUFFER(*state, l, return -1);
+ code = GET_BITS(l);
+
+ /* Collect the rest of the Huffman code one bit at a time. */
+ /* This is per Figure F.16 in the JPEG spec. */
+
+ while (code > htbl->maxcode[l]) {
+ code <<= 1;
+ CHECK_BIT_BUFFER(*state, 1, return -1);
+ code |= GET_BITS(1);
+ l++;
+ }
+
+ /* Unload the local registers */
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ /* With garbage input we may reach the sentinel value l = 17. */
+
+ if (l > 16) {
+ WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
+ return 0; /* fake a zero as the safest result */
+ }
+
+ return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] = /* entry n is 2**(n-1) */
+ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+ ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+ ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->pub.insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Decode and return one MCU's worth of Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
+ * (Wholesale zeroing is usually a little faster than retail...)
+ *
+ * Returns FALSE if data source requested suspension. In that case no
+ * changes have been made to permanent state. (Exception: some output
+ * coefficients may already have been assigned. This is harmless for
+ * this module, since we'll just re-assign them on the next call.)
+ */
+
+METHODDEF(boolean)
+decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int blkn;
+ BITREAD_STATE_VARS;
+ savable_state state;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ JBLOCKROW block = MCU_data[blkn];
+ d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
+ d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+ register int s, k, r;
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+
+ if (entropy->dc_needed[blkn]) {
+ /* Convert DC difference to actual value, update last_dc_val */
+ int ci = cinfo->MCU_membership[blkn];
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
+ (*block)[0] = (JCOEF) s;
+ }
+
+ if (entropy->ac_needed[blkn]) {
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* Since zeroes are skipped, output area must be cleared beforehand */
+ for (k = 1; k < DCTSIZE2; k++) {
+ HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Output coefficient in natural (dezigzagged) order.
+ * Note: the extra entries in jpeg_natural_order[] will save us
+ * if k >= DCTSIZE2, which could happen if the data is corrupted.
+ */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ } else {
+ if (r != 15)
+ break;
+ k += 15;
+ }
+ }
+
+ } else {
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* In this path we just discard the values */
+ for (k = 1; k < DCTSIZE2; k++) {
+ HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ DROP_BITS(s);
+ } else {
+ if (r != 15)
+ break;
+ k += 15;
+ }
+ }
+
+ }
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_huff_decoder (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy;
+ int i;
+
+ entropy = (huff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(huff_entropy_decoder));
+ cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ entropy->pub.start_pass = start_pass_huff_decoder;
+ entropy->pub.decode_mcu = decode_mcu;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+ }
+}
diff --git a/SrcShared/jpeg/jdhuff.h b/SrcShared/jpeg/jdhuff.h
new file mode 100644
index 0000000..ae19b6c
--- /dev/null
+++ b/SrcShared/jpeg/jdhuff.h
@@ -0,0 +1,201 @@
+/*
+ * jdhuff.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy decoding routines
+ * that are shared between the sequential decoder (jdhuff.c) and the
+ * progressive decoder (jdphuff.c). No other modules need to see these.
+ */
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_d_derived_tbl jMkDDerived
+#define jpeg_fill_bit_buffer jFilBitBuf
+#define jpeg_huff_decode jHufDecode
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Derived data constructed for each Huffman table */
+
+#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
+
+typedef struct {
+ /* Basic tables: (element [0] of each array is unused) */
+ INT32 maxcode[18]; /* largest code of length k (-1 if none) */
+ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+ INT32 valoffset[17]; /* huffval[] offset for codes of length k */
+ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
+ * the smallest code of length k; so given a code of length k, the
+ * corresponding symbol is huffval[code + valoffset[k]]
+ */
+
+ /* Link to public Huffman table (needed only in jpeg_huff_decode) */
+ JHUFF_TBL *pub;
+
+ /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
+ * the input data stream. If the next Huffman code is no more
+ * than HUFF_LOOKAHEAD bits long, we can obtain its length and
+ * the corresponding symbol directly from these tables.
+ */
+ int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+ UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
+} d_derived_tbl;
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_d_derived_tbl
+ JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl ** pdtbl));
+
+
+/*
+ * Fetching the next N bits from the input stream is a time-critical operation
+ * for the Huffman decoders. We implement it with a combination of inline
+ * macros and out-of-line subroutines. Note that N (the number of bits
+ * demanded at one time) never exceeds 15 for JPEG use.
+ *
+ * We read source bytes into get_buffer and dole out bits as needed.
+ * If get_buffer already contains enough bits, they are fetched in-line
+ * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
+ * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
+ * as full as possible (not just to the number of bits needed; this
+ * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
+ * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
+ * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
+ * at least the requested number of bits --- dummy zeroes are inserted if
+ * necessary.
+ */
+
+typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
+#define BIT_BUF_SIZE 32 /* size of buffer in bits */
+
+/* If long is > 32 bits on your machine, and shifting/masking longs is
+ * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
+ * appropriately should be a win. Unfortunately we can't define the size
+ * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
+ * because not all machines measure sizeof in 8-bit bytes.
+ */
+
+typedef struct { /* Bitreading state saved across MCUs */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+} bitread_perm_state;
+
+typedef struct { /* Bitreading working state within an MCU */
+ /* Current data source location */
+ /* We need a copy, rather than munging the original, in case of suspension */
+ const JOCTET * next_input_byte; /* => next byte to read from source */
+ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
+ /* Bit input buffer --- note these values are kept in register variables,
+ * not in this struct, inside the inner loops.
+ */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+ /* Pointer needed by jpeg_fill_bit_buffer. */
+ j_decompress_ptr cinfo; /* back link to decompress master record */
+} bitread_working_state;
+
+/* Macros to declare and load/save bitread local variables. */
+#define BITREAD_STATE_VARS \
+ register bit_buf_type get_buffer; \
+ register int bits_left; \
+ bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop,permstate) \
+ br_state.cinfo = cinfop; \
+ br_state.next_input_byte = cinfop->src->next_input_byte; \
+ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+ get_buffer = permstate.get_buffer; \
+ bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop,permstate) \
+ cinfop->src->next_input_byte = br_state.next_input_byte; \
+ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+ permstate.get_buffer = get_buffer; \
+ permstate.bits_left = bits_left
+
+/*
+ * These macros provide the in-line portion of bit fetching.
+ * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
+ * before using GET_BITS, PEEK_BITS, or DROP_BITS.
+ * The variables get_buffer and bits_left are assumed to be locals,
+ * but the state struct might not be (jpeg_huff_decode needs this).
+ * CHECK_BIT_BUFFER(state,n,action);
+ * Ensure there are N bits in get_buffer; if suspend, take action.
+ * val = GET_BITS(n);
+ * Fetch next N bits.
+ * val = PEEK_BITS(n);
+ * Fetch next N bits without removing them from the buffer.
+ * DROP_BITS(n);
+ * Discard next N bits.
+ * The value N should be a simple variable, not an expression, because it
+ * is evaluated multiple times.
+ */
+
+#define CHECK_BIT_BUFFER(state,nbits,action) \
+ { if (bits_left < (nbits)) { \
+ if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
+ { action; } \
+ get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+
+#define GET_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
+
+#define PEEK_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
+
+#define DROP_BITS(nbits) \
+ (bits_left -= (nbits))
+
+/* Load up the bit buffer to a depth of at least nbits */
+EXTERN(boolean) jpeg_fill_bit_buffer
+ JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+ register int bits_left, int nbits));
+
+
+/*
+ * Code for extracting next Huffman-coded symbol from input bit stream.
+ * Again, this is time-critical and we make the main paths be macros.
+ *
+ * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
+ * without looping. Usually, more than 95% of the Huffman codes will be 8
+ * or fewer bits long. The few overlength codes are handled with a loop,
+ * which need not be inline code.
+ *
+ * Notes about the HUFF_DECODE macro:
+ * 1. Near the end of the data segment, we may fail to get enough bits
+ * for a lookahead. In that case, we do it the hard way.
+ * 2. If the lookahead table contains no entry, the next code must be
+ * more than HUFF_LOOKAHEAD bits long.
+ * 3. jpeg_huff_decode returns -1 if forced to suspend.
+ */
+
+#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
+{ register int nb, look; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ nb = 1; goto slowlabel; \
+ } \
+ } \
+ look = PEEK_BITS(HUFF_LOOKAHEAD); \
+ if ((nb = htbl->look_nbits[look]) != 0) { \
+ DROP_BITS(nb); \
+ result = htbl->look_sym[look]; \
+ } else { \
+ nb = HUFF_LOOKAHEAD+1; \
+slowlabel: \
+ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ } \
+}
+
+/* Out-of-line case for Huffman code fetching */
+EXTERN(int) jpeg_huff_decode
+ JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+ register int bits_left, d_derived_tbl * htbl, int min_bits));
diff --git a/SrcShared/jpeg/jdinput.c b/SrcShared/jpeg/jdinput.c
new file mode 100644
index 0000000..0c2ac8f
--- /dev/null
+++ b/SrcShared/jpeg/jdinput.c
@@ -0,0 +1,381 @@
+/*
+ * jdinput.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input control logic for the JPEG decompressor.
+ * These routines are concerned with controlling the decompressor's input
+ * processing (marker reading and coefficient decoding). The actual input
+ * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_input_controller pub; /* public fields */
+
+ boolean inheaders; /* TRUE until first SOS is reached */
+} my_input_controller;
+
+typedef my_input_controller * my_inputctl_ptr;
+
+
+/* Forward declarations */
+METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Routines to calculate various quantities related to the size of the image.
+ */
+
+LOCAL(void)
+initial_setup (j_decompress_ptr cinfo)
+/* Called once, when first SOS marker is reached */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
+ * In the full decompressor, this will be overridden by jdmaster.c;
+ * but in the transcoder, jdmaster.c is not used, so we must do it here.
+ */
+ cinfo->min_DCT_scaled_size = DCTSIZE;
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->DCT_scaled_size = DCTSIZE;
+ /* Size in DCT blocks */
+ compptr->width_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->height_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* downsampled_width and downsampled_height will also be overridden by
+ * jdmaster.c if we are doing full decompression. The transcoder library
+ * doesn't use these values, but the calling application might.
+ */
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) cinfo->max_h_samp_factor);
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) cinfo->max_v_samp_factor);
+ /* Mark component needed, until color conversion says otherwise */
+ compptr->component_needed = TRUE;
+ /* Mark no quantization table yet saved for component */
+ compptr->quant_table = NULL;
+ }
+
+ /* Compute number of fully interleaved MCU rows. */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ /* Decide whether file contains multiple scans */
+ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
+ cinfo->inputctl->has_multiple_scans = TRUE;
+ else
+ cinfo->inputctl->has_multiple_scans = FALSE;
+}
+
+
+LOCAL(void)
+per_scan_setup (j_decompress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_blocks;
+ cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
+
+ /* For noninterleaved scan, always one block per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_blocks = 1;
+ compptr->MCU_sample_width = compptr->DCT_scaled_size;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of block rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->blocks_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width,
+ (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ cinfo->blocks_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of blocks of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
+ /* Figure number of non-dummy blocks in last MCU column & row */
+ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_blocks;
+ if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+ }
+ }
+
+ }
+}
+
+
+/*
+ * Save away a copy of the Q-table referenced by each component present
+ * in the current scan, unless already saved during a prior scan.
+ *
+ * In a multiple-scan JPEG file, the encoder could assign different components
+ * the same Q-table slot number, but change table definitions between scans
+ * so that each component uses a different Q-table. (The IJG encoder is not
+ * currently capable of doing this, but other encoders might.) Since we want
+ * to be able to dequantize all the components at the end of the file, this
+ * means that we have to save away the table actually used for each component.
+ * We do this by copying the table at the start of the first scan containing
+ * the component.
+ * The JPEG spec prohibits the encoder from changing the contents of a Q-table
+ * slot between scans of a component using that slot. If the encoder does so
+ * anyway, this decoder will simply use the Q-table values that were current
+ * at the start of the first scan for the component.
+ *
+ * The decompressor output side looks only at the saved quant tables,
+ * not at the current Q-table slots.
+ */
+
+LOCAL(void)
+latch_quant_tables (j_decompress_ptr cinfo)
+{
+ int ci, qtblno;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* No work if we already saved Q-table for this component */
+ if (compptr->quant_table != NULL)
+ continue;
+ /* Make sure specified quantization table is present */
+ qtblno = compptr->quant_tbl_no;
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ /* OK, save away the quantization table */
+ qtbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(JQUANT_TBL));
+ MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
+ compptr->quant_table = qtbl;
+ }
+}
+
+
+/*
+ * Initialize the input modules to read a scan of compressed data.
+ * The first call to this is done by jdmaster.c after initializing
+ * the entire decompressor (during jpeg_start_decompress).
+ * Subsequent calls come from consume_markers, below.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ per_scan_setup(cinfo);
+ latch_quant_tables(cinfo);
+ (*cinfo->entropy->start_pass) (cinfo);
+ (*cinfo->coef->start_input_pass) (cinfo);
+ cinfo->inputctl->consume_input = cinfo->coef->consume_data;
+}
+
+
+/*
+ * Finish up after inputting a compressed-data scan.
+ * This is called by the coefficient controller after it's read all
+ * the expected data of the scan.
+ */
+
+METHODDEF(void)
+finish_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->inputctl->consume_input = consume_markers;
+}
+
+
+/*
+ * Read JPEG markers before, between, or after compressed-data scans.
+ * Change state as necessary when a new scan is reached.
+ * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ *
+ * The consume_input method pointer points either here or to the
+ * coefficient controller's consume_data routine, depending on whether
+ * we are reading a compressed data segment or inter-segment markers.
+ */
+
+METHODDEF(int)
+consume_markers (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ int val;
+
+ if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
+ return JPEG_REACHED_EOI;
+
+ val = (*cinfo->marker->read_markers) (cinfo);
+
+ switch (val) {
+ case JPEG_REACHED_SOS: /* Found SOS */
+ if (inputctl->inheaders) { /* 1st SOS */
+ initial_setup(cinfo);
+ inputctl->inheaders = FALSE;
+ /* Note: start_input_pass must be called by jdmaster.c
+ * before any more input can be consumed. jdapimin.c is
+ * responsible for enforcing this sequencing.
+ */
+ } else { /* 2nd or later SOS marker */
+ if (! inputctl->pub.has_multiple_scans)
+ ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+ start_input_pass(cinfo);
+ }
+ break;
+ case JPEG_REACHED_EOI: /* Found EOI */
+ inputctl->pub.eoi_reached = TRUE;
+ if (inputctl->inheaders) { /* Tables-only datastream, apparently */
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_NO_SOS);
+ } else {
+ /* Prevent infinite loop in coef ctlr's decompress_data routine
+ * if user set output_scan_number larger than number of scans.
+ */
+ if (cinfo->output_scan_number > cinfo->input_scan_number)
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ }
+ break;
+ case JPEG_SUSPENDED:
+ break;
+ }
+
+ return val;
+}
+
+
+/*
+ * Reset state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+ /* Reset other modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->marker->reset_marker_reader) (cinfo);
+ /* Reset progression state -- would be cleaner if entropy decoder did this */
+ cinfo->coef_bits = NULL;
+}
+
+
+/*
+ * Initialize the input controller module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl;
+
+ /* Create subobject in permanent pool */
+ inputctl = (my_inputctl_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_input_controller));
+ cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+ /* Initialize method pointers */
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.reset_input_controller = reset_input_controller;
+ inputctl->pub.start_input_pass = start_input_pass;
+ inputctl->pub.finish_input_pass = finish_input_pass;
+ /* Initialize state: can't use reset_input_controller since we don't
+ * want to try to reset other modules yet.
+ */
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+}
diff --git a/SrcShared/jpeg/jdmainct.c b/SrcShared/jpeg/jdmainct.c
new file mode 100644
index 0000000..13c956f
--- /dev/null
+++ b/SrcShared/jpeg/jdmainct.c
@@ -0,0 +1,512 @@
+/*
+ * jdmainct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for decompression.
+ * The main buffer lies between the JPEG decompressor proper and the
+ * post-processor; it holds downsampled data in the JPEG colorspace.
+ *
+ * Note that this code is bypassed in raw-data mode, since the application
+ * supplies the equivalent of the main buffer in that case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * In the current system design, the main buffer need never be a full-image
+ * buffer; any full-height buffers will be found inside the coefficient or
+ * postprocessing controllers. Nonetheless, the main controller is not
+ * trivial. Its responsibility is to provide context rows for upsampling/
+ * rescaling, and doing this in an efficient fashion is a bit tricky.
+ *
+ * Postprocessor input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
+ * sample rows of each component. (We require DCT_scaled_size values to be
+ * chosen such that these numbers are integers. In practice DCT_scaled_size
+ * values will likely be powers of two, so we actually have the stronger
+ * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
+ * Upsampling will typically produce max_v_samp_factor pixel rows from each
+ * row group (times any additional scale factor that the upsampler is
+ * applying).
+ *
+ * The coefficient controller will deliver data to us one iMCU row at a time;
+ * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
+ * exactly min_DCT_scaled_size row groups. (This amount of data corresponds
+ * to one row of MCUs when the image is fully interleaved.) Note that the
+ * number of sample rows varies across components, but the number of row
+ * groups does not. Some garbage sample rows may be included in the last iMCU
+ * row at the bottom of the image.
+ *
+ * Depending on the vertical scaling algorithm used, the upsampler may need
+ * access to the sample row(s) above and below its current input row group.
+ * The upsampler is required to set need_context_rows TRUE at global selection
+ * time if so. When need_context_rows is FALSE, this controller can simply
+ * obtain one iMCU row at a time from the coefficient controller and dole it
+ * out as row groups to the postprocessor.
+ *
+ * When need_context_rows is TRUE, this controller guarantees that the buffer
+ * passed to postprocessing contains at least one row group's worth of samples
+ * above and below the row group(s) being processed. Note that the context
+ * rows "above" the first passed row group appear at negative row offsets in
+ * the passed buffer. At the top and bottom of the image, the required
+ * context rows are manufactured by duplicating the first or last real sample
+ * row; this avoids having special cases in the upsampling inner loops.
+ *
+ * The amount of context is fixed at one row group just because that's a
+ * convenient number for this controller to work with. The existing
+ * upsamplers really only need one sample row of context. An upsampler
+ * supporting arbitrary output rescaling might wish for more than one row
+ * group of context when shrinking the image; tough, we don't handle that.
+ * (This is justified by the assumption that downsizing will be handled mostly
+ * by adjusting the DCT_scaled_size values, so that the actual scale factor at
+ * the upsample step needn't be much less than one.)
+ *
+ * To provide the desired context, we have to retain the last two row groups
+ * of one iMCU row while reading in the next iMCU row. (The last row group
+ * can't be processed until we have another row group for its below-context,
+ * and so we have to save the next-to-last group too for its above-context.)
+ * We could do this most simply by copying data around in our buffer, but
+ * that'd be very slow. We can avoid copying any data by creating a rather
+ * strange pointer structure. Here's how it works. We allocate a workspace
+ * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
+ * of row groups per iMCU row). We create two sets of redundant pointers to
+ * the workspace. Labeling the physical row groups 0 to M+1, the synthesized
+ * pointer lists look like this:
+ * M+1 M-1
+ * master pointer --> 0 master pointer --> 0
+ * 1 1
+ * ... ...
+ * M-3 M-3
+ * M-2 M
+ * M-1 M+1
+ * M M-2
+ * M+1 M-1
+ * 0 0
+ * We read alternate iMCU rows using each master pointer; thus the last two
+ * row groups of the previous iMCU row remain un-overwritten in the workspace.
+ * The pointer lists are set up so that the required context rows appear to
+ * be adjacent to the proper places when we pass the pointer lists to the
+ * upsampler.
+ *
+ * The above pictures describe the normal state of the pointer lists.
+ * At top and bottom of the image, we diddle the pointer lists to duplicate
+ * the first or last sample row as necessary (this is cheaper than copying
+ * sample rows around).
+ *
+ * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
+ * situation each iMCU row provides only one row group so the buffering logic
+ * must be different (eg, we must read two iMCU rows before we can emit the
+ * first row group). For now, we simply do not support providing context
+ * rows when min_DCT_scaled_size is 1. That combination seems unlikely to
+ * be worth providing --- if someone wants a 1/8th-size preview, they probably
+ * want it quick and dirty, so a context-free upsampler is sufficient.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_main_controller pub; /* public fields */
+
+ /* Pointer to allocated workspace (M or M+2 row groups). */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+ boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
+ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
+
+ /* Remaining fields are only used in the context case. */
+
+ /* These are the master pointers to the funny-order pointer lists. */
+ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
+
+ int whichptr; /* indicates which pointer set is now in use */
+ int context_state; /* process_data state machine status */
+ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
+ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+/* context_state values: */
+#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
+#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
+#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+METHODDEF(void) process_data_context_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) process_data_crank_post
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#endif
+
+
+LOCAL(void)
+alloc_funny_pointers (j_decompress_ptr cinfo)
+/* Allocate space for the funny pointer lists.
+ * This is done only once, not once per pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, rgroup;
+ int M = cinfo->min_DCT_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ /* Get top-level space for component array pointers.
+ * We alloc both arrays with one call to save a few cycles.
+ */
+ main->xbuffer[0] = (JSAMPIMAGE)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
+ main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size; /* height of a row group of component */
+ /* Get space for pointer lists --- M+4 row groups in each list.
+ * We alloc both pointer lists with one call to save a few cycles.
+ */
+ xbuf = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
+ xbuf += rgroup; /* want one row group at negative offsets */
+ main->xbuffer[0][ci] = xbuf;
+ xbuf += rgroup * (M + 4);
+ main->xbuffer[1][ci] = xbuf;
+ }
+}
+
+
+LOCAL(void)
+make_funny_pointers (j_decompress_ptr cinfo)
+/* Create the funny pointer lists discussed in the comments above.
+ * The actual workspace is already allocated (in main->buffer),
+ * and the space for the pointer lists is allocated too.
+ * This routine just fills in the curiously ordered lists.
+ * This will be repeated at the beginning of each pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_DCT_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY buf, xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ /* First copy the workspace pointers as-is */
+ buf = main->buffer[ci];
+ for (i = 0; i < rgroup * (M + 2); i++) {
+ xbuf0[i] = xbuf1[i] = buf[i];
+ }
+ /* In the second list, put the last four row groups in swapped order */
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
+ xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+ }
+ /* The wraparound pointers at top and bottom will be filled later
+ * (see set_wraparound_pointers, below). Initially we want the "above"
+ * pointers to duplicate the first actual data line. This only needs
+ * to happen in xbuffer[0].
+ */
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[0];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_wraparound_pointers (j_decompress_ptr cinfo)
+/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
+ * This changes the pointer list state from top-of-image to the normal state.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_DCT_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
+ xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
+ xbuf0[rgroup*(M+2) + i] = xbuf0[i];
+ xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_bottom_pointers (j_decompress_ptr cinfo)
+/* Change the pointer lists to duplicate the last sample row at the bottom
+ * of the image. whichptr indicates which xbuffer holds the final iMCU row.
+ * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup, iMCUheight, rows_left;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Count sample rows in one iMCU row and in one row group */
+ iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
+ rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
+ /* Count nondummy sample rows remaining for this component */
+ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+ if (rows_left == 0) rows_left = iMCUheight;
+ /* Count nondummy row groups. Should get same answer for each component,
+ * so we need only do it once.
+ */
+ if (ci == 0) {
+ main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+ }
+ /* Duplicate the last real sample row rgroup*2 times; this pads out the
+ * last partial rowgroup and ensures at least one full rowgroup of context.
+ */
+ xbuf = main->xbuffer[main->whichptr][ci];
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf[rows_left + i] = xbuf[rows_left-1];
+ }
+ }
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->upsample->need_context_rows) {
+ main->pub.process_data = process_data_context_main;
+ make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
+ main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ main->iMCU_row_ctr = 0;
+ } else {
+ /* Simple case with no context needed */
+ main->pub.process_data = process_data_simple_main;
+ }
+ main->buffer_full = FALSE; /* Mark buffer empty */
+ main->rowgroup_ctr = 0;
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_CRANK_DEST:
+ /* For last pass of 2-pass quantization, just crank the postprocessor */
+ main->pub.process_data = process_data_crank_post;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the simple case where no context is required.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ JDIMENSION rowgroups_avail;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ }
+
+ /* There are always min_DCT_scaled_size row groups in an iMCU row. */
+ rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
+ /* Note: at the bottom of the image, we may pass extra garbage row groups
+ * to the postprocessor. The postprocessor has to check for bottom
+ * of image anyway (at row resolution), so no point in us doing it too.
+ */
+
+ /* Feed the postprocessor */
+ (*cinfo->post->post_process_data) (cinfo, main->buffer,
+ &main->rowgroup_ctr, rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+
+ /* Has postprocessor consumed all the data yet? If so, mark buffer empty */
+ if (main->rowgroup_ctr >= rowgroups_avail) {
+ main->buffer_full = FALSE;
+ main->rowgroup_ctr = 0;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the case where context rows must be provided.
+ */
+
+METHODDEF(void)
+process_data_context_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->coef->decompress_data) (cinfo,
+ main->xbuffer[main->whichptr]))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ main->iMCU_row_ctr++; /* count rows received */
+ }
+
+ /* Postprocessor typically will not swallow all the input data it is handed
+ * in one call (due to filling the output buffer first). Must be prepared
+ * to exit and restart. This switch lets us keep track of how far we got.
+ * Note that each case falls through to the next on successful completion.
+ */
+ switch (main->context_state) {
+ case CTX_POSTPONED_ROW:
+ /* Call postprocessor using previously set pointers for postponed row */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ if (*out_row_ctr >= out_rows_avail)
+ return; /* Postprocessor exactly filled output buf */
+ /*FALLTHROUGH*/
+ case CTX_PREPARE_FOR_IMCU:
+ /* Prepare to process first M-1 row groups of this iMCU row */
+ main->rowgroup_ctr = 0;
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
+ /* Check for bottom of image: if so, tweak pointers to "duplicate"
+ * the last sample row, and adjust rowgroups_avail to ignore padding rows.
+ */
+ if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
+ set_bottom_pointers(cinfo);
+ main->context_state = CTX_PROCESS_IMCU;
+ /*FALLTHROUGH*/
+ case CTX_PROCESS_IMCU:
+ /* Call postprocessor using previously set pointers */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ /* After the first iMCU, change wraparound pointers to normal state */
+ if (main->iMCU_row_ctr == 1)
+ set_wraparound_pointers(cinfo);
+ /* Prepare to load new iMCU row using other xbuffer list */
+ main->whichptr ^= 1; /* 0=>1 or 1=>0 */
+ main->buffer_full = FALSE;
+ /* Still need to process last row group of this iMCU row, */
+ /* which is saved at index M+1 of the other xbuffer */
+ main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
+ main->context_state = CTX_POSTPONED_ROW;
+ }
+}
+
+
+/*
+ * Process some data.
+ * Final pass of two-pass quantization: just call the postprocessor.
+ * Source data will be the postprocessor controller's internal buffer.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF(void)
+process_data_crank_post (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
+ (JDIMENSION *) NULL, (JDIMENSION) 0,
+ output_buf, out_row_ctr, out_rows_avail);
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci, rgroup, ngroups;
+ jpeg_component_info *compptr;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_d_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ if (need_full_buffer) /* shouldn't happen */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Allocate the workspace.
+ * ngroups is the number of row groups we need.
+ */
+ if (cinfo->upsample->need_context_rows) {
+ if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
+ ngroups = cinfo->min_DCT_scaled_size + 2;
+ } else {
+ ngroups = cinfo->min_DCT_scaled_size;
+ }
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size; /* height of a row group of component */
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_blocks * compptr->DCT_scaled_size,
+ (JDIMENSION) (rgroup * ngroups));
+ }
+}
diff --git a/SrcShared/jpeg/jdmarker.c b/SrcShared/jpeg/jdmarker.c
new file mode 100644
index 0000000..f4cca8c
--- /dev/null
+++ b/SrcShared/jpeg/jdmarker.c
@@ -0,0 +1,1360 @@
+/*
+ * jdmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to decode JPEG datastream markers.
+ * Most of the complexity arises from our desire to support input
+ * suspension: if not all of the data for a marker is available,
+ * we must exit back to the application. On resumption, we reprocess
+ * the marker.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_reader pub; /* public fields */
+
+ /* Application-overridable marker processing methods */
+ jpeg_marker_parser_method process_COM;
+ jpeg_marker_parser_method process_APPn[16];
+
+ /* Limit on marker data length to save for each marker type */
+ unsigned int length_limit_COM;
+ unsigned int length_limit_APPn[16];
+
+ /* Status of COM/APPn marker saving */
+ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */
+ unsigned int bytes_read; /* data bytes read so far in marker */
+ /* Note: cur_marker is not linked into marker_list until it's all read. */
+} my_marker_reader;
+
+typedef my_marker_reader * my_marker_ptr;
+
+
+/*
+ * Macros for fetching data from the data source module.
+ *
+ * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
+ * the current restart point; we update them only when we have reached a
+ * suitable place to restart if a suspension occurs.
+ */
+
+/* Declare and initialize local copies of input pointer/count */
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr * datasrc = (cinfo)->src; \
+ const JOCTET * next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
+
+/* Unload the local copies --- do this only at a restart boundary */
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
+
+/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
+
+/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
+ * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
+ * but we must reload the local copies after a successful fill.
+ */
+#define MAKE_BYTE_AVAIL(cinfo,action) \
+ if (bytes_in_buffer == 0) { \
+ if (! (*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ }
+
+/* Read a byte into variable V.
+ * If must suspend, take the specified action (typically "return FALSE").
+ */
+#define INPUT_BYTE(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = GETJOCTET(*next_input_byte++); )
+
+/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
+ * V should be declared unsigned int or perhaps INT32.
+ */
+#define INPUT_2BYTES(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
+
+
+/*
+ * Routines to process JPEG markers.
+ *
+ * Entry condition: JPEG marker itself has been read and its code saved
+ * in cinfo->unread_marker; input restart point is just after the marker.
+ *
+ * Exit: if return TRUE, have read and processed any parameters, and have
+ * updated the restart point to point after the parameters.
+ * If return FALSE, was forced to suspend before reaching end of
+ * marker parameters; restart point has not been moved. Same routine
+ * will be called again after application supplies more input data.
+ *
+ * This approach to suspension assumes that all of a marker's parameters
+ * can fit into a single input bufferload. This should hold for "normal"
+ * markers. Some COM/APPn markers might have large parameter segments
+ * that might not fit. If we are simply dropping such a marker, we use
+ * skip_input_data to get past it, and thereby put the problem on the
+ * source manager's shoulders. If we are saving the marker's contents
+ * into memory, we use a slightly different convention: when forced to
+ * suspend, the marker processor updates the restart point to the end of
+ * what it's consumed (ie, the end of the buffer) before returning FALSE.
+ * On resumption, cinfo->unread_marker still contains the marker code,
+ * but the data source will point to the next chunk of marker data.
+ * The marker processor must retain internal state to deal with this.
+ *
+ * Note that we don't bother to avoid duplicate trace messages if a
+ * suspension occurs within marker parameters. Other side effects
+ * require more care.
+ */
+
+
+LOCAL(boolean)
+get_soi (j_decompress_ptr cinfo)
+/* Process an SOI marker */
+{
+ int i;
+
+ TRACEMS(cinfo, 1, JTRC_SOI);
+
+ if (cinfo->marker->saw_SOI)
+ ERREXIT(cinfo, JERR_SOI_DUPLICATE);
+
+ /* Reset all parameters that are defined to be reset by SOI */
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+ cinfo->restart_interval = 0;
+
+ /* Set initial assumptions for colorspace etc */
+
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
+
+ cinfo->saw_JFIF_marker = FALSE;
+ cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0;
+ cinfo->X_density = 1;
+ cinfo->Y_density = 1;
+ cinfo->saw_Adobe_marker = FALSE;
+ cinfo->Adobe_transform = 0;
+
+ cinfo->marker->saw_SOI = TRUE;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
+/* Process a SOFn marker */
+{
+ INT32 length;
+ int c, ci;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ cinfo->progressive_mode = is_prog;
+ cinfo->arith_code = is_arith;
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
+ INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
+
+ length -= 8;
+
+ TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
+ (int) cinfo->image_width, (int) cinfo->image_height,
+ cinfo->num_components);
+
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_DUPLICATE);
+
+ /* We don't support files in which the image height is initially specified */
+ /* as 0 and is later redefined by DNL. As long as we have to check that, */
+ /* might as well have a general sanity check. */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+ || cinfo->num_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ if (length != (cinfo->num_components * 3))
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ if (cinfo->comp_info == NULL) /* do only once, even if suspend */
+ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * SIZEOF(jpeg_component_info));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->component_index = ci;
+ INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ compptr->h_samp_factor = (c >> 4) & 15;
+ compptr->v_samp_factor = (c ) & 15;
+ INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
+
+ TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
+ compptr->component_id, compptr->h_samp_factor,
+ compptr->v_samp_factor, compptr->quant_tbl_no);
+ }
+
+ cinfo->marker->saw_SOF = TRUE;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sos (j_decompress_ptr cinfo)
+/* Process a SOS marker */
+{
+ INT32 length;
+ int i, ci, n, c, cc;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ if (! cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOS_NO_SOF);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
+
+ TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+ if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ cinfo->comps_in_scan = n;
+
+ /* Collect the component-spec parameters */
+
+ for (i = 0; i < n; i++) {
+ INPUT_BYTE(cinfo, cc, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (cc == compptr->component_id)
+ goto id_found;
+ }
+
+ ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+
+ id_found:
+
+ cinfo->cur_comp_info[i] = compptr;
+ compptr->dc_tbl_no = (c >> 4) & 15;
+ compptr->ac_tbl_no = (c ) & 15;
+
+ TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
+ compptr->dc_tbl_no, compptr->ac_tbl_no);
+ }
+
+ /* Collect the additional scan parameters Ss, Se, Ah/Al. */
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ss = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Se = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ah = (c >> 4) & 15;
+ cinfo->Al = (c ) & 15;
+
+ TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
+ cinfo->Ah, cinfo->Al);
+
+ /* Prepare to scan data & restart markers */
+ cinfo->marker->next_restart_num = 0;
+
+ /* Count another SOS marker */
+ cinfo->input_scan_number++;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+#ifdef D_ARITH_CODING_SUPPORTED
+
+LOCAL(boolean)
+get_dac (j_decompress_ptr cinfo)
+/* Process a DAC marker */
+{
+ INT32 length;
+ int index, val;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+ INPUT_BYTE(cinfo, val, return FALSE);
+
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+
+ if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+ ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+
+ if (index >= NUM_ARITH_TBLS) { /* define AC table */
+ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+ } else { /* define DC table */
+ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
+ cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+ if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+ ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+ }
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+#else /* ! D_ARITH_CODING_SUPPORTED */
+
+#define get_dac(cinfo) skip_variable(cinfo)
+
+#endif /* D_ARITH_CODING_SUPPORTED */
+
+
+LOCAL(boolean)
+get_dht (j_decompress_ptr cinfo)
+/* Process a DHT marker */
+{
+ INT32 length;
+ UINT8 bits[17];
+ UINT8 huffval[256];
+ int i, index, count;
+ JHUFF_TBL **htblptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 16) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DHT, index);
+
+ bits[0] = 0;
+ count = 0;
+ for (i = 1; i <= 16; i++) {
+ INPUT_BYTE(cinfo, bits[i], return FALSE);
+ count += bits[i];
+ }
+
+ length -= 1 + 16;
+
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[1], bits[2], bits[3], bits[4],
+ bits[5], bits[6], bits[7], bits[8]);
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[9], bits[10], bits[11], bits[12],
+ bits[13], bits[14], bits[15], bits[16]);
+
+ /* Here we just do minimal validation of the counts to avoid walking
+ * off the end of our table space. jdhuff.c will check more carefully.
+ */
+ if (count > 256 || ((INT32) count) > length)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ for (i = 0; i < count; i++)
+ INPUT_BYTE(cinfo, huffval[i], return FALSE);
+
+ length -= count;
+
+ if (index & 0x10) { /* AC table definition */
+ index -= 0x10;
+ htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+ } else { /* DC table definition */
+ htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (index < 0 || index >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_DHT_INDEX, index);
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+ MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dqt (j_decompress_ptr cinfo)
+/* Process a DQT marker */
+{
+ INT32 length;
+ int n, i, prec;
+ unsigned int tmp;
+ JQUANT_TBL *quant_ptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, n, return FALSE);
+ prec = n >> 4;
+ n &= 0x0F;
+
+ TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
+
+ if (n >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, n);
+
+ if (cinfo->quant_tbl_ptrs[n] == NULL)
+ cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ quant_ptr = cinfo->quant_tbl_ptrs[n];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (prec)
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+ else
+ INPUT_BYTE(cinfo, tmp, return FALSE);
+ /* We convert the zigzag-order table to natural array order. */
+ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+ }
+
+ if (cinfo->err->trace_level >= 2) {
+ for (i = 0; i < DCTSIZE2; i += 8) {
+ TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
+ quant_ptr->quantval[i], quant_ptr->quantval[i+1],
+ quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
+ quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
+ quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+ }
+ }
+
+ length -= DCTSIZE2+1;
+ if (prec) length -= DCTSIZE2;
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dri (j_decompress_ptr cinfo)
+/* Process a DRI marker */
+{
+ INT32 length;
+ unsigned int tmp;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ if (length != 4)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
+
+ cinfo->restart_interval = tmp;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Routines for processing APPn and COM markers.
+ * These are either saved in memory or discarded, per application request.
+ * APP0 and APP14 are specially checked to see if they are
+ * JFIF and Adobe markers, respectively.
+ */
+
+#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */
+#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */
+#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */
+
+
+LOCAL(void)
+examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP0.
+ * Take appropriate action if it is a JFIF marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ INT32 totallen = (INT32) datalen + remaining;
+
+ if (datalen >= APP0_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x49 &&
+ GETJOCTET(data[3]) == 0x46 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF APP0 marker: save info */
+ cinfo->saw_JFIF_marker = TRUE;
+ cinfo->JFIF_major_version = GETJOCTET(data[5]);
+ cinfo->JFIF_minor_version = GETJOCTET(data[6]);
+ cinfo->density_unit = GETJOCTET(data[7]);
+ cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
+ cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
+ /* Check version.
+ * Major version must be 1, anything else signals an incompatible change.
+ * (We used to treat this as an error, but now it's a nonfatal warning,
+ * because some bozo at Hijaak couldn't read the spec.)
+ * Minor version should be 0..2, but process anyway if newer.
+ */
+ if (cinfo->JFIF_major_version != 1)
+ WARNMS2(cinfo, JWRN_JFIF_MAJOR,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
+ /* Generate trace messages */
+ TRACEMS5(cinfo, 1, JTRC_JFIF,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
+ cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
+ /* Validate thumbnail dimensions and issue appropriate messages */
+ if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
+ TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+ GETJOCTET(data[12]), GETJOCTET(data[13]));
+ totallen -= APP0_DATA_LEN;
+ if (totallen !=
+ ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3))
+ TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+ } else if (datalen >= 6 &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x58 &&
+ GETJOCTET(data[3]) == 0x58 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF "JFXX" extension APP0 marker */
+ /* The library doesn't actually do anything with these,
+ * but we try to produce a helpful trace message.
+ */
+ switch (GETJOCTET(data[5])) {
+ case 0x10:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+ break;
+ case 0x11:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+ break;
+ case 0x13:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
+ GETJOCTET(data[5]), (int) totallen);
+ break;
+ }
+ } else {
+ /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+ }
+}
+
+
+LOCAL(void)
+examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP14.
+ * Take appropriate action if it is an Adobe marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ unsigned int version, flags0, flags1, transform;
+
+ if (datalen >= APP14_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x41 &&
+ GETJOCTET(data[1]) == 0x64 &&
+ GETJOCTET(data[2]) == 0x6F &&
+ GETJOCTET(data[3]) == 0x62 &&
+ GETJOCTET(data[4]) == 0x65) {
+ /* Found Adobe APP14 marker */
+ version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
+ flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
+ flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
+ transform = GETJOCTET(data[11]);
+ TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
+ cinfo->saw_Adobe_marker = TRUE;
+ cinfo->Adobe_transform = (UINT8) transform;
+ } else {
+ /* Start of APP14 does not match "Adobe", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+ }
+}
+
+
+METHODDEF(boolean)
+get_interesting_appn (j_decompress_ptr cinfo)
+/* Process an APP0 or APP14 marker without saving it */
+{
+ INT32 length;
+ JOCTET b[APPN_DATA_LEN];
+ unsigned int i, numtoread;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ /* get the interesting part of the marker data */
+ if (length >= APPN_DATA_LEN)
+ numtoread = APPN_DATA_LEN;
+ else if (length > 0)
+ numtoread = (unsigned int) length;
+ else
+ numtoread = 0;
+ for (i = 0; i < numtoread; i++)
+ INPUT_BYTE(cinfo, b[i], return FALSE);
+ length -= numtoread;
+
+ /* process it */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ default:
+ /* can't get here unless jpeg_save_markers chooses wrong processor */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo);
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+METHODDEF(boolean)
+save_marker (j_decompress_ptr cinfo)
+/* Save an APPn or COM marker into the marker list */
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
+ unsigned int bytes_read, data_length;
+ JOCTET FAR * data;
+ INT32 length = 0;
+ INPUT_VARS(cinfo);
+
+ if (cur_marker == NULL) {
+ /* begin reading a marker */
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+ if (length >= 0) { /* watch out for bogus length word */
+ /* figure out how much we want to save */
+ unsigned int limit;
+ if (cinfo->unread_marker == (int) M_COM)
+ limit = marker->length_limit_COM;
+ else
+ limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
+ if ((unsigned int) length < limit)
+ limit = (unsigned int) length;
+ /* allocate and initialize the marker item */
+ cur_marker = (jpeg_saved_marker_ptr)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(struct jpeg_marker_struct) + limit);
+ cur_marker->next = NULL;
+ cur_marker->marker = (UINT8) cinfo->unread_marker;
+ cur_marker->original_length = (unsigned int) length;
+ cur_marker->data_length = limit;
+ /* data area is just beyond the jpeg_marker_struct */
+ data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
+ marker->cur_marker = cur_marker;
+ marker->bytes_read = 0;
+ bytes_read = 0;
+ data_length = limit;
+ } else {
+ /* deal with bogus length word */
+ bytes_read = data_length = 0;
+ data = NULL;
+ }
+ } else {
+ /* resume reading a marker */
+ bytes_read = marker->bytes_read;
+ data_length = cur_marker->data_length;
+ data = cur_marker->data + bytes_read;
+ }
+
+ while (bytes_read < data_length) {
+ INPUT_SYNC(cinfo); /* move the restart point to here */
+ marker->bytes_read = bytes_read;
+ /* If there's not at least one byte in buffer, suspend */
+ MAKE_BYTE_AVAIL(cinfo, return FALSE);
+ /* Copy bytes with reasonable rapidity */
+ while (bytes_read < data_length && bytes_in_buffer > 0) {
+ *data++ = *next_input_byte++;
+ bytes_in_buffer--;
+ bytes_read++;
+ }
+ }
+
+ /* Done reading what we want to read */
+ if (cur_marker != NULL) { /* will be NULL if bogus length word */
+ /* Add new marker to end of list */
+ if (cinfo->marker_list == NULL) {
+ cinfo->marker_list = cur_marker;
+ } else {
+ jpeg_saved_marker_ptr prev = cinfo->marker_list;
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = cur_marker;
+ }
+ /* Reset pointer & calc remaining data length */
+ data = cur_marker->data;
+ length = cur_marker->original_length - data_length;
+ }
+ /* Reset to initial state for next marker */
+ marker->cur_marker = NULL;
+
+ /* Process the marker if interesting; else just make a generic trace msg */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, data, data_length, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, data, data_length, length);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
+ (int) (data_length + length));
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+METHODDEF(boolean)
+skip_variable (j_decompress_ptr cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+ INT32 length;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+/*
+ * Find the next JPEG marker, save it in cinfo->unread_marker.
+ * Returns FALSE if had to suspend before reaching a marker;
+ * in that case cinfo->unread_marker is unchanged.
+ *
+ * Note that the result might not be a valid marker code,
+ * but it will never be 0 or FF.
+ */
+
+LOCAL(boolean)
+next_marker (j_decompress_ptr cinfo)
+{
+ int c;
+ INPUT_VARS(cinfo);
+
+ for (;;) {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ /* Skip any non-FF bytes.
+ * This may look a bit inefficient, but it will not occur in a valid file.
+ * We sync after each discarded byte so that a suspending data source
+ * can discard the byte from its buffer.
+ */
+ while (c != 0xFF) {
+ cinfo->marker->discarded_bytes++;
+ INPUT_SYNC(cinfo);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ }
+ /* This loop swallows any duplicate FF bytes. Extra FFs are legal as
+ * pad bytes, so don't count them in discarded_bytes. We assume there
+ * will not be so many consecutive FF bytes as to overflow a suspending
+ * data source's input buffer.
+ */
+ do {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ } while (c == 0xFF);
+ if (c != 0)
+ break; /* found a valid marker, exit loop */
+ /* Reach here if we found a stuffed-zero data sequence (FF/00).
+ * Discard it and loop back to try again.
+ */
+ cinfo->marker->discarded_bytes += 2;
+ INPUT_SYNC(cinfo);
+ }
+
+ if (cinfo->marker->discarded_bytes != 0) {
+ WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
+ cinfo->marker->discarded_bytes = 0;
+ }
+
+ cinfo->unread_marker = c;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+first_marker (j_decompress_ptr cinfo)
+/* Like next_marker, but used to obtain the initial SOI marker. */
+/* For this marker, we do not allow preceding garbage or fill; otherwise,
+ * we might well scan an entire input file before realizing it ain't JPEG.
+ * If an application wants to process non-JFIF files, it must seek to the
+ * SOI before calling the JPEG library.
+ */
+{
+ int c, c2;
+ INPUT_VARS(cinfo);
+
+ INPUT_BYTE(cinfo, c, return FALSE);
+ INPUT_BYTE(cinfo, c2, return FALSE);
+ if (c != 0xFF || c2 != (int) M_SOI)
+ ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+ cinfo->unread_marker = c2;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Read markers until SOS or EOI.
+ *
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+
+METHODDEF(int)
+read_markers (j_decompress_ptr cinfo)
+{
+ /* Outer loop repeats once for each marker. */
+ for (;;) {
+ /* Collect the marker proper, unless we already did. */
+ /* NB: first_marker() enforces the requirement that SOI appear first. */
+ if (cinfo->unread_marker == 0) {
+ if (! cinfo->marker->saw_SOI) {
+ if (! first_marker(cinfo))
+ return JPEG_SUSPENDED;
+ } else {
+ if (! next_marker(cinfo))
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* At this point cinfo->unread_marker contains the marker code and the
+ * input point is just past the marker proper, but before any parameters.
+ * A suspension will cause us to return with this state still true.
+ */
+ switch (cinfo->unread_marker) {
+ case M_SOI:
+ if (! get_soi(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF0: /* Baseline */
+ case M_SOF1: /* Extended sequential, Huffman */
+ if (! get_sof(cinfo, FALSE, FALSE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF2: /* Progressive, Huffman */
+ if (! get_sof(cinfo, TRUE, FALSE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF9: /* Extended sequential, arithmetic */
+ if (! get_sof(cinfo, FALSE, TRUE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF10: /* Progressive, arithmetic */
+ if (! get_sof(cinfo, TRUE, TRUE))
+ return JPEG_SUSPENDED;
+ break;
+
+ /* Currently unsupported SOFn types */
+ case M_SOF3: /* Lossless, Huffman */
+ case M_SOF5: /* Differential sequential, Huffman */
+ case M_SOF6: /* Differential progressive, Huffman */
+ case M_SOF7: /* Differential lossless, Huffman */
+ case M_JPG: /* Reserved for JPEG extensions */
+ case M_SOF11: /* Lossless, arithmetic */
+ case M_SOF13: /* Differential sequential, arithmetic */
+ case M_SOF14: /* Differential progressive, arithmetic */
+ case M_SOF15: /* Differential lossless, arithmetic */
+ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
+ break;
+
+ case M_SOS:
+ if (! get_sos(cinfo))
+ return JPEG_SUSPENDED;
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_SOS;
+
+ case M_EOI:
+ TRACEMS(cinfo, 1, JTRC_EOI);
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_EOI;
+
+ case M_DAC:
+ if (! get_dac(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DHT:
+ if (! get_dht(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DQT:
+ if (! get_dqt(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DRI:
+ if (! get_dri(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_APP0:
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP14:
+ case M_APP15:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
+ cinfo->unread_marker - (int) M_APP0]) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_COM:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_RST0: /* these are all parameterless */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
+ break;
+
+ case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
+ if (! skip_variable(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ default: /* must be DHP, EXP, JPGn, or RESn */
+ /* For now, we treat the reserved markers as fatal errors since they are
+ * likely to be used to signal incompatible JPEG Part 3 extensions.
+ * Once the JPEG 3 version-number marker is well defined, this code
+ * ought to change!
+ */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+ /* Successfully processed marker, so reset state variable */
+ cinfo->unread_marker = 0;
+ } /* end loop */
+}
+
+
+/*
+ * Read a restart marker, which is expected to appear next in the datastream;
+ * if the marker is not there, take appropriate recovery action.
+ * Returns FALSE if suspension is required.
+ *
+ * This is called by the entropy decoder after it has read an appropriate
+ * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder
+ * has already read a marker from the data source. Under normal conditions
+ * cinfo->unread_marker will be reset to 0 before returning; if not reset,
+ * it holds a marker which the decoder will be unable to read past.
+ */
+
+METHODDEF(boolean)
+read_restart_marker (j_decompress_ptr cinfo)
+{
+ /* Obtain a marker unless we already did. */
+ /* Note that next_marker will complain if it skips any data. */
+ if (cinfo->unread_marker == 0) {
+ if (! next_marker(cinfo))
+ return FALSE;
+ }
+
+ if (cinfo->unread_marker ==
+ ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+ /* Normal case --- swallow the marker and let entropy decoder continue */
+ TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
+ cinfo->unread_marker = 0;
+ } else {
+ /* Uh-oh, the restart markers have been messed up. */
+ /* Let the data source manager determine how to resync. */
+ if (! (*cinfo->src->resync_to_restart) (cinfo,
+ cinfo->marker->next_restart_num))
+ return FALSE;
+ }
+
+ /* Update next-restart state */
+ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
+
+ return TRUE;
+}
+
+
+/*
+ * This is the default resync_to_restart method for data source managers
+ * to use if they don't have any better approach. Some data source managers
+ * may be able to back up, or may have additional knowledge about the data
+ * which permits a more intelligent recovery strategy; such managers would
+ * presumably supply their own resync method.
+ *
+ * read_restart_marker calls resync_to_restart if it finds a marker other than
+ * the restart marker it was expecting. (This code is *not* used unless
+ * a nonzero restart interval has been declared.) cinfo->unread_marker is
+ * the marker code actually found (might be anything, except 0 or FF).
+ * The desired restart marker number (0..7) is passed as a parameter.
+ * This routine is supposed to apply whatever error recovery strategy seems
+ * appropriate in order to position the input stream to the next data segment.
+ * Note that cinfo->unread_marker is treated as a marker appearing before
+ * the current data-source input point; usually it should be reset to zero
+ * before returning.
+ * Returns FALSE if suspension is required.
+ *
+ * This implementation is substantially constrained by wanting to treat the
+ * input as a data stream; this means we can't back up. Therefore, we have
+ * only the following actions to work with:
+ * 1. Simply discard the marker and let the entropy decoder resume at next
+ * byte of file.
+ * 2. Read forward until we find another marker, discarding intervening
+ * data. (In theory we could look ahead within the current bufferload,
+ * without having to discard data if we don't find the desired marker.
+ * This idea is not implemented here, in part because it makes behavior
+ * dependent on buffer size and chance buffer-boundary positions.)
+ * 3. Leave the marker unread (by failing to zero cinfo->unread_marker).
+ * This will cause the entropy decoder to process an empty data segment,
+ * inserting dummy zeroes, and then we will reprocess the marker.
+ *
+ * #2 is appropriate if we think the desired marker lies ahead, while #3 is
+ * appropriate if the found marker is a future restart marker (indicating
+ * that we have missed the desired restart marker, probably because it got
+ * corrupted).
+ * We apply #2 or #3 if the found marker is a restart marker no more than
+ * two counts behind or ahead of the expected one. We also apply #2 if the
+ * found marker is not a legal JPEG marker code (it's certainly bogus data).
+ * If the found marker is a restart marker more than 2 counts away, we do #1
+ * (too much risk that the marker is erroneous; with luck we will be able to
+ * resync at some future point).
+ * For any valid non-restart JPEG marker, we apply #3. This keeps us from
+ * overrunning the end of a scan. An implementation limited to single-scan
+ * files might find it better to apply #2 for markers other than EOI, since
+ * any other marker would have to be bogus data in that case.
+ */
+
+GLOBAL(boolean)
+jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+{
+ int marker = cinfo->unread_marker;
+ int action = 1;
+
+ /* Always put up a warning. */
+ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
+
+ /* Outer loop handles repeated decision after scanning forward. */
+ for (;;) {
+ if (marker < (int) M_SOF0)
+ action = 2; /* invalid marker */
+ else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+ action = 3; /* valid non-restart marker */
+ else {
+ if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired+2) & 7)))
+ action = 3; /* one of the next two expected restarts */
+ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired-2) & 7)))
+ action = 2; /* a prior restart, so advance */
+ else
+ action = 1; /* desired restart or too far away */
+ }
+ TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
+ switch (action) {
+ case 1:
+ /* Discard marker and let entropy decoder resume processing. */
+ cinfo->unread_marker = 0;
+ return TRUE;
+ case 2:
+ /* Scan to the next marker, and repeat the decision loop. */
+ if (! next_marker(cinfo))
+ return FALSE;
+ marker = cinfo->unread_marker;
+ break;
+ case 3:
+ /* Return without advancing past this marker. */
+ /* Entropy decoder will be forced to process an empty segment. */
+ return TRUE;
+ }
+ } /* end loop */
+}
+
+
+/*
+ * Reset marker processing state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ cinfo->comp_info = NULL; /* until allocated by get_sof */
+ cinfo->input_scan_number = 0; /* no SOS seen yet */
+ cinfo->unread_marker = 0; /* no pending marker */
+ marker->pub.saw_SOI = FALSE; /* set internal state too */
+ marker->pub.saw_SOF = FALSE;
+ marker->pub.discarded_bytes = 0;
+ marker->cur_marker = NULL;
+}
+
+
+/*
+ * Initialize the marker reader module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker;
+ int i;
+
+ /* Create subobject in permanent pool */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_marker_reader));
+ cinfo->marker = (struct jpeg_marker_reader *) marker;
+ /* Initialize public method pointers */
+ marker->pub.reset_marker_reader = reset_marker_reader;
+ marker->pub.read_markers = read_markers;
+ marker->pub.read_restart_marker = read_restart_marker;
+ /* Initialize COM/APPn processing.
+ * By default, we examine and then discard APP0 and APP14,
+ * but simply discard COM and all other APPn.
+ */
+ marker->process_COM = skip_variable;
+ marker->length_limit_COM = 0;
+ for (i = 0; i < 16; i++) {
+ marker->process_APPn[i] = skip_variable;
+ marker->length_limit_APPn[i] = 0;
+ }
+ marker->process_APPn[0] = get_interesting_appn;
+ marker->process_APPn[14] = get_interesting_appn;
+ /* Reset marker processing state */
+ reset_marker_reader(cinfo);
+}
+
+
+/*
+ * Control saving of COM and APPn markers into marker_list.
+ */
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+GLOBAL(void)
+jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ long maxlength;
+ jpeg_marker_parser_method processor;
+
+ /* Length limit mustn't be larger than what we can allocate
+ * (should only be a concern in a 16-bit environment).
+ */
+ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
+ if (((long) length_limit) > maxlength)
+ length_limit = (unsigned int) maxlength;
+
+ /* Choose processor routine to use.
+ * APP0/APP14 have special requirements.
+ */
+ if (length_limit) {
+ processor = save_marker;
+ /* If saving APP0/APP14, save at least enough for our internal use. */
+ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+ length_limit = APP0_DATA_LEN;
+ else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+ length_limit = APP14_DATA_LEN;
+ } else {
+ processor = skip_variable;
+ /* If discarding APP0/APP14, use our regular on-the-fly processor. */
+ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+ processor = get_interesting_appn;
+ }
+
+ if (marker_code == (int) M_COM) {
+ marker->process_COM = processor;
+ marker->length_limit_COM = length_limit;
+ } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
+ marker->process_APPn[marker_code - (int) M_APP0] = processor;
+ marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+ } else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+/*
+ * Install a special processing method for COM or APPn markers.
+ */
+
+GLOBAL(void)
+jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ if (marker_code == (int) M_COM)
+ marker->process_COM = routine;
+ else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
+ marker->process_APPn[marker_code - (int) M_APP0] = routine;
+ else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
diff --git a/SrcShared/jpeg/jdmaster.c b/SrcShared/jpeg/jdmaster.c
new file mode 100644
index 0000000..2802c5b
--- /dev/null
+++ b/SrcShared/jpeg/jdmaster.c
@@ -0,0 +1,557 @@
+/*
+ * jdmaster.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG decompressor.
+ * These routines are concerned with selecting the modules to be executed
+ * and with determining the number of passes and the work to be done in each
+ * pass.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_decomp_master pub; /* public fields */
+
+ int pass_number; /* # of passes completed */
+
+ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
+
+ /* Saved references to initialized quantizer modules,
+ * in case we need to switch modes.
+ */
+ struct jpeg_color_quantizer * quantizer_1pass;
+ struct jpeg_color_quantizer * quantizer_2pass;
+} my_decomp_master;
+
+typedef my_decomp_master * my_master_ptr;
+
+
+/*
+ * Determine whether merged upsample/color conversion should be used.
+ * CRUCIAL: this must match the actual capabilities of jdmerge.c!
+ */
+
+LOCAL(boolean)
+use_merged_upsample (j_decompress_ptr cinfo)
+{
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ /* Merging is the equivalent of plain box-filter upsampling */
+ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
+ return FALSE;
+ /* jdmerge.c only supports YCC=>RGB color conversion */
+ if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
+ cinfo->out_color_space != JCS_RGB ||
+ cinfo->out_color_components != RGB_PIXELSIZE)
+ return FALSE;
+ /* and it only handles 2h1v or 2h2v sampling ratios */
+ if (cinfo->comp_info[0].h_samp_factor != 2 ||
+ cinfo->comp_info[1].h_samp_factor != 1 ||
+ cinfo->comp_info[2].h_samp_factor != 1 ||
+ cinfo->comp_info[0].v_samp_factor > 2 ||
+ cinfo->comp_info[1].v_samp_factor != 1 ||
+ cinfo->comp_info[2].v_samp_factor != 1)
+ return FALSE;
+ /* furthermore, it doesn't work if we've scaled the IDCTs differently */
+ if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
+ cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
+ cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
+ return FALSE;
+ /* ??? also need to test for upsample-time rescaling, when & if supported */
+ return TRUE; /* by golly, it'll work... */
+#else
+ return FALSE;
+#endif
+}
+
+
+/*
+ * Compute output image dimensions and related values.
+ * NOTE: this is exported for possible use by application.
+ * Hence it mustn't do anything that can't be done twice.
+ * Also note that it may be called before the master module is initialized!
+ */
+
+GLOBAL(void)
+jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+#ifdef IDCT_SCALING_SUPPORTED
+ int ci;
+ jpeg_component_info *compptr;
+#endif
+
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_READY)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+ /* Compute actual output image dimensions and DCT scaling choices. */
+ if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
+ /* Provide 1/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 8L);
+ cinfo->min_DCT_scaled_size = 1;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
+ /* Provide 1/4 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 4L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 4L);
+ cinfo->min_DCT_scaled_size = 2;
+ } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
+ /* Provide 1/2 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 2L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 2L);
+ cinfo->min_DCT_scaled_size = 4;
+ } else {
+ /* Provide 1/1 scaling */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ cinfo->min_DCT_scaled_size = DCTSIZE;
+ }
+ /* In selecting the actual DCT scaling for each component, we try to
+ * scale up the chroma components via IDCT scaling rather than upsampling.
+ * This saves time if the upsampler gets to use 1:1 scaling.
+ * Note this code assumes that the supported DCT scalings are powers of 2.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ int ssize = cinfo->min_DCT_scaled_size;
+ while (ssize < DCTSIZE &&
+ (compptr->h_samp_factor * ssize * 2 <=
+ cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
+ (compptr->v_samp_factor * ssize * 2 <=
+ cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
+ ssize = ssize * 2;
+ }
+ compptr->DCT_scaled_size = ssize;
+ }
+
+ /* Recompute downsampled dimensions of components;
+ * application needs to know these if using raw downsampled data.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Size in samples, after IDCT scaling */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width *
+ (long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height *
+ (long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ }
+
+#else /* !IDCT_SCALING_SUPPORTED */
+
+ /* Hardwire it to "no scaling" */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
+ * and has computed unscaled downsampled_width and downsampled_height.
+ */
+
+#endif /* IDCT_SCALING_SUPPORTED */
+
+ /* Report number of components in selected colorspace. */
+ /* Probably this should be in the color conversion module... */
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ break;
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ break;
+#endif /* else share code with YCbCr */
+ case JCS_YCbCr:
+ cinfo->out_color_components = 3;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+ cinfo->out_color_components = 4;
+ break;
+ default: /* else must be same colorspace as in file */
+ cinfo->out_color_components = cinfo->num_components;
+ break;
+ }
+ cinfo->output_components = (cinfo->quantize_colors ? 1 :
+ cinfo->out_color_components);
+
+ /* See if upsampler will want to emit more than one row at a time */
+ if (use_merged_upsample(cinfo))
+ cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
+ else
+ cinfo->rec_outbuf_height = 1;
+}
+
+
+/*
+ * Several decompression processes need to range-limit values to the range
+ * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
+ * due to noise introduced by quantization, roundoff error, etc. These
+ * processes are inner loops and need to be as fast as possible. On most
+ * machines, particularly CPUs with pipelines or instruction prefetch,
+ * a (subscript-check-less) C table lookup
+ * x = sample_range_limit[x];
+ * is faster than explicit tests
+ * if (x < 0) x = 0;
+ * else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
+ * These processes all use a common table prepared by the routine below.
+ *
+ * For most steps we can mathematically guarantee that the initial value
+ * of x is within MAXJSAMPLE+1 of the legal range, so a table running from
+ * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
+ * limiting step (just after the IDCT), a wildly out-of-range value is
+ * possible if the input data is corrupt. To avoid any chance of indexing
+ * off the end of memory and getting a bad-pointer trap, we perform the
+ * post-IDCT limiting thus:
+ * x = range_limit[x & MASK];
+ * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
+ * samples. Under normal circumstances this is more than enough range and
+ * a correct output will be generated; with bogus input data the mask will
+ * cause wraparound, and we will safely generate a bogus-but-in-range output.
+ * For the post-IDCT step, we want to convert the data from signed to unsigned
+ * representation by adding CENTERJSAMPLE at the same time that we limit it.
+ * So the post-IDCT limiting table ends up looking like this:
+ * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
+ * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0,1,...,CENTERJSAMPLE-1
+ * Negative inputs select values from the upper half of the table after
+ * masking.
+ *
+ * We can save some space by overlapping the start of the post-IDCT table
+ * with the simpler range limiting table. The post-IDCT table begins at
+ * sample_range_limit + CENTERJSAMPLE.
+ *
+ * Note that the table is allocated in near data space on PCs; it's small
+ * enough and used often enough to justify this.
+ */
+
+LOCAL(void)
+prepare_range_limit_table (j_decompress_ptr cinfo)
+/* Allocate and fill in the sample_range_limit table */
+{
+ JSAMPLE * table;
+ int i;
+
+ table = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
+ cinfo->sample_range_limit = table;
+ /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+ /* Main part of "simple" table: limit[x] = x */
+ for (i = 0; i <= MAXJSAMPLE; i++)
+ table[i] = (JSAMPLE) i;
+ table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
+ /* End of simple table, rest of first half of post-IDCT table */
+ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+ table[i] = MAXJSAMPLE;
+ /* Second half of post-IDCT table */
+ MEMZERO(table + (2 * (MAXJSAMPLE+1)),
+ (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+ cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
+}
+
+
+/*
+ * Master selection of decompression modules.
+ * This is done once at jpeg_start_decompress time. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ * We also initialize the decompressor input side to begin consuming data.
+ *
+ * Since jpeg_read_header has finished, we know what is in the SOF
+ * and (first) SOS markers. We also have all the application parameter
+ * settings.
+ */
+
+LOCAL(void)
+master_selection (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ boolean use_c_buffer;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ /* Initialize dimensions and other stuff */
+ jpeg_calc_output_dimensions(cinfo);
+ prepare_range_limit_table(cinfo);
+
+ /* Width of an output scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* Initialize my private state */
+ master->pass_number = 0;
+ master->using_merged_upsample = use_merged_upsample(cinfo);
+
+ /* Color quantizer selection */
+ master->quantizer_1pass = NULL;
+ master->quantizer_2pass = NULL;
+ /* No mode changes if not using buffered-image mode. */
+ if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ }
+ if (cinfo->quantize_colors) {
+ if (cinfo->raw_data_out)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ /* 2-pass quantizer only works in 3-component color space. */
+ if (cinfo->out_color_components != 3) {
+ cinfo->enable_1pass_quant = TRUE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ cinfo->colormap = NULL;
+ } else if (cinfo->colormap != NULL) {
+ cinfo->enable_external_quant = TRUE;
+ } else if (cinfo->two_pass_quantize) {
+ cinfo->enable_2pass_quant = TRUE;
+ } else {
+ cinfo->enable_1pass_quant = TRUE;
+ }
+
+ if (cinfo->enable_1pass_quant) {
+#ifdef QUANT_1PASS_SUPPORTED
+ jinit_1pass_quantizer(cinfo);
+ master->quantizer_1pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+
+ /* We use the 2-pass code to map to external colormaps. */
+ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
+#ifdef QUANT_2PASS_SUPPORTED
+ jinit_2pass_quantizer(cinfo);
+ master->quantizer_2pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+ /* If both quantizers are initialized, the 2-pass one is left active;
+ * this is necessary for starting with quantization to an external map.
+ */
+ }
+
+ /* Post-processing: in particular, color conversion first */
+ if (! cinfo->raw_data_out) {
+ if (master->using_merged_upsample) {
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ jinit_merged_upsampler(cinfo); /* does color conversion too */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ jinit_color_deconverter(cinfo);
+ jinit_upsampler(cinfo);
+ }
+ jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
+ }
+ /* Inverse DCT */
+ jinit_inverse_dct(cinfo);
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->progressive_mode) {
+#ifdef D_PROGRESSIVE_SUPPORTED
+ jinit_phuff_decoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_huff_decoder(cinfo);
+ }
+
+ /* Initialize principal buffer controllers. */
+ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+ jinit_d_coef_controller(cinfo, use_c_buffer);
+
+ if (! cinfo->raw_data_out)
+ jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* If jpeg_start_decompress will read the whole file, initialize
+ * progress monitoring appropriately. The input step is counted
+ * as one pass.
+ */
+ if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+ cinfo->inputctl->has_multiple_scans) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->progressive_mode) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
+ /* Count the input pass as done */
+ master->pass_number++;
+ }
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each output pass. We determine which
+ * modules will be active during this pass and give them appropriate
+ * start_pass calls. We also set is_dummy_pass to indicate whether this
+ * is a "real" output pass or a dummy pass for color quantization.
+ * (In the latter case, jdapistd.c will crank the pass to completion.)
+ */
+
+METHODDEF(void)
+prepare_for_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (master->pub.is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Final pass of 2-pass quantization */
+ master->pub.is_dummy_pass = FALSE;
+ (*cinfo->cquantize->start_pass) (cinfo, FALSE);
+ (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
+ (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ if (cinfo->quantize_colors && cinfo->colormap == NULL) {
+ /* Select new quantization method */
+ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
+ cinfo->cquantize = master->quantizer_2pass;
+ master->pub.is_dummy_pass = TRUE;
+ } else if (cinfo->enable_1pass_quant) {
+ cinfo->cquantize = master->quantizer_1pass;
+ } else {
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+ }
+ }
+ (*cinfo->idct->start_pass) (cinfo);
+ (*cinfo->coef->start_output_pass) (cinfo);
+ if (! cinfo->raw_data_out) {
+ if (! master->using_merged_upsample)
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->upsample->start_pass) (cinfo);
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
+ (*cinfo->post->start_pass) (cinfo,
+ (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ }
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->pass_number +
+ (master->pub.is_dummy_pass ? 2 : 1);
+ /* In buffered-image mode, we assume one more output pass if EOI not
+ * yet reached, but no more passes if EOI has been reached.
+ */
+ if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+ cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
+ }
+ }
+}
+
+
+/*
+ * Finish up at end of an output pass.
+ */
+
+METHODDEF(void)
+finish_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->finish_pass) (cinfo);
+ master->pass_number++;
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+GLOBAL(void)
+jpeg_new_colormap (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_BUFIMAGE)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (cinfo->quantize_colors && cinfo->enable_external_quant &&
+ cinfo->colormap != NULL) {
+ /* Select 2-pass quantizer for external colormap use */
+ cinfo->cquantize = master->quantizer_2pass;
+ /* Notify quantizer of colormap change */
+ (*cinfo->cquantize->new_color_map) (cinfo);
+ master->pub.is_dummy_pass = FALSE; /* just in case */
+ } else
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize master decompression control and select active modules.
+ * This is performed at the start of jpeg_start_decompress.
+ */
+
+GLOBAL(void)
+jinit_master_decompress (j_decompress_ptr cinfo)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_decomp_master));
+ cinfo->master = (struct jpeg_decomp_master *) master;
+ master->pub.prepare_for_output_pass = prepare_for_output_pass;
+ master->pub.finish_output_pass = finish_output_pass;
+
+ master->pub.is_dummy_pass = FALSE;
+
+ master_selection(cinfo);
+}
diff --git a/SrcShared/jpeg/jdmerge.c b/SrcShared/jpeg/jdmerge.c
new file mode 100644
index 0000000..3744446
--- /dev/null
+++ b/SrcShared/jpeg/jdmerge.c
@@ -0,0 +1,400 @@
+/*
+ * jdmerge.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains code for merged upsampling/color conversion.
+ *
+ * This file combines functions from jdsample.c and jdcolor.c;
+ * read those files first to understand what's going on.
+ *
+ * When the chroma components are to be upsampled by simple replication
+ * (ie, box filtering), we can save some work in color conversion by
+ * calculating all the output pixels corresponding to a pair of chroma
+ * samples at one time. In the conversion equations
+ * R = Y + K1 * Cr
+ * G = Y + K2 * Cb + K3 * Cr
+ * B = Y + K4 * Cb
+ * only the Y term varies among the group of pixels corresponding to a pair
+ * of chroma samples, so the rest of the terms can be calculated just once.
+ * At typical sampling ratios, this eliminates half or three-quarters of the
+ * multiplications needed for color conversion.
+ *
+ * This file currently provides implementations for the following cases:
+ * YCbCr => RGB color conversion only.
+ * Sampling ratios of 2h1v or 2h2v.
+ * No scaling needed at upsample time.
+ * Corner-aligned (non-CCIR601) sampling alignment.
+ * Other special cases could be added, but in most applications these are
+ * the only common cases. (For uncommon cases we fall back on the more
+ * general code in jdsample.c and jdcolor.c.)
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Pointer to routine to do actual upsampling/conversion of one row group */
+ JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf));
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+
+ /* For 2:1 vertical sampling, we produce two output rows at a time.
+ * We need a "spare" row buffer to hold the second output row if the
+ * application provides just a one-row buffer; we also use the spare
+ * to discard the dummy last row if the image height is odd.
+ */
+ JSAMPROW spare_row;
+ boolean spare_full; /* T if spare buffer is occupied */
+
+ JDIMENSION out_row_width; /* samples per output row */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ * This is taken directly from jdcolor.c; see that file for more info.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ upsample->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ upsample->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ upsample->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ upsample->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_merged_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the spare buffer empty */
+ upsample->spare_full = FALSE;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * The control routine just handles the row buffering considerations.
+ */
+
+METHODDEF(void)
+merged_2v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 2:1 vertical sampling case: may need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPROW work_ptrs[2];
+ JDIMENSION num_rows; /* number of rows returned to caller */
+
+ if (upsample->spare_full) {
+ /* If we have a spare row saved from a previous cycle, just return it. */
+ jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
+ 1, upsample->out_row_width);
+ num_rows = 1;
+ upsample->spare_full = FALSE;
+ } else {
+ /* Figure number of rows to return to caller. */
+ num_rows = 2;
+ /* Not more than the distance to the end of the image. */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+ /* Create output pointer array for upsampler. */
+ work_ptrs[0] = output_buf[*out_row_ctr];
+ if (num_rows > 1) {
+ work_ptrs[1] = output_buf[*out_row_ctr + 1];
+ } else {
+ work_ptrs[1] = upsample->spare_row;
+ upsample->spare_full = TRUE;
+ }
+ /* Now do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
+ }
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (! upsample->spare_full)
+ (*in_row_group_ctr)++;
+}
+
+
+METHODDEF(void)
+merged_1v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 1:1 vertical sampling case: much easier, never need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Just do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
+ output_buf + *out_row_ctr);
+ /* Adjust counts */
+ (*out_row_ctr)++;
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by the control routines to do
+ * the actual upsampling/conversion. One row group is processed per call.
+ *
+ * Note: since we may be writing directly into application-supplied buffers,
+ * we have to be honest about the output width; we can't assume the buffer
+ * has been rounded up to an even width.
+ */
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
+ */
+
+METHODDEF(void)
+h2v1_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr;
+ JSAMPROW inptr0, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr0 = input_buf[0][in_row_group_ctr];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr = output_buf[0];
+ /* Loop for each pair of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 2 Y values and emit 2 pixels */
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr0);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
+ */
+
+METHODDEF(void)
+h2v2_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr0, outptr1;
+ JSAMPROW inptr00, inptr01, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr00 = input_buf[0][in_row_group_ctr*2];
+ inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr0 = output_buf[0];
+ outptr1 = output_buf[1];
+ /* Loop for each group of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 4 Y values and emit 4 pixels */
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr00);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ y = GETJSAMPLE(*inptr01);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Module initialization routine for merged upsampling/color conversion.
+ *
+ * NB: this is called under the conditions determined by use_merged_upsample()
+ * in jdmaster.c. That routine MUST correspond to the actual capabilities
+ * of this module; no safety checks are made here.
+ */
+
+GLOBAL(void)
+jinit_merged_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_merged_upsample;
+ upsample->pub.need_context_rows = FALSE;
+
+ upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
+
+ if (cinfo->max_v_samp_factor == 2) {
+ upsample->pub.upsample = merged_2v_upsample;
+ upsample->upmethod = h2v2_merged_upsample;
+ /* Allocate a spare row buffer */
+ upsample->spare_row = (JSAMPROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
+ } else {
+ upsample->pub.upsample = merged_1v_upsample;
+ upsample->upmethod = h2v1_merged_upsample;
+ /* No spare row needed */
+ upsample->spare_row = NULL;
+ }
+
+ build_ycc_rgb_table(cinfo);
+}
+
+#endif /* UPSAMPLE_MERGING_SUPPORTED */
diff --git a/SrcShared/jpeg/jdphuff.c b/SrcShared/jpeg/jdphuff.c
new file mode 100644
index 0000000..2267809
--- /dev/null
+++ b/SrcShared/jpeg/jdphuff.c
@@ -0,0 +1,668 @@
+/*
+ * jdphuff.c
+ *
+ * Copyright (C) 1995-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for progressive JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdhuff.h" /* Declarations shared with jdhuff.c */
+
+
+#ifdef D_PROGRESSIVE_SUPPORTED
+
+/*
+ * Expanded entropy decoder object for progressive Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ unsigned int EOBRUN; /* remaining EOBs in EOBRUN */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).EOBRUN = (src).EOBRUN, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ struct jpeg_entropy_decoder pub; /* public fields */
+
+ /* These fields are loaded into local variables at start of each MCU.
+ * In case of suspension, we exit WITHOUT updating them.
+ */
+ bitread_perm_state bitstate; /* Bit buffer at start of MCU */
+ savable_state saved; /* Other state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
+} phuff_entropy_decoder;
+
+typedef phuff_entropy_decoder * phuff_entropy_ptr;
+
+/* Forward declarations */
+METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_phuff_decoder (j_decompress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ boolean is_DC_band, bad;
+ int ci, coefi, tbl;
+ int *coef_bit_ptr;
+ jpeg_component_info * compptr;
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* Validate scan parameters */
+ bad = FALSE;
+ if (is_DC_band) {
+ if (cinfo->Se != 0)
+ bad = TRUE;
+ } else {
+ /* need not check Ss/Se < 0 since they came from unsigned bytes */
+ if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
+ bad = TRUE;
+ /* AC scans may have only one component */
+ if (cinfo->comps_in_scan != 1)
+ bad = TRUE;
+ }
+ if (cinfo->Ah != 0) {
+ /* Successive approximation refinement scan: must have Al = Ah-1. */
+ if (cinfo->Al != cinfo->Ah-1)
+ bad = TRUE;
+ }
+ if (cinfo->Al > 13) /* need not check for < 0 */
+ bad = TRUE;
+ /* Arguably the maximum Al value should be less than 13 for 8-bit precision,
+ * but the spec doesn't say so, and we try to be liberal about what we
+ * accept. Note: large Al values could result in out-of-range DC
+ * coefficients during early scans, leading to bizarre displays due to
+ * overflows in the IDCT math. But we won't crash.
+ */
+ if (bad)
+ ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
+ cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+ /* Update progression status, and verify that scan order is legal.
+ * Note that inter-scan inconsistencies are treated as warnings
+ * not fatal errors ... not clear if this is right way to behave.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ int cindex = cinfo->cur_comp_info[ci]->component_index;
+ coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+ for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
+ int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+ if (cinfo->Ah != expected)
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+ coef_bit_ptr[coefi] = cinfo->Al;
+ }
+ }
+
+ /* Select MCU decoding routine */
+ if (cinfo->Ah == 0) {
+ if (is_DC_band)
+ entropy->pub.decode_mcu = decode_mcu_DC_first;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_first;
+ } else {
+ if (is_DC_band)
+ entropy->pub.decode_mcu = decode_mcu_DC_refine;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_refine;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Make sure requested tables are present, and compute derived tables.
+ * We may build same derived table more than once, but it's not expensive.
+ */
+ if (is_DC_band) {
+ if (cinfo->Ah == 0) { /* DC refinement needs no table */
+ tbl = compptr->dc_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, TRUE, tbl,
+ & entropy->derived_tbls[tbl]);
+ }
+ } else {
+ tbl = compptr->ac_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, FALSE, tbl,
+ & entropy->derived_tbls[tbl]);
+ /* remember the single active table */
+ entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->pub.insufficient_data = FALSE;
+
+ /* Initialize private state variables */
+ entropy->saved.EOBRUN = 0;
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] = /* entry n is 2**(n-1) */
+ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+ ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+ ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Re-init EOB run count, too */
+ entropy->saved.EOBRUN = 0;
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->pub.insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Huffman MCU decoding.
+ * Each of these routines decodes and returns one MCU's worth of
+ * Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
+ *
+ * We return FALSE if data source requested suspension. In that case no
+ * changes have been made to permanent state. (Exception: some output
+ * coefficients may already have been assigned. This is harmless for
+ * spectral selection, since we'll just re-assign them on the next call.
+ * Successive approximation AC refinement has to be more careful, however.)
+ */
+
+/*
+ * MCU decoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ int Al = cinfo->Al;
+ register int s, r;
+ int blkn, ci;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ savable_state state;
+ d_derived_tbl * tbl;
+ jpeg_component_info * compptr;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ tbl = entropy->derived_tbls[compptr->dc_tbl_no];
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+
+ /* Convert DC difference to actual value, update last_dc_val */
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
+ (*block)[0] = (JCOEF) (s << Al);
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state.
+ * We can avoid loading/saving bitread state if in an EOB run.
+ */
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+
+ if (EOBRUN > 0) /* if it's a band of zeroes... */
+ EOBRUN--; /* ...process it now (we do nothing) */
+ else {
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Scale and output coefficient in natural (dezigzagged) order */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
+ } else {
+ if (r == 15) { /* ZRL */
+ k += 15; /* skip 15 zeroes in band */
+ } else { /* EOBr, run length is 2^r + appended bits */
+ EOBRUN = 1 << r;
+ if (r) { /* EOBr, r > 0 */
+ CHECK_BIT_BUFFER(br_state, r, return FALSE);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ EOBRUN--; /* this band is processed at this moment */
+ break; /* force end-of-band */
+ }
+ }
+ }
+
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ }
+
+ /* Completed MCU, so update state */
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int blkn;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* Not worth the cycles to check insufficient_data here,
+ * since we will not change the data anyway if we read zeroes.
+ */
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* Encoded data is simply the next bit of the two's-complement DC value */
+ CHECK_BIT_BUFFER(br_state, 1, return FALSE);
+ if (GET_BITS(1))
+ (*block)[0] |= p1;
+ /* Note: since we use |=, repeating the assignment later is safe */
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ int Se = cinfo->Se;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ JCOEFPTR thiscoef;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+ int num_newnz;
+ int newnz_pos[DCTSIZE2];
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, don't modify the MCU.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ /* If we are forced to suspend, we must undo the assignments to any newly
+ * nonzero coefficients in the block, because otherwise we'd get confused
+ * next time about which coefficients were already nonzero.
+ * But we need not undo addition of bits to already-nonzero coefficients;
+ * instead, we can test the current bit to see if we already did it.
+ */
+ num_newnz = 0;
+
+ /* initialize coefficient loop counter to start of band */
+ k = cinfo->Ss;
+
+ if (EOBRUN == 0) {
+ for (; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ if (s != 1) /* size of new coef should always be 1 */
+ WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1))
+ s = p1; /* newly nonzero coef is positive */
+ else
+ s = m1; /* newly nonzero coef is negative */
+ } else {
+ if (r != 15) {
+ EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */
+ if (r) {
+ CHECK_BIT_BUFFER(br_state, r, goto undoit);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ break; /* rest of block is handled by EOB logic */
+ }
+ /* note s = 0 for processing ZRL */
+ }
+ /* Advance over already-nonzero coefs and r still-zero coefs,
+ * appending correction bits to the nonzeroes. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ do {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ } else {
+ if (--r < 0)
+ break; /* reached target zero coefficient */
+ }
+ k++;
+ } while (k <= Se);
+ if (s) {
+ int pos = jpeg_natural_order[k];
+ /* Output newly nonzero coefficient */
+ (*block)[pos] = (JCOEF) s;
+ /* Remember its position in case we have to suspend */
+ newnz_pos[num_newnz++] = pos;
+ }
+ }
+ }
+
+ if (EOBRUN > 0) {
+ /* Scan any remaining coefficient positions after the end-of-band
+ * (the last newly nonzero coefficient, if any). Append a correction
+ * bit to each already-nonzero coefficient. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ for (; k <= Se; k++) {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ }
+ }
+ /* Count one block completed in EOB run */
+ EOBRUN--;
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+
+undoit:
+ /* Re-zero any output coefficients that we made newly nonzero */
+ while (num_newnz > 0)
+ (*block)[newnz_pos[--num_newnz]] = 0;
+
+ return FALSE;
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_decoder (j_decompress_ptr cinfo)
+{
+ phuff_entropy_ptr entropy;
+ int *coef_bit_ptr;
+ int ci, i;
+
+ entropy = (phuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(phuff_entropy_decoder));
+ cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ entropy->pub.start_pass = start_pass_phuff_decoder;
+
+ /* Mark derived tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ }
+
+ /* Create progression status table */
+ cinfo->coef_bits = (int (*)[DCTSIZE2])
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components*DCTSIZE2*SIZEOF(int));
+ coef_bit_ptr = & cinfo->coef_bits[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (i = 0; i < DCTSIZE2; i++)
+ *coef_bit_ptr++ = -1;
+}
+
+#endif /* D_PROGRESSIVE_SUPPORTED */
diff --git a/SrcShared/jpeg/jdpostct.c b/SrcShared/jpeg/jdpostct.c
new file mode 100644
index 0000000..571563d
--- /dev/null
+++ b/SrcShared/jpeg/jdpostct.c
@@ -0,0 +1,290 @@
+/*
+ * jdpostct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the decompression postprocessing controller.
+ * This controller manages the upsampling, color conversion, and color
+ * quantization/reduction steps; specifically, it controls the buffering
+ * between upsample/color conversion and color quantization/reduction.
+ *
+ * If no color quantization/reduction is required, then this module has no
+ * work to do, and it just hands off to the upsample/color conversion code.
+ * An integrated upsample/convert/quantize process would replace this module
+ * entirely.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_post_controller pub; /* public fields */
+
+ /* Color quantization source buffer: this holds output data from
+ * the upsample/color conversion step to be passed to the quantizer.
+ * For two-pass color quantization, we need a full-image buffer;
+ * for one-pass operation, a strip buffer is sufficient.
+ */
+ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
+ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
+ JDIMENSION strip_height; /* buffer size in rows */
+ /* for two-pass mode only: */
+ JDIMENSION starting_row; /* row # of first row in current strip */
+ JDIMENSION next_row; /* index of next row to fill/empty in strip */
+} my_post_controller;
+
+typedef my_post_controller * my_post_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) post_process_1pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) post_process_prepass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+METHODDEF(void) post_process_2pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->quantize_colors) {
+ /* Single-pass processing with color quantization. */
+ post->pub.post_process_data = post_process_1pass;
+ /* We could be doing buffered-image output before starting a 2-pass
+ * color quantization; in that case, jinit_d_post_controller did not
+ * allocate a strip buffer. Use the virtual-array buffer as workspace.
+ */
+ if (post->buffer == NULL) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ (JDIMENSION) 0, post->strip_height, TRUE);
+ }
+ } else {
+ /* For single-pass processing without color quantization,
+ * I have no work to do; just call the upsampler directly.
+ */
+ post->pub.post_process_data = cinfo->upsample->upsample;
+ }
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ /* First pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_prepass;
+ break;
+ case JBUF_CRANK_DEST:
+ /* Second pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_2pass;
+ break;
+#endif /* QUANT_2PASS_SUPPORTED */
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+ post->starting_row = post->next_row = 0;
+}
+
+
+/*
+ * Process some data in the one-pass (strip buffer) case.
+ * This is used for color precision reduction as well as one-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_1pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Fill the buffer, but not more than what we can dump out in one go. */
+ /* Note we rely on the upsampler to detect bottom of image. */
+ max_rows = out_rows_avail - *out_row_ctr;
+ if (max_rows > post->strip_height)
+ max_rows = post->strip_height;
+ num_rows = 0;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &num_rows, max_rows);
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+ *out_row_ctr += num_rows;
+}
+
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+/*
+ * Process some data in the first pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_prepass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION old_next_row, num_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, TRUE);
+ }
+
+ /* Upsample some data (up to a strip height's worth). */
+ old_next_row = post->next_row;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &post->next_row, post->strip_height);
+
+ /* Allow quantizer to scan new data. No data is emitted, */
+ /* but we advance out_row_ctr so outer loop can tell when we're done. */
+ if (post->next_row > old_next_row) {
+ num_rows = post->next_row - old_next_row;
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
+ (JSAMPARRAY) NULL, (int) num_rows);
+ *out_row_ctr += num_rows;
+ }
+
+ /* Advance if we filled the strip. */
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+
+/*
+ * Process some data in the second pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_2pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, FALSE);
+ }
+
+ /* Determine number of rows to emit. */
+ num_rows = post->strip_height - post->next_row; /* available in strip */
+ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+ /* We have to check bottom of image here, can't depend on upsampler. */
+ max_rows = cinfo->output_height - post->starting_row;
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer + post->next_row, output_buf + *out_row_ctr,
+ (int) num_rows);
+ *out_row_ctr += num_rows;
+
+ /* Advance if we filled the strip. */
+ post->next_row += num_rows;
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize postprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_post_ptr post;
+
+ post = (my_post_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_post_controller));
+ cinfo->post = (struct jpeg_d_post_controller *) post;
+ post->pub.start_pass = start_pass_dpost;
+ post->whole_image = NULL; /* flag for no virtual arrays */
+ post->buffer = NULL; /* flag for no strip buffer */
+
+ /* Create the quantization buffer, if needed */
+ if (cinfo->quantize_colors) {
+ /* The buffer strip height is max_v_samp_factor, which is typically
+ * an efficient number of rows for upsampling to return.
+ * (In the presence of output rescaling, we might want to be smarter?)
+ */
+ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+ if (need_full_buffer) {
+ /* Two-pass color quantization: need full-image storage. */
+ /* We round up the number of rows to a multiple of the strip height. */
+#ifdef QUANT_2PASS_SUPPORTED
+ post->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ cinfo->output_width * cinfo->out_color_components,
+ (JDIMENSION) jround_up((long) cinfo->output_height,
+ (long) post->strip_height),
+ post->strip_height);
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ /* One-pass color quantization: just make a strip buffer. */
+ post->buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width * cinfo->out_color_components,
+ post->strip_height);
+ }
+ }
+}
diff --git a/SrcShared/jpeg/jdsample.c b/SrcShared/jpeg/jdsample.c
new file mode 100644
index 0000000..80ffefb
--- /dev/null
+++ b/SrcShared/jpeg/jdsample.c
@@ -0,0 +1,478 @@
+/*
+ * jdsample.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains upsampling routines.
+ *
+ * Upsampling input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
+ * sample rows of each component. Upsampling will normally produce
+ * max_v_samp_factor pixel rows from each row group (but this could vary
+ * if the upsampler is applying a scale factor of its own).
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to upsample a single component */
+typedef JMETHOD(void, upsample1_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Color conversion buffer. When using separate upsampling and color
+ * conversion steps, this buffer holds one upsampled row group until it
+ * has been color converted and output.
+ * Note: we do not allocate any storage for component(s) which are full-size,
+ * ie do not need rescaling. The corresponding entry of color_buf[] is
+ * simply set to point to the input data array, thereby avoiding copying.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ /* Per-component upsampling method pointers */
+ upsample1_ptr methods[MAX_COMPONENTS];
+
+ int next_row_out; /* counts rows emitted from color_buf */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+
+ /* Height of an input row group for each component. */
+ int rowgroup_height[MAX_COMPONENTS];
+
+ /* These arrays save pixel expansion factors so that int_expand need not
+ * recompute them each time. They are unused for other upsampling methods.
+ */
+ UINT8 h_expand[MAX_COMPONENTS];
+ UINT8 v_expand[MAX_COMPONENTS];
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the conversion buffer empty */
+ upsample->next_row_out = cinfo->max_v_samp_factor;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * In this version we upsample each component independently.
+ * We upsample one row group into the conversion buffer, then apply
+ * color conversion a row at a time.
+ */
+
+METHODDEF(void)
+sep_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JDIMENSION num_rows;
+
+ /* Fill the conversion buffer, if it's empty */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Invoke per-component upsample method. Notice we pass a POINTER
+ * to color_buf[ci], so that fullsize_upsample can change it.
+ */
+ (*upsample->methods[ci]) (cinfo, compptr,
+ input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
+ upsample->color_buf + ci);
+ }
+ upsample->next_row_out = 0;
+ }
+
+ /* Color-convert and emit rows */
+
+ /* How many we have in the buffer: */
+ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+ /* Not more than the distance to the end of the image. Need this test
+ * in case the image height is not a multiple of max_v_samp_factor:
+ */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+
+ (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
+ (JDIMENSION) upsample->next_row_out,
+ output_buf + *out_row_ctr,
+ (int) num_rows);
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ upsample->next_row_out += num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor)
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by sep_upsample to upsample pixel values
+ * of a single component. One row group is processed per call.
+ */
+
+
+/*
+ * For full-size components, we just make color_buf[ci] point at the
+ * input buffer, and thus avoid copying any data. Note that this is
+ * safe only because sep_upsample doesn't declare the input row group
+ * "consumed" until we are done color converting and emitting it.
+ */
+
+METHODDEF(void)
+fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = input_data;
+}
+
+
+/*
+ * This is a no-op version used for "uninteresting" components.
+ * These components will not be referenced by color conversion.
+ */
+
+METHODDEF(void)
+noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = NULL; /* safety check */
+}
+
+
+/*
+ * This version handles any integral sampling ratios.
+ * This is not used for typical JPEG files, so it need not be fast.
+ * Nor, for that matter, is it particularly accurate: the algorithm is
+ * simple replication of the input pixel onto the corresponding output
+ * pixels. The hi-falutin sampling literature refers to this as a
+ * "box filter". A box filter tends to introduce visible artifacts,
+ * so if you are actually going to use 3:1 or 4:1 sampling ratios
+ * you would be well advised to improve this code.
+ */
+
+METHODDEF(void)
+int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ register int h;
+ JSAMPROW outend;
+ int h_expand, v_expand;
+ int inrow, outrow;
+
+ h_expand = upsample->h_expand[compptr->component_index];
+ v_expand = upsample->v_expand[compptr->component_index];
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ /* Generate one output row with proper horizontal expansion */
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ for (h = h_expand; h > 0; h--) {
+ *outptr++ = invalue;
+ }
+ }
+ /* Generate any additional output rows by duplicating the first one */
+ if (v_expand > 1) {
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ v_expand-1, cinfo->output_width);
+ }
+ inrow++;
+ outrow += v_expand;
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int inrow;
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ inptr = input_data[inrow];
+ outptr = output_data[inrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int inrow, outrow;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ 1, cinfo->output_width);
+ inrow++;
+ outrow += 2;
+ }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
+ *
+ * The upsampling algorithm is linear interpolation between pixel centers,
+ * also known as a "triangle filter". This is a good compromise between
+ * speed and visual quality. The centers of the output pixels are 1/4 and 3/4
+ * of the way between input pixel centers.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register int invalue;
+ register JDIMENSION colctr;
+ int inrow;
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ inptr = input_data[inrow];
+ outptr = output_data[inrow];
+ /* Special case for first column */
+ invalue = GETJSAMPLE(*inptr++);
+ *outptr++ = (JSAMPLE) invalue;
+ *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
+
+ for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+ /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
+ invalue = GETJSAMPLE(*inptr++) * 3;
+ *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
+ *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
+ }
+
+ /* Special case for last column */
+ invalue = GETJSAMPLE(*inptr);
+ *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
+ *outptr++ = (JSAMPLE) invalue;
+ }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * Again a triangle filter; see comments for h2v1 case, above.
+ *
+ * It is OK for us to reference the adjacent input rows because we demanded
+ * context from the main buffer controller (see initialization code).
+ */
+
+METHODDEF(void)
+h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr0, inptr1, outptr;
+#if BITS_IN_JSAMPLE == 8
+ register int thiscolsum, lastcolsum, nextcolsum;
+#else
+ register INT32 thiscolsum, lastcolsum, nextcolsum;
+#endif
+ register JDIMENSION colctr;
+ int inrow, outrow, v;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ for (v = 0; v < 2; v++) {
+ /* inptr0 points to nearest input row, inptr1 points to next nearest */
+ inptr0 = input_data[inrow];
+ if (v == 0) /* next nearest is row above */
+ inptr1 = input_data[inrow-1];
+ else /* next nearest is row below */
+ inptr1 = input_data[inrow+1];
+ outptr = output_data[outrow++];
+
+ /* Special case for first column */
+ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+
+ for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+ /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
+ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
+ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ }
+
+ /* Special case for last column */
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
+ }
+ inrow++;
+ }
+}
+
+
+/*
+ * Module initialization routine for upsampling.
+ */
+
+GLOBAL(void)
+jinit_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean need_buffer, do_fancy;
+ int h_in_group, v_in_group, h_out_group, v_out_group;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_upsample;
+ upsample->pub.upsample = sep_upsample;
+ upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+
+ if (cinfo->CCIR601_sampling) /* this isn't supported */
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
+ * so don't ask for it.
+ */
+ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
+
+ /* Verify we can handle the sampling factors, select per-component methods,
+ * and create storage as needed.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Compute size of an "input group" after IDCT scaling. This many samples
+ * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
+ */
+ h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size;
+ v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
+ cinfo->min_DCT_scaled_size;
+ h_out_group = cinfo->max_h_samp_factor;
+ v_out_group = cinfo->max_v_samp_factor;
+ upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
+ need_buffer = TRUE;
+ if (! compptr->component_needed) {
+ /* Don't bother to upsample an uninteresting component. */
+ upsample->methods[ci] = noop_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
+ /* Fullsize components can be processed without any work. */
+ upsample->methods[ci] = fullsize_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group == v_out_group) {
+ /* Special cases for 2h1v upsampling */
+ if (do_fancy && compptr->downsampled_width > 2)
+ upsample->methods[ci] = h2v1_fancy_upsample;
+ else
+ upsample->methods[ci] = h2v1_upsample;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group * 2 == v_out_group) {
+ /* Special cases for 2h2v upsampling */
+ if (do_fancy && compptr->downsampled_width > 2) {
+ upsample->methods[ci] = h2v2_fancy_upsample;
+ upsample->pub.need_context_rows = TRUE;
+ } else
+ upsample->methods[ci] = h2v2_upsample;
+ } else if ((h_out_group % h_in_group) == 0 &&
+ (v_out_group % v_in_group) == 0) {
+ /* Generic integral-factors upsampling method */
+ upsample->methods[ci] = int_upsample;
+ upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
+ upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ if (need_buffer) {
+ upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) cinfo->output_width,
+ (long) cinfo->max_h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/SrcShared/jpeg/jdtrans.c b/SrcShared/jpeg/jdtrans.c
new file mode 100644
index 0000000..6c0ab71
--- /dev/null
+++ b/SrcShared/jpeg/jdtrans.c
@@ -0,0 +1,143 @@
+/*
+ * jdtrans.c
+ *
+ * Copyright (C) 1995-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding decompression,
+ * that is, reading raw DCT coefficient arrays from an input JPEG file.
+ * The routines in jdapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Read the coefficient arrays from a JPEG file.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * The entire image is read into a set of virtual coefficient-block arrays,
+ * one per component. The return value is a pointer to the array of
+ * virtual-array descriptors. These can be manipulated directly via the
+ * JPEG memory manager, or handed off to jpeg_write_coefficients().
+ * To release the memory occupied by the virtual arrays, call
+ * jpeg_finish_decompress() when done with the data.
+ *
+ * An alternative usage is to simply obtain access to the coefficient arrays
+ * during a buffered-image-mode decompression operation. This is allowed
+ * after any jpeg_finish_output() call. The arrays can be accessed until
+ * jpeg_finish_decompress() is called. (Note that any call to the library
+ * may reposition the arrays, so don't rely on access_virt_barray() results
+ * to stay valid across library calls.)
+ *
+ * Returns NULL if suspended. This case need be checked only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jpeg_read_coefficients (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize active modules */
+ transdecode_master_selection(cinfo);
+ cinfo->global_state = DSTATE_RDCOEFS;
+ }
+ if (cinfo->global_state == DSTATE_RDCOEFS) {
+ /* Absorb whole file into the coef buffer */
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return NULL;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* startup underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+ /* Set state so that jpeg_finish_decompress does the right thing */
+ cinfo->global_state = DSTATE_STOPPING;
+ }
+ /* At this point we should be in state DSTATE_STOPPING if being used
+ * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access
+ * to the coefficients during a full buffered-image-mode decompression.
+ */
+ if ((cinfo->global_state == DSTATE_STOPPING ||
+ cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
+ return cinfo->coef->coef_arrays;
+ }
+ /* Oops, improper usage */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return NULL; /* keep compiler happy */
+}
+
+
+/*
+ * Master selection of decompression modules for transcoding.
+ * This substitutes for jdmaster.c's initialization of the full decompressor.
+ */
+
+LOCAL(void)
+transdecode_master_selection (j_decompress_ptr cinfo)
+{
+ /* This is effectively a buffered-image operation. */
+ cinfo->buffered_image = TRUE;
+
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->progressive_mode) {
+#ifdef D_PROGRESSIVE_SUPPORTED
+ jinit_phuff_decoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_huff_decoder(cinfo);
+ }
+
+ /* Always get a full-image coefficient buffer. */
+ jinit_d_coef_controller(cinfo, TRUE);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+ /* Initialize progress monitoring. */
+ if (cinfo->progress != NULL) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->progressive_mode) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else if (cinfo->inputctl->has_multiple_scans) {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ } else {
+ nscans = 1;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = 1;
+ }
+}
diff --git a/SrcShared/jpeg/jerror.c b/SrcShared/jpeg/jerror.c
new file mode 100644
index 0000000..3da7be8
--- /dev/null
+++ b/SrcShared/jpeg/jerror.c
@@ -0,0 +1,252 @@
+/*
+ * jerror.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains simple error-reporting and trace-message routines.
+ * These are suitable for Unix-like systems and others where writing to
+ * stderr is the right thing to do. Many applications will want to replace
+ * some or all of these routines.
+ *
+ * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
+ * you get a Windows-specific hack to display error messages in a dialog box.
+ * It ain't much, but it beats dropping error messages into the bit bucket,
+ * which is what happens to output to stderr under most Windows C compilers.
+ *
+ * These routines are used by both the compression and decompression code.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jversion.h"
+#include "jerror.h"
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+#include <windows.h>
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+
+
+/*
+ * Create the message string table.
+ * We do this from the master message list in jerror.h by re-reading
+ * jerror.h with a suitable definition for macro JMESSAGE.
+ * The message table is made an external symbol just in case any applications
+ * want to refer to it directly.
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_message_table jMsgTable
+#endif
+
+#define JMESSAGE(code,string) string ,
+
+const char * const jpeg_std_message_table[] = {
+#include "jerror.h"
+ NULL
+};
+
+
+/*
+ * Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error. Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object. Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ */
+
+METHODDEF(void)
+error_exit (j_common_ptr cinfo)
+{
+ /* Always display the message */
+ (*cinfo->err->output_message) (cinfo);
+
+ /* Let the memory manager delete any temp files before we die */
+ jpeg_destroy(cinfo);
+
+ exit(EXIT_FAILURE);
+}
+
+
+/*
+ * Actual output of an error or trace message.
+ * Applications may override this method to send JPEG messages somewhere
+ * other than stderr.
+ *
+ * On Windows, printing to stderr is generally completely useless,
+ * so we provide optional code to produce an error-dialog popup.
+ * Most Windows applications will still prefer to override this routine,
+ * but if they don't, it'll do something at least marginally useful.
+ *
+ * NOTE: to use the library in an environment that doesn't support the
+ * C stdio library, you may have to delete the call to fprintf() entirely,
+ * not just not use this routine.
+ */
+
+METHODDEF(void)
+output_message (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+ /* Display it in a message dialog box */
+ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
+ MB_OK | MB_ICONERROR);
+#else
+ /* Send it to stderr, adding a newline */
+ fprintf(stderr, "%s\n", buffer);
+#endif
+}
+
+
+/*
+ * Decide whether to emit a trace or warning message.
+ * msg_level is one of:
+ * -1: recoverable corrupt-data warning, may want to abort.
+ * 0: important advisory messages (always display to user).
+ * 1: first level of tracing detail.
+ * 2,3,...: successively more detailed tracing messages.
+ * An application might override this method if it wanted to abort on warnings
+ * or change the policy about which messages to display.
+ */
+
+METHODDEF(void)
+emit_message (j_common_ptr cinfo, int msg_level)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+
+ if (msg_level < 0) {
+ /* It's a warning message. Since corrupt files may generate many warnings,
+ * the policy implemented here is to show only the first warning,
+ * unless trace_level >= 3.
+ */
+ if (err->num_warnings == 0 || err->trace_level >= 3)
+ (*err->output_message) (cinfo);
+ /* Always count warnings in num_warnings. */
+ err->num_warnings++;
+ } else {
+ /* It's a trace message. Show it if trace_level >= msg_level. */
+ if (err->trace_level >= msg_level)
+ (*err->output_message) (cinfo);
+ }
+}
+
+
+/*
+ * Format a message string for the most recent JPEG error or message.
+ * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
+ * characters. Note that no '\n' character is added to the string.
+ * Few applications should need to override this method.
+ */
+
+METHODDEF(void)
+format_message (j_common_ptr cinfo, char * buffer)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+ int msg_code = err->msg_code;
+ const char * msgtext = NULL;
+ const char * msgptr;
+ char ch;
+ boolean isstring;
+
+ /* Look up message string in proper table */
+ if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
+ msgtext = err->jpeg_message_table[msg_code];
+ } else if (err->addon_message_table != NULL &&
+ msg_code >= err->first_addon_message &&
+ msg_code <= err->last_addon_message) {
+ msgtext = err->addon_message_table[msg_code - err->first_addon_message];
+ }
+
+ /* Defend against bogus message number */
+ if (msgtext == NULL) {
+ err->msg_parm.i[0] = msg_code;
+ msgtext = err->jpeg_message_table[0];
+ }
+
+ /* Check for string parameter, as indicated by %s in the message text */
+ isstring = FALSE;
+ msgptr = msgtext;
+ while ((ch = *msgptr++) != '\0') {
+ if (ch == '%') {
+ if (*msgptr == 's') isstring = TRUE;
+ break;
+ }
+ }
+
+ /* Format the message into the passed buffer */
+ if (isstring)
+ sprintf(buffer, msgtext, err->msg_parm.s);
+ else
+ sprintf(buffer, msgtext,
+ err->msg_parm.i[0], err->msg_parm.i[1],
+ err->msg_parm.i[2], err->msg_parm.i[3],
+ err->msg_parm.i[4], err->msg_parm.i[5],
+ err->msg_parm.i[6], err->msg_parm.i[7]);
+}
+
+
+/*
+ * Reset error state variables at start of a new image.
+ * This is called during compression startup to reset trace/error
+ * processing to default state, without losing any application-specific
+ * method pointers. An application might possibly want to override
+ * this method if it has additional error processing state.
+ */
+
+METHODDEF(void)
+reset_error_mgr (j_common_ptr cinfo)
+{
+ cinfo->err->num_warnings = 0;
+ /* trace_level is not reset since it is an application-supplied parameter */
+ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
+}
+
+
+/*
+ * Fill in the standard error-handling methods in a jpeg_error_mgr object.
+ * Typical call is:
+ * struct jpeg_compress_struct cinfo;
+ * struct jpeg_error_mgr err;
+ *
+ * cinfo.err = jpeg_std_error(&err);
+ * after which the application may override some of the methods.
+ */
+
+GLOBAL(struct jpeg_error_mgr *)
+jpeg_std_error (struct jpeg_error_mgr * err)
+{
+ err->error_exit = error_exit;
+ err->emit_message = emit_message;
+ err->output_message = output_message;
+ err->format_message = format_message;
+ err->reset_error_mgr = reset_error_mgr;
+
+ err->trace_level = 0; /* default = no tracing */
+ err->num_warnings = 0; /* no warnings emitted yet */
+ err->msg_code = 0; /* may be useful as a flag for "no error" */
+
+ /* Initialize message table pointers */
+ err->jpeg_message_table = jpeg_std_message_table;
+ err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+
+ err->addon_message_table = NULL;
+ err->first_addon_message = 0; /* for safety */
+ err->last_addon_message = 0;
+
+ return err;
+}
diff --git a/SrcShared/jpeg/jerror.h b/SrcShared/jpeg/jerror.h
new file mode 100644
index 0000000..fc2fffe
--- /dev/null
+++ b/SrcShared/jpeg/jerror.h
@@ -0,0 +1,291 @@
+/*
+ * jerror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the JPEG library.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ * A set of error-reporting macros are defined too. Some applications using
+ * the JPEG library may wish to include this file to get the error codes
+ * and/or the macros.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef JERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* JERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
+
+/* For maintenance convenience, list is alphabetical by message code name */
+JMESSAGE(JERR_ARITH_NOTIMPL,
+ "Sorry, there are legal restrictions on arithmetic coding")
+JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
+JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
+JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
+JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
+JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
+JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
+JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
+JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
+JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
+JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
+JMESSAGE(JERR_BAD_LIB_VERSION,
+ "Wrong JPEG library version: library is %d, caller expects %d")
+JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
+JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
+JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
+JMESSAGE(JERR_BAD_PROGRESSION,
+ "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_PROG_SCRIPT,
+ "Invalid progressive parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
+JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
+JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
+JMESSAGE(JERR_BAD_STRUCT_SIZE,
+ "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
+JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
+JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
+JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
+JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
+JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
+JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
+JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
+JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
+JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
+JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
+JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
+JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
+JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
+JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
+JMESSAGE(JERR_FILE_READ, "Input file read error")
+JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
+JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
+JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
+JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
+JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
+JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
+JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
+JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
+ "Cannot transcode due to multiple use of quantization table %d")
+JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
+JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
+JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
+JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
+JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
+JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
+JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
+JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
+JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
+JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
+JMESSAGE(JERR_QUANT_COMPONENTS,
+ "Cannot quantize more than %d color components")
+JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
+JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
+JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
+JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
+JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
+JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
+JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
+JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
+JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
+JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
+JMESSAGE(JERR_TFILE_WRITE,
+ "Write failed on temporary file --- out of disk space?")
+JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
+JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
+JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
+JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
+JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
+JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
+JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
+JMESSAGE(JMSG_VERSION, JVERSION)
+JMESSAGE(JTRC_16BIT_TABLES,
+ "Caution: quantization tables are too coarse for baseline JPEG")
+JMESSAGE(JTRC_ADOBE,
+ "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
+JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
+JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
+JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
+JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
+JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
+JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
+JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
+JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
+JMESSAGE(JTRC_EOI, "End Of Image")
+JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
+JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
+JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
+ "Warning: thumbnail image size does not match data length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION,
+ "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
+JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
+JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
+JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
+JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
+JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
+JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
+JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
+JMESSAGE(JTRC_RST, "RST%d")
+JMESSAGE(JTRC_SMOOTH_NOTIMPL,
+ "Smoothing not supported with nonstandard sampling ratios")
+JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
+JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
+JMESSAGE(JTRC_SOI, "Start of Image")
+JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
+JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
+JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
+JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
+JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
+JMESSAGE(JTRC_THUMB_JPEG,
+ "JFIF extension marker: JPEG-compressed thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_PALETTE,
+ "JFIF extension marker: palette thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_RGB,
+ "JFIF extension marker: RGB thumbnail image, length %u")
+JMESSAGE(JTRC_UNKNOWN_IDS,
+ "Unrecognized component IDs %d %d %d, assuming YCbCr")
+JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
+JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
+JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
+JMESSAGE(JWRN_BOGUS_PROGRESSION,
+ "Inconsistent progression sequence for component %d coefficient %d")
+JMESSAGE(JWRN_EXTRANEOUS_DATA,
+ "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
+JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
+JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
+JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
+JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
+JMESSAGE(JWRN_MUST_RESYNC,
+ "Corrupt JPEG data: found marker 0x%02x instead of RST%d")
+JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
+JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTMSGCODE
+} J_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
+
+
+#ifndef JERROR_H
+#define JERROR_H
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is either type of cinfo pointer */
+
+/* Fatal errors (print message and exit) */
+#define ERREXIT(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT3(cinfo,code,p1,p2,p3) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (cinfo)->err->msg_parm.i[3] = (p4), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXITS(cinfo,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+#define MAKESTMT(stuff) do { stuff } while (0)
+
+/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
+#define WARNMS(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+
+/* Informational/debugging messages */
+#define TRACEMS(cinfo,lvl,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS1(cinfo,lvl,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS2(cinfo,lvl,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMSS(cinfo,lvl,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+
+#endif /* JERROR_H */
diff --git a/SrcShared/jpeg/jfdctflt.c b/SrcShared/jpeg/jfdctflt.c
new file mode 100644
index 0000000..79d7a00
--- /dev/null
+++ b/SrcShared/jpeg/jfdctflt.c
@@ -0,0 +1,168 @@
+/*
+ * jfdctflt.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * This implementation should be more accurate than either of the integer
+ * DCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_float (FAST_FLOAT * data)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
+ FAST_FLOAT *dataptr;
+ int ctr;
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/SrcShared/jpeg/jfdctfst.c b/SrcShared/jpeg/jfdctfst.c
new file mode 100644
index 0000000..ccb378a
--- /dev/null
+++ b/SrcShared/jpeg/jfdctfst.c
@@ -0,0 +1,224 @@
+/*
+ * jfdctfst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jfdctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * Again to save a few shifts, the intermediate results between pass 1 and
+ * pass 2 are not upscaled, but are represented only to integral precision.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#define CONST_BITS 8
+
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
+#else
+#define FIX_0_382683433 FIX(0.382683433)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_707106781 FIX(0.707106781)
+#define FIX_1_306562965 FIX(1.306562965)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_ifast (DCTELEM * data)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/SrcShared/jpeg/jfdctint.c b/SrcShared/jpeg/jfdctint.c
new file mode 100644
index 0000000..0a78b64
--- /dev/null
+++ b/SrcShared/jpeg/jfdctint.c
@@ -0,0 +1,283 @@
+/*
+ * jfdctint.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D DCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true DCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D DCT,
+ * because the y0 and y4 outputs need not be divided by sqrt(N).
+ * In the IJG code, this factor of 8 is removed by the quantization step
+ * (in jcdctmgr.c), NOT in this module.
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (For 12-bit sample data, the intermediate
+ * array is INT32 anyway.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_islow (DCTELEM * data)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+
+ z1 = tmp4 + tmp7;
+ z2 = tmp5 + tmp6;
+ z3 = tmp4 + tmp6;
+ z4 = tmp5 + tmp7;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+
+ z1 = tmp4 + tmp7;
+ z2 = tmp5 + tmp6;
+ z3 = tmp4 + tmp6;
+ z4 = tmp5 + tmp7;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/SrcShared/jpeg/jidctflt.c b/SrcShared/jpeg/jidctflt.c
new file mode 100644
index 0000000..0188ce3
--- /dev/null
+++ b/SrcShared/jpeg/jidctflt.c
@@ -0,0 +1,242 @@
+/*
+ * jidctflt.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * This implementation should be more accurate than either of the integer
+ * IDCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a float result.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ FLOAT_MULT_TYPE * quantptr;
+ FAST_FLOAT * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = tmp0 + tmp7;
+ wsptr[DCTSIZE*7] = tmp0 - tmp7;
+ wsptr[DCTSIZE*1] = tmp1 + tmp6;
+ wsptr[DCTSIZE*6] = tmp1 - tmp6;
+ wsptr[DCTSIZE*2] = tmp2 + tmp5;
+ wsptr[DCTSIZE*5] = tmp2 - tmp5;
+ wsptr[DCTSIZE*4] = tmp3 + tmp4;
+ wsptr[DCTSIZE*3] = tmp3 - tmp4;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * And testing floats for zero is relatively expensive, so we don't bother.
+ */
+
+ /* Even part */
+
+ tmp10 = wsptr[0] + wsptr[4];
+ tmp11 = wsptr[0] - wsptr[4];
+
+ tmp13 = wsptr[2] + wsptr[6];
+ tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = wsptr[5] + wsptr[3];
+ z10 = wsptr[5] - wsptr[3];
+ z11 = wsptr[1] + wsptr[7];
+ z12 = wsptr[1] - wsptr[7];
+
+ tmp7 = z11 + z13;
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7;
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/SrcShared/jpeg/jidctfst.c b/SrcShared/jpeg/jidctfst.c
new file mode 100644
index 0000000..dba4216
--- /dev/null
+++ b/SrcShared/jpeg/jidctfst.c
@@ -0,0 +1,368 @@
+/*
+ * jidctfst.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jidctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * The dequantized coefficients are not integers because the AA&N scaling
+ * factors have been incorporated. We represent them scaled up by PASS1_BITS,
+ * so that the first and second IDCT rounds have the same input scaling.
+ * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
+ * avoid a descaling shift; this compromises accuracy rather drastically
+ * for small quantization table entries, but it saves a lot of shifts.
+ * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
+ * so we use a much larger scaling factor to preserve accuracy.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 8
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 8
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */
+#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */
+#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */
+#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */
+#else
+#define FIX_1_082392200 FIX(1.082392200)
+#define FIX_1_414213562 FIX(1.414213562)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_2_613125930 FIX(2.613125930)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a DCTELEM result. For 8-bit data a 16x16->16
+ * multiplication will do. For 12-bit data, the multiplier table is
+ * declared INT32, so a 32-bit multiply will be used.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#else
+#define DEQUANTIZE(coef,quantval) \
+ DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#endif
+
+
+/* Like DESCALE, but applies to a DCTELEM and produces an int.
+ * We assume that int right shift is unsigned if INT32 right shift is.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS DCTELEM ishift_temp;
+#if BITS_IN_JSAMPLE == 8
+#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */
+#else
+#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
+#endif
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+#ifdef USE_ACCURATE_ROUNDING
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#else
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
+#endif
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ IFAST_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS /* for DESCALE */
+ ISHIFT_TEMPS /* for IDESCALE */
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
+ wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
+ wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
+ wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
+ wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
+ wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
+ wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
+ wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
+ tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+
+ tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
+ tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
+ - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
+ z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
+ z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
+ z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/SrcShared/jpeg/jidctint.c b/SrcShared/jpeg/jidctint.c
new file mode 100644
index 0000000..a72b320
--- /dev/null
+++ b/SrcShared/jpeg/jidctint.c
@@ -0,0 +1,389 @@
+/*
+ * jidctint.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate INT32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result. In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+
+ tmp0 = (z2 + z3) << CONST_BITS;
+ tmp1 = (z2 - z3) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
+ tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) wsptr[7];
+ tmp1 = (INT32) wsptr[5];
+ tmp2 = (INT32) wsptr[3];
+ tmp3 = (INT32) wsptr[1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/SrcShared/jpeg/jidctred.c b/SrcShared/jpeg/jidctred.c
new file mode 100644
index 0000000..421f3c7
--- /dev/null
+++ b/SrcShared/jpeg/jidctred.c
@@ -0,0 +1,398 @@
+/*
+ * jidctred.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains inverse-DCT routines that produce reduced-size output:
+ * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
+ *
+ * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
+ * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step
+ * with an 8-to-4 step that produces the four averages of two adjacent outputs
+ * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
+ * These steps were derived by computing the corresponding values at the end
+ * of the normal LL&M code, then simplifying as much as possible.
+ *
+ * 1x1 is trivial: just take the DC coefficient divided by 8.
+ *
+ * See jidctint.c for additional comments.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling is the same as in jidctint.c. */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */
+#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */
+#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */
+#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */
+#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */
+#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */
+#else
+#define FIX_0_211164243 FIX(0.211164243)
+#define FIX_0_509795579 FIX(0.509795579)
+#define FIX_0_601344887 FIX(0.601344887)
+#define FIX_0_720959822 FIX(0.720959822)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_850430095 FIX(0.850430095)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_061594337 FIX(1.061594337)
+#define FIX_1_272758580 FIX(1.272758580)
+#define FIX_1_451774981 FIX(1.451774981)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_2_172734803 FIX(2.172734803)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_624509785 FIX(3.624509785)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result. In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 4x4 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE*4]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+ /* Don't bother to process column 4, because second pass won't use it */
+ if (ctr == DCTSIZE-4)
+ continue;
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
+ inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero; we need not examine term 4 for 4x4 output */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= (CONST_BITS+1);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+
+ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+ /* Final output stage */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
+ }
+
+ /* Pass 2: process 4 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
+
+ tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
+ + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[7];
+ z2 = (INT32) wsptr[5];
+ z3 = (INT32) wsptr[3];
+ z4 = (INT32) wsptr[1];
+
+ tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+
+ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 2x2 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp10, z1;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE*2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+ /* Don't bother to process columns 2,4,6 */
+ if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
+ continue;
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+
+ continue;
+ }
+
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 = z1 << (CONST_BITS+2);
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+ /* Final output stage */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
+ }
+
+ /* Pass 2: process 2 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 2; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
+ + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
+ + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
+ + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3+2)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3+2)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 1x1 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ int dcval;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* We hardly need an inverse DCT routine for this: just take the
+ * average pixel value, which is one-eighth of the DC coefficient.
+ */
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
+ dcval = (int) DESCALE((INT32) dcval, 3);
+
+ output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
+}
+
+#endif /* IDCT_SCALING_SUPPORTED */
diff --git a/SrcShared/jpeg/jinclude.h b/SrcShared/jpeg/jinclude.h
new file mode 100644
index 0000000..0a4f151
--- /dev/null
+++ b/SrcShared/jpeg/jinclude.h
@@ -0,0 +1,91 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file exists to provide a single place to fix any problems with
+ * including the wrong system include files. (Common problems are taken
+ * care of by the standard jconfig symbols, but on really weird systems
+ * you may have to edit this file.)
+ *
+ * NOTE: this file is NOT intended to be included by applications using the
+ * JPEG library. Most applications need only include jpeglib.h.
+ */
+
+
+/* Include auto-config file to find out which system include files we need. */
+
+#include "jconfig.h" /* auto configuration options */
+#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
+
+/*
+ * We need the NULL macro and size_t typedef.
+ * On an ANSI-conforming system it is sufficient to include <stddef.h>.
+ * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
+ * pull in <sys/types.h> as well.
+ * Note that the core JPEG library does not require <stdio.h>;
+ * only the default error handler and data source/destination modules do.
+ * But we must pull it in because of the references to FILE in jpeglib.h.
+ * You can remove those references if you want to compile without <stdio.h>.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+
+/*
+ * We need memory copying and zeroing functions, plus strncpy().
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * Some systems may declare memset and memcpy in <memory.h>.
+ *
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Change the casts in these macros if not!
+ */
+
+#ifdef NEED_BSD_STRINGS
+
+#include <strings.h>
+#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+
+#else /* not BSD, assume ANSI/SysV string lib */
+
+#include <string.h>
+#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof(). However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long. To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object) ((size_t) sizeof(object))
+
+/*
+ * The modules that use fread() and fwrite() always invoke them through
+ * these macros. On some systems you may need to twiddle the argument casts.
+ * CAUTION: argument order is different from underlying functions!
+ */
+
+#define JFREAD(file,buf,sizeofbuf) \
+ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf) \
+ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
diff --git a/SrcShared/jpeg/jmemmac.c b/SrcShared/jpeg/jmemmac.c
new file mode 100644
index 0000000..fb2dcf5
--- /dev/null
+++ b/SrcShared/jpeg/jmemmac.c
@@ -0,0 +1,383 @@
+#if 1
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#include "Platform.h" /* Platform_AllocateMemory */
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) Platform_AllocateMemory(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ Platform_DisposeMemory(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return max_bytes_needed;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ return 0; /* just set max_memory_to_use to 0 */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
+
+#else
+
+/*
+ * jmemmac.c
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * jmemmac.c provides an Apple Macintosh implementation of the system-
+ * dependent portion of the JPEG memory manager.
+ *
+ * If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the
+ * JPEG_INTERNALS part of jconfig.h.
+ *
+ * jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr
+ * instead of malloc and free. It accurately determines the amount of
+ * memory available by using CompactMem. Notice that if left to its
+ * own devices, this code can chew up all available space in the
+ * application's zone, with the exception of the rather small "slop"
+ * factor computed in jpeg_mem_available(). The application can ensure
+ * that more space is left over by reducing max_memory_to_use.
+ *
+ * Large images are swapped to disk using temporary files and System 7.0+'s
+ * temporary folder functionality.
+ *
+ * Note that jmemmac.c depends on two features of MacOS that were first
+ * introduced in System 7: FindFolder and the FSSpec-based calls.
+ * If your application uses jmemmac.c and is run under System 6 or earlier,
+ * and the jpeg library decides it needs a temporary file, it will abort,
+ * printing error messages about requiring System 7. (If no temporary files
+ * are created, it will run fine.)
+ *
+ * If you want to use jmemmac.c in an application that might be used with
+ * System 6 or earlier, then you should remove dependencies on FindFolder
+ * and the FSSpec calls. You will need to replace FindFolder with some
+ * other mechanism for finding a place to put temporary files, and you
+ * should replace the FSSpec calls with their HFS equivalents:
+ *
+ * FSpDelete -> HDelete
+ * FSpGetFInfo -> HGetFInfo
+ * FSpCreate -> HCreate
+ * FSpOpenDF -> HOpen *** Note: not HOpenDF ***
+ * FSMakeFSSpec -> (fill in spec by hand.)
+ *
+ * (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen,
+ * which is on all HFS macs. HOpenDF is a System 7 addition which avoids the
+ * ages-old problem of names starting with a period.)
+ *
+ * Contributed by Sam Bushell (jsam@iagu.on.net) and
+ * Dan Gildor (gyld@in-touch.com).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef USE_MAC_MEMMGR /* make sure user got configuration right */
+ You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */
+#endif
+
+#include <Memory.h> /* we use the MacOS memory manager */
+#include <Files.h> /* we use the MacOS File stuff */
+#include <Folders.h> /* we use the MacOS HFS stuff */
+#include <Script.h> /* for smSystemScript */
+#include <Gestalt.h> /* we use Gestalt to test for specific functionality */
+
+#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
+#define TEMP_FILE_NAME "JPG%03d.TMP"
+#endif
+
+static int next_file_num; /* to distinguish among several temp files */
+
+
+/*
+ * Memory allocation and freeing are controlled by the MacOS library
+ * routines NewPtr() and DisposePtr(), which allocate fixed-address
+ * storage. Unfortunately, the IJG library isn't smart enough to cope
+ * with relocatable storage.
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) NewPtr(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ DisposePtr((Ptr) object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: we include FAR keywords in the routine declarations simply for
+ * consistency with the rest of the IJG code; FAR should expand to empty
+ * on rational architectures like the Mac.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) NewPtr(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ DisposePtr((Ptr) object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ long limit = cinfo->mem->max_memory_to_use - already_allocated;
+ long slop, mem;
+
+ /* Don't ask for more than what application has told us we may use */
+ if (max_bytes_needed > limit && limit > 0)
+ max_bytes_needed = limit;
+ /* Find whether there's a big enough free block in the heap.
+ * CompactMem tries to create a contiguous block of the requested size,
+ * and then returns the size of the largest free block (which could be
+ * much more or much less than we asked for).
+ * We add some slop to ensure we don't use up all available memory.
+ */
+ slop = max_bytes_needed / 16 + 32768L;
+ mem = CompactMem(max_bytes_needed + slop) - slop;
+ if (mem < 0)
+ mem = 0; /* sigh, couldn't even get the slop */
+ /* Don't take more than the application says we can have */
+ if (mem > limit && limit > 0)
+ mem = limit;
+ return mem;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Backing store objects are only used when the value returned by
+ * jpeg_mem_available is less than the total space needed. You can dispense
+ * with these routines if you have plenty of virtual memory; see jmemnobs.c.
+ */
+
+
+METHODDEF(void)
+read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ long bytes = byte_count;
+ long retVal;
+
+ if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+
+ retVal = FSRead ( info->temp_file, &bytes,
+ (unsigned char *) buffer_address );
+ if ( retVal != noErr || bytes != byte_count )
+ ERREXIT(cinfo, JERR_TFILE_READ);
+}
+
+
+METHODDEF(void)
+write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ long bytes = byte_count;
+ long retVal;
+
+ if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+
+ retVal = FSWrite ( info->temp_file, &bytes,
+ (unsigned char *) buffer_address );
+ if ( retVal != noErr || bytes != byte_count )
+ ERREXIT(cinfo, JERR_TFILE_WRITE);
+}
+
+
+METHODDEF(void)
+close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ FSClose ( info->temp_file );
+ FSpDelete ( &(info->tempSpec) );
+}
+
+
+/*
+ * Initial opening of a backing-store object.
+ *
+ * This version uses FindFolder to find the Temporary Items folder,
+ * and puts the temporary file in there.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ short tmpRef, vRefNum;
+ long dirID;
+ FInfo finderInfo;
+ FSSpec theSpec;
+ Str255 fName;
+ OSErr osErr;
+ long gestaltResponse = 0;
+
+ /* Check that FSSpec calls are available. */
+ osErr = Gestalt( gestaltFSAttr, &gestaltResponse );
+ if ( ( osErr != noErr )
+ || !( gestaltResponse & (1<<gestaltHasFSSpecCalls) ) )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required");
+ /* TO DO: add a proper error message to jerror.h. */
+
+ /* Check that FindFolder is available. */
+ osErr = Gestalt( gestaltFindFolderAttr, &gestaltResponse );
+ if ( ( osErr != noErr )
+ || !( gestaltResponse & (1<<gestaltFindFolderPresent) ) )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required.");
+ /* TO DO: add a proper error message to jerror.h. */
+
+ osErr = FindFolder ( kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
+ &vRefNum, &dirID );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- temporary items folder unavailable");
+ /* TO DO: Try putting the temp files somewhere else. */
+
+ /* Keep generating file names till we find one that's not in use */
+ for (;;) {
+ next_file_num++; /* advance counter */
+
+ sprintf(info->temp_name, TEMP_FILE_NAME, next_file_num);
+ strcpy ( (Ptr)fName+1, info->temp_name );
+ *fName = strlen (info->temp_name);
+ osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec );
+
+ if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr )
+ break;
+ }
+
+ osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+
+ osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+
+ info->tempSpec = theSpec;
+
+ info->read_backing_store = read_backing_store;
+ info->write_backing_store = write_backing_store;
+ info->close_backing_store = close_backing_store;
+ TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ next_file_num = 0;
+
+ /* max_memory_to_use will be initialized to FreeMem()'s result;
+ * the calling application might later reduce it, for example
+ * to leave room to invoke multiple JPEG objects.
+ * Note that FreeMem returns the total number of free bytes;
+ * it may not be possible to allocate a single block of this size.
+ */
+ return FreeMem();
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
+
+#endif
diff --git a/SrcShared/jpeg/jmemmgr.c b/SrcShared/jpeg/jmemmgr.c
new file mode 100644
index 0000000..d801b32
--- /dev/null
+++ b/SrcShared/jpeg/jmemmgr.c
@@ -0,0 +1,1118 @@
+/*
+ * jmemmgr.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the JPEG system-independent memory management
+ * routines. This code is usable across a wide variety of machines; most
+ * of the system dependencies have been isolated in a separate file.
+ * The major functions provided here are:
+ * * pool-based allocation and freeing of memory;
+ * * policy decisions about how to divide available memory among the
+ * virtual arrays;
+ * * control logic for swapping virtual arrays between main memory and
+ * backing storage.
+ * The separate system-dependent file provides the actual backing-storage
+ * access code, and it contains the policy decision about how much total
+ * main memory to use.
+ * This file is system-dependent in the sense that some of its functions
+ * are unnecessary in some systems. For example, if there is enough virtual
+ * memory so that backing storage will never be used, much of the virtual
+ * array control logic could be removed. (Of course, if you have that much
+ * memory then you shouldn't care about a little bit of unused code...)
+ */
+
+#define JPEG_INTERNALS
+#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef NO_GETENV
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */
+extern char * getenv JPP((const char * name));
+#endif
+#endif
+
+
+/*
+ * Some important notes:
+ * The allocation routines provided here must never return NULL.
+ * They should exit to error_exit if unsuccessful.
+ *
+ * It's not a good idea to try to merge the sarray and barray routines,
+ * even though they are textually almost the same, because samples are
+ * usually stored as bytes while coefficients are shorts or ints. Thus,
+ * in machines where byte pointers have a different representation from
+ * word pointers, the resulting machine code could not be the same.
+ */
+
+
+/*
+ * Many machines require storage alignment: longs must start on 4-byte
+ * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc()
+ * always returns pointers that are multiples of the worst-case alignment
+ * requirement, and we had better do so too.
+ * There isn't any really portable way to determine the worst-case alignment
+ * requirement. This module assumes that the alignment requirement is
+ * multiples of sizeof(ALIGN_TYPE).
+ * By default, we define ALIGN_TYPE as double. This is necessary on some
+ * workstations (where doubles really do need 8-byte alignment) and will work
+ * fine on nearly everything. If your machine has lesser alignment needs,
+ * you can save a few bytes by making ALIGN_TYPE smaller.
+ * The only place I know of where this will NOT work is certain Macintosh
+ * 680x0 compilers that define double as a 10-byte IEEE extended float.
+ * Doing 10-byte alignment is counterproductive because longwords won't be
+ * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have
+ * such a compiler.
+ */
+
+#ifndef ALIGN_TYPE /* so can override from jconfig.h */
+#define ALIGN_TYPE double
+#endif
+
+
+/*
+ * We allocate objects from "pools", where each pool is gotten with a single
+ * request to jpeg_get_small() or jpeg_get_large(). There is no per-object
+ * overhead within a pool, except for alignment padding. Each pool has a
+ * header with a link to the next pool of the same class.
+ * Small and large pool headers are identical except that the latter's
+ * link pointer must be FAR on 80x86 machines.
+ * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
+ * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
+ * of the alignment requirement of ALIGN_TYPE.
+ */
+
+typedef union small_pool_struct * small_pool_ptr;
+
+typedef union small_pool_struct {
+ struct {
+ small_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} small_pool_hdr;
+
+typedef union large_pool_struct FAR * large_pool_ptr;
+
+typedef union large_pool_struct {
+ struct {
+ large_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} large_pool_hdr;
+
+
+/*
+ * Here is the full definition of a memory manager object.
+ */
+
+typedef struct {
+ struct jpeg_memory_mgr pub; /* public fields */
+
+ /* Each pool identifier (lifetime class) names a linked list of pools. */
+ small_pool_ptr small_list[JPOOL_NUMPOOLS];
+ large_pool_ptr large_list[JPOOL_NUMPOOLS];
+
+ /* Since we only have one lifetime class of virtual arrays, only one
+ * linked list is necessary (for each datatype). Note that the virtual
+ * array control blocks being linked together are actually stored somewhere
+ * in the small-pool list.
+ */
+ jvirt_sarray_ptr virt_sarray_list;
+ jvirt_barray_ptr virt_barray_list;
+
+ /* This counts total space obtained from jpeg_get_small/large */
+ long total_space_allocated;
+
+ /* alloc_sarray and alloc_barray set this value for use by virtual
+ * array routines.
+ */
+ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
+} my_memory_mgr;
+
+typedef my_memory_mgr * my_mem_ptr;
+
+
+/*
+ * The control blocks for virtual arrays.
+ * Note that these blocks are allocated in the "small" pool area.
+ * System-dependent info for the associated backing store (if any) is hidden
+ * inside the backing_store_info struct.
+ */
+
+struct jvirt_sarray_control {
+ JSAMPARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_sarray_ptr next; /* link to next virtual sarray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+struct jvirt_barray_control {
+ JBLOCKARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_barray_ptr next; /* link to next virtual barray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+
+#ifdef MEM_STATS /* optional extra stuff for statistics */
+
+LOCAL(void)
+print_mem_stats (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+
+ /* Since this is only a debugging stub, we can cheat a little by using
+ * fprintf directly rather than going through the trace message code.
+ * This is helpful because message parm array can't handle longs.
+ */
+ fprintf(stderr, "Freeing pool %d, total space = %ld\n",
+ pool_id, mem->total_space_allocated);
+
+ for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
+ lhdr_ptr = lhdr_ptr->hdr.next) {
+ fprintf(stderr, " Large chunk used %ld\n",
+ (long) lhdr_ptr->hdr.bytes_used);
+ }
+
+ for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
+ shdr_ptr = shdr_ptr->hdr.next) {
+ fprintf(stderr, " Small chunk used %ld free %ld\n",
+ (long) shdr_ptr->hdr.bytes_used,
+ (long) shdr_ptr->hdr.bytes_left);
+ }
+}
+
+#endif /* MEM_STATS */
+
+
+LOCAL(void)
+out_of_memory (j_common_ptr cinfo, int which)
+/* Report an out-of-memory error and stop execution */
+/* If we compiled MEM_STATS support, report alloc requests before dying */
+{
+#ifdef MEM_STATS
+ cinfo->err->trace_level = 2; /* force self_destruct to report stats */
+#endif
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
+}
+
+
+/*
+ * Allocation of "small" objects.
+ *
+ * For these, we use pooled storage. When a new pool must be created,
+ * we try to get enough space for the current request plus a "slop" factor,
+ * where the slop will be the amount of leftover space in the new pool.
+ * The speed vs. space tradeoff is largely determined by the slop values.
+ * A different slop value is provided for each pool class (lifetime),
+ * and we also distinguish the first pool of a class from later ones.
+ * NOTE: the values given work fairly well on both 16- and 32-bit-int
+ * machines, but may be too small if longs are 64 bits or more.
+ */
+
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 1600, /* first PERMANENT pool */
+ 16000 /* first IMAGE pool */
+};
+
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 0, /* additional PERMANENT pools */
+ 5000 /* additional IMAGE pools */
+};
+
+#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
+
+
+METHODDEF(void *)
+alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "small" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr hdr_ptr, prev_hdr_ptr;
+ char * data_ptr;
+ size_t odd_bytes, min_request, slop;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
+ out_of_memory(cinfo, 1); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* See if space is available in any existing pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+ prev_hdr_ptr = NULL;
+ hdr_ptr = mem->small_list[pool_id];
+ while (hdr_ptr != NULL) {
+ if (hdr_ptr->hdr.bytes_left >= sizeofobject)
+ break; /* found pool with enough space */
+ prev_hdr_ptr = hdr_ptr;
+ hdr_ptr = hdr_ptr->hdr.next;
+ }
+
+ /* Time to make a new pool? */
+ if (hdr_ptr == NULL) {
+ /* min_request is what we need now, slop is what will be leftover */
+ min_request = sizeofobject + SIZEOF(small_pool_hdr);
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ slop = first_pool_slop[pool_id];
+ else
+ slop = extra_pool_slop[pool_id];
+ /* Don't ask for more than MAX_ALLOC_CHUNK */
+ if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
+ slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+ /* Try to get space, if fail reduce slop and try again */
+ for (;;) {
+ hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+ if (hdr_ptr != NULL)
+ break;
+ slop /= 2;
+ if (slop < MIN_SLOP) /* give up when it gets real small */
+ out_of_memory(cinfo, 2); /* jpeg_get_small failed */
+ }
+ mem->total_space_allocated += min_request + slop;
+ /* Success, initialize the new pool header and add to end of list */
+ hdr_ptr->hdr.next = NULL;
+ hdr_ptr->hdr.bytes_used = 0;
+ hdr_ptr->hdr.bytes_left = sizeofobject + slop;
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ mem->small_list[pool_id] = hdr_ptr;
+ else
+ prev_hdr_ptr->hdr.next = hdr_ptr;
+ }
+
+ /* OK, allocate the object from the current pool */
+ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
+ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
+ hdr_ptr->hdr.bytes_used += sizeofobject;
+ hdr_ptr->hdr.bytes_left -= sizeofobject;
+
+ return (void *) data_ptr;
+}
+
+
+/*
+ * Allocation of "large" objects.
+ *
+ * The external semantics of these are the same as "small" objects,
+ * except that FAR pointers are used on 80x86. However the pool
+ * management heuristics are quite different. We assume that each
+ * request is large enough that it may as well be passed directly to
+ * jpeg_get_large; the pool management just links everything together
+ * so that we can free it all on demand.
+ * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
+ * structures. The routines that create these structures (see below)
+ * deliberately bunch rows together to ensure a large request size.
+ */
+
+METHODDEF(void FAR *)
+alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "large" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ large_pool_ptr hdr_ptr;
+ size_t odd_bytes;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
+ out_of_memory(cinfo, 3); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* Always make a new pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
+ SIZEOF(large_pool_hdr));
+ if (hdr_ptr == NULL)
+ out_of_memory(cinfo, 4); /* jpeg_get_large failed */
+ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
+
+ /* Success, initialize the new pool header and add to list */
+ hdr_ptr->hdr.next = mem->large_list[pool_id];
+ /* We maintain space counts in each pool header for statistical purposes,
+ * even though they are not needed for allocation.
+ */
+ hdr_ptr->hdr.bytes_used = sizeofobject;
+ hdr_ptr->hdr.bytes_left = 0;
+ mem->large_list[pool_id] = hdr_ptr;
+
+ return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */
+}
+
+
+/*
+ * Creation of 2-D sample arrays.
+ * The pointers are in near heap, the samples themselves in FAR heap.
+ *
+ * To minimize allocation overhead and to allow I/O of large contiguous
+ * blocks, we allocate the sample rows in groups of as many rows as possible
+ * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
+ * NB: the virtual array control routines, later in this file, know about
+ * this chunking of rows. The rowsperchunk value is left in the mem manager
+ * object so that it can be saved away if this sarray is the workspace for
+ * a virtual array.
+ */
+
+METHODDEF(JSAMPARRAY)
+alloc_sarray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow, JDIMENSION numrows)
+/* Allocate a 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JSAMPARRAY result;
+ JSAMPROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) samplesperrow * SIZEOF(JSAMPLE));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JSAMPROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
+ * SIZEOF(JSAMPLE)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += samplesperrow;
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * Creation of 2-D coefficient-block arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JBLOCKARRAY)
+alloc_barray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow, JDIMENSION numrows)
+/* Allocate a 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JBLOCKARRAY result;
+ JBLOCKROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) blocksperrow * SIZEOF(JBLOCK));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JBLOCKROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
+ * SIZEOF(JBLOCK)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += blocksperrow;
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * About virtual array management:
+ *
+ * The above "normal" array routines are only used to allocate strip buffers
+ * (as wide as the image, but just a few rows high). Full-image-sized buffers
+ * are handled as "virtual" arrays. The array is still accessed a strip at a
+ * time, but the memory manager must save the whole array for repeated
+ * accesses. The intended implementation is that there is a strip buffer in
+ * memory (as high as is possible given the desired memory limit), plus a
+ * backing file that holds the rest of the array.
+ *
+ * The request_virt_array routines are told the total size of the image and
+ * the maximum number of rows that will be accessed at once. The in-memory
+ * buffer must be at least as large as the maxaccess value.
+ *
+ * The request routines create control blocks but not the in-memory buffers.
+ * That is postponed until realize_virt_arrays is called. At that time the
+ * total amount of space needed is known (approximately, anyway), so free
+ * memory can be divided up fairly.
+ *
+ * The access_virt_array routines are responsible for making a specific strip
+ * area accessible (after reading or writing the backing file, if necessary).
+ * Note that the access routines are told whether the caller intends to modify
+ * the accessed strip; during a read-only pass this saves having to rewrite
+ * data to disk. The access routines are also responsible for pre-zeroing
+ * any newly accessed rows, if pre-zeroing was requested.
+ *
+ * In current usage, the access requests are usually for nonoverlapping
+ * strips; that is, successive access start_row numbers differ by exactly
+ * num_rows = maxaccess. This means we can get good performance with simple
+ * buffer dump/reload logic, by making the in-memory buffer be a multiple
+ * of the access height; then there will never be accesses across bufferload
+ * boundaries. The code will still work with overlapping access requests,
+ * but it doesn't handle bufferload overlaps very efficiently.
+ */
+
+
+METHODDEF(jvirt_sarray_ptr)
+request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION samplesperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_sarray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_sarray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->samplesperrow = samplesperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
+ mem->virt_sarray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(jvirt_barray_ptr)
+request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION blocksperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_barray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_barray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->blocksperrow = blocksperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_barray_list; /* add to list of virtual arrays */
+ mem->virt_barray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(void)
+realize_virt_arrays (j_common_ptr cinfo)
+/* Allocate the in-memory buffers for any unrealized virtual arrays */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ long space_per_minheight, maximum_space, avail_mem;
+ long minheights, max_minheights;
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ /* Compute the minimum space needed (maxaccess rows in each buffer)
+ * and the maximum space needed (full image height in each buffer).
+ * These may be of use to the system-dependent jpeg_mem_available routine.
+ */
+ space_per_minheight = 0;
+ maximum_space = 0;
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) sptr->maxaccess *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ maximum_space += (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ }
+ }
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) bptr->maxaccess *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ maximum_space += (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ }
+ }
+
+ if (space_per_minheight <= 0)
+ return; /* no unrealized arrays, no work */
+
+ /* Determine amount of memory to actually use; this is system-dependent. */
+ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
+ mem->total_space_allocated);
+
+ /* If the maximum space needed is available, make all the buffers full
+ * height; otherwise parcel it out with the same number of minheights
+ * in each buffer.
+ */
+ if (avail_mem >= maximum_space)
+ max_minheights = 1000000000L;
+ else {
+ max_minheights = avail_mem / space_per_minheight;
+ /* If there doesn't seem to be enough space, try to get the minimum
+ * anyway. This allows a "stub" implementation of jpeg_mem_available().
+ */
+ if (max_minheights <= 0)
+ max_minheights = 1;
+ }
+
+ /* Allocate the in-memory buffers and initialize backing store as needed. */
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ sptr->rows_in_mem = sptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & sptr->b_s_info,
+ (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow *
+ (long) SIZEOF(JSAMPLE));
+ sptr->b_s_open = TRUE;
+ }
+ sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
+ sptr->samplesperrow, sptr->rows_in_mem);
+ sptr->rowsperchunk = mem->last_rowsperchunk;
+ sptr->cur_start_row = 0;
+ sptr->first_undef_row = 0;
+ sptr->dirty = FALSE;
+ }
+ }
+
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ bptr->rows_in_mem = bptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & bptr->b_s_info,
+ (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow *
+ (long) SIZEOF(JBLOCK));
+ bptr->b_s_open = TRUE;
+ }
+ bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
+ bptr->blocksperrow, bptr->rows_in_mem);
+ bptr->rowsperchunk = mem->last_rowsperchunk;
+ bptr->cur_start_row = 0;
+ bptr->first_undef_row = 0;
+ bptr->dirty = FALSE;
+ }
+ }
+}
+
+
+LOCAL(void)
+do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual sample array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+LOCAL(void)
+do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual coefficient-block array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+METHODDEF(JSAMPARRAY)
+access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual sample array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_sarray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_sarray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+METHODDEF(JBLOCKARRAY)
+access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual block array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_barray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_barray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+/*
+ * Release all objects belonging to a specified pool.
+ */
+
+METHODDEF(void)
+free_pool (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+ size_t space_freed;
+
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+#ifdef MEM_STATS
+ if (cinfo->err->trace_level > 1)
+ print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
+#endif
+
+ /* If freeing IMAGE pool, close any virtual arrays first */
+ if (pool_id == JPOOL_IMAGE) {
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->b_s_open) { /* there may be no backing store */
+ sptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+ }
+ }
+ mem->virt_sarray_list = NULL;
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->b_s_open) { /* there may be no backing store */
+ bptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+ }
+ }
+ mem->virt_barray_list = NULL;
+ }
+
+ /* Release large objects */
+ lhdr_ptr = mem->large_list[pool_id];
+ mem->large_list[pool_id] = NULL;
+
+ while (lhdr_ptr != NULL) {
+ large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
+ space_freed = lhdr_ptr->hdr.bytes_used +
+ lhdr_ptr->hdr.bytes_left +
+ SIZEOF(large_pool_hdr);
+ jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
+ mem->total_space_allocated -= space_freed;
+ lhdr_ptr = next_lhdr_ptr;
+ }
+
+ /* Release small objects */
+ shdr_ptr = mem->small_list[pool_id];
+ mem->small_list[pool_id] = NULL;
+
+ while (shdr_ptr != NULL) {
+ small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
+ space_freed = shdr_ptr->hdr.bytes_used +
+ shdr_ptr->hdr.bytes_left +
+ SIZEOF(small_pool_hdr);
+ jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+ mem->total_space_allocated -= space_freed;
+ shdr_ptr = next_shdr_ptr;
+ }
+}
+
+
+/*
+ * Close up shop entirely.
+ * Note that this cannot be called unless cinfo->mem is non-NULL.
+ */
+
+METHODDEF(void)
+self_destruct (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Close all backing store, release all memory.
+ * Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ free_pool(cinfo, pool);
+ }
+
+ /* Release the memory manager control block too. */
+ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
+ cinfo->mem = NULL; /* ensures I will be called only once */
+
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+}
+
+
+/*
+ * Memory manager initialization.
+ * When this is called, only the error manager pointer is valid in cinfo!
+ */
+
+GLOBAL(void)
+jinit_memory_mgr (j_common_ptr cinfo)
+{
+ my_mem_ptr mem;
+ long max_to_use;
+ int pool;
+ size_t test_mac;
+
+ cinfo->mem = NULL; /* for safety if init fails */
+
+ /* Check for configuration errors.
+ * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
+ * doesn't reflect any real hardware alignment requirement.
+ * The test is a little tricky: for X>0, X and X-1 have no one-bits
+ * in common if and only if X is a power of 2, ie has only one one-bit.
+ * Some compilers may give an "unreachable code" warning here; ignore it.
+ */
+ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
+ /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
+ * a multiple of SIZEOF(ALIGN_TYPE).
+ * Again, an "unreachable code" warning may be ignored here.
+ * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
+ */
+ test_mac = (size_t) MAX_ALLOC_CHUNK;
+ if ((long) test_mac != MAX_ALLOC_CHUNK ||
+ (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+
+ max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
+
+ /* Attempt to allocate memory manager's control block */
+ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
+
+ if (mem == NULL) {
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
+ }
+
+ /* OK, fill in the method pointers */
+ mem->pub.alloc_small = alloc_small;
+ mem->pub.alloc_large = alloc_large;
+ mem->pub.alloc_sarray = alloc_sarray;
+ mem->pub.alloc_barray = alloc_barray;
+ mem->pub.request_virt_sarray = request_virt_sarray;
+ mem->pub.request_virt_barray = request_virt_barray;
+ mem->pub.realize_virt_arrays = realize_virt_arrays;
+ mem->pub.access_virt_sarray = access_virt_sarray;
+ mem->pub.access_virt_barray = access_virt_barray;
+ mem->pub.free_pool = free_pool;
+ mem->pub.self_destruct = self_destruct;
+
+ /* Make MAX_ALLOC_CHUNK accessible to other modules */
+ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
+
+ /* Initialize working state */
+ mem->pub.max_memory_to_use = max_to_use;
+
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ mem->small_list[pool] = NULL;
+ mem->large_list[pool] = NULL;
+ }
+ mem->virt_sarray_list = NULL;
+ mem->virt_barray_list = NULL;
+
+ mem->total_space_allocated = SIZEOF(my_memory_mgr);
+
+ /* Declare ourselves open for business */
+ cinfo->mem = & mem->pub;
+
+ /* Check for an environment variable JPEGMEM; if found, override the
+ * default max_memory setting from jpeg_mem_init. Note that the
+ * surrounding application may again override this value.
+ * If your system doesn't support getenv(), define NO_GETENV to disable
+ * this feature.
+ */
+#ifndef NO_GETENV
+ { char * memenv;
+
+ if ((memenv = getenv("JPEGMEM")) != NULL) {
+ char ch = 'x';
+
+ if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
+ if (ch == 'm' || ch == 'M')
+ max_to_use *= 1000L;
+ mem->pub.max_memory_to_use = max_to_use * 1000L;
+ }
+ }
+ }
+#endif
+
+}
diff --git a/SrcShared/jpeg/jmemnobs.c b/SrcShared/jpeg/jmemnobs.c
new file mode 100644
index 0000000..eb8c337
--- /dev/null
+++ b/SrcShared/jpeg/jmemnobs.c
@@ -0,0 +1,109 @@
+/*
+ * jmemnobs.c
+ *
+ * Copyright (C) 1992-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a really simple implementation of the system-
+ * dependent portion of the JPEG memory manager. This implementation
+ * assumes that no backing-store files are needed: all required space
+ * can be obtained from malloc().
+ * This is very portable in the sense that it'll compile on almost anything,
+ * but you'd better have lots of main memory (or virtual memory) if you want
+ * to process big images.
+ * Note that the max_memory_to_use option is ignored by this implementation.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return max_bytes_needed;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ return 0; /* just set max_memory_to_use to 0 */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/SrcShared/jpeg/jmemsys.h b/SrcShared/jpeg/jmemsys.h
new file mode 100644
index 0000000..6c3c6d3
--- /dev/null
+++ b/SrcShared/jpeg/jmemsys.h
@@ -0,0 +1,198 @@
+/*
+ * jmemsys.h
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file defines the interface between the system-independent
+ * and system-dependent portions of the JPEG memory manager. No other
+ * modules need include it. (The system-independent portion is jmemmgr.c;
+ * there are several different versions of the system-dependent portion.)
+ *
+ * This file works as-is for the system-dependent memory managers supplied
+ * in the IJG distribution. You may need to modify it if you write a
+ * custom memory manager. If system-dependent changes are needed in
+ * this file, the best method is to #ifdef them based on a configuration
+ * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR
+ * and USE_MAC_MEMMGR.
+ */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_get_small jGetSmall
+#define jpeg_free_small jFreeSmall
+#define jpeg_get_large jGetLarge
+#define jpeg_free_large jFreeLarge
+#define jpeg_mem_available jMemAvail
+#define jpeg_open_backing_store jOpenBackStore
+#define jpeg_mem_init jMemInit
+#define jpeg_mem_term jMemTerm
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * These two functions are used to allocate and release small chunks of
+ * memory. (Typically the total amount requested through jpeg_get_small is
+ * no more than 20K or so; this will be requested in chunks of a few K each.)
+ * Behavior should be the same as for the standard library functions malloc
+ * and free; in particular, jpeg_get_small must return NULL on failure.
+ * On most systems, these ARE malloc and free. jpeg_free_small is passed the
+ * size of the object being freed, just in case it's needed.
+ * On an 80x86 machine using small-data memory model, these manage near heap.
+ */
+
+EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
+EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
+ size_t sizeofobject));
+
+/*
+ * These two functions are used to allocate and release large chunks of
+ * memory (up to the total free space designated by jpeg_mem_available).
+ * The interface is the same as above, except that on an 80x86 machine,
+ * far pointers are used. On most other machines these are identical to
+ * the jpeg_get/free_small routines; but we keep them separate anyway,
+ * in case a different allocation strategy is desirable for large chunks.
+ */
+
+EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
+ size_t sizeofobject));
+EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
+ size_t sizeofobject));
+
+/*
+ * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
+ * be requested in a single call to jpeg_get_large (and jpeg_get_small for that
+ * matter, but that case should never come into play). This macro is needed
+ * to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
+ * On those machines, we expect that jconfig.h will provide a proper value.
+ * On machines with 32-bit flat address spaces, any large constant may be used.
+ *
+ * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
+ * size_t and will be a multiple of sizeof(align_type).
+ */
+
+#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
+#define MAX_ALLOC_CHUNK 1000000000L
+#endif
+
+/*
+ * This routine computes the total space still available for allocation by
+ * jpeg_get_large. If more space than this is needed, backing store will be
+ * used. NOTE: any memory already allocated must not be counted.
+ *
+ * There is a minimum space requirement, corresponding to the minimum
+ * feasible buffer sizes; jmemmgr.c will request that much space even if
+ * jpeg_mem_available returns zero. The maximum space needed, enough to hold
+ * all working storage in memory, is also passed in case it is useful.
+ * Finally, the total space already allocated is passed. If no better
+ * method is available, cinfo->mem->max_memory_to_use - already_allocated
+ * is often a suitable calculation.
+ *
+ * It is OK for jpeg_mem_available to underestimate the space available
+ * (that'll just lead to more backing-store access than is really necessary).
+ * However, an overestimate will lead to failure. Hence it's wise to subtract
+ * a slop factor from the true available space. 5% should be enough.
+ *
+ * On machines with lots of virtual memory, any large constant may be returned.
+ * Conversely, zero may be returned to always use the minimum amount of memory.
+ */
+
+EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
+ long min_bytes_needed,
+ long max_bytes_needed,
+ long already_allocated));
+
+
+/*
+ * This structure holds whatever state is needed to access a single
+ * backing-store object. The read/write/close method pointers are called
+ * by jmemmgr.c to manipulate the backing-store object; all other fields
+ * are private to the system-dependent backing store routines.
+ */
+
+#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
+
+
+#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
+
+typedef unsigned short XMSH; /* type of extended-memory handles */
+typedef unsigned short EMSH; /* type of expanded-memory handles */
+
+typedef union {
+ short file_handle; /* DOS file handle if it's a temp file */
+ XMSH xms_handle; /* handle if it's a chunk of XMS */
+ EMSH ems_handle; /* handle if it's a chunk of EMS */
+} handle_union;
+
+#endif /* USE_MSDOS_MEMMGR */
+
+#ifdef USE_MAC_MEMMGR /* Mac-specific junk */
+#include <Files.h>
+#endif /* USE_MAC_MEMMGR */
+
+
+typedef struct backing_store_struct * backing_store_ptr;
+
+typedef struct backing_store_struct {
+ /* Methods for reading/writing/closing this backing-store object */
+ JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info));
+
+ /* Private fields for system-dependent backing-store management */
+#ifdef USE_MSDOS_MEMMGR
+ /* For the MS-DOS manager (jmemdos.c), we need: */
+ handle_union handle; /* reference to backing-store storage object */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+#ifdef USE_MAC_MEMMGR
+ /* For the Mac manager (jmemmac.c), we need: */
+ short temp_file; /* file reference number to temp file */
+ FSSpec tempSpec; /* the FSSpec for the temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+ /* For a typical implementation with temp files, we need: */
+ FILE * temp_file; /* stdio reference to temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
+#endif
+#endif
+} backing_store_info;
+
+
+/*
+ * Initial opening of a backing-store object. This must fill in the
+ * read/write/close pointers in the object. The read/write routines
+ * may take an error exit if the specified maximum file size is exceeded.
+ * (If jpeg_mem_available always returns a large value, this routine can
+ * just take an error exit.)
+ */
+
+EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
+ backing_store_ptr info,
+ long total_bytes_needed));
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. jpeg_mem_init will be called before anything is
+ * allocated (and, therefore, nothing in cinfo is of use except the error
+ * manager pointer). It should return a suitable default value for
+ * max_memory_to_use; this may subsequently be overridden by the surrounding
+ * application. (Note that max_memory_to_use is only important if
+ * jpeg_mem_available chooses to consult it ... no one else will.)
+ * jpeg_mem_term may assume that all requested memory has been freed and that
+ * all opened backing-store objects have been closed.
+ */
+
+EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
diff --git a/SrcShared/jpeg/jmorecfg.h b/SrcShared/jpeg/jmorecfg.h
new file mode 100644
index 0000000..54a7d1c
--- /dev/null
+++ b/SrcShared/jpeg/jmorecfg.h
@@ -0,0 +1,363 @@
+/*
+ * jmorecfg.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains additional configuration options that customize the
+ * JPEG software for special applications or support machine-dependent
+ * optimizations. Most users will not need to touch this file.
+ */
+
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ * 8 for 8-bit sample values (the usual setting)
+ * 12 for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
+
+
+/*
+ * Maximum number of components (color channels) allowed in JPEG image.
+ * To meet the letter of the JPEG spec, set this to 255. However, darn
+ * few applications need more than 4 channels (maybe 5 for CMYK + alpha
+ * mask). We recommend 10 as a reasonable compromise; use 4 if you are
+ * really short on memory. (Each allowed component costs a hundred or so
+ * bytes of storage, whether actually used in an image or not.)
+ */
+
+#define MAX_COMPONENTS 10 /* maximum number of image components */
+
+
+/*
+ * Basic data types.
+ * You may need to change these if you have a machine with unusual data
+ * type sizes; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* Representation of a single sample (pixel element value).
+ * We frequently allocate large arrays of these, so it's important to keep
+ * them small. But if you have memory to burn and access to char or short
+ * arrays is very slow on your hardware, you might want to change these.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JSAMPLE;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJSAMPLE(value) ((int) (value))
+#else
+#define GETJSAMPLE(value) ((int) (value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE 255
+#define CENTERJSAMPLE 128
+
+#endif /* BITS_IN_JSAMPLE == 8 */
+
+
+#if BITS_IN_JSAMPLE == 12
+/* JSAMPLE should be the smallest type that will hold the values 0..4095.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 4095
+#define CENTERJSAMPLE 2048
+
+#endif /* BITS_IN_JSAMPLE == 12 */
+
+
+/* Representation of a DCT frequency coefficient.
+ * This should be a signed value of at least 16 bits; "short" is usually OK.
+ * Again, we allocate large arrays of these, but you can change to int
+ * if you have memory to burn and "short" is really slow.
+ */
+
+typedef short JCOEF;
+
+
+/* Compressed datastreams are represented as arrays of JOCTET.
+ * These must be EXACTLY 8 bits wide, at least once they are written to
+ * external storage. Note that when using the stdio data source/destination
+ * managers, this is also the data type passed to fread/fwrite.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JOCTET;
+#define GETJOCTET(value) (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JOCTET;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJOCTET(value) (value)
+#else
+#define GETJOCTET(value) ((value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+/* These typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE. (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
+typedef short INT16;
+#endif
+
+/* INT32 must hold at least signed 32-bit values. */
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
+typedef long INT32;
+#endif
+
+/* Datatype used for image dimensions. The JPEG standard only supports
+ * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
+ * "unsigned int" is sufficient on all machines. However, if you need to
+ * handle larger images and you don't mind deviating from the spec, you
+ * can change this datatype.
+ */
+
+typedef unsigned int JDIMENSION;
+
+#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
+
+
+/* These macros are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions;
+ * in particular, you'll need to do that to make the library a Windows DLL.
+ * Another application is to make all functions global for use with debuggers
+ * or code profilers that require it.
+ */
+
+/* a function called through method pointers: */
+#define METHODDEF(type) static type
+/* a function used only in its module: */
+#define LOCAL(type) static type
+/* a function referenced thru EXTERNs: */
+#define GLOBAL(type) type
+/* a reference to a GLOBAL function: */
+#define EXTERN(type) extern type
+
+
+/* This macro is used to declare a "method", that is, a function pointer.
+ * We want to supply prototype parameters if the compiler can cope.
+ * Note that the arglist parameter must be parenthesized!
+ * Again, you can customize this if you need special linkage keywords.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+#else
+#define JMETHOD(type,methodname,arglist) type (*methodname) ()
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines. Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed. In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifdef NEED_FAR_POINTERS
+#define FAR far
+#else
+#define FAR
+#endif
+
+
+/*
+ * On a few systems, type boolean and/or its values FALSE, TRUE may appear
+ * in standard header files. Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
+ */
+
+#ifndef HAVE_BOOLEAN
+typedef int boolean;
+#endif
+#ifndef FALSE /* in case these macros already exist */
+#define FALSE 0 /* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+
+/*
+ * The remaining options affect code selection within the JPEG library,
+ * but they don't need to be visible to most applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+#define JPEG_INTERNAL_OPTIONS
+#endif
+
+#ifdef JPEG_INTERNAL_OPTIONS
+
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * library. Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
+
+/* Capability options common to encoder and decoder: */
+
+#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
+#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
+#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
+
+/* Encoder capability options: */
+
+#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
+/* Note: if you selected 12-bit data precision, it is dangerous to turn off
+ * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
+ * precision, so jchuff.c normally uses entropy optimization to compute
+ * usable tables for higher precision. If you don't want to do optimization,
+ * you'll have to supply different default Huffman tables.
+ * The exact same statements apply for progressive JPEG: the default tables
+ * don't work for progressive mode. (This may get fixed, however.)
+ */
+#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
+
+/* Decoder capability options: */
+
+#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
+#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
+#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
+#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
+#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
+#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
+#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Ordering of RGB data in scanlines passed to or from the application.
+ * If your application wants to deal with data in the order B,G,R, just
+ * change these macros. You can also deal with formats such as R,G,B,X
+ * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
+ * the offsets will also change the order in which colormap data is organized.
+ * RESTRICTIONS:
+ * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
+ * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
+ * useful if you are using JPEG color spaces other than YCbCr or grayscale.
+ * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
+ * is not 3 (they don't understand about dummy color components!). So you
+ * can't use color quantization if you change that value.
+ */
+
+#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
+#define RGB_GREEN 1 /* Offset of Green */
+#define RGB_BLUE 2 /* Offset of Blue */
+#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
+
+
+/* Definitions for speed-related optimizations. */
+
+
+/* If your compiler supports inline functions, define INLINE
+ * as the inline keyword; otherwise define it as empty.
+ */
+
+#ifndef INLINE
+#ifdef __GNUC__ /* for instance, GNU C knows about inline */
+#define INLINE __inline__
+#endif
+#ifndef INLINE
+#define INLINE /* default is to define it as empty */
+#endif
+#endif
+
+
+/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
+ * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
+ * as short on such a machine. MULTIPLIER must be at least 16 bits wide.
+ */
+
+#ifndef MULTIPLIER
+#define MULTIPLIER int /* type for fastest integer multiply */
+#endif
+
+
+/* FAST_FLOAT should be either float or double, whichever is done faster
+ * by your compiler. (Note that this type is only used in the floating point
+ * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
+ * Typically, float is faster in ANSI C compilers, while double is faster in
+ * pre-ANSI compilers (because they insist on converting to double anyway).
+ * The code below therefore chooses float if we have ANSI-style prototypes.
+ */
+
+#ifndef FAST_FLOAT
+#ifdef HAVE_PROTOTYPES
+#define FAST_FLOAT float
+#else
+#define FAST_FLOAT double
+#endif
+#endif
+
+#endif /* JPEG_INTERNAL_OPTIONS */
diff --git a/SrcShared/jpeg/jpegint.h b/SrcShared/jpeg/jpegint.h
new file mode 100644
index 0000000..95b00d4
--- /dev/null
+++ b/SrcShared/jpeg/jpegint.h
@@ -0,0 +1,392 @@
+/*
+ * jpegint.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides common declarations for the various JPEG modules.
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+
+/* Declarations for both compression & decompression */
+
+typedef enum { /* Operating modes for buffer controllers */
+ JBUF_PASS_THRU, /* Plain stripwise operation */
+ /* Remaining modes require a full-image buffer to have been created */
+ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
+ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
+ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
+} J_BUF_MODE;
+
+/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+
+
+/* Declarations for compression modules */
+
+/* Master control module */
+struct jpeg_comp_master {
+ JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean call_pass_startup; /* True if pass_startup must be called */
+ boolean is_last_pass; /* True during last pass */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_c_main_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail));
+};
+
+/* Compression preprocessing (downsampling input buffer control) */
+struct jpeg_c_prep_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf,
+ JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_c_coef_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf));
+};
+
+/* Colorspace conversion */
+struct jpeg_color_converter {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows));
+};
+
+/* Downsampling */
+struct jpeg_downsampler {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, downsample, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Forward DCT (also controls coefficient quantization) */
+struct jpeg_forward_dct {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ /* perhaps this should be an array??? */
+ JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
+ jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks));
+};
+
+/* Entropy encoding */
+struct jpeg_entropy_encoder {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
+ JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+};
+
+/* Marker writing */
+struct jpeg_marker_writer {
+ JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
+ JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
+ /* These routines are exported to allow insertion of extra markers */
+ /* Probably only COM and APPn markers should be written this way */
+ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
+ unsigned int datalen));
+ JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
+};
+
+
+/* Declarations for decompression modules */
+
+/* Master control module */
+struct jpeg_decomp_master {
+ JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
+};
+
+/* Input control module */
+struct jpeg_input_controller {
+ JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
+ JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean has_multiple_scans; /* True if file has multiple scans */
+ boolean eoi_reached; /* True when EOI has been consumed */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_d_main_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_d_coef_controller {
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf));
+ /* Pointer to array of coefficient virtual arrays, or NULL if none */
+ jvirt_barray_ptr *coef_arrays;
+};
+
+/* Decompression postprocessing (color quantization buffer control) */
+struct jpeg_d_post_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Marker reading & parsing */
+struct jpeg_marker_reader {
+ JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
+ /* Read markers until SOS or EOI.
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+ JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
+ /* Read a restart marker --- exported for use by entropy decoder only */
+ jpeg_marker_parser_method read_restart_marker;
+
+ /* State of marker reader --- nominally internal, but applications
+ * supplying COM or APPn handlers might like to know the state.
+ */
+ boolean saw_SOI; /* found SOI? */
+ boolean saw_SOF; /* found SOF? */
+ int next_restart_num; /* next restart number expected (0-7) */
+ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
+};
+
+/* Entropy decoding */
+struct jpeg_entropy_decoder {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+ /* This is here to share code between baseline and progressive decoders; */
+ /* other modules probably should not use it */
+ boolean insufficient_data; /* set TRUE after emitting warning */
+};
+
+/* Inverse DCT (also performs dequantization) */
+typedef JMETHOD(void, inverse_DCT_method_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col));
+
+struct jpeg_inverse_dct {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ /* It is useful to allow each component to have a separate IDCT method. */
+ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+};
+
+/* Upsampling (note that upsampler must also call color converter) */
+struct jpeg_upsampler {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Colorspace conversion */
+struct jpeg_color_deconverter {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows));
+};
+
+/* Color quantization or color precision reduction */
+struct jpeg_color_quantizer {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
+ JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+ int num_rows));
+ JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+};
+
+
+/* Miscellaneous useful macros */
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_compress_master jICompress
+#define jinit_c_master_control jICMaster
+#define jinit_c_main_controller jICMainC
+#define jinit_c_prep_controller jICPrepC
+#define jinit_c_coef_controller jICCoefC
+#define jinit_color_converter jICColor
+#define jinit_downsampler jIDownsampler
+#define jinit_forward_dct jIFDCT
+#define jinit_huff_encoder jIHEncoder
+#define jinit_phuff_encoder jIPHEncoder
+#define jinit_marker_writer jIMWriter
+#define jinit_master_decompress jIDMaster
+#define jinit_d_main_controller jIDMainC
+#define jinit_d_coef_controller jIDCoefC
+#define jinit_d_post_controller jIDPostC
+#define jinit_input_controller jIInCtlr
+#define jinit_marker_reader jIMReader
+#define jinit_huff_decoder jIHDecoder
+#define jinit_phuff_decoder jIPHDecoder
+#define jinit_inverse_dct jIIDCT
+#define jinit_upsampler jIUpsampler
+#define jinit_color_deconverter jIDColor
+#define jinit_1pass_quantizer jI1Quant
+#define jinit_2pass_quantizer jI2Quant
+#define jinit_merged_upsampler jIMUpsampler
+#define jinit_memory_mgr jIMemMgr
+#define jdiv_round_up jDivRound
+#define jround_up jRound
+#define jcopy_sample_rows jCopySamples
+#define jcopy_block_row jCopyBlocks
+#define jzero_far jZeroFar
+#define jpeg_zigzag_order jZIGTable
+#define jpeg_natural_order jZAGTable
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
+ boolean transcode_only));
+EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
+/* Memory manager initialization */
+EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
+
+/* Utility routines in jutils.c */
+EXTERN(long) jdiv_round_up JPP((long a, long b));
+EXTERN(long) jround_up JPP((long a, long b));
+EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols));
+EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks));
+EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
+/* Constant tables in jutils.c */
+#if 0 /* This table is not actually needed in v6a */
+extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
+#endif
+extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
+
+/* Suppress undefined-structure complaints if necessary. */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+#endif
+#endif /* INCOMPLETE_TYPES_BROKEN */
diff --git a/SrcShared/jpeg/jpeglib.h b/SrcShared/jpeg/jpeglib.h
new file mode 100644
index 0000000..d1be8dd
--- /dev/null
+++ b/SrcShared/jpeg/jpeglib.h
@@ -0,0 +1,1096 @@
+/*
+ * jpeglib.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the application interface for the JPEG library.
+ * Most applications using the library need only include this file,
+ * and perhaps jerror.h if they want to know the exact error codes.
+ */
+
+#ifndef JPEGLIB_H
+#define JPEGLIB_H
+
+/*
+ * First we include the configuration files that record how this
+ * installation of the JPEG library is set up. jconfig.h can be
+ * generated automatically for many systems. jmorecfg.h contains
+ * manual configuration options that most people need not worry about.
+ */
+
+#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
+#include "jconfig.h" /* widely used configuration options */
+#endif
+#include "jmorecfg.h" /* seldom changed options */
+
+
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+
+#define JPEG_LIB_VERSION 62 /* Version 6b */
+
+
+/* Various constants determining the sizes of things.
+ * All of these are specified by the JPEG standard, so don't change them
+ * if you want to be compatible.
+ */
+
+#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
+#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
+#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
+/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
+ * the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
+ * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
+ * to handle it. We even let you do this from the jconfig.h file. However,
+ * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
+ * sometimes emits noncompliant files doesn't mean you should too.
+ */
+#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */
+#ifndef D_MAX_BLOCKS_IN_MCU
+#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */
+#endif
+
+
+/* Data structures for images (arrays of samples and of DCT coefficients).
+ * On 80x86 machines, the image arrays are too big for near pointers,
+ * but the pointer arrays can fit in near memory.
+ */
+
+typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
+
+typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+/* DCT coefficient quantization tables. */
+
+typedef struct {
+ /* This array gives the coefficient quantizers in natural array order
+ * (not the zigzag order in which they are stored in a JPEG DQT marker).
+ * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+ */
+ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JQUANT_TBL;
+
+
+/* Huffman coding tables. */
+
+typedef struct {
+ /* These two fields directly represent the contents of a JPEG DHT marker */
+ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
+ /* length k bits; bits[0] is unused */
+ UINT8 huffval[256]; /* The symbols, in order of incr code length */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JHUFF_TBL;
+
+
+/* Basic info about one component (color channel). */
+
+typedef struct {
+ /* These values are fixed over the whole image. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOF marker. */
+ int component_id; /* identifier for this component (0..255) */
+ int component_index; /* its index in SOF or cinfo->comp_info[] */
+ int h_samp_factor; /* horizontal sampling factor (1..4) */
+ int v_samp_factor; /* vertical sampling factor (1..4) */
+ int quant_tbl_no; /* quantization table selector (0..3) */
+ /* These values may vary between scans. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOS marker. */
+ /* The decompressor output side may not use these variables. */
+ int dc_tbl_no; /* DC entropy table selector (0..3) */
+ int ac_tbl_no; /* AC entropy table selector (0..3) */
+
+ /* Remaining fields should be treated as private by applications. */
+
+ /* These values are computed during compression or decompression startup: */
+ /* Component's size in DCT blocks.
+ * Any dummy blocks added to complete an MCU are not counted; therefore
+ * these values do not depend on whether a scan is interleaved or not.
+ */
+ JDIMENSION width_in_blocks;
+ JDIMENSION height_in_blocks;
+ /* Size of a DCT block in samples. Always DCTSIZE for compression.
+ * For decompression this is the size of the output from one DCT block,
+ * reflecting any scaling we choose to apply during the IDCT step.
+ * Values of 1,2,4,8 are likely to be supported. Note that different
+ * components may receive different IDCT scalings.
+ */
+ int DCT_scaled_size;
+ /* The downsampled dimensions are the component's actual, unpadded number
+ * of samples at the main buffer (preprocessing/compression interface), thus
+ * downsampled_width = ceil(image_width * Hi/Hmax)
+ * and similarly for height. For decompression, IDCT scaling is included, so
+ * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
+ */
+ JDIMENSION downsampled_width; /* actual width in samples */
+ JDIMENSION downsampled_height; /* actual height in samples */
+ /* This flag is used only for decompression. In cases where some of the
+ * components will be ignored (eg grayscale output from YCbCr image),
+ * we can skip most computations for the unused components.
+ */
+ boolean component_needed; /* do we need the value of this component? */
+
+ /* These values are computed before starting a scan of the component. */
+ /* The decompressor output side may not use these variables. */
+ int MCU_width; /* number of blocks per MCU, horizontally */
+ int MCU_height; /* number of blocks per MCU, vertically */
+ int MCU_blocks; /* MCU_width * MCU_height */
+ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
+ int last_col_width; /* # of non-dummy blocks across in last MCU */
+ int last_row_height; /* # of non-dummy blocks down in last MCU */
+
+ /* Saved quantization table for component; NULL if none yet saved.
+ * See jdinput.c comments about the need for this information.
+ * This field is currently used only for decompression.
+ */
+ JQUANT_TBL * quant_table;
+
+ /* Private per-component storage for DCT or IDCT subsystem. */
+ void * dct_table;
+} jpeg_component_info;
+
+
+/* The script for encoding a multiple-scan file is an array of these: */
+
+typedef struct {
+ int comps_in_scan; /* number of components encoded in this scan */
+ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
+ int Ss, Se; /* progressive JPEG spectral selection parms */
+ int Ah, Al; /* progressive JPEG successive approx. parms */
+} jpeg_scan_info;
+
+/* The decompressor can save APPn and COM markers in a list of these: */
+
+typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
+
+struct jpeg_marker_struct {
+ jpeg_saved_marker_ptr next; /* next in list, or NULL */
+ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
+ unsigned int original_length; /* # bytes of data in the file */
+ unsigned int data_length; /* # bytes of data saved at data[] */
+ JOCTET FAR * data; /* the data contained in the marker */
+ /* the marker length word is not counted in data_length or original_length */
+};
+
+/* Known color spaces. */
+
+typedef enum {
+ JCS_UNKNOWN, /* error/unspecified */
+ JCS_GRAYSCALE, /* monochrome */
+ JCS_RGB, /* red/green/blue */
+ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
+ JCS_CMYK, /* C/M/Y/K */
+ JCS_YCCK /* Y/Cb/Cr/K */
+} J_COLOR_SPACE;
+
+/* DCT/IDCT algorithm options. */
+
+typedef enum {
+ JDCT_ISLOW, /* slow but accurate integer algorithm */
+ JDCT_IFAST, /* faster, less accurate integer method */
+ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
+} J_DCT_METHOD;
+
+#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
+#define JDCT_DEFAULT JDCT_ISLOW
+#endif
+#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
+#define JDCT_FASTEST JDCT_IFAST
+#endif
+
+/* Dithering options for decompression. */
+
+typedef enum {
+ JDITHER_NONE, /* no dithering */
+ JDITHER_ORDERED, /* simple ordered dither */
+ JDITHER_FS /* Floyd-Steinberg error diffusion dither */
+} J_DITHER_MODE;
+
+
+/* Common fields between JPEG compression and decompression master structs. */
+
+#define jpeg_common_fields \
+ struct jpeg_error_mgr * err; /* Error handler module */\
+ struct jpeg_memory_mgr * mem; /* Memory manager module */\
+ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
+ void * client_data; /* Available for use by application */\
+ boolean is_decompressor; /* So common code can tell which is which */\
+ int global_state /* For checking call sequence validity */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure. There are no actual instances of
+ * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
+ */
+struct jpeg_common_struct {
+ jpeg_common_fields; /* Fields common to both master struct types */
+ /* Additional fields follow in an actual jpeg_compress_struct or
+ * jpeg_decompress_struct. All three structs must agree on these
+ * initial fields! (This would be a lot cleaner in C++.)
+ */
+};
+
+typedef struct jpeg_common_struct * j_common_ptr;
+typedef struct jpeg_compress_struct * j_compress_ptr;
+typedef struct jpeg_decompress_struct * j_decompress_ptr;
+
+
+/* Master record for a compression instance */
+
+struct jpeg_compress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
+
+ /* Destination for compressed data */
+ struct jpeg_destination_mgr * dest;
+
+ /* Description of source image --- these fields must be filled in by
+ * outer application before starting compression. in_color_space must
+ * be correct before you can even call jpeg_set_defaults().
+ */
+
+ JDIMENSION image_width; /* input image width */
+ JDIMENSION image_height; /* input image height */
+ int input_components; /* # of color components in input image */
+ J_COLOR_SPACE in_color_space; /* colorspace of input image */
+
+ double input_gamma; /* image gamma of input image */
+
+ /* Compression parameters --- these fields must be set before calling
+ * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
+ * initialize everything to reasonable defaults, then changing anything
+ * the application specifically wants to change. That way you won't get
+ * burnt when new parameters are added. Also note that there are several
+ * helper routines to simplify changing parameters.
+ */
+
+ int data_precision; /* bits of precision in image data */
+
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ int num_scans; /* # of entries in scan_info array */
+ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
+ /* The default value of scan_info is NULL, which causes a single-scan
+ * sequential JPEG file to be emitted. To create a multi-scan file,
+ * set num_scans and scan_info to point to an array of scan definitions.
+ */
+
+ boolean raw_data_in; /* TRUE=caller supplies downsampled data */
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+ int smoothing_factor; /* 1..100, or 0 for no input smoothing */
+ J_DCT_METHOD dct_method; /* DCT algorithm selector */
+
+ /* The restart interval can be specified in absolute MCUs by setting
+ * restart_interval, or in MCU rows by setting restart_in_rows
+ * (in which case the correct restart_interval will be figured
+ * for each scan).
+ */
+ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
+ int restart_in_rows; /* if > 0, MCU rows per restart interval */
+
+ /* Parameters controlling emission of special markers. */
+
+ boolean write_JFIF_header; /* should a JFIF marker be written? */
+ UINT8 JFIF_major_version; /* What to write for the JFIF version number */
+ UINT8 JFIF_minor_version;
+ /* These three values are not used by the JPEG code, merely copied */
+ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
+ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
+ /* ratio is defined by X_density/Y_density even when density_unit=0. */
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean write_Adobe_marker; /* should an Adobe marker be written? */
+
+ /* State variable: index of next scanline to be written to
+ * jpeg_write_scanlines(). Application may use this to control its
+ * processing loop, e.g., "while (next_scanline < image_height)".
+ */
+
+ JDIMENSION next_scanline; /* 0 .. image_height-1 */
+
+ /* Remaining fields are known throughout compressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during compression startup
+ */
+ boolean progressive_mode; /* TRUE if scan script uses progressive mode */
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
+ /* The coefficient controller receives data in units of MCU rows as defined
+ * for fully interleaved scans (whether the JPEG file is interleaved or not).
+ * There are v_samp_factor * DCTSIZE sample rows of each component in an
+ * "iMCU" (interleaved MCU) row.
+ */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int blocks_in_MCU; /* # of DCT blocks per MCU */
+ int MCU_membership[C_MAX_BLOCKS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th block in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
+
+ /*
+ * Links to compression subobjects (methods and private variables of modules)
+ */
+ struct jpeg_comp_master * master;
+ struct jpeg_c_main_controller * main;
+ struct jpeg_c_prep_controller * prep;
+ struct jpeg_c_coef_controller * coef;
+ struct jpeg_marker_writer * marker;
+ struct jpeg_color_converter * cconvert;
+ struct jpeg_downsampler * downsample;
+ struct jpeg_forward_dct * fdct;
+ struct jpeg_entropy_encoder * entropy;
+ jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
+ int script_space_size;
+};
+
+
+/* Master record for a decompression instance */
+
+struct jpeg_decompress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
+
+ /* Source of compressed data */
+ struct jpeg_source_mgr * src;
+
+ /* Basic description of image --- filled in by jpeg_read_header(). */
+ /* Application may inspect these values to decide how to process image. */
+
+ JDIMENSION image_width; /* nominal image width (from SOF marker) */
+ JDIMENSION image_height; /* nominal image height */
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ /* Decompression processing parameters --- these fields must be set before
+ * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
+ * them to default values.
+ */
+
+ J_COLOR_SPACE out_color_space; /* colorspace for output */
+
+ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+ double output_gamma; /* image gamma wanted in output */
+
+ boolean buffered_image; /* TRUE=multiple output passes */
+ boolean raw_data_out; /* TRUE=downsampled data wanted */
+
+ J_DCT_METHOD dct_method; /* IDCT algorithm selector */
+ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
+ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
+
+ boolean quantize_colors; /* TRUE=colormapped output wanted */
+ /* the following are ignored if not quantize_colors: */
+ J_DITHER_MODE dither_mode; /* type of color dithering to use */
+ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
+ int desired_number_of_colors; /* max # colors to use in created colormap */
+ /* these are significant only in buffered-image mode: */
+ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
+ boolean enable_external_quant;/* enable future use of external colormap */
+ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
+
+ /* Description of actual output image that will be returned to application.
+ * These fields are computed by jpeg_start_decompress().
+ * You can also use jpeg_calc_output_dimensions() to determine these values
+ * in advance of calling jpeg_start_decompress().
+ */
+
+ JDIMENSION output_width; /* scaled image width */
+ JDIMENSION output_height; /* scaled image height */
+ int out_color_components; /* # of color components in out_color_space */
+ int output_components; /* # of color components returned */
+ /* output_components is 1 (a colormap index) when quantizing colors;
+ * otherwise it equals out_color_components.
+ */
+ int rec_outbuf_height; /* min recommended height of scanline buffer */
+ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+ * high, space and time will be wasted due to unnecessary data copying.
+ * Usually rec_outbuf_height will be 1 or 2, at most 4.
+ */
+
+ /* When quantizing colors, the output colormap is described by these fields.
+ * The application can supply a colormap by setting colormap non-NULL before
+ * calling jpeg_start_decompress; otherwise a colormap is created during
+ * jpeg_start_decompress or jpeg_start_output.
+ * The map has out_color_components rows and actual_number_of_colors columns.
+ */
+ int actual_number_of_colors; /* number of entries in use */
+ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */
+
+ /* State variables: these variables indicate the progress of decompression.
+ * The application may examine these but must not modify them.
+ */
+
+ /* Row index of next scanline to be read from jpeg_read_scanlines().
+ * Application may use this to control its processing loop, e.g.,
+ * "while (output_scanline < output_height)".
+ */
+ JDIMENSION output_scanline; /* 0 .. output_height-1 */
+
+ /* Current input scan number and number of iMCU rows completed in scan.
+ * These indicate the progress of the decompressor input side.
+ */
+ int input_scan_number; /* Number of SOS markers seen so far */
+ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
+
+ /* The "output scan number" is the notional scan being displayed by the
+ * output side. The decompressor will not allow output scan/row number
+ * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+ */
+ int output_scan_number; /* Nominal scan number being displayed */
+ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
+
+ /* Current progression status. coef_bits[c][i] indicates the precision
+ * with which component c's DCT coefficient i (in zigzag order) is known.
+ * It is -1 when no data has yet been received, otherwise it is the point
+ * transform (shift) value for the most recent scan of the coefficient
+ * (thus, 0 at completion of the progression).
+ * This pointer is NULL when reading a non-progressive file.
+ */
+ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
+
+ /* Internal JPEG parameters --- the application usually need not look at
+ * these fields. Note that the decompressor output side may not use
+ * any parameters that can change between scans.
+ */
+
+ /* Quantization and Huffman tables are carried forward across input
+ * datastreams when processing abbreviated JPEG datastreams.
+ */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ /* These parameters are never carried across datastreams, since they
+ * are given in SOF/SOS markers or defined to be reset by SOI.
+ */
+
+ int data_precision; /* bits of precision in image data */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+ /* These fields record data obtained from optional markers recognized by
+ * the JPEG library.
+ */
+ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
+ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
+ UINT8 JFIF_major_version; /* JFIF version number */
+ UINT8 JFIF_minor_version;
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
+ UINT8 Adobe_transform; /* Color transform code from Adobe marker */
+
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+
+ /* Aside from the specific data retained from APPn markers known to the
+ * library, the uninterpreted contents of any or all APPn and COM markers
+ * can be saved in a list for examination by the application.
+ */
+ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
+
+ /* Remaining fields are known throughout decompressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during decompression startup
+ */
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
+ /* The coefficient controller's input and output progress is measured in
+ * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
+ * in fully interleaved JPEG scans, but are used whether the scan is
+ * interleaved or not. We define an iMCU row as v_samp_factor DCT block
+ * rows of each component. Therefore, the IDCT output contains
+ * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.
+ */
+
+ JSAMPLE * sample_range_limit; /* table for fast range-limiting */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ * Note that the decompressor output side must not use these fields.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int blocks_in_MCU; /* # of DCT blocks per MCU */
+ int MCU_membership[D_MAX_BLOCKS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th block in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
+
+ /* This field is shared between entropy decoder and marker parser.
+ * It is either zero or the code of a JPEG marker that has been
+ * read from the data source, but has not yet been processed.
+ */
+ int unread_marker;
+
+ /*
+ * Links to decompression subobjects (methods, private variables of modules)
+ */
+ struct jpeg_decomp_master * master;
+ struct jpeg_d_main_controller * main;
+ struct jpeg_d_coef_controller * coef;
+ struct jpeg_d_post_controller * post;
+ struct jpeg_input_controller * inputctl;
+ struct jpeg_marker_reader * marker;
+ struct jpeg_entropy_decoder * entropy;
+ struct jpeg_inverse_dct * idct;
+ struct jpeg_upsampler * upsample;
+ struct jpeg_color_deconverter * cconvert;
+ struct jpeg_color_quantizer * cquantize;
+};
+
+
+/* "Object" declarations for JPEG modules that may be supplied or called
+ * directly by the surrounding application.
+ * As with all objects in the JPEG library, these structs only define the
+ * publicly visible methods and state variables of a module. Additional
+ * private fields may exist after the public ones.
+ */
+
+
+/* Error handler object */
+
+struct jpeg_error_mgr {
+ /* Error exit handler: does not return to caller */
+ JMETHOD(void, error_exit, (j_common_ptr cinfo));
+ /* Conditionally emit a trace or warning message */
+ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
+ /* Routine that actually outputs a trace or error message */
+ JMETHOD(void, output_message, (j_common_ptr cinfo));
+ /* Format a message string for the most recent JPEG error or message */
+ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
+#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
+ /* Reset error state variables at start of a new image */
+ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
+
+ /* The message ID code and any parameters are saved here.
+ * A message can have one string parameter or up to 8 int parameters.
+ */
+ int msg_code;
+#define JMSG_STR_PARM_MAX 80
+ union {
+ int i[8];
+ char s[JMSG_STR_PARM_MAX];
+ } msg_parm;
+
+ /* Standard state variables for error facility */
+
+ int trace_level; /* max msg_level that will be displayed */
+
+ /* For recoverable corrupt-data errors, we emit a warning message,
+ * but keep going unless emit_message chooses to abort. emit_message
+ * should count warnings in num_warnings. The surrounding application
+ * can check for bad data by seeing if num_warnings is nonzero at the
+ * end of processing.
+ */
+ long num_warnings; /* number of corrupt-data warnings */
+
+ /* These fields point to the table(s) of error message strings.
+ * An application can change the table pointer to switch to a different
+ * message list (typically, to change the language in which errors are
+ * reported). Some applications may wish to add additional error codes
+ * that will be handled by the JPEG library error mechanism; the second
+ * table pointer is used for this purpose.
+ *
+ * First table includes all errors generated by JPEG library itself.
+ * Error code 0 is reserved for a "no such error string" message.
+ */
+ const char * const * jpeg_message_table; /* Library errors */
+ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
+ /* Second table can be added by application (see cjpeg/djpeg for example).
+ * It contains strings numbered first_addon_message..last_addon_message.
+ */
+ const char * const * addon_message_table; /* Non-library errors */
+ int first_addon_message; /* code for first string in addon table */
+ int last_addon_message; /* code for last string in addon table */
+};
+
+
+/* Progress monitor object */
+
+struct jpeg_progress_mgr {
+ JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
+
+ long pass_counter; /* work units completed in this pass */
+ long pass_limit; /* total number of work units in this pass */
+ int completed_passes; /* passes completed so far */
+ int total_passes; /* total number of passes expected */
+};
+
+
+/* Data destination object for compression */
+
+struct jpeg_destination_mgr {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+
+ JMETHOD(void, init_destination, (j_compress_ptr cinfo));
+ JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
+ JMETHOD(void, term_destination, (j_compress_ptr cinfo));
+};
+
+
+/* Data source object for decompression */
+
+struct jpeg_source_mgr {
+ const JOCTET * next_input_byte; /* => next byte to read from buffer */
+ size_t bytes_in_buffer; /* # of bytes remaining in buffer */
+
+ JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+ JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+ JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+ JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+
+
+/* Memory manager object.
+ * Allocates "small" objects (a few K total), "large" objects (tens of K),
+ * and "really big" objects (virtual arrays with backing store if needed).
+ * The memory manager does not allow individual objects to be freed; rather,
+ * each created object is assigned to a pool, and whole pools can be freed
+ * at once. This is faster and more convenient than remembering exactly what
+ * to free, especially where malloc()/free() are not too speedy.
+ * NB: alloc routines never return NULL. They exit to error_exit if not
+ * successful.
+ */
+
+#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
+#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS 2
+
+typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
+typedef struct jvirt_barray_control * jvirt_barray_ptr;
+
+
+struct jpeg_memory_mgr {
+ /* Method pointers */
+ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows));
+ JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows));
+ JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
+ JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
+ jvirt_sarray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
+ jvirt_barray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
+ JMETHOD(void, self_destruct, (j_common_ptr cinfo));
+
+ /* Limit on memory allocation for this JPEG object. (Note that this is
+ * merely advisory, not a guaranteed maximum; it only affects the space
+ * used for virtual-array buffers.) May be changed by outer application
+ * after creating the JPEG object.
+ */
+ long max_memory_to_use;
+
+ /* Maximum allocation request accepted by alloc_large. */
+ long max_alloc_chunk;
+};
+
+
+/* Routine signature for application-supplied marker processing methods.
+ * Need not pass marker code since it is stored in cinfo->unread_marker.
+ */
+typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
+
+
+/* Declarations for routines called by application.
+ * The JPP macro hides prototype parameters from compilers that can't cope.
+ * Note JPP requires double parentheses.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JPP(arglist) arglist
+#else
+#define JPP(arglist) ()
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers.
+ * We shorten external names to be unique in the first six letters, which
+ * is good enough for all known systems.
+ * (If your compiler itself needs names to be unique in less than 15
+ * characters, you are out of luck. Get a better compiler.)
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_error jStdError
+#define jpeg_CreateCompress jCreaCompress
+#define jpeg_CreateDecompress jCreaDecompress
+#define jpeg_destroy_compress jDestCompress
+#define jpeg_destroy_decompress jDestDecompress
+#define jpeg_stdio_dest jStdDest
+#define jpeg_stdio_src jStdSrc
+#define jpeg_set_defaults jSetDefaults
+#define jpeg_set_colorspace jSetColorspace
+#define jpeg_default_colorspace jDefColorspace
+#define jpeg_set_quality jSetQuality
+#define jpeg_set_linear_quality jSetLQuality
+#define jpeg_add_quant_table jAddQuantTable
+#define jpeg_quality_scaling jQualityScaling
+#define jpeg_simple_progression jSimProgress
+#define jpeg_suppress_tables jSuppressTables
+#define jpeg_alloc_quant_table jAlcQTable
+#define jpeg_alloc_huff_table jAlcHTable
+#define jpeg_start_compress jStrtCompress
+#define jpeg_write_scanlines jWrtScanlines
+#define jpeg_finish_compress jFinCompress
+#define jpeg_write_raw_data jWrtRawData
+#define jpeg_write_marker jWrtMarker
+#define jpeg_write_m_header jWrtMHeader
+#define jpeg_write_m_byte jWrtMByte
+#define jpeg_write_tables jWrtTables
+#define jpeg_read_header jReadHeader
+#define jpeg_start_decompress jStrtDecompress
+#define jpeg_read_scanlines jReadScanlines
+#define jpeg_finish_decompress jFinDecompress
+#define jpeg_read_raw_data jReadRawData
+#define jpeg_has_multiple_scans jHasMultScn
+#define jpeg_start_output jStrtOutput
+#define jpeg_finish_output jFinOutput
+#define jpeg_input_complete jInComplete
+#define jpeg_new_colormap jNewCMap
+#define jpeg_consume_input jConsumeInput
+#define jpeg_calc_output_dimensions jCalcDimensions
+#define jpeg_save_markers jSaveMarkers
+#define jpeg_set_marker_processor jSetMarker
+#define jpeg_read_coefficients jReadCoefs
+#define jpeg_write_coefficients jWrtCoefs
+#define jpeg_copy_critical_parameters jCopyCrit
+#define jpeg_abort_compress jAbrtCompress
+#define jpeg_abort_decompress jAbrtDecompress
+#define jpeg_abort jAbort
+#define jpeg_destroy jDestroy
+#define jpeg_resync_to_restart jResyncRestart
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Default error-management setup */
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error
+ JPP((struct jpeg_error_mgr * err));
+
+/* Initialization of JPEG compression objects.
+ * jpeg_create_compress() and jpeg_create_decompress() are the exported
+ * names that applications should call. These expand to calls on
+ * jpeg_CreateCompress and jpeg_CreateDecompress with additional information
+ * passed for version mismatch checking.
+ * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
+ */
+#define jpeg_create_compress(cinfo) \
+ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_compress_struct))
+#define jpeg_create_decompress(cinfo) \
+ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
+ int version, size_t structsize));
+EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
+ int version, size_t structsize));
+/* Destruction of JPEG compression objects */
+EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
+
+/* Standard data source and destination managers: stdio streams. */
+/* Caller is responsible for opening the file before and closing after. */
+EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
+EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* Default parameter setup for compression */
+EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
+/* Compression parameter setup aids */
+EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
+ J_COLOR_SPACE colorspace));
+EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
+ boolean force_baseline));
+EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(int) jpeg_quality_scaling JPP((int quality));
+EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
+ boolean suppress));
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
+
+/* Main entry points for compression */
+EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
+ boolean write_all_tables));
+EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION num_lines));
+EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
+
+/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION num_lines));
+
+/* Write a special marker. See libjpeg.doc concerning safe usage. */
+EXTERN(void) jpeg_write_marker
+ JPP((j_compress_ptr cinfo, int marker,
+ const JOCTET * dataptr, unsigned int datalen));
+/* Same, but piecemeal. */
+EXTERN(void) jpeg_write_m_header
+ JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
+EXTERN(void) jpeg_write_m_byte
+ JPP((j_compress_ptr cinfo, int val));
+
+/* Alternate compression function: just write an abbreviated table file */
+EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
+
+/* Decompression startup: read start of JPEG datastream to see what's there */
+EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
+ boolean require_image));
+/* Return value is one of: */
+#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK 1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
+/* If you pass require_image = TRUE (normal case), you need not check for
+ * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
+ * JPEG_SUSPENDED is only possible if you use a data source module that can
+ * give a suspension return (the stdio source module doesn't).
+ */
+
+/* Main entry points for decompression */
+EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION max_lines));
+EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
+
+/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION max_lines));
+
+/* Additional entry points for buffered-image mode. */
+EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
+ int scan_number));
+EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
+EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
+/* Return value is one of: */
+/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
+#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
+#define JPEG_REACHED_EOI 2 /* Reached end of image */
+#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
+#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
+
+/* Precalculate output dimensions for current decompression parameters. */
+EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
+
+/* Control saving of COM and APPn markers into marker_list. */
+EXTERN(void) jpeg_save_markers
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit));
+
+/* Install a special processing method for COM or APPn markers. */
+EXTERN(void) jpeg_set_marker_processor
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine));
+
+/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays));
+EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo));
+
+/* If you choose to abort compression or decompression before completing
+ * jpeg_finish_(de)compress, then you need to clean up to release memory,
+ * temporary files, etc. You can just call jpeg_destroy_(de)compress
+ * if you're done with the JPEG object, but if you want to clean it up and
+ * reuse it, call this:
+ */
+EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
+
+/* Generic versions of jpeg_abort and jpeg_destroy that work on either
+ * flavor of JPEG object. These may be more convenient in some places.
+ */
+EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
+
+/* Default restart-marker-resync procedure for use by data source modules */
+EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
+ int desired));
+
+
+/* These marker codes are exported since applications and data source modules
+ * are likely to want to use them.
+ */
+
+#define JPEG_RST0 0xD0 /* RST0 marker code */
+#define JPEG_EOI 0xD9 /* EOI marker code */
+#define JPEG_APP0 0xE0 /* APP0 marker code */
+#define JPEG_COM 0xFE /* COM marker code */
+
+
+/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
+ * for structure definitions that are never filled in, keep it quiet by
+ * supplying dummy definitions for the various substructures.
+ */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+struct jpeg_comp_master { long dummy; };
+struct jpeg_c_main_controller { long dummy; };
+struct jpeg_c_prep_controller { long dummy; };
+struct jpeg_c_coef_controller { long dummy; };
+struct jpeg_marker_writer { long dummy; };
+struct jpeg_color_converter { long dummy; };
+struct jpeg_downsampler { long dummy; };
+struct jpeg_forward_dct { long dummy; };
+struct jpeg_entropy_encoder { long dummy; };
+struct jpeg_decomp_master { long dummy; };
+struct jpeg_d_main_controller { long dummy; };
+struct jpeg_d_coef_controller { long dummy; };
+struct jpeg_d_post_controller { long dummy; };
+struct jpeg_input_controller { long dummy; };
+struct jpeg_marker_reader { long dummy; };
+struct jpeg_entropy_decoder { long dummy; };
+struct jpeg_inverse_dct { long dummy; };
+struct jpeg_upsampler { long dummy; };
+struct jpeg_color_deconverter { long dummy; };
+struct jpeg_color_quantizer { long dummy; };
+#endif /* JPEG_INTERNALS */
+#endif /* INCOMPLETE_TYPES_BROKEN */
+
+
+/*
+ * The JPEG library modules define JPEG_INTERNALS before including this file.
+ * The internal structure declarations are read only when that is true.
+ * Applications using the library should not include jpegint.h, but may wish
+ * to include jerror.h.
+ */
+
+#ifdef JPEG_INTERNALS
+#include "jpegint.h" /* fetch private declarations */
+#include "jerror.h" /* fetch error codes too */
+#endif
+
+#endif /* JPEGLIB_H */
diff --git a/SrcShared/jpeg/jquant1.c b/SrcShared/jpeg/jquant1.c
new file mode 100644
index 0000000..b2f96aa
--- /dev/null
+++ b/SrcShared/jpeg/jquant1.c
@@ -0,0 +1,856 @@
+/*
+ * jquant1.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 1-pass color quantization (color mapping) routines.
+ * These routines provide mapping to a fixed color map using equally spaced
+ * color values. Optional Floyd-Steinberg or ordered dithering is available.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_1PASS_SUPPORTED
+
+
+/*
+ * The main purpose of 1-pass quantization is to provide a fast, if not very
+ * high quality, colormapped output capability. A 2-pass quantizer usually
+ * gives better visual quality; however, for quantized grayscale output this
+ * quantizer is perfectly adequate. Dithering is highly recommended with this
+ * quantizer, though you can turn it off if you really want to.
+ *
+ * In 1-pass quantization the colormap must be chosen in advance of seeing the
+ * image. We use a map consisting of all combinations of Ncolors[i] color
+ * values for the i'th component. The Ncolors[] values are chosen so that
+ * their product, the total number of colors, is no more than that requested.
+ * (In most cases, the product will be somewhat less.)
+ *
+ * Since the colormap is orthogonal, the representative value for each color
+ * component can be determined without considering the other components;
+ * then these indexes can be combined into a colormap index by a standard
+ * N-dimensional-array-subscript calculation. Most of the arithmetic involved
+ * can be precalculated and stored in the lookup table colorindex[].
+ * colorindex[i][j] maps pixel value j in component i to the nearest
+ * representative value (grid plane) for that component; this index is
+ * multiplied by the array stride for component i, so that the
+ * index of the colormap entry closest to a given pixel value is just
+ * sum( colorindex[component-number][pixel-component-value] )
+ * Aside from being fast, this scheme allows for variable spacing between
+ * representative values with no additional lookup cost.
+ *
+ * If gamma correction has been applied in color conversion, it might be wise
+ * to adjust the color grid spacing so that the representative colors are
+ * equidistant in linear space. At this writing, gamma correction is not
+ * implemented by jdcolor, so nothing is done here.
+ */
+
+
+/* Declarations for ordered dithering.
+ *
+ * We use a standard 16x16 ordered dither array. The basic concept of ordered
+ * dithering is described in many references, for instance Dale Schumacher's
+ * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
+ * In place of Schumacher's comparisons against a "threshold" value, we add a
+ * "dither" value to the input pixel and then round the result to the nearest
+ * output value. The dither value is equivalent to (0.5 - threshold) times
+ * the distance between output values. For ordered dithering, we assume that
+ * the output colors are equally spaced; if not, results will probably be
+ * worse, since the dither may be too much or too little at a given point.
+ *
+ * The normal calculation would be to form pixel value + dither, range-limit
+ * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
+ * We can skip the separate range-limiting step by extending the colorindex
+ * table in both directions.
+ */
+
+#define ODITHER_SIZE 16 /* dimension of dither matrix */
+/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
+#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */
+#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */
+
+typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
+typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
+
+static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
+ /* Bayer's order-4 dither array. Generated by the code given in
+ * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
+ * The values in this array must range from 0 to ODITHER_CELLS-1.
+ */
+ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
+ { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
+ { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
+ { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
+ { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
+ { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
+ { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
+ { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
+ { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
+ { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
+ { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
+ { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
+ { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
+ { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
+ { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
+ { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
+};
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array is indexed [component#][position].
+ * We provide (#columns + 2) entries per component; the extra entry at each
+ * end saves us from special-casing the first and last pixels.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+#define MAX_Q_COMPS 4 /* max components I can handle */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Initially allocated colormap is saved here */
+ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */
+ int sv_actual; /* number of entries in use */
+
+ JSAMPARRAY colorindex; /* Precomputed mapping for speed */
+ /* colorindex[i][j] = index of color closest to pixel value j in component i,
+ * premultiplied as described above. Since colormap indexes must fit into
+ * JSAMPLEs, the entries of this array will too.
+ */
+ boolean is_padded; /* is the colorindex padded for odither? */
+
+ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
+
+ /* Variables for ordered dithering */
+ int row_index; /* cur row's vertical index in dither matrix */
+ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Policy-making subroutines for create_colormap and create_colorindex.
+ * These routines determine the colormap to be used. The rest of the module
+ * only assumes that the colormap is orthogonal.
+ *
+ * * select_ncolors decides how to divvy up the available colors
+ * among the components.
+ * * output_value defines the set of representative values for a component.
+ * * largest_input_value defines the mapping from input values to
+ * representative values for a component.
+ * Note that the latter two routines may impose different policies for
+ * different components, though this is not currently done.
+ */
+
+
+LOCAL(int)
+select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+/* Determine allocation of desired colors to components, */
+/* and fill in Ncolors[] array to indicate choice. */
+/* Return value is total number of colors (product of Ncolors[] values). */
+{
+ int nc = cinfo->out_color_components; /* number of color components */
+ int max_colors = cinfo->desired_number_of_colors;
+ int total_colors, iroot, i, j;
+ boolean changed;
+ long temp;
+ static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
+
+ /* We can allocate at least the nc'th root of max_colors per component. */
+ /* Compute floor(nc'th root of max_colors). */
+ iroot = 1;
+ do {
+ iroot++;
+ temp = iroot; /* set temp = iroot ** nc */
+ for (i = 1; i < nc; i++)
+ temp *= iroot;
+ } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+ iroot--; /* now iroot = floor(root) */
+
+ /* Must have at least 2 color values per component */
+ if (iroot < 2)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+
+ /* Initialize to iroot color values for each component */
+ total_colors = 1;
+ for (i = 0; i < nc; i++) {
+ Ncolors[i] = iroot;
+ total_colors *= iroot;
+ }
+ /* We may be able to increment the count for one or more components without
+ * exceeding max_colors, though we know not all can be incremented.
+ * Sometimes, the first component can be incremented more than once!
+ * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
+ * In RGB colorspace, try to increment G first, then R, then B.
+ */
+ do {
+ changed = FALSE;
+ for (i = 0; i < nc; i++) {
+ j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
+ /* calculate new total_colors if Ncolors[j] is incremented */
+ temp = total_colors / Ncolors[j];
+ temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
+ if (temp > (long) max_colors)
+ break; /* won't fit, done with this pass */
+ Ncolors[j]++; /* OK, apply the increment */
+ total_colors = (int) temp;
+ changed = TRUE;
+ }
+ } while (changed);
+
+ return total_colors;
+}
+
+
+LOCAL(int)
+output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return j'th output value, where j will range from 0 to maxj */
+/* The output values must fall in 0..MAXJSAMPLE in increasing order */
+{
+ /* We always provide values 0 and MAXJSAMPLE for each component;
+ * any additional values are equally spaced between these limits.
+ * (Forcing the upper and lower values to the limits ensures that
+ * dithering can't produce a color outside the selected gamut.)
+ */
+ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
+}
+
+
+LOCAL(int)
+largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return largest input value that should map to j'th output value */
+/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
+{
+ /* Breakpoints are halfway between values returned by output_value */
+ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+}
+
+
+/*
+ * Create the colormap.
+ */
+
+LOCAL(void)
+create_colormap (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colormap; /* Created colormap */
+ int total_colors; /* Number of distinct output colors */
+ int i,j,k, nci, blksize, blkdist, ptr, val;
+
+ /* Select number of colors for each component */
+ total_colors = select_ncolors(cinfo, cquantize->Ncolors);
+
+ /* Report selected color counts */
+ if (cinfo->out_color_components == 3)
+ TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
+ total_colors, cquantize->Ncolors[0],
+ cquantize->Ncolors[1], cquantize->Ncolors[2]);
+ else
+ TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
+
+ /* Allocate and fill in the colormap. */
+ /* The colors are ordered in the map in standard row-major order, */
+ /* i.e. rightmost (highest-indexed) color changes most rapidly. */
+
+ colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ /* blkdist is distance between groups of identical entries for a component */
+ blkdist = total_colors;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colormap entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blkdist / nci;
+ for (j = 0; j < nci; j++) {
+ /* Compute j'th output value (out of nci) for component */
+ val = output_value(cinfo, i, j, nci-1);
+ /* Fill in all colormap entries that have this value of this component */
+ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
+ /* fill in blksize entries beginning at ptr */
+ for (k = 0; k < blksize; k++)
+ colormap[i][ptr+k] = (JSAMPLE) val;
+ }
+ }
+ blkdist = blksize; /* blksize of this color is blkdist of next */
+ }
+
+ /* Save the colormap in private storage,
+ * where it will survive color quantization mode changes.
+ */
+ cquantize->sv_colormap = colormap;
+ cquantize->sv_actual = total_colors;
+}
+
+
+/*
+ * Create the color index table.
+ */
+
+LOCAL(void)
+create_colorindex (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPROW indexptr;
+ int i,j,k, nci, blksize, val, pad;
+
+ /* For ordered dither, we pad the color index tables by MAXJSAMPLE in
+ * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
+ * This is not necessary in the other dithering modes. However, we
+ * flag whether it was done in case user changes dithering mode.
+ */
+ if (cinfo->dither_mode == JDITHER_ORDERED) {
+ pad = MAXJSAMPLE*2;
+ cquantize->is_padded = TRUE;
+ } else {
+ pad = 0;
+ cquantize->is_padded = FALSE;
+ }
+
+ cquantize->colorindex = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (MAXJSAMPLE+1 + pad),
+ (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ blksize = cquantize->sv_actual;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colorindex entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blksize / nci;
+
+ /* adjust colorindex pointers to provide padding at negative indexes. */
+ if (pad)
+ cquantize->colorindex[i] += MAXJSAMPLE;
+
+ /* in loop, val = index of current output value, */
+ /* and k = largest j that maps to current val */
+ indexptr = cquantize->colorindex[i];
+ val = 0;
+ k = largest_input_value(cinfo, i, 0, nci-1);
+ for (j = 0; j <= MAXJSAMPLE; j++) {
+ while (j > k) /* advance val if past boundary */
+ k = largest_input_value(cinfo, i, ++val, nci-1);
+ /* premultiply so that no multiplication needed in main processing */
+ indexptr[j] = (JSAMPLE) (val * blksize);
+ }
+ /* Pad at both ends if necessary */
+ if (pad)
+ for (j = 1; j <= MAXJSAMPLE; j++) {
+ indexptr[-j] = indexptr[0];
+ indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+ }
+ }
+}
+
+
+/*
+ * Create an ordered-dither array for a component having ncolors
+ * distinct output values.
+ */
+
+LOCAL(ODITHER_MATRIX_PTR)
+make_odither_array (j_decompress_ptr cinfo, int ncolors)
+{
+ ODITHER_MATRIX_PTR odither;
+ int j,k;
+ INT32 num,den;
+
+ odither = (ODITHER_MATRIX_PTR)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ODITHER_MATRIX));
+ /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
+ * Hence the dither value for the matrix cell with fill order f
+ * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
+ * On 16-bit-int machine, be careful to avoid overflow.
+ */
+ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
+ for (j = 0; j < ODITHER_SIZE; j++) {
+ for (k = 0; k < ODITHER_SIZE; k++) {
+ num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
+ * MAXJSAMPLE;
+ /* Ensure round towards zero despite C's lack of consistency
+ * about rounding negative values in integer division...
+ */
+ odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+ }
+ }
+ return odither;
+}
+
+
+/*
+ * Create the ordered-dither tables.
+ * Components having the same number of representative colors may
+ * share a dither table.
+ */
+
+LOCAL(void)
+create_odither_tables (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ ODITHER_MATRIX_PTR odither;
+ int i, j, nci;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ odither = NULL; /* search for matching prior component */
+ for (j = 0; j < i; j++) {
+ if (nci == cquantize->Ncolors[j]) {
+ odither = cquantize->odither[j];
+ break;
+ }
+ }
+ if (odither == NULL) /* need a new table? */
+ odither = make_odither_array(cinfo, nci);
+ cquantize->odither[i] = odither;
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colorindex = cquantize->colorindex;
+ register int pixcode, ci;
+ register JSAMPROW ptrin, ptrout;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ register int nc = cinfo->out_color_components;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = 0;
+ for (ci = 0; ci < nc; ci++) {
+ pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
+ }
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW ptrin, ptrout;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ int * dither; /* points to active row of dither matrix */
+ int row_index, col_index; /* current indexes into dither matrix */
+ int nc = cinfo->out_color_components;
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ row_index = cquantize->row_index;
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ colorindex_ci = cquantize->colorindex[ci];
+ dither = cquantize->odither[ci][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
+ * select output value, accumulate into output code for this pixel.
+ * Range-limiting need not be done explicitly, as we have extended
+ * the colorindex table to produce the right answers for out-of-range
+ * inputs. The maximum dither is +- MAXJSAMPLE; this sets the
+ * required amount of padding.
+ */
+ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+ input_ptr += nc;
+ output_ptr++;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ }
+ /* Advance row index for next row */
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int * dither0; /* points to active row of dither matrix */
+ int * dither1;
+ int * dither2;
+ int row_index, col_index; /* current indexes into dither matrix */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ row_index = cquantize->row_index;
+ input_ptr = input_buf[row];
+ output_ptr = output_buf[row];
+ dither0 = cquantize->odither[0][row_index];
+ dither1 = cquantize->odither[1][row_index];
+ dither2 = cquantize->odither[2][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
+ dither0[col_index]]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
+ dither1[col_index]]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
+ dither2[col_index]]);
+ *output_ptr++ = (JSAMPLE) pixcode;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register LOCFSERROR cur; /* current error or pixel value */
+ LOCFSERROR belowerr; /* error for pixel below cur */
+ LOCFSERROR bpreverr; /* error for below/prev col */
+ LOCFSERROR bnexterr; /* error for below/next col */
+ LOCFSERROR delta;
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ JSAMPROW colormap_ci;
+ int pixcode;
+ int nc = cinfo->out_color_components;
+ int dir; /* 1 for left-to-right, -1 for right-to-left */
+ int dirnc; /* dir * nc */
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ input_ptr += (width-1) * nc; /* so point to rightmost pixel */
+ output_ptr += width-1;
+ dir = -1;
+ dirnc = -nc;
+ errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dirnc = nc;
+ errorptr = cquantize->fserrors[ci]; /* => entry before first column */
+ }
+ colorindex_ci = cquantize->colorindex[ci];
+ colormap_ci = cquantize->sv_colormap[ci];
+ /* Preset error values: no error propagated to first pixel from left */
+ cur = 0;
+ /* and no error propagated to row below yet */
+ belowerr = bpreverr = 0;
+
+ for (col = width; col > 0; col--) {
+ /* cur holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE; this sets the required size
+ * of the range_limit array.
+ */
+ cur += GETJSAMPLE(*input_ptr);
+ cur = GETJSAMPLE(range_limit[cur]);
+ /* Select output value, accumulate into output code for this pixel */
+ pixcode = GETJSAMPLE(colorindex_ci[cur]);
+ *output_ptr += (JSAMPLE) pixcode;
+ /* Compute actual representation error at this pixel */
+ /* Note: we can do this even though we don't have the final */
+ /* pixel code, because the colormap is orthogonal. */
+ cur -= GETJSAMPLE(colormap_ci[pixcode]);
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ bnexterr = cur;
+ delta = cur * 2;
+ cur += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr + cur);
+ cur += delta; /* form error * 5 */
+ bpreverr = belowerr + cur;
+ belowerr = bnexterr;
+ cur += delta; /* form error * 7 */
+ /* At this point cur contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ input_ptr += dirnc; /* advance input ptr to next column */
+ output_ptr += dir; /* advance output ptr to next column */
+ errorptr += dir; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error value into the
+ * final fserrors[] entry. Note we need not unload belowerr because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+ }
+ cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
+ }
+}
+
+
+/*
+ * Allocate workspace for Floyd-Steinberg errors.
+ */
+
+LOCAL(void)
+alloc_fs_workspace (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ cquantize->fserrors[i] = (FSERRPTR)
+ (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ }
+}
+
+
+/*
+ * Initialize for one-pass color quantization.
+ */
+
+METHODDEF(void)
+start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ /* Install my colormap. */
+ cinfo->colormap = cquantize->sv_colormap;
+ cinfo->actual_number_of_colors = cquantize->sv_actual;
+
+ /* Initialize for desired dithering mode. */
+ switch (cinfo->dither_mode) {
+ case JDITHER_NONE:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = color_quantize3;
+ else
+ cquantize->pub.color_quantize = color_quantize;
+ break;
+ case JDITHER_ORDERED:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = quantize3_ord_dither;
+ else
+ cquantize->pub.color_quantize = quantize_ord_dither;
+ cquantize->row_index = 0; /* initialize state for ordered dither */
+ /* If user changed to ordered dither from another mode,
+ * we must recreate the color index table with padding.
+ * This will cost extra space, but probably isn't very likely.
+ */
+ if (! cquantize->is_padded)
+ create_colorindex(cinfo);
+ /* Create ordered-dither tables if we didn't already. */
+ if (cquantize->odither[0] == NULL)
+ create_odither_tables(cinfo);
+ break;
+ case JDITHER_FS:
+ cquantize->pub.color_quantize = quantize_fs_dither;
+ cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
+ /* Allocate Floyd-Steinberg workspace if didn't already. */
+ if (cquantize->fserrors[0] == NULL)
+ alloc_fs_workspace(cinfo);
+ /* Initialize the propagated errors to zero. */
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++)
+ jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+}
+
+
+/*
+ * Finish up at the end of the pass.
+ */
+
+METHODDEF(void)
+finish_pass_1_quant (j_decompress_ptr cinfo)
+{
+ /* no work in 1-pass case */
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ * Shouldn't get to this module!
+ */
+
+METHODDEF(void)
+new_color_map_1_quant (j_decompress_ptr cinfo)
+{
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+
+/*
+ * Module initialization routine for 1-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_1pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_1_quant;
+ cquantize->pub.finish_pass = finish_pass_1_quant;
+ cquantize->pub.new_color_map = new_color_map_1_quant;
+ cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
+ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */
+
+ /* Make sure my internal arrays won't overflow */
+ if (cinfo->out_color_components > MAX_Q_COMPS)
+ ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+
+ /* Create the colormap and color index table. */
+ create_colormap(cinfo);
+ create_colorindex(cinfo);
+
+ /* Allocate Floyd-Steinberg workspace now if requested.
+ * We do this now since it is FAR storage and may affect the memory
+ * manager's space calculations. If the user changes to FS dither
+ * mode in a later pass, we will allocate the space then, and will
+ * possibly overrun the max_memory_to_use setting.
+ */
+ if (cinfo->dither_mode == JDITHER_FS)
+ alloc_fs_workspace(cinfo);
+}
+
+#endif /* QUANT_1PASS_SUPPORTED */
diff --git a/SrcShared/jpeg/jquant2.c b/SrcShared/jpeg/jquant2.c
new file mode 100644
index 0000000..af601e3
--- /dev/null
+++ b/SrcShared/jpeg/jquant2.c
@@ -0,0 +1,1310 @@
+/*
+ * jquant2.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 2-pass color quantization (color mapping) routines.
+ * These routines provide selection of a custom color map for an image,
+ * followed by mapping of the image to that color map, with optional
+ * Floyd-Steinberg dithering.
+ * It is also possible to use just the second pass to map to an arbitrary
+ * externally-given color map.
+ *
+ * Note: ordered dithering is not supported, since there isn't any fast
+ * way to compute intercolor distances; it's unclear that ordered dither's
+ * fundamental assumptions even hold with an irregularly spaced color map.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
+/*
+ * This module implements the well-known Heckbert paradigm for color
+ * quantization. Most of the ideas used here can be traced back to
+ * Heckbert's seminal paper
+ * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display",
+ * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
+ *
+ * In the first pass over the image, we accumulate a histogram showing the
+ * usage count of each possible color. To keep the histogram to a reasonable
+ * size, we reduce the precision of the input; typical practice is to retain
+ * 5 or 6 bits per color, so that 8 or 4 different input values are counted
+ * in the same histogram cell.
+ *
+ * Next, the color-selection step begins with a box representing the whole
+ * color space, and repeatedly splits the "largest" remaining box until we
+ * have as many boxes as desired colors. Then the mean color in each
+ * remaining box becomes one of the possible output colors.
+ *
+ * The second pass over the image maps each input pixel to the closest output
+ * color (optionally after applying a Floyd-Steinberg dithering correction).
+ * This mapping is logically trivial, but making it go fast enough requires
+ * considerable care.
+ *
+ * Heckbert-style quantizers vary a good deal in their policies for choosing
+ * the "largest" box and deciding where to cut it. The particular policies
+ * used here have proved out well in experimental comparisons, but better ones
+ * may yet be found.
+ *
+ * In earlier versions of the IJG code, this module quantized in YCbCr color
+ * space, processing the raw upsampled data without a color conversion step.
+ * This allowed the color conversion math to be done only once per colormap
+ * entry, not once per pixel. However, that optimization precluded other
+ * useful optimizations (such as merging color conversion with upsampling)
+ * and it also interfered with desired capabilities such as quantizing to an
+ * externally-supplied colormap. We have therefore abandoned that approach.
+ * The present code works in the post-conversion color space, typically RGB.
+ *
+ * To improve the visual quality of the results, we actually work in scaled
+ * RGB space, giving G distances more weight than R, and R in turn more than
+ * B. To do everything in integer math, we must use integer scale factors.
+ * The 2/3/1 scale factors used here correspond loosely to the relative
+ * weights of the colors in the NTSC grayscale equation.
+ * If you want to use this code to quantize a non-RGB color space, you'll
+ * probably need to change these scale factors.
+ */
+
+#define R_SCALE 2 /* scale R distances by this much */
+#define G_SCALE 3 /* scale G distances by this much */
+#define B_SCALE 1 /* and B by this much */
+
+/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
+ * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B
+ * and B,G,R orders. If you define some other weird order in jmorecfg.h,
+ * you'll get compile errors until you extend this logic. In that case
+ * you'll probably want to tweak the histogram sizes too.
+ */
+
+#if RGB_RED == 0
+#define C0_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 0
+#define C0_SCALE B_SCALE
+#endif
+#if RGB_GREEN == 1
+#define C1_SCALE G_SCALE
+#endif
+#if RGB_RED == 2
+#define C2_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 2
+#define C2_SCALE B_SCALE
+#endif
+
+
+/*
+ * First we have the histogram data structure and routines for creating it.
+ *
+ * The number of bits of precision can be adjusted by changing these symbols.
+ * We recommend keeping 6 bits for G and 5 each for R and B.
+ * If you have plenty of memory and cycles, 6 bits all around gives marginally
+ * better results; if you are short of memory, 5 bits all around will save
+ * some space but degrade the results.
+ * To maintain a fully accurate histogram, we'd need to allocate a "long"
+ * (preferably unsigned long) for each cell. In practice this is overkill;
+ * we can get by with 16 bits per cell. Few of the cell counts will overflow,
+ * and clamping those that do overflow to the maximum value will give close-
+ * enough results. This reduces the recommended histogram size from 256Kb
+ * to 128Kb, which is a useful savings on PC-class machines.
+ * (In the second pass the histogram space is re-used for pixel mapping data;
+ * in that capacity, each cell must be able to store zero to the number of
+ * desired colors. 16 bits/cell is plenty for that too.)
+ * Since the JPEG code is intended to run in small memory model on 80x86
+ * machines, we can't just allocate the histogram in one chunk. Instead
+ * of a true 3-D array, we use a row of pointers to 2-D arrays. Each
+ * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
+ * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that
+ * on 80x86 machines, the pointer row is in near memory but the actual
+ * arrays are in far memory (same arrangement as we use for image arrays).
+ */
+
+#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */
+
+/* These will do the right thing for either R,G,B or B,G,R color order,
+ * but you may not like the results for other color orders.
+ */
+#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */
+#define HIST_C1_BITS 6 /* bits of precision in G histogram */
+#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */
+
+/* Number of elements along histogram axes. */
+#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
+#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
+#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+
+/* These are the amounts to shift an input value to get a histogram index. */
+#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS)
+#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS)
+#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS)
+
+
+typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */
+
+typedef histcell FAR * histptr; /* for pointers to histogram cells */
+
+typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
+typedef hist1d FAR * hist2d; /* type for the 2nd-level pointers */
+typedef hist2d * hist3d; /* type for top-level pointer */
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array has (#columns + 2) entries; the extra entry at
+ * each end saves us from special-casing the first and last pixels.
+ * Each entry is three values long, one value for each color component.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Space for the eventually created colormap is stashed here */
+ JSAMPARRAY sv_colormap; /* colormap allocated at init time */
+ int desired; /* desired # of colors = size of colormap */
+
+ /* Variables for accumulating image statistics */
+ hist3d histogram; /* pointer to the histogram */
+
+ boolean needs_zeroed; /* TRUE if next pass must zero histogram */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+ int * error_limiter; /* table for clamping the applied error */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Prescan some rows of pixels.
+ * In this module the prescan simply updates the histogram, which has been
+ * initialized to zeroes by start_pass.
+ * An output_buf parameter is required by the method signature, but no data
+ * is actually output (in fact the buffer controller is probably passing a
+ * NULL pointer).
+ */
+
+METHODDEF(void)
+prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW ptr;
+ register histptr histp;
+ register hist3d histogram = cquantize->histogram;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptr = input_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the histogram */
+ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+ [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+ [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
+ /* increment, check for overflow and undo increment if so. */
+ if (++(*histp) <= 0)
+ (*histp)--;
+ ptr += 3;
+ }
+ }
+}
+
+
+/*
+ * Next we have the really interesting routines: selection of a colormap
+ * given the completed histogram.
+ * These routines work with a list of "boxes", each representing a rectangular
+ * subset of the input color space (to histogram precision).
+ */
+
+typedef struct {
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
+ int c0min, c0max;
+ int c1min, c1max;
+ int c2min, c2max;
+ /* The volume (actually 2-norm) of the box */
+ INT32 volume;
+ /* The number of nonzero histogram cells within this box */
+ long colorcount;
+} box;
+
+typedef box * boxptr;
+
+
+LOCAL(boxptr)
+find_biggest_color_pop (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest color population */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register long maxc = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->colorcount > maxc && boxp->volume > 0) {
+ which = boxp;
+ maxc = boxp->colorcount;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(boxptr)
+find_biggest_volume (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest (scaled) volume */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register INT32 maxv = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->volume > maxv) {
+ which = boxp;
+ maxv = boxp->volume;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(void)
+update_box (j_decompress_ptr cinfo, boxptr boxp)
+/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
+/* and recompute its volume and population */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ INT32 dist0,dist1,dist2;
+ long ccount;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ if (c0max > c0min)
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0min = c0min = c0;
+ goto have_c0min;
+ }
+ }
+ have_c0min:
+ if (c0max > c0min)
+ for (c0 = c0max; c0 >= c0min; c0--)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0max = c0max = c0;
+ goto have_c0max;
+ }
+ }
+ have_c0max:
+ if (c1max > c1min)
+ for (c1 = c1min; c1 <= c1max; c1++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1min = c1min = c1;
+ goto have_c1min;
+ }
+ }
+ have_c1min:
+ if (c1max > c1min)
+ for (c1 = c1max; c1 >= c1min; c1--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1max = c1max = c1;
+ goto have_c1max;
+ }
+ }
+ have_c1max:
+ if (c2max > c2min)
+ for (c2 = c2min; c2 <= c2max; c2++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2min = c2min = c2;
+ goto have_c2min;
+ }
+ }
+ have_c2min:
+ if (c2max > c2min)
+ for (c2 = c2max; c2 >= c2min; c2--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2max = c2max = c2;
+ goto have_c2max;
+ }
+ }
+ have_c2max:
+
+ /* Update box volume.
+ * We use 2-norm rather than real volume here; this biases the method
+ * against making long narrow boxes, and it has the side benefit that
+ * a box is splittable iff norm > 0.
+ * Since the differences are expressed in histogram-cell units,
+ * we have to shift back to JSAMPLE units to get consistent distances;
+ * after which, we scale according to the selected distance scale factors.
+ */
+ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
+ dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+ dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+ boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+
+ /* Now scan remaining volume of box and compute population */
+ ccount = 0;
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++, histp++)
+ if (*histp != 0) {
+ ccount++;
+ }
+ }
+ boxp->colorcount = ccount;
+}
+
+
+LOCAL(int)
+median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+ int desired_colors)
+/* Repeatedly select and split the largest box until we have enough boxes */
+{
+ int n,lb;
+ int c0,c1,c2,cmax;
+ register boxptr b1,b2;
+
+ while (numboxes < desired_colors) {
+ /* Select box to split.
+ * Current algorithm: by population for first half, then by volume.
+ */
+ if (numboxes*2 <= desired_colors) {
+ b1 = find_biggest_color_pop(boxlist, numboxes);
+ } else {
+ b1 = find_biggest_volume(boxlist, numboxes);
+ }
+ if (b1 == NULL) /* no splittable boxes left! */
+ break;
+ b2 = &boxlist[numboxes]; /* where new box will go */
+ /* Copy the color bounds to the new box. */
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ /* Choose which axis to split the box on.
+ * Current algorithm: longest scaled axis.
+ * See notes in update_box about scaling distances.
+ */
+ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
+ c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
+ c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
+ /* We want to break any ties in favor of green, then red, blue last.
+ * This code does the right thing for R,G,B or B,G,R color orders only.
+ */
+#if RGB_RED == 0
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
+ if (c2 > cmax) { n = 2; }
+#else
+ cmax = c1; n = 1;
+ if (c2 > cmax) { cmax = c2; n = 2; }
+ if (c0 > cmax) { n = 0; }
+#endif
+ /* Choose split point along selected axis, and update box bounds.
+ * Current algorithm: split at halfway point.
+ * (Since the box has been shrunk to minimum volume,
+ * any split will produce two nonempty subboxes.)
+ * Note that lb value is max for lower box, so must be < old max.
+ */
+ switch (n) {
+ case 0:
+ lb = (b1->c0max + b1->c0min) / 2;
+ b1->c0max = lb;
+ b2->c0min = lb+1;
+ break;
+ case 1:
+ lb = (b1->c1max + b1->c1min) / 2;
+ b1->c1max = lb;
+ b2->c1min = lb+1;
+ break;
+ case 2:
+ lb = (b1->c2max + b1->c2min) / 2;
+ b1->c2max = lb;
+ b2->c2min = lb+1;
+ break;
+ }
+ /* Update stats for boxes */
+ update_box(cinfo, b1);
+ update_box(cinfo, b2);
+ numboxes++;
+ }
+ return numboxes;
+}
+
+
+LOCAL(void)
+compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+/* Compute representative color for a box, put it in colormap[icolor] */
+{
+ /* Current algorithm: mean weighted by pixels (not colors) */
+ /* Note it is important to get the rounding correct! */
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ long count;
+ long total = 0;
+ long c0total = 0;
+ long c1total = 0;
+ long c2total = 0;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++) {
+ if ((count = *histp++) != 0) {
+ total += count;
+ c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ }
+ }
+ }
+
+ cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+ cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+ cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+}
+
+
+LOCAL(void)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
+/* Master routine for color selection */
+{
+ boxptr boxlist;
+ int numboxes;
+ int i;
+
+ /* Allocate workspace for box list */
+ boxlist = (boxptr) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
+ /* Initialize one box containing whole space */
+ numboxes = 1;
+ boxlist[0].c0min = 0;
+ boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
+ boxlist[0].c1min = 0;
+ boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
+ boxlist[0].c2min = 0;
+ boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
+ /* Shrink it to actually-used volume and set its statistics */
+ update_box(cinfo, & boxlist[0]);
+ /* Perform median-cut to produce final box list */
+ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
+ /* Compute the representative color for each box, fill colormap */
+ for (i = 0; i < numboxes; i++)
+ compute_color(cinfo, & boxlist[i], i);
+ cinfo->actual_number_of_colors = numboxes;
+ TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
+}
+
+
+/*
+ * These routines are concerned with the time-critical task of mapping input
+ * colors to the nearest color in the selected colormap.
+ *
+ * We re-use the histogram space as an "inverse color map", essentially a
+ * cache for the results of nearest-color searches. All colors within a
+ * histogram cell will be mapped to the same colormap entry, namely the one
+ * closest to the cell's center. This may not be quite the closest entry to
+ * the actual input color, but it's almost as good. A zero in the cache
+ * indicates we haven't found the nearest color for that cell yet; the array
+ * is cleared to zeroes before starting the mapping pass. When we find the
+ * nearest color for a cell, its colormap index plus one is recorded in the
+ * cache for future use. The pass2 scanning routines call fill_inverse_cmap
+ * when they need to use an unfilled entry in the cache.
+ *
+ * Our method of efficiently finding nearest colors is based on the "locally
+ * sorted search" idea described by Heckbert and on the incremental distance
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
+ * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
+ * the distances from a given colormap entry to each cell of the histogram can
+ * be computed quickly using an incremental method: the differences between
+ * distances to adjacent cells themselves differ by a constant. This allows a
+ * fairly fast implementation of the "brute force" approach of computing the
+ * distance from every colormap entry to every histogram cell. Unfortunately,
+ * it needs a work array to hold the best-distance-so-far for each histogram
+ * cell (because the inner loop has to be over cells, not colormap entries).
+ * The work array elements have to be INT32s, so the work array would need
+ * 256Kb at our recommended precision. This is not feasible in DOS machines.
+ *
+ * To get around these problems, we apply Thomas' method to compute the
+ * nearest colors for only the cells within a small subbox of the histogram.
+ * The work array need be only as big as the subbox, so the memory usage
+ * problem is solved. Furthermore, we need not fill subboxes that are never
+ * referenced in pass2; many images use only part of the color gamut, so a
+ * fair amount of work is saved. An additional advantage of this
+ * approach is that we can apply Heckbert's locality criterion to quickly
+ * eliminate colormap entries that are far away from the subbox; typically
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
+ * and we need not compute their distances to individual cells in the subbox.
+ * The speed of this approach is heavily influenced by the subbox size: too
+ * small means too much overhead, too big loses because Heckbert's criterion
+ * can't eliminate as many colormap entries. Empirically the best subbox
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
+ *
+ * Thomas' article also describes a refined method which is asymptotically
+ * faster than the brute-force method, but it is also far more complex and
+ * cannot efficiently be applied to small subboxes. It is therefore not
+ * useful for programs intended to be portable to DOS machines. On machines
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
+ * refined method might be faster than the present code --- but then again,
+ * it might not be any faster, and it's certainly more complicated.
+ */
+
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_C0_LOG (HIST_C0_BITS-3)
+#define BOX_C1_LOG (HIST_C1_BITS-3)
+#define BOX_C2_LOG (HIST_C2_BITS-3)
+
+#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
+#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+
+#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
+#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
+#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG)
+
+
+/*
+ * The next three routines implement inverse colormap filling. They could
+ * all be folded into one big routine, but splitting them up this way saves
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
+ * and may allow some compilers to produce better code by registerizing more
+ * inner-loop variables.
+ */
+
+LOCAL(int)
+find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ JSAMPLE colorlist[])
+/* Locate the colormap entries close enough to an update box to be candidates
+ * for the nearest entry to some cell(s) in the update box. The update box
+ * is specified by the center coordinates of its first cell. The number of
+ * candidate colormap entries is returned, and their colormap indexes are
+ * placed in colorlist[].
+ * This routine uses Heckbert's "locally sorted search" criterion to select
+ * the colors that need further consideration.
+ */
+{
+ int numcolors = cinfo->actual_number_of_colors;
+ int maxc0, maxc1, maxc2;
+ int centerc0, centerc1, centerc2;
+ int i, x, ncolors;
+ INT32 minmaxdist, min_dist, max_dist, tdist;
+ INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
+
+ /* Compute true coordinates of update box's upper corner and center.
+ * Actually we compute the coordinates of the center of the upper-corner
+ * histogram cell, which are the upper bounds of the volume we care about.
+ * Note that since ">>" rounds down, the "center" values may be closer to
+ * min than to max; hence comparisons to them must be "<=", not "<".
+ */
+ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
+ centerc0 = (minc0 + maxc0) >> 1;
+ maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
+ centerc1 = (minc1 + maxc1) >> 1;
+ maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
+ centerc2 = (minc2 + maxc2) >> 1;
+
+ /* For each color in colormap, find:
+ * 1. its minimum squared-distance to any point in the update box
+ * (zero if color is within update box);
+ * 2. its maximum squared-distance to any point in the update box.
+ * Both of these can be found by considering only the corners of the box.
+ * We save the minimum distance for each color in mindist[];
+ * only the smallest maximum distance is of interest.
+ */
+ minmaxdist = 0x7FFFFFFFL;
+
+ for (i = 0; i < numcolors; i++) {
+ /* We compute the squared-c0-distance term, then add in the other two. */
+ x = GETJSAMPLE(cinfo->colormap[0][i]);
+ if (x < minc0) {
+ tdist = (x - minc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else if (x > maxc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ min_dist = 0;
+ if (x <= centerc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[1][i]);
+ if (x < minc1) {
+ tdist = (x - minc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[2][i]);
+ if (x < minc2) {
+ tdist = (x - minc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ mindist[i] = min_dist; /* save away the results */
+ if (max_dist < minmaxdist)
+ minmaxdist = max_dist;
+ }
+
+ /* Now we know that no cell in the update box is more than minmaxdist
+ * away from some colormap entry. Therefore, only colors that are
+ * within minmaxdist of some part of the box need be considered.
+ */
+ ncolors = 0;
+ for (i = 0; i < numcolors; i++) {
+ if (mindist[i] <= minmaxdist)
+ colorlist[ncolors++] = (JSAMPLE) i;
+ }
+ return ncolors;
+}
+
+
+LOCAL(void)
+find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+/* Find the closest colormap entry for each cell in the update box,
+ * given the list of candidate colors prepared by find_nearby_colors.
+ * Return the indexes of the closest entries in the bestcolor[] array.
+ * This routine uses Thomas' incremental distance calculation method to
+ * find the distance from a colormap entry to successive cells in the box.
+ */
+{
+ int ic0, ic1, ic2;
+ int i, icolor;
+ register INT32 * bptr; /* pointer into bestdist[] array */
+ JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ INT32 dist0, dist1; /* initial distance values */
+ register INT32 dist2; /* current distance in inner loop */
+ INT32 xx0, xx1; /* distance increments */
+ register INT32 xx2;
+ INT32 inc0, inc1, inc2; /* initial values for increments */
+ /* This array holds the distance to the nearest-so-far color for each cell */
+ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Initialize best-distance for each cell of the update box */
+ bptr = bestdist;
+ for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ *bptr++ = 0x7FFFFFFFL;
+
+ /* For each color selected by find_nearby_colors,
+ * compute its distance to the center of each cell in the box.
+ * If that's less than best-so-far, update best distance and color number.
+ */
+
+ /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE)
+#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE)
+#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
+
+ for (i = 0; i < numcolors; i++) {
+ icolor = GETJSAMPLE(colorlist[i]);
+ /* Compute (square of) distance from minc0/c1/c2 to this color */
+ inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
+ dist0 = inc0*inc0;
+ inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
+ dist0 += inc1*inc1;
+ inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
+ dist0 += inc2*inc2;
+ /* Form the initial difference increments */
+ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
+ inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
+ inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
+ /* Now loop over all cells in box, updating distance per Thomas method */
+ bptr = bestdist;
+ cptr = bestcolor;
+ xx0 = inc0;
+ for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ dist1 = dist0;
+ xx1 = inc1;
+ for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ dist2 = dist1;
+ xx2 = inc2;
+ for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ if (dist2 < *bptr) {
+ *bptr = dist2;
+ *cptr = (JSAMPLE) icolor;
+ }
+ dist2 += xx2;
+ xx2 += 2 * STEP_C2 * STEP_C2;
+ bptr++;
+ cptr++;
+ }
+ dist1 += xx1;
+ xx1 += 2 * STEP_C1 * STEP_C1;
+ }
+ dist0 += xx0;
+ xx0 += 2 * STEP_C0 * STEP_C0;
+ }
+ }
+}
+
+
+LOCAL(void)
+fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+/* Fill the inverse-colormap entries in the update box that contains */
+/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */
+/* we can fill as many others as we wish.) */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int minc0, minc1, minc2; /* lower left corner of update box */
+ int ic0, ic1, ic2;
+ register JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ register histptr cachep; /* pointer into main cache array */
+ /* This array lists the candidate colormap indexes. */
+ JSAMPLE colorlist[MAXNUMCOLORS];
+ int numcolors; /* number of candidate colors */
+ /* This array holds the actually closest colormap index for each cell. */
+ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Convert cell coordinates to update box ID */
+ c0 >>= BOX_C0_LOG;
+ c1 >>= BOX_C1_LOG;
+ c2 >>= BOX_C2_LOG;
+
+ /* Compute true coordinates of update box's origin corner.
+ * Actually we compute the coordinates of the center of the corner
+ * histogram cell, which are the lower bounds of the volume we care about.
+ */
+ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+ minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+ minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+
+ /* Determine which colormap entries are close enough to be candidates
+ * for the nearest entry to some cell in the update box.
+ */
+ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
+
+ /* Determine the actually nearest colors. */
+ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
+ bestcolor);
+
+ /* Save the best color numbers (plus 1) in the main cache array */
+ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */
+ c1 <<= BOX_C1_LOG;
+ c2 <<= BOX_C2_LOG;
+ cptr = bestcolor;
+ for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
+ for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
+ cachep = & histogram[c0+ic0][c1+ic1][c2];
+ for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
+ *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+ }
+ }
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+pass2_no_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register JSAMPROW inptr, outptr;
+ register histptr cachep;
+ register int c0, c1, c2;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the cache */
+ c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
+ c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
+ c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
+ cachep = & histogram[c0][c1][c2];
+ /* If we have not seen this color before, find nearest colormap entry */
+ /* and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, c0,c1,c2);
+ /* Now emit the colormap index for this cell */
+ *outptr++ = (JSAMPLE) (*cachep - 1);
+ }
+ }
+}
+
+
+METHODDEF(void)
+pass2_fs_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
+ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
+ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ JSAMPROW inptr; /* => current input pixel */
+ JSAMPROW outptr; /* => current output pixel */
+ histptr cachep;
+ int dir; /* +1 or -1 depending on direction */
+ int dir3; /* 3*dir, for advancing inptr & errorptr */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *error_limit = cquantize->error_limiter;
+ JSAMPROW colormap0 = cinfo->colormap[0];
+ JSAMPROW colormap1 = cinfo->colormap[1];
+ JSAMPROW colormap2 = cinfo->colormap[2];
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ inptr += (width-1) * 3; /* so point to rightmost pixel */
+ outptr += width-1;
+ dir = -1;
+ dir3 = -3;
+ errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+ cquantize->on_odd_row = FALSE; /* flip for next time */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dir3 = 3;
+ errorptr = cquantize->fserrors; /* => entry before first real column */
+ cquantize->on_odd_row = TRUE; /* flip for next time */
+ }
+ /* Preset error values: no error propagated to first pixel from left */
+ cur0 = cur1 = cur2 = 0;
+ /* and no error propagated to row below yet */
+ belowerr0 = belowerr1 = belowerr2 = 0;
+ bpreverr0 = bpreverr1 = bpreverr2 = 0;
+
+ for (col = width; col > 0; col--) {
+ /* curN holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
+ cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
+ cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+ /* Limit the error using transfer function set by init_error_limit.
+ * See comments with init_error_limit for rationale.
+ */
+ cur0 = error_limit[cur0];
+ cur1 = error_limit[cur1];
+ cur2 = error_limit[cur2];
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE (or less with error limiting);
+ * this sets the required size of the range_limit array.
+ */
+ cur0 += GETJSAMPLE(inptr[0]);
+ cur1 += GETJSAMPLE(inptr[1]);
+ cur2 += GETJSAMPLE(inptr[2]);
+ cur0 = GETJSAMPLE(range_limit[cur0]);
+ cur1 = GETJSAMPLE(range_limit[cur1]);
+ cur2 = GETJSAMPLE(range_limit[cur2]);
+ /* Index into the cache with adjusted pixel value */
+ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+ /* If we have not seen this color before, find nearest colormap */
+ /* entry and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+ /* Now emit the colormap index for this cell */
+ { register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE) pixcode;
+ /* Compute representation error for this pixel */
+ cur0 -= GETJSAMPLE(colormap0[pixcode]);
+ cur1 -= GETJSAMPLE(colormap1[pixcode]);
+ cur2 -= GETJSAMPLE(colormap2[pixcode]);
+ }
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ { register LOCFSERROR bnexterr, delta;
+
+ bnexterr = cur0; /* Process component 0 */
+ delta = cur0 * 2;
+ cur0 += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr0 + cur0);
+ cur0 += delta; /* form error * 5 */
+ bpreverr0 = belowerr0 + cur0;
+ belowerr0 = bnexterr;
+ cur0 += delta; /* form error * 7 */
+ bnexterr = cur1; /* Process component 1 */
+ delta = cur1 * 2;
+ cur1 += delta; /* form error * 3 */
+ errorptr[1] = (FSERROR) (bpreverr1 + cur1);
+ cur1 += delta; /* form error * 5 */
+ bpreverr1 = belowerr1 + cur1;
+ belowerr1 = bnexterr;
+ cur1 += delta; /* form error * 7 */
+ bnexterr = cur2; /* Process component 2 */
+ delta = cur2 * 2;
+ cur2 += delta; /* form error * 3 */
+ errorptr[2] = (FSERROR) (bpreverr2 + cur2);
+ cur2 += delta; /* form error * 5 */
+ bpreverr2 = belowerr2 + cur2;
+ belowerr2 = bnexterr;
+ cur2 += delta; /* form error * 7 */
+ }
+ /* At this point curN contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ inptr += dir3; /* Advance pixel pointers to next column */
+ outptr += dir;
+ errorptr += dir3; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error values into the
+ * final fserrors[] entry. Note we need not unload belowerrN because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR) bpreverr1;
+ errorptr[2] = (FSERROR) bpreverr2;
+ }
+}
+
+
+/*
+ * Initialize the error-limiting transfer function (lookup table).
+ * The raw F-S error computation can potentially compute error values of up to
+ * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be
+ * much less, otherwise obviously wrong pixels will be created. (Typical
+ * effects include weird fringes at color-area boundaries, isolated bright
+ * pixels in a dark area, etc.) The standard advice for avoiding this problem
+ * is to ensure that the "corners" of the color cube are allocated as output
+ * colors; then repeated errors in the same direction cannot cause cascading
+ * error buildup. However, that only prevents the error from getting
+ * completely out of hand; Aaron Giles reports that error limiting improves
+ * the results even with corner colors allocated.
+ * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
+ * well, but the smoother transfer function used below is even better. Thanks
+ * to Aaron Giles for this idea.
+ */
+
+LOCAL(void)
+init_error_limit (j_decompress_ptr cinfo)
+/* Allocate and fill in the error_limiter table */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ int * table;
+ int in, out;
+
+ table = (int *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
+ table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
+ cquantize->error_limiter = table;
+
+#define STEPSIZE ((MAXJSAMPLE+1)/16)
+ /* Map errors 1:1 up to +- MAXJSAMPLE/16 */
+ out = 0;
+ for (in = 0; in < STEPSIZE; in++, out++) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
+ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
+ for (; in <= MAXJSAMPLE; in++) {
+ table[in] = out; table[-in] = -out;
+ }
+#undef STEPSIZE
+}
+
+
+/*
+ * Finish up at the end of each pass.
+ */
+
+METHODDEF(void)
+finish_pass1 (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Select the representative colors and fill in cinfo->colormap */
+ cinfo->colormap = cquantize->sv_colormap;
+ select_colors(cinfo, cquantize->desired);
+ /* Force next pass to zero the color index table */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+METHODDEF(void)
+finish_pass2 (j_decompress_ptr cinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * Initialize for each processing pass.
+ */
+
+METHODDEF(void)
+start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int i;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ if (is_pre_scan) {
+ /* Set up method pointers */
+ cquantize->pub.color_quantize = prescan_quantize;
+ cquantize->pub.finish_pass = finish_pass1;
+ cquantize->needs_zeroed = TRUE; /* Always zero histogram */
+ } else {
+ /* Set up method pointers */
+ if (cinfo->dither_mode == JDITHER_FS)
+ cquantize->pub.color_quantize = pass2_fs_dither;
+ else
+ cquantize->pub.color_quantize = pass2_no_dither;
+ cquantize->pub.finish_pass = finish_pass2;
+
+ /* Make sure color count is acceptable */
+ i = cinfo->actual_number_of_colors;
+ if (i < 1)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+ if (i > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+ if (cinfo->dither_mode == JDITHER_FS) {
+ size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+ (3 * SIZEOF(FSERROR)));
+ /* Allocate Floyd-Steinberg workspace if we didn't already. */
+ if (cquantize->fserrors == NULL)
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ /* Initialize the propagated errors to zero. */
+ jzero_far((void FAR *) cquantize->fserrors, arraysize);
+ /* Make the error-limit table if we didn't already. */
+ if (cquantize->error_limiter == NULL)
+ init_error_limit(cinfo);
+ cquantize->on_odd_row = FALSE;
+ }
+
+ }
+ /* Zero the histogram or inverse color map, if necessary */
+ if (cquantize->needs_zeroed) {
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ jzero_far((void FAR *) histogram[i],
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = FALSE;
+ }
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF(void)
+new_color_map_2_quant (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Reset the inverse color map */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+/*
+ * Module initialization routine for 2-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_2pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+ int i;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_2_quant;
+ cquantize->pub.new_color_map = new_color_map_2_quant;
+ cquantize->fserrors = NULL; /* flag optional arrays not allocated */
+ cquantize->error_limiter = NULL;
+
+ /* Make sure jdmaster didn't give me a case I can't handle */
+ if (cinfo->out_color_components != 3)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+
+ /* Allocate the histogram/inverse colormap storage */
+ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
+
+ /* Allocate storage for the completed colormap, if required.
+ * We do this now since it is FAR storage and may affect
+ * the memory manager's space calculations.
+ */
+ if (cinfo->enable_2pass_quant) {
+ /* Make sure color count is acceptable */
+ int desired = cinfo->desired_number_of_colors;
+ /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+ if (desired < 8)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (desired > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+ cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ cquantize->desired = desired;
+ } else
+ cquantize->sv_colormap = NULL;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ /* Allocate Floyd-Steinberg workspace if necessary.
+ * This isn't really needed until pass 2, but again it is FAR storage.
+ * Although we will cope with a later change in dither_mode,
+ * we do not promise to honor max_memory_to_use if dither_mode changes.
+ */
+ if (cinfo->dither_mode == JDITHER_FS) {
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+ /* Might as well create the error-limiting table too. */
+ init_error_limit(cinfo);
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/SrcShared/jpeg/jutils.c b/SrcShared/jpeg/jutils.c
new file mode 100644
index 0000000..d18a955
--- /dev/null
+++ b/SrcShared/jpeg/jutils.c
@@ -0,0 +1,179 @@
+/*
+ * jutils.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains tables and miscellaneous utility routines needed
+ * for both compression and decompression.
+ * Note we prefix all global names with "j" to minimize conflicts with
+ * a surrounding application.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
+ * of a DCT block read in natural order (left to right, top to bottom).
+ */
+
+#if 0 /* This table is not actually needed in v6a */
+
+const int jpeg_zigzag_order[DCTSIZE2] = {
+ 0, 1, 5, 6, 14, 15, 27, 28,
+ 2, 4, 7, 13, 16, 26, 29, 42,
+ 3, 8, 12, 17, 25, 30, 41, 43,
+ 9, 11, 18, 24, 31, 40, 44, 53,
+ 10, 19, 23, 32, 39, 45, 52, 54,
+ 20, 22, 33, 38, 46, 51, 55, 60,
+ 21, 34, 37, 47, 50, 56, 59, 61,
+ 35, 36, 48, 49, 57, 58, 62, 63
+};
+
+#endif
+
+/*
+ * jpeg_natural_order[i] is the natural-order position of the i'th element
+ * of zigzag order.
+ *
+ * When reading corrupted data, the Huffman decoders could attempt
+ * to reference an entry beyond the end of this array (if the decoded
+ * zero run length reaches past the end of the block). To prevent
+ * wild stores without adding an inner-loop test, we put some extra
+ * "63"s after the real entries. This will cause the extra coefficient
+ * to be stored in location 63 of the block, not somewhere random.
+ * The worst case would be a run-length of 15, which means we need 16
+ * fake entries.
+ */
+
+const int jpeg_natural_order[DCTSIZE2+16] = {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
+ 63, 63, 63, 63, 63, 63, 63, 63
+};
+
+
+/*
+ * Arithmetic utilities
+ */
+
+GLOBAL(long)
+jdiv_round_up (long a, long b)
+/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
+/* Assumes a >= 0, b > 0 */
+{
+ return (a + b - 1L) / b;
+}
+
+
+GLOBAL(long)
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+ a += b - 1L;
+ return a - (a % b);
+}
+
+
+/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
+ * and coefficient-block arrays. This won't work on 80x86 because the arrays
+ * are FAR and we're assuming a small-pointer memory model. However, some
+ * DOS compilers provide far-pointer versions of memcpy() and memset() even
+ * in the small-model libraries. These will be used if USE_FMEM is defined.
+ * Otherwise, the routines below do it the hard way. (The performance cost
+ * is not all that great, because these routines aren't very heavily used.)
+ */
+
+#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */
+#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size)
+#define FMEMZERO(target,size) MEMZERO(target,size)
+#else /* 80x86 case, define if we can */
+#ifdef USE_FMEM
+#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
+#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
+#endif
+#endif
+
+
+GLOBAL(void)
+jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas may overlap for duplication.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+ register JSAMPROW inptr, outptr;
+#ifdef FMEMCOPY
+ register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
+#else
+ register JDIMENSION count;
+#endif
+ register int row;
+
+ input_array += source_row;
+ output_array += dest_row;
+
+ for (row = num_rows; row > 0; row--) {
+ inptr = *input_array++;
+ outptr = *output_array++;
+#ifdef FMEMCOPY
+ FMEMCOPY(outptr, inptr, count);
+#else
+ for (count = num_cols; count > 0; count--)
+ *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
+#endif
+ }
+}
+
+
+GLOBAL(void)
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+#ifdef FMEMCOPY
+ FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
+#else
+ register JCOEFPTR inptr, outptr;
+ register long count;
+
+ inptr = (JCOEFPTR) input_row;
+ outptr = (JCOEFPTR) output_row;
+ for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
+ *outptr++ = *inptr++;
+ }
+#endif
+}
+
+
+GLOBAL(void)
+jzero_far (void FAR * target, size_t bytestozero)
+/* Zero out a chunk of FAR memory. */
+/* This might be sample-array data, block-array data, or alloc_large data. */
+{
+#ifdef FMEMZERO
+ FMEMZERO(target, bytestozero);
+#else
+ register char FAR * ptr = (char FAR *) target;
+ register size_t count;
+
+ for (count = bytestozero; count > 0; count--) {
+ *ptr++ = 0;
+ }
+#endif
+}
diff --git a/SrcShared/jpeg/jversion.h b/SrcShared/jpeg/jversion.h
new file mode 100644
index 0000000..6472c58
--- /dev/null
+++ b/SrcShared/jpeg/jversion.h
@@ -0,0 +1,14 @@
+/*
+ * jversion.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains software version identification.
+ */
+
+
+#define JVERSION "6b 27-Mar-1998"
+
+#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane"
diff --git a/SrcShared/omnithread/mach.cpp b/SrcShared/omnithread/mach.cpp
new file mode 100644
index 0000000..4c3c623
--- /dev/null
+++ b/SrcShared/omnithread/mach.cpp
@@ -0,0 +1,643 @@
+// Package : omnithread
+// omnithread/mach.cc Created : 7/97 lars immisch lars@ibp.de
+//
+// Copyright (C) 1997 Immisch, Becker & Partner
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+
+//
+// Implementation of OMNI thread abstraction for mach threads
+//
+// to the author's pleasure, mach cthreads are very similar to posix threads
+//
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <mach/cthreads.h>
+#include "omnithread.h"
+
+#define DB(x) // x
+// #include <iostream> or #include <iostream.h> if DB is on.
+
+#define ERRNO(x) (x)
+
+//
+// static variables
+//
+
+int omni_thread::init_t::count = 0;
+
+omni_mutex* omni_thread::next_id_mutex;
+int omni_thread::next_id = 0;
+
+static int normal_priority;
+static int highest_priority;
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_mutex::omni_mutex(void)
+{
+ mutex_init(&mach_mutex);
+}
+
+
+omni_mutex::~omni_mutex(void)
+{
+ mutex_clear(&mach_mutex);
+}
+
+
+void omni_mutex::lock(void)
+{
+ mutex_lock(&mach_mutex);
+}
+
+
+void omni_mutex::unlock(void)
+{
+ mutex_unlock(&mach_mutex);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_condition::omni_condition(omni_mutex* m) : mutex(m)
+{
+ condition_init(&mach_cond);
+}
+
+
+omni_condition::~omni_condition(void)
+{
+ condition_clear(&mach_cond);
+}
+
+void
+omni_condition::wait(void)
+{
+ condition_wait(&mach_cond, &mutex->mach_mutex);
+}
+
+typedef struct alarmclock_args {
+ unsigned long secs;
+ unsigned long nsecs;
+ bool wakeup;
+ condition_t condition;
+ mutex_t mutex;
+};
+
+any_t alarmclock(any_t arg)
+{
+ alarmclock_args* alarm = (alarmclock_args*)arg;
+
+ omni_thread::sleep(alarm->secs, alarm->nsecs);
+
+ mutex_lock(alarm->mutex);
+
+ alarm->wakeup = TRUE;
+
+ condition_signal(alarm->condition);
+
+ mutex_unlock(alarm->mutex);
+
+ return (any_t)TRUE;
+}
+
+int omni_condition::timedwait(unsigned long abs_secs, unsigned long abs_nsecs)
+{
+ alarmclock_args alarm;
+
+ omni_thread::get_time(&alarm.secs, &alarm.nsecs, 0, 0);
+
+ if (abs_secs < alarm.secs || (abs_secs == alarm.secs && abs_nsecs <= alarm.nsecs))
+ return ETIMEDOUT;
+
+ alarm.secs = abs_secs - alarm.secs;
+ if (abs_nsecs <= alarm.nsecs) {
+ alarm.nsecs = 1000000 - alarm.nsecs + abs_nsecs;
+ alarm.secs--;
+ }
+ else {
+ alarm.nsecs = abs_nsecs - alarm.nsecs;
+ }
+
+ alarm.mutex = &mutex->mach_mutex;
+ alarm.condition = &mach_cond;
+ alarm.wakeup = FALSE;
+
+ cthread_t ct = cthread_fork((cthread_fn_t)alarmclock, (any_t)&alarm);
+ cthread_detach(ct);
+
+ condition_wait(&mach_cond, &mutex->mach_mutex);
+
+ if (alarm.wakeup) {
+ return 0;
+ }
+
+ // interrupt the alarmclock thread sleep
+ cthread_abort(ct);
+
+ // wait until it has signalled the condition
+ condition_wait(&mach_cond, &mutex->mach_mutex);
+
+ return 1;
+}
+
+
+void omni_condition::signal(void)
+{
+ condition_signal(&mach_cond);
+}
+
+
+void omni_condition::broadcast(void)
+{
+ condition_signal(&mach_cond);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_semaphore::omni_semaphore(unsigned int initial) : c(&m)
+{
+ value = initial;
+}
+
+
+omni_semaphore::~omni_semaphore(void)
+{
+}
+
+
+void
+omni_semaphore::wait(void)
+{
+ omni_mutex_lock l(m);
+
+ while (value == 0)
+ c.wait();
+
+ value--;
+}
+
+
+int
+omni_semaphore::trywait(void)
+{
+ omni_mutex_lock l(m);
+
+ if (value == 0)
+ return 0;
+
+ value--;
+}
+
+
+void
+omni_semaphore::post(void)
+{
+ omni_mutex_lock l(m);
+
+ if (value == 0)
+ c.signal();
+
+ value++;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//
+// Initialisation function (gets called before any user code).
+//
+
+omni_thread::init_t::init_t(void)
+{
+ if (count++ != 0) // only do it once however many objects get created.
+ return;
+
+ //
+ // find base and max priority.
+ // This is the initial thread, so the max priority of this
+ // thread also applies to any newly created thread.
+ //
+
+ kern_return_t error;
+ struct thread_sched_info info;
+ unsigned int info_count = THREAD_SCHED_INFO_COUNT;
+
+ error = thread_info(thread_self(), THREAD_SCHED_INFO, (thread_info_t)&info, &info_count);
+ if (error != KERN_SUCCESS) {
+ cerr << "omni_thread::init: error determining thread_info" << endl;
+ ::exit(1);
+ }
+ else {
+ normal_priority = info.base_priority;
+ highest_priority = info.max_priority;
+ }
+
+ next_id_mutex = new omni_mutex;
+
+ //
+ // Create object for this (i.e. initial) thread.
+ //
+
+ omni_thread* t = new omni_thread;
+
+ if (t->_state != STATE_NEW) {
+ cerr << "omni_thread::init: problem creating initial thread object\n";
+ ::exit(1);
+ }
+
+ t->_state = STATE_RUNNING;
+
+ t->mach_thread = cthread_self();
+
+ DB(cerr << "initial thread " << t->id() << endl);
+
+ cthread_set_data(t->mach_thread, (any_t)t);
+}
+
+
+//
+// Wrapper for thread creation.
+//
+
+extern "C" void*
+omni_thread_wrapper(void* ptr)
+{
+ omni_thread* me = (omni_thread*)ptr;
+
+ DB(cerr << "omni_thread::wrapper: thread " << me->id()
+ << " started\n");
+
+ cthread_set_data(cthread_self(), (any_t)me);
+
+ //
+ // Now invoke the thread function with the given argument.
+ //
+
+ if (me->fn_void != NULL) {
+ (*me->fn_void)(me->thread_arg);
+ omni_thread::exit();
+ }
+
+ if (me->fn_ret != NULL) {
+ void* return_value = (*me->fn_ret)(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ if (me->detached) {
+ me->run(me->thread_arg);
+ omni_thread::exit();
+ } else {
+ void* return_value = me->run_undetached(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ // should never get here.
+
+ return NULL;
+}
+
+
+//
+// Constructors for omni_thread - set up the thread object but don't
+// start it running.
+//
+
+// construct a detached thread running a given function.
+
+omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = fn;
+ fn_ret = NULL;
+}
+
+// construct an undetached thread running a given function.
+
+omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 0);
+ fn_void = NULL;
+ fn_ret = fn;
+}
+
+// construct a thread which will run either run() or run_undetached().
+
+omni_thread::omni_thread(void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = NULL;
+ fn_ret = NULL;
+}
+
+// common part of all constructors.
+
+void omni_thread::common_constructor(void* arg, priority_t pri, int det)
+{
+ _state = STATE_NEW;
+ _priority = pri;
+
+ next_id_mutex->lock();
+ _id = next_id++;
+ next_id_mutex->unlock();
+
+ thread_arg = arg;
+ detached = det; // may be altered in start_undetached()
+
+ // posix_thread is set up in initialisation routine or start().
+}
+
+
+//
+// Destructor for omni_thread.
+//
+
+omni_thread::~omni_thread(void)
+{
+ DB(cerr << "destructor called for thread " << id() << endl);
+}
+
+
+//
+// Start the thread
+//
+
+void
+omni_thread::start(void)
+{
+ omni_mutex_lock l(mutex);
+
+ int rc;
+
+ if (_state != STATE_NEW)
+ throw omni_thread_invalid();
+
+ mach_thread = cthread_fork(omni_thread_wrapper, (any_t)this);
+
+ _state = STATE_RUNNING;
+
+ if (detached) {
+ cthread_detach(mach_thread);
+ }
+}
+
+//
+// Start a thread which will run the member function run_undetached().
+//
+
+void
+omni_thread::start_undetached(void)
+{
+ if ((fn_void != NULL) || (fn_ret != NULL))
+ throw omni_thread_invalid();
+
+ detached = 0;
+ start();
+}
+
+
+//
+// join - simply check error conditions & call cthread_join.
+//
+
+void
+omni_thread::join(void** status)
+{
+ mutex.lock();
+
+ if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
+ mutex.unlock();
+ throw omni_thread_invalid();
+ }
+
+ mutex.unlock();
+
+ if (this == self())
+ throw omni_thread_invalid();
+
+ if (detached)
+ throw omni_thread_invalid();
+
+ DB(cerr << "omni_thread::join: doing cthread_join\n");
+
+ *status = cthread_join(mach_thread);
+
+ delete this;
+}
+
+
+//
+// Change this thread's priority.
+//
+
+void
+omni_thread::set_priority(priority_t pri)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_RUNNING)
+ throw omni_thread_invalid();
+
+ _priority = pri;
+
+ kern_return_t rc = cthread_priority(mach_thread, mach_priority(pri), FALSE);
+
+ if (rc != KERN_SUCCESS)
+ throw omni_thread_fatal(errno);
+}
+
+//
+// create - construct a new thread object and start it running. Returns thread
+// object if successful, null pointer if not.
+//
+
+// detached version
+
+omni_thread*
+omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+// undetached version
+
+omni_thread*
+omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+//
+// exit() _must_ lock the mutex even in the case of a detached thread. This is
+// because a thread may run to completion before the thread that created it has
+// had a chance to get out of start(). By locking the mutex we ensure that the
+// creating thread must have reached the end of start() before we delete the
+// thread object. Of course, once the call to start() returns, the user can
+// still incorrectly refer to the thread object, but that's their problem.
+//
+
+void omni_thread::exit(void* return_value)
+{
+ omni_thread* me = self();
+
+ if (me)
+ {
+ me->mutex.lock();
+
+ if (me->_state != STATE_RUNNING)
+ cerr << "omni_thread::exit: thread not in \"running\" state\n";
+
+ me->_state = STATE_TERMINATED;
+
+ me->mutex.unlock();
+
+ DB(cerr << "omni_thread::exit: thread " << me->id() << " detached "
+ << me->detached << " return value " << return_value << endl);
+
+ if (me->detached)
+ delete me;
+ }
+ else
+ {
+ DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl);
+ }
+ cthread_exit(return_value);
+}
+
+omni_thread* omni_thread::self(void)
+{
+ omni_thread* me;
+
+ me = (omni_thread*)cthread_data(cthread_self());
+
+ if (!me) {
+ // This thread is not created by omni_thread::start because it
+ // doesn't has a class omni_thread instance attached to its key.
+ DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl);
+ }
+
+ return me;
+}
+
+void omni_thread::yield(void)
+{
+ cthread_yield();
+}
+
+#define MAX_SLEEP_SECONDS (unsigned)4294966 // (2**32-2)/1000
+
+void
+omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
+{
+ if (secs <= MAX_SLEEP_SECONDS) {
+ thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, secs * 1000 + nanosecs / 1000000);
+ return;
+ }
+
+ unsigned no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;
+
+ for (unsigned i = 0; i < no_of_max_sleeps; i++)
+ thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, MAX_SLEEP_SECONDS * 1000);
+
+ thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT,
+ (secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000);
+
+ return;
+}
+
+void
+omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec, unsigned long rel_nsec)
+{
+ int rc;
+ unsigned long tv_sec;
+ unsigned long tv_nsec;
+ struct timeval tv;
+
+ rc = gettimeofday(&tv, NULL);
+ if (rc) throw omni_thread_fatal(rc);
+
+ tv_sec = tv.tv_sec;
+ tv_nsec = tv.tv_usec * 1000;
+
+ tv_nsec += rel_nsec;
+ tv_sec += rel_sec + tv_nsec / 1000000000;
+ tv_nsec = tv_nsec % 1000000000;
+
+ *abs_sec = tv_sec;
+ *abs_nsec = tv_nsec;
+}
+
+
+int
+omni_thread::mach_priority(priority_t pri)
+{
+ switch (pri) {
+
+ case PRIORITY_LOW:
+ return 0;
+
+ case PRIORITY_NORMAL:
+ return normal_priority;
+
+ case PRIORITY_HIGH:
+ return highest_priority;
+
+ default:
+ return -1;
+ }
+}
+
diff --git a/SrcShared/omnithread/mach.h b/SrcShared/omnithread/mach.h
new file mode 100644
index 0000000..483f600
--- /dev/null
+++ b/SrcShared/omnithread/mach.h
@@ -0,0 +1,51 @@
+// Package : omnithread
+// omnithread/posix.h Created : 7/97 lars immisch lars@ibp.de
+//
+// Copyright (C) 1994,1995,1996, 1997 Immisch, becker & Partner
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+//
+// OMNI thread implementation classes for posix threads
+//
+
+#ifndef __omnithread_mach_h_
+#define __omnithread_mach_h_
+
+#include <mach/cthreads.h>
+
+extern "C" void* omni_thread_wrapper(void* ptr);
+
+#define OMNI_MUTEX_IMPLEMENTATION \
+ struct mutex mach_mutex;
+
+#define OMNI_CONDITION_IMPLEMENTATION \
+ struct condition mach_cond;
+
+#define OMNI_SEMAPHORE_IMPLEMENTATION \
+ omni_mutex m; \
+ omni_condition c; \
+ int value;
+
+
+#define OMNI_THREAD_IMPLEMENTATION \
+ cthread_t mach_thread; \
+ static int mach_priority(priority_t); \
+ friend void* omni_thread_wrapper(void* ptr);
+
+#endif
diff --git a/SrcShared/omnithread/nt.cpp b/SrcShared/omnithread/nt.cpp
new file mode 100644
index 0000000..8a994bc
--- /dev/null
+++ b/SrcShared/omnithread/nt.cpp
@@ -0,0 +1,876 @@
+// Package : omnithread
+// omnithread/nt.cc Created : 6/95 tjr
+//
+// Copyright (C) 1995-1999 AT&T Laboratories Cambridge
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+
+//
+// Implementation of OMNI thread abstraction for NT threads
+//
+
+#include <stdlib.h>
+#include <errno.h>
+#include <omnithread.h>
+#include <process.h>
+
+#define DB(x) // x
+//#include <iostream.h> or #include <iostream> if DB is on.
+
+static void get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec);
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_mutex::omni_mutex(void)
+{
+ InitializeCriticalSection(&crit);
+}
+
+omni_mutex::~omni_mutex(void)
+{
+ DeleteCriticalSection(&crit);
+}
+
+void
+omni_mutex::lock(void)
+{
+ EnterCriticalSection(&crit);
+}
+
+void
+omni_mutex::unlock(void)
+{
+ LeaveCriticalSection(&crit);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//
+// Condition variables are tricky to implement using NT synchronisation
+// primitives, since none of them have the atomic "release mutex and wait to be
+// signalled" which is central to the idea of a condition variable. To get
+// around this the solution is to record which threads are waiting and
+// explicitly wake up those threads.
+//
+// Here we implement a condition variable using a list of waiting threads
+// (protected by a critical section), and a per-thread semaphore (which
+// actually only needs to be a binary semaphore).
+//
+// To wait on the cv, a thread puts itself on the list of waiting threads for
+// that cv, then releases the mutex and waits on its own personal semaphore. A
+// signalling thread simply takes a thread from the head of the list and kicks
+// that thread's semaphore. Broadcast is simply implemented by kicking the
+// semaphore of each waiting thread.
+//
+// The only other tricky part comes when a thread gets a timeout from a timed
+// wait on its semaphore. Between returning with a timeout from the wait and
+// entering the critical section, a signalling thread could get in, kick the
+// waiting thread's semaphore and remove it from the list. If this happens,
+// the waiting thread's semaphore is now out of step so it needs resetting, and
+// the thread should indicate that it was signalled rather than that it timed
+// out.
+//
+// It is possible that the thread calling wait or timedwait is not a
+// omni_thread. In this case we have to provide a temporary data structure,
+// i.e. for the duration of the call, for the thread to link itself on the
+// list of waiting threads. _internal_omni_thread_dummy provides such
+// a data structure and _internal_omni_thread_helper is a helper class to
+// deal with this special case for wait() and timedwait(). Once created,
+// the _internal_omni_thread_dummy is cached for use by the next wait() or
+// timedwait() call from a non-omni_thread. This is probably worth doing
+// because creating a Semaphore is quite heavy weight.
+
+class _internal_omni_thread_helper;
+
+class _internal_omni_thread_dummy : public omni_thread {
+public:
+ inline _internal_omni_thread_dummy() : next(0) { }
+ inline ~_internal_omni_thread_dummy() { }
+ friend class _internal_omni_thread_helper;
+private:
+ _internal_omni_thread_dummy* next;
+};
+
+class _internal_omni_thread_helper {
+public:
+ inline _internal_omni_thread_helper() {
+ d = 0;
+ t = omni_thread::self();
+ if (!t) {
+ omni_mutex_lock sync(cachelock);
+ if (cache) {
+ d = cache;
+ cache = cache->next;
+ }
+ else {
+ d = new _internal_omni_thread_dummy;
+ }
+ t = d;
+ }
+ }
+ inline ~_internal_omni_thread_helper() {
+ if (d) {
+ omni_mutex_lock sync(cachelock);
+ d->next = cache;
+ cache = d;
+ }
+ }
+ inline operator omni_thread* () { return t; }
+ inline omni_thread* operator->() { return t; }
+
+ static _internal_omni_thread_dummy* cache;
+ static omni_mutex cachelock;
+
+private:
+ _internal_omni_thread_dummy* d;
+ omni_thread* t;
+};
+
+_internal_omni_thread_dummy* _internal_omni_thread_helper::cache = 0;
+omni_mutex _internal_omni_thread_helper::cachelock;
+
+
+omni_condition::omni_condition(omni_mutex* m) : mutex(m)
+{
+ InitializeCriticalSection(&crit);
+ waiting_head = waiting_tail = NULL;
+}
+
+
+omni_condition::~omni_condition(void)
+{
+ DeleteCriticalSection(&crit);
+ DB( if (waiting_head != NULL) {
+ cerr << "omni_condition::~omni_condition: list of waiting threads "
+ << "is not empty\n";
+ } )
+}
+
+
+void
+omni_condition::wait(void)
+{
+ _internal_omni_thread_helper me;
+
+ EnterCriticalSection(&crit);
+
+ me->cond_next = NULL;
+ me->cond_prev = waiting_tail;
+ if (waiting_head == NULL)
+ waiting_head = me;
+ else
+ waiting_tail->cond_next = me;
+ waiting_tail = me;
+ me->cond_waiting = TRUE;
+
+ LeaveCriticalSection(&crit);
+
+ mutex->unlock();
+
+ DWORD result = WaitForSingleObject(me->cond_semaphore, INFINITE);
+
+ mutex->lock();
+
+ if (result != WAIT_OBJECT_0)
+ throw omni_thread_fatal(GetLastError());
+}
+
+
+int
+omni_condition::timedwait(unsigned long abs_sec, unsigned long abs_nsec)
+{
+ _internal_omni_thread_helper me;
+
+ EnterCriticalSection(&crit);
+
+ me->cond_next = NULL;
+ me->cond_prev = waiting_tail;
+ if (waiting_head == NULL)
+ waiting_head = me;
+ else
+ waiting_tail->cond_next = me;
+ waiting_tail = me;
+ me->cond_waiting = TRUE;
+
+ LeaveCriticalSection(&crit);
+
+ mutex->unlock();
+
+ unsigned long now_sec, now_nsec;
+
+ get_time_now(&now_sec, &now_nsec);
+
+ DWORD timeout;
+ if ((abs_sec <= now_sec) && ((abs_sec < now_sec) || (abs_nsec < now_nsec)))
+ timeout = 0;
+ else {
+ timeout = (abs_sec-now_sec) * 1000;
+
+ if( abs_nsec < now_nsec ) timeout -= (now_nsec-abs_nsec) / 1000000;
+ else timeout += (abs_nsec-now_nsec) / 1000000;
+ }
+
+ DWORD result = WaitForSingleObject(me->cond_semaphore, timeout);
+
+ if (result == WAIT_TIMEOUT) {
+ EnterCriticalSection(&crit);
+
+ if (me->cond_waiting) {
+ if (me->cond_prev != NULL)
+ me->cond_prev->cond_next = me->cond_next;
+ else
+ waiting_head = me->cond_next;
+ if (me->cond_next != NULL)
+ me->cond_next->cond_prev = me->cond_prev;
+ else
+ waiting_tail = me->cond_prev;
+ me->cond_waiting = FALSE;
+
+ LeaveCriticalSection(&crit);
+
+ mutex->lock();
+ return 0;
+ }
+
+ //
+ // We timed out but another thread still signalled us. Wait for
+ // the semaphore (it _must_ have been signalled) to decrement it
+ // again. Return that we were signalled, not that we timed out.
+ //
+
+ LeaveCriticalSection(&crit);
+
+ result = WaitForSingleObject(me->cond_semaphore, INFINITE);
+ }
+
+ if (result != WAIT_OBJECT_0)
+ throw omni_thread_fatal(GetLastError());
+
+ mutex->lock();
+ return 1;
+}
+
+
+void
+omni_condition::signal(void)
+{
+ EnterCriticalSection(&crit);
+
+ if (waiting_head != NULL) {
+ omni_thread* t = waiting_head;
+ waiting_head = t->cond_next;
+ if (waiting_head == NULL)
+ waiting_tail = NULL;
+ else
+ waiting_head->cond_prev = NULL;
+ t->cond_waiting = FALSE;
+
+ if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) {
+ int rc = GetLastError();
+ LeaveCriticalSection(&crit);
+ throw omni_thread_fatal(rc);
+ }
+ }
+
+ LeaveCriticalSection(&crit);
+}
+
+
+void
+omni_condition::broadcast(void)
+{
+ EnterCriticalSection(&crit);
+
+ while (waiting_head != NULL) {
+ omni_thread* t = waiting_head;
+ waiting_head = t->cond_next;
+ if (waiting_head == NULL)
+ waiting_tail = NULL;
+ else
+ waiting_head->cond_prev = NULL;
+ t->cond_waiting = FALSE;
+
+ if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) {
+ int rc = GetLastError();
+ LeaveCriticalSection(&crit);
+ throw omni_thread_fatal(rc);
+ }
+ }
+
+ LeaveCriticalSection(&crit);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#define SEMAPHORE_MAX 0x7fffffff
+
+
+omni_semaphore::omni_semaphore(unsigned int initial)
+{
+ nt_sem = CreateSemaphore(NULL, initial, SEMAPHORE_MAX, NULL);
+
+ if (nt_sem == NULL) {
+ DB( cerr << "omni_semaphore::omni_semaphore: CreateSemaphore error "
+ << GetLastError() << endl );
+ throw omni_thread_fatal(GetLastError());
+ }
+}
+
+
+omni_semaphore::~omni_semaphore(void)
+{
+ if (!CloseHandle(nt_sem)) {
+ DB( cerr << "omni_semaphore::~omni_semaphore: CloseHandle error "
+ << GetLastError() << endl );
+ throw omni_thread_fatal(GetLastError());
+ }
+}
+
+
+void
+omni_semaphore::wait(void)
+{
+ if (WaitForSingleObject(nt_sem, INFINITE) != WAIT_OBJECT_0)
+ throw omni_thread_fatal(GetLastError());
+}
+
+
+int
+omni_semaphore::trywait(void)
+{
+ switch (WaitForSingleObject(nt_sem, 0)) {
+
+ case WAIT_OBJECT_0:
+ return 1;
+ case WAIT_TIMEOUT:
+ return 0;
+ }
+
+ throw omni_thread_fatal(GetLastError());
+ return 0; /* keep msvc++ happy */
+}
+
+
+void
+omni_semaphore::post(void)
+{
+ if (!ReleaseSemaphore(nt_sem, 1, NULL))
+ throw omni_thread_fatal(GetLastError());
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//
+// Static variables
+//
+
+int omni_thread::init_t::count = 0;
+
+omni_thread* omni_thread::root_thread;
+omni_mutex* omni_thread::next_id_mutex;
+int omni_thread::next_id = 0;
+static DWORD self_tls_index;
+
+//
+// Initialisation function (gets called before any user code).
+//
+
+omni_thread::init_t::init_t(void)
+{
+ if (count++ != 0) // only do it once however many objects get created.
+ return;
+
+ DB(cerr << "omni_thread::init: NT implementation initialising\n");
+
+ self_tls_index = TlsAlloc();
+
+ if (self_tls_index == 0xffffffff)
+ throw omni_thread_fatal(GetLastError());
+
+ next_id_mutex = new omni_mutex;
+
+ //
+ // Create object for this (i.e. initial) thread.
+ //
+
+ root_thread = new omni_thread;
+
+ root_thread->_state = STATE_RUNNING;
+
+ if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+ GetCurrentProcess(), &root_thread->handle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ throw omni_thread_fatal(GetLastError());
+
+ root_thread->nt_id = GetCurrentThreadId();
+
+ DB(cerr << "initial thread " << root_thread->id() << " NT thread id " << root_thread->nt_id
+ << endl);
+
+ if (!TlsSetValue(self_tls_index, (LPVOID) root_thread))
+ throw omni_thread_fatal(GetLastError());
+
+ if (!SetThreadPriority(root_thread->handle, nt_priority(PRIORITY_NORMAL)))
+ throw omni_thread_fatal(GetLastError());
+}
+
+omni_thread::init_t::~init_t (void)
+{
+ if (--count != 0) // only do it once however many objects get created.
+ return;
+
+ delete root_thread;
+ delete next_id_mutex;
+}
+
+//
+// Wrapper for thread creation.
+//
+
+extern "C"
+#ifndef __BCPLUSPLUS__
+unsigned __stdcall
+#else
+void _USERENTRY
+#endif
+omni_thread_wrapper(void* ptr)
+{
+ omni_thread* me = (omni_thread*)ptr;
+
+ DB(cerr << "omni_thread_wrapper: thread " << me->id()
+ << " started\n");
+
+ if (!TlsSetValue(self_tls_index, (LPVOID)me))
+ throw omni_thread_fatal(GetLastError());
+
+ //
+ // Now invoke the thread function with the given argument.
+ //
+
+ if (me->fn_void != NULL) {
+ (*me->fn_void)(me->thread_arg);
+ omni_thread::exit();
+ }
+
+ if (me->fn_ret != NULL) {
+ void* return_value = (*me->fn_ret)(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ if (me->detached) {
+ me->run(me->thread_arg);
+ omni_thread::exit();
+ } else {
+ void* return_value = me->run_undetached(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ // should never get here.
+#ifndef __BCPLUSPLUS__
+ return 0;
+#endif
+}
+
+
+//
+// Constructors for omni_thread - set up the thread object but don't
+// start it running.
+//
+
+// construct a detached thread running a given function.
+
+omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = fn;
+ fn_ret = NULL;
+}
+
+// construct an undetached thread running a given function.
+
+omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 0);
+ fn_void = NULL;
+ fn_ret = fn;
+}
+
+// construct a thread which will run either run() or run_undetached().
+
+omni_thread::omni_thread(void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = NULL;
+ fn_ret = NULL;
+}
+
+// common part of all constructors.
+
+void
+omni_thread::common_constructor(void* arg, priority_t pri, int det)
+{
+ _state = STATE_NEW;
+ _priority = pri;
+
+ next_id_mutex->lock();
+ _id = next_id++;
+ next_id_mutex->unlock();
+
+ thread_arg = arg;
+ detached = det; // may be altered in start_undetached()
+
+ cond_semaphore = CreateSemaphore(NULL, 0, SEMAPHORE_MAX, NULL);
+
+ if (cond_semaphore == NULL)
+ throw omni_thread_fatal(GetLastError());
+
+ cond_next = cond_prev = NULL;
+ cond_waiting = FALSE;
+
+ handle = NULL;
+}
+
+
+//
+// Destructor for omni_thread.
+//
+
+omni_thread::~omni_thread(void)
+{
+ DB(cerr << "destructor called for thread " << id() << endl);
+ if (handle && !CloseHandle(handle))
+ throw omni_thread_fatal(GetLastError());
+ if (cond_semaphore && !CloseHandle(cond_semaphore))
+ throw omni_thread_fatal(GetLastError());
+}
+
+
+//
+// Start the thread
+//
+
+void
+omni_thread::start(void)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_NEW)
+ throw omni_thread_invalid();
+
+#ifndef __BCPLUSPLUS__
+ // MSVC++ or compatiable
+ unsigned int t;
+ handle = (HANDLE)_beginthreadex(
+ NULL,
+ 0,
+ omni_thread_wrapper,
+ (LPVOID)this,
+ CREATE_SUSPENDED,
+ &t);
+ nt_id = t;
+ if (handle == NULL)
+ throw omni_thread_fatal(GetLastError());
+#else
+ // Borland C++
+ handle = (HANDLE)_beginthreadNT(omni_thread_wrapper,
+ 0,
+ (void*)this,
+ NULL,
+ CREATE_SUSPENDED,
+ &nt_id);
+ if (handle == INVALID_HANDLE_VALUE)
+ throw omni_thread_fatal(errno);
+#endif
+
+ if (!SetThreadPriority(handle, this->nt_priority (_priority)))
+ throw omni_thread_fatal(GetLastError());
+
+ if (ResumeThread(handle) == 0xffffffff)
+ throw omni_thread_fatal(GetLastError());
+
+ _state = STATE_RUNNING;
+}
+
+
+//
+// Start a thread which will run the member function run_undetached().
+//
+
+void
+omni_thread::start_undetached(void)
+{
+ if ((fn_void != NULL) || (fn_ret != NULL))
+ throw omni_thread_invalid();
+
+ detached = 0;
+ start();
+}
+
+
+//
+// join - simply check error conditions & call WaitForSingleObject.
+//
+
+void
+omni_thread::join(void** status)
+{
+ mutex.lock();
+
+ if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
+ mutex.unlock();
+ throw omni_thread_invalid();
+ }
+
+ mutex.unlock();
+
+ if (this == self())
+ throw omni_thread_invalid();
+
+ if (detached)
+ throw omni_thread_invalid();
+
+ DB(cerr << "omni_thread::join: doing WaitForSingleObject\n");
+
+ if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0)
+ throw omni_thread_fatal(GetLastError());
+
+ DB(cerr << "omni_thread::join: WaitForSingleObject succeeded\n");
+
+ if (status)
+ *status = return_val;
+
+ delete this;
+}
+
+
+//
+// Change this thread's priority.
+//
+
+void
+omni_thread::set_priority(priority_t pri)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_RUNNING)
+ throw omni_thread_invalid();
+
+ _priority = pri;
+
+ if (!SetThreadPriority(handle, nt_priority(pri)))
+ throw omni_thread_fatal(GetLastError());
+}
+
+
+//
+// create - construct a new thread object and start it running. Returns thread
+// object if successful, null pointer if not.
+//
+
+// detached version
+
+omni_thread*
+omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+ t->start();
+ return t;
+}
+
+// undetached version
+
+omni_thread*
+omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+ t->start();
+ return t;
+}
+
+
+//
+// exit() _must_ lock the mutex even in the case of a detached thread. This is
+// because a thread may run to completion before the thread that created it has
+// had a chance to get out of start(). By locking the mutex we ensure that the
+// creating thread must have reached the end of start() before we delete the
+// thread object. Of course, once the call to start() returns, the user can
+// still incorrectly refer to the thread object, but that's their problem.
+//
+
+void
+omni_thread::exit(void* return_value)
+{
+ omni_thread* me = self();
+
+ if (me)
+ {
+ me->mutex.lock();
+
+ me->_state = STATE_TERMINATED;
+
+ me->mutex.unlock();
+
+ DB(cerr << "omni_thread::exit: thread " << me->id() << " detached "
+ << me->detached << " return value " << return_value << endl);
+
+ if (me->detached) {
+ delete me;
+ } else {
+ me->return_val = return_value;
+ }
+ }
+ else
+ {
+ DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl);
+ }
+#ifndef __BCPLUSPLUS__
+ // MSVC++ or compatiable
+ // _endthreadex() does not automatically closes the thread handle.
+ // The omni_thread dtor closes the thread handle.
+ _endthreadex(0);
+#else
+ // Borland C++
+ // _endthread() does not automatically closes the thread handle.
+ // _endthreadex() is only available if __MFC_COMPAT__ is defined and
+ // all it does is to call _endthread().
+ _endthread();
+#endif
+}
+
+
+omni_thread*
+omni_thread::self(void)
+{
+ LPVOID me;
+
+ me = TlsGetValue(self_tls_index);
+
+ if (me == NULL) {
+ DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl);
+ }
+ return (omni_thread*)me;
+}
+
+
+void
+omni_thread::yield(void)
+{
+ Sleep(0);
+}
+
+
+#define MAX_SLEEP_SECONDS (DWORD)4294966 // (2**32-2)/1000
+
+void
+omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
+{
+ if (secs <= MAX_SLEEP_SECONDS) {
+ Sleep(secs * 1000 + nanosecs / 1000000);
+ return;
+ }
+
+ DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS;
+
+ for (DWORD i = 0; i < no_of_max_sleeps; i++)
+ Sleep(MAX_SLEEP_SECONDS * 1000);
+
+ Sleep((secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000);
+}
+
+
+void
+omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec, unsigned long rel_nsec)
+{
+ get_time_now(abs_sec, abs_nsec);
+ *abs_nsec += rel_nsec;
+ *abs_sec += rel_sec + *abs_nsec / 1000000000;
+ *abs_nsec = *abs_nsec % 1000000000;
+}
+
+
+int
+omni_thread::nt_priority(priority_t pri)
+{
+ switch (pri) {
+
+ case PRIORITY_LOW:
+ return THREAD_PRIORITY_LOWEST;
+
+ case PRIORITY_NORMAL:
+ return THREAD_PRIORITY_NORMAL;
+
+ case PRIORITY_HIGH:
+ return THREAD_PRIORITY_HIGHEST;
+ }
+
+ throw omni_thread_invalid();
+ return 0; /* keep msvc++ happy */
+}
+
+
+static void
+get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec)
+{
+ static int days_in_preceding_months[12]
+ = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ static int days_in_preceding_months_leap[12]
+ = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ *abs_nsec = st.wMilliseconds * 1000000;
+
+ // this formula should work until 1st March 2100
+
+ DWORD days = ((st.wYear - 1970) * 365 + (st.wYear - 1969) / 4
+ + ((st.wYear % 4)
+ ? days_in_preceding_months[st.wMonth - 1]
+ : days_in_preceding_months_leap[st.wMonth - 1])
+ + st.wDay - 1);
+
+ *abs_sec = st.wSecond + 60 * (st.wMinute + 60 * (st.wHour + 24 * days));
+}
diff --git a/SrcShared/omnithread/nt.h b/SrcShared/omnithread/nt.h
new file mode 100644
index 0000000..ddf03fd
--- /dev/null
+++ b/SrcShared/omnithread/nt.h
@@ -0,0 +1,65 @@
+// Package : omnithread
+// omnithread/nt.h Created : 6/95 tjr
+//
+// Copyright (C) 1995, 1996, 1997 Olivetti & Oracle Research Laboratory
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+//
+// OMNI thread implementation classes for NT threads.
+//
+
+#ifndef __omnithread_nt_h_
+#define __omnithread_nt_h_
+
+#include <windows.h>
+
+#ifndef __BCPLUSPLUS__
+#define OMNI_THREAD_WRAPPER \
+ unsigned __stdcall omni_thread_wrapper(LPVOID ptr);
+#else
+#define OMNI_THREAD_WRAPPER \
+ void _USERENTRY omni_thread_wrapper(void *ptr);
+#endif
+
+extern "C" OMNI_THREAD_WRAPPER;
+
+#define OMNI_MUTEX_IMPLEMENTATION \
+ CRITICAL_SECTION crit;
+
+#define OMNI_CONDITION_IMPLEMENTATION \
+ CRITICAL_SECTION crit; \
+ omni_thread* waiting_head; \
+ omni_thread* waiting_tail;
+
+#define OMNI_SEMAPHORE_IMPLEMENTATION \
+ HANDLE nt_sem;
+
+#define OMNI_THREAD_IMPLEMENTATION \
+ HANDLE handle; \
+ DWORD nt_id; \
+ void* return_val; \
+ HANDLE cond_semaphore; \
+ omni_thread* cond_next; \
+ omni_thread* cond_prev; \
+ BOOL cond_waiting; \
+ static int nt_priority(priority_t); \
+ friend class omni_condition; \
+ friend OMNI_THREAD_WRAPPER;
+
+#endif
diff --git a/SrcShared/omnithread/null_thread.cpp b/SrcShared/omnithread/null_thread.cpp
new file mode 100644
index 0000000..f571f32
--- /dev/null
+++ b/SrcShared/omnithread/null_thread.cpp
@@ -0,0 +1,335 @@
+// Package : omnithread
+// omnithread/nt.cc Created : 6/95 tjr
+//
+// Copyright (C) 1995-1999 AT&T Laboratories Cambridge
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+
+//
+// Implementation of OMNI thread abstraction for NT threads
+//
+
+#include "EmCommon.h"
+#include "omnithread.h"
+
+#define DB(x) // x
+//#include <iostream.h> or #include <iostream> if DB is on.
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_mutex::omni_mutex(void)
+{
+}
+
+omni_mutex::~omni_mutex(void)
+{
+}
+
+void
+omni_mutex::lock(void)
+{
+}
+
+void
+omni_mutex::unlock(void)
+{
+}
+
+
+#if 0
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_condition::omni_condition(omni_mutex* m) : mutex(m)
+{
+}
+
+
+omni_condition::~omni_condition(void)
+{
+}
+
+
+void
+omni_condition::wait(void)
+{
+}
+
+
+int
+omni_condition::timedwait(unsigned long abs_sec, unsigned long abs_nsec)
+{
+#pragma unused (abs_sec, abs_nsec)
+
+ return 1;
+}
+
+
+void
+omni_condition::signal(void)
+{
+}
+
+
+void
+omni_condition::broadcast(void)
+{
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_semaphore::omni_semaphore(unsigned int initial)
+{
+#pragma unused (initial)
+}
+
+
+omni_semaphore::~omni_semaphore(void)
+{
+}
+
+
+void
+omni_semaphore::wait(void)
+{
+}
+
+
+int
+omni_semaphore::trywait(void)
+{
+ return 0;
+}
+
+
+void
+omni_semaphore::post(void)
+{
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+#endif // 0
+
+//
+// Static variables
+//
+
+int omni_thread::init_t::count = 0;
+
+
+//
+// Initialisation function (gets called before any user code).
+//
+
+omni_thread::init_t::init_t(void)
+{
+}
+
+omni_thread::init_t::~init_t(void)
+{
+}
+
+#if 0
+//
+// Wrapper for thread creation.
+//
+
+void
+omni_thread_wrapper(void* ptr)
+{
+#pragma unused (ptr)
+}
+
+
+//
+// Constructors for omni_thread - set up the thread object but don't
+// start it running.
+//
+
+// construct a detached thread running a given function.
+
+omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
+{
+#pragma unused (fn, arg, pri)
+}
+
+// construct an undetached thread running a given function.
+
+omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
+{
+#pragma unused (fn, arg, pri)
+}
+
+// construct a thread which will run either run() or run_undetached().
+
+omni_thread::omni_thread(void* arg, priority_t pri)
+{
+#pragma unused (arg, pri)
+}
+
+// common part of all constructors.
+
+void
+omni_thread::common_constructor(void* arg, priority_t pri, int det)
+{
+#pragma unused (arg, pri, det)
+}
+
+
+//
+// Destructor for omni_thread.
+//
+
+omni_thread::~omni_thread(void)
+{
+}
+
+
+//
+// Start the thread
+//
+
+void
+omni_thread::start(void)
+{
+}
+
+
+//
+// Start a thread which will run the member function run_undetached().
+//
+
+void
+omni_thread::start_undetached(void)
+{
+}
+
+
+//
+// join - simply check error conditions & call WaitForSingleObject.
+//
+
+void
+omni_thread::join(void** status)
+{
+#pragma unused (status)
+}
+
+
+//
+// Change this thread's priority.
+//
+
+void
+omni_thread::set_priority(priority_t pri)
+{
+#pragma unused (pri)
+}
+
+
+//
+// create - construct a new thread object and start it running. Returns thread
+// object if successful, null pointer if not.
+//
+
+// detached version
+
+omni_thread*
+omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
+{
+#pragma unused (fn, arg, pri)
+ return NULL;
+}
+
+// undetached version
+
+omni_thread*
+omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
+{
+#pragma unused (fn, arg, pri)
+ return NULL;
+}
+
+
+//
+// exit() _must_ lock the mutex even in the case of a detached thread. This is
+// because a thread may run to completion before the thread that created it has
+// had a chance to get out of start(). By locking the mutex we ensure that the
+// creating thread must have reached the end of start() before we delete the
+// thread object. Of course, once the call to start() returns, the user can
+// still incorrectly refer to the thread object, but that's their problem.
+//
+
+void
+omni_thread::exit(void* return_value)
+{
+#pragma unused (return_value)
+}
+
+
+omni_thread*
+omni_thread::self(void)
+{
+ return NULL;
+}
+
+
+void
+omni_thread::yield(void)
+{
+}
+
+
+void
+omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
+{
+#pragma unused (secs, nanosecs)
+}
+
+
+void
+omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec, unsigned long rel_nsec)
+{
+#pragma unused (abs_sec, abs_nsec, rel_sec, rel_nsec)
+}
+
+#endif // 0
diff --git a/SrcShared/omnithread/null_thread.h b/SrcShared/omnithread/null_thread.h
new file mode 100644
index 0000000..86f38ea
--- /dev/null
+++ b/SrcShared/omnithread/null_thread.h
@@ -0,0 +1,40 @@
+// Package : omnithread
+// omnithread/nt.h Created : 6/95 tjr
+//
+// Copyright (C) 1995, 1996, 1997 Olivetti & Oracle Research Laboratory
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+//
+// OMNI thread implementation classes for NT threads.
+//
+
+#ifndef null_thread_h
+#define null_thread_h
+
+extern "C" void omni_thread_wrapper(void *ptr);
+
+#define OMNI_MUTEX_IMPLEMENTATION
+
+#define OMNI_CONDITION_IMPLEMENTATION
+
+#define OMNI_SEMAPHORE_IMPLEMENTATION
+
+#define OMNI_THREAD_IMPLEMENTATION
+
+#endif /* null_thread_h */
diff --git a/SrcShared/omnithread/omnithread.h b/SrcShared/omnithread/omnithread.h
new file mode 100644
index 0000000..9baffdd
--- /dev/null
+++ b/SrcShared/omnithread/omnithread.h
@@ -0,0 +1,542 @@
+// Package : omnithread
+// omnithread.h Created : 7/94 tjr
+//
+// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+
+//
+// Interface to OMNI thread abstraction.
+//
+// This file declares classes for threads and synchronisation objects
+// (mutexes, condition variables and counting semaphores).
+//
+// Wherever a seemingly arbitrary choice has had to be made as to the interface
+// provided, the intention here has been to be as POSIX-like as possible. This
+// is why there is no semaphore timed wait, for example.
+//
+
+#ifndef __omnithread_h_
+#define __omnithread_h_
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+class omni_mutex;
+class omni_condition;
+class omni_semaphore;
+class omni_thread;
+
+//
+// OMNI_THREAD_EXPOSE can be defined as public or protected to expose the
+// implementation class - this may be useful for debugging. Hopefully this
+// won't change the underlying structure which the compiler generates so that
+// this can work without recompiling the library.
+//
+
+#ifndef OMNI_THREAD_EXPOSE
+#define OMNI_THREAD_EXPOSE private
+#endif
+
+//
+// Include implementation-specific header file.
+//
+// This must define 4 CPP macros of the form OMNI_x_IMPLEMENTATION for mutex,
+// condition variable, semaphore and thread. Each should define any
+// implementation-specific members of the corresponding classes.
+//
+
+
+#if defined(__arm__) && defined(__atmos__)
+#include <omnithread/posix.h>
+
+#elif defined(__alpha__) && defined(__osf1__)
+#include <omnithread/posix.h>
+
+#elif defined(__powerpc__) && defined(__aix__)
+#include <omnithread/posix.h>
+
+#elif defined(__hpux__)
+#include <omnithread/posix.h>
+
+#elif defined(__WIN32__)
+#include <omnithread/nt.h>
+
+#ifdef _MSC_VER
+
+// Using MSVC++ to compile. If compiling library as a DLL,
+// define _OMNITHREAD_DLL. If compiling as a statuc library, define
+// _WINSTATIC
+// If compiling an application that is to be statically linked to omnithread,
+// define _WINSTATIC (if the application is to be dynamically linked,
+// there is no need to define any of these macros).
+
+#if defined (_OMNITHREAD_DLL) && defined(_WINSTATIC)
+#error "Both _OMNITHREAD_DLL and _WINSTATIC are defined."
+#elif defined(_OMNITHREAD_DLL)
+#define _OMNITHREAD_NTDLL_ __declspec(dllexport)
+#elif !defined(_WINSTATIC)
+#define _OMNITHREAD_NTDLL_ __declspec(dllimport)
+#elif defined(_WINSTATIC)
+#define _OMNITHREAD_NTDLL_
+#endif
+ // _OMNITHREAD_DLL && _WINSTATIC
+
+#else
+
+// Not using MSVC++ to compile
+#define _OMNITHREAD_NTDLL_
+
+#endif
+ // _MSC_VER
+
+#elif defined(__sun__)
+#include <omnithread/solaris.h>
+
+#elif defined(__sunos__)
+#if __OSVERSION__ != 5
+// XXX Workaround for SUN C++ compiler (seen on 4.2) Template.DB code
+// regeneration bug. See omniORB2/CORBA_sysdep.h for details.
+#if !defined(__SUNPRO_CC) || __OSVERSION__ != '5'
+#error "Only SunOS 5.x or later is supported."
+#endif
+#endif
+#ifdef UsePthread
+#include <omnithread/posix.h>
+#else
+#include <omnithread/solaris.h>
+#endif
+
+#elif defined(__linux__)
+#include <omnithread/posix.h>
+
+#elif defined(__nextstep__)
+#include <omnithread/mach.h>
+
+#elif defined(__VMS)
+#include <omnithread/posix.h>
+
+#elif defined(__SINIX__)
+#include <omnithread/posix.h>
+
+#elif defined(__osr5__)
+#include <omnithread/posix.h>
+
+#elif defined(__irix__)
+#include <omnithread/posix.h>
+
+#elif defined(macintosh)
+#include <null_thread.h>
+
+#elif defined(__QNXNTO__)
+#include <omnithread/posix.h>
+
+#elif defined(__svr4__)
+#include <omnithread/posix.h>
+
+#elif defined(__FreeBSD__)
+#include <omnithread/posix.h>
+
+#elif defined(__bsdi__)
+#include <omnithread/posix.h>
+
+#else
+#error "No implementation header file"
+#endif
+
+#if !defined(__WIN32__)
+#define _OMNITHREAD_NTDLL_
+#endif
+
+#if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \
+ !defined(OMNI_CONDITION_IMPLEMENTATION) || \
+ !defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \
+ !defined(OMNI_THREAD_IMPLEMENTATION))
+#error "Implementation header file incomplete"
+#endif
+
+
+//
+// This exception is thrown in the event of a fatal error.
+//
+
+class _OMNITHREAD_NTDLL_ omni_thread_fatal {
+public:
+ int error;
+ omni_thread_fatal(int e = 0) : error(e) {}
+};
+
+
+//
+// This exception is thrown when an operation is invoked with invalid
+// arguments.
+//
+
+class _OMNITHREAD_NTDLL_ omni_thread_invalid {};
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+class _OMNITHREAD_NTDLL_ omni_mutex {
+
+public:
+ omni_mutex(void);
+ ~omni_mutex(void);
+
+ void lock(void);
+ void unlock(void);
+ void acquire(void) { lock(); }
+ void release(void) { unlock(); }
+ // the names lock and unlock are preferred over acquire and release
+ // since we are attempting to be as POSIX-like as possible.
+
+ friend class omni_condition;
+
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_mutex(const omni_mutex&);
+ omni_mutex& operator=(const omni_mutex&);
+
+OMNI_THREAD_EXPOSE:
+ OMNI_MUTEX_IMPLEMENTATION
+};
+
+//
+// As an alternative to:
+// {
+// mutex.lock();
+// .....
+// mutex.unlock();
+// }
+//
+// you can use a single instance of the omni_mutex_lock class:
+//
+// {
+// omni_mutex_lock l(mutex);
+// ....
+// }
+//
+// This has the advantage that mutex.unlock() will be called automatically
+// when an exception is thrown.
+//
+
+class _OMNITHREAD_NTDLL_ omni_mutex_lock {
+ omni_mutex& mutex;
+public:
+ omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); }
+ ~omni_mutex_lock(void) { mutex.unlock(); }
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_mutex_lock(const omni_mutex_lock&);
+ omni_mutex_lock& operator=(const omni_mutex_lock&);
+};
+
+
+// Handy class -- based on omni_mutex_lock -- that does the opposite.
+// It unlocks a mutex in the c'tor, and then relocks it in the d'tor.
+
+class _OMNITHREAD_NTDLL_ omni_mutex_unlock {
+ omni_mutex& mutex;
+public:
+ omni_mutex_unlock(omni_mutex& m) : mutex(m) { mutex.unlock(); }
+ ~omni_mutex_unlock(void) { mutex.lock(); }
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_mutex_unlock(const omni_mutex_unlock&);
+ omni_mutex_unlock& operator=(const omni_mutex_unlock&);
+};
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+class _OMNITHREAD_NTDLL_ omni_condition {
+
+ omni_mutex* mutex;
+
+public:
+ omni_condition(omni_mutex* m);
+ // constructor must be given a pointer to an existing mutex. The
+ // condition variable is then linked to the mutex, so that there is an
+ // implicit unlock and lock around wait() and timed_wait().
+
+ ~omni_condition(void);
+
+ void wait(void);
+ // wait for the condition variable to be signalled. The mutex is
+ // implicitly released before waiting and locked again after waking up.
+ // If wait() is called by multiple threads, a signal may wake up more
+ // than one thread. See POSIX threads documentation for details.
+
+ int timedwait(unsigned long secs, unsigned long nanosecs = 0);
+ // timedwait() is given an absolute time to wait until. To wait for a
+ // relative time from now, use omni_thread::get_time. See POSIX threads
+ // documentation for why absolute times are better than relative.
+ // Returns 1 (true) if successfully signalled, 0 (false) if time
+ // expired.
+
+ void signal(void);
+ // if one or more threads have called wait(), signal wakes up at least
+ // one of them, possibly more. See POSIX threads documentation for
+ // details.
+
+ void broadcast(void);
+ // broadcast is like signal but wakes all threads which have called
+ // wait().
+
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_condition(const omni_condition&);
+ omni_condition& operator=(const omni_condition&);
+
+OMNI_THREAD_EXPOSE:
+ OMNI_CONDITION_IMPLEMENTATION
+};
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+class _OMNITHREAD_NTDLL_ omni_semaphore {
+
+public:
+ omni_semaphore(unsigned int initial = 1);
+ ~omni_semaphore(void);
+
+ void wait(void);
+ // if semaphore value is > 0 then decrement it and carry on. If it's
+ // already 0 then block.
+
+ int trywait(void);
+ // if semaphore value is > 0 then decrement it and return 1 (true).
+ // If it's already 0 then return 0 (false).
+
+ void post(void);
+ // if any threads are blocked in wait(), wake one of them up. Otherwise
+ // increment the value of the semaphore.
+
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_semaphore(const omni_semaphore&);
+ omni_semaphore& operator=(const omni_semaphore&);
+
+OMNI_THREAD_EXPOSE:
+ OMNI_SEMAPHORE_IMPLEMENTATION
+};
+
+//
+// A helper class for semaphores, similar to omni_mutex_lock above.
+//
+
+class _OMNITHREAD_NTDLL_ omni_semaphore_lock {
+ omni_semaphore& sem;
+public:
+ omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); }
+ ~omni_semaphore_lock(void) { sem.post(); }
+private:
+ // dummy copy constructor and operator= to prevent copying
+ omni_semaphore_lock(const omni_semaphore_lock&);
+ omni_semaphore_lock& operator=(const omni_semaphore_lock&);
+};
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+
+class _OMNITHREAD_NTDLL_ omni_thread {
+
+public:
+
+ enum priority_t {
+ PRIORITY_LOW,
+ PRIORITY_NORMAL,
+ PRIORITY_HIGH
+ };
+
+ enum state_t {
+ STATE_NEW, // thread object exists but thread hasn't
+ // started yet.
+ STATE_RUNNING, // thread is running.
+ STATE_TERMINATED // thread has terminated but storage has not
+ // been reclaimed (i.e. waiting to be joined).
+ };
+
+ //
+ // Constructors set up the thread object but the thread won't start until
+ // start() is called. The create method can be used to construct and start
+ // a thread in a single call.
+ //
+
+ omni_thread(void (*fn)(void*), void* arg = NULL,
+ priority_t pri = PRIORITY_NORMAL);
+ omni_thread(void* (*fn)(void*), void* arg = NULL,
+ priority_t pri = PRIORITY_NORMAL);
+ // these constructors create a thread which will run the given function
+ // when start() is called. The thread will be detached if given a
+ // function with void return type, undetached if given a function
+ // returning void*. If a thread is detached, storage for the thread is
+ // reclaimed automatically on termination. Only an undetached thread
+ // can be joined.
+
+ void start(void);
+ // start() causes a thread created with one of the constructors to
+ // start executing the appropriate function.
+
+protected:
+
+ omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL);
+ // this constructor is used in a derived class. The thread will
+ // execute the run() or run_undetached() member functions depending on
+ // whether start() or start_undetached() is called respectively.
+
+ void start_undetached(void);
+ // can be used with the above constructor in a derived class to cause
+ // the thread to be undetached. In this case the thread executes the
+ // run_undetached member function.
+
+ virtual ~omni_thread(void);
+ // destructor cannot be called by user (except via a derived class).
+ // Use exit() or cancel() instead. This also means a thread object must
+ // be allocated with new - it cannot be statically or automatically
+ // allocated. The destructor of a class that inherits from omni_thread
+ // shouldn't be public either (otherwise the thread object can be
+ // destroyed while the underlying thread is still running).
+
+public:
+
+ void join(void**);
+ // join causes the calling thread to wait for another's completion,
+ // putting the return value in the variable of type void* whose address
+ // is given (unless passed a null pointer). Only undetached threads
+ // may be joined. Storage for the thread will be reclaimed.
+
+ void set_priority(priority_t);
+ // set the priority of the thread.
+
+ static omni_thread* create(void (*fn)(void*), void* arg = NULL,
+ priority_t pri = PRIORITY_NORMAL);
+ static omni_thread* create(void* (*fn)(void*), void* arg = NULL,
+ priority_t pri = PRIORITY_NORMAL);
+ // create spawns a new thread executing the given function with the
+ // given argument at the given priority. Returns a pointer to the
+ // thread object. It simply constructs a new thread object then calls
+ // start.
+
+ static void exit(void* return_value = NULL);
+ // causes the calling thread to terminate.
+
+ static omni_thread* self(void);
+ // returns the calling thread's omni_thread object.
+ // If the calling thread is not the main thread and
+ // is not created using this library, returns 0.
+
+ static void yield(void);
+ // allows another thread to run.
+
+ static void sleep(unsigned long secs, unsigned long nanosecs = 0);
+ // sleeps for the given time.
+
+ static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec = 0, unsigned long rel_nsec=0);
+ // calculates an absolute time in seconds and nanoseconds, suitable for
+ // use in timed_waits on condition variables, which is the current time
+ // plus the given relative offset.
+
+private:
+
+ virtual void run(void* /*arg*/) {}
+ virtual void* run_undetached(void* /*arg*/) { return NULL; }
+ // can be overridden in a derived class. When constructed using the
+ // the constructor omni_thread(void*, priority_t), these functions are
+ // called by start() and start_undetached() respectively.
+
+ void common_constructor(void* arg, priority_t pri, int det);
+ // implements the common parts of the constructors.
+
+ omni_mutex mutex;
+ // used to protect any members which can change after construction,
+ // i.e. the following 2 members:
+
+ state_t _state;
+ priority_t _priority;
+
+ static omni_thread* root_thread;
+ static omni_mutex* next_id_mutex;
+ static int next_id;
+ int _id;
+
+ void (*fn_void)(void*);
+ void* (*fn_ret)(void*);
+ void* thread_arg;
+ int detached;
+
+public:
+
+ priority_t priority(void) {
+
+ // return this thread's priority.
+
+ omni_mutex_lock l(mutex);
+ return _priority;
+ }
+
+ state_t state(void) {
+
+ // return thread state (invalid, new, running or terminated).
+
+ omni_mutex_lock l(mutex);
+ return _state;
+ }
+
+ int id(void) { return _id; }
+ // return unique thread id within the current process.
+
+
+ // This class plus the instance of it declared below allows us to execute
+ // some initialisation code before main() is called.
+
+ class _OMNITHREAD_NTDLL_ init_t {
+ static int count;
+ public:
+ init_t(void);
+ ~init_t (void);
+ };
+
+ friend class init_t;
+
+OMNI_THREAD_EXPOSE:
+ OMNI_THREAD_IMPLEMENTATION
+};
+
+static omni_thread::init_t omni_thread_init;
+
+#endif
diff --git a/SrcShared/omnithread/posix.cpp b/SrcShared/omnithread/posix.cpp
new file mode 100644
index 0000000..ce3a35b
--- /dev/null
+++ b/SrcShared/omnithread/posix.cpp
@@ -0,0 +1,898 @@
+// Package : omnithread
+// omnithread/posix.cc Created : 7/94 tjr
+//
+// Copyright (C) 1994-1999 AT&T Laboratories Cambridge
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+
+//
+// Implementation of OMNI thread abstraction for posix threads
+//
+// The source below tests for the definition of the macros:
+// PthreadDraftVersion
+// PthreadSupportThreadPriority
+// NoNanoSleep
+// NeedPthreadInit
+//
+// As different draft versions of the pthread standard P1003.4a/P1003.1c
+// define slightly different APIs, the macro 'PthreadDraftVersion'
+// identifies the draft version supported by this particular platform.
+//
+// Some unix variants do not support thread priority unless a real-time
+// kernel option is installed. The macro 'PthreadSupportThreadPriority',
+// if defined, enables the use of thread priority. If it is not defined,
+// setting or changing thread priority will be silently ignored.
+//
+// nanosleep() is defined in Posix P1003.4 since Draft 9 (?).
+// Not all platforms support this standard. The macro 'NoNanoSleep'
+// identifies platform that don't.
+//
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <omnithread.h>
+
+#if (defined(__GLIBC__) && __GLIBC__ >= 2)
+// typedef of struct timeval and gettimeofday();
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#if defined(__linux__) && defined(_MIT_POSIX_THREADS)
+#include <pthread/mit/sys/timers.h>
+#endif
+
+#if defined(__irix__) && defined(PthreadSupportThreadPriority)
+#if _POSIX_THREAD_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif
+#endif
+
+#if defined(__QNXNTO__) && defined(PthreadSupportThreadPriority)
+#if _POSIX_THREAD_PRIORITY_SCHEDULING
+#include <sched.h>
+#endif
+#endif
+
+#define DB(x) // x
+//#include <iostream.h> or #include <iostream> if DB is on.
+
+#if (PthreadDraftVersion <= 6)
+#define ERRNO(x) (((x) != 0) ? (errno) : 0)
+#ifdef __VMS
+// pthread_setprio returns old priority on success (draft version 4:
+// OpenVms version < 7)
+#define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); }
+#else
+#define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); }
+#endif
+#else
+#define ERRNO(x) (x)
+#define THROW_ERRORS(x) { int rc = (x); \
+ if (rc != 0) throw omni_thread_fatal(rc); }
+#endif
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_mutex::omni_mutex(void)
+{
+#if (PthreadDraftVersion == 4)
+ THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default));
+#else
+ THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0));
+#endif
+}
+
+omni_mutex::~omni_mutex(void)
+{
+ THROW_ERRORS(pthread_mutex_destroy(&posix_mutex));
+}
+
+void
+omni_mutex::lock(void)
+{
+#ifdef __QNXNTO__
+ int err = pthread_mutex_lock(&posix_mutex);
+ if ((err != EOK) && (err != EDEADLK))
+ {
+ DB(cerr << "omni_mutex::lock err=" << err);
+ THROW_ERRORS(err);
+ }
+#else
+ THROW_ERRORS(pthread_mutex_lock(&posix_mutex));
+#endif
+}
+
+void
+omni_mutex::unlock(void)
+{
+#ifdef __QNXNTO__
+ int err = pthread_mutex_unlock(&posix_mutex);
+ if ((err != EOK) && (err != EPERM))
+ {
+ DB(cerr << "omni_mutex::unlock err=" << err);
+ THROW_ERRORS(err);
+ }
+#else
+ THROW_ERRORS(pthread_mutex_unlock(&posix_mutex));
+#endif
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_condition::omni_condition(omni_mutex* m) : mutex(m)
+{
+#if (PthreadDraftVersion == 4)
+ THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default));
+#else
+ THROW_ERRORS(pthread_cond_init(&posix_cond, 0));
+#endif
+}
+
+omni_condition::~omni_condition(void)
+{
+ THROW_ERRORS(pthread_cond_destroy(&posix_cond));
+}
+
+void
+omni_condition::wait(void)
+{
+ THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex));
+}
+
+int
+omni_condition::timedwait(unsigned long secs, unsigned long nanosecs)
+{
+ timespec rqts = { secs, nanosecs };
+
+again:
+ int rc = ERRNO(pthread_cond_timedwait(&posix_cond,
+ &mutex->posix_mutex, &rqts));
+ if (rc == 0)
+ return 1;
+
+#if (PthreadDraftVersion <= 6)
+ if (rc == EAGAIN)
+ return 0;
+#endif
+
+#if defined(__GLIBC__)
+ // Some versions of the glibc 2.0.x produces this errno when the
+ // program is debugged under gdb. Straightly speaking this is non-posix
+ // compliant. We catch this here to make debugging possible.
+ if (rc == EINTR)
+ goto again;
+#endif
+
+ if (rc == ETIMEDOUT)
+ return 0;
+
+ throw omni_thread_fatal(rc);
+}
+
+void
+omni_condition::signal(void)
+{
+ THROW_ERRORS(pthread_cond_signal(&posix_cond));
+}
+
+void
+omni_condition::broadcast(void)
+{
+ THROW_ERRORS(pthread_cond_broadcast(&posix_cond));
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_semaphore::omni_semaphore(unsigned int initial) : c(&m)
+{
+ value = initial;
+}
+
+omni_semaphore::~omni_semaphore(void)
+{
+}
+
+void
+omni_semaphore::wait(void)
+{
+ omni_mutex_lock l(m);
+
+ while (value == 0)
+ c.wait();
+
+ value--;
+}
+
+int
+omni_semaphore::trywait(void)
+{
+ omni_mutex_lock l(m);
+
+ if (value == 0)
+ return 0;
+
+ value--;
+ return 1;
+}
+
+void
+omni_semaphore::post(void)
+{
+ {
+ omni_mutex_lock l(m);
+ value++;
+ }
+
+ c.signal();
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//
+// static variables
+//
+
+int omni_thread::init_t::count = 0;
+
+omni_thread* omni_thread::root_thread;
+omni_mutex* omni_thread::next_id_mutex;
+int omni_thread::next_id = 0;
+
+static pthread_key_t self_key;
+
+#ifdef PthreadSupportThreadPriority
+static int lowest_priority;
+static int normal_priority;
+static int highest_priority;
+#endif
+
+
+//
+// Initialisation function (gets called before any user code).
+//
+
+omni_thread::init_t::init_t(void)
+{
+ if (count++ != 0) // only do it once however many objects get created.
+ return;
+
+ DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft "
+ << PthreadDraftVersion << ") implementation initialising\n");
+
+#ifdef NeedPthreadInit
+
+ pthread_init();
+
+#endif
+
+#if (PthreadDraftVersion == 4)
+ THROW_ERRORS(pthread_keycreate(&self_key, NULL));
+#else
+ THROW_ERRORS(pthread_key_create(&self_key, NULL));
+#endif
+
+#ifdef PthreadSupportThreadPriority
+
+#if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
+
+ lowest_priority = PRI_OTHER_MIN;
+ highest_priority = PRI_OTHER_MAX;
+
+#elif defined(__hpux__)
+
+ lowest_priority = PRI_OTHER_MIN;
+ highest_priority = PRI_OTHER_MAX;
+
+#elif defined(__sunos__) && (__OSVERSION__ == 5)
+
+ // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0
+
+ lowest_priority = 1;
+ highest_priority = 3;
+
+#else
+
+ lowest_priority = sched_get_priority_min(SCHED_FIFO);
+ highest_priority = sched_get_priority_max(SCHED_FIFO);
+
+#endif
+
+ switch (highest_priority - lowest_priority) {
+
+ case 0:
+ case 1:
+ normal_priority = lowest_priority;
+ break;
+
+ default:
+ normal_priority = lowest_priority + 1;
+ break;
+ }
+
+#endif /* PthreadSupportThreadPriority */
+
+ next_id_mutex = new omni_mutex;
+
+ //
+ // Create object for this (i.e. initial) thread.
+ //
+
+ root_thread = new omni_thread;
+
+ root_thread->_state = STATE_RUNNING;
+
+ root_thread->posix_thread = pthread_self ();
+
+ DB(cerr << "initial thread " << root_thread->id() << endl);
+
+ THROW_ERRORS(pthread_setspecific(self_key, (void*) root_thread));
+
+#ifdef PthreadSupportThreadPriority
+
+#if (PthreadDraftVersion == 4)
+
+ THROW_ERRORS(pthread_setprio(root_thread->posix_thread,
+ posix_priority(PRIORITY_NORMAL)));
+
+#elif (PthreadDraftVersion == 6)
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+
+ THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL)));
+
+ THROW_ERRORS(pthread_setschedattr(root_thread->posix_thread, attr));
+
+#else
+
+ struct sched_param sparam;
+
+ sparam.sched_priority = posix_priority(PRIORITY_NORMAL);
+
+ THROW_ERRORS(pthread_setschedparam(root_thread->posix_thread, SCHED_OTHER, &sparam));
+
+#endif /* PthreadDraftVersion */
+
+#endif /* PthreadSupportThreadPriority */
+}
+
+omni_thread::init_t::~init_t (void)
+{
+ if (--count != 0) // only do it once however many objects get created.
+ return;
+
+ delete root_thread;
+ delete next_id_mutex;
+}
+
+
+//
+// Wrapper for thread creation.
+//
+
+extern "C" void*
+omni_thread_wrapper(void* ptr)
+{
+ omni_thread* me = (omni_thread*)ptr;
+
+ DB(cerr << "omni_thread_wrapper: thread " << me->id()
+ << " started\n");
+
+ THROW_ERRORS(pthread_setspecific(self_key, me));
+
+ //
+ // Now invoke the thread function with the given argument.
+ //
+
+ if (me->fn_void != NULL) {
+ (*me->fn_void)(me->thread_arg);
+ omni_thread::exit();
+ }
+
+ if (me->fn_ret != NULL) {
+ void* return_value = (*me->fn_ret)(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ if (me->detached) {
+ me->run(me->thread_arg);
+ omni_thread::exit();
+ } else {
+ void* return_value = me->run_undetached(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ // should never get here.
+
+ return NULL;
+}
+
+
+//
+// Constructors for omni_thread - set up the thread object but don't
+// start it running.
+//
+
+// construct a detached thread running a given function.
+
+omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = fn;
+ fn_ret = NULL;
+}
+
+// construct an undetached thread running a given function.
+
+omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 0);
+ fn_void = NULL;
+ fn_ret = fn;
+}
+
+// construct a thread which will run either run() or run_undetached().
+
+omni_thread::omni_thread(void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = NULL;
+ fn_ret = NULL;
+}
+
+// common part of all constructors.
+
+void
+omni_thread::common_constructor(void* arg, priority_t pri, int det)
+{
+ _state = STATE_NEW;
+ _priority = pri;
+
+ next_id_mutex->lock();
+ _id = next_id++;
+ next_id_mutex->unlock();
+
+ thread_arg = arg;
+ detached = det; // may be altered in start_undetached()
+
+ // posix_thread is set up in initialisation routine or start().
+}
+
+
+//
+// Destructor for omni_thread.
+//
+
+omni_thread::~omni_thread(void)
+{
+ DB(cerr << "destructor called for thread " << id() << endl);
+}
+
+
+//
+// Start the thread
+//
+
+void
+omni_thread::start(void)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_NEW)
+ throw omni_thread_invalid();
+
+ pthread_attr_t attr;
+
+#if (PthreadDraftVersion == 4)
+ pthread_attr_create(&attr);
+#else
+ pthread_attr_init(&attr);
+#endif
+
+#if (PthreadDraftVersion == 8)
+ pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED);
+#endif
+
+#ifdef PthreadSupportThreadPriority
+
+#if (PthreadDraftVersion <= 6)
+
+ THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(_priority)));
+
+#else
+
+ struct sched_param sparam;
+
+ sparam.sched_priority = posix_priority(_priority);
+
+ THROW_ERRORS(pthread_attr_setschedparam(&attr, &sparam));
+
+#endif /* PthreadDraftVersion */
+
+#endif /* PthreadSupportThreadPriority */
+
+#if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
+
+ // omniORB requires a larger stack size than the default (21120)
+ // on OSF/1
+
+ THROW_ERRORS(pthread_attr_setstacksize(&attr, 32768));
+
+#endif /* __osf1__ && __alpha__ */
+
+#if (PthreadDraftVersion == 4)
+ THROW_ERRORS(pthread_create(&posix_thread, attr, omni_thread_wrapper,
+ (void*)this));
+ pthread_attr_delete(&attr);
+#else
+ THROW_ERRORS(pthread_create(&posix_thread, &attr, omni_thread_wrapper,
+ (void*)this));
+ pthread_attr_destroy(&attr);
+#endif
+
+ _state = STATE_RUNNING;
+
+ if (detached) {
+
+#if (PthreadDraftVersion <= 6)
+ THROW_ERRORS(pthread_detach(&posix_thread));
+#else
+ THROW_ERRORS(pthread_detach(posix_thread));
+#endif
+ }
+}
+
+
+//
+// Start a thread which will run the member function run_undetached().
+//
+
+void
+omni_thread::start_undetached(void)
+{
+ if ((fn_void != NULL) || (fn_ret != NULL))
+ throw omni_thread_invalid();
+
+ detached = 0;
+ start();
+}
+
+
+//
+// join - simply check error conditions & call pthread_join.
+//
+
+void
+omni_thread::join(void** status)
+{
+ mutex.lock();
+
+ if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
+ mutex.unlock();
+ throw omni_thread_invalid();
+ }
+
+ mutex.unlock();
+
+ if (this == self())
+ throw omni_thread_invalid();
+
+ if (detached)
+ throw omni_thread_invalid();
+
+ DB(cerr << "omni_thread::join: doing pthread_join\n");
+
+ THROW_ERRORS(pthread_join(posix_thread, status));
+
+ DB(cerr << "omni_thread::join: pthread_join succeeded\n");
+
+#if (PthreadDraftVersion == 4)
+ // With draft 4 pthreads implementations (HPUX 10.x and
+ // Digital Unix 3.2), have to detach the thread after
+ // join. If not, the storage for the thread will not be
+ // be reclaimed.
+ THROW_ERRORS(pthread_detach(&posix_thread));
+#endif
+
+ delete this;
+}
+
+
+//
+// Change this thread's priority.
+//
+
+void
+omni_thread::set_priority(priority_t pri)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_RUNNING)
+ throw omni_thread_invalid();
+
+ _priority = pri;
+
+#ifdef PthreadSupportThreadPriority
+
+#if (PthreadDraftVersion == 4)
+
+ THROW_ERRORS(pthread_setprio(posix_thread, posix_priority(pri)));
+
+#elif (PthreadDraftVersion == 6)
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+
+ THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(pri)));
+
+ THROW_ERRORS(pthread_setschedattr(posix_thread, attr));
+
+#else
+
+ struct sched_param sparam;
+
+ sparam.sched_priority = posix_priority(pri);
+
+ THROW_ERRORS(pthread_setschedparam(posix_thread, SCHED_OTHER, &sparam));
+
+#endif /* PthreadDraftVersion */
+
+#endif /* PthreadSupportThreadPriority */
+}
+
+
+//
+// create - construct a new thread object and start it running. Returns thread
+// object if successful, null pointer if not.
+//
+
+// detached version
+
+omni_thread*
+omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+// undetached version
+
+omni_thread*
+omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+
+//
+// exit() _must_ lock the mutex even in the case of a detached thread. This is
+// because a thread may run to completion before the thread that created it has
+// had a chance to get out of start(). By locking the mutex we ensure that the
+// creating thread must have reached the end of start() before we delete the
+// thread object. Of course, once the call to start() returns, the user can
+// still incorrectly refer to the thread object, but that's their problem.
+//
+
+void
+omni_thread::exit(void* return_value)
+{
+ omni_thread* me = self();
+
+ if (me)
+ {
+ me->mutex.lock();
+
+ me->_state = STATE_TERMINATED;
+
+ me->mutex.unlock();
+
+ DB(cerr << "omni_thread::exit: thread " << me->id() << " detached "
+ << me->detached << " return value " << return_value << endl);
+
+ if (me->detached)
+ delete me;
+ }
+ else
+ {
+ DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl);
+ }
+
+ pthread_exit(return_value);
+}
+
+
+omni_thread*
+omni_thread::self(void)
+{
+ omni_thread* me;
+
+#if (PthreadDraftVersion <= 6)
+
+ THROW_ERRORS(pthread_getspecific(self_key, (void**)&me));
+
+#else
+
+ me = (omni_thread *)pthread_getspecific(self_key);
+
+#endif
+
+ if (!me) {
+ // This thread is not created by omni_thread::start because it
+ // doesn't has a class omni_thread instance attached to its key.
+ DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl);
+ }
+
+ return me;
+}
+
+
+void
+omni_thread::yield(void)
+{
+#if (PthreadDraftVersion == 6)
+
+ pthread_yield(NULL);
+
+#elif (PthreadDraftVersion < 9)
+
+ pthread_yield();
+
+#elif (__svr4__)
+
+ thr_yield();
+
+#else
+
+ THROW_ERRORS(sched_yield());
+
+#endif
+}
+
+
+void
+omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
+{
+ timespec rqts = { secs, nanosecs };
+
+#ifndef NoNanoSleep
+
+ if (nanosleep(&rqts, (timespec*)NULL) != 0)
+ throw omni_thread_fatal(errno);
+#else
+
+#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__)
+
+ if (pthread_delay_np(&rqts) != 0)
+ throw omni_thread_fatal(errno);
+
+#elif defined(__linux__) || defined(__aix__) || defined(__svr4__) || defined(__bsdi__)
+
+ if (secs > 2000) {
+ ::sleep(secs);
+ } else {
+ usleep(secs * 1000000 + (nanosecs / 1000));
+ }
+
+#else
+
+#error You need to define how to emulate nanosleep!
+ throw omni_thread_invalid();
+
+#endif
+#endif /* NoNanoSleep */
+}
+
+
+void
+omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec, unsigned long rel_nsec)
+{
+ timespec abs;
+
+#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__)
+
+ timespec rel;
+ rel.tv_sec = rel_sec;
+ rel.tv_nsec = rel_nsec;
+ THROW_ERRORS(pthread_get_expiration_np(&rel, &abs));
+
+#else
+
+#if defined(__linux__) || defined(__aix__) || defined(__svr4__)
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ abs.tv_sec = tv.tv_sec;
+ abs.tv_nsec = tv.tv_usec * 1000;
+
+#else /* __linux__ || __aix__ */
+
+ clock_gettime(CLOCK_REALTIME, &abs);
+
+#endif /* __linux__ || __aix__ */
+
+ abs.tv_nsec += rel_nsec;
+ abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000;
+ abs.tv_nsec = abs.tv_nsec % 1000000000;
+
+#endif /* __osf1__ && __alpha__ */
+
+ *abs_sec = abs.tv_sec;
+ *abs_nsec = abs.tv_nsec;
+}
+
+
+int
+omni_thread::posix_priority(priority_t pri)
+{
+#ifdef PthreadSupportThreadPriority
+ switch (pri) {
+
+ case PRIORITY_LOW:
+ return lowest_priority;
+
+ case PRIORITY_NORMAL:
+ return normal_priority;
+
+ case PRIORITY_HIGH:
+ return highest_priority;
+
+ }
+#endif
+
+ throw omni_thread_invalid();
+ return 0; /* keep compilers happy */
+}
diff --git a/SrcShared/omnithread/posix.h b/SrcShared/omnithread/posix.h
new file mode 100644
index 0000000..407fcc6
--- /dev/null
+++ b/SrcShared/omnithread/posix.h
@@ -0,0 +1,57 @@
+// Package : omnithread
+// omnithread/posix.h Created : 7/94 tjr
+//
+// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+//
+// OMNI thread implementation classes for posix threads
+//
+
+#ifndef __omnithread_posix_h_
+#define __omnithread_posix_h_
+
+#if defined(__alpha__) && defined(__osf1__) || defined(__hpux__)
+// stop unnecessary definitions of TRY, etc on OSF
+#ifndef EXC_HANDLING
+#define EXC_HANDLING
+#endif
+#endif
+
+#include <pthread.h>
+
+extern "C" void* omni_thread_wrapper(void* ptr);
+
+#define OMNI_MUTEX_IMPLEMENTATION \
+ pthread_mutex_t posix_mutex;
+
+#define OMNI_CONDITION_IMPLEMENTATION \
+ pthread_cond_t posix_cond;
+
+#define OMNI_SEMAPHORE_IMPLEMENTATION \
+ omni_mutex m; \
+ omni_condition c; \
+ int value;
+
+#define OMNI_THREAD_IMPLEMENTATION \
+ pthread_t posix_thread; \
+ static int posix_priority(priority_t); \
+ friend void* omni_thread_wrapper(void* ptr);
+
+#endif
diff --git a/SrcShared/omnithread/solaris.cpp b/SrcShared/omnithread/solaris.cpp
new file mode 100644
index 0000000..a0a2db7
--- /dev/null
+++ b/SrcShared/omnithread/solaris.cpp
@@ -0,0 +1,533 @@
+// Package : omnithread
+// omnithread/solaris.cc Created : 7/94 tjr
+//
+// Copyright (C) 1994-1999 AT&T Laboratories Cambridge
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+//
+// Implementation of OMNI thread abstraction for solaris threads.
+//
+
+#include <stdlib.h>
+#include <errno.h>
+#include <omnithread.h>
+#include <time.h>
+#include <unistd.h>
+
+#define DB(x) // x
+// #include <iostream> or #include <iostream.h> if DB is on.
+
+#define THROW_ERRORS(x) { int rc = (x); \
+ if (rc != 0) throw omni_thread_fatal(rc); }
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Mutex
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_mutex::omni_mutex(void)
+{
+ THROW_ERRORS(mutex_init(&sol_mutex, USYNC_THREAD, 0));
+}
+
+omni_mutex::~omni_mutex(void)
+{
+ THROW_ERRORS(mutex_destroy(&sol_mutex));
+}
+
+void
+omni_mutex::lock(void)
+{
+ THROW_ERRORS(mutex_lock(&sol_mutex));
+}
+
+void
+omni_mutex::unlock(void)
+{
+ THROW_ERRORS(mutex_unlock(&sol_mutex));
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Condition variable
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_condition::omni_condition(omni_mutex* m) : mutex(m)
+{
+ THROW_ERRORS(cond_init(&sol_cond, USYNC_THREAD, 0));
+}
+
+omni_condition::~omni_condition(void)
+{
+ THROW_ERRORS(cond_destroy(&sol_cond));
+}
+
+void
+omni_condition::wait(void)
+{
+ THROW_ERRORS(cond_wait(&sol_cond, &mutex->sol_mutex));
+}
+
+int
+omni_condition::timedwait(unsigned long secs, unsigned long nanosecs)
+{
+ timespec rqts = { secs, nanosecs };
+
+ int rc = cond_timedwait(&sol_cond, &mutex->sol_mutex, &rqts);
+
+ if (rc == 0)
+ return 1;
+
+ if (rc == ETIME)
+ return 0;
+
+ throw omni_thread_fatal(rc);
+}
+
+void
+omni_condition::signal(void)
+{
+ THROW_ERRORS(cond_signal(&sol_cond));
+}
+
+void
+omni_condition::broadcast(void)
+{
+ THROW_ERRORS(cond_broadcast(&sol_cond));
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Counting semaphore
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+omni_semaphore::omni_semaphore(unsigned int initial)
+{
+ THROW_ERRORS(sema_init(&sol_sem, initial, USYNC_THREAD, NULL));
+}
+
+omni_semaphore::~omni_semaphore(void)
+{
+ THROW_ERRORS(sema_destroy(&sol_sem));
+}
+
+void
+omni_semaphore::wait(void)
+{
+ THROW_ERRORS(sema_wait(&sol_sem));
+}
+
+void
+omni_semaphore::post(void)
+{
+ THROW_ERRORS(sema_post(&sol_sem));
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Thread
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//
+// Static variables
+//
+
+int omni_thread::init_t::count = 0;
+
+omni_mutex* omni_thread::next_id_mutex;
+int omni_thread::next_id = 0;
+
+static thread_key_t self_key;
+
+
+//
+// Initialisation function (gets called before any user code).
+//
+
+omni_thread::init_t::init_t(void)
+{
+ if (count++ != 0) // only do it once however many objects get created.
+ return;
+
+ DB(cerr << "omni_thread::init: solaris implementation initialising\n");
+
+ THROW_ERRORS(thr_keycreate(&self_key, NULL));
+
+ next_id_mutex = new omni_mutex;
+
+ //
+ // Create object for this (i.e. initial) thread.
+ //
+
+ omni_thread* t = new omni_thread;
+
+ t->_state = STATE_RUNNING;
+
+ t->sol_thread = thr_self();
+
+ DB(cerr << "initial thread " << t->id() << " sol_thread " << t->sol_thread
+ << endl);
+
+ THROW_ERRORS(thr_setspecific(self_key, (void*)t));
+
+ THROW_ERRORS(thr_setprio(t->sol_thread, sol_priority(PRIORITY_NORMAL)));
+}
+
+
+//
+// Wrapper for thread creation.
+//
+
+extern "C" void*
+omni_thread_wrapper(void* ptr)
+{
+ omni_thread* me = (omni_thread*)ptr;
+
+ DB(cerr << "omni_thread::wrapper: thread " << me->id()
+ << " started\n");
+
+ THROW_ERRORS(thr_setspecific(self_key, me));
+
+ //
+ // Now invoke the thread function with the given argument.
+ //
+
+ if (me->fn_void != NULL) {
+ (*me->fn_void)(me->thread_arg);
+ omni_thread::exit();
+ }
+
+ if (me->fn_ret != NULL) {
+ void* return_value = (*me->fn_ret)(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ if (me->detached) {
+ me->run(me->thread_arg);
+ omni_thread::exit();
+ } else {
+ void* return_value = me->run_undetached(me->thread_arg);
+ omni_thread::exit(return_value);
+ }
+
+ // should never get here.
+
+ return NULL;
+}
+
+
+//
+// Constructors for omni_thread - set up the thread object but don't
+// start it running.
+//
+
+// construct a detached thread running a given function.
+
+omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = fn;
+ fn_ret = NULL;
+}
+
+// construct an undetached thread running a given function.
+
+omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 0);
+ fn_void = NULL;
+ fn_ret = fn;
+}
+
+// construct a thread which will run either run() or run_undetached().
+
+omni_thread::omni_thread(void* arg, priority_t pri)
+{
+ common_constructor(arg, pri, 1);
+ fn_void = NULL;
+ fn_ret = NULL;
+}
+
+// common part of all constructors.
+
+void
+omni_thread::common_constructor(void* arg, priority_t pri, int det)
+{
+ _state = STATE_NEW;
+ _priority = pri;
+
+ next_id_mutex->lock();
+ _id = next_id++;
+ next_id_mutex->unlock();
+
+ thread_arg = arg;
+ detached = det; // may be altered in start_undetached()
+
+ // sol_thread is set up in initialisation routine or start().
+}
+
+
+//
+// Destructor for omni_thread.
+//
+
+omni_thread::~omni_thread(void)
+{
+ DB(cerr << "destructor called for thread " << id() << endl);
+}
+
+
+//
+// Start the thread
+//
+
+void
+omni_thread::start(void)
+{
+ long flags = 0;
+
+ if (detached)
+ flags |= THR_DETACHED;
+
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_NEW)
+ throw omni_thread_invalid();
+
+ THROW_ERRORS(thr_create(0, 0, omni_thread_wrapper, (void*)this, flags,
+ &sol_thread));
+
+ _state = STATE_RUNNING;
+
+ THROW_ERRORS(thr_setprio(sol_thread, sol_priority(_priority)));
+}
+
+
+//
+// Start a thread which will run the member function run_undetached().
+//
+
+void
+omni_thread::start_undetached(void)
+{
+ if ((fn_void != NULL) || (fn_ret != NULL))
+ throw omni_thread_invalid();
+
+ detached = 0;
+ start();
+}
+
+
+//
+// join - simply check error conditions & call thr_join.
+//
+
+void
+omni_thread::join(void** status)
+{
+ mutex.lock();
+
+ if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
+ mutex.unlock();
+ throw omni_thread_invalid();
+ }
+
+ mutex.unlock();
+
+ if (this == self())
+ throw omni_thread_invalid();
+
+ if (detached)
+ throw omni_thread_invalid();
+
+ DB(cerr << "omni_thread::join: doing thr_join\n");
+
+ THROW_ERRORS(thr_join(sol_thread, (thread_t *)NULL, status));
+
+ DB(cerr << "omni_thread::join: thr_join succeeded\n");
+
+ delete this;
+}
+
+
+//
+// Change this thread's priority.
+//
+
+void
+omni_thread::set_priority(priority_t pri)
+{
+ omni_mutex_lock l(mutex);
+
+ if (_state != STATE_RUNNING)
+ throw omni_thread_invalid();
+
+ _priority = pri;
+
+ THROW_ERRORS(thr_setprio(sol_thread, sol_priority(pri)));
+}
+
+
+//
+// create - construct a new thread object and start it running. Returns thread
+// object if successful, null pointer if not.
+//
+
+// detached version
+
+omni_thread*
+omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+// undetached version
+
+omni_thread*
+omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
+{
+ omni_thread* t = new omni_thread(fn, arg, pri);
+
+ t->start();
+
+ return t;
+}
+
+
+//
+// exit() _must_ lock the mutex even in the case of a detached thread. This is
+// because a thread may run to completion before the thread that created it has
+// had a chance to get out of start(). By locking the mutex we ensure that the
+// creating thread must have reached the end of start() before we delete the
+// thread object. Of course, once the call to start() returns, the user can
+// still incorrectly refer to the thread object, but that's their problem.
+//
+
+void
+omni_thread::exit(void* return_value)
+{
+ omni_thread* me = self();
+
+ if (me)
+ {
+ me->mutex.lock();
+
+ me->_state = STATE_TERMINATED;
+
+ me->mutex.unlock();
+
+ DB(cerr << "omni_thread::exit: thread " << me->id() << " detached "
+ << me->detached << " return value " << return_value << endl);
+
+ if (me->detached)
+ delete me;
+ }
+ else
+ {
+ DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl);
+ }
+
+ thr_exit(return_value);
+}
+
+
+omni_thread*
+omni_thread::self(void)
+{
+ omni_thread* me;
+
+ THROW_ERRORS(thr_getspecific(self_key, (void**)&me));
+
+ if (!me) {
+ // This thread is not created by omni_thread::start because it
+ // doesn't has a class omni_thread instance attached to its key.
+ DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl);
+ }
+
+ return me;
+}
+
+
+void
+omni_thread::yield(void)
+{
+ thr_yield();
+}
+
+
+void
+omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
+{
+ timespec rqts = { secs, nanosecs };
+ if (nanosleep(&rqts, (timespec*)NULL) != 0)
+ throw omni_thread_fatal(errno);
+}
+
+
+void
+omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
+ unsigned long rel_sec, unsigned long rel_nsec)
+{
+ timespec abs;
+ clock_gettime(CLOCK_REALTIME, &abs);
+ abs.tv_nsec += rel_nsec;
+ abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000;
+ abs.tv_nsec = abs.tv_nsec % 1000000000;
+ *abs_sec = abs.tv_sec;
+ *abs_nsec = abs.tv_nsec;
+}
+
+
+int
+omni_thread::sol_priority(priority_t pri)
+{
+ switch (pri) {
+
+ case PRIORITY_LOW:
+ return 0;
+
+ case PRIORITY_NORMAL:
+ return 1;
+
+ case PRIORITY_HIGH:
+ return 2;
+ }
+
+ throw omni_thread_invalid();
+}
diff --git a/SrcShared/omnithread/solaris.h b/SrcShared/omnithread/solaris.h
new file mode 100644
index 0000000..aaef036
--- /dev/null
+++ b/SrcShared/omnithread/solaris.h
@@ -0,0 +1,47 @@
+// Package : omnithread
+// omnithread/solaris.h Created : 7/94 tjr
+//
+// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory
+//
+// This file is part of the omnithread library
+//
+// The omnithread library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA
+//
+// OMNI thread implementation classes for solaris threads.
+//
+
+#ifndef __omnithread_solaris_h_
+#define __omnithread_solaris_h_
+
+#include <thread.h>
+
+extern "C" void* omni_thread_wrapper(void* ptr);
+
+#define OMNI_MUTEX_IMPLEMENTATION \
+ mutex_t sol_mutex;
+
+#define OMNI_CONDITION_IMPLEMENTATION \
+ cond_t sol_cond;
+
+#define OMNI_SEMAPHORE_IMPLEMENTATION \
+ sema_t sol_sem;
+
+#define OMNI_THREAD_IMPLEMENTATION \
+ thread_t sol_thread; \
+ static int sol_priority(priority_t); \
+ friend void* omni_thread_wrapper(void* ptr);
+
+#endif
diff --git a/SrcShared/xstring2 b/SrcShared/xstring2
new file mode 100644
index 0000000..4cbd8de
--- /dev/null
+++ b/SrcShared/xstring2
@@ -0,0 +1,638 @@
+// xstring internal header (from <string>)
+#ifndef _XSTRING_
+#define _XSTRING_
+
+/* This file is for use only in conjunction with a valid license for
+Microsoft Visual C++ V5.0. Microsoft Corporation is in no way involved
+with the production or release of this file. The file is offered on an
+``as is'' basis.
+
+DINKUMWARE, LTD. AND P.J. PLAUGER MAKE NO REPRESENTATIONS OR WARRANTIES
+ABOUT THE SUITABILITY OF THIS FILE, EITHER EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. DINKUMWARE, LTD.
+AND P.J. PLAUGER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
+LICENSEE AS A RESULT OF USING THIS FILE.
+
+For additional information, contact Dinkumware, Ltd. (+1-888-4DINKUM or
+support@dinkumware.com).
+
+Version date: 25 May 1998
+ */
+
+#include <xmemory>
+
+#ifdef _MSC_VER
+#pragma pack(push,8)
+#endif /* _MSC_VER */
+ #include <xutility>
+_STD_BEGIN
+_CRTIMP void __cdecl _Xlen();
+_CRTIMP void __cdecl _Xran();
+ // TEMPLATE CLASS basic_string
+template<class _E,
+ class _Tr = char_traits<_E>,
+ class _A = allocator<_E> >
+ class basic_string {
+public:
+ typedef basic_string<_E, _Tr, _A> _Myt;
+ typedef _A::size_type size_type;
+ typedef _A::difference_type difference_type;
+ typedef _A::pointer pointer;
+ typedef _A::const_pointer const_pointer;
+ typedef _A::reference reference;
+ typedef _A::const_reference const_reference;
+ typedef _A::value_type value_type;
+ typedef _A::pointer iterator;
+ typedef _A::const_pointer const_iterator;
+ typedef reverse_iterator<const_iterator, value_type,
+ const_reference, const_pointer, difference_type>
+ const_reverse_iterator;
+ typedef reverse_iterator<iterator, value_type,
+ reference, pointer, difference_type>
+ reverse_iterator;
+ explicit basic_string(const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(); }
+ basic_string(const _Myt& _X)
+ : allocator(_X.allocator)
+ {_Tidy(), assign(_X, 0, npos); }
+ basic_string(const _Myt& _X, size_type _P, size_type _M,
+ const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(), assign(_X, _P, _M); }
+ basic_string(const _E *_S, size_type _N,
+ const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(), assign(_S, _N); }
+ basic_string(const _E *_S, const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(), assign(_S); }
+ basic_string(size_type _N, _E _C, const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(), assign(_N, _C); }
+ typedef const_iterator _It;
+ basic_string(_It _F, _It _L, const _A& _Al = _A())
+ : allocator(_Al) {_Tidy(); assign(_F, _L); }
+ ~basic_string()
+ {_Tidy(true); }
+ typedef _Tr traits_type;
+ typedef _A allocator_type;
+ enum _Mref {_FROZEN = 255};
+ static const size_type npos;
+ _Myt& operator=(const _Myt& _X)
+ {return (assign(_X)); }
+ _Myt& operator=(const _E *_S)
+ {return (assign(_S)); }
+ _Myt& operator=(_E _C)
+ {return (assign(1, _C)); }
+ _Myt& operator+=(const _Myt& _X)
+ {return (append(_X)); }
+ _Myt& operator+=(const _E *_S)
+ {return (append(_S)); }
+ _Myt& operator+=(_E _C)
+ {return (append(1, _C)); }
+ _Myt& append(const _Myt& _X)
+ {return (append(_X, 0, npos)); }
+ _Myt& append(const _Myt& _X, size_type _P, size_type _M)
+ {if (_X.size() < _P)
+ _Xran();
+ size_type _N = _X.size() - _P;
+ if (_N < _M)
+ _M = _N;
+ if (npos - _Len <= _M)
+ _Xlen();
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::copy(_Ptr + _Len, &_X.c_str()[_P], _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& append(const _E *_S, size_type _M)
+ {if (npos - _Len <= _M)
+ _Xlen();
+ size_type _N;
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::copy(_Ptr + _Len, _S, _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& append(const _E *_S)
+ {return (append(_S, _Tr::length(_S))); }
+ _Myt& append(size_type _M, _E _C)
+ {if (npos - _Len <= _M)
+ _Xlen();
+ size_type _N;
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::assign(_Ptr + _Len, _M, _C);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& append(_It _F, _It _L)
+ {return (replace(end(), end(), _F, _L)); }
+ _Myt& assign(const _Myt& _X)
+ {return (assign(_X, 0, npos)); }
+ _Myt& assign(const _Myt& _X, size_type _P, size_type _M)
+ {if (_X.size() < _P)
+ _Xran();
+ size_type _N = _X.size() - _P;
+ if (_M < _N)
+ _N = _M;
+ if (this == &_X)
+ erase((size_type)(_P + _N)), erase(0, _P);
+ else if (0 < _N && _N == _X.size()
+ && _Refcnt(_X.c_str()) < _FROZEN - 1
+ && allocator == _X.allocator)
+ {_Tidy(true);
+ _Ptr = (_E *)_X.c_str();
+ _Len = _X.size();
+ _Res = _X.capacity();
+ ++_Refcnt(_Ptr); }
+ else if (_Grow(_N, true))
+ {_Tr::copy(_Ptr, &_X.c_str()[_P], _N);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& assign(const _E *_S, size_type _N)
+ {if (_Grow(_N, true))
+ {_Tr::copy(_Ptr, _S, _N);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& assign(const _E *_S)
+ {return (assign(_S, _Tr::length(_S))); }
+ _Myt& assign(size_type _N, _E _C)
+ {if (_N == npos)
+ _Xlen();
+ if (_Grow(_N, true))
+ {_Tr::assign(_Ptr, _N, _C);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& assign(_It _F, _It _L)
+ {return (replace(begin(), end(), _F, _L)); }
+ _Myt& insert(size_type _P0, const _Myt& _X)
+ {return (insert(_P0, _X, 0, npos)); }
+ _Myt& insert(size_type _P0, const _Myt& _X, size_type _P,
+ size_type _M)
+ {if (_Len < _P0 || _X.size() < _P)
+ _Xran();
+ size_type _N = _X.size() - _P;
+ if (_N < _M)
+ _M = _N;
+ if (npos - _Len <= _M)
+ _Xlen();
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, _Len - _P0);
+ _Tr::copy(_Ptr + _P0, &_X.c_str()[_P], _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& insert(size_type _P0, const _E *_S, size_type _M)
+ {if (_Len < _P0)
+ _Xran();
+ if (npos - _Len <= _M)
+ _Xlen();
+ size_type _N;
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, _Len - _P0);
+ _Tr::copy(_Ptr + _P0, _S, _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& insert(size_type _P0, const _E *_S)
+ {return (insert(_P0, _S, _Tr::length(_S))); }
+ _Myt& insert(size_type _P0, size_type _M, _E _C)
+ {if (_Len < _P0)
+ _Xran();
+ if (npos - _Len <= _M)
+ _Xlen();
+ size_type _N;
+ if (0 < _M && _Grow(_N = _Len + _M))
+ {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, _Len - _P0);
+ _Tr::assign(_Ptr + _P0, _M, _C);
+ _Eos(_N); }
+ return (*this); }
+ iterator insert(iterator _P, _E _C)
+ {size_type _P0 = _Pdif(_P, begin());
+ insert(_P0, 1, _C);
+ return (begin() + _P0); }
+ void insert(iterator _P, size_type _M, _E _C)
+ {size_type _P0 = _Pdif(_P, begin());
+ insert(_P0, _M, _C); }
+ void insert(iterator _P, _It _F, _It _L)
+ {replace(_P, _P, _F, _L); }
+ _Myt& erase(size_type _P0 = 0, size_type _M = npos)
+ {if (_Len < _P0)
+ _Xran();
+ if (_Len - _P0 < _M)
+ _M = _Len - _P0;
+ if (0 < _M)
+ {_Freeze();
+ _Tr::move(_Ptr + _P0, _Ptr + _P0 + _M,
+ _Len - _P0 - _M);
+ size_type _N = _Len - _M;
+ if (_Grow(_N))
+ _Eos(_N); }
+ return (*this); }
+ iterator erase(iterator _P)
+ {size_t _M = _Pdif(_P, begin());
+ erase(_M, 1);
+ return (_Psum(_Ptr, _M)); }
+ iterator erase(iterator _F, iterator _L)
+ {size_t _M = _Pdif(_F, begin());
+ erase(_M, _Pdif(_L, _F));
+ return (_Psum(_Ptr, _M)); }
+ _Myt& replace(size_type _P0, size_type _N0, const _Myt& _X)
+ {return (replace(_P0, _N0, _X, 0, npos)); }
+ _Myt& replace(size_type _P0, size_type _N0, const _Myt& _X,
+ size_type _P, size_type _M)
+ {if (_Len < _P0 || _X.size() < _P)
+ _Xran();
+ if (_Len - _P0 < _N0)
+ _N0 = _Len - _P0;
+ size_type _N = _X.size() - _P;
+ if (_N < _M)
+ _M = _N;
+ if (npos - _M <= _Len - _N0)
+ _Xlen();
+ size_type _Nm = _Len - _N0 - _P0;
+ if (_M < _N0)
+ {_Freeze();
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); }
+ if ((0 < _M || 0 < _N0) && _Grow(_N = _Len + _M - _N0))
+ {if (_N0 < _M)
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
+ _Tr::copy(_Ptr + _P0, &_X.c_str()[_P], _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& replace(size_type _P0, size_type _N0, const _E *_S,
+ size_type _M)
+ {if (_Len < _P0)
+ _Xran();
+ if (_Len - _P0 < _N0)
+ _N0 = _Len - _P0;
+ if (npos - _M <= _Len - _N0)
+ _Xlen();
+ size_type _Nm = _Len - _N0 - _P0;
+ if (_M < _N0)
+ {_Freeze();
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); }
+ size_type _N;
+ if ((0 < _M || 0 < _N0) && _Grow(_N = _Len + _M - _N0))
+ {if (_N0 < _M)
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
+ _Tr::copy(_Ptr + _P0, _S, _M);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& replace(size_type _P0, size_type _N0, const _E *_S)
+ {return (replace(_P0, _N0, _S, _Tr::length(_S))); }
+ _Myt& replace(size_type _P0, size_type _N0,
+ size_type _M, _E _C)
+ {if (_Len < _P0)
+ _Xran();
+ if (_Len - _P0 < _N0)
+ _N0 = _Len - _P0;
+ if (npos - _M <= _Len - _N0)
+ _Xlen();
+ size_type _Nm = _Len - _N0 - _P0;
+ if (_M < _N0)
+ {_Freeze();
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); }
+ size_type _N;
+ if ((0 < _M || 0 < _N0) && _Grow(_N = _Len + _M - _N0))
+ {if (_N0 < _M)
+ _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0,
+ _Nm);
+ _Tr::assign(_Ptr + _P0, _M, _C);
+ _Eos(_N); }
+ return (*this); }
+ _Myt& replace(iterator _F, iterator _L, const _Myt& _X)
+ {return (replace(
+ _Pdif(_F, begin()), _Pdif(_L, _F), _X)); }
+ _Myt& replace(iterator _F, iterator _L, const _E *_S,
+ size_type _M)
+ {return (replace(
+ _Pdif(_F, begin()), _Pdif(_L, _F), _S, _M)); }
+ _Myt& replace(iterator _F, iterator _L, const _E *_S)
+ {return (replace(
+ _Pdif(_F, begin()), _Pdif(_L, _F), _S)); }
+ _Myt& replace(iterator _F, iterator _L, size_type _M, _E _C)
+ {return (replace(
+ _Pdif(_F, begin()), _Pdif(_L, _F), _M, _C)); }
+ _Myt& replace(iterator _F1, iterator _L1,
+ _It _F2, _It _L2)
+ {size_type _P0 = _Pdif(_F1, begin());
+ size_type _M = 0;
+ _Distance(_F2, _L2, _M);
+ replace(_P0, _Pdif(_L1, _F1), _M, _E(0));
+ for (_F1 = begin() + _P0; 0 < _M; ++_F1, ++_F2, --_M)
+ *_F1 = *_F2;
+ return (*this); }
+ iterator begin()
+ {_Freeze();
+ return (_Ptr); }
+ const_iterator begin() const
+ {return (_Ptr); }
+ iterator end()
+ {_Freeze();
+ return ((iterator)_Psum(_Ptr, _Len)); }
+ const_iterator end() const
+ {return ((const_iterator)_Psum(_Ptr, _Len)); }
+ reverse_iterator rbegin()
+ {return (reverse_iterator(end())); }
+ const_reverse_iterator rbegin() const
+ {return (const_reverse_iterator(end())); }
+ reverse_iterator rend()
+ {return (reverse_iterator(begin())); }
+ const_reverse_iterator rend() const
+ {return (const_reverse_iterator(begin())); }
+ reference at(size_type _P0)
+ {if (_Len <= _P0)
+ _Xran();
+ _Freeze();
+ return (_Ptr[_P0]); }
+ const_reference at(size_type _P0) const
+ {if (_Len <= _P0)
+ _Xran();
+ return (_Ptr[_P0]); }
+ reference operator[](size_type _P0)
+ {if (_Len < _P0 || _Ptr == 0)
+ return ((reference)*_Nullstr());
+ _Freeze();
+ return (_Ptr[_P0]); }
+ const_reference operator[](size_type _P0) const
+ {if (_Ptr == 0)
+ return (*_Nullstr());
+ else
+ return (_Ptr[_P0]); }
+ const _E *c_str() const
+ {return (_Ptr == 0 ? _Nullstr() : _Ptr); }
+ const _E *data() const
+ {return (c_str()); }
+ size_type length() const
+ {return (_Len); }
+ size_type size() const
+ {return (_Len); }
+ size_type max_size() const
+ {size_type _N = allocator.max_size();
+ return (_N <= 2 ? 1 : _N - 2); }
+ void resize(size_type _N, _E _C)
+ {_N <= _Len ? erase(_N) : append(_N - _Len, _C); }
+ void resize(size_type _N)
+ {_N <= _Len ? erase(_N) : append(_N - _Len, _E(0)); }
+ size_type capacity() const
+ {return (_Res); }
+ void reserve(size_type _N = 0)
+ {if (_Res < _N)
+ _Grow(_N); }
+ bool empty() const
+ {return (_Len == 0); }
+ size_type copy(_E *_S, size_type _N, size_type _P0 = 0) const
+ {if (_Len < _P0)
+ _Xran();
+ if (_Len - _P0 < _N)
+ _N = _Len - _P0;
+ if (0 < _N)
+ _Tr::copy(_S, _Ptr + _P0, _N);
+ return (_N); }
+ void swap(_Myt& _X)
+ {if (allocator == _X.allocator)
+ {std::swap(_Ptr, _X._Ptr);
+ std::swap(_Len, _X._Len);
+ std::swap(_Res, _X._Res); }
+ else
+ {_Myt _Ts = *this; *this = _X, _X = _Ts; }}
+ friend void swap(_Myt& _X, _Myt& _Y)
+ {_X.swap(_Y); }
+ size_type find(const _Myt& _X, size_type _P = 0) const
+ {return (find(_X.c_str(), _P, _X.size())); }
+ size_type find(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (_N == 0 && _P <= _Len)
+ return (_P);
+ size_type _Nm;
+ if (_P < _Len && _N <= (_Nm = _Len - _P))
+ {const _E *_U, *_V;
+ for (_Nm -= _N - 1, _V = _Ptr + _P;
+ (_U = _Tr::find(_V, _Nm, *_S)) != 0;
+ _Nm -= _U - _V + 1, _V = _U + 1)
+ if (_Tr::compare(_U, _S, _N) == 0)
+ return (_U - _Ptr); }
+ return (npos); }
+ size_type find(const _E *_S, size_type _P = 0) const
+ {return (find(_S, _P, _Tr::length(_S))); }
+ size_type find(_E _C, size_type _P = 0) const
+ {return (find((const _E *)&_C, _P, 1)); }
+ size_type rfind(const _Myt& _X, size_type _P = npos) const
+ {return (rfind(_X.c_str(), _P, _X.size())); }
+ size_type rfind(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (_N == 0)
+ return (_P < _Len ? _P : _Len);
+ if (_N <= _Len)
+ for (const _E *_U = _Ptr +
+ + (_P < _Len - _N ? _P : _Len - _N); ; --_U)
+ if (_Tr::eq(*_U, *_S)
+ && _Tr::compare(_U, _S, _N) == 0)
+ return (_U - _Ptr);
+ else if (_U == _Ptr)
+ break;
+ return (npos); }
+ size_type rfind(const _E *_S, size_type _P = npos) const
+ {return (rfind(_S, _P, _Tr::length(_S))); }
+ size_type rfind(_E _C, size_type _P = npos) const
+ {return (rfind((const _E *)&_C, _P, 1)); }
+ size_type find_first_of(const _Myt& _X,
+ size_type _P = 0) const
+ {return (find_first_of(_X.c_str(), _P, _X.size())); }
+ size_type find_first_of(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (0 < _N && _P < _Len)
+ {const _E *const _V = _Ptr + _Len;
+ for (const _E *_U = _Ptr + _P; _U < _V; ++_U)
+ if (_Tr::find(_S, _N, *_U) != 0)
+ return (_U - _Ptr); }
+ return (npos); }
+ size_type find_first_of(const _E *_S, size_type _P = 0) const
+ {return (find_first_of(_S, _P, _Tr::length(_S))); }
+ size_type find_first_of(_E _C, size_type _P = 0) const
+ {return (find((const _E *)&_C, _P, 1)); }
+ size_type find_last_of(const _Myt& _X,
+ size_type _P = npos) const
+ {return (find_last_of(_X.c_str(), _P, _X.size())); }
+ size_type find_last_of(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (0 < _N && 0 < _Len)
+ for (const _E *_U = _Ptr
+ + (_P < _Len ? _P : _Len - 1); ; --_U)
+ if (_Tr::find(_S, _N, *_U) != 0)
+ return (_U - _Ptr);
+ else if (_U == _Ptr)
+ break;
+ return (npos); }
+ size_type find_last_of(const _E *_S,
+ size_type _P = npos) const
+ {return (find_last_of(_S, _P, _Tr::length(_S))); }
+ size_type find_last_of(_E _C, size_type _P = npos) const
+ {return (rfind((const _E *)&_C, _P, 1)); }
+ size_type find_first_not_of(const _Myt& _X,
+ size_type _P = 0) const
+ {return (find_first_not_of(_X.c_str(), _P,
+ _X.size())); }
+ size_type find_first_not_of(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (_P < _Len)
+ {const _E *const _V = _Ptr + _Len;
+ for (const _E *_U = _Ptr + _P; _U < _V; ++_U)
+ if (_Tr::find(_S, _N, *_U) == 0)
+ return (_U - _Ptr); }
+ return (npos); }
+ size_type find_first_not_of(const _E *_S,
+ size_type _P = 0) const
+ {return (find_first_not_of(_S, _P, _Tr::length(_S))); }
+ size_type find_first_not_of(_E _C, size_type _P = 0) const
+ {return (find_first_not_of((const _E *)&_C, _P, 1)); }
+ size_type find_last_not_of(const _Myt& _X,
+ size_type _P = npos) const
+ {return (find_last_not_of(_X.c_str(), _P, _X.size())); }
+ size_type find_last_not_of(const _E *_S, size_type _P,
+ size_type _N) const
+ {if (0 < _Len)
+ for (const _E *_U = _Ptr
+ + (_P < _Len ? _P : _Len - 1); ; --_U)
+ if (_Tr::find(_S, _N, *_U) == 0)
+ return (_U - _Ptr);
+ else if (_U == _Ptr)
+ break;
+ return (npos); }
+ size_type find_last_not_of(const _E *_S,
+ size_type _P = npos) const
+ {return (find_last_not_of(_S, _P, _Tr::length(_S))); }
+ size_type find_last_not_of(_E _C, size_type _P = npos) const
+ {return (find_last_not_of((const _E *)&_C, _P, 1)); }
+ _Myt substr(size_type _P = 0, size_type _M = npos) const
+ {return (_Myt(*this, _P, _M)); }
+ int compare(const _Myt& _X) const
+ {return (compare(0, _Len, _X.c_str(), _X.size())); }
+ int compare(size_type _P0, size_type _N0,
+ const _Myt& _X) const
+ {return (compare(_P0, _N0, _X, 0, npos)); }
+ int compare(size_type _P0, size_type _N0, const _Myt& _X,
+ size_type _P, size_type _M) const
+ {if (_X.size() < _P)
+ _Xran();
+ if (_X._Len - _P < _M)
+ _M = _X._Len - _P;
+ return (compare(_P0, _N0, _X.c_str() + _P, _M)); }
+ int compare(const _E *_S) const
+ {return (compare(0, _Len, _S, _Tr::length(_S))); }
+ int compare(size_type _P0, size_type _N0, const _E *_S) const
+ {return (compare(_P0, _N0, _S, _Tr::length(_S))); }
+ int compare(size_type _P0, size_type _N0, const _E *_S,
+ size_type _M) const
+ {if (_Len < _P0)
+ _Xran();
+ if (_Len - _P0 < _N0)
+ _N0 = _Len - _P0;
+ size_type _Ans = _Tr::compare(_Psum(_Ptr, _P0), _S,
+ _N0 < _M ? _N0 : _M);
+ return (_Ans != 0 ? _Ans : _N0 < _M ? -1
+ : _N0 == _M ? 0 : +1); }
+ _A get_allocator() const
+ {return (allocator); }
+protected:
+ _A allocator;
+private:
+ enum {_MIN_SIZE = sizeof (_E) <= 32 ? 31 : 7};
+ void _Copy(size_type _N)
+ {size_type _Ns = _N | _MIN_SIZE;
+ if (max_size() < _Ns)
+ _Ns = _N;
+ _E *_S;
+ _TRY_BEGIN
+ _S = allocator.allocate(_Ns + 2, (void *)0);
+ _CATCH_ALL
+ _Ns = _N;
+ _S = allocator.allocate(_Ns + 2, (void *)0);
+ _CATCH_END
+ if (0 < _Len)
+ _Tr::copy(_S + 1, _Ptr, _Len);
+ size_type _Olen = _Len;
+ _Tidy(true);
+ _Ptr = _S + 1;
+ _Refcnt(_Ptr) = 0;
+ _Res = _Ns;
+ _Eos(_Olen); }
+ void _Eos(size_type _N)
+ {_Tr::assign(_Ptr[_Len = _N], _E(0)); }
+ void _Freeze()
+ {if (_Ptr != 0
+ && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
+ _Grow(_Len);
+ if (_Ptr != 0)
+ _Refcnt(_Ptr) = _FROZEN; }
+ bool _Grow(size_type _N, bool _Trim = false)
+ {if (max_size() < _N)
+ _Xlen();
+ if (_Trim)
+ _Len = 0;
+ else if (_N < _Len)
+ _Len = _N;
+ if (_Ptr != 0
+ && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
+ if (_N == 0)
+ {_Tidy(true);
+ return (false); }
+ else
+ {_Copy(_N);
+ return (true); }
+ if (_N == 0)
+ {if (_Trim)
+ _Tidy(true);
+ else if (_Ptr != 0)
+ _Eos(0);
+ return (false); }
+ else
+ {if (_Trim && (_MIN_SIZE < _Res || _Res < _N))
+ {_Tidy(true);
+ _Copy(_N); }
+ else if (!_Trim && _Res < _N)
+ _Copy(_N);
+ return (true); }}
+ static const _E * __cdecl _Nullstr()
+ {static const _E _C = _E(0);
+ return (&_C); }
+ static size_type _Pdif(const_pointer _P2, const_pointer _P1)
+ {return (_P2 == 0 ? 0 : _P2 - _P1); }
+ static const_pointer _Psum(const_pointer _P, size_type _N)
+ {return (_P == 0 ? 0 : _P + _N); }
+ static pointer _Psum(pointer _P, size_type _N)
+ {return (_P == 0 ? 0 : _P + _N); }
+ unsigned char& _Refcnt(const _E *_U)
+ {return (((unsigned char *)_U)[-1]); }
+ void _Tidy(bool _Built = false)
+ {if (!_Built || _Ptr == 0)
+ ;
+ else if (_Refcnt(_Ptr) == 0 || _Refcnt(_Ptr) == _FROZEN)
+ allocator.deallocate(_Ptr - 1, _Res + 2);
+ else
+ --_Refcnt(_Ptr);
+ _Ptr = 0, _Len = 0, _Res = 0; }
+ _E *_Ptr;
+ size_type _Len, _Res;
+ };
+template<class _E, class _Tr, class _A>
+ const basic_string<_E, _Tr, _A>::size_type
+ basic_string<_E, _Tr, _A>::npos = -1;
+
+#ifdef _DLL
+#pragma warning(disable:4231) /* the extern before template is a non-standard extension */
+
+extern template class _CRTIMP basic_string<char, char_traits<char>, allocator<char> >;
+extern template class _CRTIMP basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >;
+
+#pragma warning(default:4231) /* restore previous warning */
+#endif
+
+typedef basic_string<char, char_traits<char>, allocator<char> >
+ string;
+typedef basic_string<wchar_t, char_traits<wchar_t>,
+ allocator<wchar_t> > wstring;
+_STD_END
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+#endif /* _XSTRING */
+
+/*
+ * Copyright (c) 1995-1998 by P.J. Plauger. ALL RIGHTS RESERVED.
+ * Consult your license regarding permissions and restrictions.
+ */
diff --git a/SrcUnix/DefaultLarge.xpm b/SrcUnix/DefaultLarge.xpm
new file mode 100644
index 0000000..acec0f5
--- /dev/null
+++ b/SrcUnix/DefaultLarge.xpm
@@ -0,0 +1,732 @@
+/* XPM */
+static char *DefaultLarge[] = {
+/* width height ncolors chars_per_pixel */
+"436 664 61 1",
+/* colors */
+" c #000000",
+". c #005A31",
+"X c #ADADAD",
+"o c #082918",
+"O c #A5A5A5",
+"+ c #525A39",
+"@ c #394231",
+"# c #002110",
+"$ c #738C63",
+"% c #7B8C5A",
+"& c #738452",
+"* c #7B7B7B",
+"= c #737373",
+"- c #525A42",
+"; c #6B6B6B",
+": c #636363",
+"> c #004A29",
+", c #006B39",
+"< c #393939",
+"1 c #313131",
+"2 c #DEDEDE",
+"3 c #292929",
+"4 c #D6D6D6",
+"5 c #212921",
+"6 c #007B42",
+"7 c #212121",
+"8 c #CECECE",
+"9 c #182118",
+"0 c #5A6B52",
+"q c #C6C6C6",
+"w c #52634A",
+"e c #63734A",
+"r c #636B4A",
+"t c #9C9C9C",
+"y c #949494",
+"u c #293121",
+"i c #087B42",
+"p c #8C8C8C",
+"a c #848484",
+"s c #737B52",
+"d c #425239",
+"f c #6B7B4A",
+"g c #424A39",
+"h c #21945A",
+"j c #6B845A",
+"k c #5A5A5A",
+"l c #525252",
+"z c #FFFFFF",
+"x c #4A4A4A",
+"c c #424242",
+"v c #EFEFEF",
+"b c #E7E7E7",
+"n c #4A4A39",
+"m c #5A6342",
+"M c #181818",
+"N c #101810",
+"B c #101010",
+"V c #BDBDBD",
+"C c #081008",
+"Z c #4A5242",
+"A c #000800",
+/* pixels */
+"zzzzzzz11333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111zzzzzzz",
+"zzzzz<<1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111133zzzzz",
+"zzzz<<<xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxllllllc<133Mzzzz",
+"zzz<<kyy=lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklxc<37Mzzz",
+"zz<<:XOp;kllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllxc<<137Mzz",
+"z<<kXXXy=:lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc<<111773z",
+"z<xyXXX=xccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1111M3z",
+"<<:yXXacccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1117B3",
+"1<:ptpcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1333B3",
+"1c:=p;cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1333BB",
+"1ck:=lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VzV;cc;VvV;ccccccccccp8kvk8ccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVccVzzzVcccccccccccXc8VXccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzzzzzzccctcX8tccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVccVzzzVccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;cc;VvV;ccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccckXV*8;Xpcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;ccccc;VvV;cccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccck;*;*;*;*kcccccccccccccccccccc*;*cccccccccccccccccccccccccccccccccccc*X288Xpcccccccccc;X888X*ccccc*tcvp8tcccccccc;;*;*;*;*;*;kccccccccccccccccccccccccccccccccccccccc;*;kccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccVzzzVcccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccc;zzzzzzzzzvtcccccccccccccccccczzz;ccccccccccccccccccccccccccccccccc*vzzzzzzzv*cccccck8zzzzzzzv;ccc;tc8X8tcccccccczzzzzzzzzzzztccccccccccccccccccccccccccccccccccccccczzz;ccccccccccccccccptX;cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzzzzzzccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccc;zzzzzzzzzzzVccccccccccccccccczzz*ccccccccccccccccccccccccccccccccpzzzzzzzzzzzpccccc2zzzzzzzzzz;cc;Xc8VpXcccccccczzzzzzzzzzzzXccccccccccccccccccccccccccccccccccccccczzz*cccccccccccccccc8zzXccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccVzzzVcccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz28888zzzz*cccccccccccccccczzz;ccccccccccccccccccccccccccccccc;zzzzV*k;Xzzzz;ccctzzzX;k;XzzzvccccccccccccccccczzzvV8888888pccccccccccccccccccccccccccccccccccccccczzz;cccccccccccccccc8zztcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VzX;ccccc;VvV;cccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzkcccc*zzzXcccccccccccccccczzz;ccccccccccccccccccccccccccccccc8zzz*ccccc*zzz8ccc2zzpccccckzzz;cccccccccccccccczzzpcccccccccccccccccccccccccccccccccccccccccccccccczzz*cccccccccccccccc8zzXccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz;ccccc2zz8ccccp2zzz2tccccczzz*cck82XcVvzzVcc*2zz8;ccccccccccczzzXcccccccXzzz;cczzz;cccccc2zztcccccccccccccccczzztcccccccccccc288ctvzz8;c;Vzz2*ccccX88pccccp88Xccczzz;cccct8zzz8Xccc*8vzz22pccccp8zzz8pcccccp82*cVz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc*VzV;cc;VvV;ccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz;ccccc8zz2ccc2zzzzzzzzkccczzz;cc*zz82zzzzz8pzzzzzz*cccccccccpzzzkcccccccczzzpcczzz8cccccccccccccccccccccccccczzztcccccccccccczzzXzzzzzv;zzzzzztccc8zzXcccctzz8ccczzz*ccc2zzzzzzzzkctzzzzzztccc2zzzzzzz2cccctzzX8zz8ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccXzzzVccVzzzVccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz;cccccvzzVcctzzz282zzz8ccczzz;cc;zzzz28zzzzzz82zzzVcccccccccXzzzccccccccczzzVccVzzzvVtkcccccccccccccccccccccczzz8tXtXtXt;cccczzzzvVzzzzzz22zzzzccc8zztcccctzz8ccczzz;cctzzz282zzzVckt2zz8t;cc2zzzv8vzzz8ccctzz2zzz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzzzzzzccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzt;;**8zzztccvzzVccc*zzzccczzz*cckzzz*ccczzzvkccVzzzccccccccc8zz8ccccccccc8zz8cckzzzzzzzz8tkcccccccccccccccccczzzzzzzzzzzXcccczzzVccc2zzz*cc*zzz*cc8zztccccpzz8ccczzz*ccvzzVccc*zzzccc8zztccc*zzz*ccc*zzzpccpzzzzVtpccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVccVzzzVccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzzzzzzzzzvcccpptccccpzzzccczzz;cckzzzcccc8zztccckzzzccccccccc8zz8ccccccccc8zz8ccc;2zzzzzzzzztccccccccccccccccczzzzzzzzzzztcccczzz;ccctzz2cccczzz;cc8zzXcccctzz8ccczzz;ccpptccccpzzzccc8zztcccVzzXcccccXzz8cctzzz*ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;cc;VvV;ccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzzzzzzzzv;ccccckpt88zzzzccczzz*cckzzzcccc8zztccckzzzcccccccccVzz2cccccccccVzz8ccccckt8zzzzzzzpcccccccccccccccczzz8tptpptt;cccczzz;cccpzz8cccczzz*cc8zztccccpzz8ccczzz;cccckpt88zzzzccc8zzXcccvzz*ccccc;zzvccpzz2ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz28888X*cccccc8zzzzzvzzzccczzz;cckzzzcccc8zzXccckzzzcccccccccXzzzccccccccczzzXccccccccccp8zzz2cccccccccccccccczzzpcccccccccccczzz*cccpzz8cccczzz;cc8zztccccpzz8ccczzz*ccc2zzzzzvzzzccc8zztccczzz;ccccckzzzcctzz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;cccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzkccccccccccc8zz2tkckzzzccczzz;cckzzzccccVzztccckzzzccccccccc;zzz;ccccccckzzzpcc;;;cccccccpzzzcccccccccccccccczzztcccccccccccczzz;ccctzz2cccczzz;cc8zztcccctzz8ccczzz;cc8zz2tkckzzzccc8zztccczzz*ccccckzzzccpzz2ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzzkccccccccccczzzcccc;zzzccczzz*cckzzzcccc8zztccckzzzcccccccccczzz8ccccccc8zzzkc;zzz;cccccckzzzcccccccccccccccczzztcccccccccccczzz;ccctzz8cccczzz*cc8zzXccccXzz8ccczzz;cczzzcccc;zzzccc8zzXccc8zzXccccctzz8cctzz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzzzzzzccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz*cccccccccckzzzcccc2zzzccczzz;cckzzzcccc8zztccckzzzccccccccccXzzzVkccccXzzzVccczzz8ccccccVzz2cccccccccccccccczzztcccccccccccczzz*cccpzz8cccczzz;ccXzz2ccckvzz8ccczzz;ckzzzcccc2zzzcccVzztcccpzzv;ccccvzztccpzz8ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz;ccccccccccczzzvtXvzzzzccczzz*cckzzzcccc8zzXccckzzzccccccccccczzzzvVtXvzzzvcccctzzzzXXtXvzzzpcccccccccccccccczzzzzzzzzzzzzccczzz;ccctzz8cccczzz*ccpzzz8tXvzzz8ccczzz;cczzzvtXvzzzzccc8zz2tkcczzzvVtVvzzvcccpzz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;cccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz*ccccccccccc8zzzzzzXzzzccczzz;cckzzzcccc8zztccckzzzccccccccccccvzzzzzzzzzv;ccccc2zzzzzzzzzzVccccccccccccccccczzzzzzzzzzzzzccczzz*cccpzz2cccczzz;cccvzzzzzz8zz2ccczzz;cc8zzzzzzXzzzcccXzzzztcccvzzzzzzzv;ccctzz2ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccckzzz;cccccccccccc8zzzv;czzzXcczzz*cckzzzcccc8zztccckzzzcccccccccccccXzzzzzzzXkcccccccpvzzzzzzvpcccccccccccccccccczzzzzzzzzzzzzccczzz;cccpzz8cccczzz*ccccvzzzv*kzz8ccczzz;ccc8zzz2;czzzXcccvzzztccccVzzzzzV;ccccpzz8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VzX*cccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccckcccccccccccccccccccccccccccccccccccccccccccccccccc;ppp;cccccccccccck*tppkccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccckkcccccccccccccccccckkcccccccccccc;;kcccccckkkcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzzzzzzccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccVzzzVcccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;VvV;cccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1ck:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccccccc<<<1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111<<cccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccccc<13333311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111133333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333311<cccccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lccccccccccccccccccccccccccccccccccccccccccccccccc133333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333111<cccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccccc13333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333331111<ccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lccccccccccccccccccccccccccccccccccccccccccccccc133377MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM311111<cccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccccc13337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM1111<cccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lccccccccccccccccccccccccccccccccccccccccccccc<3337BBBM@@nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn@@uBM7111<<ccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lccccccccccccccccccccccccccccccccccccccccccccc1337MBB@nnn+mrfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe+9M71<<<ccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc<3337BB@nnnr%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%s771<<<ccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc<333MBMnn+&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%+73<ccccccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BB@n+&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%73<xcxcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BB@ne%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cllxcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBn+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnm%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBne%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kklcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<kkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1cl:;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1clk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1clk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1clk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk;lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:lcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkcccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<lk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<lkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<333MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%n1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1333BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xkkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xk:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1cxlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBnf%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xl:xcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$www$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$0u9 9uZ$$$$$$$$$$$$$$$$$$$$$$$$$$$$juA NZ$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0wwwwj$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$j@C A@j$$$$$$$$$$$$$$$$$$$$$$$$jN 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@9 A@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@uC d$$$$$$$$$$$$$$$$$$$$$$$$0uN 9gj$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$gA A@$$$$$$$$$$$$$$$$$$$$$$$g d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j @$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jNA$$$$$$$$$$$$$$$$$$$$$$dC 9w$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$j9 N0$$$$$$$$$$$$$$$$$$$$$9C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$d w$$$$$$$$$$$$$$$$$$$ZC A99N 90$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$0A C9999 AZ$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jA Z$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$ju 5dj$$$$@ g$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$0A uj$$$jZuC d$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@ 9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$jN 9j$$$ZZ$$$ZA u$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$0A AZ$$$$$$0uA w$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jCj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$jC A d$$$Z Z$$$Z u$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$jC u$$$$$$$j@A Aj$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$jN Cwju d$$ZZjuC wg u$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$u Z$$$$$$$$ju 9$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$5 uj$$$u w$ju NZj$9 g$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$w Ng$$$$$$$$$$wC d$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$g Aw$$$$$$u A0u ujZ$$$w Aj$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$9 5dj$$$$$$$$$$$$$j5 C$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$jA 9j$$$$$$$$N Nj0$Z Z$$$9 9$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$w Auj$$$$$$$$$$$$$$$$$$5 d$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$@ u$$$g d$w@jjA 5$$ZZZ$$ju w$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$u uj$$$$$$$$$$$$$$$$$$$$@ 9$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$jA u$$$$jN 5 0$w Z$$$$$dA 5$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$A Aw$$$$$$$$$$$$$$$$$$$$$$u j$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$d d$$$$$d 9j$$$u Aj$$wN j$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$w 9j$$$$$$$$$$$$$$$$$$$$$$$9 d$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$5 d$$j5 CAN$$$$jA uZ9 g$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$@ u$$$$$$$$$$$$$$$$$$$$$$$$$ u$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$ 0$@ ujg g$$$$d Adu 5$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$u u$$$$$$$$$$$$$$$$$$$$$$$$$w 9$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$0 A0j0$$$NN$$$$Z 9j$jA C$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$9 9$$$$$$$$$$$$$$$$$$$$$$$$$$u 9$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$Z Nj$$$$j0$$j5 CZ$$$$u $$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$9 Nj$$$$$$$$$$$$$$$$$Zj$$$$$$$C $$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$@ u$$$$$$j@A @j$$$dZZ 0$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$9 0$$$$$$$$$$$$$$$j@A 9$$$$$$0 $$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$@ Z$$$j@A j$$j9 5j w$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$9 @$$$$$$$$$$$$$$$gA j$$$$$u N$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$@ Ajwu Au g$ZA @j$ w$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$5 N$$$$$$$$$$$$$$ju Z$$$$jA 9$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$@ A C@j$@ N0 C0$$$ 0$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$@ @$$$$$$$$$$$$$jN @$$$$@ u$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$Z 9d$$jZj 0@j$@A0 $$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$Z u$$$$$$$$$$$$$9 @$$$jA g$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$w 9w$$$$u $u d$jN 9j A$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$j C$$$$$$$$$$$$@ @$$$u 0$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$ Cw$Zw$$$N9$d ujA g$$ 5$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$9 0$$$$$$$$$$0 @$$w C$$$$0j$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$9 Aj$C 5jj u$j CZA0$$Z g$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$@u5999u$$$d u$$$$$$$$$$9 @$jC @$$$@A@du0$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$g g$ju A9 0$$C j$$$jC j$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$du @uN j$$$A 0$$$$$$$$w @$N j$$wAjwC5N$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$j C$$$0N j$$u Z$$jN 9$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$N@5Cw$$$$g N$$$$$$$$5 Zu @$$$@uj900A$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$u 0$$$d A0$@ u$0N Z$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$@ Nj$$$$$$N @$$$$$$j A Aj$$$wC95$u5$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$jA u$$jACwAA0w NgA 9$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$w u$$$wg$$$0 d$$$$$g Z$$$j$dg09C0$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$@uuj$$$@ C$$u w$0Agj 0$$$@@j$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$jg$$ju A0$$$d w$$$$5 @$$$jA5j$jdj$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$jCCggNj$$$N jw 5$$$$j@ @$$$@55N$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$wCN0wN$$$$u d$$$ u$$$$$0NCw$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$5u$$$ud$$$jA dgAj$$0u 9$$$jCj$NC@j$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$g uCj$90$$$$@ u$0 u$$$$dgjju @$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$Nj$$$uu$$$$0A u$$0gN Nj$$$9g$Z5ZN5$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$dw$@5uAjw$$$$dA Cu g$$$$0 A5CC Z$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$uZ$$$u0$$$$$0A C5A 9j$$$$u uNj$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$d50d u$$$$j9 N0$$$$$$wANj$0w$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$jCN@$$$$$$$$$j9 u$$$$0@Z0NAZ$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$d u9uj$$$$w9 Cd$$$$j@C9Zj9Ad$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$00$$$$Zu$$$$$gA Cw$$$$dA9NNjgAu$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$0 9$$ j$$$$$$0uC Cuw$$$$$$Nuwu w$g j$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$jgC9N$$$$$$j@A Cd$$$$$j 0$$uu$jw$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$0A5A@uAj5Z$$$$$$$jwg@@@@wj$$$$$$$$wC$$$uC$$j$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$09A9jN0$@Z$$$$$jd5A CuZ$$$$$$ww $$$j j$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$dN$j59ZwAj$$$$$$$$$$$$$$$$$$$$$jNjdA$$$0 j$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$0@wAu5$w 0$$$$$$$$$jwZ@@wwj$$$$$$$09ujC0$$jAj$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$9@$$$$dj$$$$$$$$$$$$$0uC59@jA@$$0C$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$0 ZjC@$$$$$$$$$$$$$$$$$$$$$$$juAC$$dCwwNu$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$dAj$$$0 0$wu@$$$$$$$jN d$wAjd 5@Cd$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$ZN$uCj$$$juuw$$$$$$$$$$$$$$w$jdjCg$$wCAu$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$jCd$$$$uN$gAuuCj$0 g$$Z$Ad$$9@$wuu0$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$0Z0 w$$$0AuuAZjg$$$$$$$$$$u @$$$ZAj$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<xlkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$w d$$$$AgjAd$$Cd$@CN$$$$u9$$0 j$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$dAw$$$uu$$d9d $$@9u5$$$$u9Aw$$$95$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$ju9w$Z jw $$$$j$9@CZ$$$Z j$$uu$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$0Nuj$N0$$jd@9$$u5@9$$$$55gA0$$jAw$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$ww$u5$0 j$$$$$A0gC$$$$Ag$$j$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$@0$Cw$$$$u9$$9@dC$$$$u5u N$$$0$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$uZ$jAd$dNjZ 0$$$@d$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$ZA@u9$9@$$N@w $$$$uAuZ u$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$ZAACd$@9$$u9$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$Zu@j$u5$j ww $$wjuu$$j$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$j$$$dw$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$wCAC5$$ 9ZZw$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$jj$$$j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$jw@@@@@@Z0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$jgN Cu0$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$jg5C 9uZ$$$$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$ju 9w$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$dN A@j$$$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$gA 5j$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$wC A@j$$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<133MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$j9 Aw$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$ju C0$$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$jN 9999N d$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$jN d$$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$jN 9@Z0$$$$$$$$u d$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$0A C5@5C d$$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$jN AuZ$$$$$$$$$$$$$$u w$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$jN 9w$$$$$gA d$$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$u 9d$$$$$$$$$$$$$$$$$$9Aj$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$9 g$$jdu9u$w A0$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$w 9Z@u$$$$$$$$$$$$$$$$$$jA5$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$@ d$ju 0$5 N$$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$C 9wdA @$$$$$$$$$$$$$$0wwg5 w$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$jA u$0A N@Z0$$@ @$$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$d AgwN w$$$$$$$w@u9A 9$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$u CjjC Nw$$$$$$Z Aj$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$9 90u 9$$$0@N 0$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$j @$u Cj$$$$$$$@ @$$$$$$$$$$$$$%g1<xlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$j @wA NdjuC u$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$g 0j w$$$$$$$$N C C$$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$g dZ Nww5 A5N C$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$N $w N$$$$$$$$0 99 0$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$5 A0jN Cdw9 Au0$00N j$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$00$$$w w$$$$$$$$$$j $juw$$$$$$$$9 wN @$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$C CjjN @0u 9d$$$N @jA w$$$$$$$$$$$$$$$$99$$$$$$$$$$$dudj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0u9 9$$$w w$$$$$$$$$$Z Z$$$$$$$$$$u uj 5$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$ NjjujgA 9w$$$$$@gj$w @$$$$$$$$$$$$$$$$99$$$$$$$$$$$$C j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$w 9ud0$$$w w$$$$$$$$$$@ 9$$$$$$$$ju Cj@ C$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$ 5$j9 9w$dCA$$$$$$$$u @$$$$$$$$$$$$$$$$99$$$$$$$$$$$Z 5$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$wj$$$$9$$$$$$$w w$$$$$$$$$$@ d$$$$$$wN A0jA $$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$w 5A Cd$w9 CZ$$$$$dANjA @$$$$$$$$$$$$$$$$99$$$ZCAuj$$$u d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0Au$$$$9wu9uj$$w w$$$$$$$$$$9 C 9dww@N A0$5 $$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$j 0$9 A@j$$$$$$g5Z$g @$$$$$$$$$$$$$$$$99$$ju$u d$$jAAjj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$gC j$$$uAA 5$$w w$$$$$$$$$$9 udA 9j$d $$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$ 9$9uj$$$099$$$$$$$C @$$$$$$$$$$$$$$$$99$$$$$g @$$d AC Cj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@d 5$$$ZZ$0 j$w w$$$$$$$$$$u @$jg9 A5w$$g $$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$ g$$$$ju Ag$$$$$$$g d$$$$$$$$$$$$$$$$99$$059u @$$9 w$@ 9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@j9 w$$$$$$u j$w w$$$$$$$$$$@ Aw$$$$$$jw$$$$j5 A$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$9 Aj$j@ uj$$$$$0CAjA w$$$$$$$$$$$$$$$$99$$CN$w @$j C$$j C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$g00 9ujj$$$@9$$w w$$$$$$$$$$d Nj$$jN@0$$$$$0uA 9$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$u u$5 90$$$$$$$ZC@$u $$$$$$$$$$$$$$$$$99$$ AZ5 @$@ u$$d u$$j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@Cuj$$$uwjC 9jduj0C0$$w w$$$$$$$$$$0 Nj$$$N A999A u$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$Z www$$$$d5$$$$$$d9 5$$$$$$$$$$$$$$$$$99$$@ 9wC9jC @$jNAj$dC 5uj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u u$$$guA9 Cjj5Cuj$$$w w$$$$$$$$$$$A Nj$$$u Z$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$A 9$$$$ZC N$$$j@A d$$$$$$$$$$$$$$$$$99$$$$$$$$$j@ 995w$Z A0$5N$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Agju5d@jZ9w$u uj$$$$$$$w w$$$$$$$$$$$u Aj$$$d j$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$u w$w9 Ad$$juA Aj$$$$$$$$$$$$$$$$$99$$$$$$$$$$$jj$$$$C Z$$u@$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$uw$wA Aj$$Zuw$$$$$$$$$w w$$$$$$$$$$$w w$$$0A u$$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$j 9$ A@j$j@ @$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$ Cj$$w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jZ$u@w@ d$$j$$$$$$$$$$$w w$$$$$$$$$$$$C u$$$0A w$$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$@ w0j$$@A Aj$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$9C$$$$$j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0$$$9j$$$$$$$$$$$$$$w w$$$$$$$$$$$$Z Cj$$0A 9$$$$$$$$$$$$$$%g1cxlkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$jC 9$$ZC Z$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$0Agj$j9 uj$$@j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ju9@$$$$$$$uj$$$$$$$$$$$$$$w w$$$$$$$$$$$$$9 d$$dA j$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$0 w9 u$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$juZjA 9w0Cjj5AZ$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$C @$$jud5d$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$jA uju g$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$d N$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$u @$$$59A N0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$d ZjuAj$$@Nd$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$Z u$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$d Nj$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$5 $$$jN @$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@9$$$ud$w d$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$d Nj$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$d 5j$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$ZA0$wA N0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$dNj$$j5$9 j$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$d 9j$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$0C @$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$Zu9 uj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$wZ$$$@d u$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$ZA u$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$j@A 90$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$@ Cw$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$gCAj$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$j5 CZ$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$j@C 5w$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$jNj$Zu@j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0 @$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$w9 A@j$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$w@9A 9udj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$0jN Cj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$9j$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$0uC A5d$$$$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$u 5Cjw9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jZ0$$$$$$jw$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$jw@@@@@Z0$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$$uC0$$$$$$$$$$$$$$$$$$$uw$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$CN$u0$Nj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j 9ugw$ww$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$jAAw$0j$$$$$$$$$$$$00$$uu$$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$Nd$Z5u $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$CuN j$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$$u0$$$$$$$$$$$$$j0$$$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$g9AjjC @C9u@00w$$90@u$$j j$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$@u$j u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0 9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Nj$$wdu9A$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$w CCu00$$$$$$j@N 5$$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBns$$$$$$$$$$$$$$$$$Cg $5NCZ wg@0u d$Ndj j$$9d$$$$$$$$$$$$$$$$$$$$$$$99$$$$$$$$$$$$$$$$$$$$$$$$$$5w$wZ$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$9 w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$uj$$$$$$u$$$$$$$$$$$$$$$$$$$$$w w$$$$$$$$$$$$$$$$$$$$uN$0@d j9g$0Nj @$wAg$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBnf$$$$$$$$$$$$$$$$ZCwNu99@@C0$$$@CAj9@$5g$$g9$$$$$$$$$$$$$$$$$$$$$$$9N$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$d C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j$$$$$$d$$$$$$$$$$$$$$$$$$$$$Z w$$$$$$$$$$$$$$$$$$$$CCgj$Z $ Ajw $9u$$u9$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBnf$$$$$$$$$$$$$$$$ggdCA0 juAC 9$dC@u5u$dNj09u$$$$$$$$$$$$$$$$$$$$$$$@ 0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jC d$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$5 j$$$$$$$$$$$$$$$$$$$0 guA0@9$A9uw $gA$$dN$$$$$$$$$$$$$$$$$$$$$%g1cxxkxccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BBnf$$$$$$$$$$$$$$$$$$dCwuu$9@$$j$w $9A9$$5 Ag$$$$$$$$$$$$$$$$$$$$$$$$jAAgwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwu CwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwZ5 u$$$$$$$$$$$$$$$$$$$$gC$$$$u5$9u9g $j 0$55$$$$$$$$$$$$$$$$$$$$$%n1xllkcccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc1133BB@f$$$$$$$$$$$$$$$$$$$$$90$C9Zw$$0 $0 9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0C u$$$$$$$$$$$$$$$$$$$$$d@$$$$9@$9@jA w$CCCNj$$$$$$$$$$$$$$$$$$$$$%@1k:k:cccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc<113MBuf$$$$$$$$$$$$$$$$$$$$$$$$g@9NC$$C0$w@$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwj$$$$$$$$$$$$$$$$$$$$$$$$$$$$Ad$9@$u w$g@0$$$$$$$$$$$$$$$$$$$$$$$&1<==;:cccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccc<1137MNr$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jj$dw$jwj$$$$$$$$$$$$$$$$$$$$$$$$$$$-<xaa*:cccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccc11137Mu$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$r<<atyakcccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccc<111377ue$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$&-<<kXOtaccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccc11113733@gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnZ1<<kXXXOkccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccc<1111113311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111<<<c*OXVXacccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccc<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ccccccccccccccccccccclk*tXXXaccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccc<<<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkk;*pOXXpcccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk::::::::::::::::::::::::::;=apty;ccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccccxxlkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;*a=:ccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<cc<cc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<cc<cc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cccc<cc<cccccc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<ccc<c<cccccc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<ccc<c<cccccc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<ccc<c<cccccc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<ccc<<<c<<c<<<<c<c<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccc<c<ccc<c<c<c<c<<<<c<cc<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<ccc<c<c<c<c<<<<c<cc<c<cccccccccccccccccccccccccccccccccccccccccccccccccc<c<ccc<c<c<c<c<<<<c<cc<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<c<cc<<c<c<<<<<<c<<c<cc<ccccccccccccccccccccccccccccccccccccccccccccccccccc<cccc<<c<c<<<<<<<c<<<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cccc<<c<c<<<<<<<c<<<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccc<cccc<<c<c<<<<<<<c<<<c<c<ccccccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<c<c<<<<<<<<<<<<<<<<<<<c<<c<ccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<c<<<<<<<<<<<<<<<<<c<c<c<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<c<<<<<<<<<<<<<<<<<c<c<c<cccccccccccccccccccccccccccccccccccccccccccc<cc<<<<c<<<<<<<<<<<<<<<<<c<c<c<ccccccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<c<<<<<<1<11111<11<<<<<<c<cc<c<ccccccccccccccccccccccccccccccccccccccccccc<ccc<<<<<<1<11111<1<<<<<<<c<cc<c<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<ccc<<<<<<1<11111<1<<<<<<<c<cc<c<cccccccccccccccccccccccccccccccccccccccccc<ccc<<<<<<1<11111<1<<<<<<<c<cc<c<cccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<cc<<<<<1<11111111111111<1<<<<<<c<c<cccccccccccccccccccccccccccccccccccccc<c<cc<<<<<<111111111111111<1<<<<<<c<c<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<cc<<<<<<111111111111111<1<<<<<<c<c<ccccccccccccccccccccccccccccccccccccc<c<cc<<<<<<111111111111111<1<<<<<<c<c<ccccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<<<1111113333333333111111<<<<<<cccc<cccccccccccccccccccccccccccccccccc<cc<<<<<<1111113333333333311111<<<<<<cccc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<<<1111113333333333311111<<<<<<cccc<ccccccccccccccccccccccccccccccccc<cc<<<<<<1111113333333333311111<<<<<<ccc<ccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<<111113337377777733333331111<<<<<<<ccccccccccccccccccccccccccccccccc<c<c<<<<<111113337377777733333331111<<<<<<<ccc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<<111113337377777733333331111<<<<<<<ccc<cccccccccccccccccccccccccccc<c<c<<<<<111113337377777733333331111<<<<<<ccc<ccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccccc<c<c<<<111333777777M7M7MM77773331111<<<<c<<ccccccccccccccccccccccccccccccccc<c<c<<<111333777777M7M7MM77773331111<<<<c<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<<111333777777M7M7MM77773331111<<<<c<<cccccccccccccccccccccccccccccccc<c<c<<<111333777777M7M7MM77773331111<<<<<<cccccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<111333777MMMBBBBBBBBBMM7M77333311<<<<<c<c<cccccccccccccccccccccccccc<c<c<<<<111333777MMMBBBBBBBBBMM7M77333311<<<<<c<c<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<111333777MMMBBBBBBBBBMM7M77333311<<<<<c<c<cccccccccccccccccccccccccc<cc<<<<111333777MMMBBBBBBBBBMM7M77333311<<<<<<c<c<cccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxcccccccccccccccccccccccccccccccccccccccccccccc<cc<<<<11133377MMBBBBBBBBBBBBBBBBMM777333111<<<<<ccccccccccccccccccccccccccccc<c<<<11133377MMBBBBBBBBBBBBBBBBMM777333111<<<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<c<<<<1133377MMBBBBBBBBBBBBBBBBMM777333111<<<<<cccccccccccccccccccccccccc<cc<<<<11133377MMBBBBBBBBBBBBBBBBMM777333111<<<c<ccccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccccc<<<<<111337MMMBBBBBBBBBCBBBBBBBBBBBM77333111<<<c<<c<cccccccccccccccccccccc<c<c<<<111337MMMBBBBBBBBBCBBBBBBBBBBBM77333111<<<c<c<cccccccccccccccccccccccccccccccc1137BBC C C CCBB7311cccccccccccccccccccccccccccccccccc<c<<<111337MMMBBBBBBBBBCBBBBBBBBBBBM77333111<<<c<c<cccccccccccccccccccccccc<<<<<111337MMMBBBBBBBBBCBBBBBBBBBBBM77333111<<<<c<ccccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccc<cc<<<111377MMBBBBBBBCBBBBBCBBCBBBBBBBBM7733111<<<c<ccccccccccccccccccccccccc<c<<<111377MMBBBBBBBCBBBBBCBBCBBBBBBBBM7733111<<<<ccc<ccccccccccccccccccccccccc137BCCBM73331111113337MBCCB731ccccccccccccccccccccccccccc<c<<<<113377MMBBBBBBBCBBBBBCBBCBBBBBBBBM7733111<<<<ccc<cccccccccccccccccccc<cc<<<111377MMBBBBBBBCBBBBBCBBCBBBBBBBBM77331111<<<cc<c<ccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccc<cc<<<<113377MBBBBBBBCBBBBCBBBBBBBBBCBBBBBM77331111<<c<c<cccccccccccccccccccc<cc<<<113377MBBBBBBBCBBBBCBBBBBBBBBCBBBBBM77331111<<<<cccccccccccccccccccccccc17BBM73<c<c<cc<cc<ccccc<c<<c<37MBB71cccccccccccccccccccccc<ccc<<<113377MBBBBBBBCBBBBCBBBBBBBBBCBBBBBM77331111<<<<cccccccccccccccccccc<cc<<<<113377MBBBBBBBCBBBBCBBBBBBBBBCBBBBBM7733111<<<<<cccccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccccc<c<<11337MMBBBBBBCBBBB731<<<<<137MBBBBBBBMM773111<<<<ccccccccccccccccccccc<cc<<<11337MMBBBBBBCBBBB731<<<<<137MBBBBBBBMM773111<<<c<cccccccccccccccccccc17CM31cccccccccccccccccccccccccccc<c13MC71ccccccccccccccccccccc<<<<11337MMBBBBBBCBBBB731<<<<<137MBBBBBBBMM773111<<<c<ccccccccccccccccccccc<c<<11337MMBBBBBBCBBBB731<<<<<137MBBBBBBBMM773111<<<cc<cccccccccccccccccccccccccccccccccccc<333MB",
+"1<clkxccccccccccccccccccccccccccccccccccccccccccc<c<<<11337MMBBBBCBBBB7<cccc<<<<<<1<<13BBCBBCMM733311<<c<ccccccccccccccccccccc<<<<11337MMBBBBCBBBB7<cccc<<<<<<1<<13BBCBBCMM733311<<<cc<cccccccccccccccc1CM3cxcxxxxxxxxxxxxxxxxxxxxxxxxxxxccxxccxc3MC1ccccccccccccccccc<c<<<11337MMBBBBCBBBB7<cccc<<<<<<1<<13BBCBBCMM733311<<<cc<ccccccccccccccccc<c<<<11337MMBBBBCBBBB7<cccc<<<<<<1<<13BBCBBCMM733311<<<<ccccccccccccccccccccccccccccccccccccc<333MB",
+"1MMMMMMMMMMMMMMMMMMMMMMMMMMM3<ccccccccccccccccccc<c<<11137MBBBBBBBBB3cxcxxxxxccc<<<1<1113MBBBBBM733111<<<c<ccccccccccccccccc<cc<<<1137MBBBBBBBBB3cxcxxxxxccc<<<1<1113MBBBBBM733111<<<cccccccccccccccccCB3cxxllllllllllklklkkklklklllllllllllxlxxxxc3BCcccccccccccccccc<c<<<1137MBBBBBBBBB3cxcxxxxxccc<<<1<1113MBBBBBM733111<<<ccccccccccccccccccc<c<<11137MBBBBBBBBB3cxcxxxxxccc<<<1<1113MBBBBBM733111<<c<cccccccccccccccccccccccccccccccccccc<333MB",
+"1BBMBBBBBBBBBBBBBBBBBBBBBBBBM3<cccccccccccccccc<cc<<<1337MBBBBBBCB7<xllkkklllxcccc<<<<11117BBBBBM733111<<<ccccccccccccccccccc<<<<1337MBBBBBBCB7<xllkkklllxcccc<<<<11117BBBBBM73311<<<<cccccccccccccccC7cxlllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklkllllxc7Cccccccccccccc<cc<<<1337MBBBBBBCB7<xllkkklllxcccc<<<<11117BBBBBM73311<<<<cccccccccccccccc<cc<<<1337MBBBBBBCB7<xllkkklllxcccc<<<<11117BBBBBM73311<<<<cccccccccccccccccccccccccccccccccccc<333MB",
+"1BBMBBo>>>>>>>>>>>>>>>>>>>>oBM3cccccccccccccccccc<<<1137MMBBBBCBB1xlk:;;;;:kkllxcc<<<1<11113MCBBB733111<<cc<cccccccccccccc<c<c<<1137MMBBBBCBB1xlk:;;;;:kkllxcc<<<1<11113MCBBB733111<<c<ccccccccccccc1 cxlllkkkkkkk:k::k:k::k::k::k::::kk:kkkkkkkklllx1 Mcccccccccccccc<<<1137MMBBBBCBB1xlk:;;;;:kkllxcc<<<1<11113MCBBB733111<<<c<cccccccccccccccc<<<1137MMBBBBCBB1xlk:;;;;:kkllxcc<<<1<11113MCBBB733111<<c<ccccccccccccccccccccccccccccccccccc<333MB",
+"1BBMBoh66666666666666666666,oB3ccccccccccccccc<c<<<<1337MBBBBBBBcxk;=*a**==;:klxxcc<<<1111113MBBBB773111<<<ccccccccccccccccc<<<<1337MBBBBBBBcxk;=*a**==;:klxxcc<<<1111113MBBBB773111<<cccccccccccccc1 cxllkkkkkkkkkkkkkkkkkkkkkkkkkkkkk:kkkkkkkkkkllx1 M<ccccccccc<c<<<<<1337MBBBBBBBcxk;=*a**==;:klxktVa<<1111113MBBBB773111<<ccccccccccccccc<c<<<<1337MBBBBBBBcxk;=*a**==;:klxxcc<<<1111113MBBBB773111<<cccccccccccccccccccccccccccccccccccc<333MB",
+"1MMMB,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<c<<1137MBBBBCBBcl:=apypppa*=;=yqvzzX<<<<111113MBBBM7331<<<cccccccccccccccc<cc<<1137MBBBBCBBcl:=apyppXa*=;:klxxcc<<<<111113MBBBM7331<<<<c<ccccccccccc1 cxllllllkllkllklkklklkkklkkkkkkkkkkkkkkkkkllllx1 M<ccccccccccccc<<1137MBBBBCBBcl:=apypppa*=;aXvzzzzO<<<111113MBBBM7331<<<<cccccccccccccccc<<<1137MBBBBCBBcl:=apypppa*pVyklxxcc<<<<111113MBBBM7331<<<<c<ccccccccccccccccccccccccccccccccc<333MB",
+"1MMMB,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<cc<<1137MMBBBBBBcl:*pyttttpp*y8zzzzzzzq<1<1111113MCBBM33111<<c<cccccccccccccc<<<1137MMBBBBBBcl:*pytttvz4*=;:klxxcc<<1<1111113MCBBM33111<<ccccccccccccc1 <xxxxxllxllxllxlxlllllxlllllllllllllllllllllllx< M<ccccccccc<c<<<1137MMBBBBBBcl:*pyttttpp*X4zzzzzzzz*1<1111113MCBBM33111<<cccccccccccccc<c<<1137MMBBBBBBcl:*pyttttyatz4v8lxxcc<<1<1111113MCBBM3311<<<ccccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<<<1137MBBBBCB<l:*ptOXXOtyOvzzzzzzzz4y<<<11111333MBBB7311<<<<cccccccccccc<c<c<<1137MBBBBCB<l:*ptOXXOvzzX*;:kllxcc<<<<11111333MBBB7311<<<<cccccccccccc1 cccxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1 M<ccccccccccc<<<1137MBBBBCB<l:*ptOXXOtyVzzzzzzzzzzzz:<11111333MBBB7311<<<<ccccccccccc<cc<<<1137MBBBBCB<l:*ptOXXOtXpvO=:Ollxcc<<<<11111333MBBB73111<<<cccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<<<11377BBBCBB3xk=pOXXXXOXvzzzzzzzztk<<<<1111131337BBBM3311<<ccccccccccccccc<<<<1377BBBCBB3xk=pOXX4vXXzzv=;:kkxxcc<<<1111131337BBBM3311<<ccccccccccccc1 <cccccccccccccccccccccccccccccccxcxcxcxcxxxxccc1 M<cccccccc<c<<<<1377BBBCBB3xk=pOXXXXO4vzbvzzzzzzzzzzv:111131337BBBM3311<<cccccccccccccc<<<11377BBBCBB3xk=pOXXXX4zzvz=;t*lxxcc<<<1x*1131337BBBM3311<<ccccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<<1137MBBBBBBck=atOXXXVvzzzzzzzvpxxcc;VV<1111131337CBB7311<<<ccccccccccccc<c<<1137MBBBBBBck=atOX4zzVt4zzX;:kllxccc<<<1111131337CBB7311<<<cccccccccccc1 <<c<c<c<c<c<c<c<cc<cc<cc<cccccccccccccccccccccc1 M<ccccccccccc<<1137MBBBBBBck=atOXXXqvzzb*azzzzzvyaXzz41111131337CBB7311<<<cccccccccccc<c<<1137MBBBBBBck=atOXXXqzqX84a4zal:xccc<<:zz4c131337CBB7311<<<cccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccc<c<<<133MMBBCBB<x:*pOXXV4zzzzzzz4aklxxXvzzzy1111113333BBBM3311<<ccccccccccc<cc<<1133MMBBCBB<x:*pOXXvzzzOtvzz*kklxxcc<<<<1111113333BBBM3311<<cccccccccccc1 1c<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<c1 M<ccccccccc<<<1133MMBBCBB<x:*pOXXqvzzzzX=qzzz4axcc*zzzy111113333BBBM3311<<cccccccccc<cc<<<133MMBBCBB<x:*pOXqv48vypa=az4kl4=cc<<14vVz4c13333BBBM3311<<cccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<cc<<1137MBBBBBMcl;ayOXVvzzzzzzvX:kl:xcXzzzzvx1111313377BBB7111<cccccccccccccc<<<<137MBBBBBMcl;ayOXXbzzz4aXzzakllxxcc<<<111111313377BBB7111<ccccccccccccc1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<3 M<ccccccc<cc<<<137MBBBBBMcl;ayOX8vzzzzzt=4z4tlxc;y4zzzzx111313377BBB7111<ccccccccccccc<<<1137MBBBBBMcl;ayO8zbbz8pV8=:zzXqz4kc<<yz=14zp313377BBB3111<ccccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccc<<<<1137MBBCBB1xk=ayOqzzzzzzzV;:k*qz=xcvzzzzp1113133337BBB7311<<cccccccccccc<c<<1137MBBCBB1xk=ayOXX4zzzzt=z4:klxxcc<<<<<11113133337BBB7311<<cccccccccccc1 1<<1<1111111111111<11<11<11<1<1<1<1<1<1<1<1<<<<3 M<cccccccc<<<<1137MBBCBB1xk=ayObzzzzzzv=;zzylx=vzzzzzzzV113133337BBB7311<<ccccccccccc<c<<1137MBBCBB1xk=ayXz8OtOp4zO;=zzzzzzX<<<z4111zV313337BBB7311<<cccccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccccc<<1337BBBBBBcx:=ayXzzzzzz4a;:=4zzzzkclzzpx11111313337MBCM311<<ccxccccccccc<c<<1337BBBBBBcx:=aytOOVzzzz4;;:klllxccc<<1<11111313337MBCM311<<ccxccccccccc1 1<1<1111111111<1<1111111111111<1<1<1<1<1<1<11<<3 M<cccccc<ccc<<1337BBBBBBcx:=aOvzzzzzzz8;tzzqO4zzzzzzzzzzk11313337MBCM311<<ccxcccccccc<c<<1337BBBBBBcx:=ayVzqtVXpXzV:4zzzzzzza<Xz=11Oz=333337MBCM311<<ccxccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccc<c<<<<133MBBCBB7cx:=apyOzzzvX=;;=zzzzzzVc<:<<1:p1111333337BBB3111<cxcccccccc<cc<<1133MBBCBB7cx:=ayytyVzzzzzt::kklxcc<c<<<<111111333337BBB3111<cxcccccccccc1 1<<1111111111111111111111111<1111111111111111<<3 M<cccccccc<<<1133MBBCBB7cx:=ap4zzzzX*yp:tzzzzzzzzzzzzzzzv111333337BBB3111<cxccccccc<cc<<<133MBBCBB7cx:=ayyz4vvy*Xzzbzzz4aaqzv:z4<11b411133337BBB3111<cxcccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<1137MBBBBB1cl:=*ppyXz4p=;;;:4zzzzzv;<<<:Ozzk133333377BBB711<<ccxxcccccccc<<<<137MBBBBB1cl:=*apyppzzzzzt::kllxxcc<<<11111133333377BBB711<<ccxxcccccccc1 1<<1<1111111111111111111111<111<1<1<1<1<1<1<<<<3 M<cccccc<cc<<<137MBBBBB1cl:=*py4zzzX=;;:8zzzzzzzzzzbypzzzk33333377BBB711<<ccxxccccccc<<<1137MBBBBB1cl:=*apqzzv*=bzzzz4Olxcyzzvz*11Ozk33333377BBB711<<ccxxcccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<<<<1137MBBBCB<clk;=aaaaX==;Vv=:=vzzzXl<<<<zzzzV311333377MCB711<<cxxcccccccc<c<<1137MBBBCB<clk;=aaaa*4zzzzy:kkllxcc<<<<<1111311333377MCB711<<cxxccccccccc1 1<<1<1<<<<<<<<<<<<<<<<<<<<<1<<<1<1<1<1<1<1<1<<<7 M<ccccccc<<<<1137MBBBCB<clk;=aaavzzz4X=:4zzzzzzzzzOx11zzzO31333377MCB711<<cxxccccccc<c<<1137MBBBCB<clk;=aaabzz88zzzzO;lxxavzzzb11xzV313333377MCB711<<cxxccccccccccccccccccccccccccccccc<333MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<1137MBBBBM<cxk:==***==*vz4OkkOz4kc<lX1<Ozzzzx33133337MBBM11<<cxxxccccccc<c<<1137MBBBBM<cxk:==***=Xzzzz8kkklxcc<<<<1<1111131333337MBBM11<<cxxxcccccccc1 77777777777777777777777777777777777373737373777M M<ccccccccc<<1137MBBBBM<cxk:==***vzzzzzzzzplazzzV<1<xVzzzzc1333337MBBM11<<cxxxcccccc<c<<1137MBBBBM<cxk:==**=vzzzzz4=kkl=vzzzzz*11yzk131333337MBBM11<<cxxxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<<<<1337MBBCB7<cxkk;;===;:vyk:kkllxxc<qzz*1xzzzO313333377MBBM11<<cxxxcccccccc<<<1337MBBCB7<cxkk;;===;*zzzzvkllxxcc<<<1<11111131333377MBBM11<<cxxxcccccccccM M<cccccccc<<<1337MBBCB7<cxkk;;===pzzzzzzq;lxxzzl<<<OzzzzzzO1333377MBBM11<<cxxxccccccc<<<1337MBBCB7<cxkk;;===*vzzzykkl=4zzyl<zz11xzV1111333377MBBM11<<cxxxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccc<c<c<<1337MBBBBM<cxlk:::;:::kkk;pyp:ccc*bzzv11Obp1313333737MBCM11<<cxlxxcccc<c<c<<1337MBBBBM<cxlk:::;:::8zzzzplxccc<<<1<111111313333737MBCM11<<cxlxxccccccccccMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM3<ccccc<c<<<<1337MBBBBM<cxlk:::;::Ozzzv*llkkcyzlxpzzzzzzzz83333737MBCM11<<cxlxxccc<c<c<<1337MBBBBM<cxlk:::;;:yzzOkk;XzzXl<1yzO11Ozc1333333737MBCM11<<cxlxxccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<<<<1137MBCBBM<<cxlkk:::kkk*qvzzzz4y<<*vzzp1xc13=k33333777BBM31<<cllxccccccc<<<<1137MBCBBM<<cxlkk:::kk*zzzzvkxc<<<<1111111131333333777BBM31<<cllxccccccccccccc<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ccccccc<c<<1137MBCBBM<<cxlkk:::kkvzzqlxtvy<lz4bzzzzzzzzzz33333777BBM31<<cllxcccccc<<<<1137MBCBBM<<cxlkk::kkkqztl=4z4;<<<*vzx1:v8113133333777BBM31<<cllxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccc<<<1337MBBBBM<<cxxlklkkllXzzzzzzzzz4x1:zz41111Vz=3337377MBBM1<<<xlllxccc<ccc<<<1337MBBBBM<<cxxlkklkkllvzzzzqccc1<*x11111111313337377MBBM1<<<xlllxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<1337MBBBBM<<cxxlklkkll*zz4xx4zq<14zzzzzzzzzzzz=337377MBBM1<<<xlllxcccccc<<<1337MBBBBM<<cxxlkkkkkllvzzzzyc<cxvzz411Vzk31333337377MBBM1<<<xlllxccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccc<c<<<1337MBBCB7<<ccxxlllllqzzzzzzllvzzvx1pO111cbzzV3333777MBCM11<<xllxxccccc<c<<<1337MBBCB7<<ccxxllllllx=zzzzz4l<<4zz:1111113133333777MBCM11<<xllxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<1337MBBCB7<<ccxxllllllxqzzacXX<<<VzzzzzzzzV4zzV333777MBCM11<<xllxxcccc<c<<<1337MBBCB7<<ccxxllllllxazzv;cc<Ozzzz=1xzz113113333777MBCM11<<xllxxccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccc<ccc<<1137MBBBBM<<<ccxxxxxXzzzzzzq<<4zzzO111111kzzzV3333777MBBM1<<cxlklccccc<ccc<<1137MBBBBM<<<ccxxxxxxxxcXzzzzzzy1=zzzx111131333333777MBBM1<<cxlklcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<1137MBBBBM<<<ccxxxxxxxxkzzq<<<<x4zzzzzzzvk33zzX333777MBBM1<<cxlklcccc<ccc<<1137MBBBBM<<<ccxxxxxxxxc4zyc<:vzzpzz11Vzz131333333777MBBM1<<cxlklcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<<<<1137MBBBCM<<<<ccccxxvzzzzzzO<:zzzzzp11kp11zzzt337777MMBB71<<clkkxxcccccc<<<<1137MBBBCM<<<<ccccxxcxccc4zzzzzz*1Vzzbc1131333333777MMBB71<<clkkxxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<1137MBBBCM<<<<ccccxxcxccXzz<<lOvzzzzzzzp331Ozzv37777MMBB71<<clkkxxccccc<<<<1137MBBBCM<<<<ccccxxcxcckv4*XzzOxpzO1xzzzO3133333777MMBB71<<clkkxxccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<11337BBBBB1<<<<ccccXzzzzzzzx<*zzzzzV11zV31zzVc3333777BBC71<<cl:klccccccccc<<11337BBBBB1<<<<ccccccccc<lvzzzzzzxx4zzV31131333373777BBC71<<cl:klccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<11337BBBBB1<<<<ccccccccc<vzX*bzbOxpzz4c11kbzzzX333777BBC71<<cl:klcccccccc<<11337BBBBB1<<<<ccccccccc<Ozzzv=114z=1Vzzz433333373777BBC71<<cl:klcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccc<c<<<<1377MBCBB31<<<<<c<Vzzv*yV4<1Vzzzzzz11zz13V833337777MBBB1<<<xk:llcccccc<c<<<<1377MBCBB31<<<<<<c<cc<c<<:zzzzzzzcczzzx331333333777MBBB1<<<xk:llccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<1377MBCBB31<<<<<<c<cc<<<OzzzzVx11xzzc1cVzzzzv337777MBBB1<<<xk:llccccc<c<<<<1377MBCBB31<<<<<<c<cc<<<lbz4111xzb1kzzzzz3133333777MBBB1<<<xk:llcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccc<c<11137MBBBB71<1<<<<<zzzV<<<<<14zzzzzz13Vz=3c33337377MMBBB1<<cx::kxcccccccc<c<11137MBBBB71<1<<<<<<<<<<<<<:zzzzzzV1kzz131333333777MMBBB1<<cx::kxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<11137MBBBB71<1<<<<<<<<<<<:zzz:11113VzV=vzzzzb<37377MMBBB1<<cx::kxccccccc<c<11137MBBBB71<1<<<<<<<<<<<<Oz*11*zzV34zzzzz=33333777MMBBB1<<cx::kxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<<11377BBBBM11<1<<<<zzzvyx<11<zzzzzzz11Vz=33333737777BBBM1<<ck::lxccccccccc<<<11377BBBBM11<1<<<<<<<<<<<11:vzzzzzO1=c3133333377777BBBM1<<ck::lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<11377BBBBM11<1<<<<<<<<<<<4zV11*v=1pzzzzzzzXc3377777BBBM1<<ck::lxcccccccc<<<11377BBBBM11<1<<<<<<<<<<<xz4=4zzz=Vzzzzzzc333777777BBBM1<<ck::lxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccc<c<<<<1337MBBCB11111<1<vzzzzzz4V4zzzzzzz33V;3333337777MMBBB3<<cx:;:lxccccccc<c<<<<1337MBBCB11111<1<<<<<1<1<11x4zzzzzc1133333373777MMBBB3<<cx:;:lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<1337MBBCB11111<1<<<<<1<1pzz11Vzk1kzzzzzzp3373777MMBBB3<<cx:;:lxcccccc<c<<<<1337MBBCB11111<1<<<<<1<1<Vzzzzzzzzzzzz8c33333777MMBBB3<<cx:;:lxcccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<<11377BBBBM1111111Vzzzzzzzzzzzzzzzv13c33333373777MMBBB1<<cl;;klcccccccccccc<<11377BBBBM11111111111<111111cVzzzz13=pc333333777MMBBB1<<cl;;klccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11377BBBBM11111111111<11:zz:1p=11czzzzbk33333777MMBBB1<<cl;;klccccccccccc<<11377BBBBM11111111111<111kzzzzzzzzzzzOc333373777MMBBB1<<cl;;klccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccc<<<<11377MBBBB3111111kzzzzzzzzzzzzzzzt31333333737777MBBC7<<<xk;;klcccccccccc<<<<11377MBBBB31111111111111111111=VbzzzzzV333377777MBBC7<<<xk;;klccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<11377MBBBB311111111111111zzp1113=vzzzO3333377777MBBC7<<<xk;;klccccccccc<<<<11377MBBBB3111111111111111vzzzzzzzzbk33333737777MBBC7<<<xk;;klccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<<<11377BBCBM11111114zzzzzzzzzzzzzzc333333337777MMMBBB1<<cl;=:lxcccccccccccc<<<11377BBCBM111111111111111111313cVzzzz;3377777MMMBBB1<<cl;=:lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<11377BBCBM11111111111111zzV31cvzzzVc333377777MMMBBB1<<cl;=:lxccccccccccc<<<11377BBCBM111111111111111XzzzzzzzO33333373777MMMBBB1<<cl;=:lxccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccc<c<c<<11337MBBBB7111111kzzzzzzzzzzzzzp3333333737777MMBCB7<<cx:==:lcccccccccc<c<c<<11337MBBBB71111111111111113131333=Ozz=3337777MMBCB7<<cx:==:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<<<11337MBBBB71111111111111zzzOOzzzbk33333337777MMBCB7<<cx:==:lccccccccc<c<c<<11337MBBBB711111111111111=zzzzz8k333333377777MMBCB7<<cx:==:lcccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<<<<11337MBBBB3131111=zzzzzzzzzzzp3333333737777MMBBBB<<<cl=*;kxccccccccccccc<<<<11337MBBBB31311111113131313131333;zzzz47777MMBBBB<<<cl=*;kxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<11337MBBBB3131111111313zzzzzz8k333333777777MMBBBB<<<cl=*;kxcccccccccccc<<<<11337MBBBB313111111131313zzz8=3333333773777MMBBBB<<<cl=*;kxcccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccccc<cc<<11337MMBCBM3313333k4zzzzzzzbp3333333737777MMBBBB3<<<l;*=:lxcccccccccccc<cc<<11337MMBCBM3313313131311313333333czz4XX777MMBBBB3<<<l;*=:lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<11337MMBCBM331331313131zzzz8=3333333773777MMBBBB3<<<l;*=:lxccccccccccc<cc<<11337MMBCBM33133131313113z8p33333333737777MMBBBB3<<<l;*=:lxcccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3ccccccccccccccccc<<<<11337MMBBBM33111133kV8zzV=33333337377777MMMBBC7<<cx:**=kxccccccccccccccc<<<<11337MMBBBM33113131313333333333373777377MMMBBC7<<cx:**=kxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<11337MMBBBM3311313131czbOc33333373737777MMMBBC7<<cx:**=kxcccccccccccccc<<<<11337MMBBBM33113131313333333333337737777MMMBBC7<<cx:**=kxccccccccccccccccccccccccccccccccc<313MB",
+"1337B,hiiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccc<c<<<<11337MBBBBM333331333333333333337377777MMBBBBM<<<cl=a*:lxcccccccccccccc<c<<<<11337MBBBBM33333333333333333333737777MMMBBBBM<<<cl=a*:lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<11337MBBBBM333333333ck3333333333777777MMBBBBM<<<cl=a*:lxccccccccccccc<c<<<<11337MBBBBM33333333333333333333737777MMMBBBBM<<<cl=a*:lxccccccccccccccccccccccccccccccccc<313MB",
+"1337B.6iiiiiiiiiiiiiiiiiiii,>B3cccccccccccccccccccc<<1113377MCBBB7333333333333333373777777MMBBCBM<<<cl=aa=kxccccccccccccccccccc<<1113377MCBBB333333333333333337377777M7MBBCBM<<<cl=aa=kxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<1113377MCBBB3333333333333333377777777MMBBCBM<<<cl=aa=kxcccccccccccccccccc<<1113377MCBBB333333333333333337377777M7MBBCBM<<<cl=aa=kxcccccccccccccccccccccccccccccccccc<313MB",
+"1337Bo>....................>#B3cccccccccccccccc<cc<<<<113337MMBBBB7333333333373737777777MMMBBBBM<<<cl;ap=:lxccccccccccccccc<cc<<<<113337MMBBBBM3333333333337377777777MMBBBBM<<<cl;ap=:lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<113337MMBBBBM333333333373737777777MMMBBBBM<<<cl;ap=:lxcccccccccccccc<cc<<<<113337MMBBBBM3333333333737377777777MMBBBBM<<<cl;ap=:lxcccccccccccccccccccccccccccccccccc<313MB",
+"1337BB#o####################BM3cccccccccccccccccc<c<<<<1113377MCBBBB777373737377777777MMMBBBBB7<<<cx:ap*;kxcccccccccccccccccc<c<<<<1113377MCBBBM777373737777777777MMMBBBBB7<<<cx:ap*;kxcccccccccccccc7 7ccccccccccccc<ccc<<<<1113377MCBBBM777373777377777777MMMBBBBB7<<<cx:ap*;kxccccccccccccccccc<c<<<<1113377MCBBBM773737373737777777MMMBBBBB7<<<cx:ap*;kxccccccccccccccccccccccccccccccccccc<313MB",
+"1337MBBBBBBBBBBBBBBBBBBBBBBBM3<ccccccccccccccccccccc<<<<1113377MBBBBBMM777777777777M7MMBBBBCB3<<<cx:apa;kxcccccccccccccccccccccc<<<<1113377MBBBCBMM777777777777M7MMBBBCBB7<<<cx:apa;kxcccccccccccccc1 1<<<c<<c<c<c<<<c<<<c<<<c<<<c<<<c<<<c<<<c<<<<c<<1 3ccccccccccccccccc<<<<1113377MBBBCBMM777377777777M7MMBBBBCB3<<<cx:apa;kxccccccccccccccccccccc<<<<1113377MBBBCBMM777777777777M7MMBBBCBB7<<<cx:apa;kxcccccccccccccccccccccccccccccccccccc<313MB",
+"11111111111111111111111111<<<clcccccccccccccccccc<ccc<<<<11113337MBBCBBBMM7777777MMMBBBBBBBM1<<<cx:apa=:lxccccccccccccccccccc<ccc<<<<11113337MBBBBBBMM7777777MMMBBBBBBBM1<<<cx:apa=:lxcccccccccccccc1 <xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcxxxxcxc7 M<cccccccccccccc<cc<<<<11113337MBBBBBBMM7777777MMMBBBBBBBM1<<<cx:apa=:lxcccccccccccccccccc<ccc<<<<11113337MBBBBBBMM77777M7MMMBBBBBBBM1<<<cx:apa=:lxcccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccc<c<<<<111133377MBBBBBBBBBBBBBBBBBBCBBB3<<<<cl;apa=:lxccccccccccccccccccccccc<c<<<<111133377MCBBBBBBBBBBBBBBBBBCBBB3<<<<cl;apa=:lxccccccccccccccc1 cxlllllllllllllllllllllllllllllllllllllllxlllxx1 M<cccccccccccc<ccc<c<<<<111133377MCBBBBBCBBBBBBBBBBBCBBB3<<<<cl;apa=:lxcccccccccccccccccccccc<c<<<<111133377MCBBBBBBBBBBBBBBBBBCBBB3<<<<cl;apa=:lxccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccccc<c<<<1111133337MBBCBBCBBBBBBBBBBB71<<<<cxl;apa=:lxcccccccccccccccccccccccccc<c<<<1111133337MBBBCBBBBBBBBBBBBB71<<<<cxl;apa=:lxcccccccccccccccc1 cllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklkkkkkkkllll< M<cccccccccccccccccc<c<<<1111133337MBBBBBBBBBBBBBBBBB71<<<<cxl;apa=:lxccccccccccccccccccccccccc<c<<<1111133337MBBBCBBBBBBBBBBBBB71<<<<cxl;apa=:lxcccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccc<cc<c<<<<111113333377MBBBBBBBCBM7311<<<<cxk=ap*=klxccccccccccccccccccccccccc<cc<c<<<<111113133377MMCBBCBBCBM7311<<<<cxk=ap*=klxccccccccccccccccc1 cllkkkk:k:k:k:k:k:k:k:kk:kk:kkk:kkk:kkkkkkk:kll< M<cccccccccccccccc<cc<c<<<<111113133377MBBBCBBCBBM7311<<<<cxk=ap*=klxcccccccccccccccccccccccc<cc<c<<<<111113133377MMCBBBBBBBM7311<<<<cxk=ap*=klxccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxccccccccccccccccccccccccccccccccccccccccccccccc<cc<c<<<<<<111111113313333311111<<<<<cxl:=aa*;klxccccccccccccccccccccccccccc<cc<c<<<<<<111111113333333311111<<<<<cxl:=aa*;klxcccccccccccccccccc1 clllkkkkkkkkkkkkkkkkkkkkkkkkk:kkk:kk:k:k:kkkkkl< M<ccccccccccccccccc<cc<c<<<<<<111111113313333311111<<<<<cxl:=aa*;klxcccccccccccccccccccccccccc<cc<c<<<<<<111111113333333331111<<<<<cxl:=aa*;klxcccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<<<1<111111111111111<<<<<ccxk;*a*=:klcccccccccccccccccccccccccccccccccc<c<<<<<<1<111111111111111<<<<<ccxk;*a*=:klcccccccccccccccccccc1 cxllllllllkllkllklklklkkkkkkklkkkkkklkkkkkkklll< M<cccccccccccccccccccccc<c<<<<<<1<111111111111111<<<<<ccxk;*a*=:klccccccccccccccccccccccccccccccccc<c<<<<<<1<1111111111111<1<<<<<ccxk;*a*=:klcccccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccccccc<ccc<c<<<<<<1<11<11<1<<<<<<<<<cxxk:==*=;klxccccccccccccccccccccccccccccccccc<ccc<c<<<<<<1<1<1<1<<<<<<<<<<<cxxk:==*=;klxccccccccccccccccccccc1 cxxxxlllllxllxllxllllllxlxllllllllllllllllllllx< M<cccccccccccccccccccc<ccc<c<<<<<<1<1<1<1<<<<<<<<<<<cxxk:==*=;klxcccccccccccccccccccccccccccccccc<ccc<c<<<<<<1<1<1<1<1<<<<<<<<<cxxk:==*=;klxccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccccccccc<cccc<c<<<<<<<<<<<<<<<<<cccxll:;==;:kllxcccccccccccccccccccccccccccccccccccc<cccc<c<<<<<<<<<<<<<<<<<cccxll:;==;:kllxcccccccccccccccccccccc1 <ccxxxcxxxxxxxxxxxxcxxxxxxxxxxxxxxxxxxxxxxxxxxx1 M<cccccccccccccccccccccc<cccc<c<<<<<<<<<<<<<<<<<cccxll:;==;:kllxccccccccccccccccccccccccccccccccccc<cccc<c<<<<<<<<<<<<<<<<<<ccxll:;==;:kllxcccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxccccccccccccccccccccccccccccccccccccccccccccccccccccccc<ccccccc<c<<<<<<c<cccxxlk:;;;::kklxccccccccccccccccccccccccccccccccccccccccc<cccccccc<<<<<<<c<cccxxlk:;;;::kklxcccccccccccccccccccccccc1 <cccccccccccccccccccccccccccccccccccxcxcxcxcccc1 M<ccccccccccccccccccccccccc<cccccccc<<<<<<<c<cccxxlk:;;;::kklxcccccccccccccccccccccccccccccccccccccccc<cccccccc<<<<<<<c<cccxxlk:;;;::kklxcccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"1<cxkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxcxxlllk:::::kklxxccccccccccccccccccccccccccccccccccccccccccccccccc<ccccccccxcxxlllk:::::kklxxcccccccccccccccccccccccccc1 <c<c<c<c<c<c<c<c<c<cc<cc<cccccccccccccccccccccc1 M<ccccccccccccccccccccccccccccccc<ccccccccxcxxlllk:::::kklxxcccccccccccccccccccccccccccccccccccccccccccccccc<cccccccxxcxxlllk:::::kklxxcccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"31<cxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxllllkkklkllxxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxllllkkklkllxxxcccccccccccccccccccccccccccc1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<c<c< M<ccccccccccccccccccccccccccccccccccccxxxxxxllllkkklkllxxxcccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxlllkkkklkllxxxcccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"31<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxlllxlxxxxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxlllxlxxxxxcccccccccccccccccccccccccccccc1 1<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<c1 M<ccccccccccccccccccccccccccccccccccccccxxxxxxlllxlxxxxxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxlllxlxxxxxcccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"331<<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxxxxxxcccccccccccccccccccccccccccccccccc1 1<<1<1111111111111111<11<111<1<1<1<1<1<1<1<<1<<1 M<cccccccccccccccccccccccccccccccccccccccccxxxxxxxxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxxxxcxxxxcccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"z3311<<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1 1<<1<1<1<1111111111111111111111111111111<11<<<<1 M<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"z33311111111111111111111<<<<<<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccBB3<<11111111111111111111111111111111111111<11<<B M<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"zzM731111111113333333333333333333331111111<<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc3 M73<111111111111111111111111111111111111111<3B BMcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"zzzM773333333333333333333333333333333333333333111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc3MMM7311111111111111111111111111111111111113M BBM1cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"zzzz3MMM7333333333333333333333333333333333333333331111111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc3B BM7311111111111111111111111111111113MB BBM31ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<313MB",
+"zzzzzz3BBBBBBBBBBBBBBBBBMMMMMMMM7777773333333333333331313111111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<7B M731111111111111111111111137MB BBM31ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1333BB",
+"zzzzzzzz33BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMMM77733333331333131311311111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<7MB BM7333111111111337BB BBM31<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1333BB",
+"zzzzzzzzzzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMM7733333333333333311111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<33MMB BBB7771<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<3337BB",
+"zzzzzzzzzzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM77333333333333311111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1133MMMBBBBBBBBB77331<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<3333MB3",
+"zzzzzzzzzzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM7733333333333111111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<133337MBBz",
+"zzzzzzzzzzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM77333333333311111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11333337MBB3z",
+"zzzzzzzzzzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM7733333333311111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11333333337MBB3zz",
+"zzzzzzzzzzzzzzzzB7<lkxccccccc1111111377777MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM733333333311111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<133333333337MBBB3zzz",
+"zzzzzzzzzzzzzzzz3<xkkxccccccccccccccccccccccccc1111777BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM733333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333333337MBBBB3zzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccc111777BBBBBBBBBBBBBBBBBBBBBBBBBBBBM773333333111111<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133333333377MMBBBB33zzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccc11377BBBBBBBBBBBBBBBBBBBBBBBBBM77333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1333333333377MBBBBB33zzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccc117MBBBBBBBBBBBBBBBBBBBBBBBM73333331111111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133333333377MBBBBBB33zzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccc<137BBBBBBBBBBBBBBBBBBBBBBM7333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133333333337MMBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc177BBBBBBBBBBBBBBBBBBBBMM7333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1333333333377MBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<17MBBBBBBBBBBBBBBBBBBBM73333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333333337MBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBM7333333331111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133333333333MMBBBBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBMM7333333331111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11333333333337MBBBBBBBBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBM73333333311111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<113333333333377MBBBBBBBBBBBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBM73333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<113333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc17MBBBBBBBBBBBBBBBBBMM73333333111111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<113333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc17BBBBBBBBBBBBBBBBBBM773333333111111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<113333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB77333MBzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<37BBBBBBBBBBBBBBBBBBM733333333111111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71cc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc17MBBBBBBBBBBBBBBBBBBM7333333333111111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71<ccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<17BBBBBBBBBBBBBBBBBBBM7733333333111111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11333333333333377MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM31ccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13MBBBBBBBBBBBBBBBBBBBM77333333333111111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11333333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM71ccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc17MBBBBBBBBBBBBBBBBBBBMM73333333333111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<113333333333333377MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71<cccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<xkkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<17BBBBBBBBBBBBBBBBBBBBBM7733333333331111111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333333333333337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71<cccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBMM77333333333311111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<11333333333333333337MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71<cccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBBMM773333333333331111111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1113333333333333333377MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB731cccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBBBMM77333333333333333111111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<111333333333333333333377MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB71<cccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBBBBBMM7733333333333333331111111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<11133333333333333333333377MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM71<cccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBBBBBBBMM7733333333333333333311111111<<<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<111133333333333333333333333377MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB731ccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<17MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM7333333333333333333333333111111111<<<<<<ccccccccccccccccccccccccccccccccccccccccccccccccc<<<<<11111333333333333333333333333333377MMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM71<ccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMM7773333333333333333333333333333333311111111111111111<<<<<<<<<<<<111111111111333333333333333333333333333333333333377MMMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB731cccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<177BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMM77733333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333777MMMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB731ccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<177BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMMM77733333333333333333333333333333333333333333333333333333333333333333333377777MMMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM731cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMMMMM7777773333333333333333333333333333333333377777777MMMMMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB7711ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<137MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBMMMMMMMMMMMBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB7711ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<137BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM7711ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1177MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM7711<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc11177MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB77311ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckkxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc113777BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM777111ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1137Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckklccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1113777BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB77777111ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1117Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckklcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11111377777MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB777777771111<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1117Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<ckklcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11111111111111111cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc11117Bzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzz1<<lllccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11137Mzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzz1<cxxccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1113M3zzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzz11<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11137Mzzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzz1<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<111117M3zzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzz311<<<11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111337MMzzzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzzz333111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111333333333333333333333333333337MMzzzzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzzzz37331111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333777777777777777777777777777777777777777777777777777MMMMzzzzzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzzzzz337333333333333333333333333333333333333333333333333333333333333333333777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM3zzzzzzzzzzzzzzzzzzzzz",
+"zzzzzzzzzzzzzzzzzzzzzzz33BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3zzzzzzzzzzzzzzzzzzzzzzz"
+};
diff --git a/SrcUnix/DefaultSmall.xpm b/SrcUnix/DefaultSmall.xpm
new file mode 100644
index 0000000..1ee49bd
--- /dev/null
+++ b/SrcUnix/DefaultSmall.xpm
@@ -0,0 +1,401 @@
+/* XPM */
+static char *DefaultSmall[] = {
+/* width height ncolors chars_per_pixel */
+"219 333 61 1",
+/* colors */
+" c #000000",
+". c #005A31",
+"X c #ADADAD",
+"o c #082918",
+"O c #A5A5A5",
+"+ c #525A39",
+"@ c #394231",
+"# c #002110",
+"$ c #738C63",
+"% c #7B8C5A",
+"& c #738452",
+"* c #7B7B7B",
+"= c #737373",
+"- c #525A42",
+"; c #6B6B6B",
+": c #636363",
+"> c #004A29",
+", c #006B39",
+"< c #393939",
+"1 c #313131",
+"2 c #DEDEDE",
+"3 c #292929",
+"4 c #D6D6D6",
+"5 c #212921",
+"6 c #007B42",
+"7 c #212121",
+"8 c #CECECE",
+"9 c #182118",
+"0 c #5A6B52",
+"q c #C6C6C6",
+"w c #52634A",
+"e c #63734A",
+"r c #636B4A",
+"t c #9C9C9C",
+"y c #949494",
+"u c #293121",
+"i c #087B42",
+"p c #8C8C8C",
+"a c #848484",
+"s c #737B52",
+"d c #425239",
+"f c #6B7B4A",
+"g c #424A39",
+"h c #21945A",
+"j c #6B845A",
+"k c #5A5A5A",
+"l c #525252",
+"z c #FFFFFF",
+"x c #4A4A4A",
+"c c #424242",
+"v c #EFEFEF",
+"b c #E7E7E7",
+"n c #4A4A39",
+"m c #5A6342",
+"M c #181818",
+"N c #101810",
+"B c #101010",
+"V c #BDBDBD",
+"C c #081008",
+"Z c #4A5242",
+"A c #000800",
+/* pixels */
+"zz7<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<3333bz",
+"z7aa::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::x<33b",
+"7aX*lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll<173",
+"7Xpcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<13B",
+"M=kccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccck*kcck*kccccccccyatpcc13B",
+"M:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc=4z2l=4z2lccccccca*Vqcc13M",
+"M:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzcckk*ycc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxtvOcxtvOcccccccccccccc13M",
+"M:lccccccpOOOOO*ccccccccccccpO=cccccccccccccccccccccccpV4VpcccccckO44X=cc=4=b:qcccccOOOOOOOOccccccccccccccccccccccccccpO=ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;t;ccl;kk*kccccccccccc13M",
+"M:lccccc18zzzzzz2cccccccccc<8zOcccccccccccccccccccccx2zzzzz2xcccpzzzzzzpccOc4XOcccc1zzzzzzzzccccccccccccccccccccccccc<8zOccccccccccc44:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccc=4z2lccc=4z2lcccccccccc13M",
+"M:lccccc78z8yyXzzpccccccccc18zOccccccccccccccccccccc8zz*k*zz8ccczzVkkVzzkcOcXqOcccc3zzXyyyyyccccccccccccccccccccccccc<8zOcccccccccc1zz=cccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzcccccccc13M",
+"M:lccccc78zt137Ozqcc=V4qpcc18zOckOpkV4*cp4Xkccccccc*zzl1<1xzz*c;zz1<134zycccccccccc3zz:11111cc=O==qq:xO4yxcc=OpcckOOc<8zOccxy44XkcctzzV=cckX4qpccckOpkVpcccccccccccccccccccccccccccccccccccccccccxtvOccccxtvOccccccccccc13M",
+"M:lccccc78zOcc3yz4c*zzzzzXc18zOc:z2bzzzXzzzzxccccccyzVcccc1VztclzzOkc<77<cccccccccc3zz=cccccc<tzqzzzzqzzz4cctz8cc;zzc<8zOcc2zzzzzk1zzzztc*zzzzz4cc;z82ztcccccccccccccccccccccccccccccccccccccccccc;t;cck*klccccccccccccc13M",
+"M:lccccc78zV==;zzy<4za7azzc18zOckzzyk4zz*;zzpcccccc8ztcccccyz8c38zzzbV*cccccccccccc3zzzzzzz4c<yzz;;zzb;yzzkcyz8cc:zzc<8zOc=zb11bzO37zzk<xzzVk*zzOc:zzby;ccccccccccccccccccccccccccccccccccccccccc=4z2l=4z2lccccccccccccc13M",
+"M:lccccc78zzzzzz2x1k:x=Ozzc18zOckzzc<yz8c<8ztccccc<8ztcccccyz8c<1ybzzzz2xcccccccccc3zzzzzzz8c<yz8c18ztc1zz=cyz8cc:zzc<8zOcckkk*bztc1zz=c=zb<c1*z2c:zzc1<ccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzcccccccc13M",
+"M:lccccc78zb888acc<:2zzzzzc18zOckzzccyz8cc8ztccccc<XzXcccccOzXcc<37c*XzzXcccccccccc3zzk7777<c<yz4c<8zOc<zz=cyz8cc:zzc<8zOc<Xzzzzztc1zz=cyz8ccc:zzc:zzccccccccccccccccccccccccccccccccccccccccccccxtvOcxtvOcccccccccccccc13M",
+"M:lccccc78zy773<ccczzV;;zzc18zOckzzccyz8cc8ztccccc<azbcccccbzpc=Opc<13Oz8cccccccccc3zz=cccccc<yz4c<8zOc<zz=cyz8cc:zzc<8zOcyzzax8ztc1zz=caz8ccc:zzc:zzccccccccccccccccccccccccccccccccccccccccccccc:p:ccl;kcccccccccccccc13M",
+"M:lccccc78zOcccccc:zz<<;zzc18zOckzzccyz8cc8ztccccccczzVcccXzzxc=zz:cccVzOcccccccccc3zz=cccccc<yz4c<8zOc<zz=cyzbcctzzc<8zOc8zy<c4ztc1zz=cxzz:ccVzVc:zzcccccccccccccccccccccccccccccccccccccccccccc=4z2lcccccccccccccccccc13M",
+"M:lccccc78zOccccccczzy*zzzc18zOckzzccyz8cc8ztcccccc1*zzb4bzz*<c34zz44bzzkcccccccccc3zzzzzzzzO<yz4c<8zOc<zz=cxzzb2zzzc<8zO<Xz2=Xzztc1zz2p3Vzz4bzzkc:zzcccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzcccccccc13M",
+"M:lccccc78zOcccccc3Xzzzazz:18zOckzzccyz8cc8ztccccccc3;bzzzb;1cc11Xzzzz4kccccccccccc3zzzzzzzzO<yz4c<8zOc<zz=c3Ozzzkzzc<8zO<xzzz8Xzqc1*zzt<1Ozzzbkcc:zzccccccccccccccccccccccccccccccccccccccccccccxtvOccccccccccccccccccc13M",
+"M:lccccc771ccccccc13ck<373c173cc77<cc77<cc77<cccccccc17ckc3<cccc<37kk13<ccccccccccc377777777c<77cc<77cc<77cc<3ck3173c<77cc17kl1371c<377<c<31kx3<cc371ccccccccccccccccccccccccccccccccccccccccccccc:p:ccccccccccccccccccc13M",
+"M:lccccccccccccccccc<<ccccccccccccccccccccccccccccccccc<<<cccccccc<<<ccccccccccccccccccccccccccccccccccccccccc<<ccccccccccc<<cccccccccccccc<<<ccccccccccccccccccccccccccccccccccccccccccccccccccc=4z2lcccccccccccccccccc13M",
+"M:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccczzzzzzzzzzzzzzzzzcccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccxtvOccccccccccccccccccc13M",
+"M:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccl;kccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccc<1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111<cccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccc<13333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333311<cccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc<337MBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBM311cccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc13MNu@dmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmduM3<<ccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc37Bg+s%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%m3<cccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379+&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%ucxccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379e%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zxkccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Zckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$jZ@@@Zj$$$$$$$$$$$$$$jwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$w9 50$$$$$$$$$$$wN@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 C@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Cj$$$$$$$$$$juN A5d$$$$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$u @$$$$$$$$$$@Z$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jA Z$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$ju Nuu Cw$$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$u u0wg5 u$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@9$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$jN A0$$$d d$$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$@ A0$$j@A g$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$jN Agu u$ju5g d$$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$j Nw$$$$j9 Aj$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$u Nj$$u u5d$$9 Aj$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$u A@j$$$$$$$$5 u$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$j u$Zudw9 Z$$j5 u$$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$A 9j$$$$$$$$$$5 C$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$u 0$0A9jjAAj@A j$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$w u$$$$$$$$$$$$C j$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$N Aj5ZNj$@ Cu Z$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$w u$$$$$$$$$$$$j w$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$ Nj$0jdA ujj @$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$w N$$$$$$$ju j$$g w$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$ u$dN @$uu9 @$$$$%nckxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$w j$$$$$$dA @$$C w$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$ A u0AN5g0u @$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$j $$$$$$Z @$d j$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$A A@j$uu ju95 g$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$CZ$$$$jA @jA N$dZj$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$5 d@uwuZ uu$C 0$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$g59u$@9$$$$@ @9 dju@u0$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$d N$dA@j u$u C$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$5g$$jCg$$$A A C$$9@uj$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$C jjNNdCN9 d$j$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$jw$@g$w d$w A0$Zu0w$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$Zug$Z g9wjdC N$w5gj$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$j5@w0$d @@ AZ$0d@Nj$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$j@$@j$d 5dgC Aj$90u@$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$j0@gu$0C N0$jg9Zw$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$5wZZ0$d Njj@@9w$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$d5@dj$d5 5d$$0duwu$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$jg5uu$$05 C@$$@$uZZ$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$juu5Zd$$$$jwj$$$wj@jwg$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$duNju$$$jd@5@@w$$Z@5jj@$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$5$$ujwj$$$Z5@u0ud0$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$wg@0$Zgj$$$$$$00@g0uuj$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$wu$jduZ@$Njjdj@w$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$jNjj@j@d$Zd$$uu$uj$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$wguj@$j$9u$jg$j$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$0uZZ$$@$@@$$u9wj0$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$j$guZ0guj$j$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$u@0uj@uwju$w$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$j$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$Zg$dZj$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$$$j@9999ud$$$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$$$jd@@@@0$$$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$$ju Ag$$$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$$09 Cd$$$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$$0A uj$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$$@ 9j$$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$$0A 5@wj$$$u5$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$$u Au@uA Nj$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$jC A9j$$$$$$$$u@$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$$Z N0g95w 9$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$@ A9N u$$$$wg@uNAj$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$jA A0N9Z0$ Z$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$$A C5 AwgN g$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$g uu5$$$$ N$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<379f$$$$w 95 u5 Au5 N$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@w$$$$$N @uj$$$g 9 j$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$@ gN95 9d$uZN $$$$$$$$@w$$$$$Zw$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j9Nw$@w$$$$$ u$$$$wA5N d$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$@ dC Ndu@$$jg $$$$$$$$@w$00$$uw$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Z$$@jj$@w$$$$j gj0u NZ @$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$@ AZNd$0$Z0@ $$$$$$$$@wjwC0$CZj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$N@$u5Aj@w$$$$w 9u uwA @$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$@ @$w9uj$jZA $$$$$$$$@w0uNwduwu$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$gCjj$@j@w$$$$$ NjZjwwjgA g$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$w w5w$j$wZ9 N$$$$$$$$@wguNd5j050@0$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$09u$$du5wdd$@w$$$$$C Njw N9 w$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$A 5$wC@j@C g$$$$$$$$@w$$$$dZgjC0dj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$@Z5g0djuj$$$@w$$$$$u Nj0A A$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$@ duj@A Aj$$$$$$$$@w$$$$$$$09$jjj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$0$uuu$j$$$$$@w$$$$$w A0jN u$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$jC uZC @$$$$$$$$$@w$$$$$$$$djwCudjj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jgw$j$@$$$$$$$@w$$$$$$5 u0C Aj$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$0A u$$$$$$$$$$@w$$$$$$$$$$9Z$u@C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ud5$Zuj$$$$$$$@w$$$$$$jC Z$$$$$$%nclxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$0A u$$$$$$$$$$$@w$$$$$$$$$$@wjN5j$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Zj0ZNj$$$$$$$$@w$$$$$$$0C d$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$$ju Cd$$$$$$$$$$$$@w$$$$$$$$$$$uCZ$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$9@$$$$$$$$$@w$$$$$$$$ju C0$$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$$j$jg5999uZ$$$$$$$$$$$$$$@w$$$$$$$$$$$0@ANj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$dj$$$$$$$$$@w$$$$$$$$$$0uC A5d$$$$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$jC$j$$$$$$$$g$$$$$$$$$$$$@w$$$$$$$$$$$$5d0@$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$j$$$$$$$$$$$$$$$$$$$$$$$$j9ugw0$$$$$$$$$$@w$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$dudCZd0d$Zu$u$$$$$$$$$$$$@w$$$$$$$$$$$$@jAw$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$d9$$$$$$$$$$$$$$$$$$$$$$$$$ugu9u$$$$$$$$$$@w$$$$$$$$$$ugjjjjjuuj$$$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$uuudu00ug@d0gj$$$$$$$$$$$@Z$$$$$$$$$$$$jj$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$jC d$$$$$$$$$$$$$$$$$$$$$$$$j$$$w$$$$$$$$$$@w$$$$$$$$$Zu0@Z5wdd$u$$$$$$$$$%nxlxcccccccccccccccc13M",
+"M:lccccccccccccccccccccc<179f$$$$$$$$duju@juwNju@j$$$$$$$$$$$wNdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwu CwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwgCj$$$$$$$$$@j0@w@@wujd$$$$$$$$$%nxlccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<175f$$$$$$$$$$$@@jd$d$$$$$$$$$$$$$$$$j@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@gj$$$$$$$$$$j$$dwwuwddj$$$$$$$$$%<::ccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc13Me$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$rcp=ccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc<133-rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr-<aO:ccccccccccccccccc13M",
+"M:lccccccccccccccccccccccc<1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111<xpXpcccccccccccccccccc13M",
+"M:lcccccccccccccccccccccccc<ccxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkk:aOpccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccxlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk::lcccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccc<cc<cc<cc<ccccccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccccc<cc<c<c<c<c<cc<cccccccccccccccccccccc<cc<c<c<c<c<cc<cccccccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<c<c<c<c<cc<cccccccccccccccccccccc<cc<c<c<c<c<cc<cccccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccccccc<cc<c<<<<<<c<c<ccc<cccccccccccccccccc<cc<c<<<<<<c<c<ccc<cccccccccccccccccccccccccccccccccccccccccccccccccccc<cc<c<<<<<<c<c<ccc<cccccccccccccccccc<cc<c<<<<<<c<c<ccc<cccccccccccccccccccccc13M",
+"M:lcccccccccccccccccccccccccc<c<<<<<<<<<1<<<<<<<c<cccccccccccccccc<c<<<<<<<<<1<<<<<<<c<cccccccccccccccccccccccccccccccccccccccccccccccccc<c<<<<<<<<<1<<<<<<<c<cccccccccccccccc<c<<<<<<<<<1<<<<<<<c<ccccccccccccccccccccc13M",
+"M:lccccccccccccccccccccccc<c<c<<<<1111311111<<<c<cccccccccccccc<c<c<<<<1111311111<<<c<cccccccccccccccccccccccccccccccccccccccccccccccc<c<c<<<<1111311111<<<c<cccccccccccccc<c<c<<<<1111311111<<<c<cccccccccccccccccccccc13M",
+"M:lcccccccccccccccccccccccc<c<<<11333737333111<<<c<c<ccccccccccc<c<<<11333737333111<<<c<c<ccccccccccccccccccccccccccccccccccccccccccccc<c<<<11333737333111<<<c<c<ccccccccccc<c<<<11333737333111<<<c<c<cccccccccccccccccc13M",
+"M:lcccccccccccccccccccccc<<c<111377MMMMMMM773311<<<ccccccccccc<<c<111377MMMMMMM773311<<<ccccccccccccccccccccccccccccccccccccccccccccc<<c<111377MMMMMMM773311<<<ccccccccccc<<c<111377MMMMMMM773311<<<cccccccccccccccccccc13M",
+"M:lccccccccccccccccccccc<c<<11377MBBBBBBBBBM73311<<c<c<cccccc<c<<11377MBBBBBBBBBM73311<<c<c<cccccccccccc117MBBBBBBBM711ccccccccccccc<c<<11377MBBBBBBBBBM73311<<c<c<cccccc<c<<11377MBBBBBBBBBM73311<<c<c<cccccccccccccccc13M",
+"M111111111111111cccccc<cc<<<137MBBBBBBBCBBBBBM7311<<<ccccccccc<<<137MBBBBBBBCBBBBBM7311<<<ccccccccccc17M711cxxxxxxxc117M71cccccccc<cc<<<137MBBBBBBBCBBBBBM7311<<<ccccccccc<<<137MBBBBBBBCBBBBBM7311<<<cccccccccccccccccc13M",
+"BBBBooooooooooo1<cccccc<<<<137MBBBBM33<<<37MBBB7311<c<cccccc<<<<137MBBBBM33<<<37MBBB7311<c<cccccccc171ckkkkkkkkkkkkkkkkkc171ccccccc<<<<137MBBBBM33<<<37MBBB7311<c<cccccc<<<<137MBBBBM33<<<37MBBB7311<c<ccccccccccccccccc13M",
+"BBM,iiii666iii>M<ccccccc<<137BBBBM<xllxc<<113BBB7311<ccccc<cc<<137BBBBM<xllxc<<113BBB7311<cc<ccccc71ckkkkkkkkkkkkkkkkkkkkkc17ccccccc<<137BBBBM<xllxc<<113BBB7311<ccccc<cc<<137BBBBM<xllxc<<113BBB7311<cc<ccccccccccccccc13M",
+"MMMhiiiiiiiiii>M<ccccc<<<137MBBC3l:=;:kxx<<111MBM711<<c<ccc<c<137MBBC3l:=;:kxx<<111MBM711<<cccccccMlllllllllllllllllllllllll 3cccc<<<137MBBC3l:=;:kxc;<111MBM711<<c<ccc<c<137MBBC3l:=;:kxx<<111MBM711<<ccccccccccccccccc13M",
+"77Mhiiiiiiiiii>M<cc<c<c<<13MBBB1:*yyp*tqvvl<111MBM31<<ccc<cc<113MBBB1:*yt8*:kxc<<111MBM31<<cccccccMxxxxxxxxxxxxccccccccccccc 3c<c<c<<13MBBB1:*yyp*X4zzy<111MBM31<<ccc<cc<113MBBB1:*yypO8;xc<<111MBM31<<ccccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<cccc<c<137BBB7kpOXOqvzzvO:<1133MB731<cccc<<<137BBB7kpOVVzO;kxc<<1133MB731<cccccccM<<<<<<<<<<<<<<<<<<<<<<<<< 3ccc<c<137BBB7kpOXXqzzzzzz*1133MB731<cccc<<<137BBB7kpOXXq4;pxc<<1133MB731<ccccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<cccc<<<13MBBBl*OXqvzzvtx=XO11137BM31<ccccc<<13MBBBl*Oqzq8v:kxc<<11137BM31<cccccccM<<<<<<<111111111111111111 3ccc<<<13MBBBl*OXqvvazzqa4zx1137BM31<ccccc<<13MBBBl*OVV4XOv;:c<xzV137BM31<ccccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccc<c<137MBB3kpO4zzzXkpkXzz:1133MB31<ccc<c<117MBB3kpO8zvtz;lxc<<11133MB31<cccccccM1111111111111111111111111 3cc<c<137MBB3kpXbzz4t4=kXbz41133MB31<ccccc<117MBB3kpX48X4;z4z;<4xV=33MB31<ccccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<cccc<<137BBCx:pVzz4*avz4<V:x11337C71<cxcc<<137BBCx:pttzzV:klcc<<111337BM1<cxcccccM3333333333333333333333333 3ccc<<137BBBc;avzv4p8vqzzzzz=1337BM1<cxcc<<137BBCx:p4qqpvVzv4v;O14k337BM1<cxccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<c<c<c<137BB7x:*pXO*pazz4l<Ozk3337BM1<cxcc<<137BB7x:*ppvz8:kxcc<1113337BM11cxcccccM7777777777777777777777777 3cc<c<137BBMx:*yzvp:8zzzz4=z43337BM11cxcc<<137BB7x:*yv4XzvOx;zz::t3137BM11cxccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccc<<<13MBB7ck===*VOkOalXxOzO1337BB1<cxcc<<13MBB7c:===Vzzklxc1<1111337BB1<xxxccccMB B3ccc<<13MBB3ck=*yzzz4:Xv*xOzzk337BB1<xxccc<13MBB7ck==yzz8;*q44V14c3337BB1<xxxcccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccccc<137BB3cl:::k;Xqtl*zOxp3c337MB1<xlccc<137BB3cl:::;zzpxc<<11113337MB1<xlccccccc33333333333333333333333331ccc<<13MBB3cl:::XzXlal4OzzzzO337MB1<xlccc<137BB3cl:::O4lXv;<4k=O11337MB1<xlccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<c<c<<<13MBB3<xllkpzzv4z*=41cv=337MB1<xlcc<<13MBB3<xllkl4zvl1**11113337MC1<xlxcccccccccccccccccccccccccccccccccc<<<137BB3<xllllvXa414zzzzz8337MC1<xlxc<<13MBB3<xlklx4zX<kvb14x33337MC1<xlxcccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccc<c<137BB3<ccx=zzz*yzvc1cpz=377BB1<lkxc<<137BB3<ccxxxlvzz*pz=1133377BB1<lkxcccccccccccccccccccccccccccccccccc<c<137BC3<ccxxxyz<lXzzz4cpz377BB1<lkxcc<137BB3<ccxxx;vlV4VO=zc33377BB1<lkxcccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccc<<<137BBM<<ccVzVzxVzzp=p=8c777BM<c:kccc<137BBM<<cccc<*zzz=Vb3133377BM<ck:xcccccccccccccccccccccccccccccccccc<c<137BBM<<ccccc4Vbpkz=cVz8377BM<ck:xc<<<37BBM<<cccc<Xzp1bkvzO33377BM<ck:xcccccccccccccc13M",
+"33Mhiiiiiiiiii>M<c<ccc<<13MBB1<1<zzl<1bzzV=Vc3337MB7<x;kxc<<<13MBB1<1<<<<<*zzvc4133377MB7<x;kcccccccccccccccccccccccccccccccccccc<<<13MBB11<<<<<yzxkxV4bz8c77MB7<x;kccc<113MBB1<1<<<<x4xVbpzzV3377MB7<x;kccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<cccc<<<13MBB31<14zzvVzzzVkc3377MMB3<k=kccc<<13MBB31<1<1<11:bzV3c33377MB3<k=kxccccccccccccccccccccccccccccccccc<cc<<13MBB3<1<1<1xzxOcpzzO3777MB3<k=kccc<<13MBB311<1<114zzzzzXc3377MB3<k=kxcccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccc<c<<137MBB111pzzzzzzzk333377MBM<c==lcc<c<137MBB111111111cpbzv3377MBM<c==lcccccccccccccccccccccccccccccccccccc<c<137MBB1111111z=1pb8k7377MBM<c==lccc<<133MCM1111111=zzzz=33777MBM<c==lccccccccccccccc13M",
+"33Mhiiiiiiiiii>M<ccccc<<<137BB7111bzzzzzV3333777BB3cka;xccc<<<137BB71111113133c88;777BB3cka;xcccccccccccccccccccccccccccccccccccc<<<<137BB7111111zb4bp333777BB3cka;xcc<c<<137BB71111111zzVc333777BB3cka;xccccccccccccccc13M",
+"33M.,,,,,,,,,,>M<ccc<cc<<133MBB333cOzzbp333377MBB7<x*akcc<cc<<133MBB33131313333=t=7MBB7<x*akccccccccccccccccccccccccccccccccccccccc<<133MBB331313z8p333377MBB7<x*akccccc<<1337BB3313133Ok333777MBB7<x*akcccccccccccccccc13M",
+"33M############1<ccccc<c<<133MBB73333337337777BBM<c;y;xcccc<c<<133MBB7333333333777MBBM<c;y;xcccccc1MMMMMMMMMMMMMMMMMMMMMMMMM1<c<cc<c<<133MBB73333c37337777BBM<c;y;xcccc<c<<117MBB7333333333777MMBM<c;y;xcccccccccccccccc13M",
+"<<<<<<<<<<<<<<<<cccccccc<<<133MBBM3333337777MBBM<c:t*kcccccc<<<<133MBBM3333377777MBBM<c:t*kcccccccMxxxxxxxxxxxxxcccccccccccc 1ccccc<<<<133MBBM3333337777MBBM<c:t*kccccccc<<1133MBBM3333377777MBBM<c:t*kccccccccccccccccc13M",
+"3:lccccccccccccccccccc<cc<<<1137MBBM77777MMBBB7<c:yp:xcccccccc<<<1137MBBM77777MMBBB7<c:yp:xcccccccMkkkkkkkkkkkkkkkkkkkkkkkkl 3ccccccc<<<1137MBBM77777MMBBB7<c:yp:xcccccc<c<<<1137MBBM77777MMBBB7<c:yp:xccccccccccccccccc13M",
+"3:lcccccccccccccc<cccccc<c<<111337MBCBBBBBBB71<c:yp;xcccccccc<c<<111337MBCBBBBBBB71<c:yp;xccccccccMkkkkkkkkkkkkkkkkkkkkkkkkk 3cccc<c<c<<111337MBCBBBBBBB71<c:yp;xcccccccccc<<111337MBCBBBBBBB71<c:yp;xcccccccccccccccccc13M",
+"3:lccccccccccccccccccccccc<c<<1111337MMMM731<cx=yp;xccccccccccc<c<<1111337MMMM731<cx=yp;xcccccccccMlllllllllllllllllllllllll 3cccccccc<c<<1111337MMMM731<cx=yp;xccccccccc<c<c<<1111337MMMM731<cx=yp;xccccccccccccccccccc13M",
+"3:lcccccccccccccccccccc<cc<c<<<<11111111<<<cckap*kxccccccccc<cc<c<<<<11111111<<<cckap*kxccccccccccMcccccccccccccxxxxxxxxxxxx 3ccccccc<c<c<<<11111111<<<cckap*kxcccccccccccc<c<<<<11111111<<<cckap*kxcccccccccccccccccccc13M",
+"3kxcccccccccccccccccccccccccccc<c<<<<<<<ccxk=*=:lxcccccccccccccccccc<c<<<<<<<ccxk=**:lxcccccccccccM<<<<<<<<<<<<<<<<<<<<<<<<< 3cccccccccc<cc<c<<<<<<<ccxk=*=:lxcccccccccccccccccc<c<<<<<<<ccxk=**:lxccccccccccccccccccccc13M",
+"3lccccccccccccccccccccccccc<c<cccccccxxllk;;;:lxcccccccccccccccc<c<cccccccxxllk;;;:lxcccccccccccccM111111111111111111<<<<<<1 3ccccccccccc<cccccccxxllk;;;:lxcccccccccccccccc<c<cccccccxxllk;;;:lxccccccccccccccccccccccc13M",
+"3<<ccccccccccccccccccccc<cccccccccccxxxlllllxcccccccccccccccc<cccccccccccxxxlllllxcccccccccccccccc7M11111111111111111111117C 3ccccccccccccccccccxxxlllllxcccccccccccccccc<cccccccccccxxxlllllxcccccccccccccccccccccccccc13M",
+"331111111111111<<<<<<cccccccccc<cccccccxccxccccccccccccccccccccccccc<cccccccxccxccccccccccccccccccc1MM733333333333333337MC M<ccccccccccccc<cccccccxccxccccccccccccccccccccccccc<cccccccxccxcccccccccccccccccccccccccccc13M",
+"z37333333333333333333333111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc17MMM777777777MMCC B71cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13M",
+"zz37BBBBBBBBMMMMMMM777733333333111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13MBB CBM71ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc13B",
+"zzzzzzzzBBBBBBBBBBBBBBBBBBMM77733331111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<<<<<<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<37B",
+"zzzzzzzzBBBBBBBBBBBBBBBBBBBBBBBBBMM77333111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<137B7",
+"zzzzzzzzM377777777BBBBBBBBBBBBBBBBBBBBMM73331111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<13337BB7z",
+"zzzzzzzz3:lcccccccccccc111377MBBBBBBBBBBBBBM7733311<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133337BB7zzz",
+"zzzzzzzz3:lccccccccccccccccccccc1137MBBBBBBBBBBM7733111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<133337MBBB7zzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccc117MBBBBBBBBBM7333111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133337BBBBM7zzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccc117BBBBBBBBBM733311<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<1133337MBBBBBBBMzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccc<17BBBBBBBBM7733311<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<133337MMBBBBBBBBBBMzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccccccc<17BBBBBBBBM7333111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1333377MBBBBBBBBBBBBBBMzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccccccccccc<37BBBBBBBBM7333111<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11333377MBBBBBBBBBBBBBBM733Mzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccccccccccccccc17MBBBBBBBMM73333111<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<13333377MBBBBBBBBBBBBBBB71<cc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccc<17BBBBBBBBBM73333311<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<11333337MMBBBBBBBBBBBBBBB731cccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBM7733333111<<<cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<1133333377MBBBBBBBBBBBBBBBB731cccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBM77333333111<<<ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<<<11333333377MBBBBBBBBBBBBBBBBB731cccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBMM7733333333111<<<<ccccccccccccccccccccccccccccccccccccccccccc<<<<1113333333377MMBBBBBBBBBBBBBBBBBB731cccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc117BBBBBBBBBBBBBBMM7733333333333111111<<<<<<<<<ccccccc<<<<<<<<<<111113333333333377MMMBBBBBBBBBBBBBBBBBBBM71<cccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc137BBBBBBBBBBBBBBBBMMM77773333333333333333333333333333333333333337777MMMBBBBBBBBBBBBBBBBBBBBBBM711ccccccccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1177BBBBBBBBBBBBBBBBBBBBBMMMMMM7777777777777777777MMMMMMBBBBBBBBBBBBBBBBBBBBBBBBBBBB731<cccccccccccccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc1177BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB7731<cccccccccccccccccccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11777BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB777111ccccccccccccccccccccccccccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3:lcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<11177777BBBBBBBBBBBBBBBBBBBBBBBBBBB777771111cccccccccccccccccccccccccccccccccccccccccccccccccccccc<1Mzzzzzzzz",
+"zzzzzzzz3klcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc111111111cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc11Mzzzzzzzz",
+"zzzzzzzz3lxcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc<13Mzzzzzzzz",
+"zzzzzzzz37<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<111M7zzzzzzzz",
+"zzzzzzzzz7711111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111113333333333333333333333333333333333333333333333333333333333333333333333333337MMzzzzzzzzz",
+"zzzzzzzzzz37777777777777777777777777777777MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM7zzzzzzzzzz"
+};
diff --git a/SrcUnix/EmApplicationFltk.cpp b/SrcUnix/EmApplicationFltk.cpp
new file mode 100644
index 0000000..085f4b5
--- /dev/null
+++ b/SrcUnix/EmApplicationFltk.cpp
@@ -0,0 +1,494 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmApplicationFltk.h"
+
+#include "EmDlgFltk.h" // HandleDialogs
+#include "EmDocument.h" // gDocument
+#include "EmMenus.h" // MenuInitialize
+#include "EmWindowFltk.h"
+
+#include <FL/Fl.H> // Fl::wait
+#include <FL/x.H> // fl_display
+#include <FL/Fl_Widget.h>
+
+#ifdef __QNXNTO__
+#include <sys/neutrino.h>
+#endif
+
+EmApplicationFltk* gHostApplication;
+
+// These variables are defined in Platform_Unix.cpp.
+
+const double kClipboardFreq = 0.1;
+extern ByteList gClipboardDataPalm;
+extern ByteList gClipboardDataHost;
+extern omni_mutex gClipboardMutex;
+extern omni_condition gClipboardCondition;
+extern Bool gClipboardHaveOutgoingData;
+extern Bool gClipboardNeedIncomingData;
+extern Bool gClipboardPendingIncomingData;
+extern Bool gClipboardHaveIncomingData;
+
+// Little private widget used solely for receiving notification
+// that clipboard data has arrived.
+
+class EmClipboardWidget : public Fl_Widget
+{
+public:
+ EmClipboardWidget () : Fl_Widget (0, 0, 0, 0) {}
+ virtual ~EmClipboardWidget () {};
+ int handle (int);
+ void draw (void) {}
+};
+
+
+/***********************************************************************
+ *
+ * FUNCTION: main
+ *
+ * DESCRIPTION: Application entry point. Creates the preferences and
+ * then the application object. Uses the application
+ * object to initizalize, run, and shutdown the system.
+ * A top-level exception handler is also installed in
+ * order to catch any wayward exceptions and report them
+ * to the user with a Fatal Internal Error message.
+ *
+ * PARAMETERS: Standard main parameters
+ *
+ * RETURNED: Zero by default. If a non-fatal error occurred, returns
+ * 1. If a fatal error occurred while running a Gremlin,
+ * returns 2. This is handy for Palm's automated testing.
+ *
+ ***********************************************************************/
+
+int main (int argc, char** argv)
+{
+ EmulatorPreferences prefs;
+ EmApplicationFltk theApp;
+
+ try
+ {
+ if (theApp.Startup (argc, argv))
+ {
+ theApp.Run ();
+ }
+ }
+ catch (...)
+ {
+ // !!! TBD
+// ::MessageBox (NULL, "Palm OS Emulator: Fatal Internal Error",
+// "Fatal Error", MB_OK);
+ }
+
+ theApp.Shutdown ();
+
+ return
+ gErrorHappened ? 2 :
+ gWarningHappened ? 1 : 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::EmApplicationFltk
+ *
+ * DESCRIPTION: Constructor. Sets the globalhost application variable
+ * to point to us.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmApplicationFltk::EmApplicationFltk (void) :
+ EmApplication (),
+ fAppWindow (NULL)
+{
+ EmAssert (gHostApplication == NULL);
+ gHostApplication = this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::~EmApplicationFltk
+ *
+ * DESCRIPTION: Destructor. Closes our window and sets the host
+ * application variable to NULL.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmApplicationFltk::~EmApplicationFltk (void)
+{
+ delete fAppWindow;
+
+ EmAssert (gHostApplication == this);
+ gHostApplication = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::Startup
+ *
+ * DESCRIPTION: Performes one-time startup initialization.
+ *
+ * PARAMETERS: argc, argv from main()
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmApplicationFltk::Startup (int argc, char** argv)
+{
+#ifdef __QNXNTO__
+ // speed NTO up so the timing will be about right (for an x86 anyway)
+ struct _clockperiod cpnew;
+ struct _clockperiod old;
+
+ cpnew.nsec = 5000000;
+ cpnew.fract = 0;
+ ClockPeriod(CLOCK_REALTIME, &cpnew, &old, 0);
+// printf ("%d %d %d\n", old.nsec, old.fract);
+#endif
+
+ // Initialize the base system.
+
+ if (!EmApplication::Startup (argc, argv))
+ return false;
+
+ // Create our window.
+
+ this->PrvCreateWindow (argc, argv);
+
+ // Start up the sub-systems.
+
+ ::MenuInitialize (false);
+
+ // Start the clipboard idling.
+ // !!! Get rid of this special clipboard window. I think that
+ // we can roll this functionality into fAppWindow.
+
+ (void) this->PrvGetClipboardWidget ();
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::Run
+ *
+ * DESCRIPTION: Generally run the application.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmApplicationFltk::Run (void)
+{
+ this->HandleStartupActions ();
+
+ while (1)
+ {
+ Fl::wait (0.1);
+
+ if (this->GetTimeToQuit ())
+ break;
+
+ this->HandleIdle ();
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::Shutdown
+ *
+ * DESCRIPTION: Performs one-time shutdown operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmApplicationFltk::Shutdown (void)
+{
+ // Delete our window now, so that its position will be recorded
+ // in the preferences before EmApplication::Shutdown saves them.
+
+ delete fAppWindow;
+ fAppWindow = NULL;
+
+ // Perform common shutdown.
+
+ EmApplication::Shutdown ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::HandleIdle
+ *
+ * DESCRIPTION: Perform idle-time operations.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmApplicationFltk::HandleIdle (void)
+{
+ // Idle the clipboard. Do this first, in case the CPU
+ // thread is blocked waiting for the data.
+
+ if (!this->PrvIdleClipboard ())
+ return; // CPU thread is still blocked.
+
+ // Handle any modeless dialogs
+
+ ::HandleDialogs ();
+
+ EmApplication::HandleIdle ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::PrvCreateWindow
+ *
+ * DESCRIPTION: Create the window that displays the LCD/skin stuff,
+ * or the message saying to right-click to show a menu.
+ *
+ * PARAMETERS: argc, argv from main()
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmApplicationFltk::PrvCreateWindow (int argc, char** argv)
+{
+ Fl::visual (FL_RGB);
+
+ fAppWindow = new EmWindowFltk;
+ fAppWindow->WindowInit ();
+ fAppWindow->show (argc, argv);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::PrvClipbardPeriodic
+ *
+ * DESCRIPTION: Idle time routine called when it's time to check to
+ * see if there are any clipboard tasks to perform.
+ * Handles those tasks and then queues up another
+ * callback into us.
+ *
+ * PARAMETERS: data - value passed in to Fl::add_timeout when this
+ * function was queued up for execution.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmApplicationFltk::PrvClipboardPeriodic (void* data)
+{
+ EmApplicationFltk* This = (EmApplicationFltk*) data;
+ (void) This->PrvIdleClipboard ();
+ Fl::add_timeout (kClipboardFreq, &PrvClipboardPeriodic, This);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::PrvGetClipboardWidget
+ *
+ * DESCRIPTION: Return the widget being used to receive the message
+ * that clipboard data has arrived. This clipboard is
+ * created on demand.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Pointer to the "clipboard widget".
+ *
+ ***********************************************************************/
+
+Fl_Widget* EmApplicationFltk::PrvGetClipboardWidget (void)
+{
+ if (!fClipboardWidget)
+ {
+ fClipboardWidget = new EmClipboardWidget;
+ Fl::add_timeout (kClipboardFreq, &PrvClipboardPeriodic, this);
+ }
+
+ return fClipboardWidget;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmApplicationFltk::PrvIdleClipboard
+ *
+ * DESCRIPTION: Check to see if there is any incoming or outgoing
+ * clipboard data and handle it if there is.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: TRUE if there is pending incoming data. This helps
+ * prevent us from deadlocking with the CPU thread, since
+ * it's now blocked on us waiting for data.
+ *
+ ***********************************************************************/
+
+Bool EmApplicationFltk::PrvIdleClipboard (void)
+{
+ omni_mutex_lock lock (gClipboardMutex);
+
+ // See if there's anything outgoing.
+
+ if (gClipboardHaveOutgoingData)
+ {
+ // Get the widget that FLTK requires for clipboard management.
+
+ Fl_Widget* w = this->PrvGetClipboardWidget ();
+ EmAssert (w);
+
+ // Tell FLTK the data to make available to other X programs if they need
+ // to know the current selection. We make a local copy of the data in
+ // case ... <something about race conditions>.
+
+ fClipboardData = gClipboardDataHost;
+
+ Fl::selection (*w, (const char*) &fClipboardData[0], (int) fClipboardData.size ());
+
+ // Clear the flag saying that we changed the clipboard.
+
+ gClipboardHaveOutgoingData = false;
+ }
+
+ // See if there's a request for incoming data.
+
+ if (gClipboardNeedIncomingData)
+ {
+ // Clear the flag saying that we need to ask for the
+ // current selection.
+
+ gClipboardNeedIncomingData = false;
+
+ // FLTK only sends a FL_PASTE event if a selection exists. If there
+ // is no selection, we note that ourselves instead of waiting for an
+ // event that will never arrive.
+ //
+ // !!! Do we get a FL_PASTE event if there is a primary selection
+ // but it can't be converted to XA_STRING? We might still wait
+ // forever in that case.
+
+ if (XGetSelectionOwner (fl_display, XA_PRIMARY) != None)
+ {
+ gClipboardPendingIncomingData = true;
+
+ // Get the widget that FLTK requires for clipboard management.
+
+ Fl_Widget* w = PrvGetClipboardWidget ();
+ EmAssert (w);
+
+ // Our clipboard widget may get called in this
+ // context. It will try to acquire the clipboard
+ // mutex, so give it up here.
+
+ omni_mutex_unlock unlock (gClipboardMutex);
+
+ // Tell FLTK to get the clipboard data. Usually, this will
+ // require sending a request to the X server to get the
+ // data from the application holding the current selection.
+ // When the remote application responds, we'll get notified
+ // via an FL_PASTE event sent to our widget's handle() method.
+
+ Fl::paste (*w);
+ }
+ else
+ {
+ gClipboardHaveIncomingData = true;
+ gClipboardCondition.broadcast ();
+ }
+ }
+
+ return !gClipboardPendingIncomingData;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmClipboardWidget::handle
+ *
+ * DESCRIPTION: Handle the event indicating that clipboard data has
+ * arrived from the selection owner.
+ *
+ * PARAMETERS: event - number indicating the event that occurred.
+ *
+ * RETURNED: Non-zero if we handled the event.
+ *
+ ***********************************************************************/
+
+int EmClipboardWidget::handle (int event)
+{
+ // It's a "paste" event, meaning that our application has requested
+ // data to paste, and it just showed up from the X server.
+
+ if (event == FL_PASTE)
+ {
+ // Get exclusive access to our clipboard data.
+
+ omni_mutex_lock lock (gClipboardMutex);
+
+ // Say that the data is here.
+
+ gClipboardPendingIncomingData = false;
+ gClipboardHaveIncomingData = true;
+
+ // Copy the data to the host data clipboard. The Palm-specific
+ // clipboard will remain empty, and the host data will get
+ // convert to it on demand.
+
+ gClipboardDataPalm.clear ();
+ gClipboardDataHost.clear ();
+
+ copy ((char*) Fl::e_text,
+ (char*) Fl::e_text + Fl::e_length,
+ back_inserter (gClipboardDataHost));
+
+ // Tell the CPU thread that the new data is here.
+
+ gClipboardCondition.broadcast ();
+
+ // Return that we handled the event.
+
+ return 1;
+ }
+
+ // Return that we didn't handle the event.
+
+ return 0;
+}
diff --git a/SrcUnix/EmApplicationFltk.h b/SrcUnix/EmApplicationFltk.h
new file mode 100644
index 0000000..c1120a6
--- /dev/null
+++ b/SrcUnix/EmApplicationFltk.h
@@ -0,0 +1,50 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmApplicationFltk_h
+#define EmApplicationFltk_h
+
+#include "EmApplication.h" // EmApplication
+#include "EmStructs.h" // ByteList
+
+class EmWindowFltk;
+class Fl_Widget;
+
+class EmApplicationFltk : public EmApplication
+{
+ public:
+ EmApplicationFltk (void);
+ virtual ~EmApplicationFltk (void);
+
+ public:
+ virtual Bool Startup (int argc, char** argv);
+ void Run (void);
+ virtual void Shutdown (void);
+ void HandleIdle (void);
+
+ private:
+ void PrvCreateWindow (int argc, char** argv);
+
+ Bool PrvIdleClipboard (void);
+ static void PrvClipboardPeriodic (void* data);
+ Fl_Widget* PrvGetClipboardWidget (void);
+
+ private:
+ EmWindowFltk* fAppWindow;
+ Fl_Widget* fClipboardWidget;
+ ByteList fClipboardData;
+};
+
+extern EmApplicationFltk* gHostApplication;
+
+#endif // EmApplicationFltk_h
diff --git a/SrcUnix/EmCommonUnix.h b/SrcUnix/EmCommonUnix.h
new file mode 100644
index 0000000..87e75ac
--- /dev/null
+++ b/SrcUnix/EmCommonUnix.h
@@ -0,0 +1,90 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmUnixCommon_h
+#define EmUnixCommon_h
+
+// Common header file included by all Palm OS Emulator for UNIX files.
+
+// Define this before anything else, especially anything that can pull in
+// an STL header. gcc-2.95.2 has a problem instantiating vector<ptmf>
+// classes, which we use in EmRegs. When it gets around to instantiating
+// the allocator class to be used with the vector, the compiler complains
+// that alloc::address (an allocator function) is already instantiated.
+// By defining this macro, we appear to avoid that problem.
+
+#define __STL_USE_SGI_ALLOCATORS
+
+
+// Palm headers
+
+#include "Palm.h"
+
+
+// Std C/C++ Library stuff
+
+// Don't pull these in here. These would be brought in for *every*
+// file, which is too expensive. We can do this on other platforms,
+// as EmCommon.h is the basis for the precompiled header files,
+// which load in quickly even with lots of extra stuff in them.
+
+//#include <ctype.h> // isalpha, tolower
+//#include <stdarg.h>
+//#include <stddef.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+
+//#include <sys/types.h>
+//#include <sys/socket.h>
+//#include <sys/ioctl.h>
+//#include <netinet/in.h>
+//#include <netinet/tcp.h>
+//#include <netdb.h>
+
+//#include <algorithm> // find, sort
+//#include <deque> // deque
+//#include <list> // list
+//#include <string> // list
+//#include <utility> // pair
+//#include <vector>
+//#include <map>
+
+
+#define down fl_down // "down" defined both in WindowNew.h and Fl/Enumerations.h
+
+
+// ============================================
+// ========== Windows socket mapping ==========
+// ============================================
+
+#include <sys/types.h>
+#include <sys/socket.h> // socklen_t
+
+#if !defined(HAVE_TYPE_SOCKLEN_T)
+ typedef int socklen_t; // not defined in <sys/socket.h> on solaris or FreeBSD
+#endif
+
+typedef int SOCKET;
+
+#define WSAEINVAL EINVAL
+#define INVALID_SOCKET ((SOCKET) (~0))
+#define SOCKET_ERROR (-1)
+#define closesocket close
+#define ioctlsocket ioctl
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+#endif /* EmUnixCommon_h */
diff --git a/SrcUnix/EmDirRefUnix.cpp b/SrcUnix/EmDirRefUnix.cpp
new file mode 100644
index 0000000..5d93d1d
--- /dev/null
+++ b/SrcUnix/EmDirRefUnix.cpp
@@ -0,0 +1,506 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDirRefUnix.h"
+
+#include "EmFileRef.h"
+#include "Platform.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::EmDirRef
+ *
+ * DESCRIPTION: Various ways to make a directory reference.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+EmDirRef::EmDirRef (void) :
+ fDirPath ()
+{
+}
+
+
+EmDirRef::EmDirRef (const EmDirRef& other) :
+ fDirPath (other.fDirPath)
+{
+}
+
+
+EmDirRef::EmDirRef (const char* path) :
+ fDirPath (path)
+{
+ this->MaybeAppendSlash ();
+}
+
+
+EmDirRef::EmDirRef (const string& path) :
+ fDirPath (path)
+{
+ this->MaybeAppendSlash ();
+}
+
+
+EmDirRef::EmDirRef (const EmDirRef& parent, const char* path) :
+ fDirPath (parent.GetFullPath () + path)
+{
+ this->MaybeAppendSlash ();
+}
+
+
+EmDirRef::EmDirRef (const EmDirRef& parent, const string& path) :
+ fDirPath (parent.GetFullPath () + path)
+{
+ this->MaybeAppendSlash ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::EmDirRef
+ *
+ * DESCRIPTION: EmDirRef destructor. Nothing special to do...
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+EmDirRef::~EmDirRef (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::operator=
+ *
+ * DESCRIPTION: Assignment operator. If "other" is not the same as
+ * the controlled object, copy the contents.
+ *
+ * PARAMETERS: other - object to copy.
+ *
+ * RETURNED: reference to self.
+ *
+ ***********************************************************************/
+
+EmDirRef&
+EmDirRef::operator= (const EmDirRef& other)
+{
+ if (&other != this)
+ {
+ fDirPath = other.fDirPath;
+ }
+
+ return *this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::IsSpecified
+ *
+ * DESCRIPTION: Returns whether or not the controlled object has been
+ * pointed to a (possibly non-existant) file, or if it's
+ * empty (that it, it was created with the default ctor).
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if the object points to a file.
+ *
+ ***********************************************************************/
+
+Bool
+EmDirRef::IsSpecified (void) const
+{
+ return !fDirPath.empty ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::Exists
+ *
+ * DESCRIPTION: Returns whether or not the controlled object points to
+ * an existing file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if the referenced file exists.
+ *
+ ***********************************************************************/
+
+Bool
+EmDirRef::Exists (void) const
+{
+ if (this->IsSpecified ())
+ {
+ DIR* dir = opendir (fDirPath.c_str ());
+ if (dir)
+ {
+ closedir (dir);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::Create
+ *
+ * DESCRIPTION: Attempt to create the managed directory. Does nothing
+ * if the directory already exists. Throws an exception
+ * if the attempt to create the directory fails.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmDirRef::Create (void) const
+{
+ if (!this->Exists () && this->IsSpecified ())
+ {
+ // Make sure all directories down to us are created, too.
+
+ EmDirRef parent = this->GetParent ();
+ parent.Create ();
+
+ if (mkdir (fDirPath.c_str (), 0777) != 0)
+ {
+ // !!! throw...
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetName
+ *
+ * DESCRIPTION: Returns the name of the referenced file. Only the file
+ * *name* is returned, not the full path.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: A string containing the name. If the file is not
+ * specified, an empty string is returned. No checks are
+ * made to see if the file actually exists.
+ *
+ ***********************************************************************/
+
+string
+EmDirRef::GetName (void) const
+{
+ string result;
+
+ if (this->IsSpecified () && fDirPath != "/")
+ {
+ // Make a copy of the path, and chop off the trailing '\'
+ // in order to get _splitpath to think the thing at the
+ // end is a file name.
+
+ string dirPath (fDirPath);
+ dirPath.resize (dirPath.size () - 1);
+
+ string::size_type pos = dirPath.rfind ('/', string::npos);
+ EmAssert (pos != string::npos);
+
+ result = dirPath.substr (pos + 1, string::npos);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetParent
+ *
+ * DESCRIPTION: Returns an object representing the parent (or container)
+ * of the managed file. If the managed file is the root
+ * directory, returns an unspecified EmDirRef.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: An object representing the file's parent.
+ *
+ ***********************************************************************/
+
+EmDirRef
+EmDirRef::GetParent (void) const
+{
+ EmDirRef result;
+
+ if (this->IsSpecified () && fDirPath != "/")
+ {
+ // Make a copy of the path, and chop off the trailing '\'
+ // in order to get _splitpath to think the thing at the
+ // end is a file name.
+
+ string dirPath (fDirPath);
+ dirPath.resize (dirPath.size () - 1);
+
+ string::size_type pos = dirPath.rfind ('/', string::npos);
+ EmAssert (pos != string::npos);
+
+ result = EmDirRef (dirPath.substr (0, pos + 1));
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetFullPath
+ *
+ * DESCRIPTION: Get a full (platform-specific) path to the object. The
+ * path is canonicalized in that it will always have a
+ * trailing slash.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: An string representing the file's path.
+ *
+ ***********************************************************************/
+
+string
+EmDirRef::GetFullPath (void) const
+{
+ return fDirPath;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetChildren
+ *
+ * DESCRIPTION: Get a full (platform-specific) path to the object. The
+ * path is canonicalized in that it will always have a
+ * trailing slash.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: An string representing the file's path.
+ *
+ ***********************************************************************/
+
+void
+EmDirRef::GetChildren (EmFileRefList* fileList, EmDirRefList* dirList) const
+{
+ DIR* dir = opendir (fDirPath.c_str ());
+ if (dir)
+ {
+ struct dirent* ent;
+ while ((ent = readdir (dir)) != NULL)
+ {
+ if (strcmp (ent->d_name, ".") == 0)
+ continue;
+
+ if (strcmp (ent->d_name, "..") == 0)
+ continue;
+
+ string full_path (fDirPath + ent->d_name);
+ struct stat buf;
+ stat (full_path.c_str (), &buf);
+
+ if (S_ISDIR (buf.st_mode))
+ {
+ if (dirList)
+ dirList->push_back (EmDirRef (*this, ent->d_name));
+ }
+ else
+ {
+ if (fileList)
+ fileList->push_back (EmFileRef (*this, ent->d_name));
+ }
+ }
+
+ closedir (dir);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::operator==
+ * FUNCTION: EmDirRef::operator!=
+ * FUNCTION: EmDirRef::operator>
+ * FUNCTION: EmDirRef::operator<
+ *
+ * DESCRIPTION: Bogus operators for wiggy VC++ compiler which won't let
+ * us instantiate STL containers without them.
+ *
+ * PARAMETERS: other - object to compare ourself to.
+ *
+ * RETURNED: True if the requested condition is true. Comparisons
+ * are based on the file's full path.
+ *
+ ***********************************************************************/
+
+bool
+EmDirRef::operator== (const EmDirRef& other) const
+{
+ return _stricmp (fDirPath.c_str (), other.fDirPath.c_str ()) == 0;
+}
+
+
+bool
+EmDirRef::operator!= (const EmDirRef& other) const
+{
+ return _stricmp (fDirPath.c_str (), other.fDirPath.c_str ()) != 0;
+}
+
+
+bool
+EmDirRef::operator> (const EmDirRef& other) const
+{
+ return _stricmp (fDirPath.c_str (), other.fDirPath.c_str ()) < 0;
+}
+
+
+bool
+EmDirRef::operator< (const EmDirRef& other) const
+{
+ return _stricmp (fDirPath.c_str (), other.fDirPath.c_str ()) > 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FromPrefString
+ *
+ * DESCRIPTION: Initialize this object from the string containing a file
+ * reference stored in a preference file.
+ *
+ * PARAMETERS: s - the string from the preference file
+ *
+ * RETURNED: True if we were able to carry out the initialization.
+ * False otherwise. Note that the string is NOT validated
+ * to see if it refers to an existing file.
+ *
+ ***********************************************************************/
+
+bool
+EmDirRef::FromPrefString (const string& s)
+{
+ fDirPath = s;
+ this->MaybeAppendSlash ();
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ToPrefString
+ *
+ * DESCRIPTION: Produce a string that can be stored to a preference file
+ * and which can later be used to reproduce the current
+ * file reference object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The string to be written to the preference file.
+ *
+ ***********************************************************************/
+
+string
+EmDirRef::ToPrefString (void) const
+{
+ return fDirPath;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetEmulatorDirectory
+ *
+ * DESCRIPTION: Return an EmDirRef for Poser's directory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The desired EmDirRef.
+ *
+ ***********************************************************************/
+
+EmDirRef
+EmDirRef::GetEmulatorDirectory (void)
+{
+ const char* dir = getenv ("POSER_DIR");
+
+ if (dir == NULL)
+ dir = getenv ("HOME");
+
+ return EmDirRef (dir);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDirRef::GetPrefsDirectory
+ *
+ * DESCRIPTION: Return an EmDirRef for Poser's preferences directory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The desired EmDirRef.
+ *
+ ***********************************************************************/
+
+EmDirRef
+EmDirRef::GetPrefsDirectory (void)
+{
+ return GetEmulatorDirectory ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MaybeAppendSlash
+ *
+ * DESCRIPTION: Append a trailing slash to the full path if there isn't
+ * one already there.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void
+EmDirRef::MaybeAppendSlash (void)
+{
+ if (this->IsSpecified () && fDirPath[fDirPath.size () - 1] != '/')
+ {
+ fDirPath += '/';
+ }
+}
diff --git a/SrcUnix/EmDirRefUnix.h b/SrcUnix/EmDirRefUnix.h
new file mode 100644
index 0000000..9c5f0f7
--- /dev/null
+++ b/SrcUnix/EmDirRefUnix.h
@@ -0,0 +1,19 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDirRefWin_h
+#define EmDirRefWin_h
+
+#include "EmDirRef.h"
+
+#endif /* EmDirRefWin_h */
diff --git a/SrcUnix/EmDlgFltk.cpp b/SrcUnix/EmDlgFltk.cpp
new file mode 100644
index 0000000..c7e7dc1
--- /dev/null
+++ b/SrcUnix/EmDlgFltk.cpp
@@ -0,0 +1,2497 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDlgFltk.h"
+
+#include "ErrorHandling.h" // ParamList
+#include "Miscellaneous.h" // ReplaceString, FormatString
+#include "Platform.h" // Platform::GetString
+#include "Strings.r.h" // kStr_
+
+#include <FL/Enumerations.H>
+#include <FL/Fl.H>
+#include <FL/Fl_Adjuster.H>
+#include <FL/Fl_Bitmap.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Browser.H>
+#include <FL/Fl_Browser_.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Chart.H>
+#include <FL/Fl_Check_Button.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Clock.H>
+#include <FL/Fl_Color_Chooser.H>
+#include <FL/Fl_Counter.H>
+#include <FL/Fl_Dial.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Fill_Dial.H>
+#include <FL/Fl_Fill_Slider.H>
+#include <FL/Fl_Float_Input.H>
+#include <FL/Fl_FormsBitmap.H>
+#include <FL/Fl_FormsPixmap.H>
+#include <FL/Fl_Free.H>
+#include <FL/Fl_Gl_Window.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Hold_Browser.H>
+#include <FL/Fl_Hor_Fill_Slider.H>
+#include <FL/Fl_Hor_Nice_Slider.H>
+#include <FL/Fl_Hor_Slider.H>
+#include <FL/Fl_Hor_Value_Slider.H>
+#include <FL/Fl_Image.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Input_.H>
+#include <FL/Fl_Int_Input.H>
+#include <FL/Fl_Light_Button.H>
+#include <FL/Fl_Line_Dial.H>
+#include <FL/Fl_Menu.H>
+#include <FL/Fl_Menu_.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Menu_Window.H>
+#include <FL/Fl_Multi_Browser.H>
+#include <FL/Fl_Multi_Label.H>
+#include <FL/Fl_Multiline_Input.H>
+#include <FL/Fl_Multiline_Output.H>
+#include <FL/Fl_Nice_Slider.H>
+#include <FL/Fl_Object.H>
+#include <FL/Fl_Output.H>
+#include <FL/Fl_Overlay_Window.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/Fl_Positioner.H>
+#include <FL/Fl_Radio_Button.H>
+#include <FL/Fl_Radio_Light_Button.H>
+#include <FL/Fl_Radio_Round_Button.H>
+#include <FL/Fl_Repeat_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Roller.H>
+#include <FL/Fl_Round_Button.H>
+#include <FL/Fl_Round_Clock.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Scrollbar.H>
+#include <FL/Fl_Secret_Input.H>
+#include <FL/Fl_Select_Browser.H>
+#include <FL/Fl_Simple_Counter.H>
+#include <FL/Fl_Single_Window.H>
+#include <FL/Fl_Slider.H>
+#include <FL/Fl_Tabs.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Timer.H>
+#include <FL/Fl_Toggle_Button.H>
+#include <FL/Fl_Toggle_Light_Button.H>
+#include <FL/Fl_Toggle_Round_Button.H>
+#include <FL/Fl_Valuator.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Value_Output.H>
+#include <FL/Fl_Value_Slider.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Window.H>
+#include <FL/fl_ask.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_file_chooser.H>
+#include <FL/fl_message.H>
+#include <FL/fl_show_colormap.H>
+#include <FL/fl_show_input.H>
+
+#include "EmDlgFltkFactory.h"
+
+#include "espws-2.0/FileChooser.h"
+
+#include <algorithm> // find
+#include <list>
+#include <map>
+#include <string>
+#include <utility> // pair
+#include <queue>
+
+#if FL_MAJOR_VERSION == 1 && FL_MINOR_VERSION == 0
+// FLTK 1.0.x had a different layout for the undocumented Fl_Label structure.
+#define HAVE_LEGACY_FL_LABEL
+#endif
+
+typedef string FilterList;
+
+static FilterList PrvConvertTypeList (const EmFileTypeList&);
+static void PrvAddFilter (FilterList& filter, const char* pattern);
+static Fl_Window* PrvMakeDialog (EmDlgID);
+static Bool PrvInitializeDialog (EmDlgFn, void* data, EmDlgID, Fl_Window*);
+static void PrvIdleCallback (void* data);
+static string PrvBreakLine (Fl_Input_*, const char*);
+
+
+// -----------------------------------------------------------------------------
+// helper routines for establishing z-order independent ids for widgets.
+
+typedef map<EmDlgItemID, Fl_Widget*> ID2WidgetType;
+typedef map<Fl_Widget*, EmDlgItemID> Widget2IDType;
+
+ID2WidgetType gID2Widget;
+Widget2IDType gWidget2ID;
+
+Fl_Widget* PrvFindWidgetByID (EmDlgItemID id)
+{
+ ID2WidgetType::iterator iter = gID2Widget.find (id);
+ if (iter == gID2Widget.end ())
+ return NULL;
+
+ return iter->second;
+}
+
+EmDlgItemID PrvFindIDByWidget (Fl_Widget* o)
+{
+ Widget2IDType::iterator iter = gWidget2ID.find (o);
+ if (iter == gWidget2ID.end ())
+ return kDlgItemNone;
+
+ return iter->second;
+}
+
+void PrvSetWidgetID (Fl_Widget* o, EmDlgItemID id)
+{
+ gID2Widget[id] = o;
+ gWidget2ID[o] = id;
+}
+
+void PrvClearWidgetID (EmDlgItemID id)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (id);
+
+ if (o != NULL)
+ {
+ gID2Widget.erase (id);
+ gWidget2ID.erase (o);
+ }
+}
+
+void PrvClearWidgetID (Fl_Widget* o)
+{
+ EmDlgItemID id = ::PrvFindIDByWidget (o);
+
+ if (id != kDlgItemNone)
+ {
+ gID2Widget.erase (id);
+ gWidget2ID.erase (o);
+ }
+}
+
+void PrvClearAllWidgetIDs (void)
+{
+ gID2Widget.clear ();
+ gWidget2ID.clear ();
+}
+
+void PrvClearDlgWidgetIDs (Fl_Group* w)
+{
+ // Clear self.
+ ::PrvClearWidgetID (w);
+
+ // Clear children.
+ for (int ii = 0; ii < w->children (); ++ii)
+ {
+ Fl_Widget* child = w->child (ii);
+
+ Fl_Group* g = dynamic_cast<Fl_Group*>(child);
+ if (g)
+ {
+ ::PrvClearDlgWidgetIDs (g);
+ }
+ else
+ {
+ ::PrvClearWidgetID (child);
+ }
+ }
+}
+
+// Define data structures and routines for keeping track of
+// strings that are associated with widgets. We need to keep
+// track of what strings have been assigned to which widgets
+// because FLTK widgets don't *own* the labels assigned to
+// them. They expect the caller to own the storage. However,
+// that's not the model EmDlg uses; it assumes that the widgets
+// own the storage (as is the case in PowerPlant and with
+// Windows).
+//
+// So when we set the label of a widget, we keep ownership
+// of the string by storing it in a private collection. This
+// collection is a "list" object. I chose that one so that
+// strings currently in the collection are undisturbed when
+// new strings are added. Widgets keep a pointer to the
+// characters owned by the string object. If that object
+// moves around as the result of adding new string objects,
+// it might invalidate the pointer owned by the widget.
+
+typedef pair<Fl_Widget*, string> WidgetString;
+typedef list<WidgetString> WidgetStringList;
+
+WidgetStringList gWidgetStrings;
+
+const char* PrvSetWidgetString (Fl_Widget* o, const string& s)
+{
+ // First see if there's already an entry for this widget.
+
+ WidgetStringList::iterator iter = gWidgetStrings.end ();
+ while (iter != gWidgetStrings.end ())
+ {
+ if (iter->first == o)
+ {
+ // Widget is already in the collection.
+ // Replace the string it owns.
+
+ iter->second = s;
+ return iter->second.c_str ();
+ }
+
+ ++iter;
+ }
+
+ // Widget is not in the collection, so add an entry for it.
+
+ gWidgetStrings.push_back (WidgetString (o, s));
+ return (--(gWidgetStrings.end()))->second.c_str ();
+}
+
+void PrvClearWidgetString (Fl_Widget* o)
+{
+ WidgetStringList::iterator iter = gWidgetStrings.end ();
+ while (iter != gWidgetStrings.end ())
+ {
+ if (iter->first == o)
+ {
+ gWidgetStrings.erase (iter);
+ return;
+ }
+
+ ++iter;
+ }
+}
+
+void PrvClearAllWidgetStrings (void)
+{
+ gWidgetStrings.clear ();
+}
+
+void PrvClearDlgWidgetStrings (Fl_Group* w)
+{
+ for (int ii = 0; ii < w->children (); ++ii)
+ {
+ Fl_Widget* child = w->child (ii);
+ ::PrvClearWidgetString (child);
+
+ Fl_Group* g = dynamic_cast<Fl_Group*>(child);
+ if (g)
+ {
+ ::PrvClearDlgWidgetStrings (g);
+ }
+ }
+}
+
+typedef pair<EmDlgContext*, EmDlgItemID> EmWidget;
+
+typedef vector<EmWidget> EmWidgetList;
+EmWidgetList gWidgetList;
+
+typedef vector<Fl_Window*> Fl_Window_List;
+Fl_Window_List gDialogList;
+
+
+EmWidget PrvPopWidget (void)
+{
+ EmWidget result ((EmDlgContext*) NULL, kDlgItemNone);
+
+ if (!gWidgetList.empty ())
+ {
+ result = gWidgetList.front (); // Note, this is "top()" on Windows, maybe others...
+ gWidgetList.erase (gWidgetList.begin ());
+ }
+
+ return result;
+}
+
+
+void PrvPushWidget (EmDlgContext* context, EmDlgItemID itemID)
+{
+ EmWidget widget (context, itemID);
+ gWidgetList.push_back (widget);
+}
+
+
+void PrvClearQueue (EmDlgContext* context)
+{
+ if (!context)
+ {
+ gWidgetList.clear ();
+ }
+ else
+ {
+ EmWidgetList::iterator iter = gWidgetList.begin ();
+
+ while (iter != gWidgetList.end ())
+ {
+ if (context == iter->first)
+ {
+ EmWidgetList::size_type delta = iter - gWidgetList.begin ();
+ gWidgetList.erase (iter);
+ iter = gWidgetList.begin () + delta;
+
+ continue;
+ }
+
+ ++iter;
+ }
+ }
+}
+
+
+EmDlgItemID PrvFindCancelItem (Fl_Group* w)
+{
+ EmDlgItemID result = kDlgItemNone;
+
+ for (int ii = 0; result == kDlgItemNone && ii < w->children (); ++ii)
+ {
+ Fl_Widget* child = w->child (ii);
+
+ Fl_Group* g = dynamic_cast<Fl_Group*>(child);
+ Fl_Button* b = dynamic_cast<Fl_Button*>(child);
+ if (g)
+ {
+ result = ::PrvFindCancelItem (g);
+ }
+ else if (b)
+ {
+ if (b->shortcut () == FL_Escape)
+ {
+ result = ::PrvFindIDByWidget (b);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+void PrvWidgetCallback (Fl_Widget* w, void* c)
+{
+// EmDlgItemID id = ::PrvFindIDByWidget (w);
+// printf ("PrvWidgetCallback: id = 0x%08lX\n", (long) id);
+
+ EmDlgContext* context = (EmDlgContext*) c;
+ EmAssert (context);
+
+ EmDlgItemID itemID = ::PrvFindIDByWidget (w);
+ EmAssert (itemID != kDlgItemNone);
+
+ ::PrvPushWidget (context, itemID);
+}
+
+
+void PrvWindowCallback (Fl_Widget* w, void* c)
+{
+ EmDlgContext* context = (EmDlgContext*) c;
+ EmAssert (context);
+
+ Fl_Window* dlg = (Fl_Window*) context->fDlg;
+ EmAssert (dlg);
+
+ // Look for the item with the Escape shortcut.
+ EmDlgItemID itemID = ::PrvFindCancelItem (dlg);
+
+ // If one couldn't be found, for the kDlgItemCancel item
+ if (itemID == kDlgItemNone)
+ {
+ itemID = kDlgItemCancel;
+ }
+
+ ::PrvPushWidget (context, itemID);
+}
+
+
+void PrvInstallCallback (Fl_Widget* o, void* data)
+{
+ // Install callbacks only for our widgets. We shouldn't
+ // mess up any other callbacks -- they may do something
+ // important (such as the callback installed into scrollbars
+ // in an Fl_Scroll pane).
+
+ if (::PrvFindIDByWidget (o) != kDlgItemNone)
+ {
+ o->callback (&::PrvWidgetCallback, data);
+ }
+
+ // Set the callback for the topmost window, too, so that we
+ // get notification when it's closed.
+
+ else
+ {
+ Fl_Window* w = dynamic_cast<Fl_Window*> (o);
+
+ if (w)
+ {
+ o->callback (&::PrvWindowCallback, data);
+ }
+ }
+}
+
+
+void PrvInstallCallbacks (Fl_Group* w, EmDlgContext* context)
+{
+ // Set self.
+ ::PrvInstallCallback (w, context);
+
+ // Set children.
+ for (int ii = 0; ii < w->children (); ++ii)
+ {
+ Fl_Widget* child = w->child (ii);
+
+ Fl_Group* g = dynamic_cast<Fl_Group*>(child);
+ if (g)
+ {
+ ::PrvInstallCallbacks (g, context);
+ }
+ else
+ {
+ ::PrvInstallCallback (child, context);
+ }
+ }
+}
+
+
+void PrvAddDialog (Fl_Window* dlg)
+{
+ gDialogList.push_back (dlg);
+}
+
+
+void PrvRemoveDialog (Fl_Window* dlg)
+{
+ Fl_Window_List::iterator iter = find (gDialogList.begin (), gDialogList.end (), dlg);
+ EmAssert (iter != gDialogList.end ());
+ gDialogList.erase (iter);
+}
+
+
+void PrvDestroyDialog (EmDlgContext* context)
+{
+ EmAssert (context);
+
+ Fl_Window* dlg = reinterpret_cast<Fl_Window*>(context->fDlg);
+ EmAssert (dlg);
+
+ context->Destroy ();
+ EmDlg::HostStopIdling (*context);
+
+ dlg->hide ();
+
+ ::PrvRemoveDialog (dlg);
+ ::PrvClearDlgWidgetIDs (dlg);
+ ::PrvClearDlgWidgetStrings (dlg);
+ ::PrvClearQueue (context);
+
+ delete dlg;
+ delete context;
+}
+
+
+// Process all events on our dialog widgets. If dlg is non-NULL,
+// look for events that close that dialog. If the dialog is closed,
+// return true and fill in dismissingItemID with the ID of the item
+// that closed the dialog.
+
+Bool PrvHandleDialogEvents (Fl_Window* dlg, EmDlgItemID& dismissingItemID)
+{
+ // Loop, getting dialog items that have been manipulated in some way.
+
+ EmWidget w = ::PrvPopWidget ();
+
+ EmDlgContext* context = w.first;
+ EmDlgItemID itemID = w.second;
+
+ while (context != NULL && itemID != kDlgItemNone)
+ {
+ // Handle the event on the dialog item, checking to see if the
+ // dialog should be closed.
+
+ if (context->Event (itemID) == kDlgResultClose)
+ {
+ // The dialog is closing.
+
+ Fl_Window* closingDlg = reinterpret_cast<Fl_Window*>(context->fDlg);
+
+ // See if we're interested that this dialog closed.
+
+ Bool interested = dlg && (closingDlg == dlg);
+
+ // Destroy the dialog.
+
+ ::PrvDestroyDialog (context);
+
+ // If we're interested that this dialog closed, record the
+ // item that closed it and return TRUE.
+
+ if (interested)
+ {
+ dismissingItemID = itemID;
+
+ return true;
+ }
+ }
+
+ w = ::PrvPopWidget ();
+ context = w.first;
+ itemID = w.second;
+ }
+
+ return false;
+}
+
+
+void HandleDialogs (void)
+{
+ EmDlgItemID dummyItemID;
+ (void) ::PrvHandleDialogEvents (NULL, dummyItemID);
+}
+
+
+void HandleModalDialog (Fl_Window* dlg, EmDlgItemID& itemID)
+{
+ while (1)
+ {
+ // Handle any queued events.
+
+ if (::PrvHandleDialogEvents (dlg, itemID))
+ break;
+
+ // Process any system events.
+
+ Fl::wait ();
+
+ // Check to see if an idle handler has asked to close the window.
+
+ EmDlgContext* context = (EmDlgContext*) dlg->user_data ();
+ EmAssert (context);
+
+ if (context->fFnResult == kDlgResultClose)
+ {
+ ::PrvDestroyDialog (context);
+ break;
+ }
+ }
+}
+
+
+void CloseAllDialogs (void)
+{
+ Fl_Window_List::iterator iter = gDialogList.begin ();
+
+ while (iter != gDialogList.end ())
+ {
+ EmDlgContext* context = (EmDlgContext*) (*iter)->user_data ();
+ EmAssert (context);
+
+ ::PrvDestroyDialog (context);
+ ++iter;
+ }
+
+ gDialogList.clear ();
+}
+
+
+// -----------------------------------------------------------------------------
+// callback used to close modal dialogs. modalResult is < 0 if not yet completed.
+// set modalResult to be >=0 to complete dialog. Typically 0=cancel, 1=ok
+
+static long modalResult;
+void modalCallback(Fl_Return_Button*, void* result)
+{
+ modalResult = (long) result;
+}
+
+
+// -----------------------------------------------------------------------------
+// modal dialog control loop
+
+static int postModalDialog (Fl_Window* dlg)
+{
+ modalResult = -9999;
+ dlg->show();
+
+ // run our own event loop so that we have total control
+ // of the UI thread
+ for (;;)
+ {
+ Fl::wait ();
+ if (modalResult != -9999)
+ break;
+
+ if (!dlg->shown ())
+ {
+ // user hit escape (cancel)
+ modalResult = 0;
+ break;
+ }
+ }
+
+ // Clear out the default item queue. Stuff that we clicked on
+ // that didn't have a callback function will be in here. The
+ // items in that queue will be invalid after we close the window
+ // if we don't clear it out.
+
+ while (Fl::readqueue ())
+ ;
+
+ dlg->hide ();
+
+ return modalResult;
+}
+
+
+// -----------------------------------------------------------------------------
+// URL handler callback. This works whether netscape is currently running or
+// not.
+//!TODO: work with other browsers
+
+void openURL (Fl_Button* box, void*)
+{
+ char buffer[PATH_MAX];
+ char url[PATH_MAX];
+
+ box->labelcolor (FL_RED);
+
+ // get the label, trim the opening '<' and closing '>'
+ strcpy (url, &(box->label()[1]));
+ url [strlen (url) - 1] = '\0';
+
+#ifdef __QNXNTO__
+ sprintf (buffer, "voyager -u %s &", url);
+#else
+ sprintf (buffer, "netscape -remote 'openURL(%s,new-window)' || netscape '%s' &", url, url);
+#endif
+
+ system (buffer);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::HostRunGetFile
+ *
+ * DESCRIPTION: Platform-specific routine for getting the name of a
+ * file from the user. This file name is used to load
+ * the file.
+ *
+ * PARAMETERS: typeList - types of files user is allowed to select.
+ * ref - selected file is returned here. Valid only if
+ * function result is kDlgItemOK.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunGetFile (const void* parameters)
+{
+ EmAssert (parameters);
+ DoGetFileParameters& data = *(DoGetFileParameters*) parameters;
+
+ FilterList filter = ::PrvConvertTypeList (data.fFilterList);
+
+ FileChooser chooser (data.fDefaultPath.IsSpecified () ? data.fDefaultPath.GetFullPath ().c_str () : NULL,
+ filter.c_str (), FileChooser::SINGLE, data.fPrompt.c_str ());
+
+ chooser.show ();
+
+ while (chooser.shown ())
+ Fl::wait ();
+
+ long count = chooser.count ();
+ if (count == 0)
+ return kDlgItemCancel;
+
+ // Get a EmFileRef to the given file
+
+ data.fResult = EmFileRef (chooser.value(1));
+
+ return kDlgItemOK;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::HostRunGetFileList
+ *
+ * DESCRIPTION: Platform-specific routine for getting the name of a
+ * file from the user. This file name is used to load
+ * the file.
+ *
+ * PARAMETERS: typeList - types of files user is allowed to select.
+ * ref - selected file is returned here. Valid only if
+ * function result is kDlgItemOK.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunGetFileList (const void* parameters)
+{
+ EmAssert (parameters);
+ DoGetFileListParameters& data = *(DoGetFileListParameters*) parameters;
+
+ FilterList filter = ::PrvConvertTypeList (data.fFilterList);
+
+ FileChooser chooser (data.fDefaultPath.IsSpecified () ? data.fDefaultPath.GetFullPath ().c_str () : NULL,
+ filter.c_str (), FileChooser::MULTI, data.fPrompt.c_str ());
+
+ chooser.show ();
+
+ while (chooser.shown ())
+ Fl::wait ();
+
+ long count = chooser.count ();
+ if (count == 0)
+ return kDlgItemCancel;
+
+ for (long ii = 1; ii <= count; ++ii)
+ {
+ data.fResults.push_back (EmFileRef (chooser.value (ii)));
+ }
+
+ return kDlgItemOK;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::HostRunPutFile
+ *
+ * DESCRIPTION: Platform-specific routine for getting the name of a
+ * file from the user. This file name is used to save
+ * the file.
+ *
+ * PARAMETERS: defName - default name for the file to be saved.
+ * ref - selected file is returned here. Valid only if
+ * function result is kDlgItemOK.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunPutFile (const void* parameters)
+{
+ EmAssert (parameters);
+ DoPutFileParameters& data = *(DoPutFileParameters*) parameters;
+
+ FilterList filter = ::PrvConvertTypeList (data.fFilterList);
+
+ FileChooser chooser (data.fDefaultPath.IsSpecified () ? data.fDefaultPath.GetFullPath ().c_str () : NULL,
+ filter.c_str (), FileChooser::CREATE, data.fPrompt.c_str ());
+
+ chooser.show ();
+
+ while (chooser.shown ())
+ Fl::wait ();
+
+ long count = chooser.count ();
+ if (count == 0)
+ return kDlgItemCancel;
+
+ // Get a EmFileRef to the given file
+
+ data.fResult = EmFileRef (chooser.value (1));
+
+ return kDlgItemOK;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::HostRunGetDirectory
+ *
+ * DESCRIPTION: Platform-specific routine for getting the name of a
+ * file from the user. This file name is used to load
+ * the file.
+ *
+ * PARAMETERS: typeList - types of files user is allowed to select.
+ * ref - selected file is returned here. Valid only if
+ * function result is kDlgItemOK.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunGetDirectory (const void* parameters)
+{
+ EmAssert (parameters);
+ DoGetDirectoryParameters& data = *(DoGetDirectoryParameters*) parameters;
+
+ FileChooser chooser (data.fDefaultPath.IsSpecified () ? data.fDefaultPath.GetFullPath ().c_str () : NULL,
+ "nEveRmAtCh*", FileChooser::DIRECTORY, data.fPrompt.c_str ());
+
+ chooser.show ();
+
+ while (chooser.shown ())
+ Fl::wait ();
+
+ long count = chooser.count ();
+ if (count == 0)
+ return kDlgItemCancel;
+
+ // Get a EmFileRef to the given file
+
+ data.fResult = EmDirRef (chooser.value (1));
+
+ return kDlgItemOK;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostRunSessionSave
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunSessionSave (const void* parameters)
+{
+ EmAssert (parameters);
+ DoSessionSaveParameters& data = *(DoSessionSaveParameters*) parameters;
+
+ string saveChanges (Platform::GetString (kStr_SaveBeforeClosing));
+
+ ParamList paramList;
+ paramList.push_back (string ("%AppName"));
+ paramList.push_back (data.fAppName);
+ paramList.push_back (string ("%DocName"));
+ paramList.push_back (data.fDocName);
+
+ string msg = Errors::ReplaceParameters (saveChanges, paramList);
+
+ int result = fl_choice (msg.c_str(),
+ Platform::GetString (kStr_Cancel).c_str(),
+ Platform::GetString (kStr_Yes).c_str(),
+ Platform::GetString (kStr_No).c_str() );
+
+ if (result == 1) // yes
+ return kDlgItemYes;
+
+ else if (result == 2) // no
+ return kDlgItemNo;
+
+ // result == 0
+ return kDlgItemCancel;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostRunAboutBox
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunAboutBox (const void* parameters)
+{
+ Fl_Window* aboutWin = ::PrvMakeDialog (kDlgAboutBox);
+ postModalDialog (aboutWin);
+ delete aboutWin;
+
+ return kDlgItemOK;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostRunDialog
+ *
+ * DESCRIPTION: Common routine that handles the creation of a dialog,
+ * initializes it (via the dialog handler), fetches events,
+ * handles events (via the dialog handler), and closes
+ * the dialog.
+ *
+ * PARAMETERS: fn - the custom dialog handler
+ * userData - custom data passed back to the dialog handler.
+ * dlgID - ID of dialog to create.
+ *
+ * RETURNED: ID of dialog item that dismissed the dialog.
+ *
+ ***********************************************************************/
+
+EmDlgItemID EmDlg::HostRunDialog (const void* parameters)
+{
+ EmAssert (parameters);
+ RunDialogParameters& data = *(RunDialogParameters*) parameters;
+
+ // Create the dialog.
+ Fl_Window* dlg = ::PrvMakeDialog (data.fDlgID);
+ if (!dlg)
+ return kDlgItemNone;
+
+ // Initialize the dialog.
+ if (!::PrvInitializeDialog (data.fFn, data.fUserData, data.fDlgID, dlg))
+ return kDlgItemNone;
+
+ // Handle the dialog.
+ EmDlgItemID itemID;
+
+ ::HandleModalDialog (dlg, itemID);
+
+ // Return the item that dismissed the dialog.
+ return itemID;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostDialogOpen
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+EmDlgRef EmDlg::HostDialogOpen (EmDlgFn fn, void* data, EmDlgID dlgID)
+{
+ // Create the dialog.
+ Fl_Window* dlg = ::PrvMakeDialog (dlgID);
+ if (!dlg)
+ return (EmDlgRef) NULL;
+
+ // Initialize the dialog.
+ if (!::PrvInitializeDialog (fn, data, dlgID, dlg))
+ return (EmDlgRef) NULL;
+
+ // Return the dialog.
+ return (EmDlgRef) dlg;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostDialogClose
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: .
+ *
+ ***********************************************************************/
+
+void EmDlg::HostDialogClose (EmDlgRef dlg)
+{
+ Fl_Window* o = reinterpret_cast<Fl_Window*>(dlg);
+ if (!o)
+ return;
+
+ EmDlgContext* context = (EmDlgContext*) o->user_data ();
+ EmAssert (context);
+
+ ::PrvDestroyDialog (context);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostStartIdling
+ *
+ * DESCRIPTION: Queue up our idle callback function with FLTK.
+ *
+ * PARAMETERS: context - context data to be provided to the callback
+ * function.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmDlg::HostStartIdling (EmDlgContext& context)
+{
+ Fl::add_timeout (.01, &::PrvIdleCallback, &context);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: HostStopIdling
+ *
+ * DESCRIPTION: Remove our idle callback function from FLTK.
+ *
+ * PARAMETERS: context - context data to be provided to the callback
+ * function.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmDlg::HostStopIdling (EmDlgContext& context)
+{
+ Fl::remove_timeout (&::PrvIdleCallback, &context);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetDlgBounds
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetDlgBounds (EmDlgRef dlg, const EmRect& bounds)
+{
+ Fl_Window* o = reinterpret_cast<Fl_Window*>(dlg);
+ if (!o)
+ return;
+
+ EmRect oldBounds = EmDlg::GetDlgBounds (dlg);
+
+ if (oldBounds != bounds)
+ {
+ o->resize (bounds.fLeft, bounds.fTop,
+ bounds.Width (), bounds.Height ());
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::CenterDlg
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::CenterDlg (EmDlgRef dlg)
+{
+ Fl_Window* o = reinterpret_cast<Fl_Window*>(dlg);
+ if (!o)
+ return;
+
+ o->position (
+ (Fl::w () - o->w ()) / 2,
+ (Fl::h () - o->h ()) / 3);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetDlgBounds
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmRect EmDlg::GetDlgBounds (EmDlgRef dlg)
+{
+ EmRect result (0, 0, 0, 0);
+
+ Fl_Window* o = reinterpret_cast<Fl_Window*>(dlg);
+ if (!o)
+ return result;
+
+ result.Set (o->x(), o->y(), o->x() + o->w(), o->y() + o->h());
+
+ return result;
+}
+
+
+void EmDlg::SetDlgDefaultButton (EmDlgContext& context, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Push_Button* b = dynamic_cast<Fl_Push_Button*>(o);
+ if (!b)
+ return;
+
+ b->SetDefaultButton ();
+}
+
+
+void EmDlg::SetDlgCancelButton (EmDlgContext& context, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Push_Button* b = dynamic_cast<Fl_Push_Button*>(o);
+ if (!b)
+ return;
+
+ b->SetCancelButton ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemMin
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemMin (EmDlgRef dlg, EmDlgItemID item, long minValue)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Valuator* valuator = dynamic_cast<Fl_Valuator*> (o);
+ if (valuator)
+ valuator->minimum (minValue);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemValue
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemValue (EmDlgRef dlg, EmDlgItemID item, long value)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ // ...............................................................
+ // Includes: Fl_Button, Fl_Light_Button, Fl_Check_Button,
+ // Fl_Radio_Light_Button, Fl_Round_Button, Fl_Radio_Round_Button,
+ // Fl_Repeat_Button, Fl_Radio_Buttion, Fl_Toggle_Button
+ // ...............................................................
+
+ Fl_Button* button = dynamic_cast<Fl_Button*> (o);
+ if (button)
+ button->value (value);
+
+ // ...............................................................
+ // Includes: Fl_Choice, Fl_Menu_Bar, Fl_Menu_Button
+ // ...............................................................
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ if (menu)
+ {
+ // Prevent out-of-range values.
+
+ if (!menu->menu ())
+ return;
+
+ if (value > menu->size () - 1)
+ value = menu->size () - 1;
+ else if (value < 0)
+ value = 0;
+
+ // Adjust for the fact that FLTK treats divider lines as
+ // an attribute of the preceding menu item, while our model
+ // is to treat them as seperate menu items.
+
+ for (int ii = 0; ii < value; ++ii)
+ {
+ if (menu->menu ()[ii].flags & FL_MENU_DIVIDER)
+ {
+ --value;
+ }
+ }
+
+ menu->value (value);
+ menu->redraw ();
+ }
+
+ // ...............................................................
+ // Includes: Fl_Browser, Fl_Hold_Browser, Fl_Multi_Browser,
+ // Fl_Select_Browser (but not Fl_Browser_)
+ // ...............................................................
+
+ Fl_Browser* browser = dynamic_cast<Fl_Browser*> (o);
+ if (browser)
+ browser->value (value);
+
+ // ...............................................................
+ // Includes: Fl_Adjuster, Fl_Counter, Fl_Dial, Fl_Roller,
+ // Fl_Scrollber, Fl_Slider, Fl_Value_Input, Fl_Value_Slider,
+ // Fl_Value_Output
+ // ...............................................................
+
+ Fl_Valuator* valuator = dynamic_cast<Fl_Valuator*> (o);
+ if (valuator)
+ valuator->value (value);
+
+ // ...............................................................
+ // Includes: Fl_Input_, Fl_Input, Fl_Float_Input, Fl_Int_Input,
+ // Fl_Multiline_Input, Fl_Secret_Input, Fl_Output and
+ // Fl_Multiline_Output
+ // ...............................................................
+
+ Fl_Input_* input = dynamic_cast<Fl_Input_*> (o);
+ if (input)
+ {
+ char buffer[20];
+ sprintf (buffer, "%ld", (long) value);
+ EmDlg::SetItemText (dlg, item, buffer);
+ }
+
+ // ...............................................................
+ // Includes: Fl_Box
+ // ...............................................................
+
+ Fl_Box* box = dynamic_cast<Fl_Box*> (o);
+ if (box)
+ {
+ char buffer[20];
+ ::FormatInteger (buffer, value);
+ EmDlg::SetItemText (dlg, item, buffer);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemMax
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemMax (EmDlgRef dlg, EmDlgItemID item, long maxValue)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ // ...............................................................
+ // Includes: Fl_Adjuster, Fl_Counter, Fl_Dial, Fl_Roller,
+ // Fl_Scrollber, Fl_Slider, Fl_Value_Input, Fl_Value_Slider,
+ // Fl_Value_Output
+ // ...............................................................
+
+ Fl_Valuator* valuator = dynamic_cast<Fl_Valuator*> (o);
+ if (valuator)
+ valuator->maximum (maxValue);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemBounds
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemBounds (EmDlgRef dlg, EmDlgItemID item, const EmRect& bounds)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ EmRect oldBounds = EmDlg::GetItemBounds (dlg, item);
+
+ if (oldBounds != bounds)
+ {
+ o->resize (bounds.fLeft, bounds.fTop,
+ bounds.Width (), bounds.Height ());
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SetItemText
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SetItemText (EmDlgRef dlg, EmDlgItemID item, string str)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Input_* in = dynamic_cast<Fl_Input_*> (o);
+ if (in)
+ {
+ // Can you believe it: Fl_Input_ doesn't do word wrap!
+ // So we have to do it ourself...
+ str = ::PrvBreakLine (in, str.c_str ());
+ in->value (str.c_str ());
+ }
+ else
+ {
+ // Setting the text of other items is tricky. That would be
+ // done by calling Fl_Widget::label. However, that function
+ // does not copy the text -- just the text pointer. That
+ // means the string object (or whatever is holding the storage)
+ // must exist after this function is called.
+
+ // Additionally, it appears that we have to hide and then show
+ // the widget in order to get it to update properly. Merely
+ // calling redraw will not erase the old text in boxes like
+ // the file counter in the "Import Database" dialog.
+
+ const char* s = ::PrvSetWidgetString (o, str);
+
+ if (o->visible_r ())
+ {
+ o->hide ();
+ o->label (s);
+ o->show ();
+ }
+ else
+ {
+ o->label (s);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetItemValue
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+long EmDlg::GetItemValue (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return 0;
+
+ // ...............................................................
+ // Includes: Fl_Button, Fl_Light_Button, Fl_Check_Button,
+ // Fl_Radio_Light_Button, Fl_Round_Button, Fl_Radio_Round_Button,
+ // Fl_Repeat_Button, Fl_Radio_Buttion, Fl_Toggle_Button
+ // ...............................................................
+
+ Fl_Button* button = dynamic_cast<Fl_Button*> (o);
+ if (button)
+ return button->value ();
+
+ // ...............................................................
+ // Includes: Fl_Choice, Fl_Menu_Bar, Fl_Menu_Button
+ // ...............................................................
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ if (menu)
+ {
+ if (menu->mvalue () == NULL)
+ return -1;
+
+ long result = menu->value();
+ long add = 0;
+
+ // Adjust for the fact that FLTK treats divider lines as
+ // an attribute of the preceding menu item, while our model
+ // is to treat them as seperate menu items.
+
+ for (int ii = 0; ii < result; ++ii)
+ {
+ if (menu->menu()[ii].flags & FL_MENU_DIVIDER)
+ {
+ add++;
+ }
+ }
+
+ return result + add;
+ }
+
+ // ...............................................................
+ // Includes: Fl_Browser (but not Fl_Browser_)
+ // ...............................................................
+
+ Fl_Browser* browser = dynamic_cast<Fl_Browser*> (o);
+ if (browser)
+ return browser->value ();
+
+ // ...............................................................
+ // Includes: Fl_Adjuster, Fl_Counter, Fl_Dial, Fl_Roller,
+ // Fl_Scrollber, Fl_Slider, Fl_Value_Input, Fl_Value_Slider,
+ // Fl_Value_Output
+ // ...............................................................
+
+ Fl_Valuator* valuator = dynamic_cast<Fl_Valuator*> (o);
+ if (valuator)
+ return (long) valuator->value (); // !!! Really is a "double"!
+
+ // ...............................................................
+ // Includes: Fl_Input_, Fl_Input, Fl_Float_Input, Fl_Int_Input,
+ // Fl_Multiline_Input, Fl_Secret_Input, Fl_Output and
+ // Fl_Multiline_Output
+ // ...............................................................
+
+ Fl_Input_* input = dynamic_cast<Fl_Input_*> (o);
+ if (input)
+ {
+ const char* text = input->value ();
+ long value = 0;
+ sscanf (text, "%ld", &value);
+ return value;
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetItemBounds
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmRect EmDlg::GetItemBounds (EmDlgRef dlg, EmDlgItemID item)
+{
+ EmRect result (0, 0, 0, 0);
+
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return result;
+
+ result.Set (o->x(), o->y(), o->x() + o->w(), o->y() + o->h());
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetItemText
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+string EmDlg::GetItemText (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return string ();
+
+ Fl_Input_* in = dynamic_cast<Fl_Input_*> (o);
+ if (in)
+ return string (in->value ());
+
+ return string (o->label ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::EnableItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::EnableItem (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ o->activate ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::DisableItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::DisableItem (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ o->deactivate ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::ShowItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::ShowItem (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ o->show ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::HideItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::HideItem (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ o->hide ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::ClearMenu
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::ClearMenu (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ EmAssert (menu);
+
+ menu->clear ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::AppendToMenu
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::AppendToMenu (EmDlgRef dlg, EmDlgItemID item, const StringList& strList)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ EmAssert (menu);
+
+ StringList::const_iterator iter = strList.begin ();
+ while (iter != strList.end ())
+ {
+ if (iter->empty ())
+ {
+ menu->mode (menu->size () - 2, FL_MENU_DIVIDER);
+ }
+ else
+ {
+ menu->add (iter->c_str (), 0, NULL, NULL, 0);
+ }
+
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::ClearList
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::ClearList (EmDlgRef dlg, EmDlgItemID item)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Browser* b = dynamic_cast<Fl_Browser*> (o);
+ EmAssert (b);
+
+ b->clear ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::EnableMenuItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::EnableMenuItem (EmDlgRef dlg, EmDlgItemID item, long menuItem)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ EmAssert (menu);
+ EmAssert (menu->menu ());
+ EmAssert (menuItem >= 0);
+ EmAssert (menuItem < menu->size ());
+
+ // Adjust for the fact that FLTK treats divider lines as
+ // an attribute of the preceding menu item, while our model
+ // is to treat them as seperate menu items.
+
+ for (int ii = 0; ii < menuItem; ++ii)
+ {
+ if (menu->menu () [ii].flags & FL_MENU_DIVIDER)
+ {
+ --menuItem;
+ }
+ }
+
+ /* DOLATER - kja: This won't work properly if we try to change a divider */
+ menu->mode (menuItem, 0);
+ menu->redraw ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::DisableMenuItem
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::DisableMenuItem (EmDlgRef dlg, EmDlgItemID item, long menuItem)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Menu_* menu = dynamic_cast<Fl_Menu_*> (o);
+ EmAssert (menu);
+ EmAssert (menu->menu ());
+ EmAssert (menuItem >= 0);
+ EmAssert (menuItem < menu->value ());
+
+ // Adjust for the fact that FLTK treats divider lines as
+ // an attribute of the preceding menu item, while our model
+ // is to treat them as seperate menu items.
+
+ for (int ii = 0; ii < menuItem; ++ii)
+ {
+ if (menu->menu () [ii].flags & FL_MENU_DIVIDER)
+ {
+ --menuItem;
+ }
+ }
+
+ /* DOLATER - kja: This won't work properly if we try to change a divider */
+ menu->mode (menuItem, FL_MENU_INACTIVE);
+ menu->redraw ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::AppendToList
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::AppendToList (EmDlgRef dlg, EmDlgItemID item, const StringList& strList)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Browser* b = dynamic_cast<Fl_Browser*> (o);
+ EmAssert (b);
+
+ StringList::const_iterator iter = strList.begin ();
+ while (iter != strList.end ())
+ {
+ b->add (iter->c_str (), NULL);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::SelectListItems
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::SelectListItems (EmDlgRef dlg, EmDlgItemID item, const EmDlgItemIndexList& itemList)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Browser* b = dynamic_cast<Fl_Browser*> (o);
+ EmAssert (b);
+
+ EmDlgItemIndexList::const_iterator iter = itemList.begin ();
+ while (iter != itemList.end ())
+ {
+ b->select (*iter + 1, 1);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::UnselectListItems
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::UnselectListItems (EmDlgRef dlg, EmDlgItemID item, const EmDlgListIndexList& itemList)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Browser* b = dynamic_cast<Fl_Browser*> (o);
+ EmAssert (b);
+
+ EmDlgItemIndexList::const_iterator iter = itemList.begin ();
+ while (iter != itemList.end ())
+ {
+ b->select (*iter + 1, 0);
+ ++iter;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetSelectedItems
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmDlg::GetSelectedItems (EmDlgRef dlg, EmDlgItemID item, EmDlgItemIndexList& itemList)
+{
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return;
+
+ Fl_Browser* b = dynamic_cast<Fl_Browser*> (o);
+ EmAssert (b);
+
+ for (int ii = 1; ii <= b->size (); ++ii)
+ {
+ if (b->selected (ii))
+ {
+ itemList.push_back (ii - 1);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDlg::GetTextHeight
+ *
+ * DESCRIPTION: Determine the height the text would be if fitted into
+ * the given item.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: New text height
+ *
+ ***********************************************************************/
+
+int EmDlg::GetTextHeight (EmDlgRef dlg, EmDlgItemID item, const string& s)
+{
+ int result = 0;
+
+ Fl_Widget* o = ::PrvFindWidgetByID (item);
+ if (!o)
+ return result;
+
+ EmRect bounds = EmDlg::GetItemBounds (dlg, item);
+ int width = bounds.Width ();
+
+ Fl_Input_* i = dynamic_cast<Fl_Input_*>(o);
+
+ if (i)
+ {
+ // Note that Fl_Output::draw insets the width of the widget
+ // area when drawing. We need to account for that here if we want
+ // our text to be measured the same way it's laid out.
+
+ Fl_Boxtype b = i->box () ? i->box () : FL_DOWN_BOX;
+ width -= Fl::box_dw (b) + 6;
+
+ // FIXME: The Fl_Label structure is not documented, and its layout
+ // has changed in the past. These two measurements should be
+ // rewritten to use fl_measure or perhaps o->measure_label somehow.
+
+ Fl_Label label =
+ {
+ s.c_str (),
+#ifndef HAVE_LEGACY_FL_LABEL
+ NULL,
+ NULL,
+#endif
+ FL_NORMAL_LABEL,
+ i->textfont (),
+ i->textsize (),
+ i->textcolor ()
+ };
+
+ label.measure (width, result);
+
+ result += Fl::box_dh (b);
+ }
+ else
+ {
+ // Note that Fl_Widget::draw_label insets the width of the widget
+ // area when drawing. We need to account for that here if we want
+ // our text to be measured the same way it's laid out.
+
+ width -= Fl::box_dw (o->box ());
+
+ if ((o->w () > 11) && (o->align () & (FL_ALIGN_LEFT | FL_ALIGN_RIGHT)))
+ {
+ width -= 6;
+ }
+
+ Fl_Label label =
+ {
+ s.c_str (),
+#ifndef HAVE_LEGACY_FL_LABEL
+ NULL,
+ NULL,
+#endif
+ o->labeltype (),
+ o->labelfont (),
+ o->labelsize (),
+ o->labelcolor ()
+ };
+
+ label.measure (width, result);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvConvertTypeList
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+FilterList PrvConvertTypeList (const EmFileTypeList& typeList)
+{
+ FilterList filter;
+
+ filter += "{";
+
+ EmFileTypeList::const_iterator iter = typeList.begin ();
+
+ while (iter != typeList.end ())
+ {
+ switch (*iter)
+ {
+ case kFileTypeNone:
+ break;
+
+ case kFileTypeApplication:
+ break;
+
+ case kFileTypeROM:
+ ::PrvAddFilter (filter, "*.[Rr][Oo][Mm]");
+ break;
+
+ case kFileTypeSession:
+ ::PrvAddFilter (filter, "*.[Pp][Ss][Ff]");
+ break;
+
+ case kFileTypeEvents:
+ ::PrvAddFilter (filter, "*.[Pp][Ee][Vv]");
+ break;
+
+ case kFileTypePreference:
+ break;
+
+ case kFileTypePalmApp:
+ ::PrvAddFilter (filter, "*.[Pp][Rr][Cc]");
+ break;
+
+ case kFileTypePalmDB:
+ ::PrvAddFilter (filter, "*.[Pp][Dd][Bb]");
+ break;
+
+ case kFileTypePalmQA:
+ ::PrvAddFilter (filter, "*.[Pp][Qq][Aa]");
+ break;
+
+ case kFileTypeText:
+ ::PrvAddFilter (filter, "*.[Tt][Xx][Tt]");
+ break;
+
+ case kFileTypePicture:
+ ::PrvAddFilter (filter, "*.[Pp][Pp][Mm]");
+ break;
+
+ case kFileTypeSkin:
+ ::PrvAddFilter (filter, "*.[Ss][Kk][Ii][Nn]");
+ break;
+
+ case kFileTypeProfile:
+ break;
+
+ case kFileTypePalmAll:
+ ::PrvAddFilter (filter, "*.[Pp][Rr][Cc]|*.[Pp][Dd][Bb]|*.[Pp][Qq][Aa]");
+ break;
+
+ case kFileTypeAll:
+ ::PrvAddFilter (filter, "*");
+ break;
+
+ case kFileTypeLast:
+ EmAssert (false);
+ break;
+ }
+
+ ++iter;
+ }
+
+ filter += "}";
+
+ return filter;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvAddFilter
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void PrvAddFilter (FilterList& filter, const char* pattern)
+{
+ if (filter.size() != 1)
+ {
+ filter += "|";
+ }
+
+ filter += pattern;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvMakeDialog
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Fl_Window* PrvMakeDialog (EmDlgID id)
+{
+ Fl_Window* w = NULL;
+
+ switch (id)
+ {
+ case kDlgNone:
+ break;
+
+ case kDlgAboutBox:
+ w = ::PrvMakeAboutDialog ();
+ break;
+
+ case kDlgSessionNew:
+ w = ::PrvMakeSessionNewDialog ();
+ break;
+
+ case kDlgSessionSave:
+ break;
+
+ case kDlgHordeNew:
+ w = ::PrvMakeNewHordeDialog ();
+ break;
+
+ case kDlgDatabaseImport:
+ w = ::PrvMakeDatabaseImportDialog ();
+ break;
+
+ case kDlgDatabaseExport:
+ w = ::PrvMakeDatabaseExportDialog ();
+ break;
+
+ case kDlgROMTransferQuery:
+ w = ::PrvMakeROMTransferQueryDialog ();
+ break;
+
+ case kDlgROMTransferProgress:
+ w = ::PrvMakeROMTransferProgressDialog ();
+ break;
+
+ case kDlgGremlinControl:
+ w = ::PrvMakeGremlinControlDialog ();
+ break;
+
+ case kDlgEditPreferences:
+ w = ::PrvMakeEditPreferencesDialog ();
+ break;
+
+ case kDlgEditLogging:
+ w = ::PrvMakeEditLoggingOptionsDialog ();
+ break;
+
+ case kDlgEditDebugging:
+ w = ::PrvMakeEditDebuggingOptionsDialog ();
+ break;
+
+ case kDlgEditSkins:
+ w = ::PrvMakeEditSkinsDialog ();
+ break;
+
+ case kDlgEditHostFS:
+ w = ::PrvMakeHostFSOptionsDialog ();
+ break;
+
+ case kDlgCommonDialog:
+ w = ::PrvMakeCommonDialog ();
+ break;
+
+ case kDlgSaveBound:
+ break;
+
+ case kDlgEditBreakpoints:
+ w = ::PrvMakeEditBreakpointsDialog ();
+ break;
+
+ case kDlgEditCodeBreakpoint:
+ w = ::PrvMakeEditCodeBreakpointDialog ();
+ break;
+
+ case kDlgEditTracingOptions:
+ w = ::PrvMakeEditTracingOptionsDialog ();
+ break;
+
+ case kDlgEditPreferencesFullyBound:
+ break;
+
+ case kDlgReset:
+ w = ::PrvMakeResetDialog ();
+ break;
+
+ case kDlgSessionInfo:
+ w = ::PrvMakeSessionInfoDialog ();
+ break;
+
+ case kDlgGetSocketAddress:
+// w = ::PrvMakeGetSocketAddressDialog ();
+ break;
+
+ case kDlgEditErrorHandling:
+ w = ::PrvMakeEditErrorHandlingDialog ();
+ break;
+
+ case kDlgMinimizeProgress:
+ w = ::PrvMakeMinimizeDialog ();
+ break;
+ }
+
+ return w;
+}
+
+
+Bool PrvInitializeDialog (EmDlgFn fn, void* data, EmDlgID dlgID, Fl_Window* dlg)
+{
+ EmDlgContext* context = new EmDlgContext;
+ if (!context)
+ {
+ delete dlg;
+ return false;
+ }
+
+ context->fFn = fn;
+// context->fFnResult = filled in after fFn is called;
+ context->fDlg = (EmDlgRef) dlg;
+ context->fDlgID = dlgID;
+// context->fPanelID = filled in by subroutines;
+// context->fItemID = filled in by subroutines;
+// context->fCommandID = filled in by subroutines;
+// context->fNeedsIdle = filled in by c'tor to false;
+ context->fUserData = data;
+
+ // Center the dialog.
+ EmDlg::CenterDlg (context->fDlg);
+
+ // Install callbacks for all the items we handle.
+ ::PrvInstallCallbacks (dlg, context);
+
+ // Show the dialog. Note that the positioning of this call is
+ // important. The call to EmDlgContext::Init may result in the
+ // dialog's init handler trying to position the dialog. If it
+ // does that *before* the dialog is shown, some FLTK/X interaction
+ // causes the window to appear down and to the right by an amount
+ // equal to the top and left margins of the window frame. Showing
+ // the dialog first appears to fix that problem.
+ dlg->show();
+
+ // Initialize the dialog. Delete the dialog if
+ // initialization fails.
+ if (context->Init () == kDlgResultClose)
+ {
+ ::PrvDestroyDialog (context);
+ return false;
+ }
+
+ // Add this dialog to our internal list.
+ ::PrvAddDialog (dlg);
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: PrvIdleCallback
+ *
+ * DESCRIPTION: Function called by FLTK when our timeout function has
+ * timed out. Here we call the custom dialog handler. If
+ * it doesn't indicate that it's time to close the dialog,
+ * requeue the timeout function.
+ *
+ * PARAMETERS: data - callback data. We store the pointer to the
+ * current dialog context here.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void PrvIdleCallback (void* data)
+{
+ EmAssert (data);
+ EmDlgContext& context = *(EmDlgContext*) data;
+
+ // Call the idle function. The result is stored in context.fFnResult
+ // as well as returned from the function. If we need to continue,
+ // then requeue the idle function.
+
+ if (context.Idle () != kDlgResultClose && context.fNeedsIdle)
+ {
+ EmDlg::HostStartIdling (context);
+ }
+}
+
+
+// Copied from fl_draw.cxx, since they don't let us get to it directly.
+
+#define MAXBUF 1024
+
+// Copy p to buf, replacing unprintable characters with ^X and \nnn
+// Stop at a newline of if MAXBUF characters written to buffer.
+// Also word-wrap if width exceeds maxw.
+// Returns a pointer to the start of the next line of caharcters.
+// Sets n to the number of characters put into the buffer.
+// Sets width to the width of the string in the current font.
+
+static const char*
+expand(const char* from, char* buf, double maxw, int& n, double &width, int wrap) {
+
+ char* o = buf;
+ char* e = buf+(MAXBUF-4);
+// underline_at = 0;
+ char* word_end = o;
+ const char* word_start = from;
+ double w = 0;
+
+ const char* p = from;
+ for (;; p++) {
+
+ int c = *p & 255;
+
+ if (!c || c == ' ' || c == '\n') {
+ // test for word-wrap:
+ if (word_start < p && wrap) {
+ double newwidth = w + fl_width(word_end, o-word_end);
+ if (word_end > buf && newwidth > maxw) { // break before this word
+ o = word_end;
+ p = word_start;
+ break;
+ }
+ word_end = o;
+ w = newwidth;
+ }
+ if (!c) break;
+ else if (c == '\n') {p++; break;}
+ word_start = p+1;
+ }
+
+ if (o > e) break; // don't overflow buffer
+
+ if (c == '\t') {
+ for (c = (o-buf)%8; c<8 && o<e; c++) *o++ = ' ';
+
+#if 0
+ } else if (c == '&' && fl_draw_shortcut && *(p+1)) {
+ if (*(p+1) == '&') {p++; *o++ = '&';}
+ else if (fl_draw_shortcut != 2) underline_at = o;
+#endif
+ } else if (c < ' ' || c == 127) { // ^X
+ *o++ = '^';
+ *o++ = c ^ 0x40;
+
+ /*
+ * mike@easysw.com - The following escaping code causes problems when
+ * using the PostScript ISOLatin1 and WinANSI encodings, because these
+ * map to I18N characters...
+ */
+#if 0
+ } else if (c >= 128 && c < 0xA0) { // \nnn
+ *o++ = '\\';
+ *o++ = (c>>6)+'0';
+ *o++ = ((c>>3)&7)+'0';
+ *o++ = (c&7)+'0';
+#endif /* 0 */
+
+ } else if (c == 0xA0) { // non-breaking space
+ *o++ = ' ';
+
+ } else {
+ *o++ = c;
+
+ }
+ }
+
+ width = w + fl_width(word_end, o-word_end);
+ *o = 0;
+ n = o-buf;
+ return p;
+}
+
+string PrvBreakLine (Fl_Input_* in, const char* str)
+{
+ string result;
+
+ // This function follows the outline of fl_measure.
+
+ // Set the font so that we can measure the text's width.
+
+ fl_font (in->textfont (), in->textsize ());
+
+ // Get the width of the box in which the text will be
+ // laid out. Fl_Output fudge by box_dw() + 6, so we
+ // must do that, too.
+
+ int max_width = in->w ();
+ Fl_Boxtype b = in->box () ? in->box () : FL_DOWN_BOX;
+
+ max_width -= Fl::box_dw (b) + 6;
+
+ // Break up the string, adding it back together in
+ // "result", with the lines seperated by CR's.
+
+ if (str)
+ {
+ const char* p;
+ const char* e;
+ char buf[MAXBUF];
+ int buflen;
+ double width;
+
+ for (p = str; *p; p = e)
+ {
+ e = expand (p, buf, max_width, buflen, width, true);
+ result += buf;
+ if (*e)
+ result += '\n';
+ }
+ }
+
+ return result;
+}
+
+void Fl_Push_Button::draw (void)
+{
+ if (fType == kDefault)
+ {
+ Fl_Return_Button::draw ();
+ }
+ else
+ {
+ Fl_Button::draw ();
+ }
+}
+
+
+int Fl_Push_Button::handle (int event)
+{
+ if (fType == kDefault)
+ {
+ return Fl_Return_Button::handle (event);
+ }
+
+ if (event == FL_SHORTCUT)
+ {
+ if (fType == kCancel && Fl::event_key () == FL_Escape)
+ {
+ do_callback ();
+ return 1;
+ }
+ }
+
+ return Fl_Button::handle (event);
+}
diff --git a/SrcUnix/EmDlgFltk.h b/SrcUnix/EmDlgFltk.h
new file mode 100644
index 0000000..25adce1
--- /dev/null
+++ b/SrcUnix/EmDlgFltk.h
@@ -0,0 +1,62 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDlgFltk_h
+#define EmDlgFltk_h
+
+#include "EmDlg.h"
+
+// For EmDlgFltkFactory.cpp
+class Fl_Widget;
+void PrvSetWidgetID (Fl_Widget* o, EmDlgItemID id);
+
+// For fltk_main.cpp
+void HandleDialogs (void);
+void CloseAllDialogs (void);
+
+// Fl_Push_Button is a button that can be configured as the Default
+// Button (draws with the Return Arrow and responds to the Return
+// key), Cancel Button (responds to the Escape Key), or a Normal
+// Button (no special drawing or keyboard handling).
+
+#include <FL/Fl_Return_Button.H>
+
+class Fl_Push_Button : public Fl_Return_Button
+{
+ public:
+ Fl_Push_Button (int x, int y, int w, int h, const char* l = NULL) :
+ Fl_Return_Button (x, y, w, h, l),
+ fType (kNormal)
+ {}
+
+ virtual int handle (int);
+
+ void SetDefaultButton (void) { fType = kDefault; }
+ void SetCancelButton (void) { fType = kCancel; }
+ void SetNormalButton (void) { fType = kNormal; }
+
+ protected:
+ virtual void draw (void);
+
+ private:
+ enum
+ {
+ kNormal,
+ kDefault,
+ kCancel
+ };
+
+ int fType;
+};
+
+#endif /* EmDlgFltk_h */
diff --git a/SrcUnix/EmDlgFltkFactory.fl b/SrcUnix/EmDlgFltkFactory.fl
new file mode 100644
index 0000000..db14c33
--- /dev/null
+++ b/SrcUnix/EmDlgFltkFactory.fl
@@ -0,0 +1,1157 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.00
+header_name {.h}
+code_name {.cpp}
+gridx 5
+gridy 5
+snap 3
+Function {PrvMakeROMTransferQueryDialog()} {} {
+ Fl_Window {} {
+ label {ROM Transfer}
+ xywh {752 584 520 400} labelsize 12 hide
+ code0 {\#include "EmCommon.h"}
+ code1 {\#include "EmDlgFltk.h"}
+ code2 {\#include "Platform.h"} modal
+ } {
+ Fl_Return_Button {} {
+ label Begin
+ xywh {330 355 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {420 355 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Scroll {} {
+ label {Instructions:}
+ xywh {20 30 480 290} type VERTICAL box DOWN_FRAME labelsize 12 align 5
+ } {
+ Fl_Box {} {
+ xywh {22 32 476 550} labelsize 12 align 149
+ code0 {::PrvSetWidgetID (o, kDlgItemDlqInstructions);}
+ }
+ }
+ Fl_Input {} {
+ label {Port:}
+ xywh {60 330 130 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDlqPortList);}
+ }
+ Fl_Choice {} {
+ label {Baud:}
+ xywh {60 360 130 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDlqBaudList);}
+ } {}
+ }
+}
+
+Function {PrvMakeROMTransferProgressDialog()} {} {
+ Fl_Window {} {
+ label Progress
+ xywh {190 593 300 115} labelsize 12 hide
+ } {
+ Fl_Return_Button {} {
+ label Cancel
+ xywh {105 70 90 25} shortcut 0xff1b labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Box {} {
+ label {Waiting...}
+ xywh {20 15 280 20} box FLAT_BOX labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemDlpMessage);}
+ }
+ Fl_Slider {} {
+ xywh {20 40 260 15} type {Horz Fill} labeltype NO_LABEL labelsize 12 maximum 20 value 5
+ code0 {::PrvSetWidgetID (o, kDlgItemDlpProgress);}
+ }
+ }
+}
+
+Function {PrvMakeNewHordeDialog()} {} {
+ Fl_Window {} {
+ label {New Gremlin Horde}
+ xywh {86 192 410 460} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {220 415 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {310 415 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Button {} {
+ label {Logging Options...}
+ xywh {20 415 125 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdLogging);}
+ }
+ Fl_Group {} {
+ label {Gremlin range}
+ xywh {20 25 370 100} box THIN_DOWN_FRAME labelsize 12 align 5
+ } {
+ Fl_Input {} {
+ label {From:}
+ xywh {60 35 55 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdStart);}
+ }
+ Fl_Input {} {
+ label {To:}
+ xywh {60 65 55 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdStop);}
+ }
+ Fl_Round_Button {} {
+ label {Switch after}
+ xywh {145 35 85 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdCheckSwitch);}
+ }
+ Fl_Round_Button {} {
+ label {Save after}
+ xywh {145 65 85 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdCheckSave);}
+ }
+ Fl_Round_Button {} {
+ label {Stop after}
+ xywh {145 95 85 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdCheckStop);}
+ }
+ Fl_Input {} {
+ label events
+ xywh {235 35 100 20} type Int labelsize 12 align 8 when 0 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdDepthSwitch);}
+ }
+ Fl_Input {} {
+ label events
+ xywh {235 65 100 20} type Int labelsize 12 align 8 when 0 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdDepthSave);}
+ }
+ Fl_Input {} {
+ label events
+ xywh {235 95 100 20} type Int labelsize 12 align 8 when 0 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdDepthStop);}
+ }
+ }
+ Fl_Group {} {
+ label Applications
+ xywh {20 150 370 250} box THIN_DOWN_FRAME labelsize 12 align 5
+ } {
+ Fl_Browser {} {
+ label {Choose applications to launch:}
+ xywh {30 174 170 216} type Multi labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdAppList);}
+ }
+ Fl_Choice {} {
+ label {Choose which to launch first:} open
+ xywh {210 175 165 25} labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdFirstLaunchedApp);}
+ } {}
+ Fl_Button {} {
+ label {Select All}
+ xywh {210 225 90 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdSelectAll);}
+ }
+ Fl_Button {} {
+ label Deselect
+ xywh {210 260 90 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHrdSelectNone);}
+ }
+ }
+ }
+}
+
+Function {PrvMakeEditSkinsDialog()} {} {
+ Fl_Window {} {
+ label Skins
+ xywh {897 266 300 280} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {110 235 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {200 235 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Browser {} {
+ label {Skins for current device:}
+ xywh {20 25 260 100} type Hold labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemSknSkinList);}
+ }
+ Fl_Group {} {
+ label {Other options}
+ xywh {20 150 260 70} box ENGRAVED_FRAME labelsize 12 align 5
+ } {
+ Fl_Check_Button {} {
+ label {Double scale}
+ xywh {25 155 160 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemSknDoubleScale);}
+ }
+ Fl_Check_Button {} {
+ label {White background}
+ xywh {25 175 160 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemSknWhiteBackground);}
+ }
+ Fl_Check_Button {} {
+ label {Dim skin when inactive}
+ xywh {25 195 160 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemSknDim);}
+ }
+ }
+ }
+}
+
+Function {PrvMakeEditLoggingOptionsDialog()} {} {
+ Fl_Window {} {
+ label {Logging Options}
+ xywh {53 135 405 275} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {215 230 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {305 230 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Group {} {
+ xywh {245 5 140 25} labelsize 12
+ } {
+ Fl_Round_Button {} {
+ label Normal
+ xywh {245 5 65 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogNormal);}
+ }
+ Fl_Round_Button {} {
+ label Gremlins
+ xywh {310 5 75 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogGremlins);}
+ }
+ }
+ Fl_Box {} {
+ label {Log:}
+ xywh {20 25 365 185} box THIN_DOWN_BOX labelsize 12 align 5
+ }
+ Fl_Check_Button {} {
+ label {Error messages}
+ xywh {25 30 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogErrorMessages);}
+ }
+ Fl_Check_Button {} {
+ label {Warning messages}
+ xywh {25 45 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogWarningMessages);}
+ }
+ Fl_Check_Button {} {
+ label {Misc Gremlin info}
+ xywh {25 60 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogGremlins);}
+ }
+ Fl_Check_Button {} {
+ label {Assembly opcodes}
+ xywh {25 75 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogCPUOpcodes);}
+ }
+ Fl_Check_Button {} {
+ label {Posted events}
+ xywh {210 30 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogEnqueuedEvents);}
+ }
+ Fl_Check_Button {} {
+ label {Received events}
+ xywh {210 45 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogDequeuedEvents);}
+ }
+ Fl_Check_Button {} {
+ label {System calls}
+ xywh {210 60 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogSystemCalls);}
+ }
+ Fl_Check_Button {} {
+ label {Application calls}
+ xywh {210 75 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogApplicationCalls);}
+ }
+ Fl_Check_Button {} {
+ label {Serial activity}
+ xywh {25 110 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogSerial);}
+ }
+ Fl_Check_Button {} {
+ label {Serial data}
+ xywh {210 110 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogSerialData);}
+ }
+ Fl_Check_Button {} {
+ label {NetLib activity}
+ xywh {25 125 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogNetLib);}
+ }
+ Fl_Check_Button {} {
+ label {NetLib data}
+ xywh {210 125 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogNetLibData);}
+ }
+ Fl_Check_Button {} {
+ label {ExgMgr activity}
+ xywh {25 140 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogExgMgr);}
+ }
+ Fl_Check_Button {} {
+ label {ExgMgr data}
+ xywh {210 140 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogExgMgrData);}
+ }
+ Fl_Check_Button {} {
+ label {RPC activity}
+ xywh {25 155 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogRPC);}
+ }
+ Fl_Check_Button {} {
+ label {RPC data}
+ xywh {210 155 145 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogRPCData);}
+ }
+ Fl_Check_Button {} {
+ label {High-level debugger activity}
+ xywh {25 170 185 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogHLDebugger);}
+ }
+ Fl_Check_Button {} {
+ label {High-level debugger data}
+ xywh {210 170 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogHLDebuggerData);}
+ }
+ Fl_Check_Button {} {
+ label {Low-level debugger activity}
+ xywh {25 185 185 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogLLDebugger);}
+ }
+ Fl_Check_Button {} {
+ label {Low-level debugger data}
+ xywh {210 185 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemLogLogLLDebuggerData);}
+ }
+ }
+}
+
+Function {PrvMakeSessionNewDialog()} {} {
+ Fl_Window {} {
+ label {New Session}
+ xywh {942 412 280 170} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {90 125 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {180 125 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Choice {} {
+ label {ROM file:}
+ xywh {80 15 180 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemNewROM);}
+ } {}
+ Fl_Choice {} {
+ label {Device:}
+ xywh {80 40 180 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemNewDevice);}
+ } {}
+ Fl_Choice {} {
+ label {Skin:}
+ xywh {80 65 180 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemNewSkin);}
+ } {}
+ Fl_Choice {} {
+ label {RAM size:}
+ xywh {80 90 180 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemNewMemorySize);}
+ } {}
+ }
+}
+
+Function {PrvMakeHostFSOptionsDialog()} {} {
+ Fl_Window {} {
+ label {HostFS Options}
+ xywh {850 280 330 220} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {140 175 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {230 175 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Browser {} {
+ label Slot
+ xywh {20 30 65 125} type Hold labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHfsList);}
+ }
+ Fl_Output {} {
+ label {Root path}
+ xywh {95 30 215 95} type Multiline labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHfsPath);}
+ }
+ Fl_Check_Button {} {
+ label Mounted
+ xywh {95 135 85 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHfsMounted);}
+ }
+ Fl_Button {} {
+ label Browse
+ xywh {230 135 80 20} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemHfsBrowse);}
+ }
+ }
+}
+
+Function {PrvMakeDatabaseImportDialog()} {} {
+ Fl_Window {} {
+ label Install
+ xywh {674 242 290 90} labelsize 12 hide modal
+ } {
+ Fl_Box {} {
+ label {Items remaining to be installed:}
+ xywh {20 15 200 20} labelsize 12 align 20
+ }
+ Fl_Box {} {
+ label 999
+ xywh {225 15 45 20} labelsize 12 align 24
+ code0 {::PrvSetWidgetID (o, kDlgItemImpNumFiles);}
+ }
+ Fl_Slider {} {
+ xywh {20 50 175 15} type {Horz Fill} labelsize 12 maximum 10 step 1 value 7
+ code0 {::PrvSetWidgetID (o, kDlgItemImpProgress);}
+ }
+ Fl_Button {} {
+ label Stop
+ xywh {210 45 60 25} shortcut 0xff1b labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ }
+}
+
+Function {PrvMakeCommonDialog()} {} {
+ Fl_Window {} {
+ label {Palm OS Emulator}
+ xywh {211 257 380 150} hide modal
+ } {
+ Fl_Button {} {
+ label Continue
+ xywh {280 105 80 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCmnButton1);}
+ class Fl_Push_Button
+ }
+ Fl_Button {} {
+ label Debug
+ xywh {190 105 80 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCmnButton2);}
+ class Fl_Push_Button
+ }
+ Fl_Button {} {
+ label {Reset...}
+ xywh {100 105 80 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCmnButton3);}
+ class Fl_Push_Button
+ }
+ Fl_Output {} {
+ xywh {20 15 340 75} type Multiline labelsize 12 align 0 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCmnText);}
+ code1 {Fl_Group::current ()->resizable (o);}
+ }
+ }
+}
+
+Function {PrvMakeEditDebuggingOptionsDialog()} {} {
+ Fl_Window {} {
+ label {Debug Options}
+ xywh {76 97 415 357} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {225 315 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {315 315 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Box {} {
+ label Checks
+ xywh {20 30 375 200} box ENGRAVED_FRAME labelsize 12 align 5
+ }
+ Fl_Check_Button {} {
+ label {Free chunk access}
+ xywh {30 40 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportFreeChunkAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Hardware register access}
+ xywh {30 60 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportHardwareRegisterAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Low memory access}
+ xywh {30 80 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportLowMemoryAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Low stack access}
+ xywh {30 100 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportLowStackAccess);}
+ }
+ Fl_Check_Button {} {
+ label {MemMgr data access}
+ xywh {30 120 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportMemMgrDataAccess);}
+ }
+ Fl_Check_Button {} {
+ label {MemMgr leaks}
+ xywh {30 140 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportMemMgrLeaks);}
+ }
+ Fl_Check_Button {} {
+ label {MemMgr semaphore}
+ xywh {30 160 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportMemMgrSemaphore);}
+ }
+ Fl_Check_Button {} {
+ label {Offscreen form object}
+ xywh {30 180 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportOffscreenObject);}
+ }
+ Fl_Check_Button {} {
+ label {Overlay errors}
+ xywh {30 200 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportOverlayErrors);}
+ }
+ Fl_Check_Button {} {
+ label {Proscribed function call}
+ xywh {220 40 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportProscribedFunction);}
+ }
+ Fl_Check_Button {} {
+ label {ROM access}
+ xywh {220 60 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportROMAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Screen access}
+ xywh {220 80 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportScreenAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Sizeless form object}
+ xywh {220 100 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportSizelessObject);}
+ }
+ Fl_Check_Button {} {
+ label {Stack almost full}
+ xywh {220 120 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportStackAlmostOverflow);}
+ }
+ Fl_Check_Button {} {
+ label {Strict International checks}
+ xywh {220 140 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportStrictIntlChecks);}
+ }
+ Fl_Check_Button {} {
+ label {System global access}
+ xywh {220 160 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportSystemGlobalAccess);}
+ }
+ Fl_Check_Button {} {
+ label {UIMgr data access}
+ xywh {220 180 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportUIMgrDataAccess);}
+ }
+ Fl_Check_Button {} {
+ label {Unlocked chunk access}
+ xywh {220 200 170 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgReportUnlockedChunkAccess);}
+ }
+ Fl_Box {} {
+ label {Dialog handling}
+ xywh {20 255 375 40} box ENGRAVED_FRAME labelsize 12 align 5
+ }
+ Fl_Check_Button {} {
+ label {Beep every 2 seconds when a dialog box is displayed}
+ xywh {30 265 335 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemDbgDialogBeep);}
+ }
+ }
+}
+
+Function {PrvMakeEditBreakpointsDialog()} {} {
+ Fl_Window {} {
+ label Breakpoints
+ xywh {899 137 290 330} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {100 290 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {190 290 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Group {} {
+ label {Code breakpoints}
+ xywh {20 25 250 140} box ENGRAVED_BOX labelsize 12 align 5
+ } {
+ Fl_Browser {} {
+ xywh {30 35 230 90} type Hold labelsize 12 align 0 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkList);}
+ }
+ Fl_Button {} {
+ label Edit
+ xywh {50 135 55 20} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkButtonEdit);}
+ }
+ Fl_Button {} {
+ label Clear
+ xywh {175 135 55 20} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkButtonClear);}
+ }
+ }
+ Fl_Group {} {
+ label {Data breakpoints}
+ xywh {20 190 250 90} box ENGRAVED_BOX labelsize 12 align 5
+ } {
+ Fl_Check_Button {} {
+ label Enabled
+ xywh {30 200 80 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkCheckEnabled);}
+ }
+ Fl_Input {} {
+ label {Start address:}
+ xywh {130 225 130 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkStartAddress);}
+ }
+ Fl_Input {} {
+ label {Number of bytes:}
+ xywh {130 250 130 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkNumberOfBytes);}
+ }
+ }
+ }
+}
+
+Function {PrvMakeEditCodeBreakpointDialog()} {} {
+ Fl_Window {} {
+ label {Code Breakpoint}
+ xywh {680 176 260 120} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {70 75 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {160 75 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Input {} {
+ label {Address:}
+ xywh {75 15 165 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkAddress);}
+ }
+ Fl_Input {} {
+ label {Condition:}
+ xywh {75 40 165 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemBrkCondition);}
+ }
+ }
+}
+
+Function {PrvMakeDatabaseExportDialog()} {} {
+ Fl_Window {} {
+ label {Export Database}
+ xywh {643 135 260 385} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {70 340 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {160 340 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Browser {} {
+ label {Choose database to export:}
+ xywh {20 25 220 300} type Hold box DOWN_BOX labelsize 12 align 5 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemExpDbList);}
+ }
+ }
+}
+
+Function {PrvMakeEditPreferencesDialog()} {} {
+ Fl_Window {} {
+ label Preferences
+ xywh {251 186 270 417} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {80 375 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {170 375 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Box {} {
+ label Communications
+ xywh {20 25 230 120} box THIN_DOWN_BOX labelsize 12 align 5
+ }
+ Fl_Input {} {
+ label {Serial port:}
+ xywh {90 35 150 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfRedirectSerial);}
+ }
+ Fl_Input {} {
+ label {IR port:}
+ xywh {90 60 150 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfRedirectIR);}
+ }
+ Fl_Input {} {
+ label {Mystery:}
+ xywh {90 85 150 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfRedirectMystery);}
+ }
+ Fl_Check_Button {} {
+ label {Redirect NetLib calls to Host TCP/IP}
+ xywh {25 115 215 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfRedirectNetLib);}
+ }
+ Fl_Box {} {
+ label Sounds
+ xywh {20 180 230 30} box THIN_DOWN_BOX labelsize 12 align 5
+ }
+ Fl_Check_Button {} {
+ label {Enable sound}
+ xywh {25 185 150 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfEnableSound);}
+ }
+ Fl_Box {} {
+ label {Closing / Quitting}
+ xywh {20 235 230 70} box THIN_DOWN_BOX labelsize 12 align 5
+ }
+ Fl_Group {} {
+ xywh {25 240 150 60}
+ } {
+ Fl_Round_Button {} {
+ label {Always save session}
+ xywh {25 240 150 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfSaveAlways);}
+ }
+ Fl_Round_Button {} {
+ label {Ask to save session}
+ xywh {25 260 150 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfSaveAsk);}
+ }
+ Fl_Round_Button {} {
+ label {Never save session}
+ xywh {25 280 150 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfSaveNever);}
+ }
+ }
+ Fl_Box {} {
+ label {HotSync user name}
+ xywh {20 330 230 30} box THIN_DOWN_BOX labelsize 12 align 5
+ }
+ Fl_Input {} {
+ xywh {25 335 220 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemPrfUserName);}
+ }
+ }
+}
+
+Function {PrvMakeEditTracingOptionsDialog()} {} {
+ Fl_Window {} {
+ label {Tracing Options}
+ xywh {656 88 203 100} labelsize 12 hide modal
+ } {}
+}
+
+Function {PrvMakeResetDialog()} {} {
+ Fl_Window {} {
+ label Reset
+ xywh {446 151 480 305} labelsize 12 hide
+ } {
+ Fl_Return_Button {} {
+ label Reset
+ xywh {290 260 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {380 260 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Group {} {
+ xywh {20 14 120 106} labelsize 12
+ } {
+ Fl_Round_Button {} {
+ label {Soft reset}
+ xywh {20 15 105 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemRstSoft);}
+ }
+ Fl_Round_Button {} {
+ label {Hard reset}
+ xywh {20 55 105 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemRstHard);}
+ }
+ Fl_Round_Button {} {
+ label {Debug reset}
+ xywh {20 95 105 20} type Radio down_box ROUND_DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemRstDebug);}
+ }
+ }
+ Fl_Box {} {
+ xywh {20 157 440 3} box THIN_UP_BOX labelsize 12
+ }
+ Fl_Check_Button {} {
+ label {No extensions}
+ xywh {20 175 105 20} down_box DOWN_BOX labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemRstNoExt);}
+ }
+ Fl_Box {} {
+ label {This is the same as inserting a pin in the reset hole on a device. It performs a standard reset.}
+ xywh {130 15 330 35} labelsize 12 align 149
+ }
+ Fl_Box {} {
+ label {This is the same as a Soft Reset while holding down the Power key. It erases the storage heap.}
+ xywh {130 55 330 35} labelsize 12 align 149
+ }
+ Fl_Box {} {
+ label {This is the same as a Soft Reset while holding down the Page Down key. It causes the ROM to execute a DbgBreak early in the boot sequence.}
+ xywh {130 95 330 50} labelsize 12 align 149
+ }
+ Fl_Box {} {
+ label {This is the same as a Soft Reset while holding down the Page Up key. It skips the loading of extensions, patches, and certain libraries, as well as inhibiting the sending of sysAppLaunchCmdSystemReset to applications.}
+ xywh {130 175 330 65} labelsize 12 align 149
+ }
+ }
+}
+
+Function {PrvMakeSessionInfoDialog()} {} {
+ Fl_Window {} {
+ label {Session Info}
+ xywh {638 44 414 212} labelsize 12 hide
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {310 165 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Box {} {
+ label {Device name:}
+ xywh {25 25 105 30} labelsize 12 align 21
+ }
+ Fl_Box {} {
+ label {RAM size}
+ xywh {25 55 105 30} labelsize 12 align 21
+ }
+ Fl_Box {} {
+ label {ROM file path:}
+ xywh {25 85 105 30} labelsize 12 align 21
+ }
+ Fl_Box {} {
+ label {Session file path:}
+ xywh {25 115 105 30} labelsize 12 align 21
+ }
+ Fl_Box {} {
+ label {<Device Name>}
+ xywh {135 25 255 30} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemInfDeviceFld);}
+ }
+ Fl_Box {} {
+ label {<RAM Size>}
+ xywh {135 55 255 30} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemInfRAMFld);}
+ }
+ Fl_Box {} {
+ label {<ROM file>}
+ xywh {135 85 255 30} labelsize 12 align 213
+ code0 {::PrvSetWidgetID (o, kDlgItemInfROMFld);}
+ }
+ Fl_Box {} {
+ label {<Session file>}
+ xywh {135 115 255 30} labelsize 12 align 213
+ code0 {::PrvSetWidgetID (o, kDlgItemInfSessionFld);}
+ }
+ }
+}
+
+Function {PrvMakeGremlinControlDialog()} {} {
+ Fl_Window {} {
+ label {Gremlin Control}
+ xywh {654 76 326 109} labelsize 12 hide
+ } {
+ Fl_Box {} {
+ label {Event: 0,000,000 of 0,000,000}
+ xywh {15 15 185 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmEventNumber);}
+ }
+ Fl_Box {} {
+ label {Gremlin \#000}
+ xywh {215 15 95 20} labelsize 12 align 25
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmNumber);}
+ }
+ Fl_Box {} {
+ label {Elapsed time: 0,000,000.00 seconds}
+ xywh {15 40 225 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmElapsedTime);}
+ }
+ Fl_Button {} {
+ label Stop
+ xywh {15 70 65 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmStop);}
+ }
+ Fl_Button {} {
+ label Resume
+ xywh {135 70 65 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmResume);}
+ }
+ Fl_Button {} {
+ label Step
+ xywh {245 70 65 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemGrmStep);}
+ }
+ }
+}
+
+Function {PrvMakeEditErrorHandlingDialog()} {} {
+ Fl_Window {} {
+ label {Error Handling}
+ xywh {110 117 394 318} labelsize 12 hide modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ xywh {190 270 80 25} labelsize 12 hotspot
+ code0 {::PrvSetWidgetID (o, kDlgItemOK);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {290 270 80 25} shortcut 0xff1b labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ Fl_Box {} {
+ label {If Gremlins is off:}
+ xywh {20 30 350 90} box ENGRAVED_FRAME labelsize 12 align 5
+ }
+ Fl_Choice {} {
+ label {On warnings:}
+ xywh {115 45 225 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemErrWarningOff);}
+ } {}
+ Fl_Choice {} {
+ label {On errors:}
+ xywh {115 80 225 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemErrErrorOff);}
+ } {}
+ Fl_Box {} {
+ label {If Gremlins is on:}
+ xywh {20 160 350 90} box ENGRAVED_FRAME labelsize 12 align 5
+ }
+ Fl_Choice {} {
+ label {On warnings:}
+ xywh {115 175 225 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemErrWarningOn);}
+ } {}
+ Fl_Choice {} {
+ label {On errors:}
+ xywh {115 210 225 20} labelsize 12 textsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemErrErrorOn);}
+ } {}
+ }
+}
+
+Function {PrvMakeAboutDialog()} {} {
+ Fl_Window {} {
+ label {About Palm OS(R) Emulator}
+ xywh {124 348 362 231} hide
+ code0 {\#include <FL/Fl_Pixmap.H>}
+ code1 {\#include "poser.xpm"} modal
+ } {
+ Fl_Return_Button {} {
+ label OK
+ user_data 1
+ callback modalCallback
+ xywh {280 197 75 25} labelsize 12
+ }
+ Fl_Box {} {
+ xywh {10 15 50 60}
+ code0 {Fl_Pixmap* p = new Fl_Pixmap (poser_xpm);}
+ code1 {p->label (o);}
+ }
+ Fl_Tabs {} {
+ xywh {70 10 285 180}
+ } {
+ Fl_Group {} {
+ label Palm
+ xywh {95 35 260 155} labelsize 12 hide
+ code0 {o->show ();}
+ } {
+ Fl_Box {} {
+ label Version
+ xywh {100 45 240 20} labelfont 1 labelsize 12 align 21
+ code0 {static string versionStr;}
+ code1 {versionStr = string ("Palm OS Emulator Version ") + Platform::GetShortVersionString();}
+ code2 {o->label (versionStr.c_str ());}
+ }
+ Fl_Box {} {
+ label {Copyright (c) 1998-2001 Palm, Inc.}
+ xywh {100 70 240 15} labelsize 10 align 21
+ }
+ Fl_Button {} {
+ label {<http://www.palmos.com>}
+ callback openURL
+ xywh {100 105 125 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ Fl_Button {} {
+ label {<mailto:bug.reports@corp.palm.com>}
+ callback openURL
+ xywh {100 120 175 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ Fl_Box {} {
+ label {Download the latest version from:}
+ xywh {100 140 165 15} labelsize 10 align 21
+ }
+ Fl_Button {} {
+ label {<http://www.palmos.com/dev/tech/tools/emulator>}
+ callback openURL
+ xywh {100 155 235 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ }
+ Fl_Group {} {
+ label Windows
+ xywh {95 35 260 155} labelsize 12 hide
+ } {
+ Fl_Box {} {
+ label {Original Windows Copilot by Greg Hewgill}
+ xywh {100 55 240 15} labelsize 10 align 21
+ }
+ Fl_Box {} {
+ label {Portions copyright (c) 1996-1997}
+ xywh {100 70 240 15} labelsize 10 align 21
+ }
+ Fl_Button {} {
+ label {<http://www.hewgill.com>}
+ callback openURL
+ xywh {100 100 125 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ Fl_Button {} {
+ label {<mailto:greg@hewgill.com>}
+ callback openURL
+ xywh {100 115 130 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ }
+ Fl_Group {} {
+ label Macintosh
+ xywh {95 35 260 155} labelsize 12 hide
+ } {
+ Fl_Box {} {
+ label {Original Mac port by Craig Schofield}
+ xywh {100 55 240 15} labelsize 10 align 21
+ }
+ Fl_Box {} {
+ label {Portions copyright (c) 1995-1997}
+ xywh {100 70 240 15} labelsize 10 align 21
+ }
+ Fl_Button {} {
+ label {<http://members.aol.com/illumesoft/illume.html>}
+ callback openURL
+ xywh {100 100 220 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ Fl_Button {} {
+ label {<mailto:ILLUMESoft@aol.com>}
+ callback openURL
+ xywh {100 115 150 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ }
+ Fl_Group {} {
+ label UAE
+ xywh {95 35 260 155} labelsize 12
+ } {
+ Fl_Box {} {
+ label {UAE Amiga Emulator by Bernd Schmidt}
+ xywh {100 55 240 15} labelsize 10 align 21
+ }
+ Fl_Box {} {
+ label {Portions copyright (c) 1995-1997}
+ xywh {100 70 240 15} labelsize 10 align 21
+ }
+ Fl_Button {} {
+ label {<http://www.freiburg.linux.de/~uae>}
+ callback openURL
+ xywh {100 100 170 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ Fl_Button {} {
+ label {<mailto:crux@pool.informatik.rwth-aachen.de>}
+ callback openURL selected
+ xywh {100 115 225 15} box FLAT_BOX selection_color 2 labelsize 10 labelcolor 4 align 21
+ }
+ }
+ }
+ }
+}
+
+Function {PrvMakeMinimizeDialog()} {} {
+ Fl_Window {} {
+ label {Minimizing...}
+ xywh {644 124 375 125} labelsize 12 hide
+ } {
+ Fl_Box {} {
+ label {Pass \#000}
+ xywh {265 15 95 20} labelsize 12 align 25
+ code0 {::PrvSetWidgetID (o, kDlgItemMinPassNumber);}
+ }
+ Fl_Box {} {
+ label {Event: 0,000,000 of 0,000,000}
+ xywh {15 15 250 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemMinEventNumber);}
+ }
+ Fl_Box {} {
+ label {Elapsed time: 0,000,000.00 seconds}
+ xywh {15 35 250 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemMinElapsed);}
+ }
+ Fl_Box {} {
+ label {Excluding range 0,000,000 to 0,000,000}
+ xywh {15 55 250 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemMinRange);}
+ }
+ Fl_Box {} {
+ label {Discarded 0,000,000 of 0,000,000 events}
+ xywh {15 75 250 20} labelsize 12 align 21
+ code0 {::PrvSetWidgetID (o, kDlgItemMinDiscarded);}
+ }
+ Fl_Slider {} {
+ xywh {15 95 260 15} type {Horz Fill} labeltype NO_LABEL labelsize 12 maximum 20 value 5
+ code0 {::PrvSetWidgetID (o, kDlgItemMinProgress);}
+ }
+ Fl_Button {} {
+ label Cancel
+ xywh {295 90 65 25} labelsize 12
+ code0 {::PrvSetWidgetID (o, kDlgItemCancel);}
+ }
+ }
+}
diff --git a/SrcUnix/EmDocumentUnix.cpp b/SrcUnix/EmDocumentUnix.cpp
new file mode 100644
index 0000000..1af30d7
--- /dev/null
+++ b/SrcUnix/EmDocumentUnix.cpp
@@ -0,0 +1,142 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmDocumentUnix.h"
+
+#include "EmScreen.h" // EmScreen
+
+// !!! Need to get rid of this dependancy on FLTK
+#include <FL/filename.h> // filename_setext
+
+#include <stdio.h> // fopen, fprintf, fwrite, fclose, FILE
+
+
+EmDocumentUnix* gHostDocument;
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocument::HostCreateDocument
+// ---------------------------------------------------------------------------
+// Create our document instance. This is the one and only function that
+// creates the document. Being in a platform-specific file, it can create
+// any subclass of EmDocument it likes (in particular, one specific to our
+// platform).
+
+EmDocument* EmDocument::HostCreateDocument (void)
+{
+ return new EmDocumentUnix;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDocumentUnix::EmDocumentUnix
+ *
+ * DESCRIPTION: Constructor. Sets the global host application variable
+ * to point to us.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDocumentUnix::EmDocumentUnix (void) :
+ EmDocument ()
+{
+ EmAssert (gHostDocument == NULL);
+ gHostDocument = this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmDocumentUnix::~EmDocumentUnix
+ *
+ * DESCRIPTION: Destructor. Closes our window and sets the host
+ * application variable to NULL.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmDocumentUnix::~EmDocumentUnix (void)
+{
+ EmAssert (gHostDocument == this);
+ gHostDocument = NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmDocumentUnix::HostSaveScreen
+// ---------------------------------------------------------------------------
+// Save the current contents of the LCD buffer to the given file.
+
+void EmDocumentUnix::HostSaveScreen (const EmFileRef& destRef)
+{
+ // Make sure the extension is right.
+
+ string fullPath = destRef.GetFullPath ();
+ char* fNameExt = (char*) malloc (fullPath.size () + 4);
+ strcpy (fNameExt, fullPath.c_str ());
+ filename_setext (fNameExt, ".ppm");
+
+ FILE* f = fopen (fNameExt, "wb");
+ if (f)
+ {
+ EmScreen::InvalidateAll ();
+
+ EmScreenUpdateInfo info;
+ EmScreen::GetBits (info);
+
+ EmScreen::InvalidateAll ();
+
+ info.fImage.ConvertToFormat (kPixMapFormat24RGB);
+
+ // PPM format is:
+ //
+ // File type tag
+ // Width
+ // Height
+ // Max component value
+ // Width * Height pixels
+ //
+ // The first items in the file are all text and
+ // seperated by whitespace. The array of pixels
+ // is in text format if the file type is P3, and
+ // is in binary format if the type is P6.
+
+ EmPoint size = info.fImage.GetSize ();
+
+ fprintf (f, "P6 %ld %ld 255\x0D", size.fX, size.fY);
+
+ uint8* bits = (uint8*) info.fImage.GetBits ();
+ for (long yy = 0; yy < size.fY; ++yy)
+ {
+ long rowBytes = info.fImage.GetRowBytes ();
+ uint8* basePtr = bits + yy * rowBytes;
+
+ fwrite (basePtr, 1, rowBytes, f);
+ }
+
+ fclose (f);
+ }
+
+ free (fNameExt);
+}
diff --git a/SrcUnix/EmDocumentUnix.h b/SrcUnix/EmDocumentUnix.h
new file mode 100644
index 0000000..ee5a08f
--- /dev/null
+++ b/SrcUnix/EmDocumentUnix.h
@@ -0,0 +1,40 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmDocumentUnix_h
+#define EmDocumentUnix_h
+
+#include "EmDocument.h"
+
+/*
+ EmDocumentUnix is a Unix-specific sub-class of EmDocument. It is
+ responsible for translating platform-specific document-related
+ actions into cross-platform actions, making use of the the cross-
+ platform EmDocument implementations.
+*/
+
+class EmDocumentUnix : public EmDocument
+{
+ public:
+ EmDocumentUnix (void);
+ virtual ~EmDocumentUnix (void);
+
+ public:
+ // I'd like these to be private, but at least one part of Poser
+ // needs access to HostSaveScreen.
+ virtual void HostSaveScreen (const EmFileRef&);
+};
+
+extern EmDocumentUnix* gHostDocument;
+
+#endif // EmDocumentUnix_h
diff --git a/SrcUnix/EmFileRefUnix.cpp b/SrcUnix/EmFileRefUnix.cpp
new file mode 100644
index 0000000..df94e0c
--- /dev/null
+++ b/SrcUnix/EmFileRefUnix.cpp
@@ -0,0 +1,547 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmFileRefUnix.h"
+
+#include "Miscellaneous.h" // EndsWith
+#include "Platform.h" // stricmp
+
+#include <errno.h> // ENOENT
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+static const char* kExtension[] =
+{
+ NULL, // kFileTypeNone,
+ NULL, // kFileTypeApplication
+ ".rom", // kFileTypeROM,
+ ".psf", // kFileTypeSession,
+ ".pev", // kFileTypeEvents,
+ ".ini", // kFileTypePreference,
+ ".prc", // kFileTypePalmApp,
+ ".pdb", // kFileTypePalmDB,
+ ".pqa", // kFileTypePalmQA,
+ ".txt", // kFileTypeText,
+ NULL, // kFileTypePicture,
+ ".skin", // kFileTypeSkin,
+ ".prof", // kFileTypeProfile,
+ NULL, // kFileTypePalmAll,
+ NULL // kFileTypeAll
+};
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::EmFileRef
+ *
+ * DESCRIPTION: Various ways to make a file reference.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+EmFileRef::EmFileRef (void) :
+ fFilePath ()
+{
+ COMPILE_TIME_ASSERT(countof (kExtension) == kFileTypeLast);
+}
+
+
+EmFileRef::EmFileRef (const EmFileRef& other) :
+ fFilePath (other.fFilePath)
+{
+}
+
+
+EmFileRef::EmFileRef (const char* path) :
+ fFilePath (path)
+{
+ this->MaybePrependCurrentDirectory ();
+ this->MaybeNormalize ();
+}
+
+
+EmFileRef::EmFileRef (const string& path) :
+ fFilePath (path)
+{
+ this->MaybePrependCurrentDirectory ();
+ this->MaybeNormalize ();
+}
+
+
+EmFileRef::EmFileRef (const EmDirRef& parent, const char* path) :
+ fFilePath (parent.GetFullPath () + path)
+{
+ this->MaybeNormalize ();
+}
+
+
+EmFileRef::EmFileRef (const EmDirRef& parent, const string& path) :
+ fFilePath (parent.GetFullPath () + path)
+{
+ this->MaybeNormalize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::EmFileRef
+ *
+ * DESCRIPTION: EmFileRef destructor. Nothing special to do...
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+EmFileRef::~EmFileRef (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::operator=
+ *
+ * DESCRIPTION: Assignment operator. If "other" is not the same as
+ * the controlled object, copy the contents.
+ *
+ * PARAMETERS: other - object to copy.
+ *
+ * RETURNED: reference to self.
+ *
+ ***********************************************************************/
+
+EmFileRef&
+EmFileRef::operator= (const EmFileRef& other)
+{
+ if (&other != this)
+ {
+ fFilePath = other.fFilePath;
+ }
+
+ return *this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::IsSpecified
+ *
+ * DESCRIPTION: Returns whether or not the controlled object has been
+ * pointed to a (possibly non-existant) file, or if it's
+ * empty (that it, it was created with the default ctor).
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if the object points to a file.
+ *
+ ***********************************************************************/
+
+Bool
+EmFileRef::IsSpecified (void) const
+{
+ return !fFilePath.empty ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::Exists
+ *
+ * DESCRIPTION: Returns whether or not the controlled object points to
+ * an existing file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: True if the referenced file exists.
+ *
+ ***********************************************************************/
+
+Bool
+EmFileRef::Exists (void) const
+{
+ if (this->IsSpecified ())
+ {
+ struct stat buf;
+ int result = stat (fFilePath.c_str (), &buf);
+
+ return result == 0;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::IsType
+ *
+ * DESCRIPTION: DESCRIPTION
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool
+EmFileRef::IsType (EmFileType type) const
+{
+ if (fFilePath.size () > 4 &&
+ kExtension[type] != NULL &&
+ ::EndsWith (fFilePath.c_str (), kExtension[type]))
+ {
+ return true;
+ }
+
+ // Add special hacks for ROM files.
+ if (type == kFileTypeROM && ::StartsWith (fFilePath.c_str(), "rom."))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::SetCreatorAndType
+ *
+ * DESCRIPTION: Set the Finder type and creator information of the
+ * managed file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void
+EmFileRef::SetCreatorAndType (EmFileCreator creator, EmFileType fileType) const
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::GetAttr
+ *
+ * DESCRIPTION: Get basic file attributes of the managed file.
+ *
+ * PARAMETERS: A pointer to an integer where the mode bits will be stored.
+ *
+ * RETURNED: An integer containing an errno style error result, 0 for no error.
+ *
+ ***********************************************************************/
+
+int
+EmFileRef::GetAttr (int * mode) const
+{
+ EmAssert(mode);
+
+ *mode = 0;
+
+ if (!IsSpecified())
+ return ENOENT;
+
+ struct stat stat_buf;
+ if (stat(GetFullPath().c_str(), &stat_buf))
+ return errno;
+
+ if ((stat_buf.st_mode & S_IWUSR) == 0)
+ *mode |= kFileAttrReadOnly;
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::SetAttr
+ *
+ * DESCRIPTION: Set basic file attributes of the managed file.
+ *
+ * PARAMETERS: An integer containing bits from the EmFileAttr enum.
+ *
+ * RETURNED: An integer containing an errno style error result, 0 for no error.
+ *
+ ***********************************************************************/
+
+int
+EmFileRef::SetAttr (int mode) const
+{
+ if (!IsSpecified())
+ return ENOENT;
+
+ struct stat stat_buf;
+ if (stat(GetFullPath().c_str(), &stat_buf))
+ return errno;
+
+ stat_buf.st_mode &= ~S_IWUSR;
+ if (!(mode & kFileAttrReadOnly))
+ stat_buf.st_mode |= S_IWUSR;
+
+ if (chmod(GetFullPath().c_str(), stat_buf.st_mode))
+ return errno;
+
+ return 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::GetName
+ *
+ * DESCRIPTION: Returns the name of the referenced file. Only the file
+ * *name* is returned, not the full path.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: A string containing the name. If the file is not
+ * specified, an empty string is returned. No checks are
+ * made to see if the file actually exists.
+ *
+ ***********************************************************************/
+
+string
+EmFileRef::GetName (void) const
+{
+ string result;
+
+ if (this->IsSpecified ())
+ {
+ string::size_type pos = fFilePath.rfind ('/', string::npos);
+ EmAssert (pos != string::npos);
+
+ result = fFilePath.substr (pos + 1, string::npos);
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::GetParent
+ *
+ * DESCRIPTION: Returns an object representing the parent (or container)
+ * of the managed file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: An object representing the file's parent.
+ *
+ ***********************************************************************/
+
+EmDirRef
+EmFileRef::GetParent (void) const
+{
+ EmDirRef result;
+
+ if (this->IsSpecified () && fFilePath != "/")
+ {
+ string::size_type pos = fFilePath.rfind ('/', string::npos);
+ EmAssert (pos != string::npos);
+
+ result = EmDirRef (fFilePath.substr (0, pos + 1));
+ }
+
+ return result;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::GetFullPath
+ *
+ * DESCRIPTION: Get a full (platform-specific) path to the object.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: An string representing the file's path.
+ *
+ ***********************************************************************/
+
+string
+EmFileRef::GetFullPath (void) const
+{
+ return fFilePath;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmFileRef::operator==
+ * FUNCTION: EmFileRef::operator!=
+ * FUNCTION: EmFileRef::operator>
+ * FUNCTION: EmFileRef::operator<
+ *
+ * DESCRIPTION: Bogus operators for wiggy VC++ compiler which won't let
+ * us instantiate STL containers without them.
+ *
+ * PARAMETERS: other - object to compare ourself to.
+ *
+ * RETURNED: True if the requested condition is true. Comparisons
+ * are based on the file's full path.
+ *
+ ***********************************************************************/
+
+bool
+EmFileRef::operator== (const EmFileRef& other) const
+{
+ return _stricmp (fFilePath.c_str (), other.fFilePath.c_str ()) == 0;
+}
+
+
+bool
+EmFileRef::operator!= (const EmFileRef& other) const
+{
+ return _stricmp (fFilePath.c_str (), other.fFilePath.c_str ()) != 0;
+}
+
+
+bool
+EmFileRef::operator> (const EmFileRef& other) const
+{
+ return _stricmp (fFilePath.c_str (), other.fFilePath.c_str ()) < 0;
+}
+
+
+bool
+EmFileRef::operator< (const EmFileRef& other) const
+{
+ return _stricmp (fFilePath.c_str (), other.fFilePath.c_str ()) > 0;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: FromPrefString
+ *
+ * DESCRIPTION: Initialize this object from the string containing a file
+ * reference stored in a preference file.
+ *
+ * PARAMETERS: s - the string from the preference file
+ *
+ * RETURNED: True if we were able to carry out the initialization.
+ * False otherwise. Note that the string is NOT validated
+ * to see if it refers to an existing file.
+ *
+ ***********************************************************************/
+
+bool
+EmFileRef::FromPrefString (const string& s)
+{
+ fFilePath = s;
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ToPrefString
+ *
+ * DESCRIPTION: Produce a string that can be stored to a preference file
+ * and which can later be used to reproduce the current
+ * file reference object.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The string to be written to the preference file.
+ *
+ ***********************************************************************/
+
+string
+EmFileRef::ToPrefString (void) const
+{
+ return fFilePath;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MaybePrependCurrentDirectory
+ *
+ * DESCRIPTION: Prepend the current working directory if the managed
+ * path is not a full path.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void
+EmFileRef::MaybePrependCurrentDirectory (void)
+{
+ if (fFilePath[0] != '/')
+ {
+ size_t bufSize = 256;
+ char* buffer = (char*) Platform::AllocateMemory (bufSize);
+ while (getcwd (buffer, bufSize) == NULL)
+ {
+ if (errno != ERANGE)
+ return;
+
+ bufSize *= 2;
+ buffer = (char*) Platform::ReallocMemory (buffer, bufSize);
+ }
+
+ size_t cwdLen = strlen (buffer);
+ if (cwdLen)
+ {
+ if (buffer[cwdLen - 1] != '/')
+ fFilePath = string (buffer) + "/" + fFilePath;
+ else
+ fFilePath = string (buffer) + fFilePath;
+ }
+
+ Platform::DisposeMemory (buffer);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: MaybeNormalize
+ *
+ * DESCRIPTION: The routines we use to fetch a file from the user
+ * sometimes return full paths starting with double
+ * slashes. While the file system allows that, it play
+ * havoc with our operator=(). Patch up full paths
+ * so that they don't start with '//'
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void
+EmFileRef::MaybeNormalize (void)
+{
+ if (fFilePath.size () >= 2 &&
+ fFilePath[0] == '/' &&
+ fFilePath[1] == '/')
+ {
+ fFilePath.erase (fFilePath.begin ());
+ }
+}
diff --git a/SrcUnix/EmFileRefUnix.h b/SrcUnix/EmFileRefUnix.h
new file mode 100644
index 0000000..9cca412
--- /dev/null
+++ b/SrcUnix/EmFileRefUnix.h
@@ -0,0 +1,19 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmFileRefWin_h
+#define EmFileRefWin_h
+
+#include "EmFileRef.h"
+
+#endif /* EmFileRefWin_h */
diff --git a/SrcUnix/EmMenusFltk.cpp b/SrcUnix/EmMenusFltk.cpp
new file mode 100644
index 0000000..e42440e
--- /dev/null
+++ b/SrcUnix/EmMenusFltk.cpp
@@ -0,0 +1,94 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmMenusFltk.h"
+
+#include <ctype.h> // isalpha
+
+
+static int PrvMakeShortcut (int ch)
+{
+ if (ch == 0)
+ return 0;
+
+ if (isalpha (ch))
+ ch = tolower (ch);
+
+ return FL_ALT + ch;
+}
+
+
+void HostCreatePopupMenu (const EmMenuItemList& menu, Fl_Menu_Item_List& menuList)
+{
+ EmMenuItemList::const_iterator iter = menu.begin ();
+ while (iter != menu.end ())
+ {
+ if (iter->GetIsDivider ())
+ {
+ // Do nothing here. Dividers are not their own menu item
+ // in FLTK. Rather, they are an attribute of the previous
+ // menu item. The setting of this attribute is taken care
+ // of below when the menu item is created.
+ }
+ else
+ {
+ const EmMenuItemList& children = iter->GetChildren ();
+ Fl_Menu_Item fltkItem;
+
+ fltkItem.text = iter->GetTitle ().c_str ();
+ fltkItem.shortcut_ = ::PrvMakeShortcut (iter->GetShortcut ());
+ fltkItem.callback_ = NULL;
+ fltkItem.user_data_ = (void*) iter->GetCommand ();
+ fltkItem.flags = 0;
+ fltkItem.labeltype_ = 0;
+ fltkItem.labelfont_ = 0;
+ fltkItem.labelsize_ = FL_NORMAL_SIZE;
+ fltkItem.labelcolor_ = 0;
+
+ if (!iter->GetIsActive ())
+ {
+ fltkItem.flags |= FL_MENU_INACTIVE;
+ }
+
+ if (iter->GetIsChecked ())
+ {
+ fltkItem.flags |= FL_MENU_TOGGLE;
+ }
+
+ if (children.size () > 0)
+ {
+ fltkItem.flags |= FL_SUBMENU;
+ }
+
+ if (((iter + 1) < menu.end ()) && (iter + 1)->GetIsDivider ())
+ {
+ fltkItem.flags |= FL_MENU_DIVIDER;
+ }
+
+ menuList.push_back (fltkItem);
+
+ if (children.size () > 0)
+ {
+ ::HostCreatePopupMenu (children, menuList);
+ }
+ }
+
+ ++iter;
+ }
+
+ // Add a terminating item.
+
+ Fl_Menu_Item fltkItem = {0};
+ menuList.push_back (fltkItem);
+}
diff --git a/SrcUnix/EmMenusFltk.h b/SrcUnix/EmMenusFltk.h
new file mode 100644
index 0000000..c37d1ca
--- /dev/null
+++ b/SrcUnix/EmMenusFltk.h
@@ -0,0 +1,25 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmMenusFLTK_h
+#define EmMenusFLTK_h
+
+#include "EmMenus.h" // EmCommandID
+
+#include <FL/Fl_Menu_Item.h>
+
+typedef vector<Fl_Menu_Item> Fl_Menu_Item_List;
+
+void HostCreatePopupMenu (const EmMenuItemList&, Fl_Menu_Item_List&);
+
+#endif // EmMenusFLTK_h
diff --git a/SrcUnix/EmPixMapUnix.cpp b/SrcUnix/EmPixMapUnix.cpp
new file mode 100644
index 0000000..7ae7f6b
--- /dev/null
+++ b/SrcUnix/EmPixMapUnix.cpp
@@ -0,0 +1,48 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmPixMapUnix.h"
+
+
+
+// ---------------------------------------------------------------------------
+// ¥ ConvertPixMapToHost
+// ---------------------------------------------------------------------------
+
+void ConvertPixMapToHost ( const EmPixMap& src, void* dest,
+ int firstLine, int lastLine, Bool scale)
+{
+ // Determine a lot of the values we'll need.
+
+ int factor = scale ? 2 : 1;
+ EmPoint factorPoint = EmPoint (factor, factor);
+
+ EmPoint srcSize = src.GetSize ();
+ EmPixMapRowBytes destRowBytes = srcSize.fX * 3 * factor;
+
+ // Finally, copy the bits, converting to 24 bit format along the way.
+
+ EmPixMap wrapper;
+
+ wrapper.SetSize (srcSize * factorPoint);
+ wrapper.SetFormat (kPixMapFormat24RGB);
+ wrapper.SetRowBytes (destRowBytes);
+ wrapper.SetColorTable (src.GetColorTable ());
+ wrapper.SetBits (dest);
+
+ EmRect srcBounds (0, firstLine, srcSize.fX, lastLine);
+ EmRect destBounds (srcBounds * factorPoint);
+
+ EmPixMap::CopyRect (wrapper, src, destBounds, srcBounds);
+}
diff --git a/SrcUnix/EmPixMapUnix.h b/SrcUnix/EmPixMapUnix.h
new file mode 100644
index 0000000..dcfca9e
--- /dev/null
+++ b/SrcUnix/EmPixMapUnix.h
@@ -0,0 +1,22 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmPixMapUnix_h
+#define EmPixMapUnix_h
+
+#include "EmPixMap.h" // EmPixMap
+
+void ConvertPixMapToHost ( const EmPixMap& src, void* buffer,
+ int firstLine, int lastLine, Bool scale);
+
+#endif // EmPixMapUnix_h
diff --git a/SrcUnix/EmTransportSerialUnix.cpp b/SrcUnix/EmTransportSerialUnix.cpp
new file mode 100644
index 0000000..4ecaf4a
--- /dev/null
+++ b/SrcUnix/EmTransportSerialUnix.cpp
@@ -0,0 +1,1211 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransportSerialUnix.h"
+
+#include "Logging.h" // LogSerial
+#include "Platform.h" // Platform::AllocateMemory
+
+#include <errno.h> // errno
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h> // open(), close()
+#include <termios.h> // struct termios
+
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostConstruct
+ *
+ * DESCRIPTION: Construct platform-specific objects/data.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The platform-specific serial object.
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostConstruct (void)
+{
+ fHost = new EmHostTransportSerial;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostDestruct
+ *
+ * DESCRIPTION: Destroy platform-specific objects/data.
+ *
+ * PARAMETERS: hostData - The platform-specific serial object.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostDestruct (void)
+{
+ delete fHost;
+ fHost = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostOpen
+ *
+ * DESCRIPTION: Open the serial port in a platform-specific fashion.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::HostOpen (void)
+{
+ ErrCode err = fHost->OpenCommPort (fConfig);
+
+ if (!err)
+ err = fHost->CreateCommThreads (fConfig);
+
+ if (err)
+ this->HostClose ();
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostClose
+ *
+ * DESCRIPTION: Close the serial port in a platform-specific fashion.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::HostClose (void)
+{
+ ErrCode err;
+
+ err = fHost->DestroyCommThreads ();
+ err = fHost->CloseCommPort ();
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostRead
+ *
+ * DESCRIPTION: Read bytes from the port in a platform-specific fashion.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::HostRead (long& len, void* data)
+{
+ fHost->GetIncomingData (data, len);
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostWrite
+ *
+ * DESCRIPTION: Write bytes to the port in a platform-specific fashion.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::HostWrite (long& len, const void* data)
+{
+ fHost->PutOutgoingData (data, len);
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostBytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransportSerial::HostBytesInBuffer (long /*minBytes*/)
+{
+ return fHost->IncomingDataSize ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostSetConfig
+ *
+ * DESCRIPTION: Configure the serial port in a platform-specific
+ * fashion. The port is assumed to be open.
+ *
+ * PARAMETERS: config - configuration information.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportSerial::HostSetConfig (const ConfigSerial& config)
+{
+ PRINTF ("EmTransportSerial::HostSetConfig: Setting settings.");
+
+ ErrCode err = errNone;
+
+ struct termios io;
+
+ // Get the current settings.
+
+ if (tcgetattr (fHost->fCommHandle, &io) == -1) // macro for ioctl (..., TCGETA, ...) call
+ {
+ err = errno;
+ return err;
+ }
+
+ // One article on the net ("Serial Programming Guide for POSIX Compliant
+ // Operating Systems", <http://www.easysw.com/~mike/serial/serial.html>)
+ // recommends to *always* set these.
+
+ io.c_cflag |= (CREAD | CLOCAL);
+
+ // An execllent article on serial programming under UNIX ("Linux Serial Port
+ // Programming Mini-Howto") says to turn off these for "raw" (as opposed to
+ // "canonical") mode.
+
+ io.c_lflag &= ~(ICANON | ECHO | ISIG);
+
+ // The UNIX Programming FAQ (<www://www.faqs.org/faqs/unix-faq/programmer/faq/>)
+ // recommends just setting all the c_iflags and c_oflags to zero.
+
+ io.c_iflag = io.c_oflag = 0;
+
+ // Set the baud
+
+ int hostBaud = fHost->GetBaud (config.fBaud);
+ cfsetospeed (&io, hostBaud);
+ cfsetispeed (&io, hostBaud);
+
+ // Set the parity
+
+ if (config.fParity == EmTransportSerial::kNoParity)
+ {
+ io.c_cflag &= ~PARENB;
+ }
+ else
+ {
+ io.c_cflag |= PARENB;
+
+ if (config.fParity == EmTransportSerial::kOddParity)
+ {
+ io.c_cflag |= PARODD;
+ }
+ else
+ {
+ io.c_cflag &= ~PARODD;
+ }
+ }
+
+ // Set the data bits
+
+ io.c_cflag &= ~CSIZE;
+ io.c_cflag |= fHost->GetDataBits (config.fDataBits);
+
+ // Set the stop bits
+
+ if (config.fStopBits == 2)
+ {
+ io.c_cflag |= CSTOPB;
+ }
+ else
+ {
+ io.c_cflag &= ~CSTOPB;
+ }
+
+
+ // Set the hardware handshaking
+ //
+ // Note that I used to have the stuff in the #if 0.
+ // However, on the Windows side, Olivier Naudan argues:
+ //
+ // But I don't agree with: dcb.fRtsControl = config.fHwrHandshake ?
+ // RTS_CONTROL_HANDSHAKE : RTS_CONTROL_ENABLE;
+ // As hardware overrun can't be emulated, because of Poser timing that
+ // can't be accurate, I believe that fRtsControl should always be set to
+ // RTS_CONTROL_HANDSHAKE. So bytes will always arrive succesfully to host,
+ // and only software overrun could happen if PalmOS does not control the
+ // emulated RTS.
+
+ /*
+ Additional commentary
+
+ From Alexandre Duret-Lutz <aduret@enst.fr>:
+
+ I have a Unix application which connect to a serial device, and
+ configure the serial line with the following parameter.
+
+ ...
+ int fd = open ("/dev/ttyS0", O_RDWR);
+ ...
+ tty.c_cflag = CS8 | B9600 | CLOCAL | CREAD; // No CRTSCTS.
+ ...
+ tcsetattr (fd, TCSANOW, &tty);
+ ...
+
+ I also have the same application adapted to the Palm, which
+ connect to the same device, and initialize the line with
+
+ ...
+ UInt32 serFlags = srmSettingsFlagStopBits1 | srmSettingsFlagBitsPerChar8;
+ UInt16 serFlagsLen = sizeof serFlags;
+ ...
+ SrmOpen (serPortCradlePort, 9600, &port);
+ ...
+ SrmControl (port, srmCtlSetFlags, &serFlags, &serFlagsLen);
+ ....
+
+ Both applications work fine. But while the latter work on the
+ Palm it doesn't work in Pose. (The data seems to be sent but the
+ serial device never answer and my appl eventually timeout on
+ SrmReceive.)
+
+ Since 3.0a8, Pose is turning CRTSCTS on for all serial
+ connections, I beleive this is killing me. Indeed if I change
+ this behavior back to how it was in 3.0a7 my appl runs all fine.
+
+ --- SrcUnix/EmTransportSerialUnix.cpp.old Wed Apr 11 14:29:45 2001
+ +++ SrcUnix/EmTransportSerialUnix.cpp Wed Apr 11 14:30:00 2001
+ @@ -283,7 +283,7 @@
+ // and only software overrun could happen if PalmOS does not control the
+ // emulated RTS.
+
+ -#if 0
+ +#if 1
+ if (config.fHwrHandshake)
+ {
+ io.c_cflag |= CRTSCTS;
+
+
+ I guess this might be related to Dave Sours' recent postings,
+ as his appl broke when he switched from 3.0a7 and 3.1.
+ --
+ Alexandre Duret-Lutz
+
+ To which Olivier replies:
+
+ Keith,
+
+ Apparently, the change in Unix UART emulation is not exactly equivallent
+ to the Windows one. The change I proposed activates RTS handshaking
+ only, not CTS handshaking, whereas the change in Unix version activate
+ both (io.c_cflag |= CRTSCTS)
+
+ If opposite device does not handle flow control, or if the serial cable
+ is not completely wired, the CTS handshaking MUST be deactivated.
+ Otherwise, the host (Windows or Unix) will never send bytes to the other
+ device, because CTS will always be deasserted.
+
+ On the other hand, RTS handshaking can be activated safely on the host.
+ This signal is taken into account by the other device, or simply ignored
+ if it does not handle RTS handshaking.
+
+ So on the Unix version, the flag must also be set to RTS-only, if
+ possible. Otherwise, just revert the change.
+
+ One point is not clear to me. The developper says:
+
+ "The data seems to be sent but the serial device never answer and my
+ appl eventually timeout on SrmReceive."
+
+ In fact, since the other device does not handle flow control, the data
+ must not be sent due to CTS deasserted. As a result, the SrmReceive
+ never get an answer.
+
+ To check this, you may ask this developper to use a hardware serial spy
+ (a box with blinking LEDs indicating signal states) and check if the TD
+ (Transmit Data) led blink. It shouldn't. If it does, my guess is wrong.
+ Another option is to use a software serial spy. On Windows NT, I use
+ "PortMon". It shows low-level calls to NT serial driver.
+
+ BTW I proposed to always activate RTS handshaking on the host because in
+ the past some other tasks running may slow Poser up to the point of an
+ overrun. With this change, it does not occur any more if the other
+ device handle flow control, and I think it is safe.
+ I can't imagine a device that does not handle flow control, but that
+ still rely on a particular state of CTS/RTS.
+
+ Moreover, software overrun can still occur in the emulated UART if
+ PalmOS does not deassert RTS. Hardware overrun can't be emulated because
+ of intermediate buffering on the host and hazardous timing.
+
+ To help developpers understand the change, I propose the following text:
+
+ "dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
+
+ Whatever state of emulated UART is, we always activate RTS flow control
+ on the host. This would prevent host buffer overrun, in case the host is
+ busy and in case the opposite device handle RTS handshaking. This is
+ safe because if the opposite device does not handle flow control, it
+ will just ignore that signal.
+
+ However, we activate CTS handshaking only if IGNORE_CTS register is not
+ set. If the opposite device does not handle CTS and if we rely on CTS
+ state, data will never be sent."
+
+ To conclude, try using CTS-only flag on Unix version. If the CTS-only
+ flag does not exist, just revert the change. Also check the Macintosh
+ version. Ask the developper to investigate to check if data are really
+ sent or not. They shouldn't.
+
+ Hope this helps :-)
+
+ All of that is the long-winded explanation of why CRTSCTS is deasserted
+ when hardware handshaking is off.
+ */
+
+#if 1
+ if (config.fHwrHandshake)
+ {
+ io.c_cflag |= CRTSCTS;
+ }
+ else
+ {
+ io.c_cflag &= ~CRTSCTS;
+ }
+#else
+ io.c_cflag |= CRTSCTS;
+#endif
+
+ // Write out the changed settings.
+ if (tcsetattr (fHost->fCommHandle, TCSANOW, &io) == -1) // macro for ioctl (TCSETS, &io);
+ {
+ err = errno;
+ return err;
+ }
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostSetRTS
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostSetRTS (RTSControl /*state*/)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostSetDTR
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostSetDTR (Bool /*state*/)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostSetBreak
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostSetBreak (Bool /*state*/)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostGetCTS
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::HostGetCTS (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostGetDSR
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: .
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Bool EmTransportSerial::HostGetDSR (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostGetPortNameList
+ *
+ * DESCRIPTION: Return the list of serial ports on this computer. Used
+ * to prepare a menu of serial port choices.
+ *
+ * PARAMETERS: nameList - port names are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostGetPortNameList (PortNameList& results)
+{
+ results.clear ();
+
+#ifdef __QNXNTO__
+ results.push_back ("/dev/ser1");
+ results.push_back ("/dev/ser2");
+#else
+ results.push_back ("/dev/ttyS0");
+ results.push_back ("/dev/ttyS1");
+ results.push_back ("/dev/ttyS2");
+ results.push_back ("/dev/ttyS3");
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportSerial::HostGetSerialBaudList
+ *
+ * DESCRIPTION: Return the list of baud rates support by this computer.
+ * Used to prepare a menu of baud rate choices.
+ *
+ * PARAMETERS: baudList - baud rates are added to this list.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportSerial::HostGetSerialBaudList (BaudList& results)
+{
+ long maxBaud = 115200; // ::PrvGetMaxBaudRate ()? How to
+ // determine that on Unix?.
+
+ switch (maxBaud)
+ {
+ case 115200: results.push_back (115200);
+ case 57600: results.push_back (57600);
+ case 38400: results.push_back (38400);
+ case 19200: results.push_back (19200);
+ case 9600: results.push_back (9600);
+ }
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmHostTransportSerial::EmHostTransportSerial (void) :
+ fReadThread (NULL),
+ fWriteThread (NULL),
+ fCommHandle (0),
+ fCommSignalPipeA (0),
+ fCommSignalPipeB (0),
+ fTimeToQuit (false),
+ fDataMutex (),
+ fDataCondition (&fDataMutex),
+ fReadMutex (),
+ fReadBuffer (),
+ fWriteMutex (),
+ fWriteBuffer ()
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmHostTransportSerial::~EmHostTransportSerial (void)
+{
+ EmAssert (fReadThread == NULL);
+ EmAssert (fWriteThread == NULL);
+ EmAssert (fCommHandle == 0);
+ EmAssert (fCommSignalPipeA == 0);
+ EmAssert (fCommSignalPipeB == 0);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::OpenCommPort
+ *
+ * DESCRIPTION: Open the serial port.
+ *
+ * PARAMETERS: config - data block describing which port to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmHostTransportSerial::OpenCommPort (const EmTransportSerial::ConfigSerial& config)
+{
+ EmTransportSerial::PortName portName = config.fPort;
+
+ PRINTF ("EmTransportSerial::HostOpen: attempting to open port \"%s\"",
+ portName.c_str());
+
+ if (!portName.empty ())
+ {
+ PRINTF ("EmTransportSerial::HostOpen: Opening serial port...");
+
+ // An execllent article on serial programming under UNIX ("Linux Serial Port
+ // Programming Mini-Howto") says to set the following flags in the open call.
+ // The O_NDELAY is so that you can open the serial port without having DCD
+ // asserted. I'm not sure what the O_NOCTTY is for.
+
+ fCommHandle = open(portName.c_str (), O_RDWR | O_NOCTTY | O_NDELAY);
+
+ if (fCommHandle <= 0)
+ {
+ fCommHandle = 0;
+
+ return errno;
+ }
+ }
+ else
+ {
+ PRINTF ("EmTransportSerial::HostOpen: No port selected in the Properties dialog box...");
+ return -1; // !!! better error number
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::CreateCommThreads
+ *
+ * DESCRIPTION: Create the threads that asynchronously read from and
+ * write to the serial port.
+ *
+ * PARAMETERS: config - data block describing which port to use.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmHostTransportSerial::CreateCommThreads (const EmTransportSerial::ConfigSerial& /*config*/)
+{
+ if (fCommHandle)
+ {
+ PRINTF ("EmTransportSerial::HostOpen: Creating serial port handler threads...");
+
+ // Create the pipe used to communicate with CommRead.
+
+ int filedes[] = { 0, 0 };
+ if (pipe (filedes) == 0)
+ {
+ fCommSignalPipeA = filedes[0]; // for reading
+ fCommSignalPipeB = filedes[1]; // for writing
+ }
+
+ // Create the threads and start them up.
+
+ fTimeToQuit = false;
+ fReadThread = omni_thread::create (CommRead, this);
+ fWriteThread = omni_thread::create (CommWrite, this);
+ }
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::DestroyCommThreads
+ *
+ * DESCRIPTION: Shutdown and destroy the comm threads.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmHostTransportSerial::DestroyCommThreads (void)
+{
+ // If never created, nothing to destroy.
+
+ if (!fCommSignalPipeA)
+ return errNone;
+
+ // Signal the threads to quit.
+
+ fDataMutex.lock ();
+
+ fTimeToQuit = true;
+
+ int dummy = 0;
+ write (fCommSignalPipeB, &dummy, sizeof (dummy)); // Signals CommRead.
+
+ fDataCondition.broadcast (); // Signals CommWrite.
+ fDataMutex.unlock ();
+
+ // Wait for the threads to quit.
+
+ if (fReadThread)
+ {
+ fReadThread->join (NULL);
+ fWriteThread->join (NULL);
+ }
+
+ // Thread objects delete themselves, so set our references to NULL.
+
+ fReadThread = NULL;
+ fWriteThread = NULL;
+
+ // Close the signal pipe.
+
+ close (fCommSignalPipeA);
+ close (fCommSignalPipeB);
+
+ fCommSignalPipeA = fCommSignalPipeB = 0;
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::CloseCommPort
+ *
+ * DESCRIPTION: Close the comm port.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmHostTransportSerial::CloseCommPort (void)
+{
+ (void) close (fCommHandle);
+
+ fCommHandle = 0;
+
+ return errNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::PutIncomingData
+ *
+ * DESCRIPTION: Thread-safe method for adding data to the queue that
+ * holds data read from the serial port.
+ *
+ * PARAMETERS: data - pointer to the read data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmHostTransportSerial::PutIncomingData (const void* data, long& len)
+{
+ if (len == 0)
+ return;
+
+ omni_mutex_lock lock (fReadMutex);
+
+ char* begin = (char*) data;
+ char* end = begin + len;
+ while (begin < end)
+ fReadBuffer.push_back (*begin++);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::GetIncomingData
+ *
+ * DESCRIPTION: Thread-safe method for getting data from the queue
+ * holding data read from the serial port.
+ *
+ * PARAMETERS: data - pointer to buffer to receive data.
+ * len - on input, number of bytes available in "data".
+ * On exit, number of bytes written to "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmHostTransportSerial::GetIncomingData (void* data, long& len)
+{
+ omni_mutex_lock lock (fReadMutex);
+
+ if (len > (long) fReadBuffer.size ())
+ len = (long) fReadBuffer.size ();
+
+ char* p = (char*) data;
+ deque<char>::iterator begin = fReadBuffer.begin ();
+ deque<char>::iterator end = begin + len;
+
+ copy (begin, end, p);
+ fReadBuffer.erase (begin, end);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::IncomingDataSize
+ *
+ * DESCRIPTION: Thread-safe method returning the number of bytes in the
+ * read queue.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Number of bytes in the read queue.
+ *
+ ***********************************************************************/
+
+long EmHostTransportSerial::IncomingDataSize (void)
+{
+ omni_mutex_lock lock (fReadMutex);
+
+ return fReadBuffer.size ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::PutOutgoingData
+ *
+ * DESCRIPTION: Thread-safe method for adding data to the queue that
+ * holds data to be written to the serial port.
+ *
+ * PARAMETERS: data - pointer to the read data.
+ * len - number of bytes pointed to by "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmHostTransportSerial::PutOutgoingData (const void* data, long& len)
+{
+ if (len == 0)
+ return;
+
+ omni_mutex_lock lock (fWriteMutex);
+
+ char* begin = (char*) data;
+ char* end = begin + len;
+ while (begin < end)
+ fWriteBuffer.push_back (*begin++);
+
+ // Wake up CommWrite.
+
+ fDataMutex.lock ();
+ fDataCondition.broadcast ();
+ fDataMutex.unlock ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::GetOutgoingData
+ *
+ * DESCRIPTION: Thread-safe method for getting data from the queue
+ * holding data to be written to the serial port.
+ *
+ * PARAMETERS: data - pointer to buffer to receive data.
+ * len - on input, number of bytes available in "data".
+ * On exit, number of bytes written to "data".
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmHostTransportSerial::GetOutgoingData (void* data, long& len)
+{
+ omni_mutex_lock lock (fWriteMutex);
+
+ if (len > (long) fWriteBuffer.size ())
+ len = (long) fWriteBuffer.size ();
+
+ char* p = (char*) data;
+ deque<char>::iterator begin = fWriteBuffer.begin ();
+ deque<char>::iterator end = begin + len;
+
+ copy (begin, end, p);
+ fWriteBuffer.erase (begin, end);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::OutgoingDataSize
+ *
+ * DESCRIPTION: Thread-safe method returning the number of bytes in the
+ * write queue.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Number of bytes in the read queue.
+ *
+ ***********************************************************************/
+
+long EmHostTransportSerial::OutgoingDataSize (void)
+{
+ omni_mutex_lock lock (fWriteMutex);
+
+ return fWriteBuffer.size ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::CommRead
+ *
+ * DESCRIPTION: This function sits in its own thread, waiting for data
+ * to show up in the serial port. If data arrives, this
+ * function plucks it out and stores it in a thread-safe
+ * queue. It quits when it detects that the comm handle
+ * has been deleted.
+ *
+ * PARAMETERS: data - pointer to owning EmHostTransportSerial.
+ *
+ * RETURNED: Thread status.
+ *
+ ***********************************************************************/
+
+void* EmHostTransportSerial::CommRead (void* data)
+{
+ EmHostTransportSerial* This = (EmHostTransportSerial*) data;
+
+ PRINTF ("CommRead starting.");
+
+ while (!This->fTimeToQuit)
+ {
+ int status;
+ int fd1 = This->fCommHandle;
+ int fd2 = This->fCommSignalPipeA;
+ int maxfd = max (fd1, fd2);
+ fd_set read_fds;
+
+ FD_ZERO (&read_fds);
+ FD_SET (fd1, &read_fds);
+ FD_SET (fd2, &read_fds);
+
+ status = select (maxfd + 1, &read_fds, NULL, NULL, NULL);
+
+ if (This->fTimeToQuit)
+ break;
+
+ if (status > 0) // data available
+ {
+ if (FD_ISSET (fd1, &read_fds))
+ {
+ char buf[1024];
+ int len = 1024;
+ len = read (fd1, buf, len);
+
+ if (len == 0)
+ break; // port closed
+
+ // Log the data.
+ if (LogSerialData ())
+ LogAppendData (buf, len, "EmHostTransportSerial::CommRead: Received data:");
+ else
+ PRINTF ("EmHostTransportSerial::CommRead: Received %ld serial bytes.", len);
+
+ // Add the data to the EmHostTransportSerial object's buffer.
+ long n = (long) len;
+ This->PutIncomingData (buf, n);
+ }
+ }
+ }
+
+ PRINTF ("CommRead exitting.");
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::CommWrite
+ *
+ * DESCRIPTION: This function sits in its own thread, waiting for data
+ * to show up in the write queue. If data arrives, this
+ * function plucks it out and sends it out to the port. It
+ * quits when it detects that the comm handle has been
+ * deleted.
+ *
+ * PARAMETERS: data - pointer to owning EmHostTransportSerial.
+ *
+ * RETURNED: Thread status.
+ *
+ ***********************************************************************/
+
+void* EmHostTransportSerial::CommWrite (void* data)
+{
+ EmHostTransportSerial* This = (EmHostTransportSerial*) data;
+
+ PRINTF ("CommWrite starting.");
+
+ omni_mutex_lock lock (This->fDataMutex);
+
+ while (!This->fTimeToQuit)
+ {
+ This->fDataCondition.wait ();
+
+ // It's the EmHostTransportSerial object telling us to quit.
+
+ if (This->fTimeToQuit)
+ break;
+
+ // Get the data to write.
+
+ long len = This->OutgoingDataSize ();
+
+ // If there really wasn't any, go back to sleep.
+
+ if (len == 0)
+ continue;
+
+ // Get the data.
+
+ void* buf = Platform::AllocateMemory (len);
+ This->GetOutgoingData (buf, len);
+
+ // Log the data.
+
+ if (LogSerialData ())
+ LogAppendData (buf, len, "EmHostTransportSerial::CommWrite: Transmitted data:");
+ else
+ PRINTF ("EmHostTransportSerial::CommWrite: Transmitted %ld serial bytes.", len);
+
+ // Write the data.
+
+ ::write (This->fCommHandle, buf, len);
+
+ // Dispose of the data.
+
+ Platform::DisposeMemory (buf);
+ }
+
+ PRINTF ("CommWrite exitting.");
+
+ return NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::GetBaud
+ *
+ * DESCRIPTION: Map a baud rate into the Mac OS constant that represents
+ * that rate in a SerSettings call.
+ *
+ * PARAMETERS: baud - raw baud rate.
+ *
+ * RETURNED: Unix constant that represents that rate.
+ *
+ ***********************************************************************/
+
+int EmHostTransportSerial::GetBaud (EmTransportSerial::Baud baud)
+{
+ switch (baud)
+ {
+#if defined (B150)
+ case 150: PRINTF (" Baud = 150"); return B150;
+#endif
+
+#if defined (B300)
+ case 300: PRINTF (" Baud = 300"); return B300;
+#endif
+
+#if defined (B600)
+ case 600: PRINTF (" Baud = 600"); return B600;
+#endif
+
+#if defined (B1200)
+ case 1200: PRINTF (" Baud = 1200"); return B1200;
+#endif
+
+#if defined (B1800)
+ case 1800: PRINTF (" Baud = 1800"); return B1800;
+#endif
+
+#if defined (B2400)
+ case 2400: PRINTF (" Baud = 2400"); return B2400;
+#endif
+
+#if defined (B4800)
+ case 4800: PRINTF (" Baud = 4800"); return B4800;
+#endif
+
+#if defined (B9600)
+ case 9600: PRINTF (" Baud = 9600"); return B9600;
+#endif
+
+#if defined (B19200)
+ case 19200: PRINTF (" Baud = 19200"); return B19200;
+#endif
+
+#if defined (B38400)
+ case 38400: PRINTF (" Baud = 38400"); return B38400;
+#endif
+
+#if defined (B57600)
+ case 57600: PRINTF (" Baud = 57600"); return B57600;
+#endif
+
+#if defined (B115200)
+ case 115200: PRINTF (" Baud = 115200"); return B115200;
+#endif
+
+#if defined (B230400)
+ case 230400: PRINTF (" Baud = 230400"); return B230400;
+#endif
+ }
+
+ PRINTF (" Unknown Baud value: %ld.", (long) baud);
+
+ // Not necessarily invalid. The UART often has invalid baud values while
+ // it's being initialized. It's also equally valid for a Palm application
+ // to attempt to set the baud to something the underlying OS doesn't support.
+
+ // EmAssert (false);
+
+ return baud;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportSerial::GetDataBits
+ *
+ * DESCRIPTION: Map a dataBits value into the Mac OS constant that
+ * represents that value in a SerSettings call.
+ *
+ * PARAMETERS: dataBits - raw data bits value.
+ *
+ * RETURNED: Unix constant that represents that dataBits value.
+ *
+ ***********************************************************************/
+
+int EmHostTransportSerial::GetDataBits (EmTransportSerial::DataBits dataBits)
+{
+ switch (dataBits)
+ {
+ case 5: PRINTF (" dataBits = 5"); return CS5;
+ case 6: PRINTF (" dataBits = 6"); return CS6;
+ case 7: PRINTF (" dataBits = 7"); return CS7;
+ case 8: PRINTF (" dataBits = 8"); return CS8;
+ }
+
+ PRINTF (" Unknown DataBits value.");
+ EmAssert (false);
+ return 0;
+}
+
diff --git a/SrcUnix/EmTransportSerialUnix.h b/SrcUnix/EmTransportSerialUnix.h
new file mode 100644
index 0000000..5b0fcc6
--- /dev/null
+++ b/SrcUnix/EmTransportSerialUnix.h
@@ -0,0 +1,68 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransportSerialUnix_h
+#define EmTransportSerialUnix_h
+
+#include "EmTransportSerial.h"
+
+#include "omnithread.h" // omni_mutex
+#include <deque> // deque
+
+
+class EmHostTransportSerial
+{
+ public:
+ EmHostTransportSerial (void);
+ ~EmHostTransportSerial (void);
+
+ ErrCode OpenCommPort (const EmTransportSerial::ConfigSerial&);
+ ErrCode CreateCommThreads (const EmTransportSerial::ConfigSerial&);
+ ErrCode DestroyCommThreads (void);
+ ErrCode CloseCommPort (void);
+
+ // Manage data coming in the host serial port.
+ void PutIncomingData (const void*, long&);
+ void GetIncomingData (void*, long&);
+ long IncomingDataSize (void);
+
+ // Manage data going out the host serial port.
+ void PutOutgoingData (const void*, long&);
+ void GetOutgoingData (void*, long&);
+ long OutgoingDataSize (void);
+
+ static void* CommRead (void*);
+ static void* CommWrite (void*);
+
+ int GetBaud (EmTransportSerial::Baud);
+ int GetDataBits (EmTransportSerial::DataBits);
+
+ public:
+ omni_thread* fReadThread;
+ omni_thread* fWriteThread;
+
+ int fCommHandle;
+ int fCommSignalPipeA;
+ int fCommSignalPipeB;
+ int fTimeToQuit;
+ omni_mutex fDataMutex;
+ omni_condition fDataCondition;
+
+ omni_mutex fReadMutex;
+ deque<char> fReadBuffer;
+
+ omni_mutex fWriteMutex;
+ deque<char> fWriteBuffer;
+};
+
+#endif /* EmTransportSerialUnix_h */
diff --git a/SrcUnix/EmTransportUSBUnix.cpp b/SrcUnix/EmTransportUSBUnix.cpp
new file mode 100644
index 0000000..f8867a0
--- /dev/null
+++ b/SrcUnix/EmTransportUSBUnix.cpp
@@ -0,0 +1,394 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmTransportUSBUnix.h"
+
+#include "EmTransportSerial.h" // EmTransportSerial
+#include "Logging.h" // LogSerial, LogAppendMsg
+
+#define PRINTF if (!LogSerial ()) ; else LogAppendMsg
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostHasUSB
+ *
+ * DESCRIPTION: Return whether or not USB facilities are available.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if the host has a USB port and we can use it.
+ * False otherwise.
+ *
+ ***********************************************************************/
+
+Bool EmTransportUSB::HostHasUSB (void)
+{
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostConstruct
+ *
+ * DESCRIPTION: Construct platform-specific objects/data.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The platform-specific serial object.
+ *
+ ***********************************************************************/
+
+void EmTransportUSB::HostConstruct (void)
+{
+ fHost = new EmHostTransportUSB;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostDestruct
+ *
+ * DESCRIPTION: Destroy platform-specific objects/data.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void EmTransportUSB::HostDestruct (void)
+{
+ delete fHost;
+ fHost = NULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostOpen
+ *
+ * DESCRIPTION: Open the serial port in a platform-specific fashion.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::HostOpen (void)
+{
+ fHost->fOpenLocally = true;
+
+ fHost->UpdateOpenState ();
+
+ return errNone;
+
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostClose
+ *
+ * DESCRIPTION: Close the serial port in a platform-specific fashion.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::HostClose (void)
+{
+ fHost->fOpenLocally = false;
+ fHost->fOpenRemotely = false;
+
+ ErrCode err = fHost->fSerialTransport->Close ();
+
+ return err;
+
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostRead
+ *
+ * DESCRIPTION: Read bytes from the port in a platform-specific fashion.
+ *
+ * PARAMETERS: len - maximum number of bytes to read.
+ * data - buffer to receive the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually read is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::HostRead (long& len, void* data)
+{
+ ErrCode err = serErrTimeOut;
+ len = 0;
+
+ fHost->UpdateOpenState ();
+
+ if (!fHost->FakeOpenConnection ())
+ {
+ err = fHost->fSerialTransport->Read (len, data);
+
+ if (err)
+ {
+ fHost->fOpenRemotely = false;
+ fHost->fSerialTransport->Close (); // Close it
+ }
+ }
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostWrite
+ *
+ * DESCRIPTION: Write bytes to the port in a platform-specific fashion.
+ *
+ * PARAMETERS: len - number of bytes in the buffer.
+ * data - buffer containing the bytes.
+ *
+ * RETURNED: 0 if no error. The number of bytes actually written is
+ * returned in len if there was no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::HostWrite (long& len, const void* data)
+{
+ ErrCode err = errNone;
+ len = 0;
+
+ fHost->UpdateOpenState ();
+
+ if (!fHost->FakeOpenConnection ())
+ {
+ err = fHost->fSerialTransport->Write (len, data);
+
+ if (err)
+ {
+ fHost->fOpenRemotely = false;
+ fHost->fSerialTransport->Close (); // Close it
+ }
+ }
+
+ return err;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostCanRead
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a read operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there are
+ * actually any bytes available to be read.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportUSB::HostCanRead (void)
+{
+ return fHost->fOpenLocally && fHost->fOpenRemotely;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostCanWrite
+ *
+ * DESCRIPTION: Return whether or not the transport is available for
+ * a write operation (that is, it's connected to another
+ * entity). Does NOT indicate whether or not there is
+ * actually any room in the transport's internal buffer
+ * for the data being written.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if so.
+ *
+ ***********************************************************************/
+
+Bool EmTransportUSB::HostCanWrite (void)
+{
+ return fHost->fOpenLocally && fHost->fOpenRemotely;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostBytesInBuffer
+ *
+ * DESCRIPTION: Returns the number of bytes that can be read with the
+ * Read method. Note that bytes may be received in
+ * between the time BytesInBuffer is called and the time
+ * Read is called, so calling the latter with the result
+ * of the former is not guaranteed to fetch all received
+ * and buffered bytes.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Number of bytes that can be read.
+ *
+ ***********************************************************************/
+
+long EmTransportUSB::HostBytesInBuffer (long minBytes)
+{
+ long bytesRead = 0;
+
+ fHost->UpdateOpenState ();
+
+ if (!fHost->FakeOpenConnection ())
+ {
+ try
+ {
+ bytesRead = fHost->fSerialTransport->BytesInBuffer (minBytes);
+ }
+ catch (ErrCode)
+ {
+ fHost->fOpenRemotely = false;
+ fHost->fSerialTransport->Close ();
+ }
+ }
+
+ return bytesRead;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmTransportUSB::HostSetConfig
+ *
+ * DESCRIPTION: Configure the serial port in a platform-specific
+ * fasion. The port is assumed to be open.
+ *
+ * PARAMETERS: config - configuration information.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+ErrCode EmTransportUSB::HostSetConfig (const ConfigUSB& /*config*/)
+{
+ ErrCode result = errNone;
+
+ return result;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportUSB c'tor
+ *
+ * DESCRIPTION: Constructor. Initialize our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmHostTransportUSB::EmHostTransportUSB (void) :
+ fOpenLocally (false),
+ fOpenRemotely (false),
+ fSerialTransport (NULL)
+{
+ EmTransportSerial::ConfigSerial config;
+
+ config.fPort = "USB";
+
+ fSerialTransport = dynamic_cast<EmTransportSerial*> (config.NewTransport ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportUSB d'tor
+ *
+ * DESCRIPTION: Destructor. Delete our data members.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+EmHostTransportUSB::~EmHostTransportUSB (void)
+{
+ delete fSerialTransport;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportUSB::UpdateOpenState
+ *
+ * DESCRIPTION: If we want the serial port transport open, and it's not
+ * open, then try opening it.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: 0 if no error.
+ *
+ ***********************************************************************/
+
+void EmHostTransportUSB::UpdateOpenState (void)
+{
+ // If we need to open the USB driver and haven't done so, yet, then
+ // try to do so.
+
+ if (fOpenLocally && // Do we need the USB driver open?
+ !fOpenRemotely && // Is it closed?
+ fSerialTransport->Open () == errNone) // Could we open it?
+ {
+ fOpenRemotely = true; // Say it's open
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmHostTransportUSB::FakeOpenConnection
+ *
+ * DESCRIPTION: If we've asked the driver to be open, but could not do
+ * so because the USB device is not online, then try to
+ * pretend that we're talking with a non-responsive serial
+ * device.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: True if HostOpen has been called, but the USB device is
+ * not yet online and we haven't been able to call Open on
+ * the underlying serial transport. False otherwise.
+ *
+ ***********************************************************************/
+
+Bool EmHostTransportUSB::FakeOpenConnection (void)
+{
+ return fOpenLocally && !fOpenRemotely;
+}
diff --git a/SrcUnix/EmTransportUSBUnix.h b/SrcUnix/EmTransportUSBUnix.h
new file mode 100644
index 0000000..32ccfd6
--- /dev/null
+++ b/SrcUnix/EmTransportUSBUnix.h
@@ -0,0 +1,36 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmTransportUSBUnix_h
+#define EmTransportUSBUnix_h
+
+#include "EmTransportUSB.h"
+
+class EmTransportSerial;
+
+class EmHostTransportUSB
+{
+ public:
+ EmHostTransportUSB (void);
+ ~EmHostTransportUSB (void);
+
+ void UpdateOpenState (void);
+ Bool FakeOpenConnection (void);
+
+ public:
+ Bool fOpenLocally;
+ Bool fOpenRemotely;
+ EmTransportSerial* fSerialTransport;
+};
+
+#endif /* EmTransportUSBUnix_h */
diff --git a/SrcUnix/EmWindowFltk.cpp b/SrcUnix/EmWindowFltk.cpp
new file mode 100644
index 0000000..ebf2ca7
--- /dev/null
+++ b/SrcUnix/EmWindowFltk.cpp
@@ -0,0 +1,777 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmWindowFltk.h"
+
+#include "EmApplication.h" // gApplication
+#include "EmCommands.h" // EmCommandID
+#include "EmDocument.h" // EmDocument
+#include "EmMenusFltk.h" // HostCreatePopupMenu
+#include "EmPixMapUnix.h" // ConvertPixMapToHost
+#include "EmScreen.h" // EmScreenUpdateInfo
+#include "EmSession.h" // EmKeyEvent, EmButtonEvent
+#include "EmWindow.h" // EmWindow
+#include "Platform.h" // Platform::AllocateMemory
+
+#include <FL/Fl.H> // Fl::event_x, event_y
+#include <FL/Fl_Box.H> // Fl_Box
+#include <FL/Fl_Image.H> // Fl_Image::draw
+#include <FL/Fl_Menu_Button.H> // popup
+#include <FL/fl_draw.H> // fl_color
+
+#include <ctype.h> // isprint, isxdigit
+
+#include "DefaultSmall.xpm"
+#include "DefaultLarge.xpm"
+
+const int kDefaultWidth = 220;
+const int kDefaultHeight = 330;
+
+#if FL_MAJOR_VERSION == 1 && FL_MINOR_VERSION == 0
+// FLTK 1.0.x had no separate Fl_RGB_Image subclass of Fl_Image.
+#define Fl_RGB_Image Fl_Image
+#endif
+
+EmWindowFltk* gHostWindow;
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindow::NewWindow
+// ---------------------------------------------------------------------------
+
+EmWindow* EmWindow::NewWindow (void)
+{
+ // This is the type of window we should create. However, on Unix, we
+ // create one and only one window when we create the application. This
+ // method -- called by the document to create its window -- therefore
+ // doesn't need to actually create a window.
+
+// return new EmWindowFltk;
+
+ EmAssert (gHostWindow != NULL);
+ return NULL;
+}
+
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::EmWindowFltk
+// ---------------------------------------------------------------------------
+
+EmWindowFltk::EmWindowFltk (void) :
+ Fl_Window (kDefaultWidth, kDefaultHeight, "pose"),
+ EmWindow (),
+ fMessage (NULL),
+ fCachedSkin (NULL)
+{
+ EmAssert (gHostWindow == NULL);
+ gHostWindow = this;
+
+ this->box (FL_FLAT_BOX);
+ this->color (fl_gray_ramp (FL_NUM_GRAY - 1));
+
+ // Install a function to get called when the window is closed
+ // via a WM_DELETE_WINDOW message.
+
+ this->callback (&EmWindowFltk::CloseCallback, NULL);
+
+ // Ensure that the user can't resize this window.
+
+ this->resizable (NULL);
+
+ // Create the message to display when there's no session running.
+
+ fMessage = new Fl_Box (0, 0, 200, 40,
+ "Right click on this window to show a menu of commands.");
+ fMessage->box (FL_NO_BOX);
+ fMessage->align (FL_ALIGN_CENTER | FL_ALIGN_WRAP | FL_ALIGN_INSIDE);
+
+ this->end ();
+
+ this->redraw (); // Redraw help message
+
+ // Set the X-Windows window class. Normally, this is done when
+ // Fl_Window::show (argc, argv) is called (in main()). However, the
+ // EmWindow class gets in the way and automatically shows the host
+ // window by calling Fl_Window::show(). The latter does not set the
+ // window class. And even when the other "show" method is called later,
+ // the damage is done: the X Windows window is already created with a
+ // NULL window class.
+ //
+ // Setting the window class to the title of the window is a workaround
+ // at best. In previous versions of Poser, the window class would be
+ // set to the name of the executable. These should both be "pose",
+ // but it's possible for them to be different.
+
+ this->xclass (this->label ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::~EmWindowFltk
+// ---------------------------------------------------------------------------
+
+EmWindowFltk::~EmWindowFltk (void)
+{
+ this->PreDestroy ();
+
+ // Get rid of the cached skin.
+
+ this->CacheFlush ();
+
+ EmAssert (gHostWindow == this);
+ gHostWindow = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::CloseCallback
+// ---------------------------------------------------------------------------
+// When receiving the WM_CLOSE message on Windows or the WM_DELETE_WINDOW
+// message on X, FLTK calls Fl::handle with the FL_CLOSE message. Fl::handle
+// handles this message not by passing it to Fl_Window::handle, but by calling
+// the window's installed callback function. By default, the callback
+// function hides the window (presumably so that a main event loop would know
+// it was time to quit by checking the window's visiblity). We override that
+// behavior in order to treat the FL_CLOSE message in the same way as handling
+// a Quit menu selection.
+
+void EmWindowFltk::CloseCallback (Fl_Widget*, void*)
+{
+ gApplication->HandleCommand (kCommandQuit);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::draw
+// ---------------------------------------------------------------------------
+
+void EmWindowFltk::draw (void)
+{
+ if (gDocument)
+ {
+ this->HandleUpdate ();
+ }
+ else
+ {
+ fl_color (255, 255, 255);
+ fl_rect (0, 0, this->w (), this->h ());
+
+ fMessage->position (
+ (this->w () - fMessage->w ()) / 2,
+ (this->h () - fMessage->h ()) / 3);
+ this->draw_child (*fMessage);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::handle
+// ---------------------------------------------------------------------------
+
+int EmWindowFltk::handle (int event)
+{
+ EmPoint where (Fl::event_x(), Fl::event_y());
+
+ switch (event)
+ {
+ case FL_PUSH:
+ if (Fl::event_button () == 3)
+ {
+ this->PopupMenu ();
+ return 1;
+ }
+ // Fall through...
+
+ case FL_DRAG:
+ this->HandlePenEvent (where, true);
+ return 1;
+
+ case FL_RELEASE:
+ this->HandlePenEvent (where, false);
+ return 1;
+
+/*
+ These don't seem to get called when we want them to...
+
+ case FL_ACTIVATE:
+ this->HandleActivate (true);
+ return 1;
+
+ case FL_DEACTIVATE:
+ this->HandleActivate (false);
+ return 1;
+*/
+
+ case FL_FOCUS:
+ this->HandleActivate (true);
+ return 1;
+
+ case FL_UNFOCUS:
+ this->HandleActivate (false);
+ return 1;
+
+ case FL_SHORTCUT:
+ {
+ if (Fl::test_shortcut (FL_F + 10 | FL_SHIFT))
+ {
+ this->PopupMenu ();
+ return 1;
+ }
+
+ Fl_Menu_Item_List hostMenu;
+ this->GetHostMenu (hostMenu);
+
+ const Fl_Menu_Item* selected = hostMenu[0].test_shortcut ();
+ if (selected)
+ {
+ this->DoMenuCommand (*selected);
+ return 1;
+ }
+
+ return 0;
+ }
+
+ case FL_KEYBOARD:
+ if (Fl::event_state (FL_ALT | FL_META))
+ {
+ // Reserved for shortcuts
+ return 0;
+ }
+
+ if (gDocument != NULL)
+ {
+ // Handle printable characters.
+
+ if (strlen (Fl::event_text ()) > 0)
+ {
+ int key = (unsigned char) Fl::event_text()[0];
+ EmKeyEvent event (key);
+ // !!! Need to get modifiers
+ gDocument->HandleKey (event);
+ return 1;
+ }
+
+ // Handle all other characters.
+
+ int c = Fl::event_key ();
+
+ struct KeyConvert
+ {
+ int fEventKey;
+ SkinElementType fButton;
+ int fKey;
+ };
+
+ KeyConvert kConvert[] =
+ {
+ { FL_Enter, kElement_None, chrLineFeed },
+ { FL_KP_Enter, kElement_None, chrLineFeed },
+ { FL_Left, kElement_None, leftArrowChr },
+ { FL_Right, kElement_None, rightArrowChr },
+ { FL_Up, kElement_None, upArrowChr },
+ { FL_Down, kElement_None, downArrowChr },
+ { FL_F + 1, kElement_App1Button },
+ { FL_F + 2, kElement_App2Button },
+ { FL_F + 3, kElement_App3Button },
+ { FL_F + 4, kElement_App4Button },
+ { FL_F + 9, kElement_PowerButton },
+ { FL_Page_Up, kElement_UpButton },
+ { FL_Page_Down, kElement_DownButton }
+ };
+
+ for (size_t ii = 0; ii < countof (kConvert); ++ii)
+ {
+ if (c == kConvert[ii].fEventKey)
+ {
+ if (kConvert[ii].fButton != kElement_None)
+ {
+ gDocument->HandleButton (kConvert[ii].fButton, true);
+ gDocument->HandleButton (kConvert[ii].fButton, false);
+ return 1;
+ }
+
+ if (kConvert[ii].fKey)
+ {
+ EmKeyEvent event (kConvert[ii].fKey);
+ // !!! Need to get modifiers
+ gDocument->HandleKey (event);
+ return 1;
+ }
+ }
+ }
+
+ if (c == FL_F + 10)
+ {
+ this->PopupMenu ();
+ return 1;
+ }
+
+ if (c < 0x100)
+ {
+ EmKeyEvent event (c);
+ // !!! Need to get modifiers
+ gDocument->HandleKey (event);
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ return Fl_Window::handle (event);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::PopupMenu
+// ---------------------------------------------------------------------------
+
+void EmWindowFltk::PopupMenu (void)
+{
+ // Get the menu.
+
+ Fl_Menu_Item_List hostMenu;
+ this->GetHostMenu (hostMenu);
+
+ const Fl_Menu_Item* item = hostMenu[0].popup (Fl::event_x (), Fl::event_y ());
+ if (item)
+ {
+ this->DoMenuCommand (*item);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::GetHostMenu
+// ---------------------------------------------------------------------------
+
+void EmWindowFltk::GetHostMenu (Fl_Menu_Item_List& hostMenu)
+{
+ EmMenu* menu = ::MenuFindMenu (kMenuPopupMenuPreferred);
+ EmAssert (menu);
+
+ ::MenuUpdateMruMenus (*menu);
+ ::MenuUpdateMenuItemStatus (*menu);
+ ::HostCreatePopupMenu (*menu, hostMenu);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::DoMenuCommand
+// ---------------------------------------------------------------------------
+
+void EmWindowFltk::DoMenuCommand (const Fl_Menu_Item& item)
+{
+ EmCommandID id = (EmCommandID) item.argument ();
+
+ if (gDocument)
+ if (gDocument->HandleCommand (id))
+ return;
+
+ if (gApplication)
+ if (gApplication->HandleCommand (id))
+ return;
+
+ EmAssert (false);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::CacheFlush
+// ---------------------------------------------------------------------------
+
+void EmWindowFltk::CacheFlush (void)
+{
+ delete fCachedSkin;
+ fCachedSkin = NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::CacheFlush
+// ---------------------------------------------------------------------------
+
+Fl_Image* EmWindowFltk::GetSkin (void)
+{
+ if (!fCachedSkin)
+ {
+ const EmPixMap& p = this->GetCurrentSkin ();
+ EmPoint size = p.GetSize ();
+
+ fCachedSkin = new Fl_RGB_Image ((uchar*) p.GetBits (), size.fX, size.fY,
+ 3, p.GetRowBytes ());
+ }
+
+ EmAssert (fCachedSkin);
+
+ return fCachedSkin;
+}
+
+#pragma mark -
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowReset
+// ---------------------------------------------------------------------------
+// Update the window's appearance due to a skin change.
+
+void EmWindowFltk::HostWindowReset (void)
+{
+ // Delete te old image.
+
+ this->CacheFlush ();
+
+ // Change the window to accomodate the settings and bitmap.
+
+ // Get the desired client size.
+
+ EmRect newBounds = this->GetCurrentSkinRegion ().Bounds ();
+ EmCoord w = newBounds.Width ();
+ EmCoord h = newBounds.Height ();
+
+ // Protect against this function being called when their's
+ // no established skin.
+
+ if (w == 0)
+ w = kDefaultWidth;
+
+ if (h == 0)
+ h = kDefaultHeight;
+
+ // Resize the window.
+
+ this->size (w, h);
+ this->size_range (w, h, w, h);
+
+ // Invalidate the window contents now (necessary?).
+
+ this->redraw ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostMouseCapture
+// ---------------------------------------------------------------------------
+// Capture the mouse so that all mouse events get sent to this window.
+
+void EmWindowFltk::HostMouseCapture (void)
+{
+ Fl::grab (this);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostMouseRelease
+// ---------------------------------------------------------------------------
+// Release the mouse so that mouse events get sent to the window the
+// cursor is over.
+
+void EmWindowFltk::HostMouseRelease (void)
+{
+ Fl::grab (NULL);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostDrawingBegin
+// ---------------------------------------------------------------------------
+// Prepare the host window object for drawing outside of an update event.
+
+void EmWindowFltk::HostDrawingBegin (void)
+{
+ this->make_current ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowMoveBy
+// ---------------------------------------------------------------------------
+// Move the host window object by the given offset.
+
+void EmWindowFltk::HostWindowMoveBy (const EmPoint& offset)
+{
+ this->HostWindowMoveTo (this->HostWindowBoundsGet ().TopLeft () + offset);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowMoveTo
+// ---------------------------------------------------------------------------
+// Move the host window object to the given location.
+
+void EmWindowFltk::HostWindowMoveTo (const EmPoint& loc)
+{
+ this->position (loc.fX, loc.fY);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowBoundsGet
+// ---------------------------------------------------------------------------
+// Get the global bounds of the host window object.
+
+EmRect EmWindowFltk::HostWindowBoundsGet (void)
+{
+ return EmRect (
+ this->x (),
+ this->y (),
+ this->x () + this->w (),
+ this->y () + this->h ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowCenter
+// ---------------------------------------------------------------------------
+// Center the window to the main display.
+
+void EmWindowFltk::HostWindowCenter (void)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostWindowShow
+// ---------------------------------------------------------------------------
+// Make the host window object visible.
+
+void EmWindowFltk::HostWindowShow (void)
+{
+
+ this->show ();
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostRectFrame
+// ---------------------------------------------------------------------------
+// Draw a rectangle frame with the given width in the given color.
+
+void EmWindowFltk::HostRectFrame (const EmRect& r, const EmPoint& pen, const RGBType& color)
+{
+ EmRect r2 (r);
+ fl_color (color.fRed, color.fGreen, color.fBlue);
+
+ // !!! This could be changed to not assume a square pen, but since
+ // we're kind of tied to that on Windows right now, that's the
+ // assumption we'll make.
+
+ for (EmCoord size = 0; size < pen.fX; ++size)
+ {
+ fl_rect (r2.fLeft, r2.fTop, r2.Width (), r2.Height ());
+ r2.Inset (1, 1);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostOvalPaint
+// ---------------------------------------------------------------------------
+// Fill an oval with the given color.
+
+void EmWindowFltk::HostOvalPaint (const EmRect& r, const RGBType& color)
+{
+ fl_color (color.fRed, color.fGreen, color.fBlue);
+ fl_pie (r.fLeft, r.fTop, r.Width (), r.Height (), 0, 360);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostPaintCase
+// ---------------------------------------------------------------------------
+// Draw the skin.
+
+void EmWindowFltk::HostPaintCase (const EmScreenUpdateInfo&)
+{
+ Fl_Image* skin = this->GetSkin ();
+ skin->draw (0, 0);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostPaintLCD
+// ---------------------------------------------------------------------------
+// Draw the LCD area. info contains the raw LCD data, including a partically
+// updated fImage, and fFirstList and fLastLine which indicate the valid
+// range of the image. srcRect and destRect also indicate the range that
+// needs to be updated, and have also been scaled appropriately. scaled is
+// true if we need to scale info.fImage during the process of converting it
+// to a host pixmap.
+
+void EmWindowFltk::HostPaintLCD (const EmScreenUpdateInfo& info, const EmRect& srcRect,
+ const EmRect& destRect, Bool scaled)
+{
+ // Determine the buffer size and allocate it.
+ // We assume that ConvertPixMapToHost is converting to 24-bit RGB.
+
+ int rowBytes = srcRect.fRight * 3;
+ int bufferSize = srcRect.fBottom * rowBytes;
+ uchar* buffer = (uchar*) Platform::AllocateMemory (bufferSize);
+
+ // Convert the image, scaling along the way.
+
+ ::ConvertPixMapToHost (info.fImage, buffer,
+ info.fFirstLine, info.fLastLine, scaled);
+
+ // Draw the converted image.
+
+ fl_draw_image (buffer + srcRect.fTop * rowBytes,
+ destRect.fLeft, destRect.fTop,
+ destRect.Width (), destRect.Height ());
+
+ // Clean up.
+
+ Platform::DisposeMemory (buffer);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostGetDefaultSkin
+// ---------------------------------------------------------------------------
+// Get the default (built-in) skin image.
+
+void EmWindowFltk::HostGetDefaultSkin (EmPixMap& pixMap, int scale)
+{
+ char** xpm = (scale == 2) ? DefaultLarge : DefaultSmall;
+
+ /*
+ An XPM file is an array of strings composed of four sections:
+
+ <Values>
+ <Colors>
+ <Pixels>
+ <Extensions>
+
+ Each string is composed of words separated by spaces.
+ */
+
+ /*
+ <Values> is a string containing four or six integers in base
+ 10 that correspond to width, height, number of colors, number
+ of characters per pixel, and (optionally) hotspot location.
+ */
+
+ int w = 0;
+ int h = 0;
+ int num_colors = 0;
+ int cpp = 0;
+ int hot_x = 0;
+ int hot_y = 0;
+ int i = sscanf (xpm [0], "%d %d %d %d %d %d", &w, &h, &num_colors,
+ &cpp, &hot_x, &hot_y);
+
+ EmAssert (i == 4);
+ EmAssert (w > 0);
+ EmAssert (h > 0);
+ EmAssert (num_colors > 0);
+ EmAssert (cpp == 1);
+ EmAssert (hot_x == 0);
+ EmAssert (hot_y == 0);
+
+ /*
+ <Colors> contains as many lines as there are colors. Each string
+ contains the following words:
+
+ <color_code> {<key> <color>}+
+ */
+
+ RGBType colorMap[0x80];
+
+ for (int color_num = 0; color_num < num_colors; ++color_num)
+ {
+ const char* this_line = xpm [1 + color_num];
+ int color_code = this_line[0];
+ char key[3] = {0};
+ char color[8] = {0};
+
+ i = sscanf (this_line + 1 + 1, "%s %s", key, color);
+
+ EmAssert (i == 2);
+ EmAssert (strlen (key) == 1);
+ EmAssert (strlen (color) == 7);
+ EmAssert (key[0] == 'c');
+ EmAssert (color[0] == '#');
+ EmAssert (isxdigit (color[1]));
+ EmAssert (isxdigit (color[2]));
+ EmAssert (isxdigit (color[3]));
+ EmAssert (isxdigit (color[4]));
+ EmAssert (isxdigit (color[5]));
+ EmAssert (isxdigit (color[6]));
+
+ int r, g, b;
+ i = sscanf (color, "#%2x%2x%2x", &r, &g, &b);
+
+ EmAssert (i == 3);
+ EmAssert (isprint (color_code));
+
+ colorMap [color_code] = RGBType (r, g, b);
+ }
+
+ /*
+ <Pixels> contains "h" lines, each containing cpp * "w"
+ characters in them. Each set of cpp characters maps to
+ one of the colors in the <Colors> array.
+ */
+
+ uint8* buffer = (uint8*) Platform::AllocateMemory (w * h * 3);
+ uint8* dest = buffer;
+
+ for (int yy = 0; yy < h; ++yy)
+ {
+ char* src = xpm [1 + num_colors + yy];
+
+ for (int xx = 0; xx < w; ++xx)
+ {
+ int color_code = *src++;
+ EmAssert (isprint (color_code));
+
+ const RGBType& rgb = colorMap [color_code];
+
+ *dest++ = rgb.fRed;
+ *dest++ = rgb.fGreen;
+ *dest++ = rgb.fBlue;
+ }
+ }
+
+ EmAssert ((dest - buffer) <= (w * h * 3));
+
+ // We now have the data in RGB format. Wrap it up in a temporary
+ // EmPixMap so that we can copy it into the result EmPixMap.
+
+ EmPixMap wrapper;
+
+ wrapper.SetSize (EmPoint (w, h));
+ wrapper.SetFormat (kPixMapFormat24RGB);
+ wrapper.SetRowBytes (w * 3);
+ wrapper.SetBits (buffer);
+
+ // Copy the data to the destination.
+
+ pixMap = wrapper;
+
+ // Clean up.
+
+ Platform::DisposeMemory (buffer);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmWindowFltk::HostGetCurrentMouse
+// ---------------------------------------------------------------------------
+// Get the current mouse location.
+
+EmPoint EmWindowFltk::HostGetCurrentMouse (void)
+{
+ return EmPoint (Fl::event_x (), Fl::event_y ());
+}
diff --git a/SrcUnix/EmWindowFltk.h b/SrcUnix/EmWindowFltk.h
new file mode 100644
index 0000000..2d2ef06
--- /dev/null
+++ b/SrcUnix/EmWindowFltk.h
@@ -0,0 +1,78 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef EmWindowFltk_h
+#define EmWindowFltk_h
+
+#include "EmWindow.h" // EmWindow
+
+#include <FL/Fl_Window.H> // Fl_Window
+#include <vector>
+
+class Fl_Box;
+class Fl_Image;
+class Fl_Menu_Item;
+typedef vector<Fl_Menu_Item> Fl_Menu_Item_List;
+
+class EmWindowFltk : public Fl_Window, public EmWindow
+{
+ public:
+ EmWindowFltk (void);
+ virtual ~EmWindowFltk (void);
+
+ void PopupMenu (void);
+ void GetHostMenu (Fl_Menu_Item_List&);
+ void DoMenuCommand (const Fl_Menu_Item&);
+
+ void CacheFlush (void);
+ Fl_Image* GetSkin (void);
+
+ private:
+ virtual void draw (void);
+ virtual int handle (int event);
+ static void CloseCallback (Fl_Widget*, void*);
+
+ private:
+ virtual void HostWindowReset (void);
+
+ virtual void HostMouseCapture (void);
+ virtual void HostMouseRelease (void);
+
+ virtual void HostDrawingBegin (void);
+
+ virtual void HostWindowMoveBy (const EmPoint&);
+ virtual void HostWindowMoveTo (const EmPoint&);
+ virtual EmRect HostWindowBoundsGet (void);
+ virtual void HostWindowCenter (void);
+ virtual void HostWindowShow (void);
+
+ virtual void HostRectFrame (const EmRect&, const EmPoint&, const RGBType&);
+ virtual void HostOvalPaint (const EmRect&, const RGBType&);
+
+ virtual void HostPaintCase (const EmScreenUpdateInfo&);
+ virtual void HostPaintLCD (const EmScreenUpdateInfo& info,
+ const EmRect& srcRect,
+ const EmRect& destRect,
+ Bool scaled);
+
+ virtual void HostGetDefaultSkin (EmPixMap&, int scale);
+ virtual EmPoint HostGetCurrentMouse (void);
+
+ private:
+ Fl_Box* fMessage;
+ Fl_Image* fCachedSkin;
+};
+
+extern EmWindowFltk* gHostWindow;
+
+#endif // EmWindowFltk_h
diff --git a/SrcUnix/Platform_Unix.cpp b/SrcUnix/Platform_Unix.cpp
new file mode 100644
index 0000000..9f9a918
--- /dev/null
+++ b/SrcUnix/Platform_Unix.cpp
@@ -0,0 +1,850 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "Platform.h"
+
+#include "ErrorHandling.h" // Errors::ThrowIfNULL
+#include "Miscellaneous.h" // StMemory
+//#include "PreferenceMgr.h"
+#include "ResStrings.h"
+#include "SessionFile.h"
+#include "Strings.r.h" // kStr_ ...
+
+#include <errno.h> // EPERM, ENOENT, etc.
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h> // mkdir
+#include <time.h>
+#include <ctype.h>
+
+#include "omnithread.h" // omni_mutex
+#include <FL/x.H> // XKeyboardControl
+#include <FL/Fl.H> // Fl::args
+
+
+// ===========================================================================
+// ¥ Globals
+// ===========================================================================
+
+ByteList gClipboardDataPalm;
+ByteList gClipboardDataHost;
+omni_mutex gClipboardMutex;
+omni_condition gClipboardCondition (&gClipboardMutex);
+Bool gClipboardHaveOutgoingData;
+Bool gClipboardNeedIncomingData;
+Bool gClipboardPendingIncomingData;
+Bool gClipboardHaveIncomingData;
+
+long long PrvGetMicroseconds (void)
+{
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+
+ long long usecs = ((long long) tv.tv_sec) * 1000000ULL + tv.tv_usec;
+
+ return usecs;
+}
+
+
+// ===========================================================================
+// ¥ Platform
+// ===========================================================================
+
+#ifndef __QNXNTO__
+// Compare lexigraphically two strings
+
+int _stricmp( const char *s1, const char *s2 )
+{
+ return strcasecmp( s1, s2 );
+}
+
+int _strnicmp( const char *s1, const char *s2, int n )
+{
+ return strncasecmp( s1, s2, n );
+}
+
+char* _strdup( const char *s )
+{
+ return strdup( s );
+}
+#endif
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Initialize
+// ---------------------------------------------------------------------------
+// Initializes platform-dependent stuff.
+
+void Platform::Initialize( void )
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Reset
+// ---------------------------------------------------------------------------
+
+void Platform::Reset( void )
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Save
+// ---------------------------------------------------------------------------
+
+void Platform::Save(SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Load
+// ---------------------------------------------------------------------------
+
+void Platform::Load(SessionFile&)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Dispose
+// ---------------------------------------------------------------------------
+
+void Platform::Dispose( void )
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::GetString
+// ---------------------------------------------------------------------------
+
+string Platform::GetString( StrCode id )
+{
+ const char* str = _ResGetString (id);
+ if (str)
+ return string (str);
+
+ char buffer[20];
+ sprintf (buffer, "%ld", (long) id);
+ return string ("<missing string ") + buffer + ">";
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::GetIDForError
+// ---------------------------------------------------------------------------
+
+int Platform::GetIDForError( ErrCode error )
+{
+ switch (error)
+ {
+ // From /usr/include/asm/errno.h
+
+ case EPERM: break; // 1 /* Operation not permitted */
+ case ENOENT: return kStr_FileNotFound; // 2 /* No such file or directory */
+ case ESRCH: break; // 3 /* No such process */
+ case EINTR: break; // 4 /* Interrupted system call */
+ case EIO: return kStr_IOError; // 5 /* I/O error */
+ case ENXIO: break; // 6 /* No such device or address */
+ case E2BIG: break; // 7 /* Arg list too long */
+ case ENOEXEC: break; // 8 /* Exec format error */
+ case EBADF: break; // 9 /* Bad file number */
+ case ECHILD: break; // 10 /* No child processes */
+ case EAGAIN: break; // 11 /* Try again */
+ case ENOMEM: return kStr_MemFull; // 12 /* Out of memory */
+ case EACCES: return kStr_SerialPortBusy; // 13 /* Permission denied */
+ case EFAULT: break; // 14 /* Bad address */
+ case ENOTBLK: break; // 15 /* Block device required */
+ case EBUSY: return kStr_FileBusy; // 16 /* Device or resource busy */
+ case EEXIST: return kStr_DuplicateFileName; // 17 /* File exists */
+ case EXDEV: break; // 18 /* Cross-device link */
+ case ENODEV: return kStr_DiskMissing; // 19 /* No such device */
+ case ENOTDIR: break; // 20 /* Not a directory */
+ case EISDIR: break; // 21 /* Is a directory */
+ case EINVAL: break; // 22 /* Invalid argument */
+ case ENFILE: break; // 23 /* File table overflow */
+ case EMFILE: return kStr_TooManyFilesOpen; // 24 /* Too many open files */
+ case ENOTTY: break; // 25 /* Not a typewriter */
+ case ETXTBSY: return kStr_FileBusy; // 26 /* Text file busy */
+ case EFBIG: break; // 27 /* File too large */
+ case ENOSPC: return kStr_DiskFull; // 28 /* No space left on device */
+ case ESPIPE: break; // 29 /* Illegal seek */
+ case EROFS: return kStr_DiskWriteProtected; // 30 /* Read-only file system */
+ case EMLINK: break; // 31 /* Too many links */
+ case EPIPE: break; // 32 /* Broken pipe */
+ case EDOM: break; // 33 /* Math argument out of domain of func */
+ case ERANGE: break; // 34 /* Math result not representable */
+ case EDEADLK: break; // 35 /* Resource deadlock would occur */
+ case ENAMETOOLONG: return kStr_BadFileName; // 36 /* File name too long */
+
+#if 0
+ // Comment out this whole block. We don't map them to any specific
+ // error messages, and by commenting them out, we protect ourselves
+ // against any Unixen that don't define them.
+
+ case ENOLCK: break; // 37 /* No record locks available */
+ case ENOSYS: break; // 38 /* Function not implemented */
+ case ENOTEMPTY: break; // 39 /* Directory not empty */
+ case ELOOP: break; // 40 /* Too many symbolic links encountered */
+// case EWOULDBLOCK: break; // EAGAIN /* Operation would block */
+ case ENOMSG: break; // 42 /* No message of desired type */
+ case EIDRM: break; // 43 /* Identifier removed */
+ case ECHRNG: break; // 44 /* Channel number out of range */
+ case EL2NSYNC: break; // 45 /* Level 2 not synchronized */
+ case EL3HLT: break; // 46 /* Level 3 halted */
+ case EL3RST: break; // 47 /* Level 3 reset */
+ case ELNRNG: break; // 48 /* Link number out of range */
+ case EUNATCH: break; // 49 /* Protocol driver not attached */
+ case ENOCSI: break; // 50 /* No CSI structure available */
+ case EL2HLT: break; // 51 /* Level 2 halted */
+ case EBADE: break; // 52 /* Invalid exchange */
+ case EBADR: break; // 53 /* Invalid request descriptor */
+ case EXFULL: break; // 54 /* Exchange full */
+ case ENOANO: break; // 55 /* No anode */
+ case EBADRQC: break; // 56 /* Invalid request code */
+ case EBADSLT: break; // 57 /* Invalid slot */
+
+// case EDEADLOCK: break; // EDEADLK
+
+ case EBFONT: break; // 59 /* Bad font file format */
+ case ENOSTR: break; // 60 /* Device not a stream */
+ case ENODATA: break; // 61 /* No data available */
+ case ETIME: break; // 62 /* Timer expired */
+ case ENOSR: break; // 63 /* Out of streams resources */
+ case ENONET: break; // 64 /* Machine is not on the network */
+ case ENOPKG: break; // 65 /* Package not installed */
+ case EREMOTE: break; // 66 /* Object is remote */
+ case ENOLINK: break; // 67 /* Link has been severed */
+ case EADV: break; // 68 /* Advertise error */
+ case ESRMNT: break; // 69 /* Srmount error */
+ case ECOMM: break; // 70 /* Communication error on send */
+ case EPROTO: break; // 71 /* Protocol error */
+ case EMULTIHOP: break; // 72 /* Multihop attempted */
+ case EDOTDOT: break; // 73 /* RFS specific error */
+ case EBADMSG: break; // 74 /* Not a data message */
+ case EOVERFLOW: break; // 75 /* Value too large for defined data type */
+ case ENOTUNIQ: break; // 76 /* Name not unique on network */
+ case EBADFD: break; // 77 /* File descriptor in bad state */
+ case EREMCHG: break; // 78 /* Remote address changed */
+ case ELIBACC: break; // 79 /* Can not access a needed shared library */
+ case ELIBBAD: break; // 80 /* Accessing a corrupted shared library */
+ case ELIBSCN: break; // 81 /* .lib section in a.out corrupted */
+ case ELIBMAX: break; // 82 /* Attempting to link in too many shared libraries */
+ case ELIBEXEC: break; // 83 /* Cannot exec a shared library directly */
+ case EILSEQ: break; // 84 /* Illegal byte sequence */
+ case ERESTART: break; // 85 /* Interrupted system call should be restarted */
+ case ESTRPIPE: break; // 86 /* Streams pipe error */
+ case EUSERS: break; // 87 /* Too many users */
+ case ENOTSOCK: break; // 88 /* Socket operation on non-socket */
+ case EDESTADDRREQ: break; // 89 /* Destination address required */
+ case EMSGSIZE: break; // 90 /* Message too long */
+ case EPROTOTYPE: break; // 91 /* Protocol wrong type for socket */
+ case ENOPROTOOPT: break; // 92 /* Protocol not available */
+ case EPROTONOSUPPORT: break; // 93 /* Protocol not supported */
+ case ESOCKTNOSUPPORT: break; // 94 /* Socket type not supported */
+ case EOPNOTSUPP: break; // 95 /* Operation not supported on transport endpoint */
+ case EPFNOSUPPORT: break; // 96 /* Protocol family not supported */
+ case EAFNOSUPPORT: break; // 97 /* Address family not supported by protocol */
+ case EADDRINUSE: break; // 98 /* Address already in use */
+ case EADDRNOTAVAIL: break; // 99 /* Cannot assign requested address */
+ case ENETDOWN: break; // 100 /* Network is down */
+ case ENETUNREACH: break; // 101 /* Network is unreachable */
+ case ENETRESET: break; // 102 /* Network dropped connection because of reset */
+ case ECONNABORTED: break; // 103 /* Software caused connection abort */
+ case ECONNRESET: break; // 104 /* Connection reset by peer */
+ case ENOBUFS: break; // 105 /* No buffer space available */
+ case EISCONN: break; // 106 /* Transport endpoint is already connected */
+ case ENOTCONN: break; // 107 /* Transport endpoint is not connected */
+ case ESHUTDOWN: break; // 108 /* Cannot send after transport endpoint shutdown */
+ case ETOOMANYREFS: break; // 109 /* Too many references: cannot splice */
+ case ETIMEDOUT: break; // 110 /* Connection timed out */
+ case ECONNREFUSED: break; // 111 /* Connection refused */
+ case EHOSTDOWN: break; // 112 /* Host is down */
+ case EHOSTUNREACH: break; // 113 /* No route to host */
+ case EALREADY: break; // 114 /* Operation already in progress */
+ case EINPROGRESS: break; // 115 /* Operation now in progress */
+ case ESTALE: break; // 116 /* Stale NFS file handle */
+ case EUCLEAN: break; // 117 /* Structure needs cleaning */
+ case ENOTNAM: break; // 118 /* Not a XENIX named type file */
+ case ENAVAIL: break; // 119 /* No XENIX semaphores available */
+ case EISNAM: break; // 120 /* Is a named type file */
+ case EREMOTEIO: break; // 121 /* Remote I/O error */
+ case EDQUOT: break; // 122 /* Quota exceeded */
+
+ case ENOMEDIUM: break; // 123 /* No medium found */
+ case EMEDIUMTYPE: break; // 124 /* Wrong medium type */
+#endif
+ }
+
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::GetIDForRecovery
+// ---------------------------------------------------------------------------
+
+int Platform::GetIDForRecovery( ErrCode error )
+{
+ return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::GetShortVersionString
+// ---------------------------------------------------------------------------
+// Returns a short version string. The format of the string is:
+//
+// #.# (.#) ([dab]#)
+//
+// # = one or more numeric digits
+// . = literal '.'
+// Patterns in parentheses are optional
+// Patterns in brackets mean "one of these characters"
+// Spaces are shown above for clarity; they do not appear in the string
+//
+// Valid strings would be: 2.1d7, 2.1.1b14, 2.99, 2.1.1
+
+string Platform::GetShortVersionString( void )
+{
+ return string("3.5");
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::CopyToClipboard
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Platform::CopyToClipboard (const ByteList& palmChars,
+ const ByteList& hostChars)
+{
+ ByteList palmChars2 (palmChars);
+ ByteList hostChars2 (hostChars);
+
+ // See if any mapping needs to be done.
+
+ if (hostChars2.size () > 0 && palmChars2.size () == 0)
+ {
+ Platform::RemapHostToPalmChars (hostChars2, palmChars2);
+ }
+ else if (palmChars2.size () > 0 && hostChars2.size () == 0)
+ {
+ Platform::RemapPalmToHostChars (palmChars2, hostChars2);
+ }
+
+ omni_mutex_lock lock (gClipboardMutex);
+
+ gClipboardDataPalm = palmChars2;
+ gClipboardDataHost = hostChars2;
+
+ gClipboardHaveOutgoingData = true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::CopyFromClipboard
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Platform::CopyFromClipboard (ByteList& palmChars,
+ ByteList& hostChars)
+{
+ omni_mutex_lock lock (gClipboardMutex);
+
+ gClipboardNeedIncomingData = true;
+ gClipboardHaveIncomingData = false;
+
+ while (!gClipboardHaveIncomingData)
+ gClipboardCondition.wait ();
+
+ // Copy the data to our outgoing lists.
+
+ palmChars = gClipboardDataPalm;
+ hostChars = gClipboardDataHost;
+
+ // See if any mapping needs to be done.
+
+ if (hostChars.size () > 0 && palmChars.size () == 0)
+ {
+ Platform::RemapHostToPalmChars (hostChars, palmChars);
+ }
+ else if (palmChars.size () > 0 && hostChars.size () == 0)
+ {
+ Platform::RemapPalmToHostChars (palmChars, hostChars);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::RemapHostToPalmChars
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Platform::RemapHostToPalmChars (const ByteList& hostChars,
+ ByteList& palmChars)
+{
+ // Converting line endings is all we do for now.
+
+ ByteList::const_iterator iter = hostChars.begin ();
+ while (iter != hostChars.end ())
+ {
+ uint8 ch = *iter++;
+
+ if (ch == 0x0A)
+ {
+ palmChars.push_back (chrLineFeed);
+ }
+ else
+ {
+ palmChars.push_back (ch);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::RemapHostToPalmChars
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Platform::RemapPalmToHostChars (const ByteList& palmChars,
+ ByteList& hostChars)
+{
+ // Converting line endings is all we do for now.
+
+ ByteList::const_iterator iter = palmChars.begin ();
+ while (iter != palmChars.end ())
+ {
+ uint8 ch = *iter++;
+
+ if (ch == chrLineFeed)
+ {
+ hostChars.push_back (0x0A);
+ }
+ else
+ {
+ hostChars.push_back (ch);
+ }
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::PinToScreen
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: True if the rectangle was changed.
+ *
+ ***********************************************************************/
+
+Bool Platform::PinToScreen (EmRect& r)
+{
+ // !!! TBD
+ return false;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ToHostEOL
+ *
+ * DESCRIPTION: Converts a string of characters into another string
+ * where the EOL sequence is consistant for files on the
+ * current platform.
+ *
+ * PARAMETERS: dest - receives the result. The buffer is sized by
+ * this function, so the caller doesn't have to
+ * allocate any space itself.
+ *
+ * destLen - receives the length of the resulting string.
+ *
+ * src - pointer to input characters.
+ *
+ * srcLen - number of characters pointed to by src.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void Platform::ToHostEOL ( StMemory& dest, long& destLen,
+ const char* src, long srcLen)
+{
+ char* d = (char*) Platform::AllocateMemory (srcLen);
+ char* p = d;
+ Bool previousWas0x0D = false;
+
+ for (long ii = 0; ii < srcLen; ++ii)
+ {
+ char ch = src[ii];
+
+ // Convert 0x0D to 0x0A.
+
+ if (ch == 0x0D)
+ {
+ *p++ = 0x0A;
+ }
+
+ // If we're looking at a 0x0A that's part of
+ // a 0x0D/0x0A, just swallow it.
+
+ else if (ch == 0x0A && previousWas0x0D)
+ {
+ // Nothing
+ }
+
+ // Copy all other characters straight through.
+
+ else
+ {
+ *p++ = ch;
+ }
+
+ previousWas0x0D = ch == 0x0D;
+ }
+
+ destLen = p - d;
+ d = (char*) Platform::ReallocMemory (d, destLen);
+ dest.Adopt (d);
+}
+
+
+// -----------------------------------------------------------------------------
+// find the ROM file path embedded in the saved ram image
+
+Bool Platform::ReadROMFileReference (ChunkFile& docFile, EmFileRef& f)
+{
+ // First look for a ROM file path.
+
+ string path;
+ if (docFile.ReadString (SessionFile::kROMUnixPathTag, path))
+ {
+ f = EmFileRef (path);
+ return true;
+ }
+
+ // If a path can't be found, look for a simple ROM name.
+
+ string name;
+ if (docFile.ReadString (SessionFile::kROMNameTag, name))
+ {
+ // !!! TBD
+ }
+
+ return false;
+}
+
+void Platform::WriteROMFileReference (ChunkFile& docFile, const EmFileRef& f)
+{
+ docFile.WriteString (SessionFile::kROMUnixPathTag, f.GetFullPath ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::Delay
+// ---------------------------------------------------------------------------
+// Delay for a time period appropriate for a sleeping 68328.
+
+void Platform::Delay (void)
+{
+ // Delay 10 msecs. Delaying by this amount pauses us 1/100 of a second,
+ // which is the rate at which the device's tickcount counter increments.
+ //
+ // Wait on an event instead of just calling Sleep(10) so that another
+ // thread can wake us up before our time.
+
+ omni_thread::sleep( 0, 10000 ); // 10k nanoseconds = 1/100 sec
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::CycleSlowly
+// ---------------------------------------------------------------------------
+
+void Platform::CycleSlowly (void)
+{
+ // Nothing to do in Unix.
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::RealAllocateMemory
+// ---------------------------------------------------------------------------
+
+void* Platform::RealAllocateMemory (size_t size, Bool clear, const char*, int)
+{
+ void* result;
+
+ if (clear)
+ result = calloc (size, 1);
+ else
+ result = malloc (size);
+
+ Errors::ThrowIfNULL (result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::RealReallocMemory
+// ---------------------------------------------------------------------------
+
+void* Platform::RealReallocMemory (void* p, size_t size, const char*, int)
+{
+ void* result = realloc (p, size);
+
+ Errors::ThrowIfNULL (result);
+
+ return result;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::RealDisposeMemory
+// ---------------------------------------------------------------------------
+
+void Platform::RealDisposeMemory (void* p)
+{
+ if (p)
+ {
+ free (p);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Platform::ForceStartupScreen
+ *
+ * DESCRIPTION: See if the user has requested that the Startup dialog
+ * be presented instead of attempting to use the latest
+ * session file or creation settings.
+ *
+ * The current signal is to toggle the CAPSLOCK key.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: True if the user has signalled that the dialog should
+ * be presented.
+ *
+ ***********************************************************************/
+
+Bool Platform::ForceStartupScreen (void)
+{
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::StopOnResetKeyDown
+// ---------------------------------------------------------------------------
+
+Bool Platform::StopOnResetKeyDown( void )
+{
+ // Comment this out for now. It seems that Windows doesn't always return
+ // the expected result. That is, this function often returns TRUE even
+ // though the Control is not down.
+ //
+ // Since this functionality is really only required by Palm OS engineers,
+ // and since they're working on Macs, we don't really need this feature
+ // in the Windows version now anyway.
+
+// return ::GetAsyncKeyState (VK_CONTROL) != 0;
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::CollectOptions
+// ---------------------------------------------------------------------------
+
+int Platform::CollectOptions (int argc, char** argv, int& errorArg, int (*cb)(int, char**, int&))
+{
+ if (!Fl::args (argc, argv, errorArg, cb) || errorArg < argc - 1)
+ return false;
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::PrintHelp
+// ---------------------------------------------------------------------------
+
+void Platform::PrintHelp (void)
+{
+ printf ("%s\n", Fl::help);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::GetMilliseconds
+// ---------------------------------------------------------------------------
+
+uint32 Platform::GetMilliseconds( void )
+{
+ long long usecs = ::PrvGetMicroseconds ();
+ uint32 millis = (uint32) (usecs / 1000);
+
+ return millis;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::CreateDebuggerSocket
+// ---------------------------------------------------------------------------
+
+CSocket* Platform::CreateDebuggerSocket (void)
+{
+ return NULL;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::ExitDebugger
+// ---------------------------------------------------------------------------
+// Perform platform-specific operations when debug mode is exited.
+
+void Platform::ExitDebugger( void )
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::ViewDrawLine
+// ---------------------------------------------------------------------------
+
+void Platform::ViewDrawLine( int xStart, int yStart, int xEnd, int yEnd )
+{
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ Platform::ViewDrawPixel
+// ---------------------------------------------------------------------------
+
+void Platform::ViewDrawPixel( int xPos, int yPos )
+{
+}
+
+
+static void PrvQueueNote (int frequency, int duration, int amplitude)
+{
+ // Use XBell under X to play a simple tone. For more advanced
+ // sound functionality, direct synth manipulation (under Linux),
+ // or wave playback (probably via Esound), would be needed.
+
+ // !TODO: figure out how to get XGetKeyboardControl working, so
+ // that the actual keyboard state can be restored, instead of
+ // just "the default".
+
+ if (duration > 0 && amplitude > 0)
+ {
+ XKeyboardControl new_state;
+
+ /* fl_display global contains the XDisplay of the last
+ "current" fltk widget, under X/Windows */
+
+ new_state.bell_percent = amplitude * 100 / 64;
+ new_state.bell_pitch = frequency;
+ new_state.bell_duration = duration;
+
+ XChangeKeyboardControl (fl_display,
+ KBBellPercent | KBBellPitch | KBBellDuration,
+ &new_state);
+
+ XBell (fl_display, 100); // Give beep command
+ XFlush (fl_display); // Flush beep command to the server
+ omni_thread::sleep (0, duration * 1000000); // wait for asynch beep
+
+ /* Put bell state back to "default" values */
+
+ new_state.bell_percent = -1;
+ new_state.bell_pitch = -1;
+ new_state.bell_duration = -1;
+
+ XChangeKeyboardControl (fl_display,
+ KBBellPercent | KBBellPitch | KBBellDuration,
+ &new_state);
+ }
+}
+
+
+CallROMType Platform::SndDoCmd (SndCommandType& cmd)
+{
+ switch (cmd.cmd)
+ {
+ case sndCmdFreqDurationAmp:
+ PrvQueueNote (cmd.param1, cmd.param2, cmd.param3);
+ break;
+
+ case sndCmdNoteOn:
+ return kExecuteROM;
+
+ case sndCmdFrqOn:
+ PrvQueueNote (cmd.param1, cmd.param2, cmd.param3);
+ break;
+
+ case sndCmdQuiet:
+ return kExecuteROM;
+ }
+
+ return kSkipROM;
+}
+
+void Platform::StopSound (void)
+{
+}
+
+
+void Platform::Beep (void)
+{
+ XBell (fl_display, 100); // Give beep command. Make it loud
+ XFlush (fl_display); // Flush beep command to the server
+}
diff --git a/SrcUnix/ResStrings.h b/SrcUnix/ResStrings.h
new file mode 100644
index 0000000..0b56a1f
--- /dev/null
+++ b/SrcUnix/ResStrings.h
@@ -0,0 +1,19 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#ifndef __RESSTRINGS_H__
+#define __RESSTRINGS_H__
+
+const char *_ResGetString(int idx);
+
+#endif /* __RESSTRINGS_H__ */
diff --git a/SrcUnix/espws-2.0/CheckButton.cxx b/SrcUnix/espws-2.0/CheckButton.cxx
new file mode 100644
index 0000000..3fad85e
--- /dev/null
+++ b/SrcUnix/espws-2.0/CheckButton.cxx
@@ -0,0 +1,113 @@
+//
+// "$Id: CheckButton.cxx,v 1.10 2000/01/04 13:45:50 mike Exp $"
+//
+// CheckButton routines for the Common UNIX Printing System (CUPS).
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "LICENSE.txt" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: CUPS Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9603
+// EMail: cups-info@cups.org
+// WWW: http://www.cups.org
+//
+// Contents:
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include "CheckButton.h"
+#include <FL/fl_draw.H>
+
+
+//
+// CheckButton is a subclass of Fl_Button like Fl_Check_Button, only the
+// toggle and radio images are more like Microsoft Windows.
+//
+
+
+//
+// 'CheckButton::draw()' - Draw the check button.
+//
+
+void CheckButton::draw()
+{
+ int size, // Size of button...
+ offset; // Box Y offset...
+
+ size = labelsize();
+ offset = (h() - size) / 2;
+
+ if (type() == FL_RADIO_BUTTON)
+ {
+ // Draw the radio "hole"...
+ draw_box(FL_ROUND_DOWN_BOX, x(), y() + offset, size, size, FL_WHITE);
+
+ // Then the check...
+ if (value())
+ {
+ fl_color(active_r() ? FL_BLACK : FL_GRAY);
+
+ if (size > 14)
+ fl_pie(x() + 5, y() + offset + 5, size - 10, size - 10, 0.0, 360.0);
+ else
+ {
+ // Small circles don't draw well with some X servers...
+ fl_rect(x() + 6, y() + offset + 5, 2, 4);
+ fl_rect(x() + 5, y() + offset + 6, 4, 2);
+ }
+ }
+ }
+ else
+ {
+ // Draw the check "box"...
+ draw_box(FL_DOWN_BOX, x(), y() + offset, size, size, FL_WHITE);
+
+ // Then the check...
+ if (value())
+ {
+ fl_color(active_r() ? FL_BLACK : FL_GRAY);
+ fl_line(x() + 3, y() + offset + 3,
+ x() + size - 4, y() + offset + size - 4);
+ fl_line(x() + 4, y() + offset + 3,
+ x() + size - 3, y() + offset + size - 4);
+ fl_line(x() + 3, y() + offset + size - 4,
+ x() + size - 4, y() + offset + 3);
+ fl_line(x() + 4, y() + offset + size - 4,
+ x() + size - 3, y() + offset + 3);
+ }
+ }
+
+ // Finally, the label...
+ draw_label(x() + 5 * size / 4, y(), w() - 5 * size / 4, h());
+}
+
+
+//
+// 'CheckButton::CheckButton()' - Construct a CheckButton widget.
+//
+
+CheckButton::CheckButton(int x, int y, int w, int h, const char* l)
+: Fl_Button(x, y, w, h, l)
+{
+ type(FL_TOGGLE_BUTTON);
+ align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
+}
+
+
+//
+// End of "$Id: CheckButton.cxx,v 1.10 2000/01/04 13:45:50 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/CheckButton.h b/SrcUnix/espws-2.0/CheckButton.h
new file mode 100644
index 0000000..77d9273
--- /dev/null
+++ b/SrcUnix/espws-2.0/CheckButton.h
@@ -0,0 +1,52 @@
+//
+// "$Id: CheckButton.h,v 1.3 2000/01/04 13:45:50 mike Exp $"
+//
+// CheckButton definitions for the Common UNIX Printing System (CUPS).
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "LICENSE.txt" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: CUPS Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9603
+// EMail: cups-info@cups.org
+// WWW: http://www.cups.org
+//
+
+#ifndef _CHECKBUTTON_H_
+# define _CHECKBUTTON_H_
+
+//
+// Include necessary headers.
+//
+
+#include <FL/Fl_Button.H>
+
+
+//
+// CheckButton class...
+//
+
+class CheckButton : public Fl_Button
+{
+protected:
+ virtual void draw();
+
+public:
+ CheckButton(int x, int y, int w, int h, const char *l = 0);
+};
+
+#endif // !_CHECKBUTTON_H_
+
+//
+// End of "$Id: CheckButton.h,v 1.3 2000/01/04 13:45:50 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/CheckButton.html b/SrcUnix/espws-2.0/CheckButton.html
new file mode 100644
index 0000000..d8f0de8
--- /dev/null
+++ b/SrcUnix/espws-2.0/CheckButton.html
@@ -0,0 +1,61 @@
+<HTML>
+<HEAD>
+ <TITLE>CheckButton - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class CheckButton</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Group
+ |
+ +----<B>CheckButton</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "CheckButton.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>CheckButton</CODE> widget provides a better looking check or
+radio button. It is otherwise identical to the <CODE>Fl_Check_Button</CODE>
+widget.
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#CheckButton.CheckButton">CheckButton</A>
+ <LI><A HREF="#CheckButton.~CheckButton">~CheckButton</A>
+
+</UL>
+
+<H4><A NAME="CheckButton.CheckButton">CheckButton(int xx, int yy, int ww, int hh, const char *l = 0)</A></H4>
+
+<P>The constructor creates the <CODE>CheckButton</CODE> widget at the specified
+position and size.
+
+<H4><A NAME="CheckButton.~CheckButton">~CheckButton()</A></H4>
+
+<P>The destructor destroys the widget and frees all memory that has been
+allocated.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/FileBrowser.cxx b/SrcUnix/espws-2.0/FileBrowser.cxx
new file mode 100644
index 0000000..a5292e7
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileBrowser.cxx
@@ -0,0 +1,518 @@
+//
+// "$Id: FileBrowser.cxx,v 1.20 2000/03/14 15:33:36 mike Exp $"
+//
+// FileBrowser routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// FileBrowser::item_width() - Return the width of a list item.
+// FileBrowser::item_draw() - Draw a list item.
+// FileBrowser::FileBrowser() - Create a FileBrowser widget.
+// FileBrowser::load() - Load a directory into the browser.
+// FileBrowser::filter() - Set the filename filter.
+//
+
+//
+// Include necessary header files...
+//
+
+#include "FileBrowser.h"
+#include <FL/fl_draw.H>
+#include <FL/filename.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(WIN32)
+# include <windows.h>
+# include <direct.h>
+#endif /* WIN32 */
+
+#if defined(__EMX__)
+#define INCL_DOS
+#define INCL_DOSMISC
+#include <os2.h>
+#endif /* __EMX__ */
+
+
+//
+// FL_BLINE definition from "Fl_Browser.cxx"...
+//
+
+#define SELECTED 1
+#define NOTDISPLAYED 2
+
+struct FL_BLINE // data is in a linked list of these
+{
+ FL_BLINE *prev; // Previous item in list
+ FL_BLINE *next; // Next item in list
+ void *data; // Pointer to data (function)
+ short length; // sizeof(txt)-1, may be longer than string
+ char flags; // selected, displayed
+ char txt[1]; // start of allocated array
+};
+
+
+//
+// 'FileBrowser::item_height()' - Return the height of a list item.
+//
+
+int // O - Height in pixels
+FileBrowser::item_height(void *p) const // I - List item data
+{
+ FL_BLINE *line; // Pointer to line
+ char *text; // Pointer into text
+ int height; // Width of line
+ int textheight; // Height of text
+
+
+ // Figure out the standard text height...
+ fl_font(textfont(), textsize());
+ textheight = fl_height();
+
+ // We always have at least 1 line...
+ height = textheight;
+
+ // Scan for newlines...
+ line = (FL_BLINE *)p;
+
+ if (line != NULL)
+ for (text = line->txt; *text != '\0'; text ++)
+ if (*text == '\n')
+ height += textheight;
+
+ // If we have enabled icons then add space for them...
+ if (FileIcon::first() != NULL && height < iconsize_)
+ height = iconsize_;
+
+ // Add space for the selection border..
+ height += 2;
+
+ // Return the height
+ return (height);
+}
+
+
+//
+// 'FileBrowser::item_width()' - Return the width of a list item.
+//
+
+int // O - Width in pixels
+FileBrowser::item_width(void *p) const // I - List item data
+{
+ int i; // Looping var
+ FL_BLINE *line; // Pointer to line
+ char *text, // Pointer into text
+ *ptr, // Pointer into fragment
+ fragment[10240]; // Fragment of text
+ int width, // Width of line
+ tempwidth; // Width of fragment
+ int column; // Current column
+ const int *columns; // Columns
+
+
+ // Set the font and size...
+ fl_font(textfont(), textsize());
+
+ // Scan for newlines...
+ line = (FL_BLINE *)p;
+ columns = column_widths();
+
+ if (strchr(line->txt, '\n') == NULL &&
+ strchr(line->txt, column_char()) == NULL)
+ {
+ // Do a fast width calculation...
+ width = (int)fl_width(line->txt);
+ }
+ else
+ {
+ // More than 1 line or have columns; find the maximum width...
+ width = 0;
+ tempwidth = 0;
+ column = 0;
+
+ for (text = line->txt, ptr = fragment; *text != '\0'; text ++)
+ if (*text == '\n')
+ {
+ // Newline - nul terminate this fragment and get the width...
+ *ptr = '\0';
+
+ tempwidth += (int)fl_width(fragment);
+
+ // Update the max width as needed...
+ if (tempwidth > width)
+ width = tempwidth;
+
+ // Point back to the start of the fragment...
+ ptr = fragment;
+ tempwidth = 0;
+ }
+ else if (*text == column_char())
+ {
+ // Advance to the next column...
+ column ++;
+ if (columns)
+ {
+ for (i = 0, tempwidth = 0; i < column && columns[i]; i ++)
+ tempwidth += columns[column - 1];
+ }
+ else
+ tempwidth = column * (int)fl_width(" ");
+
+ if (tempwidth > width)
+ width = tempwidth;
+
+ ptr = fragment;
+ }
+ else
+ *ptr++ = *text;
+
+ if (ptr > fragment)
+ {
+ // Nul terminate this fragment and get the width...
+ *ptr = '\0';
+
+ tempwidth += (int)fl_width(fragment);
+
+ // Update the max width as needed...
+ if (tempwidth > width)
+ width = tempwidth;
+ }
+ }
+
+ // If we have enabled icons then add space for them...
+ if (FileIcon::first() != NULL)
+ width += iconsize_ + 8;
+
+ // Add space for the selection border..
+ width += 2;
+
+ // Return the width
+ return (width);
+}
+
+
+//
+// 'FileBrowser::item_draw()' - Draw a list item.
+//
+
+void
+FileBrowser::item_draw(void *p, // I - List item data
+ int x, // I - Upper-lefthand X coordinate
+ int y, // I - Upper-lefthand Y coordinate
+ int w, // I - Width of item
+ int h) const // I - Height of item
+{
+ int i; // Looping var
+ FL_BLINE *line; // Pointer to line
+ Fl_Color c; // Text color
+ char *text, // Pointer into text
+ *ptr, // Pointer into fragment
+ fragment[10240]; // Fragment of text
+ int width, // Width of line
+ height; // Height of line
+ int column; // Current column
+ const int *columns; // Columns
+
+
+ // Draw the list item text...
+ line = (FL_BLINE *)p;
+
+ fl_font(textfont(), textsize());
+
+ if (line->flags & SELECTED)
+ c = fl_contrast(textcolor(), selection_color());
+ else
+ c = textcolor();
+
+ if (FileIcon::first() == NULL)
+ {
+ // No icons, just draw the text...
+ x ++;
+ w -= 2;
+ }
+ else
+ {
+ // Draw the icon if it is set...
+ if (line->data)
+ ((FileIcon *)line->data)->draw(x, y, iconsize_, iconsize_,
+ (line->flags & SELECTED) ? FL_YELLOW :
+ FL_LIGHT2,
+ active_r());
+
+ // Draw the text offset to the right...
+ x += iconsize_ + 9;
+ w -= iconsize_ - 10;
+
+ // Center the text vertically...
+ line = (FL_BLINE *)p;
+ height = fl_height();
+
+ for (text = line->txt; *text != '\0'; text ++)
+ if (*text == '\n')
+ height += fl_height();
+
+ if (height < iconsize_)
+ y += (iconsize_ - height) / 2;
+ }
+
+ // Draw the text...
+ line = (FL_BLINE *)p;
+ columns = column_widths();
+ width = 0;
+ column = 0;
+
+ if (active_r())
+ fl_color(c);
+ else
+ fl_color(fl_inactive(c));
+
+ for (text = line->txt, ptr = fragment; *text != '\0'; text ++)
+ if (*text == '\n')
+ {
+ // Newline - nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ fl_draw(fragment, x + width, y, w - width, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP));
+
+ // Point back to the start of the fragment...
+ ptr = fragment;
+ width = 0;
+ y += fl_height();
+ }
+ else if (*text == column_char())
+ {
+ // Tab - nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ fl_draw(fragment, x + width, y, w - width, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP));
+
+ // Advance to the next column...
+ column ++;
+ if (columns)
+ {
+ for (i = 0, width = 0; i < column && columns[i]; i ++)
+ width += columns[column - 1];
+ }
+ else
+ width = column * (int)fl_width(" ");
+
+ ptr = fragment;
+ }
+ else
+ *ptr++ = *text;
+
+ if (ptr > fragment)
+ {
+ // Nul terminate this fragment and draw it...
+ *ptr = '\0';
+
+ fl_draw(fragment, x + width, y, w - width, fl_height(),
+ (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP));
+ }
+}
+
+
+//
+// 'FileBrowser::FileBrowser()' - Create a FileBrowser widget.
+//
+
+FileBrowser::FileBrowser(int x, // I - Upper-lefthand X coordinate
+ int y, // I - Upper-lefthand Y coordinate
+ int w, // I - Width in pixels
+ int h, // I - Height in pixels
+ const char *l) // I - Label text
+ : Fl_Browser(x, y, w, h, l)
+{
+ // Initialize the filter pattern, current directory, and icon size...
+ pattern_ = "*";
+ directory_ = "";
+ iconsize_ = 3 * textsize() / 2;
+}
+
+
+//
+// 'FileBrowser::load()' - Load a directory into the browser.
+//
+
+int // O - Number of files loaded
+FileBrowser::load(const char *directory)// I - Directory to load
+{
+ int i; // Looping var
+ int num_files; // Number of files in directory
+ char filename[4096]; // Current file
+ FileIcon *icon; // Icon to use
+
+
+ clear();
+ directory_ = directory;
+
+ if (directory_[0] == '\0')
+ {
+ //
+ // No directory specified; for UNIX list all mount points. For DOS
+ // list all valid drive letters...
+ //
+
+ num_files = 0;
+ icon = FileIcon::find("any", FileIcon::DEVICE);
+
+#if defined(WIN32) || defined(__EMX__)
+ DWORD drives; // Drive available bits
+
+
+ drives = GetLogicalDrives();
+ for (i = 'A'; i <= 'Z'; i ++, drives >>= 1)
+ if (drives & 1)
+ {
+ sprintf(filename, "%c:", i);
+
+ if (i < 'C')
+ add(filename, icon);
+ else
+ add(filename, icon);
+
+ num_files ++;
+ }
+#elif defined(__EMX__)
+ ULONG curdrive; // Current drive
+ ULONG drives; // Drive available bits
+ int start = 3; // 'C' (MRS - dunno if this is correct!)
+
+
+ DosQueryCurrentDisk(&curdrive, &drives);
+ drives >>= start - 1;
+ for (i = 'A'; i <= 'Z'; i ++, drives >>= 1)
+ if (drives & 1)
+ {
+ sprintf(filename, "%c:", i);
+ add(filename, icon);
+
+ num_files ++;
+ }
+#else
+ FILE *mtab; // /etc/mtab or /etc/mnttab file
+ char line[1024]; // Input line
+
+
+ //
+ // Open the file that contains a list of mounted filesystems...
+ //
+# if defined(hpux) || defined(__sun)
+ mtab = fopen("/etc/mnttab", "r"); // Fairly standard
+# elif defined(__sgi) || defined(linux)
+ mtab = fopen("/etc/mtab", "r"); // More standard
+# else
+ mtab = fopen("/etc/fstab", "r"); // Otherwise fallback to full list
+ if (mtab == NULL)
+ mtab = fopen("/etc/vfstab", "r");
+# endif
+
+ if (mtab != NULL)
+ {
+ while (fgets(line, sizeof(line), mtab) != NULL)
+ {
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+ if (sscanf(line, "%*s%4095s", filename) != 1)
+ continue;
+
+ add(filename, icon);
+ num_files ++;
+ }
+
+ fclose(mtab);
+ }
+#endif // WIN32 || __EMX__
+ }
+ else
+ {
+ dirent **files; // Files in in directory
+
+
+ //
+ // Build the file list...
+ //
+
+#if defined(WIN32) || defined(__EMX__)
+ strncpy(filename, directory_, sizeof(filename) - 1);
+ filename[sizeof(filename) - 1] = '\0';
+ i = strlen(filename) - 1;
+
+ if (i == 2 && filename[1] == ':' &&
+ (filename[2] == '/' || filename[2] == '\\'))
+ filename[2] = '/';
+ else if (filename[i] != '/' && filename[i] != '\\')
+ strcat(filename, "/");
+
+ num_files = filename_list(filename, &files);
+#else
+ num_files = filename_list(directory_, &files);
+#endif /* WIN32 || __EMX__ */
+
+ if (num_files <= 0)
+ return (0);
+
+ for (i = 0; i < num_files; i ++)
+ {
+ if (strcmp(files[i]->d_name, ".") != 0 &&
+ strcmp(files[i]->d_name, "..") != 0)
+ {
+ sprintf(filename, "%s/%s", directory_, files[i]->d_name);
+
+ if (filename_isdir(filename) ||
+ filename_match(files[i]->d_name, pattern_))
+ add(files[i]->d_name, FileIcon::find(filename));
+ }
+
+ free(files[i]);
+ }
+
+ free(files);
+ }
+
+ return (num_files);
+}
+
+
+//
+// 'FileBrowser::filter()' - Set the filename filter.
+//
+
+void
+FileBrowser::filter(const char *pattern) // I - Pattern string
+{
+ // If pattern is NULL set the pattern to "*"...
+ if (pattern)
+ pattern_ = pattern;
+ else
+ pattern_ = "*";
+
+ // Reload the current directory...
+ load(directory_);
+}
+
+
+//
+// End of "$Id: FileBrowser.cxx,v 1.20 2000/03/14 15:33:36 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileBrowser.h b/SrcUnix/espws-2.0/FileBrowser.h
new file mode 100644
index 0000000..ae09d96
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileBrowser.h
@@ -0,0 +1,71 @@
+//
+// "$Id: FileBrowser.h,v 1.10 2000/01/04 13:45:51 mike Exp $"
+//
+// FileBrowser definitions.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+
+//
+// Include necessary header files...
+//
+
+#ifndef _GUI_FILEBROWSER_H_
+# define _GUI_FILEBROWSER_H_
+
+# include <FL/Fl_Browser.H>
+# include "FileIcon.h"
+
+
+//
+// FileBrowser class...
+//
+
+class FileBrowser : public Fl_Browser
+{
+ const char *directory_;
+ uchar iconsize_;
+ const char *pattern_;
+
+ int item_height(void *) const;
+ int item_width(void *) const;
+ void item_draw(void *, int, int, int, int) const;
+ int incr_height() const { return (item_height(0)); }
+
+public:
+ FileBrowser(int, int, int, int, const char * = 0);
+
+ uchar iconsize() const { return (iconsize_); };
+ void iconsize(uchar s) { iconsize_ = s; redraw(); };
+
+ void filter(const char *pattern);
+ const char *filter() const { return (pattern_); };
+
+ int load(const char *directory);
+
+ uchar textsize() const { return (Fl_Browser::textsize()); };
+ void textsize(uchar s) { Fl_Browser::textsize(s); iconsize_ = 3 * s / 2; };
+
+};
+
+#endif // !_GUI_FILEBROWSER_H_
+
+//
+// End of "$Id: FileBrowser.h,v 1.10 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileBrowser.html b/SrcUnix/espws-2.0/FileBrowser.html
new file mode 100644
index 0000000..4a02032
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileBrowser.html
@@ -0,0 +1,79 @@
+<HTML>
+<HEAD>
+ <TITLE>FileBrowser - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class FileBrowser</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Browser
+ |
+ +----<B>FileBrowser</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "FileBrowser.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>FileBrowser</CODE> widget displays a list of filenames,
+optionally with file-specific icons.
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#FileBrowser.FileBrowser">FileBrowser</A>
+ <LI><A HREF="#FileBrowser.~FileBrowser">~FileBrowser</A>
+ <LI><A HREF="#FileBrowser.iconsize">iconsize</A>
+ <LI><A HREF="#FileBrowser.filter">filter</A>
+ <LI><A HREF="#FileBrowser.load">load</A>
+
+</UL>
+
+<H4><A NAME="FileBrowser.FileBrowser">FileBrowser(int xx, int yy, int ww, int hh, const char *l = 0)</A></H4>
+
+<P>The constructor creates the <CODE>FileBrowser</CODE> widget at the specified
+position and size.
+
+<H4><A NAME="FileBrowser.~FileBrowser">~FileBrowser()</A></H4>
+
+<P>The destructor destroys the widget and frees all memory that has been
+allocated.
+
+<H4><A NAME="FileBrowser.iconsize">void iconsize(uchar s)<BR>
+uchar iconsize() const</A></H4>
+
+<P>Sets or gets the size of the icons. The default size is 20 pixels.
+
+<H4><A NAME="FileBrowser.filter">void filter(const char *pattern)<BR>
+const char *filter() const</A></H4>
+
+<P>Sets or gets the filename filter. The pattern matching uses the
+<CODE>filename_match()</CODE> function in FLTK.
+
+<H4><A NAME="FileBrowser.load">int load(const char *directory)</A></H4>
+
+<P>Loads the specified directory into the browser. If icons have been
+loaded then the correct icon is associated with each file in the list.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/FileChooser.cxx b/SrcUnix/espws-2.0/FileChooser.cxx
new file mode 100644
index 0000000..64bfd04
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser.cxx
@@ -0,0 +1,249 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#include "FileChooser.h"
+
+inline void FileChooser::cb_window_i(Fl_Window*, void*) {
+ fileList->deselect();
+fileName->value("");
+window->hide();
+}
+void FileChooser::cb_window(Fl_Window* o, void* v) {
+ ((FileChooser*)(o->user_data()))->cb_window_i(o,v);
+}
+
+inline void FileChooser::cb_fileList_i(FileBrowser*, void*) {
+ fileListCB();
+}
+void FileChooser::cb_fileList(FileBrowser* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_fileList_i(o,v);
+}
+
+inline void FileChooser::cb_Cancel_i(Fl_Button*, void*) {
+ fileList->deselect();
+fileName->value("");
+window->hide();
+}
+void FileChooser::cb_Cancel(Fl_Button* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_Cancel_i(o,v);
+}
+
+inline void FileChooser::cb_okButton_i(Fl_Return_Button*, void*) {
+ window->hide();
+}
+void FileChooser::cb_okButton(Fl_Return_Button* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_okButton_i(o,v);
+}
+
+inline void FileChooser::cb_fileName_i(FileInput*, void*) {
+ fileNameCB();
+}
+void FileChooser::cb_fileName(FileInput* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_fileName_i(o,v);
+}
+
+inline void FileChooser::cb_upButton_i(Fl_Button*, void*) {
+ up();
+}
+void FileChooser::cb_upButton(Fl_Button* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_upButton_i(o,v);
+}
+
+#include <FL/Fl_Bitmap.H>
+static unsigned char bits_up[] =
+"\0\0x\0\204\0\2\1""1\376y\200\375\200""1\200""1\200""1\200""1\200""1\200\1\
+\200\1\200\377\377\0\0";
+static Fl_Bitmap bitmap_up(bits_up, 16, 16);
+
+inline void FileChooser::cb_newButton_i(Fl_Button*, void*) {
+ newdir();
+}
+void FileChooser::cb_newButton(Fl_Button* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_newButton_i(o,v);
+}
+
+static unsigned char bits_new[] =
+"\0\0x\0\204\0\2\1\1\376\1\200""1\200""1\200\375\200\375\200""1\200""1\200\1\
+\200\1\200\377\377\0\0";
+static Fl_Bitmap bitmap_new(bits_new, 16, 16);
+
+inline void FileChooser::cb_dirMenu_i(Fl_Choice*, void*) {
+ char pathname[1024];
+int i;
+
+pathname[0] = '\0';
+for (i = 1; i <= dirMenu->value(); i ++)
+ strcat(pathname, dirMenu->text(i));
+directory(pathname);
+}
+void FileChooser::cb_dirMenu(Fl_Choice* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_dirMenu_i(o,v);
+}
+
+inline void FileChooser::cb_allfiles_i(Fl_Button*, void*) {
+ fileList->filter("*");;
+rescan();
+}
+void FileChooser::cb_allfiles(Fl_Button* o, void* v) {
+ ((FileChooser*)(o->parent()->user_data()))->cb_allfiles_i(o,v);
+}
+
+static unsigned char bits_allfiles[] =
+"\374?\4 \4 \4 \204!\244%\304#\364/\364/\304#\244%\204!\4 \4 \4 \374?";
+static Fl_Bitmap bitmap_allfiles(bits_allfiles, 16, 16);
+
+FileChooser::FileChooser(const char *d, const char *p, int t, const char *title) {
+ Fl_Window* w;
+ { Fl_Window* o = window = new Fl_Window(375, 315, "Pick a File");
+ w = o;
+ o->callback((Fl_Callback*)cb_window, (void*)(this));
+ w->hotspot(o);
+ { FileBrowser* o = fileList = new FileBrowser(10, 45, 355, 180);
+ o->type(2);
+ o->callback((Fl_Callback*)cb_fileList);
+ Fl_Group::current()->resizable(o);
+ w->hotspot(o);
+ }
+ { Fl_Button* o = new Fl_Button(300, 280, 65, 25, "Cancel");
+ o->callback((Fl_Callback*)cb_Cancel);
+ }
+ { Fl_Return_Button* o = okButton = new Fl_Return_Button(240, 280, 55, 25, "OK");
+ o->callback((Fl_Callback*)cb_okButton);
+ }
+ { FileInput* o = fileName = new FileInput(10, 245, 355, 25, "Filename:");
+ o->callback((Fl_Callback*)cb_fileName);
+ o->align(FL_ALIGN_TOP_LEFT);
+ o->when(FL_WHEN_ENTER_KEY);
+ fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS);
+ }
+ { Fl_Button* o = upButton = new Fl_Button(280, 10, 25, 25);
+ bitmap_up.label(o);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)cb_upButton);
+ }
+ { Fl_Button* o = newButton = new Fl_Button(310, 10, 25, 25);
+ bitmap_new.label(o);
+ o->labelsize(8);
+ o->callback((Fl_Callback*)cb_newButton);
+ }
+ { Fl_Choice* o = dirMenu = new Fl_Choice(75, 10, 200, 25, "Directory:");
+ o->callback((Fl_Callback*)cb_dirMenu);
+ }
+ { Fl_Button* o = allFiles = new Fl_Button(340, 10, 25, 25);
+ bitmap_allfiles.label(o);
+ o->labelsize(28);
+ o->labelcolor(4);
+ o->callback((Fl_Callback*)cb_allfiles);
+ o->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
+ }
+ if (title) window->label(title);
+ o->set_modal();
+ o->end();
+ }
+ window->size_range(345, 270, 345);
+directory_chooser_ = false;
+fileList->filter(p);
+type(t);
+value(d);
+}
+
+void FileChooser::color(Fl_Color c) {
+ fileList->color(c);
+}
+
+Fl_Color FileChooser::color() {
+ return (fileList->color());
+}
+
+char * FileChooser::directory() {
+ return directory_;
+}
+
+void FileChooser::filter(const char *p) {
+ fileList->filter(p);
+rescan();
+}
+
+const char * FileChooser::filter() {
+ return (fileList->filter());
+}
+
+void FileChooser::hide() {
+ window->hide();
+}
+
+void FileChooser::iconsize(uchar s) {
+ fileList->iconsize(s);
+}
+
+uchar FileChooser::iconsize() {
+ return (fileList->iconsize());
+}
+
+void FileChooser::label(const char *l) {
+ window->label(l);
+}
+
+const char * FileChooser::label() {
+ return (window->label());
+}
+
+void FileChooser::show() {
+ window->show();
+fileList->deselect();
+}
+
+void FileChooser::textcolor(Fl_Color c) {
+ fileList->textcolor(c);
+}
+
+Fl_Color FileChooser::textcolor() {
+ return (fileList->textcolor());
+}
+
+void FileChooser::textfont(uchar f) {
+ fileList->textfont(f);
+}
+
+uchar FileChooser::textfont() {
+ return (fileList->textfont());
+}
+
+void FileChooser::textsize(uchar s) {
+ fileList->textsize(s);
+}
+
+uchar FileChooser::textsize() {
+ return (fileList->textsize());
+}
+
+void FileChooser::type(int t) {
+ if (t == DIRECTORY)
+ {
+ t = SINGLE;
+ directory_chooser_ = true;
+ allFiles->deactivate();
+ fileList->filter("-_-_-_-_-_-"); /* Match that! */
+ }
+
+ type_ = t;
+if (t == MULTI)
+ fileList->type(FL_MULTI_BROWSER);
+else
+ fileList->type(FL_HOLD_BROWSER);
+if (t != CREATE)
+ newButton->deactivate();
+else
+ newButton->activate();
+}
+
+int FileChooser::type() {
+ return (type_);
+}
+
+int FileChooser::visible() {
+ return window->visible();
+}
+
+int FileChooser::shown() {
+ return window->shown();
+}
diff --git a/SrcUnix/espws-2.0/FileChooser.fl b/SrcUnix/espws-2.0/FileChooser.fl
new file mode 100644
index 0000000..da2b12a
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser.fl
@@ -0,0 +1,189 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.00
+header_name {.h}
+code_name {.cxx}
+gridx 5
+gridy 5
+snap 3
+class FileChooser {open
+} {
+ decl {enum { SINGLE, MULTI, CREATE };} {public
+ }
+ Function {FileChooser(const char *d, const char *p, int t, const char *title)} {open
+ } {
+ Fl_Window window {
+ label {Pick a File}
+ callback {fileList->deselect();
+fileName->value("");
+window->hide();} open
+ private xywh {173 142 375 315} resizable hotspot
+ code0 {if (title) window->label(title);}
+ code1 {\#include <stdio.h>}
+ code2 {\#include <stdlib.h>}
+ code3 {\#include <string.h>} modal visible
+ } {
+ Fl_Browser fileList {
+ callback {fileListCB();} selected
+ private xywh {10 45 355 180} type Hold resizable hotspot
+ code1 {\#include "FileBrowser.h"}
+ class FileBrowser
+ }
+ Fl_Button {} {
+ label Cancel
+ callback {fileList->deselect();
+fileName->value("");
+window->hide();}
+ private xywh {300 280 65 25}
+ }
+ Fl_Return_Button okButton {
+ label OK
+ callback {window->hide();}
+ private xywh {240 280 55 25}
+ }
+ Fl_Input fileName {
+ label {Filename:}
+ callback {fileNameCB();}
+ private xywh {10 245 355 25} align 5 when 8
+ code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS);}
+ code1 {\#include "FileInput.h"}
+ class FileInput
+ }
+ Fl_Button upButton {
+ label {up.xbm}
+ callback {up();}
+ private xywh {280 10 25 25} labeltype image labelsize 8
+ }
+ Fl_Button newButton {
+ label {new.xbm}
+ callback {newdir();}
+ private xywh {310 10 25 25} labeltype image labelsize 8
+ }
+ Fl_Choice dirMenu {
+ label {Directory:}
+ callback {char pathname[1024];
+int i;
+
+pathname[0] = '\\0';
+for (i = 1; i <= dirMenu->value(); i ++)
+ strcat(pathname, dirMenu->text(i));
+directory(pathname);} open
+ private xywh {75 10 200 25}
+ } {}
+ Fl_Button {} {
+ label {allfiles.xbm}
+ callback {fileList->filter("*");;
+rescan();}
+ private xywh {340 10 25 25} labeltype image labelsize 28 labelcolor 4 align 16
+ }
+ }
+ code {window->size_range(345, 270, 345);
+fileList->filter(p);
+type(t);
+value(d);} {}
+ }
+ decl {char directory_[1024];} {}
+ decl {int type_;} {}
+ decl {void fileListCB();} {}
+ decl {void fileNameCB();} {}
+ decl {void newdir();} {}
+ decl {void up();} {}
+ Function {color(Fl_Color c)} {} {
+ code {fileList->color(c);} {}
+ }
+ Function {color()} {return_type Fl_Color
+ } {
+ code {return (fileList->color());} {}
+ }
+ decl {int count();} {public
+ }
+ decl {void directory(const char *d);} {public
+ }
+ Function {directory()} {return_type {char *}
+ } {
+ code {return directory_;} {}
+ }
+ Function {filter(const char *p)} {return_type void
+ } {
+ code {fileList->filter(p);
+rescan();} {}
+ }
+ Function {filter()} {return_type {const char *}
+ } {
+ code {return (fileList->filter());} {}
+ }
+ Function {hide()} {return_type void
+ } {
+ code {window->hide();} {}
+ }
+ Function {iconsize(uchar s)} {return_type void
+ } {
+ code {fileList->iconsize(s);} {}
+ }
+ Function {iconsize()} {return_type uchar
+ } {
+ code {return (fileList->iconsize());} {}
+ }
+ Function {label(const char *l)} {return_type void
+ } {
+ code {window->label(l);} {}
+ }
+ Function {label()} {return_type {const char *}
+ } {
+ code {return (window->label());} {}
+ }
+ decl {void rescan();} {public
+ }
+ Function {show()} {return_type void
+ } {
+ code {window->show();
+fileList->deselect();} {}
+ }
+ Function {textcolor(Fl_Color c)} {return_type void
+ } {
+ code {fileList->textcolor(c);} {}
+ }
+ Function {textcolor()} {return_type Fl_Color
+ } {
+ code {return (fileList->textcolor());} {}
+ }
+ Function {textfont(uchar f)} {return_type void
+ } {
+ code {fileList->textfont(f);} {}
+ }
+ Function {textfont()} {return_type uchar
+ } {
+ code {return (fileList->textfont());} {}
+ }
+ Function {textsize(uchar s)} {return_type void
+ } {
+ code {fileList->textsize(s);} {}
+ }
+ Function {textsize()} {return_type uchar
+ } {
+ code {return (fileList->textsize());} {}
+ }
+ Function {type(int t)} {return_type void
+ } {
+ code {type_ = t;
+if (t == MULTI)
+ fileList->type(FL_MULTI_BROWSER);
+else
+ fileList->type(FL_HOLD_BROWSER);
+if (t != CREATE)
+ newButton->deactivate();
+else
+ newButton->activate();} {}
+ }
+ Function {type()} {return_type int
+ } {
+ code {return (type_);} {}
+ }
+ decl {const char *value(int f = 1);} {public
+ }
+ decl {void value(const char *filename);} {public
+ }
+ Function {visible()} {return_type int
+ } {
+ code {return window->visible();} {}
+ }
+}
diff --git a/SrcUnix/espws-2.0/FileChooser.gif b/SrcUnix/espws-2.0/FileChooser.gif
new file mode 100644
index 0000000..5a72f62
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser.gif
Binary files differ
diff --git a/SrcUnix/espws-2.0/FileChooser.h b/SrcUnix/espws-2.0/FileChooser.h
new file mode 100644
index 0000000..0b5e7f5
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser.h
@@ -0,0 +1,82 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#ifndef FileChooser_h
+#define FileChooser_h
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "FileBrowser.h"
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include "FileInput.h"
+#include <FL/Fl_Choice.H>
+
+class FileChooser {
+public:
+ enum { SINGLE, MULTI, CREATE, DIRECTORY };
+ FileChooser(const char *d, const char *p, int t, const char *title);
+private:
+ Fl_Window *window;
+ inline void cb_window_i(Fl_Window*, void*);
+ static void cb_window(Fl_Window*, void*);
+ FileBrowser *fileList;
+ inline void cb_fileList_i(FileBrowser*, void*);
+ static void cb_fileList(FileBrowser*, void*);
+ inline void cb_Cancel_i(Fl_Button*, void*);
+ static void cb_Cancel(Fl_Button*, void*);
+ Fl_Return_Button *okButton;
+ inline void cb_okButton_i(Fl_Return_Button*, void*);
+ static void cb_okButton(Fl_Return_Button*, void*);
+ FileInput *fileName;
+ inline void cb_fileName_i(FileInput*, void*);
+ static void cb_fileName(FileInput*, void*);
+ Fl_Button *upButton;
+ inline void cb_upButton_i(Fl_Button*, void*);
+ static void cb_upButton(Fl_Button*, void*);
+ Fl_Button *newButton;
+ inline void cb_newButton_i(Fl_Button*, void*);
+ static void cb_newButton(Fl_Button*, void*);
+ Fl_Choice *dirMenu;
+ inline void cb_dirMenu_i(Fl_Choice*, void*);
+ static void cb_dirMenu(Fl_Choice*, void*);
+ Fl_Button *allFiles;
+ inline void cb_allfiles_i(Fl_Button*, void*);
+ static void cb_allfiles(Fl_Button*, void*);
+ char directory_[1024];
+ int type_;
+ int directory_chooser_;
+ void fileListCB();
+ void fileNameCB();
+ void newdir();
+ void up();
+public:
+ void color(Fl_Color c);
+ Fl_Color color();
+ int count();
+ void directory(const char *d);
+ char * directory();
+ void filter(const char *p);
+ const char * filter();
+ void hide();
+ void iconsize(uchar s);
+ uchar iconsize();
+ void label(const char *l);
+ const char * label();
+ void rescan();
+ void show();
+ void textcolor(Fl_Color c);
+ Fl_Color textcolor();
+ void textfont(uchar f);
+ uchar textfont();
+ void textsize(uchar s);
+ uchar textsize();
+ void type(int t);
+ int type();
+ const char *value(int f = 1);
+ void value(const char *filename);
+ int visible();
+ int shown();
+};
+#endif
diff --git a/SrcUnix/espws-2.0/FileChooser.html b/SrcUnix/espws-2.0/FileChooser.html
new file mode 100644
index 0000000..6a30107
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser.html
@@ -0,0 +1,172 @@
+<HTML>
+<HEAD>
+ <TITLE>FileChooser - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class FileChooser</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Group
+ |
+ +----<B>FileChooser</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "FileChooser.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>FileChooser</CODE> widget displays a standard file selection
+dialog that supports various selection modes.
+
+<CENTER><IMG SRC="FileChooser.gif" WIDTH="397" HEIGHT="322" ALT="FileChooser widget"></CENTER>
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#FileChooser.FileChooser">FileChooser</A>
+ <LI><A HREF="#FileChooser.~FileChooser">~FileChooser</A>
+ <LI><A HREF="#FileChooser.color">color</A>
+ <LI><A HREF="#FileChooser.count">count</A>
+ <LI><A HREF="#FileChooser.directory">directory</A>
+ <LI><A HREF="#FileChooser.filter">filter</A>
+ <LI><A HREF="#FileChooser.hide">hide</A>
+ <LI><A HREF="#FileChooser.iconsize">iconsize</A>
+ <LI><A HREF="#FileChooser.label">label</A>
+ <LI><A HREF="#FileChooser.rescan">rescan</A>
+ <LI><A HREF="#FileChooser.show">show</A>
+ <LI><A HREF="#FileChooser.textcolor">textcolor</A>
+ <LI><A HREF="#FileChooser.textfont">textfont</A>
+ <LI><A HREF="#FileChooser.textsize">textsize</A>
+ <LI><A HREF="#FileChooser.type">type</A>
+ <LI><A HREF="#FileChooser.value">value</A>
+ <LI><A HREF="#FileChooser.visible">visible</A>
+
+</UL>
+
+<H4><A NAME="FileChooser.FileChooser">FileChooser(const char *pathname, const char *pattern,
+int type, const char *title)</A></H4>
+
+<P>The constructor creates the <CODE>FileChooser</CODE> dialog pictured
+above. The <CODE>pathname</CODE> argument can be a directory name or a
+complete file name (in which case the corresponding file is highlighted
+in the list and in the filename input field.)
+
+<P>The <CODE>pattern</CODE> argument can be a <CODE>NULL</CODE> string or
+<CODE>"*"</CODE> to list all files. See the FLTK documentation on
+<CODE>filename_match()</CODE> for other kinds of patterns.
+
+<P>The <CODE>type</CODE> argument can be one of the following:
+
+<UL>
+ <LI><CODE>SINGLE</CODE> - allows the user to select a
+ single, existing file.
+ <LI><CODE>MULTI</CODE> - allows the user to select one
+ or more existing files.
+ <LI><CODE>CREATE</CODE> - allows the user to select a
+ single, existing file or specify a new filename.
+</UL>
+
+<P>The <CODE>title</CODE> argument is used to set the title bar text for the
+<CODE>FileChooser</CODE> window.
+
+<H4><A NAME="FileChooser.~FileChooser">~FileChooser()</A></H4>
+
+<P>Destroys the widget and frees all memory used by it.
+
+<H4><A NAME="FileChooser.color">void color(Fl_Color c)<BR>
+Fl_Color color()</A></H4>
+
+<P>Sets or gets the background color of the <CODE>FileBrowser</CODE> list.
+
+<H4><A NAME="FileChooser.count">int count()</A></H4>
+
+<P>Returns the number of selected files.
+
+<H4><A NAME="FileChooser.directory">void directory(const char *pathname)<BR>
+const char *directory()</A></H4>
+
+<P>Sets or gets the current directory.
+
+<H4><A NAME="FileChooser.filter">void filter(const char *pattern)<BR>
+const char *filter()</A></H4>
+
+<P>Sets or gets the current filename filter pattern.
+
+<H4><A NAME="FileChooser.hide">void hide()</A></H4>
+
+<P>Hides the <CODE>FileChooser</CODE> window.
+
+<H4><A NAME="FileChooser.iconsize">void iconsize(uchar s)<BR>
+uchar iconsize()</A></H4>
+
+<P>Sets or gets the size of the icons in the <CODE>FileBrowser</CODE>. By
+default the icon size is set to 1.5 times the <CODE>textsize()</CODE>.
+
+<H4><A NAME="FileChooser.label">void label(const char *l)<BR>
+const char *label()</A></H4>
+
+<P>Sets or gets the title bar text for the <CODE>FileChooser</CODE>.
+
+<H4><A NAME="FileChooser.rescan">void rescan()</A></H4>
+
+<P>Reloads the current directory in the <CODE>FileBrowser</CODE>.
+
+<H4><A NAME="FileChooser.show">void show()</A></H4>
+
+<P>Shows the <CODE>FileChooser</CODE> window.
+
+<H4><A NAME="FileChooser.textcolor">void textcolor(Fl_Color c)<BR>
+Fl_Color textcolor()</A></H4>
+
+<P>Sets or gets the current <CODE>FileBrowser</CODE> text color.
+
+<H4><A NAME="FileChooser.textfont">void textfont(uchar f)<BR>
+uchar textfont()</A></H4>
+
+<P>Sets or gets the current <CODE>FileBrowser</CODE> text font.
+
+<H4><A NAME="FileChooser.textsize">void textsize(uchar s)<BR>
+uchar textsize()</A></H4>
+
+<P>Sets or gets the current <CODE>FileBrowser</CODE> text size.
+
+<H4><A NAME="FileChooser.type">void type(int t)<BR>
+int type()</A></H4>
+
+<P>Sets or gets the current type of <CODE>FileChooser</CODE>.
+
+<H4><A NAME="FileChooser.value">const char *value(const char *pathname)<BR>
+const char *value(int file)<BR>
+const char *value()</A></H4>
+
+<P>Sets or gets the current value of the selected file.
+
+<H4><A NAME="FileChooser.visible">int visible()</A></H4>
+
+<P>Returns 1 if the <CODE>FileChooser</CODE> window is visible.
+
+<HR>
+
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/FileChooser2.cxx b/SrcUnix/espws-2.0/FileChooser2.cxx
new file mode 100644
index 0000000..b77a35c
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser2.cxx
@@ -0,0 +1,645 @@
+//
+// "$Id: FileChooser2.cxx,v 1.22 2000/01/04 13:45:51 mike Exp $"
+//
+// More FileChooser routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// FileChooser::directory() - Set the directory in the file chooser.
+// FileChooser::count() - Return the number of selected files.
+// FileChooser::value() - Return a selected filename.
+// FileChooser::up() - Go up one directory.
+// FileChooser::newdir() - Make a new directory.
+// FileChooser::rescan() - Rescan the current directory.
+// FileChooser::fileListCB() - Handle clicks (and double-clicks) in the
+// FileBrowser.
+// FileChooser::fileNameCB() - Handle text entry in the FileBrowser.
+//
+
+//
+// Include necessary headers.
+//
+
+#include "FileChooser.h"
+#include <FL/filename.H>
+#include <FL/fl_ask.H>
+#include <FL/x.H>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#if defined(WIN32) || defined(__EMX__)
+# include <direct.h>
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+//
+// 'FileChooser::directory()' - Set the directory in the file chooser.
+//
+
+void
+FileChooser::directory(const char *d) // I - Directory to change to
+{
+ char pathname[1024], // Full path of directory
+ *pathptr, // Pointer into full path
+ *dirptr; // Pointer into directory
+ int levels; // Number of levels in directory
+
+
+ // NULL == current directory
+ if (d == NULL)
+ d = ".";
+
+ if (d[0] != '\0')
+ {
+ // Make the directory absolute...
+#if defined(WIN32) || defined(__EMX__)
+ if (d[0] != '/' && d[0] != '\\' && d[1] != ':')
+#else
+ if (d[0] != '/' && d[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ filename_absolute(directory_, d);
+ else
+ {
+ strncpy(directory_, d, sizeof(directory_) - 1);
+ directory_[sizeof(directory_) - 1] = '\0';
+ }
+
+ // Strip any trailing slash and/or period...
+ dirptr = directory_ + strlen(directory_) - 1;
+ if (*dirptr == '.')
+ *dirptr-- = '\0';
+ if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_)
+ *dirptr = '\0';
+ }
+ else
+ directory_[0] = '\0';
+
+ // Clear the directory menu and fill it as needed...
+ dirMenu->clear();
+#if defined(WIN32) || defined(__EMX__)
+ dirMenu->add("My Computer");
+#else
+ dirMenu->add("File Systems");
+#endif /* WIN32 || __EMX__ */
+
+ levels = 0;
+ for (dirptr = directory_, pathptr = pathname; *dirptr != '\0';)
+ {
+ if (*dirptr == '/' || *dirptr == '\\')
+ {
+ // Need to quote the slash first, and then add it to the menu...
+ *pathptr++ = '\\';
+ *pathptr++ = '/';
+ *pathptr++ = '\0';
+ dirptr ++;
+
+ dirMenu->add(pathname);
+ levels ++;
+ pathptr = pathname;
+ }
+ else
+ *pathptr++ = *dirptr++;
+ }
+
+ if (pathptr > pathname)
+ {
+ *pathptr = '\0';
+ dirMenu->add(pathname);
+ levels ++;
+ }
+
+ dirMenu->value(levels);
+
+ // Rescan the directory...
+ rescan();
+}
+
+
+//
+// 'FileChooser::count()' - Return the number of selected files.
+//
+
+int // O - Number of selected files
+FileChooser::count()
+{
+ int i; // Looping var
+ int count; // Number of selected files
+ const char *filename; // Filename in input field or list
+ char pathname[1024]; // Full path to file
+
+
+ if (type_ != MULTI)
+ {
+ // Check to see if the file name input field is blank...
+ filename = fileName->value();
+ if (filename == NULL || filename[0] == '\0')
+ return (0);
+
+ // Is the file name a directory?
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (filename_isdir(pathname) && !directory_chooser_)
+ return (0);
+ else
+ return (1);
+ }
+
+ for (i = 1, count = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i))
+ {
+ // See if this file is a directory...
+ filename = (char *)fileList->text(i);
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ count ++;
+ }
+
+ return (count);
+}
+
+
+//
+// 'FileChooser::value()' - Return a selected filename.
+//
+
+const char * // O - Filename or NULL
+FileChooser::value(int f) // I - File number
+{
+ int i; // Looping var
+ int count; // Number of selected files
+ const char *name; // Current filename
+ static char pathname[1024]; // Filename + directory
+
+// There seems to be a little bit of a bug...sometimes
+// the returned path can start with '//'. I think the
+// Unix file system handles this OK ("ls //tmp" works),
+// but lets clean it up anyway.
+
+ if (strlen (directory_) >= 2 &&
+ directory_[0] == '/' && directory_[1] == '/')
+ {
+ memmove (directory_, directory_ + 1, strlen (directory_));
+ }
+
+ if (type_ != MULTI)
+ {
+ name = fileName->value();
+ if (name[0] == '\0')
+ return (NULL);
+
+ sprintf(pathname, "%s/%s", directory_, name);
+ return ((const char *)pathname);
+ }
+
+ for (i = 1, count = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i))
+ {
+ // See if this file is a directory...
+ name = fileList->text(i);
+ sprintf(pathname, "%s/%s", directory_, name);
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ {
+ // Nope, see if this this is "the one"...
+ count ++;
+ if (count == f)
+ return ((const char *)pathname);
+ }
+ }
+
+ return (NULL);
+}
+
+
+//
+// 'FileChooser::value()' - Set the current filename.
+//
+
+void
+FileChooser::value(const char *filename) // I - Filename + directory
+{
+ int i, // Looping var
+ count; // Number of items in list
+ char *slash; // Directory separator
+ char pathname[1024]; // Local copy of filename
+
+
+ // See if the filename is actually a directory...
+ if (filename == NULL || filename_isdir(filename))
+ {
+ // Yes, just change the current directory...
+ directory(filename);
+ return;
+ }
+
+ // Switch to single-selection mode as needed
+ if (type_ == MULTI)
+ type(SINGLE);
+
+ // See if there is a directory in there...
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+
+ if ((slash = strrchr(pathname, '/')) == NULL)
+ slash = strrchr(pathname, '\\');
+
+ if (slash != NULL)
+ {
+ // Yes, change the display to the directory...
+ *slash++ = '\0';
+ directory(pathname);
+ }
+ else
+ slash = pathname;
+
+ // Set the input field to the remaining portion
+ fileName->value(slash);
+ fileName->position(0, strlen(slash));
+ okButton->activate();
+
+ // Then find the file in the file list and select it...
+ count = fileList->size();
+
+ for (i = 1; i <= count; i ++)
+ if (strcmp(fileList->text(i), slash) == 0)
+ {
+ fileList->select(i);
+ break;
+ }
+}
+
+
+//
+// 'FileChooser::up()' - Go up one directory.
+//
+
+void
+FileChooser::up()
+{
+ char *slash; // Trailing slash
+
+
+ if ((slash = strrchr(directory_, '/')) == NULL)
+ slash = strrchr(directory_, '\\');
+
+ if (directory_[0] != '\0')
+ dirMenu->value(dirMenu->value() - 1);
+
+ if (slash != NULL)
+ *slash = '\0';
+ else
+ {
+ upButton->deactivate();
+ directory_[0] = '\0';
+ }
+
+ rescan();
+}
+
+
+//
+// 'FileChooser::newdir()' - Make a new directory.
+//
+
+void
+FileChooser::newdir()
+{
+ const char *dir; // New directory name
+ char pathname[1024]; // Full path of directory
+
+
+ // Get a directory name from the user
+ if ((dir = fl_input("New Directory?", NULL)) == NULL)
+ return;
+
+ // Make it relative to the current directory as needed...
+#if defined(WIN32) || defined(__EMX__)
+ if (dir[0] != '/' && dir[0] != '\\' && dir[1] != ':')
+#else
+ if (dir[0] != '/' && dir[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ sprintf(pathname, "%s/%s", directory_, dir);
+ else
+ {
+ strncpy(pathname, dir, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ // Create the directory; ignore EEXIST errors...
+#if defined(WIN32) || defined(__EMX__)
+ if (mkdir(pathname))
+#else
+ if (mkdir(pathname, 0777))
+#endif /* WIN32 || __EMX__ */
+ if (errno != EEXIST)
+ {
+ fl_alert("Unable to create directory!");
+ return;
+ }
+
+ // Show the new directory...
+ directory(pathname);
+}
+
+
+//
+// 'FileChooser::rescan()' - Rescan the current directory.
+//
+
+void
+FileChooser::rescan()
+{
+ // Clear the current filename
+ fileName->value("");
+ okButton->deactivate();
+
+ // Build the file list...
+ fileList->load(directory_);
+}
+
+
+//
+// 'FileChooser::fileListCB()' - Handle clicks (and double-clicks) in the
+// FileBrowser.
+//
+
+void
+FileChooser::fileListCB()
+{
+ char *filename, // New filename
+ pathname[1024]; // Full pathname to file
+
+
+ filename = (char *)fileList->text(fileList->value());
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (Fl::event_clicks())
+ {
+#if defined(WIN32) || defined(__EMX__)
+ if ((strlen(pathname) == 2 && pathname[1] == ':') ||
+ filename_isdir(pathname))
+#else
+ if (filename_isdir(pathname))
+#endif /* WIN32 || __EMX__ */
+ {
+ directory(pathname);
+ upButton->activate();
+ }
+ else
+ window->hide();
+ }
+ else
+ {
+ fileName->value(filename);
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ okButton->activate();
+ }
+}
+
+
+//
+// 'FileChooser::fileNameCB()' - Handle text entry in the FileBrowser.
+//
+
+void
+FileChooser::fileNameCB()
+{
+ char *filename, // New filename
+ *slash, // Pointer to trailing slash
+ pathname[1024]; // Full pathname to file
+ int i, // Looping var
+ min_match, // Minimum number of matching chars
+ max_match, // Maximum number of matching chars
+ num_files, // Number of files in directory
+ first_line; // First matching line
+ const char *file; // File from directory
+
+
+ // Get the filename from the text field...
+ filename = (char *)fileName->value();
+
+ if (filename == NULL || filename[0] == '\0')
+ {
+ okButton->deactivate();
+ return;
+ }
+
+#if defined(WIN32) || defined(__EMX__)
+ if (directory_[0] != '\0' &&
+ filename[0] != '/' &&
+ filename[0] != '\\' &&
+ !(isalpha(filename[0]) && filename[1] == ':'))
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+#else
+ if (directory_[0] != '\0' &&
+ filename[0] != '/')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+#endif /* WIN32 || __EMX__ */
+
+ if (Fl::event_key() == FL_Enter)
+ {
+ // Enter pressed - select or change directory...
+
+#if defined(WIN32) || defined(__EMX__)
+ if (((strlen(pathname) == 2 && pathname[1] == ':') ||
+ filename_isdir(pathname)) && !directory_chooser_)
+#else
+ if (filename_isdir(pathname) && !directory_chooser_)
+#endif /* WIN32 || __EMX__ */
+ directory(pathname);
+ else if (type_ == CREATE || access(pathname, 0) == 0)
+ {
+ // New file or file exists... If we are in multiple selection mode,
+ // switch to single selection mode...
+ if (type_ == MULTI)
+ type(SINGLE);
+
+ // Hide the window to signal things are done...
+ window->hide();
+ }
+ else
+ {
+ // File doesn't exist, so beep at and alert the user...
+ // TODO: NEED TO ADD fl_beep() FUNCTION TO 2.0!
+#ifdef WIN32
+ MessageBeep(MB_ICONEXCLAMATION);
+#else
+ XBell(fl_display, 100);
+#endif // WIN32
+
+ fl_alert("Please choose an existing file!");
+ }
+ }
+ else if (Fl::event_key() != FL_Delete)
+ {
+ // Check to see if the user has entered a directory...
+ if ((slash = strrchr(filename, '/')) == NULL)
+ slash = strrchr(filename, '\\');
+
+ if (slash != NULL)
+ {
+ // Yes, change directories and update the file name field...
+ if ((slash = strrchr(pathname, '/')) == NULL)
+ slash = strrchr(pathname, '\\');
+
+ if (slash > pathname) // Special case for "/"
+ *slash++ = '\0';
+ else
+ slash++;
+
+ if (strcmp(filename, "../") == 0) // Special case for "../"
+ up();
+ else
+ directory(pathname);
+
+ // If the string ended after the slash, we're done for now...
+ if (*slash == '\0')
+ return;
+
+ // Otherwise copy the remainder and proceed...
+ fileName->value(slash);
+ fileName->position(strlen(slash));
+ filename = slash;
+ }
+
+ // Other key pressed - do filename completion as possible...
+ num_files = fileList->size();
+ min_match = strlen(filename);
+ max_match = 100000;
+ first_line = 0;
+
+ for (i = 1; i <= num_files && max_match > min_match; i ++)
+ {
+ file = fileList->text(i);
+
+#if defined(WIN32) || defined(__EMX__)
+ if (strnicmp(filename, file, min_match) == 0)
+#else
+ if (strncmp(filename, file, min_match) == 0)
+#endif // WIN32 || __EMX__
+ {
+ // OK, this one matches; check against the previous match
+ if (max_match == 100000)
+ {
+ // First match; copy stuff over...
+ strncpy(pathname, file, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ max_match = strlen(pathname);
+
+ // And then make sure that the item is visible
+ fileList->topline(i);
+ first_line = i;
+ }
+ else
+ {
+ // Succeeding match; compare to find maximum string match...
+ while (max_match > min_match)
+#if defined(WIN32) || defined(__EMX__)
+ if (strnicmp(file, pathname, max_match) == 0)
+#else
+ if (strncmp(file, pathname, max_match) == 0)
+#endif // WIN32 || __EMX__
+ break;
+ else
+ max_match --;
+
+ // Truncate the string as needed...
+ pathname[max_match] = '\0';
+ }
+ }
+ }
+
+ fileList->deselect(0);
+ fileList->redraw();
+
+ // If we have any matches, add them to the input field...
+ if (first_line > 0 && min_match == max_match &&
+ max_match == (int)strlen(fileList->text(first_line)))
+ fileList->select(first_line);
+ else if (max_match > min_match && max_match != 100000)
+ {
+ // Add the matching portion...
+ fileName->replace(0, min_match, pathname);
+
+ // Highlight it; if the user just pressed the backspace
+ // key, position the cursor at the start of the selection.
+ // Otherwise, put the cursor at the end of the selection so
+ // s/he can press the right arrow to accept the selection
+ // (Tab and End also do this for both cases.)
+ if (Fl::event_key() == FL_BackSpace)
+ fileName->position(min_match - 1, max_match);
+ else
+ fileName->position(max_match, min_match);
+ }
+
+ // See if we need to enable the OK button...
+ sprintf(pathname, "%s/%s", directory_, fileName->value());
+
+ if ((type_ == CREATE || access(pathname, 0) == 0) &&
+ (!filename_isdir(pathname) || directory_chooser_))
+ okButton->activate();
+ else
+ okButton->deactivate();
+ }
+}
+
+
+//
+// End of "$Id: FileChooser2.cxx,v 1.22 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileIcon.cxx b/SrcUnix/espws-2.0/FileIcon.cxx
new file mode 100644
index 0000000..9eae59a
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileIcon.cxx
@@ -0,0 +1,1217 @@
+//
+// "$Id: FileIcon.cxx,v 1.19 2000/01/22 15:21:07 mike Exp $"
+//
+// FileIcon routines.
+//
+// KDE icon code donated by Maarten De Boer.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// FileIcon::FileIcon() - Create a new file icon.
+// FileIcon::~FileIcon() - Remove a file icon.
+// FileIcon::add() - Add data to an icon.
+// FileIcon::find() - Find an icon based upon a given file.
+// FileIcon::draw() - Draw an icon.
+// FileIcon::label() - Set the widgets label to an icon.
+// FileIcon::labeltype() - Draw the icon label.
+// FileIcon::load() - Load an icon file...
+// FileIcon::load_fti() - Load an SGI-format FTI file...
+// FileIcon::load_xpm() - Load an XPM icon file...
+// FileIcon::load_system_icons() - Load the standard system icons/filetypes.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+# define F_OK 0
+# define strcasecmp stricmp
+# define strncasecmp strnicmp
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+#include "FileIcon.h"
+
+#include <FL/Fl_Widget.H>
+#include <FL/fl_draw.H>
+#include <FL/filename.H>
+
+
+//
+// Define missing POSIX/XPG4 macros as needed...
+//
+
+#ifndef S_ISDIR
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif /* !S_ISDIR */
+
+
+//
+// Icon cache...
+//
+
+FileIcon *FileIcon::first_ = (FileIcon *)0;
+
+
+//
+// Local functions...
+//
+
+static void load_kde_icons(const char *directory);
+static void load_kde_mimelnk(const char *filename);
+static char *kde_to_fltk_pattern(const char *kdepattern);
+static char *get_kde_val(char *str, const char *key);
+
+
+//
+// 'FileIcon::FileIcon()' - Create a new file icon.
+//
+
+FileIcon::FileIcon(const char *p, /* I - Filename pattern */
+ int t, /* I - File type */
+ int nd, /* I - Number of data values */
+ short *d) /* I - Data values */
+{
+ // Initialize the pattern and type...
+ pattern_ = p;
+ type_ = t;
+
+ // Copy icon data as needed...
+ if (nd)
+ {
+ num_data_ = nd;
+ alloc_data_ = nd + 1;
+ data_ = (short *)calloc(sizeof(short), nd + 1);
+ memcpy(data_, d, nd * sizeof(short));
+ }
+ else
+ {
+ num_data_ = 0;
+ alloc_data_ = 0;
+ }
+
+ // And add the icon to the list of icons...
+ next_ = first_;
+ first_ = this;
+}
+
+
+//
+// 'FileIcon::~FileIcon()' - Remove a file icon.
+//
+
+FileIcon::~FileIcon()
+{
+ FileIcon *current, // Current icon in list
+ *prev; // Previous icon in list
+
+
+ // Find the icon in the list...
+ for (current = first_, prev = (FileIcon *)0;
+ current != this && current != (FileIcon *)0;
+ prev = current, current = current->next_);
+
+ // Remove the icon from the list as needed...
+ if (current)
+ {
+ if (prev)
+ prev->next_ = current->next_;
+ else
+ first_ = current->next_;
+ }
+
+ // Free any memory used...
+ if (alloc_data_)
+ free(data_);
+}
+
+
+//
+// 'FileIcon::add()' - Add data to an icon.
+//
+
+short * // O - Pointer to new data value
+FileIcon::add(short d) // I - Data to add
+{
+ short *dptr; // Pointer to new data value
+
+
+ // Allocate/reallocate memory as needed
+ if ((num_data_ + 1) >= alloc_data_)
+ {
+ alloc_data_ += 128;
+
+ if (alloc_data_ == 128)
+ dptr = (short *)malloc(sizeof(short) * alloc_data_);
+ else
+ dptr = (short *)realloc(data_, sizeof(short) * alloc_data_);
+
+ if (dptr == NULL)
+ return (NULL);
+
+ data_ = dptr;
+ }
+
+ // Store the new data value and return
+ data_[num_data_++] = d;
+ data_[num_data_] = END;
+
+ return (data_ + num_data_ - 1);
+}
+
+
+//
+// 'FileIcon::find()' - Find an icon based upon a given file.
+//
+
+FileIcon * // O - Matching file icon or NULL
+FileIcon::find(const char *filename, // I - Name of file */
+ int filetype) // I - Enumerated file type
+{
+ FileIcon *current; // Current file in list
+ struct stat fileinfo; // Information on file
+
+
+ // Get file information if needed...
+ if (filetype == ANY)
+ if (!stat(filename, &fileinfo))
+ {
+ if (S_ISDIR(fileinfo.st_mode))
+ filetype = DIRECTORY;
+#ifdef S_IFIFO
+ else if (S_ISFIFO(fileinfo.st_mode))
+ filetype = FIFO;
+#endif // S_IFIFO
+#if defined(S_ICHR) && defined(S_IBLK)
+ else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode))
+ filetype = DEVICE;
+#endif // S_ICHR && S_IBLK
+#ifdef S_ILNK
+ else if (S_ISLNK(fileinfo.st_mode))
+ filetype = LINK;
+#endif // S_ILNK
+ else
+ filetype = PLAIN;
+ }
+
+ // Loop through the available file types and return any match that
+ // is found...
+ for (current = first_; current != (FileIcon *)0; current = current->next_)
+ if ((current->type_ == filetype || current->type_ == ANY) &&
+ filename_match(filename, current->pattern_))
+ break;
+
+ // Return the match (if any)...
+ return (current);
+}
+
+
+//
+// 'FileIcon::draw()' - Draw an icon.
+//
+
+void
+FileIcon::draw(int x, // I - Upper-lefthand X
+ int y, // I - Upper-lefthand Y
+ int w, // I - Width of bounding box
+ int h, // I - Height of bounding box
+ Fl_Color ic, // I - Icon color...
+ int active) // I - Active or inactive?
+{
+ Fl_Color c; // Current color
+ short *d; // Pointer to data
+ short *prim; // Pointer to start of primitive...
+ double scale; // Scale of icon
+
+
+ // Don't try to draw a NULL array!
+ if (num_data_ == 0)
+ return;
+
+ // Setup the transform matrix as needed...
+ scale = w < h ? w : h;
+
+ fl_push_matrix();
+ fl_translate((float)x + 0.5 * ((float)w - scale),
+ (float)y + 0.5 * ((float)h + scale));
+ fl_scale(scale, -scale);
+
+ // Loop through the array until we see an unmatched END...
+ d = data_;
+ prim = NULL;
+ c = ic;
+
+ if (active)
+ fl_color(c);
+ else
+ fl_color(fl_inactive(c));
+
+ while (*d != END || prim)
+ switch (*d)
+ {
+ case END :
+ switch (*prim)
+ {
+ case LINE :
+ fl_end_line();
+ break;
+
+ case CLOSEDLINE :
+ fl_end_loop();
+ break;
+
+ case POLYGON :
+ fl_end_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ fl_end_polygon();
+
+ if (active)
+ {
+ if (prim[1] == 256)
+ fl_color(ic);
+ else
+ fl_color((Fl_Color)prim[1]);
+ }
+ else
+ {
+ if (prim[1] == 256)
+ fl_color(fl_inactive(ic));
+ else
+ fl_color(fl_inactive((Fl_Color)prim[1]));
+ }
+
+ fl_begin_loop();
+
+ prim += 2;
+ while (*prim == VERTEX)
+ {
+ fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
+ prim += 3;
+ }
+
+ fl_end_loop();
+ fl_color(c);
+ break;
+ }
+
+ prim = NULL;
+ d ++;
+ break;
+
+ case COLOR :
+ if (d[1] == 256)
+ c = ic;
+ else
+ c = (Fl_Color)d[1];
+
+ if (!active)
+ c = fl_inactive(c);
+
+ fl_color(c);
+ d += 2;
+ break;
+
+ case LINE :
+ prim = d;
+ d ++;
+ fl_begin_line();
+ break;
+
+ case CLOSEDLINE :
+ prim = d;
+ d ++;
+ fl_begin_loop();
+ break;
+
+ case POLYGON :
+ prim = d;
+ d ++;
+ fl_begin_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ prim = d;
+ d += 2;
+ fl_begin_polygon();
+ break;
+
+ case VERTEX :
+ if (prim)
+ fl_vertex(d[1] * 0.0001, d[2] * 0.0001);
+ d += 3;
+ break;
+ }
+
+ // If we still have an open primitive, close it...
+ if (prim)
+ switch (*prim)
+ {
+ case LINE :
+ fl_end_line();
+ break;
+
+ case CLOSEDLINE :
+ fl_end_loop();
+ break;
+
+ case POLYGON :
+ fl_end_polygon();
+ break;
+
+ case OUTLINEPOLYGON :
+ fl_end_polygon();
+
+ if (active)
+ {
+ if (prim[1] == 256)
+ fl_color(ic);
+ else
+ fl_color((Fl_Color)prim[1]);
+ }
+ else
+ {
+ if (prim[1] == 256)
+ fl_color(fl_inactive(ic));
+ else
+ fl_color(fl_inactive((Fl_Color)prim[1]));
+ }
+
+ fl_begin_loop();
+
+ prim += 2;
+ while (*prim == VERTEX)
+ {
+ fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001);
+ prim += 3;
+ }
+
+ fl_end_loop();
+ fl_color(c);
+ break;
+ }
+
+ // Restore the transform matrix
+ fl_pop_matrix();
+}
+
+
+//
+// 'FileIcon::label()' - Set the widget's label to an icon.
+//
+
+void
+FileIcon::label(Fl_Widget *w) // I - Widget to label
+{
+ Fl::set_labeltype(_FL_ICON_LABEL, labeltype, 0);
+ w->label(_FL_ICON_LABEL, (const char*)this);
+}
+
+
+//
+// 'FileIcon::labeltype()' - Draw the icon label.
+//
+
+void
+FileIcon::labeltype(const Fl_Label *o, // I - Label data
+ int x, // I - X position of label
+ int y, // I - Y position of label
+ int w, // I - Width of label
+ int h, // I - Height of label
+ Fl_Align a) // I - Label alignment (not used)
+{
+ FileIcon *icon; // Pointer to icon data
+
+
+ icon = (FileIcon *)(o->value);
+
+ icon->draw(x, y, w, h, (Fl_Color)(o->color));
+}
+
+
+//
+// 'FileIcon::load()' - Load an icon file...
+//
+
+void
+FileIcon::load(const char *f) // I - File to read from
+{
+ const char *ext; // File extension
+
+
+ if ((ext = filename_ext(f)) == NULL)
+ {
+ fprintf(stderr, "FileIcon::load(): Unknown file type for \"%s\".\n", f);
+ return;
+ }
+
+ if (strcmp(ext, ".fti") == 0)
+ load_fti(f);
+ else if (strcmp(ext, ".xpm") == 0)
+ load_xpm(f);
+#if 0
+ else if (strcmp(ext, ".png") == 0)
+ load_png(f);
+#endif /* 0 */
+ else
+ {
+ fprintf(stderr, "FileIcon::load(): Unknown file type for \"%s\".\n", f);
+ return;
+ }
+}
+
+
+//
+// 'FileIcon::load_fti()' - Load an SGI-format FTI file...
+//
+
+void
+FileIcon::load_fti(const char *fti) // I - File to read from
+{
+ FILE *fp; // File pointer
+ int ch; // Current character
+ char command[255], // Command string ("vertex", etc.)
+ params[255], // Parameter string ("10.0,20.0", etc.)
+ *ptr; // Pointer into strings
+ int outline; // Outline polygon
+
+
+ // Try to open the file...
+ if ((fp = fopen(fti, "r")) == NULL)
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Unable to open \"%s\" - %s\n",
+ fti, strerror(errno));
+ return;
+ }
+
+ // Read the entire file, adding data as needed...
+ outline = 0;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ // Skip whitespace
+ if (isspace(ch))
+ continue;
+
+ // Skip comments starting with "#"...
+ if (ch == '#')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\n')
+ break;
+
+ if (ch == EOF)
+ break;
+ else
+ continue;
+ }
+
+ // OK, this character better be a letter...
+ if (!isalpha(ch))
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Expected a letter at file position %d (saw '%c')\n",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Scan the command name...
+ ptr = command;
+ *ptr++ = ch;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == '(')
+ break;
+ else if ((ptr - command) < (sizeof(command) - 1))
+ *ptr++ = ch;
+ }
+
+ *ptr++ = '\0';
+
+ // Make sure we stopped on a parenthesis...
+ if (ch != '(')
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Expected a ( at file position %d (saw '%c')\n",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Scan the parameters...
+ ptr = params;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == ')')
+ break;
+ else if ((ptr - params) < (sizeof(params) - 1))
+ *ptr++ = ch;
+ }
+
+ *ptr++ = '\0';
+
+ // Make sure we stopped on a parenthesis...
+ if (ch != ')')
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Expected a ) at file position %d (saw '%c')\n",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Make sure the next character is a semicolon...
+ if ((ch = getc(fp)) != ';')
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Expected a ; at file position %d (saw '%c')\n",
+ ftell(fp) - 1, ch);
+ break;
+ }
+
+ // Now process the command...
+ if (strcmp(command, "color") == 0)
+ {
+ // Set the color; for negative colors blend the two primaries to
+ // produce a composite color. Also, the following symbolic color
+ // names are understood:
+ //
+ // name FLTK color
+ // ------------- ----------
+ // iconcolor 256; mapped to the icon color in FileIcon::draw()
+ // shadowcolor FL_DARK3
+ // outlinecolor FL_BLACK
+ if (strcmp(params, "iconcolor") == 0)
+ add_color(256);
+ else if (strcmp(params, "shadowcolor") == 0)
+ add_color(FL_DARK3);
+ else if (strcmp(params, "outlinecolor") == 0)
+ add_color(FL_BLACK);
+ else
+ {
+ short c = atoi(params); // Color value
+
+
+ if (c < 0)
+ {
+ // Composite color; compute average...
+ c = -c;
+ add_color(fl_color_average((Fl_Color)(c >> 4),
+ (Fl_Color)(c & 15), 0.5));
+ }
+ else
+ add_color(c);
+ }
+ }
+ else if (strcmp(command, "bgnline") == 0)
+ add(LINE);
+ else if (strcmp(command, "bgnclosedline") == 0)
+ add(CLOSEDLINE);
+ else if (strcmp(command, "bgnpolygon") == 0)
+ add(POLYGON);
+ else if (strcmp(command, "bgnoutlinepolygon") == 0)
+ {
+ add(OUTLINEPOLYGON);
+ outline = add(0) - data_;
+ }
+ else if (strcmp(command, "endoutlinepolygon") == 0 && outline)
+ {
+ // Set the outline color; see above for valid values...
+ if (strcmp(params, "iconcolor") == 0)
+ data_[outline] = 256;
+ else if (strcmp(params, "shadowcolor") == 0)
+ data_[outline] = FL_DARK3;
+ else if (strcmp(params, "outlinecolor") == 0)
+ data_[outline] = FL_BLACK;
+ else
+ {
+ short c = atoi(params); // Color value
+
+
+ if (c < 0)
+ {
+ // Composite color; compute average...
+ c = -c;
+ data_[outline] = fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5);
+ }
+ else
+ data_[outline] = c;
+ }
+
+ outline = 0;
+ add(END);
+ }
+ else if (strncmp(command, "end", 3) == 0)
+ add(END);
+ else if (strcmp(command, "vertex") == 0)
+ {
+ float x, y; // Coordinates of vertex
+
+
+ if (sscanf(params, "%f,%f", &x, &y) != 2)
+ break;
+
+ add_vertex((short)(x * 100.0 + 0.5), (short)(y * 100.0 + 0.5));
+ }
+ else
+ {
+ fprintf(stderr, "FileIcon::load_fti(): Unknown command \"%s\" at file position %d.\n",
+ command, ftell(fp) - 1);
+ break;
+ }
+ }
+
+ // Close the file and return...
+ fclose(fp);
+
+#ifdef DEBUG
+ printf("Icon File \"%s\":\n", fti);
+ for (int i = 0; i < num_data_; i ++)
+ printf(" %d,\n", data_[i]);
+#endif /* DEBUG */
+}
+
+
+//
+// 'FileIcon::load_xpm()' - Load an XPM icon file...
+//
+
+void
+FileIcon::load_xpm(const char *xpm) // I - File to read from
+{
+ FILE *fp; // File pointer
+ int i, j; // Looping vars
+ int ch; // Current character
+ int bg; // Background color
+ char line[1024], // Line from file
+ val[16], // Color value
+ *ptr; // Pointer into line
+ int x, y; // X & Y in image
+ int startx; // Starting X coord
+ int width, height; // Width and height of image
+ int ncolors; // Number of colors
+ short colors[256]; // Colors
+ int red, green, blue; // Red, green, and blue values
+
+
+ // Try to open the file...
+ if ((fp = fopen(xpm, "r")) == NULL)
+ return;
+
+ // Read the file header until we find the first string...
+ while (fgets(line, sizeof(line), fp) != NULL)
+ if ((ptr = strchr(line, '\"')) != NULL)
+ break;
+
+ if (ptr == NULL)
+ {
+ // Nothing to load...
+ fclose(fp);
+ return;
+ }
+
+ // Get the size of the image...
+ sscanf(ptr + 1, "%d%d%d", &width, &height, &ncolors);
+
+ // Now read the colormap...
+ memset(colors, 0, sizeof(colors));
+ bg = ' ';
+
+ for (i = 0; i < ncolors; i ++)
+ {
+ while (fgets(line, sizeof(line), fp) != NULL)
+ if ((ptr = strchr(line, '\"')) != NULL)
+ break;
+
+ if (ptr == NULL)
+ {
+ // Nothing to load...
+ fclose(fp);
+ return;
+ }
+
+ // Get the color's character
+ ptr ++;
+ ch = *ptr++;
+
+ // Get the color value...
+ if ((ptr = strstr(ptr, "c ")) == NULL)
+ {
+ // No color; make this black...
+ colors[ch] = FL_BLACK;
+ }
+ else if (ptr[2] == '#')
+ {
+ // Read the RGB triplet...
+ ptr += 3;
+ for (j = 0; j < 12; j ++)
+ if (!isxdigit(ptr[j]))
+ break;
+
+ switch (j)
+ {
+ case 0 :
+ bg = ch;
+ default :
+ red = green = blue = 0;
+ break;
+
+ case 3 :
+ val[0] = ptr[0];
+ val[1] = '\0';
+ red = 255 * strtol(val, NULL, 16) / 15;
+
+ val[0] = ptr[1];
+ val[1] = '\0';
+ green = 255 * strtol(val, NULL, 16) / 15;
+
+ val[0] = ptr[2];
+ val[1] = '\0';
+ blue = 255 * strtol(val, NULL, 16) / 15;
+ break;
+
+ case 6 :
+ case 9 :
+ case 12 :
+ j /= 3;
+
+ val[0] = ptr[0];
+ val[1] = ptr[1];
+ val[2] = '\0';
+ red = strtol(val, NULL, 16);
+
+ val[0] = ptr[j + 0];
+ val[1] = ptr[j + 1];
+ val[2] = '\0';
+ green = strtol(val, NULL, 16);
+
+ val[0] = ptr[2 * j + 0];
+ val[1] = ptr[2 * j + 1];
+ val[2] = '\0';
+ blue = strtol(val, NULL, 16);
+ break;
+ }
+
+ if (red == green && green == blue)
+ colors[ch] = FL_GRAY_RAMP + (FL_NUM_GRAY - 1) * red / 255;
+ else
+ colors[ch] = fl_color_cube((FL_NUM_RED - 1) * red / 255,
+ (FL_NUM_GREEN - 1) * green / 255,
+ (FL_NUM_BLUE - 1) * blue / 255);
+ }
+ else
+ {
+ // Read a color name...
+ if (strncasecmp(ptr + 2, "white", 5) == 0)
+ colors[ch] = FL_WHITE;
+ else if (strncasecmp(ptr + 2, "black", 5) == 0)
+ colors[ch] = FL_BLACK;
+ else if (strncasecmp(ptr + 2, "none", 4) == 0)
+ {
+ colors[ch] = FL_BLACK;
+ bg = ch;
+ }
+ else
+ colors[ch] = FL_GRAY;
+ }
+ }
+
+ // Read the image data...
+ for (y = height - 1; y >= 0; y --)
+ {
+ while (fgets(line, sizeof(line), fp) != NULL)
+ if ((ptr = strchr(line, '\"')) != NULL)
+ break;
+
+ if (ptr == NULL)
+ {
+ // Nothing to load...
+ fclose(fp);
+ return;
+ }
+
+ ch = bg;
+ ptr ++;
+
+ for (x = 0; x < width; x ++, ptr ++)
+ if (*ptr != ch)
+ {
+ if (ch != bg)
+ {
+ add_color(colors[ch]);
+ add(POLYGON);
+ add_vertex(startx * 9000 / width + 1000, y * 9000 / height + 500);
+ add_vertex(x * 9000 / width + 1000, y * 9000 / height + 500);
+ add_vertex(x * 9000 / width + 1000, (y + 1) * 9000 / height + 500);
+ add_vertex(startx * 9000 / width + 1000, (y + 1) * 9000 / height + 500);
+ add(END);
+ }
+
+ ch = *ptr;
+ startx = x;
+ }
+
+ if (ch != bg)
+ {
+ add_color(colors[ch]);
+ add(POLYGON);
+ add_vertex(startx * 9000 / width + 1000, y * 9000 / height + 500);
+ add_vertex(x * 9000 / width + 1000, y * 9000 / height + 500);
+ add_vertex(x * 9000 / width + 1000, (y + 1) * 9000 / height + 500);
+ add_vertex(startx * 9000 / width + 1000, (y + 1) * 9000 / height + 500);
+ add(END);
+ }
+ }
+
+ // Close the file and return...
+ fclose(fp);
+
+#ifdef DEBUG
+ printf("Icon File \"%s\":\n", xpm);
+ for (i = 0; i < num_data_; i ++)
+ printf(" %d,\n", data_[i]);
+#endif /* DEBUG */
+}
+
+
+//
+// 'FileIcon::load_system_icons()' - Load the standard system icons/filetypes.
+
+void
+FileIcon::load_system_icons(void)
+{
+ FileIcon *icon; // New icons
+ static int init = 0; // Have the icons been initialized?
+ static short plain[] = // Plain file icon
+ {
+ COLOR, 256, OUTLINEPOLYGON, FL_GRAY,
+ VERTEX, 2000, 1000, VERTEX, 2000, 9000,
+ VERTEX, 6000, 9000, VERTEX, 8000, 7000,
+ VERTEX, 8000, 1000, END, OUTLINEPOLYGON, FL_GRAY,
+ VERTEX, 6000, 9000, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, END,
+ COLOR, FL_BLACK, LINE, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, VERTEX, 8000, 1000,
+ VERTEX, 2000, 1000, END, LINE, VERTEX, 3000, 7000,
+ VERTEX, 5000, 7000, END, LINE, VERTEX, 3000, 6000,
+ VERTEX, 5000, 6000, END, LINE, VERTEX, 3000, 5000,
+ VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000,
+ VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000,
+ VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000,
+ VERTEX, 7000, 2000, END,
+ END
+ };
+ static short image[] = // Image file icon
+ {
+ COLOR, 256, OUTLINEPOLYGON, FL_GRAY,
+ VERTEX, 2000, 1000, VERTEX, 2000, 9000,
+ VERTEX, 6000, 9000, VERTEX, 8000, 7000,
+ VERTEX, 8000, 1000, END, OUTLINEPOLYGON, FL_GRAY,
+ VERTEX, 6000, 9000, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, END,
+ COLOR, FL_BLACK, LINE, VERTEX, 6000, 7000,
+ VERTEX, 8000, 7000, VERTEX, 8000, 1000,
+ VERTEX, 2000, 1000, END,
+ COLOR, FL_RED, POLYGON, VERTEX, 3500, 2500,
+ VERTEX, 3000, 3000, VERTEX, 3000, 4000,
+ VERTEX, 3500, 4500, VERTEX, 4500, 4500,
+ VERTEX, 5000, 4000, VERTEX, 5000, 3000,
+ VERTEX, 4500, 2500, END,
+ COLOR, FL_GREEN, POLYGON, VERTEX, 5500, 2500,
+ VERTEX, 5000, 3000, VERTEX, 5000, 4000,
+ VERTEX, 5500, 4500, VERTEX, 6500, 4500,
+ VERTEX, 7000, 4000, VERTEX, 7000, 3000,
+ VERTEX, 6500, 2500, END,
+ COLOR, FL_BLUE, POLYGON, VERTEX, 4500, 3500,
+ VERTEX, 4000, 4000, VERTEX, 4000, 5000,
+ VERTEX, 4500, 5500, VERTEX, 5500, 5500,
+ VERTEX, 6000, 5000, VERTEX, 6000, 4000,
+ VERTEX, 5500, 3500, END,
+ END
+ };
+ static short dir[] = // Directory icon
+ {
+ COLOR, 256, POLYGON, VERTEX, 1000, 1000,
+ VERTEX, 1000, 7500, VERTEX, 9000, 7500,
+ VERTEX, 9000, 1000, END,
+ POLYGON, VERTEX, 1000, 7500, VERTEX, 2500, 9000,
+ VERTEX, 5000, 9000, VERTEX, 6500, 7500, END,
+ COLOR, FL_WHITE, LINE, VERTEX, 1500, 1500,
+ VERTEX, 1500, 7000, VERTEX, 9000, 7000, END,
+ COLOR, FL_BLACK, LINE, VERTEX, 9000, 7500,
+ VERTEX, 9000, 1000, VERTEX, 1000, 1000, END,
+ COLOR, FL_GRAY, LINE, VERTEX, 1000, 1000,
+ VERTEX, 1000, 7500, VERTEX, 2500, 9000,
+ VERTEX, 5000, 9000, VERTEX, 6500, 7500,
+ VERTEX, 9000, 7500, END,
+ END
+ };
+
+
+ // Add symbols if they haven't been added already...
+ if (!init)
+ {
+ if (!access("/usr/share/mimelnk", F_OK))
+ {
+ // Load KDE icons...
+ icon = new FileIcon("*", FileIcon::PLAIN);
+ icon->load_xpm("/usr/share/icons/unknown.xpm");
+
+ load_kde_icons("/usr/share/mimelnk");
+ }
+ else if (!access("/usr/share/icons/folder.xpm", F_OK))
+ {
+ // Load GNOME icons...
+ icon = new FileIcon("*", FileIcon::PLAIN);
+ icon->load_xpm("/usr/share/icons/page.xpm");
+
+ icon = new FileIcon("*", FileIcon::DIRECTORY);
+ icon->load_xpm("/usr/share/icons/folder.xpm");
+ }
+ else if (!access("/usr/dt/appconfig/icons", F_OK))
+ {
+ // Load CDE icons...
+ icon = new FileIcon("*", FileIcon::PLAIN);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/Dtdata.m.pm");
+
+ icon = new FileIcon("*", FileIcon::DIRECTORY);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/DtdirB.m.pm");
+
+ icon = new FileIcon("core", FileIcon::PLAIN);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/Dtcore.m.pm");
+
+ icon = new FileIcon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", FileIcon::PLAIN);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/Dtimage.m.pm");
+
+ icon = new FileIcon("*.{eps|pdf|ps}", FileIcon::PLAIN);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/Dtps.m.pm");
+
+ icon = new FileIcon("*.ppd", FileIcon::PLAIN);
+ icon->load_xpm("/usr/dt/appconfig/icons/C/DtPrtpr.m.pm");
+ }
+ else if (!access("/usr/lib/filetype", F_OK))
+ {
+ // Load SGI icons...
+ icon = new FileIcon("*", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
+
+ icon = new FileIcon("*", FileIcon::DIRECTORY);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.folder.closed.fti");
+
+ icon = new FileIcon("core", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/default/iconlib/CoreFile.fti");
+
+ icon = new FileIcon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/ImageFile.fti");
+
+ if (!access("/usr/lib/filetype/install/iconlib/acroread.doc.fti", F_OK))
+ {
+ icon = new FileIcon("*.{eps|ps}", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
+
+ icon = new FileIcon("*.pdf", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/install/iconlib/acroread.doc.fti");
+ }
+ else
+ {
+ icon = new FileIcon("*.{eps|pdf|ps}", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti");
+ }
+
+ if (!access("/usr/lib/filetype/install/iconlib/html.fti", F_OK))
+ {
+ icon = new FileIcon("*.{htm|html|shtml}", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti");
+ icon->load_fti("/usr/lib/filetype/install/iconlib/html.fti");
+ }
+
+ if (!access("/usr/lib/filetype/install/iconlib/color.ps.idle.fti", F_OK))
+ {
+ icon = new FileIcon("*.ppd", FileIcon::PLAIN);
+ icon->load_fti("/usr/lib/filetype/install/iconlib/color.ps.idle.fti");
+ }
+ }
+ else
+ {
+ // Create the default icons...
+ new FileIcon("*", FileIcon::PLAIN, sizeof(plain) / sizeof(plain[0]), plain);
+ new FileIcon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", FileIcon::PLAIN,
+ sizeof(image) / sizeof(image[0]), image);
+ new FileIcon("*", FileIcon::DIRECTORY, sizeof(dir) / sizeof(dir[0]), dir);
+ }
+
+ // Mark things as initialized...
+ init = 1;
+ }
+}
+
+
+//
+// 'load_kde_icons()' - Load KDE icon files.
+//
+
+static void
+load_kde_icons(const char *directory) // I - Directory to load
+{
+ int i; // Looping var
+ int n; // Number of entries in directory
+ dirent **entries; // Entries in directory
+ char full[1024]; // Full name of file
+
+
+ entries = (dirent **)0;
+ n = filename_list(directory, &entries);
+
+ for (i = 0; i < n; i ++)
+ {
+ if (entries[i]->d_name[0] != '.')
+ {
+ strcpy(full, directory);
+ strcat(full,"/");
+ strcat(full, entries[i]->d_name);
+
+ if (filename_isdir(full))
+ load_kde_icons(full);
+ else
+ load_kde_mimelnk(full);
+ }
+
+ free((void *)entries[i]);
+ }
+
+ free((void*)entries);
+}
+
+
+//
+// 'load_kde_mimelnk()' - Load a KDE "mimelnk" file.
+//
+
+static void
+load_kde_mimelnk(const char *filename)
+{
+ FILE *fp;
+ char tmp[256];
+ char iconfilename[1024];
+ char pattern[1024];
+ char mimetype[1024];
+ char *val;
+ char full_iconfilename[1024];
+ FileIcon *icon;
+
+
+ if ((fp = fopen(filename, "r")) != NULL)
+ {
+ while (fgets(tmp, sizeof(tmp), fp))
+ {
+ if ((val = get_kde_val(tmp, "Icon")) != NULL)
+ strcpy(iconfilename, val);
+ else if ((val = get_kde_val(tmp, "MimeType")) != NULL)
+ strcpy(mimetype, val);
+ else if ((val = get_kde_val(tmp, "Patterns")) != NULL)
+ strcpy(pattern, val);
+ }
+
+ if (iconfilename && pattern)
+ {
+ sprintf(full_iconfilename, "/usr/share/icons/%s", iconfilename);
+
+ if (mimetype && strcmp(mimetype, "inode/directory") == 0)
+ icon = new FileIcon("*", FileIcon::DIRECTORY);
+ else
+ icon = new FileIcon(kde_to_fltk_pattern(pattern), FileIcon::PLAIN);
+
+ icon->load_xpm(full_iconfilename);
+ }
+
+ fclose(fp);
+ }
+}
+
+
+//
+// 'kde_to_fltk_pattern()' - Convert a KDE pattern to a FLTK pattern.
+//
+
+static char *
+kde_to_fltk_pattern(const char *kdepattern)
+{
+ char *pattern,
+ *patptr;
+
+
+ pattern = (char *)malloc(strlen(kdepattern) + 3);
+ strcpy(pattern, "{");
+ strcat(pattern, kdepattern);
+
+ if (pattern[strlen(pattern) - 1] == ';')
+ pattern[strlen(pattern) - 1] = '\0';
+
+ strcat(pattern, "}");
+
+ for (patptr = pattern; *patptr; patptr ++)
+ if (*patptr == ';')
+ *patptr = '|';
+
+ return (pattern);
+}
+
+
+//
+// 'get_kde_val()' - Get a KDE value.
+//
+
+static char *
+get_kde_val(char *str,
+ const char *key)
+{
+ while (*str == *key)
+ {
+ str ++;
+ key ++;
+ }
+
+ if (*key == '\0' && *str == '=')
+ {
+ if (str[strlen(str) - 1] == '\n')
+ str[strlen(str) - 1] = '\0';
+
+ return (str + 1);
+ }
+
+ return ((char *)0);
+}
+
+
+//
+// End of "$Id: FileIcon.cxx,v 1.19 2000/01/22 15:21:07 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileIcon.h b/SrcUnix/espws-2.0/FileIcon.h
new file mode 100644
index 0000000..2705a0d
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileIcon.h
@@ -0,0 +1,112 @@
+//
+// "$Id: FileIcon.h,v 1.8 2000/01/04 13:45:51 mike Exp $"
+//
+// FileIcon definitions.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+
+//
+// Include necessary header files...
+//
+
+#ifndef _GUI_FILEICON_H_
+# define _GUI_FILEICON_H_
+
+# include <FL/Fl.H>
+
+
+//
+// FileIcon class...
+//
+
+class FileIcon //// Icon data
+{
+ static FileIcon *first_; // Pointer to first icon/filetype
+ FileIcon *next_; // Pointer to next icon/filetype
+ const char *pattern_; // Pattern string
+ int type_; // Match only if directory or file?
+ int num_data_; // Number of data elements
+ int alloc_data_; // Number of allocated elements
+ short *data_; // Icon data
+
+ public:
+
+ enum // File types
+ {
+ ANY, // Any kind of file
+ PLAIN, // Only plain files
+ FIFO, // Only named pipes
+ DEVICE, // Only character and block devices
+ LINK, // Only symbolic links
+ DIRECTORY // Only directories
+ };
+
+ enum // Data opcodes
+ {
+ END, // End of primitive/icon
+ COLOR, // Followed by color index
+ LINE, // Start of line
+ CLOSEDLINE, // Start of closed line
+ POLYGON, // Start of polygon
+ OUTLINEPOLYGON, // Followed by outline color
+ VERTEX // Followed by scaled X,Y
+ };
+
+ FileIcon(const char *p, int t, int nd = 0, short *d = 0);
+ ~FileIcon();
+
+ short *add(short d);
+ short *add_color(short c)
+ { short *d = add(COLOR); add(c); return (d); }
+ short *add_vertex(int x, int y)
+ { short *d = add(VERTEX); add(x); add(y); return (d); }
+ short *add_vertex(float x, float y)
+ { short *d = add(VERTEX); add((int)(x * 10000.0));
+ add((int)(y * 10000.0)); return (d); }
+ void clear() { num_data_ = 0; }
+ void draw(int x, int y, int w, int h, Fl_Color ic, int active = 1);
+ void label(Fl_Widget *w);
+ static void labeltype(const Fl_Label *o, int x, int y, int w, int h, Fl_Align a);
+ void load(const char *f);
+ void load_fti(const char *fti);
+ void load_xpm(const char *xpm);
+ const char *pattern() { return (pattern_); }
+ int size() { return (num_data_); }
+ int type() { return (type_); }
+ short *value() { return (data_); }
+
+ static FileIcon *find(const char *filename, int filetype = ANY);
+ static FileIcon *first() { return (first_); }
+ static void load_system_icons(void);
+};
+
+#define _FL_ICON_LABEL FL_FREE_LABELTYPE
+
+#if FL_MAJOR_VERSION == 1 && FL_MINOR_VERSION == 0
+// FLTK 1.0.x defined these functions without the "fl_" prefix.
+#define fl_contrast contrast
+#define fl_inactive inactive
+#endif
+
+#endif // !_GUI_FILEICON_H_
+
+//
+// End of "$Id: FileIcon.h,v 1.8 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileIcon.html b/SrcUnix/espws-2.0/FileIcon.html
new file mode 100644
index 0000000..bd60fb9
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileIcon.html
@@ -0,0 +1,165 @@
+<HTML>
+<HEAD>
+ <TITLE>FileIcon - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class FileIcon</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+<B>FileIcon</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "FileIcon.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>FileIcon</CODE> class manages icon images that can be
+used as labels in other widgets and as icons in the <CODE>FileBrowser</CODE>
+widget.
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#FileIcon.FileIcon">FileIcon</A>
+ <LI><A HREF="#FileIcon.~FileIcon">~FileIcon</A>
+ <LI><A HREF="#FileIcon.add">add</A>
+ <LI><A HREF="#FileIcon.add_color">add_color</A>
+ <LI><A HREF="#FileIcon.add_vertex">add_vertex</A>
+ <LI><A HREF="#FileIcon.clear">clear</A>
+ <LI><A HREF="#FileIcon.draw">draw</A>
+ <LI><A HREF="#FileIcon.find">find</A>
+ <LI><A HREF="#FileIcon.first">first</A>
+ <LI><A HREF="#FileIcon.label">label</A>
+ <LI><A HREF="#FileIcon.labeltype">labeltype</A>
+ <LI><A HREF="#FileIcon.load_fti">load_fti</A>
+ <LI><A HREF="#FileIcon.load">load</A>
+ <LI><A HREF="#FileIcon.load_system_icons">load_system_icons</A>
+ <LI><A HREF="#FileIcon.load_xpm">load_xpm</A>
+ <LI><A HREF="#FileIcon.pattern">pattern</A>
+ <LI><A HREF="#FileIcon.size">size</A>
+ <LI><A HREF="#FileIcon.type">type</A>
+ <LI><A HREF="#FileIcon.value">value</A>
+
+</UL>
+
+<H4><A NAME="FileIcon.FileIcon">FileIcon()</A></H4>
+
+<P>The constructor creates a new <CODE>FileIcon</CODE> with the specified
+information.
+
+<H4><A NAME="FileIcon.~FileIcon">~FileIcon()</A></H4>
+
+<P>The destructor destroys the icon and frees all memory that has been
+allocated for it.
+
+<H4><A NAME="FileIcon.add">short *add(short d)</A></H4>
+
+<P>Adds a keyword value to the icon array, returning a pointer to it.
+
+<H4><A NAME="FileIcon.add_color">short *add_color(short c)</A></H4>
+
+<P>Adds a color value to the icon array, returning a pointer to it.
+
+<H4><A NAME="FileIcon.add_vertex">short *add_vertex(int x, int y)<BR>
+short *add_vertex(float x, float y)</A></H4>
+
+<P>Adds a vertex value to the icon array, returning a pointer to it.
+The integer version accepts coordinates from 0 to 10000, while the
+floating point version goes from 0.0 to 1.0. The origin (0.0) is in
+the lower-lefthand corner of the icon.
+
+<H4><A NAME="FileIcon.clear">void clear()</A></H4>
+
+<P>Clears all icon data from the icon.
+
+<H4><A NAME="FileIcon.draw">void draw(int x, int y, int w, int h, Fl_Color ic, int active = 1)</A></H4>
+
+<P>Draws the icon in the indicated area.
+
+<H4><A NAME="FileIcon.find">static FileIcon *find(const char *filename, int filetype = ANY);</A></H4>
+
+<P>Finds an icon that matches the given filename and file type.
+
+<H4><A NAME="FileIcon.first">static FileIcon *first()</A></H4>
+
+<P>Returns a pointer to the first icon in the list.
+
+<H4><A NAME="FileIcon.label">void label(Fl_Widget *w)</A></H4>
+
+<P>Applies the icon to the widget, registering the <CODE>FileIcon</CODE>
+label type as needed.
+
+<H4><A NAME="FileIcon.labeltype">static void labeltype(const Fl_Label *o, int x, int y, int w, int h, Fl_Align a)</A></H4>
+
+<P>The labeltype function for icons.
+
+<H4><A NAME="FileIcon.load">void load(const char *f)</A></H4>
+
+<P>Loads the specified icon image. The format is deduced from the filename.
+
+<H4><A NAME="FileIcon.load_fti">void load_fti(const char *fti)</A></H4>
+
+<P>Loads an SGI icon file.
+
+<H4><A NAME="FileIcon.load_system_icons">static void load_system_icons(void)</A></H4>
+
+<P>Loads all system-defined icons. This call is useful when using the
+<CODE>FileChooser</CODE> widget and should be used when the application
+starts:
+
+<UL><PRE>
+FileIcon::load_system_icons();
+</PRE></UL>
+
+<H4><A NAME="FileIcon.load_xpm">void load_xpm(const char *xpm)</A></H4>
+
+<P>Loads an XPM icon file.
+
+<H4><A NAME="FileIcon.pattern">const char *pattern()</A></H4>
+
+<P>Returns the filename matching pattern for the icon.
+
+<H4><A NAME="FileIcon.size">int size()</A></H4>
+
+<P>Returns the number of words of data used by the icon.
+
+<H4><A NAME="FileIcon.type">int type()</A></H4>
+
+<P>Returns the filetype associated with the icon, which can be one of the
+following:
+
+<UL>
+ <LI><CODE>FileIcon::ANY</CODE>, any kind of file.
+ <LI><CODE>FileIcon::PLAIN</CODE>, plain files.
+ <LI><CODE>FileIcon::FIFO</CODE>, named pipes.
+ <LI><CODE>FileIcon::DEVICE</CODE>, character and block devices.
+ <LI><CODE>FileIcon::LINK</CODE>, symbolic links.
+ <LI><CODE>FileIcon::DIRECTORY</CODE>, directories.
+</UL>
+
+<H4><A NAME="FileIcon.value">short *value()</A></H4>
+
+<P>Returns the data array for the icon.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/FileInput.cxx b/SrcUnix/espws-2.0/FileInput.cxx
new file mode 100644
index 0000000..da96749
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileInput.cxx
@@ -0,0 +1,75 @@
+//
+// "$Id: FileInput.cxx,v 1.3 2000/01/04 13:45:51 mike Exp $"
+//
+// FileInput routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// FileInput::handle() - Handle tab events.
+//
+
+//
+// Include necessary header files...
+//
+
+#include <FL/Fl.H>
+#include "FileInput.h"
+
+//
+// Note: This has got to be a runner for the world's shortest class.
+// Basically the whole purpose of this subclass is to alter the
+// behavior of the Tab key; specifically if the user hits the
+// Tab key while text is selected, the cursor is moved to the
+// end of the selected text rather than doing the navigation
+// thing.
+//
+// This is a likely enhancement to the 2.0 Fl_Input widget...
+//
+
+//
+// 'FileInput::handle()' - Handle tab events.
+//
+
+int // O - 1 if we handled the event
+FileInput::handle(int event) // I - Event to handle
+{
+ if (event == FL_KEYBOARD && Fl::event_key() == FL_Tab &&
+ mark() != position())
+ {
+ // Set the current cursor position to the end of the selection...
+ if (mark() > position())
+ position(mark());
+ else
+ position(position());
+
+ return (1);
+ }
+ else
+ {
+ // Use the Fl_Input handler...
+ return (Fl_Input::handle(event));
+ }
+}
+
+
+//
+// End of "$Id: FileInput.cxx,v 1.3 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileInput.h b/SrcUnix/espws-2.0/FileInput.h
new file mode 100644
index 0000000..602b8b4
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileInput.h
@@ -0,0 +1,52 @@
+//
+// "$Id: FileInput.h,v 1.3 2000/01/04 13:45:51 mike Exp $"
+//
+// FileInput definitions.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+
+#ifndef _GUI_FILEINPUT_H_
+# define _GUI_FILEINPUT_H_
+
+//
+// Include necessary header files...
+//
+
+# include <FL/Fl_Input.H>
+
+
+//
+// (world's shortest) FileInput class...
+//
+
+class FileInput : public Fl_Input //// File input widget
+{
+ public:
+
+ FileInput(int x, int y, int w, int h, const char *l = 0) :
+ Fl_Input(x, y, w, h, l) {}
+ int handle(int);
+};
+
+#endif // !_GUI_FILEINPUT_H_
+
+//
+// End of "$Id: FileInput.h,v 1.3 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/FileInput.html b/SrcUnix/espws-2.0/FileInput.html
new file mode 100644
index 0000000..eb8c1b9
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileInput.html
@@ -0,0 +1,56 @@
+<HTML>
+<HEAD>
+ <TITLE>FileInput - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class FileInput</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Input
+ |
+ +----<B>FileInput</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "FileInput.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>FileInput</CODE> widget has got to be a candidate for the
+shortest widget ever. The only difference between it and the <CODE>Fl_Input</CODE>
+widget is that when text is selected in the input field, the <KBD>Tab</KBD> key
+will move the cursor to the end of the selection and clear the selection,
+instead of moving to the next input field.
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#FileInput.FileInput">FileInput</A>
+ <LI><A HREF="#FileInput.~FileInput">~FileInput</A>
+
+</UL>
+
+<H4><A NAME="FileInput.FileInput">FileInput(int xx, int yy, int ww, int hh, const char *l = 0)</A></H4>
+
+<P>The constructor creates the <CODE>FileInput</CODE> widget at the specified
+position and size.
+
+<H4><A NAME="FileInput.~FileInput">~FileInput()</A></H4>
+
+<P>The destructor destroys the widget and frees all memory that has been
+allocated.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/Fl_Wizard.cxx b/SrcUnix/espws-2.0/Fl_Wizard.cxx
new file mode 100644
index 0000000..149d930
--- /dev/null
+++ b/SrcUnix/espws-2.0/Fl_Wizard.cxx
@@ -0,0 +1,201 @@
+//
+// "$Id: Fl_Wizard.cxx,v 1.2 2000/01/04 13:45:51 mike Exp $"
+//
+// Fl_Wizard widget routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// Fl_Wizard::Fl_Wizard() - Create an Fl_Wizard widget.
+// Fl_Wizard::draw() - Draw the wizard border and visible child.
+// Fl_Wizard::next() - Show the next child.
+// Fl_Wizard::prev() - Show the previous child.
+// Fl_Wizard::value() - Return the current visible child.
+// Fl_Wizard::value() - Set the visible child.
+//
+
+//
+// Include necessary header files...
+//
+
+#include "Fl_Wizard.h"
+#include <FL/fl_draw.H>
+
+
+//
+// 'Fl_Wizard::Fl_Wizard()' - Create an Fl_Wizard widget.
+//
+
+Fl_Wizard::Fl_Wizard(int xx, // I - Lefthand position
+ int yy, // I - Upper position
+ int ww, // I - Width
+ int hh, // I - Height
+ const char *l) : // I - Label
+ Fl_Group(xx, yy, ww, hh, l)
+{
+ box(FL_THIN_UP_BOX);
+
+ value_ = (Fl_Widget *)0;
+}
+
+
+//
+// 'Fl_Wizard::draw()' - Draw the wizard border and visible child.
+//
+
+void
+Fl_Wizard::draw()
+{
+ Fl_Widget *kid; // Visible child
+
+
+ kid = value();
+
+ if (damage() & FL_DAMAGE_ALL)
+ {
+ // Redraw everything...
+ if (kid)
+ {
+ draw_box(box(), x(), y(), w(), h(), kid->color());
+ draw_child(*kid);
+ }
+ else
+ draw_box(box(), x(), y(), w(), h(), color());
+
+ }
+ else if (kid)
+ update_child(*kid);
+}
+
+
+//
+// 'Fl_Wizard::next()' - Show the next child.
+//
+
+void
+Fl_Wizard::next()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ if ((*kids)->visible())
+ break;
+
+ if (num_kids > 1)
+ value(kids[1]);
+}
+
+
+//
+// 'Fl_Wizard::prev()' - Show the previous child.
+//
+
+
+void
+Fl_Wizard::prev()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ if ((*kids)->visible())
+ break;
+
+ if (num_kids > 0 && num_kids < (children() - 1))
+ value(kids[-1]);
+}
+
+
+//
+// 'Fl_Wizard::value()' - Return the current visible child.
+//
+
+Fl_Widget *
+Fl_Wizard::value()
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+ Fl_Widget *kid;
+
+
+ if ((num_kids = children()) == 0)
+ return ((Fl_Widget *)0);
+
+ for (kids = array(), kid = (Fl_Widget *)0; num_kids > 0; kids ++, num_kids --)
+ {
+ if ((*kids)->visible())
+ {
+ if (kid)
+ (*kids)->hide();
+ else
+ kid = *kids;
+ }
+ }
+
+ if (!kid)
+ {
+ kids --;
+ kid = *kids;
+ kid->show();
+ }
+
+ return (kid);
+}
+
+
+//
+// 'Fl_Wizard::value()' - Set the visible child.
+//
+
+void
+Fl_Wizard::value(Fl_Widget *kid)
+{
+ int num_kids;
+ Fl_Widget * const *kids;
+
+
+ if ((num_kids = children()) == 0)
+ return;
+
+ for (kids = array(); num_kids > 0; kids ++, num_kids --)
+ {
+ if (*kids == kid)
+ {
+ if (!kid->visible())
+ kid->show();
+ }
+ else
+ (*kids)->hide();
+ }
+}
+
+
+//
+// End of "$Id: Fl_Wizard.cxx,v 1.2 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/Fl_Wizard.h b/SrcUnix/espws-2.0/Fl_Wizard.h
new file mode 100644
index 0000000..b92bd21
--- /dev/null
+++ b/SrcUnix/espws-2.0/Fl_Wizard.h
@@ -0,0 +1,59 @@
+//
+// "$Id: Fl_Wizard.h,v 1.2 2000/01/04 13:45:51 mike Exp $"
+//
+// Fl_Wizard widget definitions.
+//
+// Copyright 1999-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+
+//
+// Include necessary header files...
+//
+
+#ifndef _FL_WIZARD_H_
+# define _FL_WIZARD_H_
+
+# include <FL/Fl_Group.H>
+
+
+//
+// FileBrowser class...
+//
+
+class Fl_Wizard : public Fl_Group
+{
+ Fl_Widget *value_;
+
+ void draw();
+
+ public:
+
+ Fl_Wizard(int, int, int, int, const char * = 0);
+
+ void next();
+ void prev();
+ Fl_Widget *value();
+ void value(Fl_Widget *);
+};
+
+#endif // !_FL_WIZARD_H_
+
+//
+// End of "$Id: Fl_Wizard.h,v 1.2 2000/01/04 13:45:51 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/Fl_Wizard.html b/SrcUnix/espws-2.0/Fl_Wizard.html
new file mode 100644
index 0000000..45b7a42
--- /dev/null
+++ b/SrcUnix/espws-2.0/Fl_Wizard.html
@@ -0,0 +1,75 @@
+<HTML>
+<HEAD>
+ <TITLE>Fl_Wizard - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class Fl_Wizard</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Group
+ |
+ +----<B>Fl_Wizard</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "Fl_Wizard.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>Fl_Wizard</CODE> widget is based off the <CODE>Fl_Tabs</CODE>
+widget, but instead of displaying tabs it only changes "tabs" under
+program control. Its primary purpose is to support "wizards" that
+step a user through configuration or troubleshooting tasks.
+
+<P>As with <CODE>Fl_Tabs</CODE>, wizard panes are composed of child (usually
+<CODE>Fl_Group</CODE>) widgets. Navigation buttons must be added separately.
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#Fl_Wizard.Fl_Wizard">Fl_Wizard</A>
+ <LI><A HREF="#Fl_Wizard.~Fl_Wizard">~Fl_Wizard</A>
+ <LI><A HREF="#Fl_Wizard.next">next</A>
+ <LI><A HREF="#Fl_Wizard.prev">prev</A>
+ <LI><A HREF="#Fl_Wizard.value">value</A>
+
+</UL>
+
+<H4><A NAME="Fl_Wizard.Fl_Wizard">Fl_Wizard(int xx, int yy, int ww, int hh, const char *l = 0)</A></H4>
+
+<P>The constructor creates the <CODE>Fl_Wizard</CODE> widget at the specified
+position and size.
+
+<H4><A NAME="Fl_Wizard.~Fl_Wizard">~Fl_Wizard()</A></H4>
+
+<P>The destructor destroys the widget and its children.
+
+<H4><A NAME="Fl_Wizard.next">void next()</A></H4>
+
+<P>This method shows the next child of the wizard. If the last child
+is already visible, this function does nothing.
+
+<H4><A NAME="Fl_Wizard.prev">void prev()</A></H4>
+
+<P>This method shows the previous child of the wizard. If the first child
+is already visible, this function does nothing.
+
+<H4><A NAME="Fl_Wizard.value">void value(Fl_Widget *w)<BR>
+Fl_Widget *value()</A></H4>
+
+<P>Sets or gets the child widget that is visible.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/HelpApp.cxx b/SrcUnix/espws-2.0/HelpApp.cxx
new file mode 100644
index 0000000..180a94d
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpApp.cxx
@@ -0,0 +1,470 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#include "HelpApp.h"
+
+inline void HelpApp::cb_view__i(HelpView*, void*) {
+ if (view_->changed())
+{
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memcpy(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memcpy(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strcpy(file_[index_], view_->filename());
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+ location_->value(view_->filename());
+}
+else if (view_->filename())
+{
+ strncpy(file_[index_], view_->filename(), 255);
+ file_[index_][255] = '\0';
+ line_[index_] = view_->topline();
+};
+}
+void HelpApp::cb_view_(HelpView* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_view__i(o,v);
+}
+
+inline void HelpApp::cb_back__i(Fl_Button*, void*) {
+ back();
+}
+void HelpApp::cb_back_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_back__i(o,v);
+}
+
+inline void HelpApp::cb_forward__i(Fl_Button*, void*) {
+ forward();
+}
+void HelpApp::cb_forward_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_forward__i(o,v);
+}
+
+inline void HelpApp::cb_smaller__i(Fl_Button*, void*) {
+ if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();
+}
+void HelpApp::cb_smaller_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_smaller__i(o,v);
+}
+
+inline void HelpApp::cb_larger__i(Fl_Button*, void*) {
+ if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();
+}
+void HelpApp::cb_larger_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_larger__i(o,v);
+}
+
+inline void HelpApp::cb_home__i(Fl_Button*, void*) {
+ load(homepage_);
+}
+void HelpApp::cb_home_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_home__i(o,v);
+}
+
+#include <FL/Fl_Bitmap.H>
+static unsigned char bits_home[] =
+"\200\1@: ,\20(\b0\4 \6`\5\240t/T)T)t)\4+\4)\4)\374?";
+static Fl_Bitmap bitmap_home(bits_home, 16, 16);
+
+inline void HelpApp::cb_reload__i(Fl_Button*, void*) {
+ int top = view_->topline();
+view_->load(location_->value());
+view_->topline(top);
+}
+void HelpApp::cb_reload_(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_reload__i(o,v);
+}
+
+static unsigned char bits_reload[] =
+"\0\0\340\7\360\17""8\34\30""8\0p\0\370\4p\16 \37\0\16\0\34\30""8\34\360\17\
+\340\7\0\0";
+static Fl_Bitmap bitmap_reload(bits_reload, 16, 16);
+
+static unsigned char bits_stop[] =
+"\340\7\360\17\370\37\374?\376\177\377\377\211\315\335\252\331\312\333\352\
+\331\355\377\177\376?\374\37\370\17\360\7";
+static Fl_Bitmap bitmap_stop(bits_stop, 16, 16);
+
+inline void HelpApp::cb_New_i(Fl_Menu_*, void*) {
+ new HelpApp;
+}
+void HelpApp::cb_New(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_New_i(o,v);
+}
+
+inline void HelpApp::cb_Close_i(Fl_Menu_*, void*) {
+ window_->hide();
+}
+void HelpApp::cb_Close(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_Close_i(o,v);
+}
+
+inline void HelpApp::cb_Set_i(Fl_Menu_*, void*) {
+ strcpy(homepage_, location_->value());
+save_bookmarks();
+}
+void HelpApp::cb_Set(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_Set_i(o,v);
+}
+
+inline void HelpApp::cb_Set1_i(Fl_Menu_*, void*) {
+ const char *proxy;
+
+if ((proxy = fl_input("Enter the URL for the proxy server:", proxy_)) != NULL)
+{
+ strcpy(proxy_, proxy);
+ save_bookmarks();
+};
+}
+void HelpApp::cb_Set1(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_Set1_i(o,v);
+}
+
+inline void HelpApp::cb_E_i(Fl_Menu_*, void*) {
+ exit(0);
+}
+void HelpApp::cb_E(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_E_i(o,v);
+}
+
+Fl_Menu_Item HelpApp::menu_menubar_[] = {
+ {"&File", 0, 0, 0, 64, 0, 0, 14, 0},
+ {"&New", 0x4006e, (Fl_Callback*)HelpApp::cb_New, 0, 0, 0, 0, 14, 0},
+ {"&Open...", 0x4006f, 0, 0, 0, 0, 0, 14, 0},
+ {"&Close", 0x40077, (Fl_Callback*)HelpApp::cb_Close, 0, 128, 0, 0, 14, 0},
+ {"Set &Home Page", 0, (Fl_Callback*)HelpApp::cb_Set, 0, 0, 0, 0, 14, 0},
+ {"Set &Proxy", 0, (Fl_Callback*)HelpApp::cb_Set1, 0, 128, 0, 0, 14, 0},
+ {"E&xit", 0x40071, (Fl_Callback*)HelpApp::cb_E, 0, 0, 0, 0, 14, 0},
+ {0},
+ {"&Options", 0, 0, 0, 64, 0, 0, 14, 0},
+ {"&Toolbar", 0, 0, 0, 6, 0, 0, 14, 0},
+ {"&Location", 0, 0, 0, 134, 0, 0, 14, 0},
+ {0},
+ {"&Go", 0, 0, 0, 64, 0, 0, 14, 0},
+ {"&Back", 0, 0, 0, 0, 0, 0, 14, 0},
+ {"&Forward", 0, 0, 0, 0, 0, 0, 14, 0},
+ {"&Home", 0, 0, 0, 0, 0, 0, 14, 0},
+ {0},
+ {0}
+};
+
+inline void HelpApp::cb_location__i(Fl_Input*, void*) {
+ load(location_->value());
+}
+void HelpApp::cb_location_(Fl_Input* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_location__i(o,v);
+}
+
+inline void HelpApp::cb_bookmark__i(Fl_Menu_Button*, void*) {
+ show_bookmark();
+}
+void HelpApp::cb_bookmark_(Fl_Menu_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_bookmark__i(o,v);
+}
+
+inline void HelpApp::cb_Add_i(Fl_Menu_*, void*) {
+ add_bookmark(view_->title(), location_->value());
+save_bookmarks();
+}
+void HelpApp::cb_Add(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_Add_i(o,v);
+}
+
+inline void HelpApp::cb_Edit_i(Fl_Menu_*, void*) {
+ edit_bookmarks();
+}
+void HelpApp::cb_Edit(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->parent()->user_data()))->cb_Edit_i(o,v);
+}
+
+Fl_Menu_Item HelpApp::menu_bookmark_[] = {
+ {"Add", 0x40062, (Fl_Callback*)HelpApp::cb_Add, 0, 0, 0, 0, 14, 0},
+ {"Edit...", 0, (Fl_Callback*)HelpApp::cb_Edit, 0, 128, 0, 0, 14, 0},
+ {0}
+};
+
+inline void HelpApp::cb_bmList__i(Fl_Browser*, void*) {
+ list_cb(Fl::event_clicks());
+}
+void HelpApp::cb_bmList_(Fl_Browser* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_bmList__i(o,v);
+}
+
+inline void HelpApp::cb_bmProperties__i(Fl_Menu_*, void*) {
+ list_cb(1);
+}
+void HelpApp::cb_bmProperties_(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_bmProperties__i(o,v);
+}
+
+inline void HelpApp::cb_Close1_i(Fl_Menu_*, void*) {
+ bmWindow_->hide();
+}
+void HelpApp::cb_Close1(Fl_Menu_* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_Close1_i(o,v);
+}
+
+Fl_Menu_Item HelpApp::menu_bmMenubar_[] = {
+ {"&Edit", 0, 0, 0, 64, 0, 0, 14, 0},
+ {"Delete", 0xffff, 0, 0, 0, 0, 0, 14, 0},
+ {"Move Up", 0xffbf, 0, 0, 0, 0, 0, 14, 0},
+ {"Move Down", 0xffc0, 0, 0, 128, 0, 0, 14, 0},
+ {"Properties", 0xff0d, (Fl_Callback*)HelpApp::cb_bmProperties_, 0, 128, 0, 0, 14, 0},
+ {"Close", 0x40077, (Fl_Callback*)HelpApp::cb_Close1, 0, 0, 0, 0, 14, 0},
+ {0},
+ {0}
+};
+Fl_Menu_Item* HelpApp::bmDelete_ = HelpApp::menu_bmMenubar_ + 1;
+Fl_Menu_Item* HelpApp::bmMoveUp_ = HelpApp::menu_bmMenubar_ + 2;
+Fl_Menu_Item* HelpApp::bmMoveDown_ = HelpApp::menu_bmMenubar_ + 3;
+Fl_Menu_Item* HelpApp::bmProperties_ = HelpApp::menu_bmMenubar_ + 4;
+
+inline void HelpApp::cb_Cancel_i(Fl_Button*, void*) {
+ propWindow_->hide();
+}
+void HelpApp::cb_Cancel(Fl_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_Cancel_i(o,v);
+}
+
+inline void HelpApp::cb_OK_i(Fl_Return_Button*, void*) {
+ prop_cb();
+propWindow_->hide();
+}
+void HelpApp::cb_OK(Fl_Return_Button* o, void* v) {
+ ((HelpApp*)(o->parent()->user_data()))->cb_OK_i(o,v);
+}
+
+HelpApp::HelpApp() {
+ Fl_Window* w;
+ { Fl_Window* o = window_ = new Fl_Window(530, 385, "Help Application");
+ w = o;
+ o->user_data((void*)(this));
+ { HelpView* o = view_ = new HelpView(0, 95, 530, 270);
+ o->box(FL_DOWN_BOX);
+ o->callback((Fl_Callback*)cb_view_);
+ o->end();
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Box* o = status_ = new Fl_Box(0, 365, 530, 20, "Ready.");
+ o->box(FL_FLAT_BOX);
+ o->labelsize(12);
+ o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+ }
+ { Fl_Pack* o = toolbar_ = new Fl_Pack(0, 25, 530, 35);
+ o->type(1);
+ { Fl_Button* o = back_ = new Fl_Button(0, 25, 35, 35, "@-5<-");
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->shortcut(0xff51);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(2);
+ o->callback((Fl_Callback*)cb_back_);
+ }
+ { Fl_Button* o = forward_ = new Fl_Button(35, 25, 35, 35, "@-5->");
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->shortcut(0xff53);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(2);
+ o->callback((Fl_Callback*)cb_forward_);
+ }
+ { Fl_Button* o = smaller_ = new Fl_Button(70, 25, 35, 35, "F");
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->labelfont(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)cb_smaller_);
+ }
+ { Fl_Button* o = larger_ = new Fl_Button(105, 25, 35, 35, "F");
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->labelfont(1);
+ o->labelsize(16);
+ o->callback((Fl_Callback*)cb_larger_);
+ }
+ { Fl_Button* o = home_ = new Fl_Button(140, 25, 35, 35);
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ bitmap_home.label(o);
+ o->labelfont(1);
+ o->labelsize(16);
+ o->callback((Fl_Callback*)cb_home_);
+ }
+ { Fl_Button* o = reload_ = new Fl_Button(175, 25, 35, 35);
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->shortcut(0x40072);
+ bitmap_reload.label(o);
+ o->labelfont(1);
+ o->labelsize(16);
+ o->labelcolor(4);
+ o->callback((Fl_Callback*)cb_reload_);
+ }
+ { Fl_Button* o = stop_ = new Fl_Button(210, 25, 35, 35);
+ o->box(FL_FLAT_BOX);
+ o->down_box(FL_THIN_DOWN_BOX);
+ o->shortcut(0xff1b);
+ bitmap_stop.label(o);
+ o->labelfont(1);
+ o->labelsize(16);
+ o->labelcolor(1);
+ o->deactivate();
+ }
+ o->end();
+ }
+ { Fl_Menu_Bar* o = menubar_ = new Fl_Menu_Bar(0, 0, 530, 25);
+ o->menu(menu_menubar_);
+ }
+ { Fl_Group* o = locationbar_ = new Fl_Group(0, 60, 530, 35);
+ o->box(FL_UP_FRAME);
+ { Fl_Input* o = location_ = new Fl_Input(180, 65, 345, 25, "Location:");
+ o->callback((Fl_Callback*)cb_location_);
+ o->when(FL_WHEN_ENTER_KEY_ALWAYS);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Menu_Button* o = bookmark_ = new Fl_Menu_Button(5, 65, 105, 25, "Bookmarks");
+ o->box(FL_THIN_UP_BOX);
+ o->down_box(FL_FLAT_BOX);
+ o->callback((Fl_Callback*)cb_bookmark_);
+ o->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+ o->menu(menu_bookmark_);
+ }
+ o->end();
+ }
+ o->end();
+ }
+ { Fl_Window* o = bmWindow_ = new Fl_Window(239, 386, "Bookmarks");
+ w = o;
+ o->user_data((void*)(this));
+ { Fl_Browser* o = bmList_ = new Fl_Browser(0, 25, 240, 360);
+ o->type(3);
+ o->callback((Fl_Callback*)cb_bmList_);
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Menu_Bar* o = bmMenubar_ = new Fl_Menu_Bar(0, 0, 240, 25);
+ o->menu(menu_bmMenubar_);
+ }
+ o->end();
+ }
+ { Fl_Window* o = propWindow_ = new Fl_Window(385, 111, "Bookmark Properties");
+ w = o;
+ o->user_data((void*)(this));
+ { Fl_Input* o = propTitle_ = new Fl_Input(50, 10, 325, 25, "Title: ");
+ o->labelfont(1);
+ }
+ { Fl_Input* o = propURL_ = new Fl_Input(50, 40, 325, 25, "URL: ");
+ o->labelfont(1);
+ }
+ { Fl_Button* o = new Fl_Button(310, 75, 65, 25, "Cancel");
+ o->callback((Fl_Callback*)cb_Cancel);
+ }
+ { Fl_Return_Button* o = new Fl_Return_Button(240, 75, 65, 25, "OK");
+ o->callback((Fl_Callback*)cb_OK);
+ }
+ o->set_modal();
+ o->end();
+ }
+ back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;
+next_ = first_;
+first_ = this;
+view_->link(link);
+if (!bookmenu_)
+ load_bookmarks();
+window_->show();
+load(homepage_);
+}
+
+int HelpApp::h() {
+ return (window_->h());
+}
+
+void HelpApp::hide() {
+ window_->hide();
+}
+
+void HelpApp::load(const char *f) {
+ view_->set_changed();
+view_->load(f);
+window_->label(view_->title());
+}
+
+void HelpApp::position(int xx, int yy) {
+ window_->position(xx, yy);
+}
+
+void HelpApp::resize(int xx, int yy, int ww, int hh) {
+ window_->resize(xx, yy, ww, hh);
+}
+
+void HelpApp::show() {
+ window_->show();
+}
+
+void HelpApp::textsize(uchar s) {
+ view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();
+}
+
+uchar HelpApp::textsize() {
+ return (view_->textsize());
+}
+
+void HelpApp::topline(const char *n) {
+ view_->topline(n);
+}
+
+void HelpApp::topline(int n) {
+ view_->topline(n);
+}
+
+int HelpApp::visible() {
+ return (window_->visible());
+}
+
+int HelpApp::w() {
+ return (window_->w());
+}
+
+int HelpApp::x() {
+ return (window_->x());
+}
+
+int HelpApp::y() {
+ return (window_->y());
+}
diff --git a/SrcUnix/espws-2.0/HelpApp.fl b/SrcUnix/espws-2.0/HelpApp.fl
new file mode 100644
index 0000000..0d37d5b
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpApp.fl
@@ -0,0 +1,380 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0008
+header_name {.h}
+code_name {.cxx}
+gridx 5
+gridy 5
+snap 3
+class HelpApp {open
+} {
+ decl {static Fl_Menu_Item *bookmenu_;} {}
+ decl {static HelpApp *first_;} {}
+ decl {struct bookmark { char title[256], url[1024]; };} {}
+ decl {static int nbookmarks_;} {}
+ decl {static bookmark *bookmarks_;} {}
+ decl {static int prop_bookmark_;} {}
+ decl {static char homepage_[1024];} {}
+ decl {static char proxy_[1024];} {}
+ decl {int index_;} {}
+ decl {int max_;} {}
+ decl {HelpApp *next_;} {}
+ decl {int line_[100];} {}
+ decl {char file_[100][256];} {}
+ decl {static void add_bookmark(const char *title, const char *url);} {}
+ decl {static const char *link(const char *f);} {}
+ decl {static void load_bookmarks();} {}
+ decl {static void save_bookmarks();} {}
+ decl {static void set_status(const char *format, ...);} {}
+ decl {void back();} {}
+ decl {void forward();} {}
+ decl {void edit_bookmarks();} {}
+ decl {void list_cb(int clicks);} {}
+ decl {void prop_cb();} {}
+ decl {void show_bookmark();} {}
+ Function {HelpApp()} {open
+ } {
+ Fl_Window window_ {
+ label {Help Application} open
+ private xywh {444 35 530 385} hide resizable
+ code0 {\#include <string.h>}
+ code1 {\#include <FL/fl_ask.H>}
+ } {
+ Fl_Group view_ {
+ callback {if (view_->changed())
+{
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memcpy(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memcpy(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strcpy(file_[index_], view_->filename());
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+ location_->value(view_->filename());
+}
+else if (view_->filename())
+{
+ strncpy(file_[index_], view_->filename(), 255);
+ file_[index_][255] = '\\0';
+ line_[index_] = view_->topline();
+}} open
+ private xywh {0 95 530 270} box DOWN_BOX resizable
+ code0 {\#include "HelpView.h"}
+ class HelpView
+ } {}
+ Fl_Box status_ {
+ label {Ready.}
+ private xywh {0 365 530 20} box FLAT_BOX labelsize 12 align 20
+ }
+ Fl_Pack toolbar_ {
+ private xywh {0 25 530 35} type HORIZONTAL
+ } {
+ Fl_Button back_ {
+ label {@-5<-}
+ callback {back();}
+ private xywh {0 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX shortcut 0xff51 labeltype SYMBOL_LABEL labelcolor 2
+ }
+ Fl_Button forward_ {
+ label {@-5->}
+ callback {forward();}
+ private xywh {35 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX shortcut 0xff53 labeltype SYMBOL_LABEL labelcolor 2
+ }
+ Fl_Button smaller_ {
+ label F
+ callback {if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();}
+ private xywh {70 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX labelfont 1 labelsize 10
+ }
+ Fl_Button larger_ {
+ label F
+ callback {if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();}
+ private xywh {105 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX labelfont 1 labelsize 16
+ }
+ Fl_Button home_ {
+ label {home.xbm}
+ callback {load(homepage_);}
+ private xywh {140 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX labeltype image labelfont 1 labelsize 16
+ }
+ Fl_Button reload_ {
+ label {reload.xbm}
+ callback {int top = view_->topline();
+view_->load(location_->value());
+view_->topline(top);}
+ private xywh {175 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX shortcut 0x40072 labeltype image labelfont 1 labelsize 16 labelcolor 4
+ }
+ Fl_Button stop_ {
+ label {stop.xbm}
+ private xywh {210 25 35 35} box FLAT_BOX down_box THIN_DOWN_BOX shortcut 0xff1b labeltype image labelfont 1 labelsize 16 labelcolor 1 deactivate
+ }
+ }
+ Fl_Menu_Bar menubar_ {open
+ private xywh {0 0 530 25}
+ } {
+ submenu {} {
+ label {&File} open
+ xywh {0 0 100 20}
+ } {
+ menuitem {} {
+ label {&New}
+ callback {new HelpApp;}
+ xywh {0 0 100 20} shortcut 0x4006e
+ }
+ menuitem {} {
+ label {&Open...}
+ xywh {0 0 100 20} shortcut 0x4006f
+ }
+ menuitem {} {
+ label {&Close}
+ callback {window_->hide();}
+ xywh {0 0 100 20} shortcut 0x40077 divider
+ }
+ menuitem {} {
+ label {Set &Home Page}
+ callback {strcpy(homepage_, location_->value());
+save_bookmarks();}
+ xywh {0 0 100 20}
+ }
+ menuitem {} {
+ label {Set &Proxy}
+ callback {const char *proxy;
+
+if ((proxy = fl_input("Enter the URL for the proxy server:", proxy_)) != NULL)
+{
+ strcpy(proxy_, proxy);
+ save_bookmarks();
+}}
+ xywh {10 10 100 20} divider
+ }
+ menuitem {} {
+ label {E&xit}
+ callback {exit(0);}
+ xywh {0 0 100 20} shortcut 0x40071
+ code0 {\#include <stdlib.h>}
+ }
+ }
+ submenu {} {
+ label {&Options} open
+ xywh {0 0 100 20}
+ } {
+ menuitem {} {
+ label {&Toolbar}
+ xywh {0 0 100 20} type Toggle value 1
+ }
+ menuitem {} {
+ label {&Location}
+ xywh {0 0 100 20} type Toggle value 1 divider
+ }
+ }
+ submenu {} {
+ label {&Go} open
+ xywh {0 0 100 20}
+ } {
+ menuitem {} {
+ label {&Back}
+ xywh {0 0 100 20}
+ }
+ menuitem {} {
+ label {&Forward}
+ xywh {0 0 100 20}
+ }
+ menuitem {} {
+ label {&Home}
+ xywh {0 0 100 20}
+ }
+ }
+ }
+ Fl_Group locationbar_ {open
+ private xywh {0 60 530 35} box UP_FRAME
+ } {
+ Fl_Input location_ {
+ label {Location:}
+ callback {load(location_->value());}
+ private xywh {180 65 345 25} when 10 resizable
+ }
+ Fl_Menu_Button bookmark_ {
+ label Bookmarks
+ callback {show_bookmark();} open
+ private xywh {5 65 105 25} box THIN_UP_BOX down_box FLAT_BOX align 20
+ } {
+ menuitem {} {
+ label Add
+ callback {add_bookmark(view_->title(), location_->value());
+save_bookmarks();}
+ xywh {0 0 100 20} shortcut 0x40062
+ }
+ menuitem {} {
+ label {Edit...}
+ callback {edit_bookmarks();}
+ xywh {0 0 100 20} divider
+ }
+ }
+ }
+ }
+ Fl_Window bmWindow_ {
+ label Bookmarks open
+ private xywh {604 456 239 386} hide resizable
+ } {
+ Fl_Browser bmList_ {
+ callback {list_cb(Fl::event_clicks());}
+ private xywh {0 25 240 360} type Multi resizable
+ }
+ Fl_Menu_Bar bmMenubar_ {open
+ private xywh {0 0 240 25}
+ } {
+ submenu {} {
+ label {&Edit} open
+ xywh {0 0 100 20}
+ } {
+ menuitem bmDelete_ {
+ label Delete
+ private xywh {0 0 100 20} shortcut 0xffff
+ }
+ menuitem bmMoveUp_ {
+ label {Move Up} selected
+ private xywh {0 0 100 20} shortcut 0xffbf
+ }
+ menuitem bmMoveDown_ {
+ label {Move Down}
+ private xywh {0 0 100 20} shortcut 0xffc0 divider
+ }
+ menuitem bmProperties_ {
+ label Properties
+ callback {list_cb(1);}
+ private xywh {0 0 100 20} shortcut 0xff0d divider
+ }
+ menuitem {} {
+ label Close
+ callback {bmWindow_->hide();}
+ private xywh {0 0 100 20} shortcut 0x40077
+ }
+ }
+ }
+ }
+ Fl_Window propWindow_ {
+ label {Bookmark Properties} open
+ private xywh {340 68 385 111} hide modal
+ } {
+ Fl_Input propTitle_ {
+ label {Title: }
+ private xywh {50 10 325 25} labelfont 1
+ }
+ Fl_Input propURL_ {
+ label {URL: }
+ private xywh {50 40 325 25} labelfont 1
+ }
+ Fl_Button {} {
+ label Cancel
+ callback {propWindow_->hide();}
+ xywh {310 75 65 25}
+ }
+ Fl_Return_Button {} {
+ label OK
+ callback {prop_cb();
+propWindow_->hide();}
+ xywh {240 75 65 25}
+ }
+ }
+ code {back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;
+next_ = first_;
+first_ = this;
+view_->link(link);
+if (!bookmenu_)
+ load_bookmarks();
+window_->show();
+load(homepage_);} {}
+ }
+ Function {h()} {return_type int
+ } {
+ code {return (window_->h());} {}
+ }
+ Function {hide()} {return_type void
+ } {
+ code {window_->hide();} {}
+ }
+ Function {load(const char *f)} {return_type void
+ } {
+ code {view_->set_changed();
+view_->load(f);
+window_->label(view_->title());} {}
+ }
+ Function {position(int xx, int yy)} {return_type void
+ } {
+ code {window_->position(xx, yy);} {}
+ }
+ Function {resize(int xx, int yy, int ww, int hh)} {return_type void
+ } {
+ code {window_->resize(xx, yy, ww, hh);} {}
+ }
+ Function {show()} {return_type void
+ } {
+ code {window_->show();} {}
+ }
+ Function {textsize(uchar s)} {return_type void
+ } {
+ code {view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();} {}
+ }
+ Function {textsize()} {return_type uchar
+ } {
+ code {return (view_->textsize());} {}
+ }
+ Function {topline(const char *n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {topline(int n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {visible()} {return_type int
+ } {
+ code {return (window_->visible());} {}
+ }
+ Function {w()} {return_type int
+ } {
+ code {return (window_->w());} {}
+ }
+ Function {x()} {return_type int
+ } {
+ code {return (window_->x());} {}
+ }
+ Function {y()} {return_type int
+ } {
+ code {return (window_->y());} {}
+ }
+}
diff --git a/SrcUnix/espws-2.0/HelpApp.gif b/SrcUnix/espws-2.0/HelpApp.gif
new file mode 100644
index 0000000..66c8fab
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpApp.gif
Binary files differ
diff --git a/SrcUnix/espws-2.0/HelpApp.h b/SrcUnix/espws-2.0/HelpApp.h
new file mode 100644
index 0000000..4ed89d0
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpApp.h
@@ -0,0 +1,135 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#ifndef HelpApp_h
+#define HelpApp_h
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <string.h>
+#include <FL/fl_ask.H>
+#include "HelpView.h"
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <stdlib.h>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Menu_Button.H>
+#include <FL/Fl_Browser.H>
+#include <FL/Fl_Return_Button.H>
+
+class HelpApp {
+ static Fl_Menu_Item *bookmenu_;
+ static HelpApp *first_;
+ struct bookmark { char title[256], url[1024]; };
+ static int nbookmarks_;
+ static bookmark *bookmarks_;
+ static int prop_bookmark_;
+ static char homepage_[1024];
+ static char proxy_[1024];
+ int index_;
+ int max_;
+ HelpApp *next_;
+ int line_[100];
+ char file_[100][256];
+ static void add_bookmark(const char *title, const char *url);
+ static const char *link(const char *f);
+ static void load_bookmarks();
+ static void save_bookmarks();
+ static void set_status(const char *format, ...);
+ void back();
+ void forward();
+ void edit_bookmarks();
+ void list_cb(int clicks);
+ void prop_cb();
+ void show_bookmark();
+public:
+ HelpApp();
+private:
+ Fl_Window *window_;
+ HelpView *view_;
+ inline void cb_view__i(HelpView*, void*);
+ static void cb_view_(HelpView*, void*);
+ Fl_Box *status_;
+ Fl_Pack *toolbar_;
+ Fl_Button *back_;
+ inline void cb_back__i(Fl_Button*, void*);
+ static void cb_back_(Fl_Button*, void*);
+ Fl_Button *forward_;
+ inline void cb_forward__i(Fl_Button*, void*);
+ static void cb_forward_(Fl_Button*, void*);
+ Fl_Button *smaller_;
+ inline void cb_smaller__i(Fl_Button*, void*);
+ static void cb_smaller_(Fl_Button*, void*);
+ Fl_Button *larger_;
+ inline void cb_larger__i(Fl_Button*, void*);
+ static void cb_larger_(Fl_Button*, void*);
+ Fl_Button *home_;
+ inline void cb_home__i(Fl_Button*, void*);
+ static void cb_home_(Fl_Button*, void*);
+ Fl_Button *reload_;
+ inline void cb_reload__i(Fl_Button*, void*);
+ static void cb_reload_(Fl_Button*, void*);
+ Fl_Button *stop_;
+ Fl_Menu_Bar *menubar_;
+ static Fl_Menu_Item menu_menubar_[];
+ inline void cb_New_i(Fl_Menu_*, void*);
+ static void cb_New(Fl_Menu_*, void*);
+ inline void cb_Close_i(Fl_Menu_*, void*);
+ static void cb_Close(Fl_Menu_*, void*);
+ inline void cb_Set_i(Fl_Menu_*, void*);
+ static void cb_Set(Fl_Menu_*, void*);
+ inline void cb_Set1_i(Fl_Menu_*, void*);
+ static void cb_Set1(Fl_Menu_*, void*);
+ inline void cb_E_i(Fl_Menu_*, void*);
+ static void cb_E(Fl_Menu_*, void*);
+ Fl_Group *locationbar_;
+ Fl_Input *location_;
+ inline void cb_location__i(Fl_Input*, void*);
+ static void cb_location_(Fl_Input*, void*);
+ Fl_Menu_Button *bookmark_;
+ inline void cb_bookmark__i(Fl_Menu_Button*, void*);
+ static void cb_bookmark_(Fl_Menu_Button*, void*);
+ static Fl_Menu_Item menu_bookmark_[];
+ inline void cb_Add_i(Fl_Menu_*, void*);
+ static void cb_Add(Fl_Menu_*, void*);
+ inline void cb_Edit_i(Fl_Menu_*, void*);
+ static void cb_Edit(Fl_Menu_*, void*);
+ Fl_Window *bmWindow_;
+ Fl_Browser *bmList_;
+ inline void cb_bmList__i(Fl_Browser*, void*);
+ static void cb_bmList_(Fl_Browser*, void*);
+ Fl_Menu_Bar *bmMenubar_;
+ static Fl_Menu_Item menu_bmMenubar_[];
+ static Fl_Menu_Item *bmDelete_;
+ static Fl_Menu_Item *bmMoveUp_;
+ static Fl_Menu_Item *bmMoveDown_;
+ static Fl_Menu_Item *bmProperties_;
+ inline void cb_bmProperties__i(Fl_Menu_*, void*);
+ static void cb_bmProperties_(Fl_Menu_*, void*);
+ inline void cb_Close1_i(Fl_Menu_*, void*);
+ static void cb_Close1(Fl_Menu_*, void*);
+ Fl_Window *propWindow_;
+ Fl_Input *propTitle_;
+ Fl_Input *propURL_;
+ inline void cb_Cancel_i(Fl_Button*, void*);
+ static void cb_Cancel(Fl_Button*, void*);
+ inline void cb_OK_i(Fl_Return_Button*, void*);
+ static void cb_OK(Fl_Return_Button*, void*);
+public:
+ int h();
+ void hide();
+ void load(const char *f);
+ void position(int xx, int yy);
+ void resize(int xx, int yy, int ww, int hh);
+ void show();
+ void textsize(uchar s);
+ uchar textsize();
+ void topline(const char *n);
+ void topline(int n);
+ int visible();
+ int w();
+ int x();
+ int y();
+};
+#endif
diff --git a/SrcUnix/espws-2.0/HelpApp2.cxx b/SrcUnix/espws-2.0/HelpApp2.cxx
new file mode 100644
index 0000000..9b12150
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpApp2.cxx
@@ -0,0 +1,546 @@
+//
+// "$Id: HelpApp2.cxx,v 1.5 2000/03/19 19:10:20 mike Exp $"
+//
+// Help Application extra routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outblockd in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// HelpApp::add_bookmark() - Add a bookmark.
+// HelpApp::link() - Handle web accesses...
+// HelpApp::load_bookmarks() - Load bookmarks from disk.
+// HelpApp::save_bookmarks() - Save bookmarks to disk.
+// HelpApp::set_status() - Set the current status...
+// HelpApp::back() - Show the previous document in the history.
+// HelpApp::forward() - Show the next document in the history.
+//
+
+//
+// Include necessary header files...
+//
+
+#include "HelpApp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#ifdef HAVE_LIBCUPS
+# include <cups/http.h>
+#endif // HAVE_LIBCUPS */
+
+
+//
+// Globals for all windows...
+//
+
+Fl_Menu_Item *HelpApp::bookmenu_ = (Fl_Menu_Item *)0;
+HelpApp *HelpApp::first_ = (HelpApp *)0;
+int HelpApp::nbookmarks_ = 0;
+HelpApp::bookmark *HelpApp::bookmarks_;
+int HelpApp::prop_bookmark_ = 0;
+char HelpApp::proxy_[1024] = "";
+char HelpApp::homepage_[1024] = "http://www.fltk.org";
+
+
+//
+// 'HelpApp::add_bookmark()' - Add a bookmark.
+//
+
+void
+HelpApp::add_bookmark(const char *title, // I - Title
+ const char *url) // I - URL
+{
+ char buffer[1024], // Title name buffer
+ *bufptr; // Pointer into buffer
+ const char *titleptr; // Pointer into title
+ bookmark *temp; // New bookmark array
+ Fl_Menu_Item *menu; // New menu array
+ HelpApp *w; // Help windows
+
+
+ if (nbookmarks_ == 0)
+ temp = (bookmark *)malloc(sizeof(struct bookmark));
+ else
+ temp = (bookmark *)realloc(bookmarks_, (nbookmarks_ + 1) * sizeof(struct bookmark));
+
+ if (!temp)
+ return;
+
+ bookmarks_ = temp;
+ temp += nbookmarks_;
+ nbookmarks_ ++;
+
+ strcpy(temp->title, title);
+ strcpy(temp->url, url);
+
+ if (!bookmenu_)
+ {
+ menu = (Fl_Menu_Item *)malloc(sizeof(Fl_Menu_Item) * 4);
+ if (menu)
+ memcpy(menu, first_->bookmark_->menu(), sizeof(Fl_Menu_Item) * 2);
+ }
+ else
+ menu = (Fl_Menu_Item *)realloc(bookmenu_, sizeof(Fl_Menu_Item) * (3 + nbookmarks_));
+
+ if (!menu)
+ return;
+
+ bookmenu_ = menu;
+ menu += 1 + nbookmarks_;
+
+ for (bufptr = buffer, titleptr = title; *titleptr;)
+ {
+ if (*titleptr == '/')
+ *bufptr++ = '\\';
+ *bufptr++ = *titleptr++;
+ }
+
+ *bufptr++ = '\0';
+
+ memset(menu, 0, 2 * sizeof(Fl_Menu_Item));
+ menu->text = strdup(buffer);
+
+ for (w = first_; w; w = w->next_)
+ w->bookmark_->menu(bookmenu_);
+}
+
+
+//
+// 'HelpApp::link()' - Handle web accesses...
+//
+
+const char * // O - New filename or NULL
+HelpApp::link(const char *url) // I - URL for access...
+{
+#ifdef HAVE_LIBCUPS
+ char method[HTTP_MAX_URI], // URL method
+ username[HTTP_MAX_URI], // Username from URL
+ hostname[HTTP_MAX_URI], // Hostname from URL
+ host[HTTP_MAX_URI], // Host: field
+ resource[HTTP_MAX_URI]; // Resource from URL
+ int port; // Port number for method
+ http_t *http; // HTTP connection
+ http_status_t status; // HTTP status
+ FILE *fp; // Temporary file
+ char buffer[8192]; // Copy buffer
+ int bytes; // Number of bytes read
+ int tbytes; // Total number of bytes read
+ int length; // Content length
+ static char tempfile[1024]; // Temporary filename
+ static char auth[255] = ""; // Authentication string
+
+
+ if (strncmp(url, "file:", 5) == 0 || strchr(url, ':') == NULL)
+ return (url);
+
+ httpSeparate(url, method, username, hostname, &port, resource);
+ strcpy(host, hostname);
+
+ if (proxy_[0])
+ {
+ httpSeparate(proxy_, method, username, hostname, &port, resource);
+ strcpy(resource, url);
+ }
+
+ if (strcmp(method, "http") != 0 && strcmp(method, "ipp") != 0)
+ return (NULL);
+
+ set_status("Contacting host %s...", hostname);
+
+ if ((http = httpConnect(hostname, port)) == NULL)
+ {
+ set_status(NULL);
+ fl_alert("Unable to connect to %s:\n\n%s", hostname, strerror(errno));
+ return (NULL);
+ }
+
+ if (username[0])
+ httpEncode64(auth, username);
+
+ set_status("Host contacted, sending request...");
+
+ // Do HTTP GET requests until we succeed or error out...
+ do
+ {
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_HOST, host);
+
+ if (auth[0])
+ {
+ sprintf(buffer, "Basic %s", auth);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, buffer);
+ }
+
+ if (httpGet(http, resource))
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ const char *userpass;
+
+
+ sprintf(buffer, "Authentication required.\nEnter username:password for %s:",
+ host);
+ if ((userpass = fl_input(buffer, username)) == NULL)
+ break;
+
+ httpEncode64(auth, userpass);
+ httpFlush(http);
+ }
+ }
+ while (status == HTTP_UNAUTHORIZED);
+
+ // Copy the output from the server to a single temp file (no caching for now)
+ sprintf(tempfile, "%s/%d.html",
+ getenv("TMPDIR") == NULL ? "/var/tmp" : getenv("TMPDIR"), getuid());
+ if ((fp = fopen(tempfile, "wb")) == NULL)
+ {
+ set_status(NULL);
+ httpClose(http);
+ return (NULL);
+ }
+
+ length = atoi(httpGetField(http, HTTP_FIELD_CONTENT_LENGTH));
+ tbytes = 0;
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ {
+ tbytes += bytes;
+
+ if (length == 0)
+ set_status("Received %d bytes...", tbytes);
+ else
+ set_status("Received %d of %d bytes (%d%%)...", tbytes, length,
+ 100 * tbytes / length);
+
+ fwrite(buffer, 1, bytes, fp);
+ }
+
+ set_status(NULL);
+ fclose(fp);
+ httpClose(http);
+
+ return (tempfile);
+#else
+ return (url);
+#endif // HAVE_LIBCUPS
+}
+
+
+//
+// 'HelpApp::load_bookmarks()' - Load bookmarks from disk.
+//
+
+void
+HelpApp::load_bookmarks()
+{
+ char flsurfrc[1024]; // Filename
+ FILE *fp; // .flsurfrc file
+ char title[1024], // Title from file
+ url[1024]; // URL from file
+
+
+ if (getenv("HOME") == NULL)
+ return;
+
+ sprintf(flsurfrc, "%s/.flsurfrc", getenv("HOME"));
+
+ if ((fp = fopen(flsurfrc, "r")) == NULL)
+ return;
+
+ // Read home page URL and strip LF...
+ fgets(homepage_, sizeof(homepage_), fp);
+ homepage_[strlen(homepage_) - 1] = '\0';
+
+ // Read proxy URL and strip LF...
+ fgets(proxy_, sizeof(proxy_), fp);
+ proxy_[strlen(proxy_) - 1] = '\0';
+
+ // Read pairs of lines with the bookmark title and URL...
+ while (fgets(title, sizeof(title), fp) != NULL)
+ {
+ // Strip title LF
+ title[strlen(title) - 1] = '\0';
+
+ // Read URL and strip LF
+ fgets(url, sizeof(url), fp);
+ url[strlen(url) - 1] = '\0';
+
+ // Add the bookmark...
+ add_bookmark(title, url);
+ }
+
+ fclose(fp);
+}
+
+
+//
+// 'HelpApp::save_bookmarks()' - Save bookmarks to disk.
+//
+
+void
+HelpApp::save_bookmarks()
+{
+ int i; // Looping var
+ char flsurfrc[1024]; // Filename
+ FILE *fp; // .flsurfrc file
+
+
+ if (getenv("HOME") == NULL)
+ return;
+
+ sprintf(flsurfrc, "%s/.flsurfrc", getenv("HOME"));
+
+ if ((fp = fopen(flsurfrc, "w")) == NULL)
+ return;
+
+ // Write home page URL and strip LF...
+ fprintf(fp, "%s\n", homepage_);
+
+ // Write proxy URL and strip LF...
+ fprintf(fp, "%s\n", proxy_);
+
+ // Write pairs of lines with the bookmark title and URL...
+ for (i = 0; i < nbookmarks_; i ++)
+ {
+ fprintf(fp, "%s\n", bookmarks_[i].title);
+ fprintf(fp, "%s\n", bookmarks_[i].url);
+ }
+
+ fclose(fp);
+}
+
+
+//
+// 'HelpApp::set_status()' - Set the current status...
+//
+
+void
+HelpApp::set_status(const char *format, // I - printf-style string
+ ...) // I - Additional args as needed
+{
+ va_list ap; // Pointer to additional args
+ Fl_Cursor cursor; // Cursor to use...
+ HelpApp *w; // Help windows
+ static char status[1024]; // Status string...
+
+
+ if (format == NULL)
+ {
+ cursor = FL_CURSOR_DEFAULT;
+ strcpy(status, "Ready.");
+ }
+ else
+ {
+ cursor = FL_CURSOR_WAIT;
+ va_start(ap, format);
+ vsprintf(status, format, ap);
+ va_end(ap);
+ }
+
+ for (w = first_; w != NULL; w = w->next_)
+ {
+ w->window_->cursor(cursor);
+ w->status_->label(status);
+ w->status_->redraw();
+
+ if (format)
+ w->stop_->activate();
+ else
+ w->stop_->deactivate();
+ }
+
+ Fl::check();
+}
+
+
+//
+// 'HelpApp::back()' - Show the previous document in the history.
+//
+
+void
+HelpApp::back()
+{
+ if (index_ > 0)
+ index_ --;
+
+ if (index_ == 0)
+ back_->deactivate();
+
+ forward_->activate();
+
+ if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+ view_->topline(line_[index_]);
+ location_->value(view_->filename());
+ window_->label(view_->title());
+}
+
+
+//
+// 'HelpApp::forward()' - Show the next document in the history.
+//
+
+void
+HelpApp::forward()
+{
+ if (index_ < max_)
+ index_ ++;
+
+ if (index_ >= max_)
+ forward_->deactivate();
+
+ back_->activate();
+
+ if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+ view_->topline(line_[index_]);
+ location_->value(view_->filename());
+ window_->label(view_->title());
+}
+
+
+//
+// 'HelpApp::show_bookmark()' - Show a bookmark...
+//
+
+void
+HelpApp::show_bookmark()
+{
+ if (bookmark_->value() < 2)
+ return;
+
+ load(bookmarks_[bookmark_->value() - 2].url);
+}
+
+
+//
+// 'HelpApp::edit_bookmarks()' - Show the bookmark editing window.
+//
+
+void
+HelpApp::edit_bookmarks()
+{
+ HelpApp *h; // Current help windows...
+ int i; // Looping var
+ bookmark *b; // Current bookmark
+
+
+ // See if the bookmarks window is already open from another window...
+ for (h = first_; h != (HelpApp *)0; h = h->next_)
+ if (h->bmWindow_->shown())
+ break;
+
+ if (h)
+ h->bmWindow_->show(); // Raise the current window
+ else
+ {
+ // Fill the list with the current bookmarks...
+ bmList_->clear();
+ for (i = nbookmarks_, b = bookmarks_; i > 0; i --, b ++)
+ bmList_->add(b->title);
+
+ // Show the window...
+ bmWindow_->show();
+ }
+}
+
+
+//
+// 'HelpApp::list_cb()' - Handle clicks in the bookmark list.
+//
+
+void
+HelpApp::list_cb(int clicks)
+{
+ int i; // Current item
+ bookmark *b; // Current bookmark...
+
+
+ i = bmList_->value() - 1;
+
+ if (clicks && i >= 0)
+ {
+ // Double-click in list; show properties of current item...
+ b = bookmarks_ + i;
+ prop_bookmark_ = i;
+
+ propTitle_->value(b->title);
+ propURL_->value(b->url);
+ propWindow_->show();
+ }
+ else if (i)
+ {
+ bmDelete_->deactivate();
+ bmMoveUp_->deactivate();
+ bmMoveDown_->deactivate();
+ bmProperties_->deactivate();
+ }
+ else
+ {
+ bmDelete_->activate();
+ bmMoveUp_->activate();
+ bmMoveDown_->activate();
+ bmProperties_->activate();
+ }
+}
+
+
+//
+// 'HelpApp::prop_cb()' - Apply the changes to the current bookmark...
+//
+
+void
+HelpApp::prop_cb()
+{
+ HelpApp *h; // Current help windows...
+ bookmark *b; // Bookmark to change
+
+
+ // See which properties window is open...
+ for (h = first_; h != (HelpApp *)0; h = h->next_)
+ if (h->propWindow_->shown())
+ break;
+
+ if (h)
+ {
+ // Found it; copy the new values over...
+ b = bookmarks_ + prop_bookmark_;
+ strncpy(b->title, h->propTitle_->value(), sizeof(b->title) - 1);
+ strncpy(b->url, h->propURL_->value(), sizeof(b->url) - 1);
+
+ h->bmList_->remove(prop_bookmark_ + 1);
+ h->bmList_->insert(prop_bookmark_ + 1, b->title);
+
+ save_bookmarks();
+ }
+}
+
+
+//
+// End of "$Id: HelpApp2.cxx,v 1.5 2000/03/19 19:10:20 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/HelpDialog.cxx b/SrcUnix/espws-2.0/HelpDialog.cxx
new file mode 100644
index 0000000..9d1ee5c
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpDialog.cxx
@@ -0,0 +1,219 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#include "HelpDialog.h"
+
+inline void HelpDialog::cb_view__i(HelpView*, void*) {
+ if (view_->changed())
+{
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memcpy(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memcpy(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strcpy(file_[index_], view_->filename());
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+}
+else if (view_->filename())
+{
+ strncpy(file_[index_], view_->filename(), 255);
+ file_[index_][255] = '\0';
+ line_[index_] = view_->topline();
+};
+}
+void HelpDialog::cb_view_(HelpView* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_view__i(o,v);
+}
+
+inline void HelpDialog::cb_Close_i(Fl_Button*, void*) {
+ window_->hide();
+}
+void HelpDialog::cb_Close(Fl_Button* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_Close_i(o,v);
+}
+
+inline void HelpDialog::cb_back__i(Fl_Button*, void*) {
+ if (index_ > 0)
+ index_ --;
+
+if (index_ == 0)
+ back_->deactivate();
+
+forward_->activate();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(line_[index_]);
+}
+void HelpDialog::cb_back_(Fl_Button* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_back__i(o,v);
+}
+
+inline void HelpDialog::cb_forward__i(Fl_Button*, void*) {
+ if (index_ < max_)
+ index_ ++;
+
+if (index_ >= max_)
+ forward_->deactivate();
+
+back_->activate();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(line_[index_]);
+}
+void HelpDialog::cb_forward_(Fl_Button* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_forward__i(o,v);
+}
+
+inline void HelpDialog::cb_smaller__i(Fl_Button*, void*) {
+ if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();
+}
+void HelpDialog::cb_smaller_(Fl_Button* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_smaller__i(o,v);
+}
+
+inline void HelpDialog::cb_larger__i(Fl_Button*, void*) {
+ if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();
+}
+void HelpDialog::cb_larger_(Fl_Button* o, void* v) {
+ ((HelpDialog*)(o->parent()->user_data()))->cb_larger__i(o,v);
+}
+
+HelpDialog::HelpDialog() {
+ Fl_Window* w;
+ { Fl_Window* o = window_ = new Fl_Window(530, 385, "Help Dialog");
+ w = o;
+ o->user_data((void*)(this));
+ { HelpView* o = view_ = new HelpView(10, 10, 510, 330);
+ o->box(FL_DOWN_BOX);
+ o->callback((Fl_Callback*)cb_view_);
+ o->end();
+ Fl_Group::current()->resizable(o);
+ }
+ { Fl_Button* o = new Fl_Button(465, 350, 55, 25, "Close");
+ o->callback((Fl_Callback*)cb_Close);
+ }
+ { Fl_Button* o = back_ = new Fl_Button(405, 350, 25, 25, "@<-");
+ o->shortcut(0xff51);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(2);
+ o->callback((Fl_Callback*)cb_back_);
+ }
+ { Fl_Button* o = forward_ = new Fl_Button(435, 350, 25, 25, "@->");
+ o->shortcut(0xff53);
+ o->labeltype(FL_SYMBOL_LABEL);
+ o->labelcolor(2);
+ o->callback((Fl_Callback*)cb_forward_);
+ }
+ { Fl_Button* o = smaller_ = new Fl_Button(345, 350, 25, 25, "F");
+ o->labelfont(1);
+ o->labelsize(10);
+ o->callback((Fl_Callback*)cb_smaller_);
+ }
+ { Fl_Button* o = larger_ = new Fl_Button(375, 350, 25, 25, "F");
+ o->labelfont(1);
+ o->labelsize(16);
+ o->callback((Fl_Callback*)cb_larger_);
+ }
+ o->end();
+ }
+ back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;
+}
+
+int HelpDialog::h() {
+ return (window_->h());
+}
+
+void HelpDialog::hide() {
+ window_->hide();
+}
+
+void HelpDialog::load(const char *f) {
+ view_->set_changed();
+view_->load(f);
+window_->label(view_->title());
+}
+
+void HelpDialog::position(int xx, int yy) {
+ window_->position(xx, yy);
+}
+
+void HelpDialog::resize(int xx, int yy, int ww, int hh) {
+ window_->resize(xx, yy, ww, hh);
+}
+
+void HelpDialog::show() {
+ window_->show();
+}
+
+void HelpDialog::textsize(uchar s) {
+ view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();
+}
+
+uchar HelpDialog::textsize() {
+ return (view_->textsize());
+}
+
+void HelpDialog::topline(const char *n) {
+ view_->topline(n);
+}
+
+void HelpDialog::topline(int n) {
+ view_->topline(n);
+}
+
+int HelpDialog::visible() {
+ return (window_->visible());
+}
+
+int HelpDialog::w() {
+ return (window_->w());
+}
+
+int HelpDialog::x() {
+ return (window_->x());
+}
+
+int HelpDialog::y() {
+ return (window_->y());
+}
diff --git a/SrcUnix/espws-2.0/HelpDialog.fl b/SrcUnix/espws-2.0/HelpDialog.fl
new file mode 100644
index 0000000..a2b3278
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpDialog.fl
@@ -0,0 +1,188 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.00
+header_name {.h}
+code_name {.cxx}
+gridx 5
+gridy 5
+snap 3
+class HelpDialog {open
+} {
+ decl {int index_;} {}
+ decl {int max_;} {}
+ decl {int line_[100];} {}
+ decl {char file_[100][256];} {}
+ Function {HelpDialog()} {open
+ } {
+ Fl_Window window_ {
+ label {Help Dialog} open
+ private xywh {459 351 530 385} resizable
+ code0 {\#include <string.h>} visible
+ } {
+ Fl_Group view_ {
+ callback {if (view_->changed())
+{
+ index_ ++;
+
+ if (index_ >= 100)
+ {
+ memcpy(line_, line_ + 10, sizeof(line_[0]) * 90);
+ memcpy(file_, file_ + 10, sizeof(file_[0]) * 90);
+ index_ -= 10;
+ }
+
+ max_ = index_;
+
+ strcpy(file_[index_], view_->filename());
+ line_[index_] = view_->topline();
+
+ if (index_ > 0)
+ back_->activate();
+ else
+ back_->deactivate();
+
+ forward_->deactivate();
+ window_->label(view_->title());
+}
+else if (view_->filename())
+{
+ strncpy(file_[index_], view_->filename(), 255);
+ file_[index_][255] = '\\0';
+ line_[index_] = view_->topline();
+}} open
+ private xywh {10 10 510 330} box DOWN_BOX resizable
+ code0 {\#include "HelpView.h"}
+ class HelpView
+ } {}
+ Fl_Button {} {
+ label Close
+ callback {window_->hide();}
+ xywh {465 350 55 25}
+ }
+ Fl_Button back_ {
+ label {@<-}
+ callback {if (index_ > 0)
+ index_ --;
+
+if (index_ == 0)
+ back_->deactivate();
+
+forward_->activate();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(line_[index_]);}
+ private xywh {405 350 25 25} shortcut 0xff51 labeltype SYMBOL_LABEL labelcolor 2
+ }
+ Fl_Button forward_ {
+ label {@->}
+ callback {if (index_ < max_)
+ index_ ++;
+
+if (index_ >= max_)
+ forward_->deactivate();
+
+back_->activate();
+
+if (strcmp(view_->filename(), file_[index_]) != 0)
+ view_->load(file_[index_]);
+
+view_->topline(line_[index_]);}
+ private xywh {435 350 25 25} shortcut 0xff53 labeltype SYMBOL_LABEL labelcolor 2
+ }
+ Fl_Button smaller_ {
+ label F
+ callback {if (view_->textsize() > 8)
+ view_->textsize(view_->textsize() - 2);
+
+if (view_->textsize() <= 8)
+ smaller_->deactivate();
+larger_->activate();}
+ private xywh {345 350 25 25} labelfont 1 labelsize 10
+ }
+ Fl_Button larger_ {
+ label F
+ callback {if (view_->textsize() < 18)
+ view_->textsize(view_->textsize() + 2);
+
+if (view_->textsize() >= 18)
+ larger_->deactivate();
+smaller_->activate();}
+ private xywh {375 350 25 25} labelfont 1 labelsize 16
+ }
+ }
+ code {back_->deactivate();
+forward_->deactivate();
+
+index_ = -1;
+max_ = 0;} {}
+ }
+ Function {h()} {selected return_type int
+ } {
+ code {return (window_->h());} {}
+ }
+ Function {hide()} {return_type void
+ } {
+ code {window_->hide();} {}
+ }
+ Function {load(const char *f)} {return_type void
+ } {
+ code {view_->set_changed();
+view_->load(f);
+window_->label(view_->title());} {}
+ }
+ Function {position(int xx, int yy)} {return_type void
+ } {
+ code {window_->position(xx, yy);} {}
+ }
+ Function {resize(int xx, int yy, int ww, int hh)} {return_type void
+ } {
+ code {window_->resize(xx, yy, ww, hh);} {}
+ }
+ Function {show()} {return_type void
+ } {
+ code {window_->show();} {}
+ }
+ Function {textsize(uchar s)} {return_type void
+ } {
+ code {view_->textsize(s);
+
+if (s <= 8)
+ smaller_->deactivate();
+else
+ smaller_->activate();
+
+if (s >= 18)
+ larger_->deactivate();
+else
+ larger_->activate();} {}
+ }
+ Function {textsize()} {return_type uchar
+ } {
+ code {return (view_->textsize());} {}
+ }
+ Function {topline(const char *n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {topline(int n)} {return_type void
+ } {
+ code {view_->topline(n);} {}
+ }
+ Function {visible()} {return_type int
+ } {
+ code {return (window_->visible());} {}
+ }
+ Function {w()} {return_type int
+ } {
+ code {return (window_->w());} {}
+ }
+ Function {x()} {return_type int
+ } {
+ code {return (window_->x());} {}
+ }
+ Function {y()} {return_type int
+ } {
+ code {return (window_->y());} {}
+ }
+}
diff --git a/SrcUnix/espws-2.0/HelpDialog.gif b/SrcUnix/espws-2.0/HelpDialog.gif
new file mode 100644
index 0000000..e0f3cbf
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpDialog.gif
Binary files differ
diff --git a/SrcUnix/espws-2.0/HelpDialog.h b/SrcUnix/espws-2.0/HelpDialog.h
new file mode 100644
index 0000000..bc6426e
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpDialog.h
@@ -0,0 +1,53 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0008
+
+#ifndef HelpDialog_h
+#define HelpDialog_h
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <string.h>
+#include "HelpView.h"
+#include <FL/Fl_Button.H>
+
+class HelpDialog {
+ int index_;
+ int max_;
+ int line_[100];
+ char file_[100][256];
+public:
+ HelpDialog();
+private:
+ Fl_Window *window_;
+ HelpView *view_;
+ inline void cb_view__i(HelpView*, void*);
+ static void cb_view_(HelpView*, void*);
+ inline void cb_Close_i(Fl_Button*, void*);
+ static void cb_Close(Fl_Button*, void*);
+ Fl_Button *back_;
+ inline void cb_back__i(Fl_Button*, void*);
+ static void cb_back_(Fl_Button*, void*);
+ Fl_Button *forward_;
+ inline void cb_forward__i(Fl_Button*, void*);
+ static void cb_forward_(Fl_Button*, void*);
+ Fl_Button *smaller_;
+ inline void cb_smaller__i(Fl_Button*, void*);
+ static void cb_smaller_(Fl_Button*, void*);
+ Fl_Button *larger_;
+ inline void cb_larger__i(Fl_Button*, void*);
+ static void cb_larger_(Fl_Button*, void*);
+public:
+ int h();
+ void hide();
+ void load(const char *f);
+ void position(int xx, int yy);
+ void resize(int xx, int yy, int ww, int hh);
+ void show();
+ void textsize(uchar s);
+ uchar textsize();
+ void topline(const char *n);
+ void topline(int n);
+ int visible();
+ int w();
+ int x();
+ int y();
+};
+#endif
diff --git a/SrcUnix/espws-2.0/HelpDialog.html b/SrcUnix/espws-2.0/HelpDialog.html
new file mode 100644
index 0000000..dc64a96
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpDialog.html
@@ -0,0 +1,89 @@
+<HTML>
+<HEAD>
+ <TITLE>HelpDialog - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class HelpDialog</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Group
+ |
+ +----<B>HelpDialog</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "HelpDialog.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>HelpDialog</CODE> widget displays a standard help dialog window
+using the <CODE>HelpView</CODE> widget.
+
+<CENTER><IMG SRC="HelpDialog.gif"></CENTER>
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#HelpDialog.HelpDialog">HelpDialog</A>
+ <LI><A HREF="#HelpDialog.~HelpDialog">~HelpDialog</A>
+ <LI><A HREF="#HelpDialog.hide">hide</A>
+ <LI><A HREF="#HelpDialog.load">load</A>
+ <LI><A HREF="#HelpDialog.show">show</A>
+ <LI><A HREF="#HelpDialog.topline">topline</A>
+ <LI><A HREF="#HelpDialog.visible">visible</A>
+
+</UL>
+
+<H4><A NAME="HelpDialog.HelpDialog">HelpDialog()</A></H4>
+
+<P>The constructor creates the dialog pictured above.
+
+<H4><A NAME="HelpView.~HelpView">~HelpView()</A></H4>
+
+<P>The destructor destroys the widget and frees all memory that has been
+allocated for the current file.
+
+<H4><A NAME="HelpDialog.hide">void hide()</A></H4>
+
+<P>Hides the <code>HelpDialog</code> window.
+
+<H4><A NAME="HelpDialog.load">void load(const char *f)</A></H4>
+
+<P>Loads the specified HTML file into the <CODE>HelpView</CODE> widget.
+The filename can also contain a target name ("filename.html#target").
+
+<H4><A NAME="HelpDialog.show">void show()</A></H4>
+
+<P>Shows the <code>HelpDialog</code> window.
+
+<H4><A NAME="HelpDialog.topline">void topline(const char *n)<BR>
+void topline(int n)</A></H4>
+
+<P>Sets the top line in the <CODE>HelpView</CODE> widget to the named or
+numbered line.
+
+<H4><A NAME="HelpDialog.visible">int visible()</A></H4>
+
+<P>Returns 1 if the <code>HelpDialog</code> window is visible.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/HelpView.cxx b/SrcUnix/espws-2.0/HelpView.cxx
new file mode 100644
index 0000000..2370338
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpView.cxx
@@ -0,0 +1,1799 @@
+//
+// "$Id: HelpView.cxx,v 1.22 2000/03/19 23:27:14 mike Exp $"
+//
+// Help Viewer widget routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outblockd in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// HelpView::add_block() - Add a text block to the list.
+// HelpView::add_link() - Add a new link to the list.
+// HelpView::add_target() - Add a new target to the list.
+// HelpView::compare_targets() - Compare two targets.
+// HelpView::do_align() - Compute the alignment for a line in a block.
+// HelpView::draw() - Draw the HelpView widget.
+// HelpView::format() - Format the help text.
+// HelpView::get_align() - Get an alignment attribute.
+// HelpView::get_attr() - Get an attribute value from the string.
+// HelpView::get_color() - Get an alignment attribute.
+// HelpView::handle() - Handle events in the widget.
+// HelpView::HelpView() - Build a HelpView widget.
+// HelpView::~HelpView() - Destroy a HelpView widget.
+// HelpView::load() - Load the specified file.
+// HelpView::resize() - Resize the help widget.
+// HelpView::topline() - Set the top line to the named target.
+// HelpView::topline() - Set the top line by number.
+// HelpView::value() - Set the help text directly.
+// scrollbar_callback() - A callback for the scrollbar.
+//
+
+//
+// Include necessary header files...
+//
+
+#include "HelpView.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#if defined(WIN32)
+# include <io.h>
+# include <direct.h>
+# define strcasecmp(s,t) stricmp((s), (t))
+# define strncasecmp(s,t,n) strnicmp((s), (t), (n))
+#elif defined(__EMX__)
+# define strcasecmp(s,t) stricmp((s), (t))
+# define strncasecmp(s,t,n) strnicmp((s), (t), (n))
+#else
+# include <unistd.h>
+#endif // WIN32
+
+
+//
+// Local functions...
+//
+
+static void scrollbar_callback(Fl_Widget *s, void *);
+
+
+//
+// 'HelpView::add_block()' - Add a text block to the list.
+//
+
+HelpBlock * // O - Pointer to new block
+HelpView::add_block(const char *s, // I - Pointer to start of block text
+ int xx, // I - X position of block
+ int yy, // I - Y position of block
+ int ww, // I - Right margin of block
+ int hh, // I - Height of block
+ uchar border) // I - Draw border?
+{
+ HelpBlock *temp; // New block
+
+
+ if (nblocks_ >= ablocks_)
+ {
+ ablocks_ += 16;
+
+ if (ablocks_ == 16)
+ blocks_ = (HelpBlock *)malloc(sizeof(HelpBlock) * ablocks_);
+ else
+ blocks_ = (HelpBlock *)realloc(blocks_, sizeof(HelpBlock) * ablocks_);
+ }
+
+ temp = blocks_ + nblocks_;
+ temp->start = s;
+ temp->x = xx;
+ temp->y = yy;
+ temp->w = ww;
+ temp->h = hh;
+ temp->border = border;
+ nblocks_ ++;
+
+ return (temp);
+}
+
+
+//
+// 'HelpView::add_link()' - Add a new link to the list.
+//
+
+void
+HelpView::add_link(const char *n, // I - Name of link
+ int xx, // I - X position of link
+ int yy, // I - Y position of link
+ int ww, // I - Width of link text
+ int hh) // I - Height of link text
+{
+ HelpLink *temp; // New link
+ char *target; // Pointer to target name
+
+
+ if (nlinks_ >= alinks_)
+ {
+ alinks_ += 16;
+
+ if (alinks_ == 16)
+ links_ = (HelpLink *)malloc(sizeof(HelpLink) * alinks_);
+ else
+ links_ = (HelpLink *)realloc(links_, sizeof(HelpLink) * alinks_);
+ }
+
+ temp = links_ + nlinks_;
+
+ temp->x = xx;
+ temp->y = yy;
+ temp->w = xx + ww;
+ temp->h = yy + hh;
+
+ strncpy(temp->filename, n, sizeof(temp->filename));
+ temp->filename[sizeof(temp->filename) - 1] = '\0';
+
+ if ((target = strrchr(temp->filename, '#')) != NULL)
+ {
+ *target++ = '\0';
+ strncpy(temp->name, target, sizeof(temp->name));
+ temp->name[sizeof(temp->name) - 1] = '\0';
+ }
+ else
+ temp->name[0] = '\0';
+
+ nlinks_ ++;
+}
+
+
+//
+// 'HelpView::add_target()' - Add a new target to the list.
+//
+
+void
+HelpView::add_target(const char *n, // I - Name of target
+ int yy) // I - Y position of target
+{
+ HelpTarget *temp; // New target
+
+
+ if (ntargets_ >= atargets_)
+ {
+ atargets_ += 16;
+
+ if (atargets_ == 16)
+ targets_ = (HelpTarget *)malloc(sizeof(HelpTarget) * atargets_);
+ else
+ targets_ = (HelpTarget *)realloc(targets_, sizeof(HelpTarget) * atargets_);
+ }
+
+ temp = targets_ + ntargets_;
+
+ temp->y = yy;
+ strncpy(temp->name, n, sizeof(temp->name));
+ temp->name[sizeof(temp->name) - 1] = '\0';
+
+ ntargets_ ++;
+}
+
+
+//
+// 'HelpView::compare_targets()' - Compare two targets.
+//
+
+int // O - Result of comparison
+HelpView::compare_targets(const HelpTarget *t0, // I - First target
+ const HelpTarget *t1) // I - Second target
+{
+ return (strcasecmp(t0->name, t1->name));
+}
+
+
+//
+// 'HelpView::do_align()' - Compute the alignment for a line in a block.
+//
+
+int // O - New line
+HelpView::do_align(HelpBlock *block, // I - Block to add to
+ int line, // I - Current line
+ int xx, // I - Current X position
+ int a, // I - Current alignment
+ int &l) // IO - Starting link
+{
+ int offset; // Alignment offset
+
+
+ switch (a)
+ {
+ case RIGHT : // Right align
+ offset = block->w - xx;
+ break;
+ case CENTER : // Center
+ offset = (block->w - xx) / 2;
+ break;
+ case LEFT : // Left align
+ offset = 0;
+ break;
+ }
+
+ block->line[line] = block->x + offset;
+
+ if (line < 31)
+ line ++;
+
+ while (l < nlinks_)
+ {
+ links_[l].x += offset;
+ links_[l].w += offset;
+ l ++;
+ }
+
+ return (line);
+}
+
+
+//
+// 'HelpView::draw()' - Draw the HelpView widget.
+//
+
+void
+HelpView::draw()
+{
+ int i; // Looping var
+ const HelpBlock *block; // Pointer to current block
+ const char *ptr, // Pointer to text in block
+ *attrs; // Pointer to start of element attributes
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024]; // Attribute buffer
+ int xx, yy, ww, hh; // Current positions and sizes
+ int line; // Current line
+ uchar font, size; // Current font and size
+ int head, pre, // Flags for text
+ needspace; // Do we need whitespace?
+ Fl_Boxtype b = box() ? box() : FL_DOWN_BOX;
+ // Box to draw...
+ Fl_Color tc, c; // Table/cell background color
+
+
+ // Draw the scrollbar and box first...
+ if (scrollbar_.visible())
+ {
+ draw_child(scrollbar_);
+ draw_box(b, x(), y(), w() - 17, h(), bgcolor_);
+ }
+ else
+ draw_box(b, x(), y(), w(), h(), bgcolor_);
+
+ if (!value_)
+ return;
+
+ // Clip the drawing to the inside of the box...
+ fl_push_clip(x() + 4, y() + 4, w() - 28, h() - 8);
+ fl_color(textcolor_);
+
+ tc = c = bgcolor_;
+
+ // Draw all visible blocks...
+ for (i = 0, block = blocks_; i < nblocks_ && (block->y - topline_) < h(); i ++, block ++)
+ if ((block->y + block->h) >= topline_)
+ {
+ line = 0;
+ xx = block->line[line];
+ yy = block->y - topline_;
+ hh = 0;
+ pre = 0;
+ head = 0;
+ needspace = 0;
+
+ initfont(font, size);
+
+ for (ptr = block->start, s = buf; ptr < block->end;)
+ {
+ if ((*ptr == '<' || isspace(*ptr)) && s > buf)
+ {
+ if (!head && !pre)
+ {
+ // Check width...
+ *s = '\0';
+ s = buf;
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+
+ fl_draw(buf, xx + x(), yy + y());
+
+ xx += ww;
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ needspace = 0;
+ }
+ else if (pre)
+ {
+ while (isspace(*ptr))
+ {
+ if (*ptr == '\n')
+ {
+ *s = '\0';
+ s = buf;
+
+ fl_draw(buf, xx + x(), yy + y());
+
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = size + 2;
+ }
+ else if (*ptr == '\t')
+ {
+ // Do tabs every 8 columns...
+ while (((s - buf) & 7))
+ *s++ = ' ';
+ }
+ else
+ *s++ = ' ';
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ ptr ++;
+ }
+
+ if (s > buf)
+ {
+ *s = '\0';
+ s = buf;
+
+ fl_draw(buf, xx + x(), yy + y());
+ xx += (int)fl_width(buf);
+ }
+
+ needspace = 0;
+ }
+ else
+ {
+ s = buf;
+
+ while (isspace(*ptr))
+ ptr ++;
+ }
+ }
+
+ if (*ptr == '<')
+ {
+ ptr ++;
+ while (*ptr && *ptr != '>' && !isspace(*ptr))
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+ s = buf;
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ if (strcasecmp(buf, "HEAD") == 0)
+ head = 1;
+ else if (strcasecmp(buf, "BR") == 0)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "HR") == 0)
+ {
+ fl_line(block->x + x(), yy + y(), block->w + x(),
+ yy + y());
+
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += 2 * hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "CENTER") == 0 ||
+ strcasecmp(buf, "P") == 0 ||
+ strcasecmp(buf, "H1") == 0 ||
+ strcasecmp(buf, "H2") == 0 ||
+ strcasecmp(buf, "H3") == 0 ||
+ strcasecmp(buf, "H4") == 0 ||
+ strcasecmp(buf, "H5") == 0 ||
+ strcasecmp(buf, "H6") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0 ||
+ strcasecmp(buf, "LI") == 0 ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "PRE") == 0)
+ {
+ if (tolower(buf[0]) == 'h')
+ {
+ font = FL_HELVETICA_BOLD;
+ size = textsize_ + '7' - buf[1];
+ }
+ else if (strcasecmp(buf, "DT") == 0)
+ {
+ font = textfont_ | FL_ITALIC;
+ size = textsize_;
+ }
+ else if (strcasecmp(buf, "PRE") == 0)
+ {
+ font = FL_COURIER;
+ size = textsize_;
+ pre = 1;
+ }
+
+ if (strcasecmp(buf, "LI") == 0)
+ {
+ fl_font(FL_SYMBOL, size);
+ fl_draw("\267", xx - size + x(), yy + y());
+ }
+
+ pushfont(font, size);
+
+ if (c != bgcolor_)
+ {
+ fl_color(c);
+ fl_rectf(block->x + x() - 4,
+ block->y - topline_ + y() - size - 3,
+ block->w - block->x + 7, block->h + size - 5);
+ fl_color(textcolor_);
+ }
+ }
+ else if (strcasecmp(buf, "A") == 0 &&
+ get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
+ fl_color(linkcolor_);
+ else if (strcasecmp(buf, "/A") == 0)
+ fl_color(textcolor_);
+ else if (strcasecmp(buf, "B") == 0)
+ pushfont(font |= FL_BOLD, size);
+ else if (strcasecmp(buf, "TABLE") == 0)
+ tc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), bgcolor_);
+ else if (strcasecmp(buf, "TD") == 0 ||
+ strcasecmp(buf, "TH") == 0)
+ {
+ if (tolower(buf[1]) == 'h')
+ pushfont(font |= FL_BOLD, size);
+ else
+ pushfont(font = textfont_, size);
+
+ c = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc);
+
+ if (c != bgcolor_)
+ {
+ fl_color(c);
+ fl_rectf(block->x + x() - 4,
+ block->y - topline_ + y() - size - 3,
+ block->w - block->x + 7, block->h + size - 5);
+ fl_color(textcolor_);
+ }
+
+ if (block->border)
+ fl_rect(block->x + x() - 4,
+ block->y - topline_ + y() - size - 3,
+ block->w - block->x + 7, block->h + size - 5);
+ }
+ else if (strcasecmp(buf, "I") == 0)
+ pushfont(font |= FL_ITALIC, size);
+ else if (strcasecmp(buf, "CODE") == 0)
+ pushfont(font = FL_COURIER, size);
+ else if (strcasecmp(buf, "KBD") == 0)
+ pushfont(font = FL_COURIER_BOLD, size);
+ else if (strcasecmp(buf, "VAR") == 0)
+ pushfont(font = FL_COURIER_ITALIC, size);
+ else if (strcasecmp(buf, "/HEAD") == 0)
+ head = 0;
+ else if (strcasecmp(buf, "/H1") == 0 ||
+ strcasecmp(buf, "/H2") == 0 ||
+ strcasecmp(buf, "/H3") == 0 ||
+ strcasecmp(buf, "/H4") == 0 ||
+ strcasecmp(buf, "/H5") == 0 ||
+ strcasecmp(buf, "/H6") == 0 ||
+ strcasecmp(buf, "/B") == 0 ||
+ strcasecmp(buf, "/I") == 0 ||
+ strcasecmp(buf, "/CODE") == 0 ||
+ strcasecmp(buf, "/KBD") == 0 ||
+ strcasecmp(buf, "/VAR") == 0)
+ popfont(font, size);
+ else if (strcasecmp(buf, "/TABLE") == 0)
+ tc = c = bgcolor_;
+ else if (strcasecmp(buf, "/TD") == 0 ||
+ strcasecmp(buf, "/TH") == 0)
+ c = tc;
+ else if (strcasecmp(buf, "/PRE") == 0)
+ {
+ popfont(font, size);
+ pre = 0;
+ }
+ }
+ else if (strcasecmp(buf, "IMG") == 0 &&
+ get_attr(attrs, "ALT", attr, sizeof(attr)) != NULL)
+ {
+ // Show alt text...
+ sprintf(buf, "[%s]", attr);
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+
+ fl_draw(buf, xx + x(), yy + y());
+
+ xx += ww;
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ needspace = 0;
+ }
+ else if (*ptr == '\n' && pre)
+ {
+ *s = '\0';
+ s = buf;
+
+ fl_draw(buf, xx + x(), yy + y());
+
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = size + 2;
+ needspace = 0;
+
+ ptr ++;
+ }
+ else if (isspace(*ptr))
+ {
+ if (pre)
+ {
+ if (*ptr == ' ')
+ *s++ = ' ';
+ else
+ {
+ // Do tabs every 8 columns...
+ while (((s - buf) & 7))
+ *s++ = ' ';
+ }
+ }
+
+ ptr ++;
+ needspace = 1;
+ }
+ else if (*ptr == '&')
+ {
+ ptr ++;
+
+ if (strncasecmp(ptr, "amp;", 4) == 0)
+ {
+ *s++ = '&';
+ ptr += 4;
+ }
+ else if (strncasecmp(ptr, "lt;", 3) == 0)
+ {
+ *s++ = '<';
+ ptr += 3;
+ }
+ else if (strncasecmp(ptr, "gt;", 3) == 0)
+ {
+ *s++ = '>';
+ ptr += 3;
+ }
+ else if (strncasecmp(ptr, "nbsp;", 5) == 0)
+ {
+ *s++ = ' ';
+ ptr += 5;
+ }
+ else if (strncasecmp(ptr, "copy;", 5) == 0)
+ {
+ *s++ = '\251';
+ ptr += 5;
+ }
+ else if (strncasecmp(ptr, "reg;", 4) == 0)
+ {
+ *s++ = '\256';
+ ptr += 4;
+ }
+ else if (strncasecmp(ptr, "quot;", 5) == 0)
+ {
+ *s++ = '\"';
+ ptr += 5;
+ }
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+ }
+ else
+ {
+ *s++ = *ptr++;
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+ }
+ }
+
+ *s = '\0';
+
+ if (s > buf && !pre && !head)
+ {
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ xx += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ if (line < 31)
+ line ++;
+ xx = block->line[line];
+ yy += hh;
+ hh = 0;
+ }
+ }
+
+ if (s > buf && !head)
+ fl_draw(buf, xx + x(), yy + y());
+ }
+
+ fl_pop_clip();
+}
+
+
+//
+// 'HelpView::format()' - Format the help text.
+//
+
+void
+HelpView::format()
+{
+ HelpBlock *block, // Current block
+ *cell; // Current table cell
+ int row; // Current table row (block number)
+ const char *ptr, // Pointer into block
+ *start, // Pointer to start of element
+ *attrs; // Pointer to start of element attributes
+ char *s, // Pointer into buffer
+ buf[1024], // Text buffer
+ attr[1024], // Attribute buffer
+ link[1024]; // Link destination
+ int xx, yy, ww, hh; // Size of current text fragment
+ int line; // Current line in block
+ int links; // Links for current line
+ uchar font, size; // Current font and size
+ uchar border; // Draw border?
+ int align, // Current alignment
+ head, // In the <HEAD> section?
+ pre, // <PRE> text?
+ needspace; // Do we need whitespace?
+ int table_width; // Width of table
+ int column, // Current table column number
+ columns[200]; // Column widths
+
+
+ nblocks_ = 0;
+ nlinks_ = 0;
+ ntargets_ = 0;
+ size_ = 0;
+ bgcolor_ = color();
+ textcolor_ = textcolor();
+ linkcolor_ = selection_color();
+
+ strcpy(title_, "Untitled");
+
+ if (!value_)
+ return;
+
+ initfont(font, size);
+
+ line = 0;
+ links = 0;
+ xx = 4;
+ yy = size + 2;
+ hh = 0;
+ block = add_block(value_, xx, yy, w() - 24, 0);
+ row = 0;
+ head = 0;
+ pre = 0;
+ align = LEFT;
+ needspace = 0;
+ link[0] = '\0';
+
+ for (ptr = value_, s = buf; *ptr;)
+ {
+ if ((*ptr == '<' || isspace(*ptr)) && s > buf)
+ {
+ if (!head && !pre)
+ {
+ // Check width...
+ *s = '\0';
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (link[0])
+ add_link(link, xx, yy - size, ww, size);
+
+ xx += ww;
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ needspace = 0;
+ }
+ else if (pre)
+ {
+ // Handle preformatted text...
+ while (isspace(*ptr))
+ {
+ if (*ptr == '\n')
+ {
+ if (link[0])
+ add_link(link, xx, yy - hh, ww, hh);
+
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = size + 2;
+ }
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ ptr ++;
+ }
+
+ needspace = 0;
+ }
+ else
+ {
+ // Handle normal text or stuff in the <HEAD> section...
+ while (isspace(*ptr))
+ ptr ++;
+ }
+
+ s = buf;
+ }
+
+ if (*ptr == '<')
+ {
+ start = ptr;
+ ptr ++;
+ while (*ptr && *ptr != '>' && !isspace(*ptr))
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ *s = '\0';
+ s = buf;
+
+ attrs = ptr;
+ while (*ptr && *ptr != '>')
+ ptr ++;
+
+ if (*ptr == '>')
+ ptr ++;
+
+ if (strcasecmp(buf, "HEAD") == 0)
+ head = 1;
+ else if (strcasecmp(buf, "/HEAD") == 0)
+ head = 0;
+ else if (strcasecmp(buf, "TITLE") == 0)
+ {
+ // Copy the title in the document...
+ for (s = title_;
+ *ptr != '<' && *ptr && s < (title_ + sizeof(title_) - 1);
+ *s++ = *ptr++);
+
+ *s = '\0';
+ s = buf;
+ }
+ else if (strcasecmp(buf, "A") == 0)
+ {
+ if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL)
+ add_target(attr, yy - size - 2);
+ else if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
+ {
+ strncpy(link, attr, sizeof(link) - 1);
+ link[sizeof(link) - 1] = '\0';
+ }
+ }
+ else if (strcasecmp(buf, "/A") == 0)
+ link[0] = '\0';
+ else if (strcasecmp(buf, "BODY") == 0)
+ {
+ bgcolor_ = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)),
+ color());
+ textcolor_ = get_color(get_attr(attrs, "TEXT", attr, sizeof(attr)),
+ textcolor());
+ linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)),
+ selection_color());
+ }
+ else if (strcasecmp(buf, "BR") == 0)
+ {
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ block->h += hh;
+ yy += hh;
+ hh = 0;
+ }
+ else if (strcasecmp(buf, "CENTER") == 0 ||
+ strcasecmp(buf, "P") == 0 ||
+ strcasecmp(buf, "H1") == 0 ||
+ strcasecmp(buf, "H2") == 0 ||
+ strcasecmp(buf, "H3") == 0 ||
+ strcasecmp(buf, "H4") == 0 ||
+ strcasecmp(buf, "H5") == 0 ||
+ strcasecmp(buf, "H6") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0 ||
+ strcasecmp(buf, "LI") == 0 ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "HR") == 0 ||
+ strcasecmp(buf, "PRE") == 0 ||
+ strcasecmp(buf, "TABLE") == 0)
+ {
+ block->end = start;
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ block->h += hh;
+
+ if (!block->h && nblocks_ > 1)
+ {
+ nblocks_ --;
+ block --;
+ }
+
+ if (strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "DL") == 0)
+ {
+ xx += 4 * size;
+ block->h += size + 2;
+ }
+ else if (strcasecmp(buf, "TABLE") == 0)
+ {
+ if (get_attr(attrs, "BORDER", attr, sizeof(attr)))
+ border = atoi(attr);
+ else
+ border = 0;
+
+ block->h += size + 2;
+
+ if (get_attr(attrs, "WIDTH", attr, sizeof(attr)))
+ {
+ if (attr[strlen(attr) - 1] == '%')
+ table_width = atoi(attr) * w() / 100;
+ else
+ table_width = atoi(attr);
+ }
+ else
+ table_width = w();
+
+ for (column = 0; column < 200; column ++)
+ columns[column] = table_width / 3;
+
+ column = 0;
+ }
+
+ if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
+ {
+ font = FL_HELVETICA_BOLD;
+ size = textsize_ + '7' - buf[1];
+ }
+ else if (strcasecmp(buf, "DT") == 0)
+ {
+ font = textfont_ | FL_ITALIC;
+ size = textsize_;
+ }
+ else if (strcasecmp(buf, "PRE") == 0)
+ {
+ font = FL_COURIER;
+ size = textsize_;
+ pre = 1;
+ }
+ else
+ {
+ font = textfont_;
+ size = textsize_;
+ }
+
+ pushfont(font, size);
+
+ yy = block->y + block->h;
+ hh = 0;
+
+ if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) ||
+ strcasecmp(buf, "DD") == 0 ||
+ strcasecmp(buf, "DT") == 0 ||
+ strcasecmp(buf, "UL") == 0 ||
+ strcasecmp(buf, "OL") == 0 ||
+ strcasecmp(buf, "P") == 0)
+ yy += size + 2;
+ else if (strcasecmp(buf, "HR") == 0)
+ {
+ hh += 2 * size;
+ yy += size;
+ }
+
+ if (row)
+ block = add_block(start, block->x, yy, block->w, 0);
+ else
+ block = add_block(start, xx, yy, w() - 24, 0);
+
+ needspace = 0;
+ line = 0;
+
+ if (strcasecmp(buf, "CENTER") == 0)
+ align = CENTER;
+ else
+ align = get_align(attrs, LEFT);
+ }
+ else if (strcasecmp(buf, "/P") == 0 ||
+ strcasecmp(buf, "/H1") == 0 ||
+ strcasecmp(buf, "/H2") == 0 ||
+ strcasecmp(buf, "/H3") == 0 ||
+ strcasecmp(buf, "/H4") == 0 ||
+ strcasecmp(buf, "/H5") == 0 ||
+ strcasecmp(buf, "/H6") == 0 ||
+ strcasecmp(buf, "/PRE") == 0 ||
+ strcasecmp(buf, "/UL") == 0 ||
+ strcasecmp(buf, "/OL") == 0 ||
+ strcasecmp(buf, "/DL") == 0 ||
+ strcasecmp(buf, "/TABLE") == 0)
+ {
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ block->end = ptr;
+
+ if (strcasecmp(buf, "/UL") == 0 ||
+ strcasecmp(buf, "/OL") == 0 ||
+ strcasecmp(buf, "/DL") == 0)
+ {
+ xx -= 4 * size;
+ block->h += size + 2;
+ }
+ else if (strcasecmp(buf, "/TABLE") == 0)
+ block->h += size + 2;
+ else if (strcasecmp(buf, "/PRE") == 0)
+ {
+ pre = 0;
+ hh = 0;
+ }
+
+ initfont(font, size);
+
+ while (isspace(*ptr))
+ ptr ++;
+
+ block->h += hh;
+ yy += hh;
+
+ if (tolower(buf[2]) == 'l')
+ yy += size + 2;
+
+ block = add_block(ptr, xx, yy, w() - 24, 0);
+ needspace = 0;
+ hh = 0;
+ line = 0;
+ align = LEFT;
+ }
+ else if (strcasecmp(buf, "TR") == 0)
+ {
+ block->end = start;
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ block->h += hh;
+
+ if (row)
+ {
+ yy = blocks_[row].y + blocks_[row].h;
+
+ for (cell = blocks_ + row + 1; cell <= block; cell ++)
+ if ((cell->y + cell->h) > yy)
+ yy = cell->y + cell->h;
+
+ block->h = yy - block->y + 2;
+
+ for (cell = blocks_ + row + 1; cell < block; cell ++)
+ cell->h = block->h;
+ }
+
+ yy = block->y + block->h - 4;
+ hh = 0;
+ block = add_block(start, xx, yy, w() - 24, 0);
+ row = block - blocks_;
+ needspace = 0;
+ column = 0;
+ line = 0;
+ }
+ else if (strcasecmp(buf, "/TR") == 0 && row)
+ {
+ line = do_align(block, line, xx, align, links);
+ block->end = start;
+ block->h += hh;
+
+ xx = blocks_[row].x;
+
+ if (block->end == block->start && nblocks_ > 1)
+ {
+ nblocks_ --;
+ block --;
+ }
+
+ yy = blocks_[row].y + blocks_[row].h;
+
+ for (cell = blocks_ + row + 1; cell <= block; cell ++)
+ if ((cell->y + cell->h) > yy)
+ yy = cell->y + cell->h;
+
+ block->h = yy - block->y + 2;
+
+ for (cell = blocks_ + row + 1; cell < block; cell ++)
+ cell->h = block->h;
+
+ yy = block->y + block->h - 4;
+ block = add_block(start, xx, yy, w() - 24, 0);
+ needspace = 0;
+ row = 0;
+ line = 0;
+ }
+ else if ((strcasecmp(buf, "TD") == 0 ||
+ strcasecmp(buf, "TH") == 0) && row)
+ {
+ line = do_align(block, line, xx, align, links);
+ block->end = start;
+ block->h += hh;
+
+ if (strcasecmp(buf, "TH") == 0)
+ font = textfont_ | FL_BOLD;
+ else
+ font = textfont_;
+
+ size = textsize_;
+
+ if (column == 0)
+ xx = block->x + size + 3;
+ else
+ xx = block->w + 6;
+
+ if (block->end == block->start && nblocks_ > 1)
+ {
+ nblocks_ --;
+ block --;
+ }
+
+ pushfont(font, size);
+
+ if (get_attr(attrs, "WIDTH", attr, sizeof(attr)) != NULL)
+ {
+ ww = atoi(attr);
+
+ if (attr[strlen(attr) - 1] == '%')
+ ww = ww * w() / 100;
+
+ columns[column] = ww;
+ }
+ else
+ ww = columns[column];
+
+ yy = blocks_[row].y;
+ hh = 0;
+ block = add_block(start, xx, yy, xx + ww, 0, border);
+ needspace = 0;
+ line = 0;
+
+ align = get_align(attrs, tolower(buf[1]) == 'h' ? CENTER : LEFT);
+
+ column ++;
+ }
+ else if ((strcasecmp(buf, "/TD") == 0 ||
+ strcasecmp(buf, "/TH") == 0) && row)
+ popfont(font, size);
+ else if (strcasecmp(buf, "B") == 0)
+ pushfont(font |= FL_BOLD, size);
+ else if (strcasecmp(buf, "I") == 0)
+ pushfont(font |= FL_ITALIC, size);
+ else if (strcasecmp(buf, "CODE") == 0)
+ pushfont(font = FL_COURIER, size);
+ else if (strcasecmp(buf, "KBD") == 0)
+ pushfont(font = FL_COURIER_BOLD, size);
+ else if (strcasecmp(buf, "VAR") == 0)
+ pushfont(font = FL_COURIER_ITALIC, size);
+ else if (strcasecmp(buf, "/B") == 0 ||
+ strcasecmp(buf, "/I") == 0 ||
+ strcasecmp(buf, "/CODE") == 0 ||
+ strcasecmp(buf, "/KBD") == 0 ||
+ strcasecmp(buf, "/VAR") == 0)
+ popfont(font, size);
+ }
+ else if (strcasecmp(buf, "IMG") == 0 &&
+ get_attr(attrs, "ALT", attr, sizeof(attr)) != NULL)
+ {
+ // Show alt text...
+ ww = (int)(fl_width(attr) + fl_width('[') + fl_width(']'));
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (link[0])
+ add_link(link, xx, yy - size, ww, size);
+
+ xx += ww;
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ needspace = 0;
+ }
+ else if (*ptr == '\n' && pre)
+ {
+ if (link[0])
+ add_link(link, xx, yy - hh, ww, hh);
+
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ needspace = 0;
+ ptr ++;
+ }
+ else if (isspace(*ptr))
+ {
+ needspace = 1;
+
+ ptr ++;
+ }
+ else if (*ptr == '&' && s < (buf + sizeof(buf) - 1))
+ {
+ ptr ++;
+
+ if (strncasecmp(ptr, "amp;", 4) == 0)
+ {
+ *s++ = '&';
+ ptr += 4;
+ }
+ else if (strncasecmp(ptr, "lt;", 3) == 0)
+ {
+ *s++ = '<';
+ ptr += 3;
+ }
+ else if (strncasecmp(ptr, "gt;", 3) == 0)
+ {
+ *s++ = '>';
+ ptr += 3;
+ }
+ else if (strncasecmp(ptr, "nbsp;", 5) == 0)
+ {
+ *s++ = '\240';
+ ptr += 5;
+ }
+ else if (strncasecmp(ptr, "copy;", 5) == 0)
+ {
+ *s++ = '\251';
+ ptr += 5;
+ }
+ else if (strncasecmp(ptr, "reg;", 4) == 0)
+ {
+ *s++ = '\256';
+ ptr += 4;
+ }
+ else if (strncasecmp(ptr, "quot;", 5) == 0)
+ {
+ *s++ = '\"';
+ ptr += 5;
+ }
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+ }
+ else
+ {
+ if (s < (buf + sizeof(buf) - 1))
+ *s++ = *ptr++;
+ else
+ ptr ++;
+
+ if ((size + 2) > hh)
+ hh = size + 2;
+ }
+ }
+
+ if (s > buf && !pre && !head)
+ {
+ *s = '\0';
+ ww = (int)fl_width(buf);
+
+ if (needspace && xx > block->x)
+ ww += (int)fl_width(' ');
+
+ if ((xx + ww) > block->w)
+ {
+ line = do_align(block, line, xx, align, links);
+ xx = block->x;
+ yy += hh;
+ block->h += hh;
+ hh = 0;
+ }
+
+ if (link[0])
+ add_link(link, xx, yy - size, ww, size);
+
+ xx += ww;
+ if ((size + 2) > hh)
+ hh = size + 2;
+
+ needspace = 0;
+ }
+
+ block->end = ptr;
+ size_ = yy + hh;
+
+ if (ntargets_ > 1)
+ qsort(targets_, ntargets_, sizeof(HelpTarget),
+ (int (*)(const void *, const void *))compare_targets);
+
+ if (size_ < (h() - 8))
+ scrollbar_.hide();
+ else
+ scrollbar_.show();
+
+ topline(topline_);
+}
+
+
+//
+// 'HelpView::get_align()' - Get an alignment attribute.
+//
+
+int // O - Alignment
+HelpView::get_align(const char *p, // I - Pointer to start of attrs
+ int a) // I - Default alignment
+{
+ char buf[255]; // Alignment value
+
+
+ if (get_attr(p, "ALIGN", buf, sizeof(buf)) == NULL)
+ return (a);
+
+ if (strcasecmp(buf, "CENTER") == 0)
+ return (CENTER);
+ else if (strcasecmp(buf, "RIGHT") == 0)
+ return (RIGHT);
+ else
+ return (LEFT);
+}
+
+
+//
+// 'HelpView::get_attr()' - Get an attribute value from the string.
+//
+
+const char * // O - Pointer to buf or NULL
+HelpView::get_attr(const char *p, // I - Pointer to start of attributes
+ const char *n, // I - Name of attribute
+ char *buf, // O - Buffer for attribute value
+ int bufsize) // I - Size of buffer
+{
+ char name[255], // Name from string
+ *ptr, // Pointer into name or value
+ quote; // Quote
+
+
+ while (*p && *p != '>')
+ {
+ while (isspace(*p))
+ p ++;
+
+ if (*p == '>' || !*p)
+ return (NULL);
+
+ for (ptr = name; *p && !isspace(*p) && *p != '=' && *p != '>';)
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ *ptr = '\0';
+
+ if (isspace(*p) || !*p || *p == '>')
+ buf[0] = '\0';
+ else
+ {
+ if (*p == '=')
+ p ++;
+
+ for (ptr = buf; *p && !isspace(*p) && *p != '>';)
+ if (*p == '\'' || *p == '\"')
+ {
+ quote = *p++;
+
+ while (*p && *p != quote)
+ if ((ptr - buf + 1) < bufsize)
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ if (*p == quote)
+ p ++;
+ }
+ else if ((ptr - buf + 1) < bufsize)
+ *ptr++ = *p++;
+ else
+ p ++;
+
+ *ptr = '\0';
+ }
+
+ if (strcasecmp(n, name) == 0)
+ return (buf);
+
+ if (*p == '>')
+ return (NULL);
+ }
+
+ return (NULL);
+}
+
+
+//
+// 'HelpView::get_color()' - Get an alignment attribute.
+//
+
+Fl_Color // O - Color value
+HelpView::get_color(const char *n, // I - Color name
+ Fl_Color c) // I - Default color value
+{
+ int rgb, r, g, b; // RGB values
+
+
+ if (!n)
+ return (c);
+
+ if (n[0] == '#')
+ {
+ // Do hex color lookup
+ rgb = strtol(n + 1, NULL, 16);
+
+ r = rgb >> 16;
+ g = (rgb >> 8) & 255;
+ b = rgb & 255;
+
+ if (r == g && g == b)
+ return (fl_gray_ramp(FL_NUM_GRAY * r / 256));
+ else
+ return (fl_color_cube((FL_NUM_RED - 1) * r / 255,
+ (FL_NUM_GREEN - 1) * g / 255,
+ (FL_NUM_BLUE - 1) * b / 255));
+ }
+ else if (strcasecmp(n, "black") == 0)
+ return (FL_BLACK);
+ else if (strcasecmp(n, "red") == 0)
+ return (FL_RED);
+ else if (strcasecmp(n, "green") == 0)
+ return (fl_color_cube(0, 4, 0));
+ else if (strcasecmp(n, "yellow") == 0)
+ return (FL_YELLOW);
+ else if (strcasecmp(n, "blue") == 0)
+ return (FL_BLUE);
+ else if (strcasecmp(n, "magenta") == 0 || strcasecmp(n, "fuchsia") == 0)
+ return (FL_MAGENTA);
+ else if (strcasecmp(n, "cyan") == 0 || strcasecmp(n, "aqua") == 0)
+ return (FL_CYAN);
+ else if (strcasecmp(n, "white") == 0)
+ return (FL_WHITE);
+ else if (strcasecmp(n, "gray") == 0 || strcasecmp(n, "grey") == 0)
+ return (FL_GRAY);
+ else if (strcasecmp(n, "lime") == 0)
+ return (FL_GREEN);
+ else if (strcasecmp(n, "maroon") == 0)
+ return (fl_color_cube(2, 0, 0));
+ else if (strcasecmp(n, "navy") == 0)
+ return (fl_color_cube(0, 0, 2));
+ else if (strcasecmp(n, "olive") == 0)
+ return (fl_color_cube(2, 4, 0));
+ else if (strcasecmp(n, "purple") == 0)
+ return (fl_color_cube(2, 0, 2));
+ else if (strcasecmp(n, "silver") == 0)
+ return (FL_LIGHT2);
+ else if (strcasecmp(n, "teal") == 0)
+ return (fl_color_cube(0, 4, 2));
+ else
+ return (c);
+}
+
+
+//
+// 'HelpView::handle()' - Handle events in the widget.
+//
+
+int // O - 1 if we handled it, 0 otherwise
+HelpView::handle(int event) // I - Event to handle
+{
+ int i; // Looping var
+ int xx, yy; // Adjusted mouse position
+ HelpLink *link; // Current link
+ char target[32]; // Current target
+
+
+ switch (event)
+ {
+ case FL_MOVE :
+ case FL_PUSH :
+ xx = Fl::event_x() - x();
+ yy = Fl::event_y() - y() + topline_;
+ if (!scrollbar_.visible() || xx < (w() - 20))
+ break;
+
+ default :
+ // Use the Fl_Group handler...
+ return (Fl_Group::handle(event));
+ }
+
+ // Handle mouse clicks on links...
+ for (i = nlinks_, link = links_; i > 0; i --, link ++)
+ if (xx >= link->x && xx < link->w &&
+ yy >= link->y && yy < link->h)
+ break;
+
+ if (!i)
+ {
+ fl_cursor(FL_CURSOR_DEFAULT);
+ return (1);
+ }
+
+ // Change the cursor for FL_MOTION events, and go to the link for
+ // clicks...
+ if (event == FL_MOVE)
+ fl_cursor(FL_CURSOR_HAND);
+ else
+ {
+ fl_cursor(FL_CURSOR_DEFAULT);
+
+ strncpy(target, link->name, sizeof(target) - 1);
+ target[sizeof(target) - 1] = '\0';
+
+ set_changed();
+
+ if (strcmp(link->filename, filename_) != 0 && link->filename[0])
+ {
+ char dir[1024]; // Current directory
+ char temp[1024]; // Temporary filename
+
+
+ if (link->filename[0] != '/' && strchr(link->filename, ':') == NULL)
+ {
+ if (directory_[0])
+ sprintf(temp, "%s/%s", directory_, link->filename);
+ else
+ {
+ getcwd(dir, sizeof(dir));
+ sprintf(temp, "file:%s/%s", dir, link->filename);
+ }
+
+ load(temp);
+ }
+ else
+ load(link->filename);
+ }
+ else if (target[0])
+ topline(target);
+ else
+ topline(0);
+ }
+
+ return (1);
+}
+
+
+//
+// 'HelpView::HelpView()' - Build a HelpView widget.
+//
+
+HelpView::HelpView(int xx, // I - Left position
+ int yy, // I - Top position
+ int ww, // I - Width in pixels
+ int hh, // I - Height in pixels
+ const char *l)
+ : Fl_Group(xx, yy, ww, hh, l),
+ scrollbar_(xx + ww - 17, yy, 17, hh)
+{
+ filename_[0] = '\0';
+ value_ = NULL;
+
+ ablocks_ = 0;
+ nblocks_ = 0;
+ blocks_ = (HelpBlock *)0;
+
+ alinks_ = 0;
+ nlinks_ = 0;
+ links_ = (HelpLink *)0;
+
+ atargets_ = 0;
+ ntargets_ = 0;
+ targets_ = (HelpTarget *)0;
+
+ nfonts_ = 0;
+ textfont_ = FL_TIMES;
+ textsize_ = 12;
+
+ topline_ = 0;
+ size_ = 0;
+
+ color(FL_WHITE);
+ textcolor(FL_BLACK);
+ selection_color(FL_BLUE);
+
+ scrollbar_.value(0, hh, 0, 1);
+ scrollbar_.step(8.0);
+ scrollbar_.show();
+ scrollbar_.callback(scrollbar_callback);
+
+ end();
+}
+
+
+//
+// 'HelpView::~HelpView()' - Destroy a HelpView widget.
+//
+
+HelpView::~HelpView()
+{
+ if (nblocks_)
+ free(blocks_);
+ if (nlinks_)
+ free(links_);
+ if (ntargets_)
+ free(targets_);
+ if (value_)
+ free((void *)value_);
+}
+
+
+//
+// 'HelpView::load()' - Load the specified file.
+//
+
+int // O - 0 on success, -1 on error
+HelpView::load(const char *f) // I - Filename to load (may also have target)
+{
+ FILE *fp; // File to read from
+ long len; // Length of file
+ char *target; // Target in file
+ char *slash; // Directory separator
+ const char *localname; // Local filename
+ char error[1024]; // Error buffer
+
+
+ strcpy(filename_, f);
+ strcpy(directory_, filename_);
+
+ if ((slash = strrchr(directory_, '/')) == NULL)
+ directory_[0] = '\0';
+ else if (slash > directory_ && slash[-1] != '/')
+ *slash = '\0';
+
+ if ((target = strrchr(filename_, '#')) != NULL)
+ *target++ = '\0';
+
+ if (link_)
+ localname = (*link_)(filename_);
+ else
+ localname = filename_;
+
+ if (localname != NULL &&
+ (strncmp(localname, "ftp:", 4) == 0 ||
+ strncmp(localname, "http:", 5) == 0 ||
+ strncmp(localname, "https:", 6) == 0 ||
+ strncmp(localname, "ipp:", 4) == 0 ||
+ strncmp(localname, "mailto:", 7) == 0 ||
+ strncmp(localname, "news:", 5) == 0))
+ localname = NULL; // Remote link wasn't resolved...
+ else if (localname != NULL &&
+ strncmp(localname, "file:", 5) == 0)
+ localname += 5; // Adjust for local filename...
+
+ if (value_ != NULL)
+ {
+ free((void *)value_);
+ value_ = NULL;
+ }
+
+ if (localname)
+ {
+ if ((fp = fopen(localname, "rb")) != NULL)
+ {
+ fseek(fp, 0, SEEK_END);
+ len = ftell(fp);
+ rewind(fp);
+
+ value_ = (const char *)calloc(len + 1, 1);
+ fread((void *)value_, 1, len, fp);
+ fclose(fp);
+ }
+ else
+ {
+ sprintf(error, "%s: %s\n", localname, strerror(errno));
+ value_ = strdup(error);
+ }
+ }
+ else
+ value_ = strdup("File or link could not be opened.\n");
+
+ format();
+
+ if (target)
+ topline(target);
+ else
+ topline(0);
+
+ return (0);
+}
+
+
+//
+// 'HelpView::resize()' - Resize the help widget.
+//
+
+void
+HelpView::resize(int xx, // I - New left position
+ int yy, // I - New top position
+ int ww, // I - New width
+ int hh) // I - New height
+{
+ Fl_Widget::resize(xx, yy, ww, hh);
+ scrollbar_.resize(xx + ww - 17, yy, 17, hh);
+
+ format();
+}
+
+
+//
+// 'HelpView::topline()' - Set the top line to the named target.
+//
+
+void
+HelpView::topline(const char *n) // I - Target name
+{
+ HelpTarget key, // Target name key
+ *target; // Pointer to matching target
+
+
+ if (ntargets_ == 0)
+ return;
+
+ strncpy(key.name, n, sizeof(key.name) - 1);
+ key.name[sizeof(key.name) - 1] = '\0';
+
+ target = (HelpTarget *)bsearch(&key, targets_, ntargets_, sizeof(HelpTarget),
+ (int (*)(const void *, const void *))compare_targets);
+
+ if (target != NULL)
+ topline(target->y);
+}
+
+
+//
+// 'HelpView::topline()' - Set the top line by number.
+//
+
+void
+HelpView::topline(int t) // I - Top line number
+{
+ if (!value_)
+ return;
+
+ if (size_ < (h() - 8) || t < 0)
+ t = 0;
+ else if (t > size_)
+ t = size_;
+
+ topline_ = t;
+
+ scrollbar_.value(topline_, h(), 0, size_);
+
+ do_callback();
+ clear_changed();
+
+ redraw();
+}
+
+
+//
+// 'HelpView::value()' - Set the help text directly.
+//
+
+void
+HelpView::value(const char *v) // I - Text to view
+{
+ if (!v)
+ return;
+
+ if (value_ != NULL)
+ free((void *)value_);
+
+ value_ = strdup(v);
+
+ format();
+
+ set_changed();
+ topline(0);
+}
+
+
+//
+// 'scrollbar_callback()' - A callback for the scrollbar.
+//
+
+static void
+scrollbar_callback(Fl_Widget *s, void *)
+{
+ ((HelpView *)(s->parent()))->topline(int(((Fl_Scrollbar*)s)->value()));
+}
+
+
+//
+// End of "$Id: HelpView.cxx,v 1.22 2000/03/19 23:27:14 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/HelpView.h b/SrcUnix/espws-2.0/HelpView.h
new file mode 100644
index 0000000..ba327da
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpView.h
@@ -0,0 +1,180 @@
+//
+// "$Id: HelpView.h,v 1.9 2000/01/22 15:21:08 mike Exp $"
+//
+// Help Viewer widget definitions.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outblockd in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+
+#ifndef _GUI_HELPVIEW_H_
+# define _GUI_HELPVIEW_H_
+
+//
+// Include necessary header files...
+//
+
+# include <FL/Fl.H>
+# include <FL/Fl_Group.H>
+# include <FL/Fl_Scrollbar.H>
+# include <FL/fl_draw.H>
+
+
+//
+// HelpFunc type - link callback function for files...
+//
+
+
+typedef const char *(HelpFunc)(const char *);
+
+
+//
+// HelpBlock structure...
+//
+
+struct HelpBlock
+{
+ const char *start, // Start of text
+ *end; // End of text
+ uchar font, // Text font
+ size, // Text size
+ border; // Draw border?
+ short x, // Indentation/starting X coordinate
+ y, // Starting Y coordinate
+ w, // Width
+ h; // Height
+ short line[32]; // Left starting position for each line
+};
+
+//
+// HelpLink structure...
+//
+
+struct HelpLink
+{
+ char filename[192], // Reference filename
+ name[32]; // Link target (blank if none)
+ int x, // X offset of link text
+ y, // Y offset of link text
+ w, // Width of link text
+ h; // Height of link text
+};
+
+//
+// HelpTarget structure...
+//
+
+struct HelpTarget
+{
+ char name[32]; // Target name
+ int y; // Y offset of target
+};
+
+//
+// HelpView class...
+//
+
+class HelpView : public Fl_Group //// Help viewer widget
+{
+ enum { RIGHT = -1, CENTER, LEFT }; // Alignments
+
+ char title_[1024]; // Title string
+ Fl_Color defcolor_, // Default text color
+ bgcolor_, // Background color
+ textcolor_, // Text color
+ linkcolor_; // Link color
+ uchar textfont_, // Default font for text
+ textsize_; // Default font size
+ const char *value_; // HTML text value
+
+ int nblocks_, // Number of blocks/paragraphs
+ ablocks_; // Allocated blocks
+ HelpBlock *blocks_; // Blocks
+
+ int nfonts_; // Number of fonts in stack
+ uchar fonts_[100][2]; // Font stack
+
+ HelpFunc *link_; // Link transform function
+
+ int nlinks_, // Number of links
+ alinks_; // Allocated links
+ HelpLink *links_; // Links
+
+ int ntargets_, // Number of targets
+ atargets_; // Allocated targets
+ HelpTarget *targets_; // Targets
+
+ char directory_[1024]; // Directory for current file
+ char filename_[1024]; // Current filename
+ int topline_, // Top line in document
+ size_; // Total document length
+ Fl_Scrollbar scrollbar_; // Scrollbar for document
+
+ HelpBlock *add_block(const char *s, int xx, int yy, int ww, int hh, uchar border = 0);
+ void add_link(const char *n, int xx, int yy, int ww, int hh);
+ void add_target(const char *n, int yy);
+ static int compare_targets(const HelpTarget *t0, const HelpTarget *t1);
+ int do_align(HelpBlock *block, int line, int xx, int a, int &l);
+ void draw();
+ void format();
+ int get_align(const char *p, int a);
+ const char *get_attr(const char *p, const char *n, char *buf, int bufsize);
+ Fl_Color get_color(const char *n, Fl_Color c);
+ int handle(int);
+
+ void initfont(uchar &f, uchar &s) { nfonts_ = 0;
+ fl_font(f = fonts_[0][0] = textfont_,
+ s = fonts_[0][1] = textsize_); }
+ void pushfont(uchar f, uchar s) { if (nfonts_ < 99) nfonts_ ++;
+ fl_font(fonts_[nfonts_][0] = f,
+ fonts_[nfonts_][1] = s); }
+ void popfont(uchar &f, uchar &s) { if (nfonts_ > 0) nfonts_ --;
+ fl_font(f = fonts_[nfonts_][0],
+ s = fonts_[nfonts_][1]); }
+
+ public:
+
+ HelpView(int xx, int yy, int ww, int hh, const char *l = 0);
+ ~HelpView();
+ const char *directory() const { if (directory_[0]) return (directory_);
+ else return ((const char *)0); }
+ const char *filename() const { if (filename_[0]) return (filename_);
+ else return ((const char *)0); }
+ void link(HelpFunc *fn) { link_ = fn; }
+ int load(const char *f);
+ void resize(int,int,int,int);
+ int size() const { return (size_); }
+ void textcolor(Fl_Color c) { if (textcolor_ == defcolor_) textcolor_ = c; defcolor_ = c; }
+ Fl_Color textcolor() const { return (defcolor_); }
+ void textfont(uchar f) { textfont_ = f; format(); }
+ uchar textfont() const { return (textfont_); }
+ void textsize(uchar s) { textsize_ = s; format(); }
+ uchar textsize() const { return (textsize_); }
+ const char *title() { return (title_); }
+ void topline(const char *n);
+ void topline(int);
+ int topline() const { return (topline_); }
+ void value(const char *v);
+ const char *value() const { return (value_); }
+};
+
+#endif // !_GUI_HELPVIEW_H_
+
+//
+// End of "$Id: HelpView.h,v 1.9 2000/01/22 15:21:08 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/HelpView.html b/SrcUnix/espws-2.0/HelpView.html
new file mode 100644
index 0000000..88294dc
--- /dev/null
+++ b/SrcUnix/espws-2.0/HelpView.html
@@ -0,0 +1,130 @@
+<HTML>
+<HEAD>
+ <TITLE>HelpView - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<!-- NEW PAGE -->
+<H2>class HelpView</H2>
+
+<HR>
+
+<H3>Class Hierarchy</H3>
+
+<UL><PRE>
+Fl_Group
+ |
+ +----<B>HelpView</B>
+</PRE></UL>
+
+<H3>Include Files</H3>
+
+<UL><PRE>
+#include "HelpView.h"
+</PRE></UL>
+
+<H3>Description</H3>
+
+<P>The <CODE>HelpView</CODE> widget displays HTML text. Most HTML 2.0
+elements are supported, as well as a primitive implementation of tables.
+Images are not currently displayed (although the ALT text is, if present.)
+
+<H3>Methods</H3>
+
+<UL>
+
+ <LI><A HREF="#HelpView.HelpView">HelpView</A>
+ <LI><A HREF="#HelpView.~HelpView">~HelpView</A>
+ <LI><A HREF="#HelpView.directory">directory</A>
+ <LI><A HREF="#HelpView.filename">filename</A>
+ <LI><A HREF="#HelpView.link">link</A>
+ <LI><A HREF="#HelpView.load">load</A>
+ <LI><A HREF="#HelpView.size">size</A>
+ <LI><A HREF="#HelpView.textcolor">textcolor</A>
+ <LI><A HREF="#HelpView.textfont">textfont</A>
+ <LI><A HREF="#HelpView.textsize">textsize</A>
+ <LI><A HREF="#HelpView.title">title</A>
+ <LI><A HREF="#HelpView.topline">topline</A>
+ <LI><A HREF="#HelpView.value">value</A>
+
+</UL>
+
+<H4><A NAME="HelpView.HelpView">HelpView(int xx, int yy, int ww, int hh, const char *l = 0)</A></H4>
+
+<P>The constructor creates the <CODE>HelpView</CODE> widget at the specified
+position and size.
+
+<H4><A NAME="HelpView.~HelpView">~HelpView()</A></H4>
+
+<P>The destructor destroys the widget and frees all memory that has been
+allocated for the current file.
+
+<H4><A NAME="HelpView.directory">const char *directory() const</A></H4>
+
+<P>This method returns the current directory (base) path for the file
+in the buffer.
+
+<H4><A NAME="HelpView.filename">const char *filename() const</A></H4>
+
+<P>This method returns the current filename for the text in the buffer.
+
+<H4><A NAME="HelpView.link">void link(HelpFunc *fn)</A></H4>
+
+<P>This method assigns a callback function to use when a link is
+followed or a file is loaded (via <CODE>HelpView::load()</CODE>) that
+requires a different file or path. The callback function receives the
+full pathname for the file in question and must return a pathname that
+can be opened as a local file. This is used by the
+<A HREF="HelpApp.html"><CODE>HelpApp</CODE></A> widget to support WWW
+addresses.
+
+<H4><A NAME="HelpView.load">int load(const char *f)</A></H4>
+
+<P>This method loads the specified file or URL.
+
+<H4><A NAME="HelpView.size">int size() const</A></H4>
+
+<P>This method returns the length of the buffer text in pixels.
+
+<H4><A NAME="HelpView.textcolor">void textcolor(Fl_Color c)<BR>
+Fl_Color textcolor() const</A></H4>
+
+<P>The first form sets the default text color. The second returns
+the current default text color.
+
+<H4><A NAME="HelpView.textfont">void textfont(uchar f)<BR>
+uchar textfont() const</A></H4>
+
+<P>The first form sets the default text font. The second returns
+the current default text font.
+
+<H4><A NAME="HelpView.textsize">void textsize(uchar s)<BR>
+uchar textsize() const</A></H4>
+
+<P>The first form sets the default text size. The second returns
+the current default text size.
+
+<H4><A NAME="HelpView.title">const char *title()</A></H4>
+
+<P>This method returns the current document title, or NULL if there
+is no title.
+
+<H4><A NAME="HelpView.topline">void topline(const char *n)<BR>
+void topline(int)<BR>
+int topline() const</A></H4>
+
+<P>The first two forms scroll the text to the indicated position, either
+with a named destination or by pixel line.
+
+<P>The second form returns the current top line in pixels.
+
+<H4><A NAME="HelpView.value">void value(const char *v)<BR>
+const char *value() const</A></H4>
+
+<P>The first form sets the current buffer to the string provided and
+reformats the text. The second form returns the current buffer contents.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/Makefile.in b/SrcUnix/espws-2.0/Makefile.in
new file mode 100644
index 0000000..7fde551
--- /dev/null
+++ b/SrcUnix/espws-2.0/Makefile.in
@@ -0,0 +1,121 @@
+#
+# Makefile for widgets and example programs.
+#
+# Copyright 1999-2000 by Michael Sweet.
+#
+
+#
+# Programs...
+#
+
+AR = @AR@
+CC = @CC@
+CXX = @CXX@
+RANLIB = @RANLIB@
+RM = @RM@ -f
+SHELL = /bin/sh
+
+#
+# Program options...
+#
+
+ARFLAGS = crvs
+CFLAGS = @CFLAGS@ @DEFS@
+CXXFLAGS = @CXXFLAGS@ @DEFS@
+LIBS = @LIBS@ -lXext -lX11
+LDFLAGS = @LDFLAGS@
+
+#
+# Rules...
+#
+
+.SILENT:
+.SUFFIXES: .c .cxx .h .o
+.c.o:
+ echo Compiling $<...
+ $(CC) $(CFLAGS) -c $<
+.cxx.o:
+ echo Compiling $<...
+ $(CXX) $(CXXFLAGS) -c $<
+
+#
+# Make all targets...
+#
+
+all: libespws.a testfile testhelp flsurf
+
+
+#
+# Remove object and target files...
+#
+
+clean:
+ $(RM) *.o
+ $(RM) libespws.a
+ $(RM) testfile
+ $(RM) testhelp
+ $(RM) flsurf
+
+
+#
+# Make the file chooser widget library.
+#
+
+LIBOBJS = FileBrowser.o FileChooser.o FileChooser2.o FileIcon.o \
+ FileInput.o Fl_Wizard.o HelpApp.o HelpApp2.o HelpDialog.o \
+ HelpView.o
+
+libespws.a: $(LIBOBJS)
+ echo Building library $@...
+ $(RM) libespws.a
+ $(AR) $(ARFLAGS) libespws.a $(LIBOBJS)
+ $(RANLIB) libespws.a
+
+FileBrowser.o: FileBrowser.h FileIcon.h
+FileChooser2.o: FileBrowser.h FileChooser.h FileIcon.h FileInput.h
+FileChooser.o: FileBrowser.h FileChooser.h FileIcon.h FileInput.h
+FileIcon.o: FileIcon.h
+FileInput.o: FileInput.h
+Fl_Wizard.o: Fl_Wizard.h
+HelpApp.o: HelpApp.h HelpView.h
+HelpApp2.o: HelpApp.h HelpView.h
+HelpDialog.o: HelpDialog.h HelpView.h
+HelpView.o: HelpView.h
+
+
+#
+# Make the file chooser test program.
+#
+
+testfile: libespws.a testfile.o
+ echo Linking $@...
+ $(CXX) $(LDFLAGS) -o testfile testfile.o libespws.a $(LIBS)
+
+testfile.o: FileBrowser.h FileChooser.h FileIcon.h FileInput.h
+
+
+#
+# Make the help test program.
+#
+
+testhelp: libespws.a testhelp.o
+ echo Linking $@...
+ $(CXX) $(LDFLAGS) -o testhelp testhelp.o libespws.a $(LIBS)
+
+testhelp.o: HelpDialog.h HelpView.h
+
+
+#
+# Make the flsurf program.
+#
+
+flsurf: libespws.a flsurf.o
+ echo Linking $@...
+ $(CXX) $(LDFLAGS) -o flsurf flsurf.o libespws.a $(LIBS)
+
+flsurf.o: HelpApp.h HelpView.h
+
+
+#
+# End of Makefile.
+#
diff --git a/SrcUnix/espws-2.0/allfiles.xbm b/SrcUnix/espws-2.0/allfiles.xbm
new file mode 100644
index 0000000..26373b6
--- /dev/null
+++ b/SrcUnix/espws-2.0/allfiles.xbm
@@ -0,0 +1,6 @@
+#define allfiles_width 16
+#define allfiles_height 16
+static unsigned char allfiles_bits[] = {
+ 0xfc, 0x3f, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x84, 0x21, 0xa4, 0x25,
+ 0xc4, 0x23, 0xf4, 0x2f, 0xf4, 0x2f, 0xc4, 0x23, 0xa4, 0x25, 0x84, 0x21,
+ 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0xfc, 0x3f};
diff --git a/SrcUnix/espws-2.0/configure b/SrcUnix/espws-2.0/configure
new file mode 100755
index 0000000..5abc232
--- /dev/null
+++ b/SrcUnix/espws-2.0/configure
@@ -0,0 +1,1865 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-x use the X Window System"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=Makefile.in
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+uname=`uname`
+if test "$uname" = "IRIX64"; then
+ uname="IRIX"
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:536: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:566: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:617: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:649: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 660 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:665: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:691: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:696: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:724: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:760: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:792: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 803 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:834: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:839: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:848: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:867: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:901: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:931: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$AR" in
+ /*)
+ ac_cv_path_AR="$AR" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_AR="$AR" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_AR="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+AR="$ac_cv_path_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:966: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$RM" in
+ /*)
+ ac_cv_path_RM="$RM" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_RM="$RM" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_RM="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+RM="$ac_cv_path_RM"
+if test -n "$RM"; then
+ echo "$ac_t""$RM" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1000: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1015 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1021: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1032 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1038: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1049 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+# If we find X, set shell vars x_includes and x_libraries to the
+# paths, otherwise set no_x=yes.
+# Uses ac_ vars as temps to allow command line to override cache and checks.
+# --without-x overrides everything else, but does not touch the cache.
+echo $ac_n "checking for X""... $ac_c" 1>&6
+echo "configure:1084: checking for X" >&5
+
+# Check whether --with-x or --without-x was given.
+if test "${with_x+set}" = set; then
+ withval="$with_x"
+ :
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+ # The user explicitly disabled X.
+ have_x=disabled
+else
+ if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+ # Both variables are already set.
+ have_x=yes
+ else
+if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=NO ac_x_libraries=NO
+rm -fr conftestdir
+if mkdir conftestdir; then
+ cd conftestdir
+ # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+ cat > Imakefile <<'EOF'
+acfindx:
+ @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+ if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+ # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+ eval `${MAKE-make} acfindx 2>/dev/null | grep -v make`
+ # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+ for ac_extension in a so sl; do
+ if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+ test -f $ac_im_libdir/libX11.$ac_extension; then
+ ac_im_usrlibdir=$ac_im_libdir; break
+ fi
+ done
+ # Screen out bogus values from the imake configuration. They are
+ # bogus both because they are the default anyway, and because
+ # using them would break gcc on systems where it needs fixed includes.
+ case "$ac_im_incroot" in
+ /usr/include) ;;
+ *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+ esac
+ case "$ac_im_usrlibdir" in
+ /usr/lib | /lib) ;;
+ *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+ esac
+ fi
+ cd ..
+ rm -fr conftestdir
+fi
+
+if test "$ac_x_includes" = NO; then
+ # Guess where to find include files, by looking for this one X11 .h file.
+ test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+
+ # First, try using that file with no special directory specified.
+cat > conftest.$ac_ext <<EOF
+#line 1146 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1151: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ for ac_dir in \
+ /usr/X11/include \
+ /usr/X11R6/include \
+ /usr/X11R5/include \
+ /usr/X11R4/include \
+ \
+ /usr/include/X11 \
+ /usr/include/X11R6 \
+ /usr/include/X11R5 \
+ /usr/include/X11R4 \
+ \
+ /usr/local/X11/include \
+ /usr/local/X11R6/include \
+ /usr/local/X11R5/include \
+ /usr/local/X11R4/include \
+ \
+ /usr/local/include/X11 \
+ /usr/local/include/X11R6 \
+ /usr/local/include/X11R5 \
+ /usr/local/include/X11R4 \
+ \
+ /usr/X386/include \
+ /usr/x386/include \
+ /usr/XFree86/include/X11 \
+ \
+ /usr/include \
+ /usr/local/include \
+ /usr/unsupported/include \
+ /usr/athena/include \
+ /usr/local/x11r5/include \
+ /usr/lpp/Xamples/include \
+ \
+ /usr/openwin/include \
+ /usr/openwin/share/include \
+ ; \
+ do
+ if test -r "$ac_dir/$x_direct_test_include"; then
+ ac_x_includes=$ac_dir
+ break
+ fi
+ done
+fi
+rm -f conftest*
+fi # $ac_x_includes = NO
+
+if test "$ac_x_libraries" = NO; then
+ # Check for the libraries.
+
+ test -z "$x_direct_test_library" && x_direct_test_library=Xt
+ test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+
+ # See if we find them without any special options.
+ # Don't add to $LIBS permanently.
+ ac_save_LIBS="$LIBS"
+ LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1220 "configure"
+#include "confdefs.h"
+
+int main() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if { (eval echo configure:1227: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+ /usr/X11/lib \
+ /usr/X11R6/lib \
+ /usr/X11R5/lib \
+ /usr/X11R4/lib \
+ \
+ /usr/lib/X11 \
+ /usr/lib/X11R6 \
+ /usr/lib/X11R5 \
+ /usr/lib/X11R4 \
+ \
+ /usr/local/X11/lib \
+ /usr/local/X11R6/lib \
+ /usr/local/X11R5/lib \
+ /usr/local/X11R4/lib \
+ \
+ /usr/local/lib/X11 \
+ /usr/local/lib/X11R6 \
+ /usr/local/lib/X11R5 \
+ /usr/local/lib/X11R4 \
+ \
+ /usr/X386/lib \
+ /usr/x386/lib \
+ /usr/XFree86/lib/X11 \
+ \
+ /usr/lib \
+ /usr/local/lib \
+ /usr/unsupported/lib \
+ /usr/athena/lib \
+ /usr/local/x11r5/lib \
+ /usr/lpp/Xamples/lib \
+ /lib/usr/lib/X11 \
+ \
+ /usr/openwin/lib \
+ /usr/openwin/share/lib \
+ ; \
+do
+ for ac_extension in a so sl; do
+ if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+ ac_x_libraries=$ac_dir
+ break 2
+ fi
+ done
+done
+fi
+rm -f conftest*
+fi # $ac_x_libraries = NO
+
+if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then
+ # Didn't find X anywhere. Cache the known absence of X.
+ ac_cv_have_x="have_x=no"
+else
+ # Record where we found X for the cache.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+ fi
+ eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+ echo "$ac_t""$have_x" 1>&6
+ no_x=yes
+else
+ # If each of the values was on the command line, it overrides each guess.
+ test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+ test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+ # Update the cache value to reflect the command line values.
+ ac_cv_have_x="have_x=yes \
+ ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+ echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+if test "$x_libraries" = "/usr/lib"; then
+ echo "Ignoring X library directory \"$x_libraries\" requested by configure."
+ x_libraries="NONE"
+fi
+if test ! "$x_libraries" = "NONE" -a ! "$x_libraries" = ""; then
+ LDFLAGS="$LDFLAGS -L$x_libraries"
+ if test "$uname" = "SunOS"; then
+ LDFLAGS="$LDFLAGS -R$x_libraries"
+ fi
+fi
+if test "$x_includes" = "/usr/include"; then
+ echo "Ignoring X include directory \"$x_includes\" requested by configure."
+ x_includes="NONE"
+fi
+if test ! "$x_includes" = "NONE" -a ! "$x_includes" = ""; then
+ CFLAGS="$CFLAGS -I$x_includes"
+ CXXFLAGS="$CXXFLAGS -I$x_includes"
+fi
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:1332: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1340 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ if test "$uname" != "IRIX"; then
+ LIBS="-lsocket $LIBS"
+else
+ echo "Not using -lsocket since you are running IRIX."
+fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for gethostbyaddr in -lnsl""... $ac_c" 1>&6
+echo "configure:1376: checking for gethostbyaddr in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyaddr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1384 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyaddr();
+
+int main() {
+gethostbyaddr()
+; return 0; }
+EOF
+if { (eval echo configure:1395: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ if test "$uname" != "IRIX"; then
+ LIBS="-lnsl $LIBS"
+else
+ echo "Not using -lnsl since you are running IRIX."
+fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for httpConnect in -lcups""... $ac_c" 1>&6
+echo "configure:1421: checking for httpConnect in -lcups" >&5
+ac_lib_var=`echo cups'_'httpConnect | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcups $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1429 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char httpConnect();
+
+int main() {
+httpConnect()
+; return 0; }
+EOF
+if { (eval echo configure:1440: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo cups | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcups $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for pow in -lm""... $ac_c" 1>&6
+echo "configure:1468: checking for pow in -lm" >&5
+ac_lib_var=`echo m'_'pow | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1476 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char pow();
+
+int main() {
+pow()
+; return 0; }
+EOF
+if { (eval echo configure:1487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lm $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for glEnable in -lGL""... $ac_c" 1>&6
+echo "configure:1515: checking for glEnable in -lGL" >&5
+ac_lib_var=`echo GL'_'glEnable | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lGL $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1523 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char glEnable();
+
+int main() {
+glEnable()
+; return 0; }
+EOF
+if { (eval echo configure:1534: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo GL | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lGL $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for numericsort in -lfltk""... $ac_c" 1>&6
+echo "configure:1562: checking for numericsort in -lfltk" >&5
+ac_lib_var=`echo fltk'_'numericsort | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lfltk $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1570 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char numericsort();
+
+int main() {
+numericsort()
+; return 0; }
+EOF
+if { (eval echo configure:1581: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo fltk | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lfltk $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CXX@%$CXX%g
+s%@RANLIB@%$RANLIB%g
+s%@AR@%$AR%g
+s%@RM@%$RM%g
+s%@CPP@%$CPP%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
diff --git a/SrcUnix/espws-2.0/configure.in b/SrcUnix/espws-2.0/configure.in
new file mode 100644
index 0000000..caaf578
--- /dev/null
+++ b/SrcUnix/espws-2.0/configure.in
@@ -0,0 +1,69 @@
+dnl
+dnl Autoconf configuration script for FLTK widget.
+dnl
+dnl Copyright 1999 by Michael Sweet.
+dnl
+dnl Permission is granted to use, copy, modify, and redistribute this file as
+dnl needed.
+dnl
+
+dnl Make sure we have the template for the makefile...
+AC_INIT(Makefile.in)
+
+dnl What OS?
+uname=`uname`
+if test "$uname" = "IRIX64"; then
+ uname="IRIX"
+fi
+
+dnl Checks for programs...
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_RANLIB
+AC_PATH_PROG(AR,ar)
+AC_PATH_PROG(RM,rm)
+
+dnl Check for libraries...
+AC_PATH_X
+if test "$x_libraries" = "/usr/lib"; then
+ echo "Ignoring X library directory \"$x_libraries\" requested by configure."
+ x_libraries="NONE"
+fi
+if test ! "$x_libraries" = "NONE" -a ! "$x_libraries" = ""; then
+ LDFLAGS="$LDFLAGS -L$x_libraries"
+ if test "$uname" = "SunOS"; then
+ LDFLAGS="$LDFLAGS -R$x_libraries"
+ fi
+fi
+if test "$x_includes" = "/usr/include"; then
+ echo "Ignoring X include directory \"$x_includes\" requested by configure."
+ x_includes="NONE"
+fi
+if test ! "$x_includes" = "NONE" -a ! "$x_includes" = ""; then
+ CFLAGS="$CFLAGS -I$x_includes"
+ CXXFLAGS="$CXXFLAGS -I$x_includes"
+fi
+AC_CHECK_LIB(socket,socket,
+if test "$uname" != "IRIX"; then
+ LIBS="-lsocket $LIBS"
+else
+ echo "Not using -lsocket since you are running IRIX."
+fi)
+AC_CHECK_LIB(nsl,gethostbyaddr,
+if test "$uname" != "IRIX"; then
+ LIBS="-lnsl $LIBS"
+else
+ echo "Not using -lnsl since you are running IRIX."
+fi)
+
+AC_CHECK_LIB(cups,httpConnect)
+AC_CHECK_LIB(m,pow)
+AC_CHECK_LIB(GL,glEnable)
+AC_CHECK_LIB(fltk,numericsort)
+
+dnl Output the makefile...
+AC_OUTPUT(Makefile)
+
+dnl
+dnl End of configure script.
+dnl
diff --git a/SrcUnix/espws-2.0/documentation.html b/SrcUnix/espws-2.0/documentation.html
new file mode 100644
index 0000000..403478b
--- /dev/null
+++ b/SrcUnix/espws-2.0/documentation.html
@@ -0,0 +1,73 @@
+<HTML>
+<HEAD>
+ <TITLE>Documentation - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,51,21" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORDS="82,8,128,21" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORDS="150,8,269,21" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORDS="291,8,369,21" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORDS="391,8,434,21" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<P ALIGN="CENTER">
+<IMG SRC="navbar.gif" WIDTH="449" HEIGHT="30" BORDER="0" ISMAP USEMAP="#navbar">
+<BR>
+<A HREF="http://www.easysw.com">ESP</A> |
+<A HREF="index.html">Home</A> |
+<A HREF="documentation.html">Documentation</A> |
+<A HREF="download.html">Download</A> |
+<A HREF="http://www.fltk.org">FLTK</A>
+</P>
+
+<H1 ALIGN="CENTER">Documentation</H1>
+
+<P><A HREF="espws.pdf">PDF Version (???k)</A>
+
+<OL>
+
+ <LI><A HREF="intro.html">Introduction</A>
+
+ <LI><A HREF="file.html">The File Chooser</A>
+
+ <LI><A HREF="help.html">The Help Dialog</A>
+
+ <LI><A HREF="flsurf.html">The Help Application (flsurf)</A>
+
+ <LI><A HREF="widgets.html">Widget Reference</A>
+
+ <UL>
+
+ <LI><A HREF="CheckButton.html">CheckButton</A>
+
+ <LI><A HREF="FileBrowser.html">FileBrowser</A>
+
+ <LI><A HREF="FileChooser.html">FileChooser</A>
+
+ <LI><A HREF="FileInput.html">FileInput</A>
+
+ <LI><A HREF="Fl_Wizard.html">Fl_Wizard</A>
+
+ <LI><A HREF="HelpApp.html">HelpApp</A>
+
+ <LI><A HREF="HelpDialog.html">HelpDialog</A>
+
+ <LI><A HREF="HelpView.html">HelpView</A>
+
+ </UL>
+
+ <LI><A HREF="relnotes.html">Release Notes</A>
+
+</OL>
+
+<HR>
+
+<P>Copyright 1997-2000 by Easy Software Products. This software is provided
+under the terms of the <A HREF="http://www.fsf.org/copyleft/gpl.html">
+GNU General Public License</A>.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/download.html b/SrcUnix/espws-2.0/download.html
new file mode 100644
index 0000000..064b089
--- /dev/null
+++ b/SrcUnix/espws-2.0/download.html
@@ -0,0 +1,54 @@
+<HTML>
+<HEAD>
+ <TITLE>Download - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,51,21" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORDS="82,8,128,21" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORDS="150,8,269,21" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORDS="291,8,369,21" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORDS="391,8,434,21" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<P ALIGN="CENTER">
+<IMG SRC="navbar.gif" WIDTH="449" HEIGHT="30" BORDER="0" ISMAP USEMAP="#navbar">
+<BR>
+<A HREF="http://www.easysw.com">ESP</A> |
+<A HREF="index.html">Home</A> |
+<A HREF="documentation.html">Documentation</A> |
+<A HREF="download.html">Download</A> |
+<A HREF="http://www.fltk.org">FLTK</A>
+</P>
+
+<H1 ALIGN="CENTER">Download</H1>
+
+<P>The ESP Widget Set for FLTK is available for download in three
+flavors for your convenience:
+
+<UL>
+
+ <LI><A HREF="ftp://ftp.easysw.com/pub/fltk/contrib/espws20.tar.gz">
+ 2.0 Source in .tar.gz format (165k)</A>
+
+ <LI><A HREF="ftp://ftp.easysw.com/pub/fltk/contrib/espws20.tar.bz2">
+ 2.0 Source in .tar.bz2 format (150k)</A>
+
+ <LI><A HREF="ftp://ftp.easysw.com/pub/fltk/contrib/espws20.zip">
+ 2.0 Source in .zip format (181k)</A>
+
+</UL>
+
+<P>Please read the <A HREF="documentation.html">documentation</A> if you need
+assistance.
+
+<HR>
+
+<P>Copyright 1997-2000 by Easy Software Products. This software is provided
+under the terms of the <A HREF="http://www.fsf.org/copyleft/gpl.html">
+GNU General Public License</A>.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/espws.book b/SrcUnix/espws-2.0/espws.book
new file mode 100644
index 0000000..c010298
--- /dev/null
+++ b/SrcUnix/espws-2.0/espws.book
@@ -0,0 +1,18 @@
+#HTMLDOC 1.8.6
+15
+intro.html
+file.html
+help.html
+flsurf.html
+widgets.html
+CheckButton.html
+FileBrowser.html
+FileChooser.html
+FileIcon.html
+FileInput.html
+Fl_Wizard.html
+HelpApp.html
+HelpDialog.html
+HelpView.html
+relnotes.html
+-t pdf12 -f espws.pdf --book --toclevels 2 --toctitle "Table of Contents" --title --linkstyle underline --bodycolor #ffffff --size Universal --left 1.00in --right 0.50in --top 0.50in --bottom 0.50in --header .t. --footer h.1 --tocheader .t. --tocfooter ..i --duplex --portrait --color --no-pscommands --compression=9 --jpeg=90 --fontsize 11.0 --fontspacing 1.2 --headingfont Helvetica --bodyfont Times --headfootsize 11.0 --headfootfont Helvetica --charset 8859-1 --pagemode outlines --pagelayout single --firstpage c1 --pageeffect none --pageduration 10 --effectduration 1.0 --browserwidth 680
diff --git a/SrcUnix/espws-2.0/espws.pdf b/SrcUnix/espws-2.0/espws.pdf
new file mode 100644
index 0000000..c2e7517
--- /dev/null
+++ b/SrcUnix/espws-2.0/espws.pdf
@@ -0,0 +1,1378 @@
+%PDF-1.2
+%âãÏÓ
+1 0 obj<</Producer(htmldoc 1.8.6 Copyright 1997-2000 Easy Software Products, All Rights Reserved.)/CreationDate(D:20000320020228Z)/Title(ESP Widget Set for FLTK)/Author(Easy Software Products)>>endobj
+2 0 obj<</Type/Encoding/Differences[ 32/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quotesingle/parenleft/parenright/asterisk/plus/comma/minus/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/grave/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 160/space/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]>>endobj
+3 0 obj<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding 2 0 R>>endobj
+4 0 obj<</Type/Font/Subtype/Type1/BaseFont/Courier-Bold/Encoding 2 0 R>>endobj
+5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Courier-BoldOblique/Encoding 2 0 R>>endobj
+6 0 obj<</Type/Font/Subtype/Type1/BaseFont/Times-Roman/Encoding 2 0 R>>endobj
+7 0 obj<</Type/Font/Subtype/Type1/BaseFont/Times-Bold/Encoding 2 0 R>>endobj
+8 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica/Encoding 2 0 R>>endobj
+9 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica-Bold/Encoding 2 0 R>>endobj
+10 0 obj<</Type/Font/Subtype/Type1/BaseFont/Symbol>>endobj
+11 0 obj<</S/URI/URI(http://www.fsf.org/copyleft/gpl.html)>>endobj
+12 0 obj<</Subtype/Link/Rect[328.3 669.6 457.5 682.6]/Border[0 0 0]/A 11 0 R>>endobj
+13 0 obj[12 0 R
+]endobj
+14 0 obj<</S/URI/URI(http://www.cups.org)>>endobj
+15 0 obj<</Subtype/Link/Rect[243.7 565.6 271.2 578.6]/Border[0 0 0]/A 14 0 R>>endobj
+16 0 obj[15 0 R
+]endobj
+17 0 obj<</Subtype/Link/Rect[108.0 656.4 180.6 669.4]/Border[0 0 0]/Dest[321 0 R/XYZ null 384 0]>>endobj
+18 0 obj<</Subtype/Link/Rect[108.0 643.2 180.6 656.2]/Border[0 0 0]/Dest[324 0 R/XYZ null 281 0]>>endobj
+19 0 obj<</Subtype/Link/Rect[108.0 630.0 160.8 643.0]/Border[0 0 0]/Dest[336 0 R/XYZ null 49 0]>>endobj
+20 0 obj<</Subtype/Link/Rect[108.0 616.8 167.4 629.8]/Border[0 0 0]/Dest[348 0 R/XYZ null 268 0]>>endobj
+21 0 obj<</Subtype/Link/Rect[108.0 603.6 160.8 616.6]/Border[0 0 0]/Dest[369 0 R/XYZ null 275 0]>>endobj
+22 0 obj<</Subtype/Link/Rect[108.0 511.2 180.6 524.2]/Border[0 0 0]/Dest[327 0 R/XYZ null 57 0]>>endobj
+23 0 obj<</Subtype/Link/Rect[108.0 484.8 174.0 497.8]/Border[0 0 0]/Dest[363 0 R/XYZ null 499 0]>>endobj
+24 0 obj<</Subtype/Link/Rect[108.0 471.6 154.2 484.6]/Border[0 0 0]/Dest[354 0 R/XYZ null 645 0]>>endobj
+25 0 obj<</Subtype/Link/Rect[433.2 432.0 457.0 445.0]/Border[0 0 0]/Dest[309 0 R/XYZ null 308 0]>>endobj
+26 0 obj[17 0 R
+18 0 R
+19 0 R
+20 0 R
+21 0 R
+22 0 R
+23 0 R
+24 0 R
+25 0 R
+]endobj
+27 0 obj<</Subtype/Link/Rect[72.0 434.7 130.1 447.7]/Border[0 0 0]/Dest[324 0 R/XYZ null 440 0]>>endobj
+28 0 obj<</Subtype/Link/Rect[72.0 421.5 136.0 434.5]/Border[0 0 0]/Dest[324 0 R/XYZ null 387 0]>>endobj
+29 0 obj[27 0 R
+28 0 R
+]endobj
+30 0 obj<</Subtype/Link/Rect[108.0 447.9 162.4 460.9]/Border[0 0 0]/Dest[327 0 R/XYZ null 413 0]>>endobj
+31 0 obj<</Subtype/Link/Rect[108.0 434.7 168.3 447.7]/Border[0 0 0]/Dest[327 0 R/XYZ null 361 0]>>endobj
+32 0 obj<</Subtype/Link/Rect[108.0 421.5 144.0 434.5]/Border[0 0 0]/Dest[327 0 R/XYZ null 308 0]>>endobj
+33 0 obj<</Subtype/Link/Rect[108.0 408.3 129.4 421.3]/Border[0 0 0]/Dest[327 0 R/XYZ null 242 0]>>endobj
+34 0 obj<</Subtype/Link/Rect[108.0 395.1 126.9 408.1]/Border[0 0 0]/Dest[327 0 R/XYZ null 176 0]>>endobj
+35 0 obj[30 0 R
+31 0 R
+32 0 R
+33 0 R
+34 0 R
+]endobj
+36 0 obj<</Subtype/Link/Rect[72.0 190.9 125.8 203.9]/Border[0 0 0]/Dest[333 0 R/XYZ null 671 0]>>endobj
+37 0 obj<</Subtype/Link/Rect[72.0 177.7 131.7 190.7]/Border[0 0 0]/Dest[333 0 R/XYZ null 447 0]>>endobj
+38 0 obj<</Subtype/Link/Rect[72.0 164.5 94.6 177.5]/Border[0 0 0]/Dest[333 0 R/XYZ null 394 0]>>endobj
+39 0 obj<</Subtype/Link/Rect[72.0 151.3 96.4 164.3]/Border[0 0 0]/Dest[333 0 R/XYZ null 328 0]>>endobj
+40 0 obj<</Subtype/Link/Rect[72.0 138.1 111.7 151.1]/Border[0 0 0]/Dest[333 0 R/XYZ null 275 0]>>endobj
+41 0 obj<</Subtype/Link/Rect[72.0 124.9 93.4 137.9]/Border[0 0 0]/Dest[333 0 R/XYZ null 209 0]>>endobj
+42 0 obj<</Subtype/Link/Rect[72.0 111.7 90.9 124.7]/Border[0 0 0]/Dest[333 0 R/XYZ null 143 0]>>endobj
+43 0 obj<</Subtype/Link/Rect[72.0 98.5 108.0 111.5]/Border[0 0 0]/Dest[336 0 R/XYZ null 763 0]>>endobj
+44 0 obj<</Subtype/Link/Rect[72.0 85.3 93.4 98.3]/Border[0 0 0]/Dest[336 0 R/XYZ null 684 0]>>endobj
+45 0 obj<</Subtype/Link/Rect[72.0 72.1 100.1 85.1]/Border[0 0 0]/Dest[336 0 R/XYZ null 618 0]>>endobj
+46 0 obj<</Subtype/Link/Rect[72.0 58.9 95.2 71.9]/Border[0 0 0]/Dest[336 0 R/XYZ null 565 0]>>endobj
+47 0 obj[36 0 R
+37 0 R
+38 0 R
+39 0 R
+40 0 R
+41 0 R
+42 0 R
+43 0 R
+44 0 R
+45 0 R
+46 0 R
+]endobj
+48 0 obj<</Subtype/Link/Rect[108.0 718.8 147.1 731.8]/Border[0 0 0]/Dest[336 0 R/XYZ null 513 0]>>endobj
+49 0 obj<</Subtype/Link/Rect[108.0 705.6 142.2 718.6]/Border[0 0 0]/Dest[336 0 R/XYZ null 447 0]>>endobj
+50 0 obj<</Subtype/Link/Rect[108.0 692.4 141.6 705.4]/Border[0 0 0]/Dest[336 0 R/XYZ null 381 0]>>endobj
+51 0 obj<</Subtype/Link/Rect[108.0 679.2 126.9 692.2]/Border[0 0 0]/Dest[336 0 R/XYZ null 315 0]>>endobj
+52 0 obj<</Subtype/Link/Rect[108.0 666.0 131.8 679.0]/Border[0 0 0]/Dest[336 0 R/XYZ null 249 0]>>endobj
+53 0 obj<</Subtype/Link/Rect[108.0 652.8 137.3 665.8]/Border[0 0 0]/Dest[336 0 R/XYZ null 169 0]>>endobj
+54 0 obj[48 0 R
+49 0 R
+50 0 R
+51 0 R
+52 0 R
+53 0 R
+]endobj
+55 0 obj<</Subtype/Link/Rect[108.0 456.7 144.7 469.7]/Border[0 0 0]/Dest[339 0 R/XYZ null 237 0]>>endobj
+56 0 obj<</Subtype/Link/Rect[108.0 443.5 150.6 456.5]/Border[0 0 0]/Dest[339 0 R/XYZ null 185 0]>>endobj
+57 0 obj<</Subtype/Link/Rect[108.0 430.3 123.9 443.3]/Border[0 0 0]/Dest[342 0 R/XYZ null 763 0]>>endobj
+58 0 obj<</Subtype/Link/Rect[108.0 417.1 152.0 430.1]/Border[0 0 0]/Dest[342 0 R/XYZ null 711 0]>>endobj
+59 0 obj<</Subtype/Link/Rect[108.0 403.9 156.9 416.9]/Border[0 0 0]/Dest[342 0 R/XYZ null 658 0]>>endobj
+60 0 obj<</Subtype/Link/Rect[108.0 390.7 129.4 403.7]/Border[0 0 0]/Dest[342 0 R/XYZ null 565 0]>>endobj
+61 0 obj<</Subtype/Link/Rect[108.0 377.5 130.0 390.5]/Border[0 0 0]/Dest[342 0 R/XYZ null 513 0]>>endobj
+62 0 obj<</Subtype/Link/Rect[108.0 364.3 125.7 377.3]/Border[0 0 0]/Dest[342 0 R/XYZ null 460 0]>>endobj
+63 0 obj<</Subtype/Link/Rect[108.0 351.1 125.7 364.1]/Border[0 0 0]/Dest[342 0 R/XYZ null 407 0]>>endobj
+64 0 obj<</Subtype/Link/Rect[108.0 337.9 129.4 350.9]/Border[0 0 0]/Dest[342 0 R/XYZ null 354 0]>>endobj
+65 0 obj<</Subtype/Link/Rect[108.0 324.7 148.3 337.7]/Border[0 0 0]/Dest[342 0 R/XYZ null 301 0]>>endobj
+66 0 obj<</Subtype/Link/Rect[108.0 311.5 142.2 324.5]/Border[0 0 0]/Dest[342 0 R/XYZ null 196 0]>>endobj
+67 0 obj<</Subtype/Link/Rect[108.0 298.3 126.9 311.3]/Border[0 0 0]/Dest[342 0 R/XYZ null 249 0]>>endobj
+68 0 obj<</Subtype/Link/Rect[108.0 285.1 191.7 298.1]/Border[0 0 0]/Dest[342 0 R/XYZ null 143 0]>>endobj
+69 0 obj<</Subtype/Link/Rect[108.0 271.9 152.0 284.9]/Border[0 0 0]/Dest[345 0 R/XYZ null 739 0]>>endobj
+70 0 obj<</Subtype/Link/Rect[108.0 258.7 138.5 271.7]/Border[0 0 0]/Dest[345 0 R/XYZ null 686 0]>>endobj
+71 0 obj<</Subtype/Link/Rect[108.0 245.5 125.1 258.5]/Border[0 0 0]/Dest[345 0 R/XYZ null 634 0]>>endobj
+72 0 obj<</Subtype/Link/Rect[108.0 232.3 126.9 245.3]/Border[0 0 0]/Dest[345 0 R/XYZ null 581 0]>>endobj
+73 0 obj<</Subtype/Link/Rect[108.0 219.1 131.8 232.1]/Border[0 0 0]/Dest[345 0 R/XYZ null 436 0]>>endobj
+74 0 obj[55 0 R
+56 0 R
+57 0 R
+58 0 R
+59 0 R
+60 0 R
+61 0 R
+62 0 R
+63 0 R
+64 0 R
+65 0 R
+66 0 R
+67 0 R
+68 0 R
+69 0 R
+70 0 R
+71 0 R
+72 0 R
+73 0 R
+]endobj
+75 0 obj<</Subtype/Link/Rect[72.0 421.5 112.3 434.5]/Border[0 0 0]/Dest[348 0 R/XYZ null 427 0]>>endobj
+76 0 obj<</Subtype/Link/Rect[72.0 408.3 118.3 421.3]/Border[0 0 0]/Dest[348 0 R/XYZ null 374 0]>>endobj
+77 0 obj[75 0 R
+76 0 R
+]endobj
+78 0 obj<</Subtype/Link/Rect[108.0 381.9 155.0 394.9]/Border[0 0 0]/Dest[351 0 R/XYZ null 347 0]>>endobj
+79 0 obj<</Subtype/Link/Rect[108.0 368.7 161.0 381.7]/Border[0 0 0]/Dest[351 0 R/XYZ null 295 0]>>endobj
+80 0 obj<</Subtype/Link/Rect[108.0 355.5 126.9 368.5]/Border[0 0 0]/Dest[351 0 R/XYZ null 242 0]>>endobj
+81 0 obj<</Subtype/Link/Rect[108.0 342.3 127.5 355.3]/Border[0 0 0]/Dest[351 0 R/XYZ null 189 0]>>endobj
+82 0 obj<</Subtype/Link/Rect[108.0 329.1 131.8 342.1]/Border[0 0 0]/Dest[354 0 R/XYZ null 763 0]>>endobj
+83 0 obj[78 0 R
+79 0 R
+80 0 R
+81 0 R
+82 0 R
+]endobj
+84 0 obj<</Subtype/Link/Rect[108.0 140.7 148.3 153.7]/Border[0 0 0]/Dest[360 0 R/XYZ null 658 0]>>endobj
+85 0 obj<</S/URI/URI(#HelpApp.~HelpApp)>>endobj
+86 0 obj<</Subtype/Link/Rect[108.0 127.5 154.3 140.5]/Border[0 0 0]/A 85 0 R>>endobj
+87 0 obj<</Subtype/Link/Rect[108.0 114.3 113.5 127.3]/Border[0 0 0]/Dest[360 0 R/XYZ null 552 0]>>endobj
+88 0 obj<</Subtype/Link/Rect[108.0 101.1 126.9 114.1]/Border[0 0 0]/Dest[360 0 R/XYZ null 499 0]>>endobj
+89 0 obj<</Subtype/Link/Rect[108.0 87.9 126.9 100.9]/Border[0 0 0]/Dest[360 0 R/XYZ null 447 0]>>endobj
+90 0 obj<</Subtype/Link/Rect[108.0 74.7 143.5 87.7]/Border[0 0 0]/Dest[360 0 R/XYZ null 381 0]>>endobj
+91 0 obj<</Subtype/Link/Rect[108.0 61.5 133.7 74.5]/Border[0 0 0]/Dest[360 0 R/XYZ null 328 0]>>endobj
+92 0 obj[84 0 R
+86 0 R
+87 0 R
+88 0 R
+89 0 R
+90 0 R
+91 0 R
+]endobj
+93 0 obj<</Subtype/Link/Rect[72.0 718.8 95.2 731.8]/Border[0 0 0]/Dest[360 0 R/XYZ null 275 0]>>endobj
+94 0 obj<</Subtype/Link/Rect[72.0 705.6 105.6 718.6]/Border[0 0 0]/Dest[360 0 R/XYZ null 222 0]>>endobj
+95 0 obj<</Subtype/Link/Rect[72.0 692.4 102.6 705.4]/Border[0 0 0]/Dest[360 0 R/XYZ null 156 0]>>endobj
+96 0 obj<</Subtype/Link/Rect[72.0 679.2 101.3 692.2]/Border[0 0 0]/Dest[363 0 R/XYZ null 763 0]>>endobj
+97 0 obj<</Subtype/Link/Rect[72.0 666.0 79.9 679.0]/Border[0 0 0]/Dest[363 0 R/XYZ null 711 0]>>endobj
+98 0 obj<</Subtype/Link/Rect[72.0 652.8 77.5 665.8]/Border[0 0 0]/Dest[363 0 R/XYZ null 658 0]>>endobj
+99 0 obj<</Subtype/Link/Rect[72.0 639.6 77.5 652.6]/Border[0 0 0]/Dest[363 0 R/XYZ null 605 0]>>endobj
+100 0 obj[93 0 R
+94 0 R
+95 0 R
+96 0 R
+97 0 R
+98 0 R
+99 0 R
+]endobj
+101 0 obj<</Subtype/Link/Rect[72.0 115.7 123.3 128.7]/Border[0 0 0]/Dest[369 0 R/XYZ null 724 0]>>endobj
+102 0 obj<</S/URI/URI(#HelpDialog.~HelpDialog)>>endobj
+103 0 obj<</Subtype/Link/Rect[72.0 104.5 129.3 115.5]/Border[0 0 0]/A 102 0 R>>endobj
+104 0 obj<</Subtype/Link/Rect[72.0 89.3 90.9 102.3]/Border[0 0 0]/Dest[369 0 R/XYZ null 618 0]>>endobj
+105 0 obj<</Subtype/Link/Rect[72.0 76.1 90.9 89.1]/Border[0 0 0]/Dest[369 0 R/XYZ null 565 0]>>endobj
+106 0 obj<</Subtype/Link/Rect[72.0 62.9 95.2 75.9]/Border[0 0 0]/Dest[369 0 R/XYZ null 499 0]>>endobj
+107 0 obj[101 0 R
+103 0 R
+104 0 R
+105 0 R
+106 0 R
+]endobj
+108 0 obj<</Subtype/Link/Rect[108.0 718.8 138.6 731.8]/Border[0 0 0]/Dest[369 0 R/XYZ null 447 0]>>endobj
+109 0 obj<</Subtype/Link/Rect[108.0 705.6 137.3 718.6]/Border[0 0 0]/Dest[369 0 R/XYZ null 381 0]>>endobj
+110 0 obj[108 0 R
+109 0 R
+]endobj
+111 0 obj<</Subtype/Link/Rect[72.0 434.7 117.2 447.7]/Border[0 0 0]/Dest[372 0 R/XYZ null 295 0]>>endobj
+112 0 obj<</Subtype/Link/Rect[72.0 421.5 123.2 434.5]/Border[0 0 0]/Dest[372 0 R/XYZ null 242 0]>>endobj
+113 0 obj<</Subtype/Link/Rect[72.0 408.3 111.7 421.3]/Border[0 0 0]/Dest[372 0 R/XYZ null 189 0]>>endobj
+114 0 obj<</Subtype/Link/Rect[72.0 395.1 110.5 408.1]/Border[0 0 0]/Dest[375 0 R/XYZ null 763 0]>>endobj
+115 0 obj<</Subtype/Link/Rect[72.0 381.9 89.1 394.9]/Border[0 0 0]/Dest[375 0 R/XYZ null 711 0]>>endobj
+116 0 obj<</Subtype/Link/Rect[72.0 368.7 90.9 381.7]/Border[0 0 0]/Dest[375 0 R/XYZ null 618 0]>>endobj
+117 0 obj<</Subtype/Link/Rect[72.0 355.5 89.1 368.5]/Border[0 0 0]/Dest[375 0 R/XYZ null 565 0]>>endobj
+118 0 obj<</Subtype/Link/Rect[72.0 342.3 111.1 355.3]/Border[0 0 0]/Dest[375 0 R/XYZ null 513 0]>>endobj
+119 0 obj<</Subtype/Link/Rect[72.0 329.1 106.2 342.1]/Border[0 0 0]/Dest[375 0 R/XYZ null 447 0]>>endobj
+120 0 obj<</Subtype/Link/Rect[72.0 315.9 105.6 328.9]/Border[0 0 0]/Dest[375 0 R/XYZ null 381 0]>>endobj
+121 0 obj<</Subtype/Link/Rect[72.0 302.7 89.1 315.7]/Border[0 0 0]/Dest[375 0 R/XYZ null 315 0]>>endobj
+122 0 obj<</Subtype/Link/Rect[72.0 289.5 102.6 302.5]/Border[0 0 0]/Dest[375 0 R/XYZ null 262 0]>>endobj
+123 0 obj<</Subtype/Link/Rect[72.0 276.3 95.8 289.3]/Border[0 0 0]/Dest[375 0 R/XYZ null 156 0]>>endobj
+124 0 obj[111 0 R
+112 0 R
+113 0 R
+114 0 R
+115 0 R
+116 0 R
+117 0 R
+118 0 R
+119 0 R
+120 0 R
+121 0 R
+122 0 R
+123 0 R
+]endobj
+125 0 obj<</Subtype/Link/Rect[101.9 600.0 148.1 613.0]/Border[0 0 0]/Dest[354 0 R/XYZ null 645 0]>>endobj
+126 0 obj[125 0 R
+]endobj
+127 0 obj<</Subtype/Link/Rect[72.0 673.2 131.9 686.2]/Border[0 0 0]/Dest[297 0 R/XYZ null 812 0]>>endobj
+128 0 obj<</Subtype/Link/Rect[108.0 660.0 281.2 673.0]/Border[0 0 0]/Dest[297 0 R/XYZ null 672 0]>>endobj
+129 0 obj<</Subtype/Link/Rect[108.0 646.8 295.9 659.8]/Border[0 0 0]/Dest[297 0 R/XYZ null 427 0]>>endobj
+130 0 obj<</Subtype/Link/Rect[72.0 620.4 152.7 633.4]/Border[0 0 0]/Dest[303 0 R/XYZ null 812 0]>>endobj
+131 0 obj<</Subtype/Link/Rect[108.0 607.2 177.7 620.2]/Border[0 0 0]/Dest[303 0 R/XYZ null 698 0]>>endobj
+132 0 obj<</Subtype/Link/Rect[108.0 594.0 242.1 607.0]/Border[0 0 0]/Dest[303 0 R/XYZ null 436 0]>>endobj
+133 0 obj<</Subtype/Link/Rect[72.0 567.6 149.0 580.6]/Border[0 0 0]/Dest[309 0 R/XYZ null 812 0]>>endobj
+134 0 obj<</Subtype/Link/Rect[108.0 554.4 177.7 567.4]/Border[0 0 0]/Dest[309 0 R/XYZ null 685 0]>>endobj
+135 0 obj<</Subtype/Link/Rect[108.0 541.2 239.7 554.2]/Border[0 0 0]/Dest[309 0 R/XYZ null 607 0]>>endobj
+136 0 obj<</Subtype/Link/Rect[72.0 514.8 209.2 527.8]/Border[0 0 0]/Dest[315 0 R/XYZ null 812 0]>>endobj
+137 0 obj<</Subtype/Link/Rect[108.0 501.6 177.7 514.6]/Border[0 0 0]/Dest[315 0 R/XYZ null 711 0]>>endobj
+138 0 obj<</Subtype/Link/Rect[108.0 488.4 228.7 501.4]/Border[0 0 0]/Dest[315 0 R/XYZ null 594 0]>>endobj
+139 0 obj<</Subtype/Link/Rect[72.0 462.0 110.5 475.0]/Border[0 0 0]/Dest[321 0 R/XYZ null 812 0]>>endobj
+140 0 obj<</Subtype/Link/Rect[108.0 448.8 190.2 461.8]/Border[0 0 0]/Dest[324 0 R/XYZ null 793 0]>>endobj
+141 0 obj<</Subtype/Link/Rect[108.0 435.6 186.5 448.6]/Border[0 0 0]/Dest[327 0 R/XYZ null 793 0]>>endobj
+142 0 obj<</Subtype/Link/Rect[108.0 422.4 185.9 435.4]/Border[0 0 0]/Dest[330 0 R/XYZ null 793 0]>>endobj
+143 0 obj<</Subtype/Link/Rect[108.0 409.2 168.8 422.2]/Border[0 0 0]/Dest[339 0 R/XYZ null 793 0]>>endobj
+144 0 obj<</Subtype/Link/Rect[108.0 396.0 172.5 409.0]/Border[0 0 0]/Dest[348 0 R/XYZ null 793 0]>>endobj
+145 0 obj<</Subtype/Link/Rect[108.0 382.8 179.2 395.8]/Border[0 0 0]/Dest[351 0 R/XYZ null 793 0]>>endobj
+146 0 obj<</Subtype/Link/Rect[108.0 369.6 172.5 382.6]/Border[0 0 0]/Dest[357 0 R/XYZ null 793 0]>>endobj
+147 0 obj<</Subtype/Link/Rect[108.0 356.4 183.5 369.4]/Border[0 0 0]/Dest[366 0 R/XYZ null 793 0]>>endobj
+148 0 obj<</Subtype/Link/Rect[108.0 343.2 177.3 356.2]/Border[0 0 0]/Dest[372 0 R/XYZ null 793 0]>>endobj
+149 0 obj<</Subtype/Link/Rect[72.0 316.8 136.4 329.8]/Border[0 0 0]/Dest[381 0 R/XYZ null 812 0]>>endobj
+150 0 obj<</Subtype/Link/Rect[108.0 303.6 179.2 316.6]/Border[0 0 0]/Dest[381 0 R/XYZ null 732 0]>>endobj
+151 0 obj<</Subtype/Link/Rect[108.0 290.4 235.4 303.4]/Border[0 0 0]/Dest[381 0 R/XYZ null 403 0]>>endobj
+152 0 obj<</Subtype/Link/Rect[108.0 277.2 244.0 290.2]/Border[0 0 0]/Dest[381 0 R/XYZ null 339 0]>>endobj
+153 0 obj<</Subtype/Link/Rect[108.0 264.0 244.0 277.0]/Border[0 0 0]/Dest[381 0 R/XYZ null 222 0]>>endobj
+154 0 obj<</Subtype/Link/Rect[108.0 250.8 235.7 263.8]/Border[0 0 0]/Dest[384 0 R/XYZ null 793 0]>>endobj
+155 0 obj<</Subtype/Link/Rect[108.0 237.6 235.7 250.6]/Border[0 0 0]/Dest[384 0 R/XYZ null 675 0]>>endobj
+156 0 obj<</Subtype/Link/Rect[108.0 224.4 235.7 237.4]/Border[0 0 0]/Dest[384 0 R/XYZ null 558 0]>>endobj
+157 0 obj<</Subtype/Link/Rect[108.0 211.2 235.7 224.2]/Border[0 0 0]/Dest[384 0 R/XYZ null 216 0]>>endobj
+158 0 obj[127 0 R
+128 0 R
+129 0 R
+130 0 R
+131 0 R
+132 0 R
+133 0 R
+134 0 R
+135 0 R
+136 0 R
+137 0 R
+138 0 R
+139 0 R
+140 0 R
+141 0 R
+142 0 R
+143 0 R
+144 0 R
+145 0 R
+146 0 R
+147 0 R
+148 0 R
+149 0 R
+150 0 R
+151 0 R
+152 0 R
+153 0 R
+154 0 R
+155 0 R
+156 0 R
+157 0 R
+]endobj
+159 0 obj<</Dests 160 0 R>>endobj
+160 0 obj<</Kids[161 0 R]>>endobj
+161 0 obj<</Limits[(1)(widgets.html)]/Names[(1)162 0 R(1_1)163 0 R(1_2)164 0 R(2)165 0 R(2_1)166 0 R(2_2)167 0 R(3)168 0 R(3_1)169 0 R(3_2)170 0 R(4)171 0 R(4_1)172 0 R(4_2)173 0 R(5)174 0 R(5_1)175 0 R(5_2)176 0 R(5_3)177 0 R(5_4)178 0 R(5_5)179 0 R(5_6)180 0 R(5_7)181 0 R(5_8)182 0 R(5_9)183 0 R(6)184 0 R(6_1)185 0 R(6_2)186 0 R(6_3)187 0 R(6_4)188 0 R(6_5)189 0 R(6_6)190 0 R(6_7)191 0 R(6_8)192 0 R(checkbutton.checkbutton)193 0 R(checkbutton.html)194 0 R(checkbutton.~checkbutton)195 0 R(file.html)196 0 R(filebrowser.filebrowser)197 0 R(filebrowser.filter)198 0 R(filebrowser.html)199 0 R(filebrowser.iconsize)200 0 R(filebrowser.load)201 0 R(filebrowser.~filebrowser)202 0 R(filechooser.color)203 0 R(filechooser.count)204 0 R(filechooser.directory)205 0 R(filechooser.filechooser)206 0 R(filechooser.filter)207 0 R(filechooser.hide)208 0 R(filechooser.html)209 0 R(filechooser.iconsize)210 0 R(filechooser.label)211 0 R(filechooser.rescan)212 0 R(filechooser.show)213 0 R(filechooser.textcolor)214 0 R(filechooser.textfont)215 0 R(filechooser.textsize)216 0 R(filechooser.type)217 0 R(filechooser.value)218 0 R(filechooser.visible)219 0 R(filechooser.~filechooser)220 0 R(fileicon.add)221 0 R(fileicon.add_color)222 0 R(fileicon.add_vertex)223 0 R(fileicon.clear)224 0 R(fileicon.draw)225 0 R(fileicon.fileicon)226 0 R(fileicon.find)227 0 R(fileicon.first)228 0 R(fileicon.html)229 0 R(fileicon.label)230 0 R(fileicon.labeltype)231 0 R(fileicon.load)232 0 R(fileicon.load_fti)233 0 R(fileicon.load_system_icons)234 0 R(fileicon.load_xpm)235 0 R(fileicon.pattern)236 0 R(fileicon.size)237 0 R(fileicon.type)238 0 R(fileicon.value)239 0 R(fileicon.~fileicon)240 0 R(fileinput.fileinput)241 0 R(fileinput.html)242 0 R(fileinput.~fileinput)243 0 R(fl_wizard.fl_wizard)244 0 R(fl_wizard.html)245 0 R(fl_wizard.next)246 0 R(fl_wizard.prev)247 0 R(fl_wizard.value)248 0 R(fl_wizard.~fl_wizard)249 0 R(flsurf.html)250 0 R(help.html)251 0 R(helpapp.h)252 0 R(helpapp.helpapp)253 0 R(helpapp.hide)254 0 R(helpapp.html)255 0 R(helpapp.load)256 0 R(helpapp.position)257 0 R(helpapp.resize)258 0 R(helpapp.show)259 0 R(helpapp.textsize)260 0 R(helpapp.topline)261 0 R(helpapp.visible)262 0 R(helpapp.w)263 0 R(helpapp.x)264 0 R(helpapp.y)265 0 R(helpdialog.helpdialog)266 0 R(helpdialog.hide)267 0 R(helpdialog.html)268 0 R(helpdialog.load)269 0 R(helpdialog.show)270 0 R(helpdialog.topline)271 0 R(helpdialog.visible)272 0 R(helpview.directory)273 0 R(helpview.filename)274 0 R(helpview.helpview)275 0 R(helpview.html)276 0 R(helpview.link)277 0 R(helpview.load)278 0 R(helpview.size)279 0 R(helpview.textcolor)280 0 R(helpview.textfont)281 0 R(helpview.textsize)282 0 R(helpview.title)283 0 R(helpview.topline)284 0 R(helpview.value)285 0 R(helpview.~helpview)286 0 R(intro.html)287 0 R(relnotes.html)288 0 R(widgets.html)289 0 R]>>endobj
+162 0 obj<</D[297 0 R/XYZ null 812 null]>>endobj
+163 0 obj<</D[297 0 R/XYZ null 672 null]>>endobj
+164 0 obj<</D[297 0 R/XYZ null 427 null]>>endobj
+165 0 obj<</D[303 0 R/XYZ null 812 null]>>endobj
+166 0 obj<</D[303 0 R/XYZ null 698 null]>>endobj
+167 0 obj<</D[303 0 R/XYZ null 436 null]>>endobj
+168 0 obj<</D[309 0 R/XYZ null 812 null]>>endobj
+169 0 obj<</D[309 0 R/XYZ null 685 null]>>endobj
+170 0 obj<</D[309 0 R/XYZ null 607 null]>>endobj
+171 0 obj<</D[315 0 R/XYZ null 812 null]>>endobj
+172 0 obj<</D[315 0 R/XYZ null 711 null]>>endobj
+173 0 obj<</D[315 0 R/XYZ null 594 null]>>endobj
+174 0 obj<</D[321 0 R/XYZ null 812 null]>>endobj
+175 0 obj<</D[324 0 R/XYZ null 793 null]>>endobj
+176 0 obj<</D[327 0 R/XYZ null 793 null]>>endobj
+177 0 obj<</D[330 0 R/XYZ null 793 null]>>endobj
+178 0 obj<</D[339 0 R/XYZ null 793 null]>>endobj
+179 0 obj<</D[348 0 R/XYZ null 793 null]>>endobj
+180 0 obj<</D[351 0 R/XYZ null 793 null]>>endobj
+181 0 obj<</D[357 0 R/XYZ null 793 null]>>endobj
+182 0 obj<</D[366 0 R/XYZ null 793 null]>>endobj
+183 0 obj<</D[372 0 R/XYZ null 793 null]>>endobj
+184 0 obj<</D[381 0 R/XYZ null 812 null]>>endobj
+185 0 obj<</D[381 0 R/XYZ null 732 null]>>endobj
+186 0 obj<</D[381 0 R/XYZ null 403 null]>>endobj
+187 0 obj<</D[381 0 R/XYZ null 339 null]>>endobj
+188 0 obj<</D[381 0 R/XYZ null 222 null]>>endobj
+189 0 obj<</D[384 0 R/XYZ null 793 null]>>endobj
+190 0 obj<</D[384 0 R/XYZ null 675 null]>>endobj
+191 0 obj<</D[384 0 R/XYZ null 558 null]>>endobj
+192 0 obj<</D[384 0 R/XYZ null 216 null]>>endobj
+193 0 obj<</D[324 0 R/XYZ null 440 null]>>endobj
+194 0 obj<</D[321 0 R/XYZ null 384 null]>>endobj
+195 0 obj<</D[324 0 R/XYZ null 387 null]>>endobj
+196 0 obj<</D[297 0 R/XYZ null 247 null]>>endobj
+197 0 obj<</D[327 0 R/XYZ null 413 null]>>endobj
+198 0 obj<</D[327 0 R/XYZ null 242 null]>>endobj
+199 0 obj<</D[324 0 R/XYZ null 281 null]>>endobj
+200 0 obj<</D[327 0 R/XYZ null 308 null]>>endobj
+201 0 obj<</D[327 0 R/XYZ null 176 null]>>endobj
+202 0 obj<</D[327 0 R/XYZ null 361 null]>>endobj
+203 0 obj<</D[333 0 R/XYZ null 394 null]>>endobj
+204 0 obj<</D[333 0 R/XYZ null 328 null]>>endobj
+205 0 obj<</D[333 0 R/XYZ null 275 null]>>endobj
+206 0 obj<</D[333 0 R/XYZ null 671 null]>>endobj
+207 0 obj<</D[333 0 R/XYZ null 209 null]>>endobj
+208 0 obj<</D[333 0 R/XYZ null 143 null]>>endobj
+209 0 obj<</D[327 0 R/XYZ null 57 null]>>endobj
+210 0 obj<</D[336 0 R/XYZ null 763 null]>>endobj
+211 0 obj<</D[336 0 R/XYZ null 684 null]>>endobj
+212 0 obj<</D[336 0 R/XYZ null 618 null]>>endobj
+213 0 obj<</D[336 0 R/XYZ null 565 null]>>endobj
+214 0 obj<</D[336 0 R/XYZ null 513 null]>>endobj
+215 0 obj<</D[336 0 R/XYZ null 447 null]>>endobj
+216 0 obj<</D[336 0 R/XYZ null 381 null]>>endobj
+217 0 obj<</D[336 0 R/XYZ null 315 null]>>endobj
+218 0 obj<</D[336 0 R/XYZ null 249 null]>>endobj
+219 0 obj<</D[336 0 R/XYZ null 169 null]>>endobj
+220 0 obj<</D[333 0 R/XYZ null 447 null]>>endobj
+221 0 obj<</D[342 0 R/XYZ null 763 null]>>endobj
+222 0 obj<</D[342 0 R/XYZ null 711 null]>>endobj
+223 0 obj<</D[342 0 R/XYZ null 658 null]>>endobj
+224 0 obj<</D[342 0 R/XYZ null 565 null]>>endobj
+225 0 obj<</D[342 0 R/XYZ null 513 null]>>endobj
+226 0 obj<</D[339 0 R/XYZ null 237 null]>>endobj
+227 0 obj<</D[342 0 R/XYZ null 460 null]>>endobj
+228 0 obj<</D[342 0 R/XYZ null 407 null]>>endobj
+229 0 obj<</D[336 0 R/XYZ null 49 null]>>endobj
+230 0 obj<</D[342 0 R/XYZ null 354 null]>>endobj
+231 0 obj<</D[342 0 R/XYZ null 301 null]>>endobj
+232 0 obj<</D[342 0 R/XYZ null 249 null]>>endobj
+233 0 obj<</D[342 0 R/XYZ null 196 null]>>endobj
+234 0 obj<</D[342 0 R/XYZ null 143 null]>>endobj
+235 0 obj<</D[345 0 R/XYZ null 739 null]>>endobj
+236 0 obj<</D[345 0 R/XYZ null 686 null]>>endobj
+237 0 obj<</D[345 0 R/XYZ null 634 null]>>endobj
+238 0 obj<</D[345 0 R/XYZ null 581 null]>>endobj
+239 0 obj<</D[345 0 R/XYZ null 436 null]>>endobj
+240 0 obj<</D[339 0 R/XYZ null 185 null]>>endobj
+241 0 obj<</D[348 0 R/XYZ null 427 null]>>endobj
+242 0 obj<</D[345 0 R/XYZ null 330 null]>>endobj
+243 0 obj<</D[348 0 R/XYZ null 374 null]>>endobj
+244 0 obj<</D[351 0 R/XYZ null 347 null]>>endobj
+245 0 obj<</D[348 0 R/XYZ null 268 null]>>endobj
+246 0 obj<</D[351 0 R/XYZ null 242 null]>>endobj
+247 0 obj<</D[351 0 R/XYZ null 189 null]>>endobj
+248 0 obj<</D[354 0 R/XYZ null 763 null]>>endobj
+249 0 obj<</D[351 0 R/XYZ null 295 null]>>endobj
+250 0 obj<</D[309 0 R/XYZ null 308 null]>>endobj
+251 0 obj<</D[303 0 R/XYZ null 82 null]>>endobj
+252 0 obj<</D[360 0 R/XYZ null 552 null]>>endobj
+253 0 obj<</D[360 0 R/XYZ null 658 null]>>endobj
+254 0 obj<</D[360 0 R/XYZ null 499 null]>>endobj
+255 0 obj<</D[354 0 R/XYZ null 645 null]>>endobj
+256 0 obj<</D[360 0 R/XYZ null 447 null]>>endobj
+257 0 obj<</D[360 0 R/XYZ null 381 null]>>endobj
+258 0 obj<</D[360 0 R/XYZ null 328 null]>>endobj
+259 0 obj<</D[360 0 R/XYZ null 275 null]>>endobj
+260 0 obj<</D[360 0 R/XYZ null 222 null]>>endobj
+261 0 obj<</D[360 0 R/XYZ null 156 null]>>endobj
+262 0 obj<</D[363 0 R/XYZ null 763 null]>>endobj
+263 0 obj<</D[363 0 R/XYZ null 711 null]>>endobj
+264 0 obj<</D[363 0 R/XYZ null 658 null]>>endobj
+265 0 obj<</D[363 0 R/XYZ null 605 null]>>endobj
+266 0 obj<</D[369 0 R/XYZ null 724 null]>>endobj
+267 0 obj<</D[369 0 R/XYZ null 618 null]>>endobj
+268 0 obj<</D[363 0 R/XYZ null 499 null]>>endobj
+269 0 obj<</D[369 0 R/XYZ null 565 null]>>endobj
+270 0 obj<</D[369 0 R/XYZ null 499 null]>>endobj
+271 0 obj<</D[369 0 R/XYZ null 447 null]>>endobj
+272 0 obj<</D[369 0 R/XYZ null 381 null]>>endobj
+273 0 obj<</D[372 0 R/XYZ null 189 null]>>endobj
+274 0 obj<</D[375 0 R/XYZ null 763 null]>>endobj
+275 0 obj<</D[372 0 R/XYZ null 295 null]>>endobj
+276 0 obj<</D[369 0 R/XYZ null 275 null]>>endobj
+277 0 obj<</D[375 0 R/XYZ null 711 null]>>endobj
+278 0 obj<</D[375 0 R/XYZ null 618 null]>>endobj
+279 0 obj<</D[375 0 R/XYZ null 565 null]>>endobj
+280 0 obj<</D[375 0 R/XYZ null 513 null]>>endobj
+281 0 obj<</D[375 0 R/XYZ null 447 null]>>endobj
+282 0 obj<</D[375 0 R/XYZ null 381 null]>>endobj
+283 0 obj<</D[375 0 R/XYZ null 315 null]>>endobj
+284 0 obj<</D[375 0 R/XYZ null 262 null]>>endobj
+285 0 obj<</D[375 0 R/XYZ null 156 null]>>endobj
+286 0 obj<</D[372 0 R/XYZ null 242 null]>>endobj
+287 0 obj<</D[297 0 R/XYZ null 698 null]>>endobj
+288 0 obj<</D[375 0 R/XYZ null 24 null]>>endobj
+289 0 obj<</D[315 0 R/XYZ null 152 null]>>endobj
+290 0 obj<</Type/Pages/MediaBox[0 0 595 792]/Count 36/Kids[291 0 R
+294 0 R
+393 0 R
+396 0 R
+297 0 R
+300 0 R
+303 0 R
+306 0 R
+309 0 R
+312 0 R
+315 0 R
+318 0 R
+321 0 R
+324 0 R
+327 0 R
+330 0 R
+333 0 R
+336 0 R
+339 0 R
+342 0 R
+345 0 R
+348 0 R
+351 0 R
+354 0 R
+357 0 R
+360 0 R
+363 0 R
+366 0 R
+369 0 R
+372 0 R
+375 0 R
+378 0 R
+381 0 R
+384 0 R
+387 0 R
+390 0 R
+]>>endobj
+291 0 obj<</Type/Page/Parent 290 0 R/Contents 292 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+292 0 obj<</Length 293 0 R/Filter/FlateDecode>>stream
+xÚ5ŽË
+Â0D÷ùŠYê"1>·J»ÑE%®K_Vh‘þ½IQ†»ºç ó"ÜG •P Ú9r(sˆf€PœÅPi Óí
+]¡žº±wÐþ;£¼˜óÞܽAˆ`d1S B1ùSjM%ã¢2b¨LX´ýše…¶ƒû4sj¶Ý»uK
+endobj
+293 0 obj
+158
+endobj
+294 0 obj<</Type/Page/Parent 290 0 R/Contents 295 0 R/Resources<</ProcSet[/PDF/Text]>>>>endobj
+295 0 obj<</Length 296 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+ár á
+ä
+endobj
+296 0 obj
+31
+endobj
+297 0 obj<</Type/Page/Parent 290 0 R/Contents 298 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F3 5 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>/Annots 13 0 R>>endobj
+298 0 obj<</Length 299 0 R/Filter/FlateDecode>>stream
+xÚU]oÚ@|çW¬"U¢
+86_!íSC“(*JÓ„4¼ö—ØwîÝšþúîúLb ©”
+²o¼;;3çûÕˆ ¤OÇè Χ“ÆÑù D'0™ÓÊà¸t`’4/•3:)b'µú8y P¢ÈƒÚAÐcÐd‰pv{ ÷2Y ƒ[úεóñääF¯d‚â%Æ0+œÓªs™"ÝÒÚ¢iÁÓV×|!TkùGþã‚–«qó³I# BbÎ?ÿÜ\@§?º0èö‚dÐv‚“ê*…[ž‹¦éöé’ˆ2£
+ŠŽV 5¥Ï dš–dá*\E!%ÊiHô'ß8„žkÎ{®Ýéù?€_Œ6‹Íà西_ë>¯]MÎn¶Çh—ÕªA.}`÷<‘–d3‚ !§[*òt)ŒJØ™¸”eMÚ*ÝÞì
+;Øñ×× o°…‘Z 3ôºÑ4˜¦ÕHe+¡jòPf) ë%šÒž9%ž2§E‚~[”ÔR93Ô í®ßm%NÝR¬¨sÇhí¼HÓ§—$[Inù€º§ßM.ðîLÒH³B¦žBí-ÂC‰Jü-²<ÅÿßÞÕkâŸgTíTëÀZy…ãÀr‹r„Ü#íbPÚA²’Œß uÊÝWä,|`ì˜ûRi/Àï¥:GUÞ: ±¶;oQb'`&\¼ôE+‡5!zǯé½aHgXÈKQuÐýhü‘U\ƒendstream
+endobj
+299 0 obj
+848
+endobj
+300 0 obj<</Type/Page/Parent 290 0 R/Contents 301 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+301 0 obj<</Length 302 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨J#˜‰‘¥ž©˜ï™WR”ŸRš\’™Ÿ’r á
+ä
+endobj
+302 0 obj
+110
+endobj
+303 0 obj<</Type/Page/Parent 290 0 R/Contents 304 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>>>endobj
+304 0 obj<</Length 305 0 R/Filter/FlateDecode>>stream
+xÚ­VMoã6½çW ÔÃ:E¬ÄΧ½èe·»…/[´uÑ ´4²¸¥H•¤ì5Šþ÷β-+6E.¡8oý÷Ånèoc¸}€¬ºø0¿¸þ<Ñæí<<Þ§c˜çƒy‰ðY*„¥1íåü+ÞÁh‡ã‡ôn7oÚÍçLÀFæ+ôP[³–9:à¼Ð¹°9ÜÍ¡ÂÌK£!—B™ÆÂÖ4D]+™ Þs)Ì<¸¦®õ|i¹¡ÝFø¹,
+´¨}§be¸ãœÔ+juÜï
+ªFyYŸØ | qÓ¸0¶Æ!HÝëž8±F.¡^¾‰˜—i$ƒÈ¾OŸZoŸ8~VQߊІÐÿ—jé`)æÐÔº`*3%œC7Y›1~"ðû^‹ñÃã©f¬Ùœh6¤)P'&Ú,C0Å‹
+êùL_
+J:š'óL¥4—ª1“…$ô¹´Ä»±[ Ò…RœÿH4&nåÝuezm¤¦J&ÔØ:Uz|ØáQî¹ÃžaöpXO)åª*\£ŠÄÆ£ìÎ!­–7Rçfô”í­Q®ëæuL³¬¯= Ø~ßYR$ÈJ¬è–ª?-Ÿ3iåÃ`©ªÉ¤ðè^°Î³òÛšˆÇoµc¥Sª/©›á«qÀë7kl¸–]FhtŽ6€ƒß~šA’^&­
+^FטnŸÈÃH†ôä¼ff§äio9¢Ç  σ¸¢´ébI}#Tté ɾJÛrÒ;¥àkã|plB}Ü»søŠéT‘?Gûx½ƒÅe\…¤ôœ!qx‹©õ­Œ?‡×+VyßòØ.cpŸ{¡ßyXb(G’¦p +Ôh©\8K¿0Š.FÛMÐ\‚üwdÃlÿÝh:¾+ÍFso&¯ä·)ﵦVÕùGê÷½œ:Ö›8ÿd™ßox¹täŽ meEu¹™îŠLqAPwýwRgª!WI:¥Ó2i9Aiš­ÿÙQ0âÀ+Ã××ðsÍʪ_ Žˆ)²Å ©…/ù~%W|ŸÒÊ£Õ´`}Ò'/½Â„ÊöêYÊ# {
+Õà.-,8«äâŠn"ëvêœ-CöÒ-sp•D'GIÿƹ?íç>¹?Iÿ—êÝÓM:!Òö-¯?Í/~¹ø½Xendstream
+endobj
+305 0 obj
+1069
+endobj
+306 0 obj<</Type/Page/Parent 290 0 R/Contents 307 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+307 0 obj<</Length 308 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨J˜‰‘ž™˜’‘ªà–™“ªàœ‘Ÿ_œZ’v á
+ä
+endobj
+308 0 obj
+114
+endobj
+309 0 obj<</Type/Page/Parent 290 0 R/Contents 310 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+310 0 obj<</Length 311 0 R/Filter/FlateDecode>>stream
+xÚ­TMÓ0½÷WŒÊ¥+µ¦é׶åìj‘à€àÒ‹“L“a;ÄN³ñßçcÛ= ¡œìy3oÞ›q¾ ˜òÀí æ+ˆóÁëpðò~ÁÂ=GV·K1ƒ0…ªޒT&½ ¿2nAÐâ&³•Xô¸68í‚#Ÿö·¬Ô”¤è ![(y´ð~x{RhAê¤R¦¶à¸de±g V?‚Ñ H?Z“Ðò@©td´ð ÜM0o»~S•%j§ŽëÚú31T˜ó=Ó”¶*
+S:L
+endobj
+311 0 obj
+563
+endobj
+312 0 obj<</Type/Page/Parent 290 0 R/Contents 313 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+313 0 obj<</Length 314 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨J3˜‰…Èt ?$#UÁ#5§@Á%31'?$ëÂÈ
+endobj
+314 0 obj
+113
+endobj
+315 0 obj<</Type/Page/Parent 290 0 R/Contents 316 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>/Annots 16 0 R>>endobj
+316 0 obj<</Length 317 0 R/Filter/FlateDecode>>stream
+xÚ­UßoÚ0~ç¯8u/PAH€ò£]‘6TF¥nëÖt{(Ue‡xuìÌv hÚÿ¾sÔÂҮɒu÷}w÷ùîò³æ‹èö!HjïýZ{:o~„–þàÈé€Öý˜ÂŒòÞ¥)g1L
+˜×#®3Í ÿâzày®Õé;½-®0º¥±nieR‡5 —Ô@ªäŠ…TÍ’”SXÓ,”\kª€<FoB ­Ý 31,¤¼Oˆº×MËñ°¥©T¦iaF^·¨„ˆ´„M±ù5í§÷$20ð,¤aØ EÈ´Ql‘åæ&Rà,#–k02M§`E}œa©Twh³:·¥$T˜<Âÿ““é\&©1[¦+ªG«QQ°bR%y‰Ð…&3ÿã¬EÇ%Xóºõž–1â92/6¹
+™}CŠêÔš°Ž>odM9 Êð2ëý'±ÄŠT5q.ò™_s›Ûž=¾~
+žo@
+<lß‹åVû~$ˆiØ´MKÄfïY±eÑ•ŠêŒLR ‡¢\’ðù~»¶Aò
+Êþï¹x/vž–™
+¨×Í &¯±ÿ,0›õñceG;.œV§W”ñ¦)8(Óqâƒm¥ÞŽÃÛéEûÁ™Kk'‡3aà¥_» Ÿ¡gÌ€ÆËôyB˜˜$D-ƒfþñŸ²dKçg*ÁFhq&¨ÅdvtwIs`‡è°º¹7*I'ÿ¦úµG¼}²âwˆ«éd—7ßÔO6V‰ïv |ÄïdJÅn­”“ͼ>oœìè  § èzlßE¸þ­Z0>…NñØ©ZcÛ„¹ÛêÆ»­ŒÒÛ©JaÊU&ªL!Í÷>ù;-EM¦ì—É}D9ý.ÚoXvg˶Ÿ×ÏçâUŸ·ÞÐuF8è=(7Ì—Úˆo…endstream
+endobj
+317 0 obj
+774
+endobj
+318 0 obj<</Type/Page/Parent 290 0 R/Contents 319 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+319 0 obj<</Length 320 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨J ˜±©¡ž±˜’‘ªà‘šS àXP“™œX’™Ÿ§£‘–S\Z”£ RíÂÈ
+endobj
+320 0 obj
+129
+endobj
+321 0 obj<</Type/Page/Parent 290 0 R/Contents 322 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 26 0 R>>endobj
+322 0 obj<</Length 323 0 R/Filter/FlateDecode>>stream
+xÚ­Vmo›0þž_qê§TJ(Â˾­ÝºN뤽 õK¥É'x1˜a(Û~ýÎIÓ*U”‹}w~î¹{Ìω&~,ðlX¸¥“Ëprq€@¸Æ×[6„ñôŽÅZÊóð®;`YÍúÜv G­‡ …Zï‰_–E¼Š©Dã„ÊH
+$‹!i.$+»íÒ
+HIF6Š+ÕœqAjõûQùz¤€xœÖ‰Ê·q¯ÂÅ¿ß±?¤ˆÇ
+1>Ùäƒ">Á•…§oø…¯.÷ÆjÙêOë¸z§nÌîà­|J]çuARZ‹b«1 ÚqïÌR©#‘;f·ÃtÍeU¬?Fë4Qù\p Çe¢“ô/¿mOû}™¾ÓLÚà-ÚñM#ÀEü7hëöyòOPÿ©endstream
+endobj
+323 0 obj
+857
+endobj
+324 0 obj<</Type/Page/Parent 290 0 R/Contents 325 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 29 0 R>>endobj
+325 0 obj<</Length 326 0 R/Filter/FlateDecode>>stream
+xÚ”]o›0†ïùGÝMºj>àb7íš®Ú&m Òn"UÔ8Á+Á™í,Í4õ·ïI™”E ƒ}Þã‡ã×üp| xøNÌŸ®œ«Ì¹œ¦à½²ŽMâ²bD«\)¸.}¼Úh-êóì»s“9Ä3!Ä‹ Jb¼ð” }¢Ð ÚDaàù&Õu“ê=g2—´Ü™D—S© D 7ˆÌ}1šV÷·RlÖ&„€ë7r
+„.™ÜrÅ
+ Îý1oX²¯Á'¦KQ´¥¥­0H0®/Á<˜Ä°·šÒ\|sùz‹«€®
+ÓÓ­ ÐFö¡‚™ñÙ@ —°çõˆ±ƒ¢îe¤—utnŒþï+p
+]2ñÆHçÒ?†â¾›YžOàK;¾Æ˜mñtó¯5<=]€iw;Ûn·¶-Ë  ¢V=’Kx]Á[ óó£Ælâå†j4•,×h9ý?†Íu£SkFù‚³ÖBq³/ ¯ PüÛ{hòüâÿAŒ›¢nnÅÎw8ÛB2³sª
+Vl%äǯÌî%V›AñM‹–(i'ò½…‰ýÝÌ>Ã7›t†ç'œ~Ì>kCÝ8 &Ò'¦3LÇ^
+äØçô‹ó²ö€tendstream
+endobj
+326 0 obj
+595
+endobj
+327 0 obj<</Type/Page/Parent 290 0 R/Contents 328 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 35 0 R>>endobj
+328 0 obj<</Length 329 0 R/Filter/FlateDecode>>stream
+xÚµVÝoÓ0ï_q‚— –,_MÚ^+L X%^*M™ã,FiRbw]Úßδ]F»‚X«Æv|¿»ûùÜ\üzûDÀæƒÓéàd2oèŒ`šá^ašZ¬H¤„‰(øi]­$¯¦ßgÓëˆë„Žbœûø«9dkCã·†ßñÈÔ[mêƒàuR³¼!C'ÆFaØ~HóÔšW[Þ\°=m
+¾Ø²ìä/öÇ%«ÅB‰ª4r!jJ‰íG˜8”™æ:¿fó1öNÍ‚•Ho¸‚TÈE‘4(„TPe¡R™Ì¹<†J{LŠ¢Ay•ë-[.8™` XUJ§ÛÝ þÄU^¥m2XëÚ¡ÜôÌbØÐ
+¸$nôêØDˆÙ ’æ]/ 5w­Ö¡³cä¬mb9]0c°ˆ.r‚vq :×5YºVx£È"¼Ø_/ƒàI’]eñ“ÿhq€)›Ã0ƺšÅÐâeÑ ÒQ=GÎ"›  ‘>fq °È3Ý©¨’t¬qK7…ölQ`f‰RÁÝÝ1ÐØ4f\­Ì˜çÇ@QÀò¤†W¼wv´·)hùzÉTU«y¢¸õ/Í"QZ¯m
+»gÖR'Tdî†0æýFnvdº3€K®$ òu¾P+ÍMÏd–, e¶…ß……¸ã…|²aýÌÚ¦Á"Qø®|~[¦Óûû
+endobj
+329 0 obj
+835
+endobj
+330 0 obj<</Type/Page/Parent 290 0 R/Contents 331 0 R/Resources<</ProcSet[/PDF/Text/ImageB/ImageC/ImageI]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 47 0 R>>endobj
+331 0 obj<</Length 332 0 R/Filter/FlateDecode>>stream
+xÚì]koK’MO¶)NÑ}û´f¿ÜÕêc0Òh%ÓÀ ßV»HûaµZ!ð1Ɔ]4?~»ºªòù¨—ÛU™îW=ݧ"NDddÔßî?^nÿ¯ž<+þzÿå»ûÞ¼X=~zr¾z÷ëvÛ³ç/Vï>þüáËûëëÕ›Ï_.7Ÿ¾~½¾¼úçw¹ÿúÝýÓ“b—Ó“õj}þ|ûùlû¼º\ýÊOôää¬:Ñ“³“ÇÅ©6»SýéóåÕû«Ÿþ^œèÑ›ÓÕ‹rÇí×øål]|þøó›/ÿóÇ«¯?¾»œ®~y¼;|µZýC_ñ/¿l[y¢Çõ‰~Ö¾¬üm~)þË“Ç'Ï‹ãßþöáË—»wíø6ÿô¹Úñ÷Ò™O>ýÞyòW—×®>ûþùëoå~ëUñ­‹ùåìÙ¶Û¶û¼ût¹ªÿo¹Ñüîõa?¯þïóÇ?_~_}ü|ýíËû¿_¯Þ¯®¿¿ÿíãû««_·G­®/¿\~(þßv—÷_¾þyõýÓûï«ëß¾}½ú~½úß÷WŸ¿þ¸–vûë×—×'ž[¯Ožì.‹³'§'ÏVOo—ÏÎηèÈÛG›ÿø¯Goýû_®¿øÃéúôlûܾ¾Ù¾ž]œmN7ë‹õöõ鳧ë'›ó×盧ëâóÓÍÅë‹Í³õ˳—ëç›g/7Ï7›³Íú|s~q¾y±~ñìÅúbsqq±Ù¬‹õ›Íë‹×›WëWÏ^­_¯_Ÿ½^¿Y¿yvº{}³þ×ÿ~ôvõýêÇå£ÿ\=yñüÑŸVOÎνü·Íê|õöÕ}–Úµ‡©íKÛ‚qx”þöâïw[0Žî+å©ÝD»{§
+ö­9¿*jõ%Ýé+=pÙÏPûÍÕ{ÌoÙ}S•î-;,Ë¥ô¼§±BÙÛåµYñ+d¨øu®m…,Å.¹ÂP—˜"P»z{ZV¼ç¯þK¥Ë¥j]±C‰5+Š4gB†÷W2–êâ=C2˜Ê
+¬ÞŠz«~%KÇ¢@à 
+Fe`9Àख़¬’5¶·¤a¨©Š3JBQº»Vß|«$7yÝkÐ \ÜénJ†AÏLéÌzêe¥·åkŸƒÛÅppWD°¨)ÅmfÂǶ¨)Y2@røväŒK#ÓŒh¹g™‚DfHÆ-
+V?ƒåv‡JÞ|ÿ:F`ãüýl÷´f~0 ¬ÝšÚ™¶v?ãŽÍÏPÔ—:–×bR­ïü³`˜ÜfÚJ&î>£OIö3d¯J(ÛV™Q\Ž\í^È$6Ù¦Ð?ÛWÈë™ê㶹ÝÐ~ îÖ©ŠC“épfƦ¸Jû¶ºÞç-^}¥ò¹ôû ÏZ=Á8涄C¸¯ÀÌ·o«d㈤üÐB‡¥»•U°"¢2XmgÝs±Ð¤³ñ 9„NI†?„«v‚WoUãöc÷™1`thm=#qˆ­TÜGQý =„îéyª¾5¿òÛ$å‚Ü¡&tJw›å˜®ù?Ì@aégTxég€ ²ˆî”8CaµÛ„ Îh§¦ $üŒÒ°e®„¸yۦΖÙ(ZEÂäV8~j¥Äœg¶GmaÚ5|¼2–yîÓj+x pFI¡§¤fÇØÐr»¿’¿–R›L
+‹q…Ø_3ns*`Ïš3ôºM¿(ŸãÆ7ìds»”ýýC´” 2O\ .…d¡#øª ]DŒTI¡™ª8CmwÅYj=·¥0E 0¤p{j½69Q‹£·§Öa[hM:L•ŒF×m©O¯´KhÈœ‘Àè =Ña©Ç¦EF‚ÁÚÙXB§5²µK†Œ…ƒ3Š]R¶ºdˆT™ª¦œÁ¶P”cüƒ
+ Æ÷ëR#Ô«°Eટ Œ-¬ä›Þ*^$0øºÔ¬` v¬+É€aÚ²BYQ’±“‰ísn‚Á_mŸRÓÀã᪚Ҭ)v¨¸Â…‚Ú>ç¦d0–Ôì’yò¥†ÌVkª„ba“ ¦}fÉæò!…
+vr±#ÁAƒ!d¹d@WSœ4 Î`óÊ{Ÿƒ‘àvúl±).&g”Ô½Cdî
+†iËÉ•`ØûWò¶™e]j2zÚ³ðÀµ¨­°¦LÎ(¨›ó?S¶hƒK:
+g(­Ú½ 5%s†B78#AÑ+Ó–Q±©E¯`@Ïp'(º#«Û§2žA‚!qF‚b 55³‚‘ÆÀ{j™ èƒKö1ðÆ€Ö”+!Á6ž<¹®ÁȬ ÎØT Å"¡Ñƒšò¸…3vP,R˜£µdHxd2gðG„dHcà;(vp¤Àésù
+sp©leRˆ¾:u~°š
+Ï8æPÐcàÌLNHhP’‘qmUFm!W|¦çgp0X5îvU>&0,’‘5” Œ¹{ ¼’ŒJ;1±n§ÃjM&žub½?cÇb™É§¤Ž)Jªsq—Œ¹Œº'<áÉ`0i3ïýcõx6Â$,Û”
+’‘ÉÂAŒgxýŒyJÕéÇG£\Ûy‚¢5•µ‹MUmS~H—ÖTFNÊ÷äÚ¦TÕì5
+É1ð”ª3°5å®’ èØÏÈü¦mºçRï’‘)ñ)ØïFÆ|µCRëž32›Ÿ¡UÕAJÕéŒL\Êî¹”Ruz$ðŒæ ¦ß©ªN¿~†âC• iú±ÍÏH©:rFf1mGTl*UÕéÞÏÈ(5¥a‰M¥ª:IF¦YSF][CM!UÕ(bÞYƸi¢µvÈPUuF FFYSÆœ>½©yJÕiÏ?#°ÞÔ0UuØtÔTBÇÍUÕ™JÞTæ¼KÀ!k];D'ð”ªcª©Ì:ìªsÆ!c¾Ú!)U§kJOï´THÈo¬ªÎ­©èÚ!CUÕ™š5…øù)U§?5åÈ¡8#Aч5÷ÍÙMÎHUuz±¦¬Yè¾ûg¤TcSö‘>¤T¬)ßv‘Ru³¦¤@!ÏH÷\ºA5¥Ýs‰œŸ–Zg A±)úžK`àIŸS‹oš5Û=—ìµÐŒý”Ðè ÂéFn‚±ƒâ'–àh F@lÊ
+%;8RŸ¶–ŒÌs£]ÒÏØÁ¡øI£f&”uKùR£ÕTf›zLçÚ–`ÔP˜`H4®g,A€‘5¯Á(¡ Á°~N`8¬©Ì‡Ì|cà¡`Tý^ê, Æõ•ûÕ†s¥õ䓱Ѫ)™3àŸÓFÝLÑWÖg}ôTö—
+÷ÏÈ”º¶y4gP’ATÕQÑbÄû±uyR’±°ÿ
+ºçRì °\`8êêŒ[22#;8cyÏ%'Çd])r‰æŒˆGfYë|&
+FÖ*6Å |XUGó3BÜ‚èh \)L&œ1_<\„š¶šÎBLÛ)€¡»Ö9}œQS)6Õ‹]£0AÑ‘šÊ˜±)DpÛZS©”KŸÖTøxFªªÓ1ksúQ×6UÕéR2²èÁ%¤ª:½€a\BüxjÝrF˜‚”ªÓ¿5Zü+O7ÀêY2²Fó3d(’ŸÑ™—ø¬sFJÕé:6•zàH©:Ã9}ˆ0U§>|”¥ßÚõ­ªŽ?6µƒÂŸ p=c­À`ãVSMýŒSuˆóÀ›rFµí?U‡'ë°Q¦’œØ1ðyìý3j}•ª#¶YMµð3øàÒ|ˆTøéqB¹Bb8c>TªÎÈÁÐ9Í8cy,'Çî[`ZMe ²CÌûô͇HÕ™ˆd´ð3|¦mg©:c'pGFaŒŸ2?£uªŽ0m§ ‘µC4Æöm
+¢ò¦RªNÇ’¼VSˆäŒ”ªÓ)°©©Y Ÿ‘RuºCª’'ƒðñŒáRuØè%C`ÁÕTìxÆ€UuÆ FÑ© .ˆªªÎÈ%yE”5…á«êŒ4EG#ð „8]oj>TªÎ¸­)&9}¿ç’"‹Å`©:cVSܸÍX㼩¹_Mu—ª3jɨñ¨À@³1ðáRuÆ
+ÈØâj‡H†Ýšjª3R02µ5ô3B‹uPUgÄ`˜¥êcò¦Ò}znÁw#C^™ªÈ{^/¥Ö°UΚô˜‡ûöaôÖ0Â'ýKC8úþ¶þ’ÞÜ}éÄT9QßHßPƒ{£3Ôw(‹yvwOB}hë'Ò _vZ'»$v@CúÎþÏÌ«ŽK媿ý8Þââó3èބ킧®„\}ÍÍ5’öPO…Ìésž „ÔÀýU`Sov¤F Ìßí3mÅ@ÈîÐK·éõñÚS°þJxµ«÷eÒg]çÛì)X9–cô£Iɹõïž ÔÇ
+u—“Où#|R@™Àº?£+¹Ûúîi$õÁ<‘ ÚÞe:aò&Ò7 °·GmQ¡*g”"Â6 i¹ƒç>Ø,ßè/‹aD3\sú`€¡HF^é š%,’áðà5Ö·k)ŠÚmÞ–õÞkÏ]׶ìp`ÀPW60¢.qh…žgÏ×Ãßj
+ AÔÆ2ƒ´
+BÁY‚'!Á)•âI…w[Öû A8g˜¦m%ÅbñÈ%év ¹ˆÌ·˜×™J§ÔÕ­…!Ä>CðvâÖ‡^É°FfAF@@©{ÐF…»ßÍpßóõ~†ñGm̸ž! jä6“uYbšŽN§oûÌRë¹ÝN´lK­×žªS€±L­ÏæŸ ôwc(0(CåÖM¯-–q¹¶Û#©) 1…¿8 &”àÏÝÚÚÊFO`Q\)ÓzÔ`„VbÛQ_¼%¼H€i+“dÄI¢¶¹ p
+ô3Pù:ö.µ¡Y[N0“$ð…ˆÝºü Z2ìÖ(0¡¦&Å­­)ÉMÔÖõ–e…ÀS#¸RªÓà­Æ´i«ì§›¶õ3Á
+“õÅDm§Æà %6åŸÓ·c1¤d,¦äi!ôÙžŒôMÒ® M!WGúpF'‰K\‘á _µù¾"ÂÀS¥•!
+¹xMÛ R—ù"úúœ×ÿaz‹yDâsjÃ5ÒšŠHyN­õ|¦°$6[å‘&««‹Óy¨—»wøžÌ=·`„M=®0aB=pcš`ÅÉ@Ì¿–R_ýÅ¿†»:&n.ø ÓÕO˜$Ú¯ö »æÍ«5+£8»ÊòÛ}¦íJdÒÜ-O\ ªQHW.誋õâUÔ,”ÁZ»xX—¹e-üŒ(ÝÓ¼Öë°ŠJ»¯dXËʉîŽUÎ<¸ÔL*:=7FäÚ}%ÃZÆškœÅíô‘ì­v"”ÙM±Ç€é,A±)›oc Q;‚ò1y©:4Ò_ÍX¥âZ”„Œ @aÓË5œ‡q³b±Óû þ{gj
+§fטîõ€P@{ £CëÒeò« XŽõ4¡›ÉðxEl‚ÙÑÁI5eÌò¼ÀÿÆ»Ï÷Š¡íeWëí!¦A:žÑwx£¥ÐÍÝu(rMô¤l7\}¯à IÁÈRå‘%iG~‡p¬NbP?Ñv==ʾêWG©ªÁT°È+0ò|)u£åØ\­8+-›ef3~Ÿ>¢|O´GìU*¯'± ¼ÒMuá9&}õíçåNE•`(.v© ÐÖÕè¨÷fœÑ.Ú„ˆ¡BaîºNm}’Á¤brråk hÇBei¥”cn.+œºz'h—,Ú@
+Z×þèm1LM1åŠY–~†nMijʆX&~Á>%— ˆ‰—ØÛ.Ö¿­TSW7䊤%OË»4ü H`@­0›KÏ Ø”ØTˆ5…¦Z*ØϳQˆ§^'‹²5•KŠ_
+ÓV‹MÁFhˆ3‚>h‚ŠMÙ†b XÙTi{q×Cxi®Ø”k‚%èóÁc ¹y7®òpÏœóêV6:îi J†»^8lˈVS>ÛÆwCDë]Æà°_ƒJ©v(›rlŠè={àF€áÈûÒÏ {¸Q‰MÝW#¢AecâLdµax̯õ¨-BŒ¨‹¦;}A ¬ò%‡ÐòÇŒ9å ´ªñ‚ˆë•vÊ;\DÀ˜BÆ3"ÊË=húGïŠ&€SúJ8Ûe!OÐJ^yÑ°]dÈQ[Ð{Ó]HŦ1V"±}Ÿ1:6Tº<PQ!LÏA/zJŠ,Õj®$£eÅgƒ3
+É(Ñ(^g, ö HUHpkÈÁ؆՚«¥–Í䌣‡"2g8¯\Ÿ8nóˆ¡tCâ{ЬœQÀTrF|È#>d’°€žµTÞnJ×J’QÉ…,dÖ¥“•{­¯çÃ]’M'WäMÒPrmuÉŽÿÁAÞÕI!F³a~µYìgtIp?CãŒx%âA Ô`…ÇùèЬmÓ« oiÚmÕ”iM‘¶'h_Àn[ûn¡{wµön^˜}<Ò•ì KïB’ ÍÏÈ#†ˆš\ržÉ8î;µ—t¦_Bn”Gà†Ž˜XqÎé;ýæö›ZE¨†F†*âÕPËx&hÎ8z8“ –…;º!ZXà–’Æ ®Áü 9%AŠŠ >VjŠt
+v&¢h2‘ƒïÐ׿5tá o.ÜÆçŠÀ禮­”Œ;f›Ý¡½EÚc&ï8óïO®™ÙvŸ©{D,Òß6ºÍZjfûX€ñ»Ôö¤¥{åíSû
+ä
+„&˜(E,ì!·$“V³ùŸ‚n K9¶µµØdÙ´õåι¾î|«Ÿ2ú]v¤Ë 6ÉâZÒè$'é¬Â[Lé¤@-6ù<)·D!žÊ‰“D<AQ‹MJ׺p1Ùƒ¦DŽI"3Ñ\¥{= ÓsQAr™ð;C’ÈE%j±IÕtu9¸î}r6Ü
+endobj
+332 0 obj
+7304
+endobj
+333 0 obj<</Type/Page/Parent 290 0 R/Contents 334 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 54 0 R>>endobj
+334 0 obj<</Length 335 0 R/Filter/FlateDecode>>stream
+xÚµ—[“Ú6ÇßùgòD2Á±¹úÖl—4SšigúÂLÆÈ«‘%*ÉKèC?{$›‹¹,ÛnfgÙ>Gÿß¹èþjEâOqzC Eë}Òz7!E,¡;
+º0õƒ$Y{ÞÆð:ù³uŸ´Â DGûÙ—‡è„hÛCÛâAU 3»iÃA­àݤ_É òNÄÐo†H.•Ú;…;§š­£C'ê!álq -[hƒr‹Ùâm+¶¥æåÑqÐG´á…üâF´Ám+4Íþ¦/Öï£mƒ~0®7¢õ^Äl×ß«‡K‹5FG¿¸«ç$S^~ª(ví?½jq#U4òíÿÈ4[ð‹dãš }:Ý¡¯ý„qz—K©©š·‰Ú
+XPH]Îöåʘ¢p Ö4EîbÍ©¡°D2ÿþ¼ÍlrFrÜHS‘JQ½–"cbåm™†œ­rŽ¿qÑÇr†iK…]7ÔíSëè4˜X——”gÏl#Ÿ§!Û
+=qÓïÓçé´é„u²A`ø ãWo^5m¬"âÜÁë
+q<Tôæ²n àX9<3Vdý<M>>GÕ« Šëêç ß=Üÿ˜¼D¼–F¯)aË-šºÙÔ9Ný¹Û1t±Æx‘#óÆq9Xà³w¡k°ç$lLnª|Oß?GsöÊ„ü‰â¡“[Ÿ® ËVÔ‰¥¢8'íá*ha“ a±f.«>J–û@4oOø—;ûÝ©‹¹äM¯àͨѶ<+û×".Ròu¥d)*¡úØœIÝ{…mpš:;5.‡`ï‚Û›«Xoá‰DY,¨ãð]†i:læKiÚüó×àIÒ|Ÿ“;RâUñíÜŸ@Ä0Ì™kÚ¾«xµßaÛÝC~“zÐ>Aš³Œ^Õû ôÿ9c£êíh¹o .èûÙoð‡?3;ÆöîqCÃvânèÒÃS­¡!Öí÷÷<êUÖ~oý ÈQ‚wendstream
+endobj
+335 0 obj
+956
+endobj
+336 0 obj<</Type/Page/Parent 290 0 R/Contents 337 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+337 0 obj<</Length 338 0 R/Filter/FlateDecode>>stream
+xÚ½UMoÚ@½ûWÌщ„ãCÌ•(¾´‡¶±Ô Reìq½ÕâMv×Pú뻆@ Æ ¤2ëÙ™7oÞjg^<¡~Œ&æ—/½YêÝ%S ÒRïLâ(ˆ!-ü§МגþÁ¹ßäU&@ÎonÒ_^2
+†ÆÍÙ_ýœÃ]íÃI×'T¸€Ÿæ_U&xi×hm?DØBø e8|-Q‚ûÌ6P`™5Lí`.• Q9` Š.Ñ&=„Þ+Dáoõv ~ྦྷÇ%Y‘X¶@6÷M
+¬·ìH§ƒ]p‰TŠ*†°Ðц'”zï„PçoÕ]‚@™gu'¥oÈxV86y#Ö
+
+*0W\l.?¸n>²âën´ƒ¼LXÓºàë3™¼9g\Ìý„ýx0+ÈNs·µç~Éqnì­—;v›©G%¯ÕöÊ–'®ì«ß nõàݧ՜¾§ÀÛ$:Ç{ó¬¹P­Ž[«Ý¿†«‰4íñ.ù~÷Ye¬ÁÃvõœ©ªÎ–ØÙµÚ8SS©)ôñ½¦jº
+™n0XØŒ§Ë3œVTÒÃ3=L5B´¼ªy˜©Ò&²lS/ BõÌŒâ{½êW ”n®Æm<‰I@à~O_à;-tå U°½<ùœ~2xç8h=IdŒ£é4˜€5ä,“þ¡©I|õþ/Ö<Äendstream
+endobj
+338 0 obj
+524
+endobj
+339 0 obj<</Type/Page/Parent 290 0 R/Contents 340 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 74 0 R>>endobj
+340 0 obj<</Length 341 0 R/Filter/FlateDecode>>stream
+xÚµ—MoÛ8†ïþƒî%=X%©O^»mv‹ÝÚ½‰ŽYèÃK1uÝC{‡ÉN¶àAA`E‡©wHÎÿ+ ÿ8”Òênõz³zu-çI›-¶¥„MsU·jáÚ´ú]=ô/7Wo7+–øv–dU%¾ üY ÛS”4S”T$ÜÇù=ÄùÓh«l½;ú@¯®9HrD†µÈü{sõt¬§ÁÖÞ)åIéÞõuûØè
+—
+Ù2¿bÁˆd+d"g¶OÚ:ýyy¸<Y—˜8dDÂåeAÝjõ ‹–‰yu2"¹²”R ±ê°<–¤þ'OF$VÊHý[Ó?ƒüyäOXÁˆÄâ%Ékìè–çb"HŸÔŒH.–’ôÃa³8—¨$íý~K"#ŽKHFª\î¸×˳!TØüv!#’­,Iùí š»­3Ë£)©ßïddD¢©ß£-•³ ~Îý‡$+’ O1~Z²ñ8:ÝÝ… Ìòø”ó EF$cZN©à?ï»åÑD²¡ðZ## o°!öÊ9m—¿lÎèð‡4‘dœS.ŒæËò)ÊeyÎ2â°¸¬(žeçàxç€ÄŽdDbU9¥Á'Õ>þ”KÎ\¡v™.Úó=óöêöå/KŸTÎ>Ön°P[­V
+z}ˆ-RÆí|Mã^×fk°1ýv°òeй^¸ük4b£O„áu8ŽaÀPùêfkµ§n[èt7Ø#•G;,zîµî}ÃPãÄÐC˜¹†©¦Ñxå7›"c¤Ì·7ïá¿PëÀ þ|—ë¿7ù>kr]—‚ý¸¼ÍÊ ?qhäù$Š«oÊendstream
+endobj
+341 0 obj
+886
+endobj
+342 0 obj<</Type/Page/Parent 290 0 R/Contents 343 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+343 0 obj<</Length 344 0 R/Filter/FlateDecode>>stream
+xÚµUaoÚ0ýί¸PK(ctÓ>t]™ª¡i[‘¦I‘k;‰73Ûòïwg-L ݤµEs÷Þ»»wî¯V
+ þ¦p>¢?¾h½›µ^L. Ma–ã7£ñ°?†™h»ÒXgLˆlû^dÎìF÷ѽÁ¨?¤èK!0ø)7kc¬˜®%x¾” ¸©€YË6]°Ò׶RUÁK£*/-…)ßÐB?™s£ÝÉá§å„øÿ%f%­—÷YóྠôØDIŸž÷OÄçÚ°ßlN—3ÿ¥˜Q(x„0NQçrévG¥*楃ܚ$Gâ#Mð§ ëRixƒh¢
+D{ÌÂìAú ‘§ý$²«
+UAÖÆ/²(‡z’6ki{Zæ¾d•8¢æÆV(ÙäûbŸžÉÊ(\K†ÖhhæE`;µŽÍ̳(ù™²õá¸ãce&z~,§x<cÜ«•„·6{¸îa¨Ûö¨J(Ž³8eÉéq&8 J?Ë13ÃVw¤d–N´¬ØBFMôÉo–¤êòÓ÷¬óæIaD†UQŽÉÂy^ʨ¶ÀÒ*Øcœ€ÀÿJ¯u¾qr_ƒ¿Ý¡»ƒ)õ kZ9bŒšÝIµqVß”($nçºi—K­ä£ñl©×!—v¯@Jii%è<%[ ö®ÌCüv:ÌA%¥âdÏäSânÆXÈ4 ™8àw^jUàÐP/­ìžòºBcÕy05òj®aÇæk ›btl­[J®r…nÓ\°BÆû™Ñtto`‹jŽûÝYïšæ¹WGºðà”2´þ퇛(‰Èž9!âstÅbz–§ÙðfŠi=!q‹·ÍpÔ,Ÿ‡›ËAíd^k¼’qùj×໫Ò'í±õ¢súâ§Z ¸“G·/RˆH@ÐŒV
+endobj
+344 0 obj
+778
+endobj
+345 0 obj<</Type/Page/Parent 290 0 R/Contents 346 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>>>endobj
+346 0 obj<</Length 347 0 R/Filter/FlateDecode>>stream
+xÚT]š@}çWÜGݬÐÚ§íRëZ—ô#1ٌøL…:3jé¯ï PWC7µ†Ë=çÜ3óÃrÁÑ ¾Ã1àÂz—Xo"&¶ÉÆÄÆIÚ‹hNbÌÙtšs”>ÉJ*R<Q‘«Þªÿ¶Ÿ|×À ¸®Á 4pàí‘î9M¡Fý,‹UÏ@à ¸1~µPç8Ó ˆÁ×ÅG0R°ÑUØçR'ù§Ì%RŠfj{•IÔN0 *#53C)œQö -l¸¨3L¯kS¦@Ò_äbA¶+ÖD
+nö(ß]näú  !Põ·Ó´`7pm†Á¤!ð…¦ÏDÁ£~ 0š%õhMêÀ÷œúÉõ?mš„‘?²¨º¾ „‰õÉú .EuJendstream
+endobj
+347 0 obj
+502
+endobj
+348 0 obj<</Type/Page/Parent 290 0 R/Contents 349 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 77 0 R>>endobj
+349 0 obj<</Length 350 0 R/Filter/FlateDecode>>stream
+xÚUßoÓ0~ï_q/,Yœ¤IúÀ °ÂHÀ"ñ2 eε1¤qqܵAh;gçG»hlk›Ä±ï¾û|wŸû{ÂÀ£/ƒ 2?¾ž¼I'ç‹9°™›@º¤µ(žCšOy™Õ5,D‰—Õf«OÓŸ“‹tâ¹ÆÀsC“˜Æ>]
+a9À®ßÁ¾Ë Ð[ ôA Ê/t¾ð`Þ ÇÍ8Ÿ.ÊC,fÝàïxâ•CŸˆõ@Ó{T¹8&FÀÜØx_V¼Üæh7V?Âå…è O\·8yúÖ\‰²jíB0ŒM2?¢”‘MZ ôQÛÅ1ïÞi
+;‘¯PC‘Õ°’´„„ xVå"Ï4e]*ÐXRi¬uï·¨\0¡dU6‹åV @ï«>ŸA»W¡0-Ô˜ÛQE &jrÊ(nhÜÛ™Käs•…
+Q–°–·h}øVÕRxSFÌw¹l3acSì†x‰™º?Ftj™õ tQ­ ƒ©,ÿYw\lïPêϨ ™wýÃ;Þ~BvC¥¯ý(†ƒjHuæÆÌíÛ{j5NDî ÖGnн”pe¤4rP+8¤Ç(—´7³Š978õÜœ˜ä=$î9Üâ€H­!ñ 7ûòLnqH¶äîIróžœ^—·Áëz** û½)™†¦iŸ»]û,Š3à’j ¼ "¿,á5xק
+ÏÚ«-פ®$T?ØôO’ÞöÔ¹ NÉa#k14]-þà¡uÆ4÷Û²v(›–mÏ‚b-Ò2#\KÕ´j4Æ ©Ü,HN»ì[9鱄ÑÑÎX[¨‹«/𽽢˜*‹OéGãã´¦Nì{Æ’%f2d©ÀûÿŸÄ×É?vÝÄLendstream
+endobj
+350 0 obj
+683
+endobj
+351 0 obj<</Type/Page/Parent 290 0 R/Contents 352 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 83 0 R>>endobj
+352 0 obj<</Length 353 0 R/Filter/FlateDecode>>stream
+xÚµV[Ú8~çW±/L inòЇÞhGíVݤyAZ™ÄIÜ;µ˜ŒVýí=ŽC˜²3 [µ 89—ï|>ç#_¸øõ ò!˜A²¼\ž-bð¦Î–>›E1,ÓQR¥`QþsÍn‰L/–Ÿo–×1®B8ðÚÇCRÈú0ãwaßñL Wm wŒJ"“¢1ž-\ˆ­!‚˜ø¡¹NG˜ì­ueL\˜x­;
+ VRuˬ3öqbx2ôkªÉ*Í·v!ĆŒ‰?CÊÐfYPØgµqïF°ciN50k¢h
+"Ë@ßë¿$ku¿÷Ö5†àJSb"@ÊTU’†ñ4zÓ xÙ@Rž[F Óeahl†Pó”J¨¤È%Ù@"¸–¢tàR+¼É6D6PÕ²Š´Z€ª«JH Ã][†ÐÑ€(* P+Œ¦ Üê¼8Jˆ±3–×’A Z­q«
+!´­¾(§óÚ³úBa¹º8™1XPPNlßDl ø– ¤`e
+«Q­jR"1ÿÙ÷è «‹ŽpåÀG²e¹-
+vk/ëD£%’⬪„ø¤£
+w«s’ò‡snKÁ´í#)Qò7­:ªôÎ&3n”Š¬Kßþ‡Â¥]âKÁÞ
+endobj
+353 0 obj
+897
+endobj
+354 0 obj<</Type/Page/Parent 290 0 R/Contents 355 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+355 0 obj<</Length 356 0 R/Filter/FlateDecode>>stream
+xÚMŽA  †ïþŠ÷Ø‚9]c­k°]êP$t bMÛ #J[ЯOÛˆP¾÷ñùÞ;á`þpÌòp›+Y
+’T pqöI^d´€“þ¦%úÚ<ÕaR™ã^ËV9L_‡(ÂóMøŽø€$Uö³ÆiN³
+M§Äk¸®vн¶úd4Ũá§ó±_¹Û`Üë¥8{iµ«ð%Èxž²@¦, 3¶ð¾ƒÆÔÖâÛû]?dHKA¶äŽqNÍendstream
+endobj
+356 0 obj
+199
+endobj
+357 0 obj<</Type/Page/Parent 290 0 R/Contents 358 0 R/Resources<</ProcSet[/PDF/Text/ImageB/ImageC/ImageI]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 92 0 R>>endobj
+358 0 obj<</Length 359 0 R/Filter/FlateDecode>>stream
+xÚì[ÛÆ€OâxS+‰»’ãÝ>é‹‹Â{ÑÞ¢Àj/‰ßŠÖhŠ"pìM²…c;»6Œ
+qòCo)•,éÙ»€ö´'­ƒTZÛ¿‡ž´2?±ÛOl½Ö$N~ª-$ L%{
+=ñýh°'’¶½€£¬V‘üâ$Gµ5Büi{⎠ážE.<iª'÷5ž'¡!žôÊ#ž4Õk@JeOT½àIO
+ë<i¬'Ö¸‚Êy¬ê?ñå±eÄ yl£ók\Aź¸—õǪج‹{A{êâ6æ±Õá/¹'“ÎX<ꞈø*a;b¤«MçIà/‚¥iO
+jë? ég ª‹EfêgC“óXÏøØEödžyRØ[Þo&sñdqßâIù÷€h2ƒ'*‹mì÷Åu áE“<I›iöøh¬'ŒgÓ O‹'Až
+ä ƒÖĹŒ?Á“¥Ëcç2ŽO–».Æ<É{2jJ8/J<™ÅŒ…néù;"œ7
+¥žˆp~1xÂy蟨DOð¤ ÞéPï@—ów
+žà‰?%î@X½ƒ'@Ü<âÇq–ÒúÙ 0?ÁÀÀÀh'F"‹'xRPã ”ybÌ4œx’žÁpÍr½f…Kœs5ôÖ{¢æ:À<)ò¤Âoyð¤åù‰ùýNsÆw±,© ö‚³=IwÐÉ֯Ư£M;=±þ×'QHE#%JÎc-kk{gÊESËúOlOÒã˜_ÐÙŒ~QÌ݇x²ž¨ ¤e«ä=ɺf³_Mv+xÒpOÆS)çÎw¬x¢·6ÒWS4i~~Òqç'b_&[â‰Ú ž´¼.¶®ƒà:ÀilÐ Oœ&?Ä“æ{"Ò±=±³DQ ®z'ßž”†!²“Vx’Ÿ'GT§Ç$Äo7°.N”Nk­Wñ¤5ý'w>ÞMÚQïtîxž<icÿÉâ-Á< ò„CÔŠº˜ùO
+ Åu1´É®‡xuÆ!î
+âNr‹=ñL6âz:÷œž+‹ùmðOVÏ“±"µyR¶ ,“'é4ŒÝô’Y‘üµ”3C¯žîoڛǮ%?LOÔ4Ñv QO§K~OìýÀ’Ôű'é®1ë¼s…T€|~’ß,“'V›à|º›;þnOL—`yê[ˆ®×¡\qÇšTUð¤Ä2Ùå÷Äw$w%—']U5áɲzbÕ;V$ºðqÖ;îõ`é<éš—Q2zMªÔÅ\õ¢Õž0ž ¦«‹Oððððð¨‹auÚ“µ5Ú‰;Ê<Á“‚ü$5Oð¤0%?Ú ?ê ÿÚ˜ÇÒž
+ä
+NZäzŠQ^/Bnª¶¿ê{ó]¿J>ÉbËRŠÇ>‚È2É€¥`^‡qe
+V$¼ÿ—Í
+endobj
+359 0 obj
+4684
+endobj
+360 0 obj<</Type/Page/Parent 290 0 R/Contents 361 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 100 0 R>>endobj
+361 0 obj<</Length 362 0 R/Filter/FlateDecode>>stream
+xÚµ–Mo›@†ïþ£öâT5›/[)i¤¦R› öâ˳°.»ŽíúÛ;³ q>L+G¶LÞ™y–yaókä‹f!}Ójô1_¦àyä0)„±ïÄdãÅ4Œà,ù9ºHF®ãb"ýxôsó Óµ3ÔVÌM"%ÜRÑ' Í
+Î/ý¶ v¾o¢
+¹¥½{¯ï°&j'Þ { ÄŠ\'D¬pŽ ÄŠ<ÔbÍwZ‰ßüôhAäø„š ¢1j M®KQ¿™ï£ÉgÖÉüÀ6¹J,ËW ›aˆdþÌ™·Á@²™iñ
+ó"ã{ßs‚6HäÅÖ÷»Ó3¹¾1½e2Á@&7°¦ß¿Ä4ï˜P=™†Ö‡W¼\X¯ãÅåJºMRpHe­t³Iµl m8Ó\Æó™`¥\ÁZ¤zÓð ØRÞqÇ–š?/õ‡ú}|{´aÆïû™?åÞ6ÜŠlÅ5°:ƒ¼áHÁÊ*^Éf×™†‚)Xr^Ó™"(
+±妛¦áµ†\”=ŒE/ß ÇÅÖ¦dÁŪРsÙ ·Íènîã:c\BÉíË
+Ԭ‘1¤’d@Í YC ËÆꞯñ›.Ñ)tU¾µÒ7‹³#Ë^K%´õ ·{Oð°ß÷z Kê|9àö6œ¶£§]ìq»µÇ¢èíJ”±ÿô§}º×T·(8¹©ºmx1ÞO) ð`pöüA×Gȵ|žWt4o ž³M©M6Pú1»ó>vyý é±–S£"Ì
+endobj
+362 0 obj
+731
+endobj
+363 0 obj<</Type/Page/Parent 290 0 R/Contents 364 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>>>endobj
+364 0 obj<</Length 365 0 R/Filter/FlateDecode>>stream
+xÚ­’±NÃ0†w?Å?¦CBìFI:‚Ô
+  –Xº´‰C;Ħžž¸)„„‚T¼Ü}wß?ø™qÄCqdóÅ»ìlµ
+endobj
+365 0 obj
+242
+endobj
+366 0 obj<</Type/Page/Parent 290 0 R/Contents 367 0 R/Resources<</ProcSet[/PDF/Text/ImageB/ImageC/ImageI]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 107 0 R>>endobj
+367 0 obj<</Length 368 0 R/Filter/FlateDecode>>stream
+xÚì]ÍÇu/è4´¨‹ôm09„F(rI®)‚%w‡¶.AÌ&‡ ‘¶0½” ÃprØj„è9dºÚ×ØÑ1™ÌAð%¤½ŒœH€¼ùd]ê?èÔ{¯>»{¾vVÚ™îªÝíéïúõ¯ÞG½WÕ?~ç|{Sýœo_¼¿ýó;×z~¥}þ{g/·{?TÛ.}p¥Ý»yú£;7îßoÿàÖ{»·oÜùäGßíýÓ;ÝÞ;›gaͳ[í­Ë¨å êoÿVû‡ö<Ï^Ðç¹xáìy8Óéö­ýû}܇»¾Ù¾B;ª»xÿÂ,ß<}ýÎ?~ÿ“ÏîÁ.›í÷Ïãáívû_Š+þì}UèDç͉N‡÷êßÌûp‘‹çÏ~
+2Uåþ@¡¨@é÷Ò–8HY8þXNÖ• ýäÌ‹¤’!Lt6ž§mP½¯á©g}øUõ©ö©ªõƒS  ˜Ú®@›S<I™b΀ €/kõ3<3ö¾)‘é
+> ‚29=XÕO2BÔò™ç(™
+–S›ð‹²ClIíÇj~¢4AK$†8 s¨&n;¤ÂÛUõéI’$©tA¸ =ó’ý¥ÿª"ȸw¥2dÈA
+k¢ª­‹²C
+qFII|Ú
+,&ð´,?àY‚‚µÀV 9@%Ø!
+C]yðvûN˜ÊÛγŠ¾Ácj*æ hx´ö—•é|`Ä}še¨’gž'¤yÆèºÙ"_†¨=8V2$A©àÚ€RåT„Vì(l5š!›¸œœÐ²}>ZØÓ$ˆaˆVÉŠ!O†(Ø«¢´$H
+[a 4tˆØ§@{ñšéo'³¬ïÑ
+{ݘ‘Ðé™F/C<ùiò|´?Òe8úõP}ÀŠáþÈüèíþ×ý¡úÚ ´€ÍN#ïøoyo¨k44÷¬£sgìî°å×^Üí·O‹ö°ã•Q§æ廉ÕÝxuºýV§#w6r7ì´ß=|ÑÉš]”
+‚˜D’e‡‡¿ßx=&ªx±Šê2iƒ[Ÿ¬Z™T1aw±ñ³7¿W‚µ³ÔUÓõ+Ù„ªd e6 ‡K=©OÔ§šv¦¡VG†LdõºG"2Ä0d–j'ÅgÈhÔ¼Æ1¡ 9ˆ ±€¼Zˆ!õ/ÚÛ%†ì6°üåo{ø?‡ª|…€  y2f f¶è»Üýú”§Ïžm")0úÿ|L ÙΛWî~­ÌS´¶‰!Ï1Ç eHc!#lÛcˆèP“i( T¶­ ±¾L£C^¡–É’f¢ªþ8dˆR½ÔÒL@”°`­P†¼òdc¼â0Vc@²dÀÐ!`ˆ‘!R©æ†’&2¤ßÁ¾ˆâG%Eê Èc0Њ2Ä0DQArÉsøeðÃ`µZP+ñ£fZ†Ò„†¤Ô§º­@€VC€@ã¡€¨%^O@ë(fÀ}ͬ-#
+U%Tc‡< Ýdºˆ° y):I£‚–™³C0?¤¹2Ĩ™6c©&QËx q½îMõe
+–ª×cÖP†€QZ&qZ¦ÉM¦kdˆÓ2cbH£{̺{™rç×"²æ
+Õn±Ç¬Ñý!=#VmÙÆ#bˆh²ÚU`6bdˆ3Ý3«ežÄ³n e¨×š «ÞJ/6EÛŠ»È çJÒ>Áåøg)àåT6ñÒ í4-WÅm㺌›êy•¼‹XC„'C4C¸Ì9w·HÇézw\¾9}Å”$Óˆóà[ “Ê£§šy U¬åHU©]ä|rî¤w"©¯+ƒoÓëÇç$<÷öáÕ•äáY§"'¢¹\
+S¯`daÖe™`D˜ëOµ‹%eèí:)0Rý˜$Ž©xübÚ
+£+JãD €ÓMPšÇDnê bÌDµ
+îIΧ‹ø,Ÿ–j¨¢/‚Oň•!áˆ*I©ösmƒqZÀâzŒ*B‡U·èr°C²´ÝD§ÒÆœDˉÅ%Tw…Ž‘ä0ëKç¸Ý¬ªðié’ÚÉÖ.0Þ35 #%ÓV!Þ>÷š5f=k˜¹ "íË”ÌàJ×10ˆ +¬#[i]CݹŕgÕv½»î$ŸÖîã_׿…ÜzU%¯¹äËTe2£Cɘs.¹s«ú\º½m/
+ÙÛt*í¸ȳåÞZß[–v ò
+ŸVûÑ’y€0ÿ™Øl@
+ ŠX‰Ó$sgvÌøå_up IÓ1Èñ ù2|¡Õ'­eÅ̾â¸}™µ…*Ê—…x̾Ì<ßb
+Pâf‚!é¦oZ†,— g¢²syå> ôÝ
+L/×Ð-DâË‹8£8—w­§/¾HBI
+L¬’!‹Dÿ­/£·¶v- ÞÀMsÀ*‚¾Ì‘zÌB@|{=°›»$‡!ù
+Ò[FËp
+E‡8[&2 ùvEÔ2FË ogñý2)’$›QË¢ðhE-ã‰o1ó’Aâ[Ì,CÒtP°Câ»2‘QË "¾Å¬À,¾+³ºÉ”µÌõ6¯T¾=D1h#›XªÞ¢´ 4™L4°(˜âfþ4ÚÇ.‘&M,•Ô1ä%j™ÔˆÛ¦C•¢¥šdF#7­xñ-ÕÆ2$qÄÍüßT,¬I†¤ e’´±ÅJ+CöÓFGÀ—inNÞns’V1dý•Ì¿=så¿q·âÙe¨ã“É6üWå³u/OþË•û¸æ7nÅ^úþû³°<}ö…YôzÝ_=¨‡ yô Î}\ó·ñ
+\&oÒ CÞꜮ“ yo÷T eî^õ8µ²¤õ8)ôvh†ü_§½qøëɇ»»ß ´ŒZq
+
+Õ@vOe¬A;$Õ2iò6PE©íü‡±ÝZtkhâ3DÕõ§»»W…S»P{Å¥eZ©j-°PýG¡Z-#îî”rÊ Õ_A5U;QÄ`)SдÔb«‚!õ!
+-3Ê öŸÕ É ÎýOµ˜Ð2DT2¤œc6ºØ!$3ý>UÝ…hÕî„â[ª£šXªŸ»BMæ½5—‘!»‹Ï¤Þî¿^ô
+®ñW C³ÉÅ“!ûõ°CüþcQZ!Œ<™T<-“Õ×It'˜sBDšPUˆÌ\
+U±ù!uþSý§©@m©ŠNMf –¢*?¦\
+9fufHqE2… Η©qòG2EÒBŽY­xQi™Ï"A~ˆÎ1kV–]¥iVŽYæçPM ˆí1kJZ¦í©– .ÇŒÅBE3äÌïÞÄB…|™'?‰…Ê#dHÖ÷ÌðE£FÌ”ªÛÞx4N}¹;|Ý,@
+Õo÷ôŸžþîi[:oN7©”ªÛ~·S(¯;*Å궣®-”ÿ
+ä
+LiâÍßî  ÆõÀ2Yžá}&™uˆV™L„‚° (@åÅ}ujúr¸ /Dì
+ pV$SÝA­áÇV™žC ¥„›ª{½j‹®¯9æ»I~5}šÅV8ˆ§9™+R2ó ™õ23㥄÷TK59øå§z™ZšJ M[VgwÒHk1;õ2'­¦mêú¢<»“²$CNž:Æz™-±ç„¡éßþrr3Ž:¥ŒÇiŒMþ
+‰&endstream
+endobj
+368 0 obj
+7978
+endobj
+369 0 obj<</Type/Page/Parent 290 0 R/Contents 370 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 110 0 R>>endobj
+370 0 obj<</Length 371 0 R/Filter/FlateDecode>>stream
+xÚµTM›0¼ó+ž¶—¤R¼@XÈ^«n©©ÔnÐö’‹cLpvjœD{éoï{@6IW!ÛJÂxæͼñÇO/
+ÆèïÎ-¡³;6îot–ˆE‘ªÕª¼èìþà 9£0fqf²Ü|T¼4ëå`9$걶„¥…atíìV8cAXɬÁáÿ¬¡ÃF ·µ2¾2;ÉÚR÷¯Ký"É'%÷W3ù¢×|šçVp¯²µtÀu¹•è‚—%T²2ö繃‚×°’RÓ„hX„¸bk­ÔrUöxÜ•A¡2Ùëq†€ÖQ ñ;ÈI¨çÜZ×™Ù_. Ï–ƒ&n·ð>ïq1Gtë¢ÞH¡r…ÝÎÒ/ó¦EPÚ™Ki^¤lPþT@ó
+Cãemh 8®p
+endobj
+371 0 obj
+558
+endobj
+372 0 obj<</Type/Page/Parent 290 0 R/Contents 373 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F1 4 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>/Annots 124 0 R>>endobj
+373 0 obj<</Length 374 0 R/Filter/FlateDecode>>stream
+xÚµ—ÝoÛ6ÀßýWºwUê[zØÃ>ê®hl‹°½‰Š¸Ñ’FQu< ýÛ{'Jrf ™Øql鬻ãÇ;òü×ʆ/üˆþóÝê»lõv›‚: d%>‹â²b+Þuð£Pí¯Rì_g¬Þe+æÐsæ$1Þ{øÖÊÙ‹ïx£ßs\òó½õ#…æ:¯äèí–Aj‘aãt_¬·ê÷÷ºé[Ra°qs
+¸[seª¦¨Ààľ½Î@ÝÈÇš8w¯OãÆŽQ»è¡W"gï%¨7í΋b8¦f/}¸ôñË{\4ŒŸ¦èn‰‹†VPpK9yb àd\½€1ËñtŽ6l¶™Ð61Vɾ%hIä„„Ú ,CóÑ"¤A>_Ž-öÙâƒ`……lq€º8H!µÈM£çg‹nÈ`¬°-rí¾Sb‰×|'ÎDNŠh¡Ya!Z;ÃÖªdýçù±|(‚0ÀA¬°Ël¨†çÇòØP
+x=ìu¿·×ªº‚¼©±ÏÉ+®ákß
+endobj
+374 0 obj
+943
+endobj
+375 0 obj<</Type/Page/Parent 290 0 R/Contents 376 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R>>>>/Annots 126 0 R>>endobj
+376 0 obj<</Length 377 0 R/Filter/FlateDecode>>stream
+xÚ­V[oÚ0~çWœG:µ¡”K߶©lÒдµéxAšLâ€Wc§¶Ý~ýα¹¥ÐÛŠ’ø\¾ó[k14ðC§ —mHgµ÷Iím¿q IŽ'ín+êB’ÕS­¬ƒtÊ ¼É…äŠÍø¨>:p–üDµÖZí¢ÙŽZ¤–L……wSá®4Ê‚›rHKc¸r°2¹6þÀñ'Bùûq™çÜDÁxo×ø\‹ ¤P£ú'.‹~©R§FgGÁaÖŠ Âa2)Ç,}€-8¡Ñ»†ÒrXL¹Âsr¨˜k)õ‚g€X™‡No¥f¾Õç‚Çãø2j’cÂ÷]ðÅõ5‰qUŒÄ¤›2‡$=–Âp‚•
+Å9-˜›F; O¹˜ó@o^JI¶n…é€_ÁcÉ­·ÀT³Òºe¢ÁZÇCK™‚1â(¸âD1£ˆ·D° ü#qù¾Ij¨åE—˜.·¡Ù‹zpÕ¾Š0ƒN;Š—î¨ôøØ&´ã_£¡jÄL`ðçõ]QTåk¹5½°Ù„;J¬-‹BÃáX–!×–Û—‹L ÿ!g•8²ÈH3¤Ä<¹@æVÙ¼¿¼îÖŠßÿÒcØY7o5Óº¿
+ñÄ¥=Ð[$œj©Í¨Þ—?>Ф!ò­ÊZm‰š*Ð ¡X3°ÜÐÏY)]Àé…‚·ííŸ!{T‡•kåFõÒg3ß )¼ßÈýŸpÈÖiÑxÃÁ„B  í+Á]PGC¶N Æk¼Ìvw9á$ß’'ì•L§åŒn¼©sj·/÷ƒß Æn¥Ãé!‚u €Wû_í°\•ÅöÝ‘ –^ œ·Ð>ljpmö$N3º*)s8Z
+mÍòsà‚âı‡€ ñ ³ƒ^1?ì‘œ±~
+Ð~ $<s¿L¬/‚}$c0^÷èy2g²|Fä|‡¦ÊiPøëŠ]!] ¿À—uF¨ FÏ­næ«—4ÙRØ­÷6Ïðîñƒ*Wtt—€ãnŒ ¯Ý»
+Š7w_aÖÒ÷È¡?H>“ÎE½è4ž‰+°ú† V‡¾Ëüa³³Ü¶ßj
+endobj
+377 0 obj
+830
+endobj
+378 0 obj<</Type/Page/Parent 290 0 R/Contents 379 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+379 0 obj<</Length 380 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨J#  ‰¡‘ž‰X 9'±¸XÁ#5§ ,3µ$éÂÈ
+endobj
+380 0 obj
+113
+endobj
+381 0 obj<</Type/Page/Parent 290 0 R/Contents 382 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F5 7 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>>>endobj
+382 0 obj<</Length 383 0 R/Filter/FlateDecode>>stream
+xÚ½WMS9½ó+º¸,TðŒ!70IÃnp²Ù*W¹äQGk4‘4ØίOK»Àá`c*ÅÅhzº_·^¿îù±Ó„CúkB§G';ý÷×gÐ<ƒ~FON:í¤}¾÷%2‹p§ÚýþÿѪœF»F»ã­º9Sc´ <¶’Ãh—B³é­Z§äªÑ:IŽ½é uÒhЮ özhÆÈáZHìæZ[4À‡(ËKÁ¤Ö1ªœÐÊ>wO šGìßÇ ß7ÚtÑ0 ©.J
+e`ÊŒjla°—jEý™ÑdR3NSJn°Ÿlò¾DE ÅÌ
+Í‘âLµ™0£+J/ÓzߺïÞA¤oV=’XØÁþF!¯ÅŒ
+hS£¥1³t“¼ÂK<<\~ü²bµtîÓaVýå€qî+7ì öÃÕÍÃ/e]²a.w8]Å{w+f«F¥¶Âóc[ƒVüÄu,§ëÍ^4ò…X1œ¿`º\sëÙF4tt‡õ‰ôûS¡¸ž&ÛÖP
+5y)zÊ<eÒI @zja®+ÉVe©jˆpÉÔHœ9ÛD»œúHê”…ÎܤÙKµÔfÍ:qÌX%©Qé=/nAO— ®@éŸ_Ü^­BiÃkuš
+îr`.êÚ7 |qùßo—äS{“`¹6â'UtI1V*÷zoŽ‘€§Ï8ŠZ
+ehñZ/|øGð1nˆãþá}‹è6ÃÚå¹Ä äî1‘¬n…¸ð®l†~û&¨×›ÉaÒ\sI|&;B¥²âžs› o€:•‰qeÐo@¢tkCzºqªã¤µ)*ï¡.íï½J8A¬”AƃRr’žÔ‘ãV‚0ÌœˆL×QÔ’G|ÆÅØr”af¨Y‰…6ó­"Ú¹uX Dâ)ºj»œÁáQÔe©õ$’¾'h'µ:s Œfoe9
+nîî{W^:¶ŠÆ ›.°4Å’ü3»,õ:·K_ l VǤiÏOkù Ë ™Ò­xŠºŽv…¥ÁSP¯ éhj1c¾_ôBjñÛ§ötº¡æÉiÒ~ñ»ò¸sLe8ôÏZgþિóÏÎ/€¯:uendstream
+endobj
+383 0 obj
+1161
+endobj
+384 0 obj<</Type/Page/Parent 290 0 R/Contents 385 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F0 3 0 R/F4 6 0 R/F8 8 0 R/F9 9 0 R/Fc 10 0 R>>>>>>endobj
+385 0 obj<</Length 386 0 R/Filter/FlateDecode>>stream
+xÚ½XmS9 þίPùR˜’”$”÷©…ÀdJ[®ä®÷!3g­$>{Ïör¿þ$ïnš—%e™ö’¬$K½8ÿì´à~ZÐ9æßdºó¾¿óúòZoš'Ðѳ㷧З{çaÆèA¸TÏ'Öztpßjí÷ÿ&Z-ÖhŸ4ÛÐh7XmÐ>~ ¹ÀQ!°÷ÉÎ uö^I”IfÂáúê溹jë­™{ÄÐCï•GõsaÔ0ÌB°æ
+çフà„ΰžKýÂD/±†Ì
+ïÁÐÚ
+IØчFäÊùE„‘ñÄÞ—Þ_Ð3H‚ºG¸@l
+ƒ=‘Û0 õ–Ò²pÀe¦Ô›ƒ}¸ÍÒÔº­_}úü±{
+‡¥‚CÔƒ½Áþš!˜b˜XÍbNrh„‡¨’ƒ4SrŒ¡tó;'9Å:'ÛyÙ©ËËw’ ip¶FŒÙ¤YX#÷ExjùÒƒŸPЇâÉ 8£ÔxK˜ J ™1bŠØiª1(FQ­ÁôÎT˜ÄlõÅð
+{c—ÞÒd”I¬sÈÇ ÌSžè牴[Jâìì¶÷é꺻Ao‘LUscF½l›Íó/Ýwýîvæÿ8¤’æe
+w}zù°š¦fjS9Mnj¤åf±µƒ‘ûþìÞÐúæK#l +Ò]‰íÅnÝôækÁZ(q_QÿVÚÁº,{™XmÝS…GÖ„JÙ
+LYþGŠŠ÷EÛ~ZQ¬ÛˆkÞ³J¢¤ ±´þÒàsÅ,̼X÷†s8™¿Ñ"¤uÌiÅþÅzßò¶ò-j>ìFg*vª…,UFËx‹1ûY;Ö{ÚÙ¶ïX“Í©±…iË &©@#;ßaH¼Üg¢ú*SᨅR[9;]0õþ¿p}~i¡
+endobj
+386 0 obj
+1344
+endobj
+387 0 obj<</Type/Page/Parent 290 0 R/Contents 388 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F4 6 0 R/F8 8 0 R/Fc 10 0 R>>>>>>endobj
+388 0 obj<</Length 389 0 R/Filter/FlateDecode>>stream
+xÚ…Aoƒ †ïþŠ7=u©(SÎmêe;l)É.»AaAèÔÖôßœ;/„äËÇÃûðñPdaQT9ŠíEr¨[P
+Ñ!ç$GÉárÿ™—žÄW
+£õa2ãP‡7œ´÷“q§„EšUñËV² ±qÉ{òQVhcendstream
+endobj
+389 0 obj
+248
+endobj
+390 0 obj<</Type/Page/Parent 290 0 R/Contents 391 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+391 0 obj<</Length 392 0 R/Filter/FlateDecode>>stream
+xÚ-Š±‚0E÷÷wÔÊkQ™%tÁAÃKœ¨QøýR5÷Üå伈‘.c˜]äö¤ƒÐÆæ`†´àœc¯SH³*ë.¾éÜŒzyFØ£Tk¹Sò “it”&Û*¯(úëй ~€õWô!LnÄ›UËRèL%x#oendstream
+endobj
+392 0 obj
+124
+endobj
+393 0 obj<</Type/Page/Parent 290 0 R/Contents 394 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F4 6 0 R/F5 7 0 R/F8 8 0 R/F9 9 0 R>>>>/Annots 158 0 R>>endobj
+394 0 obj<</Length 395 0 R/Filter/FlateDecode>>stream
+xÚÕšMo7†ïþ{LÝð›»ÇÆÛ EÐÆJÓC€Bµ×¶Z}¸’œ
+uQ#+'Ò(ù ÀS;FÙÍ`¾v"j\õ
+·ä¢Nã˜NHY›‘: 2µÎpƒôS·¼ЉþéUeíá‹F 7P?,æËÍmؽ§Û/êÂ’ámÐDÈD°ŽÊ„`$Žß‚L”æÌLFZëÁHd‚YÒÃQB­ç”ä…"’FH8\êZæ øòÕKe7¤=Ä!õ‰M‘q
++Ñ/?eLW’²ŽIŽr•k¾É)ÍYË ³A5Èè%G¹„+9‘t!#9É9Ê’9Ü<e‚(¿\íÔlBð‡)㳚òâ
+F03>\àp· u‚¿Öúþ¶·¶æÓ
+o
+ÑR¶}2’h©f¼ÔG§Œ ?`Ë?ß/>Ï·×á
+SÕ“Ú>ya“”RõbOF/©Ç‹}$¡¾Rüº¿¿píØ4ëK”ÔÞ¯zµF/!NP{8ç>^)
+~Ñ·¯ýEfS
+™P…p±&Q{ÖäjÏÚÔ$æ’9
+þ¶¿`ø}Ñ}šâjf°c ½4 ïÉ8Ò±‹oNÞvËn¾8&%—xÉ pƒöf³ïBÿ/|€§{Eîhî>ý©œŒcm¿0-ÉÑùÝ|}Û ”_r‡Vëz­Œ
+7h‹«‘äÙ¸­d$øAú(êШs3­›‚bü5½£¢¸h)¤Ð‡7T£¢E&eÁ Z9ê
+ódjTLš¢wmV%2
+/ØF& ,
+lÊ‚´rÒ
+«È_
+ÉNHHÖ”Dnb• "™rÈ/Ù©éŠDJWJÄ
+endobj
+395 0 obj
+1747
+endobj
+396 0 obj<</Type/Page/Parent 290 0 R/Contents 397 0 R/Resources<</ProcSet[/PDF/Text]/Font<</F8 8 0 R>>>>>>endobj
+397 0 obj<</Length 398 0 R/Filter/FlateDecode>>stream
+xÚ+ä2T0
+áÒw³P04TIS0´0Ô3T072PIÑp PÏLIO-Qâ´ü"7ŸoÍ,.]ˆB]¨ÊÌL kW 
+endobj
+398 0 obj
+89
+endobj
+399 0 obj<</Count 7/First 400 0 R/Last 423 0 R>>endobj
+400 0 obj<</Parent 399 0 R/Title(Table of Contents)/Dest[393 0 R/XYZ null 756 null]/Next 401 0 R>>endobj
+401 0 obj<</Parent 399 0 R/Count -2/First 402 0 R/Last 403 0 R/Title(Introduction)/Dest[297 0 R/XYZ null 743 null]/Prev 400 0 R/Next 404 0 R>>endobj
+402 0 obj<</Parent 401 0 R/Title(Compiling the Widget Set under UNIX)/Dest[297 0 R/XYZ null 634 null]/Next 403 0 R>>endobj
+403 0 obj<</Parent 401 0 R/Title(Compiling the Widget Set under Windows)/Dest[297 0 R/XYZ null 389 null]/Prev 402 0 R>>endobj
+404 0 obj<</Parent 399 0 R/Count -2/First 405 0 R/Last 406 0 R/Title(The File Chooser)/Dest[303 0 R/XYZ null 743 null]/Prev 401 0 R/Next 407 0 R>>endobj
+405 0 obj<</Parent 404 0 R/Title(Implementation)/Dest[303 0 R/XYZ null 660 null]/Next 406 0 R>>endobj
+406 0 obj<</Parent 404 0 R/Title(Using the FileChooser Widget)/Dest[303 0 R/XYZ null 397 null]/Prev 405 0 R>>endobj
+407 0 obj<</Parent 399 0 R/Count -2/First 408 0 R/Last 409 0 R/Title(The Help Dialog)/Dest[309 0 R/XYZ null 743 null]/Prev 404 0 R/Next 410 0 R>>endobj
+408 0 obj<</Parent 407 0 R/Title(Implementation)/Dest[309 0 R/XYZ null 647 null]/Next 409 0 R>>endobj
+409 0 obj<</Parent 407 0 R/Title(Using the HelpDialog Widget)/Dest[309 0 R/XYZ null 569 null]/Prev 408 0 R>>endobj
+410 0 obj<</Parent 399 0 R/Count -2/First 411 0 R/Last 412 0 R/Title(The Help Application \(flsurf\))/Dest[315 0 R/XYZ null 743 null]/Prev 407 0 R/Next 413 0 R>>endobj
+411 0 obj<</Parent 410 0 R/Title(Implementation)/Dest[315 0 R/XYZ null 673 null]/Next 412 0 R>>endobj
+412 0 obj<</Parent 410 0 R/Title(Using the HelpApp Widget)/Dest[315 0 R/XYZ null 556 null]/Prev 411 0 R>>endobj
+413 0 obj<</Parent 399 0 R/Count -9/First 414 0 R/Last 422 0 R/Title(Widgets)/Dest[321 0 R/XYZ null 743 null]/Prev 410 0 R/Next 423 0 R>>endobj
+414 0 obj<</Parent 413 0 R/Title(class CheckButton)/Dest[324 0 R/XYZ null 736 null]/Next 415 0 R>>endobj
+415 0 obj<</Parent 413 0 R/Title(class FileBrowser)/Dest[327 0 R/XYZ null 736 null]/Prev 414 0 R/Next 416 0 R>>endobj
+416 0 obj<</Parent 413 0 R/Title(class FileChooser)/Dest[330 0 R/XYZ null 736 null]/Prev 415 0 R/Next 417 0 R>>endobj
+417 0 obj<</Parent 413 0 R/Title(class FileIcon)/Dest[339 0 R/XYZ null 736 null]/Prev 416 0 R/Next 418 0 R>>endobj
+418 0 obj<</Parent 413 0 R/Title(class FileInput)/Dest[348 0 R/XYZ null 736 null]/Prev 417 0 R/Next 419 0 R>>endobj
+419 0 obj<</Parent 413 0 R/Title(class Fl_Wizard)/Dest[351 0 R/XYZ null 736 null]/Prev 418 0 R/Next 420 0 R>>endobj
+420 0 obj<</Parent 413 0 R/Title(class HelpApp)/Dest[357 0 R/XYZ null 736 null]/Prev 419 0 R/Next 421 0 R>>endobj
+421 0 obj<</Parent 413 0 R/Title(class HelpDialog)/Dest[366 0 R/XYZ null 736 null]/Prev 420 0 R/Next 422 0 R>>endobj
+422 0 obj<</Parent 413 0 R/Title(class HelpView)/Dest[372 0 R/XYZ null 736 null]/Prev 421 0 R>>endobj
+423 0 obj<</Parent 399 0 R/Count -8/First 424 0 R/Last 431 0 R/Title(Release Notes)/Dest[381 0 R/XYZ null 743 null]/Prev 413 0 R>>endobj
+424 0 obj<</Parent 423 0 R/Title(Changes in v2.0)/Dest[381 0 R/XYZ null 694 null]/Next 425 0 R>>endobj
+425 0 obj<</Parent 423 0 R/Title(Changes in HelpView v1.0.1)/Dest[381 0 R/XYZ null 365 null]/Prev 424 0 R/Next 426 0 R>>endobj
+426 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.4.2)/Dest[381 0 R/XYZ null 301 null]/Prev 425 0 R/Next 427 0 R>>endobj
+427 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.4.1)/Dest[381 0 R/XYZ null 184 null]/Prev 426 0 R/Next 428 0 R>>endobj
+428 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.4)/Dest[384 0 R/XYZ null 736 null]/Prev 427 0 R/Next 429 0 R>>endobj
+429 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.3)/Dest[384 0 R/XYZ null 637 null]/Prev 428 0 R/Next 430 0 R>>endobj
+430 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.2)/Dest[384 0 R/XYZ null 520 null]/Prev 429 0 R/Next 431 0 R>>endobj
+431 0 obj<</Parent 423 0 R/Title(Changes in FileChooser v1.1)/Dest[384 0 R/XYZ null 178 null]/Prev 430 0 R>>endobj
+432 0 obj<</Type/Catalog/Pages 290 0 R/Names 159 0 R/PageLayout/SinglePage/Outlines 399 0 R/OpenAction[297 0 R/XYZ null null null]/PageMode/UseOutlines/PageLabels<</Nums[0<</P(title)>>1<</P(eltit)>>2<</S/r>>4<</S/D>>]>>>>endobj
+xref
+0 433
+0000000000 65535 f
+0000000015 00000 n
+0000000216 00000 n
+0000001537 00000 n
+0000001611 00000 n
+0000001690 00000 n
+0000001776 00000 n
+0000001854 00000 n
+0000001931 00000 n
+0000002007 00000 n
+0000002088 00000 n
+0000002147 00000 n
+0000002214 00000 n
+0000002299 00000 n
+0000002323 00000 n
+0000002373 00000 n
+0000002458 00000 n
+0000002482 00000 n
+0000002587 00000 n
+0000002692 00000 n
+0000002796 00000 n
+0000002901 00000 n
+0000003006 00000 n
+0000003110 00000 n
+0000003215 00000 n
+0000003320 00000 n
+0000003425 00000 n
+0000003505 00000 n
+0000003609 00000 n
+0000003713 00000 n
+0000003744 00000 n
+0000003849 00000 n
+0000003954 00000 n
+0000004059 00000 n
+0000004164 00000 n
+0000004269 00000 n
+0000004321 00000 n
+0000004425 00000 n
+0000004529 00000 n
+0000004632 00000 n
+0000004735 00000 n
+0000004839 00000 n
+0000004942 00000 n
+0000005045 00000 n
+0000005148 00000 n
+0000005249 00000 n
+0000005351 00000 n
+0000005452 00000 n
+0000005546 00000 n
+0000005651 00000 n
+0000005756 00000 n
+0000005861 00000 n
+0000005966 00000 n
+0000006071 00000 n
+0000006176 00000 n
+0000006235 00000 n
+0000006340 00000 n
+0000006445 00000 n
+0000006550 00000 n
+0000006655 00000 n
+0000006760 00000 n
+0000006865 00000 n
+0000006970 00000 n
+0000007075 00000 n
+0000007180 00000 n
+0000007285 00000 n
+0000007390 00000 n
+0000007495 00000 n
+0000007600 00000 n
+0000007705 00000 n
+0000007810 00000 n
+0000007915 00000 n
+0000008020 00000 n
+0000008125 00000 n
+0000008230 00000 n
+0000008380 00000 n
+0000008484 00000 n
+0000008588 00000 n
+0000008619 00000 n
+0000008724 00000 n
+0000008829 00000 n
+0000008934 00000 n
+0000009039 00000 n
+0000009144 00000 n
+0000009196 00000 n
+0000009301 00000 n
+0000009349 00000 n
+0000009434 00000 n
+0000009539 00000 n
+0000009644 00000 n
+0000009748 00000 n
+0000009851 00000 n
+0000009954 00000 n
+0000010020 00000 n
+0000010123 00000 n
+0000010227 00000 n
+0000010331 00000 n
+0000010435 00000 n
+0000010538 00000 n
+0000010641 00000 n
+0000010744 00000 n
+0000010811 00000 n
+0000010916 00000 n
+0000010971 00000 n
+0000011057 00000 n
+0000011160 00000 n
+0000011262 00000 n
+0000011364 00000 n
+0000011422 00000 n
+0000011528 00000 n
+0000011634 00000 n
+0000011668 00000 n
+0000011773 00000 n
+0000011878 00000 n
+0000011983 00000 n
+0000012088 00000 n
+0000012192 00000 n
+0000012296 00000 n
+0000012400 00000 n
+0000012505 00000 n
+0000012610 00000 n
+0000012715 00000 n
+0000012819 00000 n
+0000012924 00000 n
+0000013028 00000 n
+0000013150 00000 n
+0000013256 00000 n
+0000013282 00000 n
+0000013387 00000 n
+0000013493 00000 n
+0000013599 00000 n
+0000013704 00000 n
+0000013810 00000 n
+0000013916 00000 n
+0000014021 00000 n
+0000014127 00000 n
+0000014233 00000 n
+0000014338 00000 n
+0000014444 00000 n
+0000014550 00000 n
+0000014655 00000 n
+0000014761 00000 n
+0000014867 00000 n
+0000014973 00000 n
+0000015079 00000 n
+0000015185 00000 n
+0000015291 00000 n
+0000015397 00000 n
+0000015503 00000 n
+0000015609 00000 n
+0000015714 00000 n
+0000015820 00000 n
+0000015926 00000 n
+0000016032 00000 n
+0000016138 00000 n
+0000016244 00000 n
+0000016350 00000 n
+0000016456 00000 n
+0000016562 00000 n
+0000016828 00000 n
+0000016862 00000 n
+0000016896 00000 n
+0000019734 00000 n
+0000019783 00000 n
+0000019832 00000 n
+0000019881 00000 n
+0000019930 00000 n
+0000019979 00000 n
+0000020028 00000 n
+0000020077 00000 n
+0000020126 00000 n
+0000020175 00000 n
+0000020224 00000 n
+0000020273 00000 n
+0000020322 00000 n
+0000020371 00000 n
+0000020420 00000 n
+0000020469 00000 n
+0000020518 00000 n
+0000020567 00000 n
+0000020616 00000 n
+0000020665 00000 n
+0000020714 00000 n
+0000020763 00000 n
+0000020812 00000 n
+0000020861 00000 n
+0000020910 00000 n
+0000020959 00000 n
+0000021008 00000 n
+0000021057 00000 n
+0000021106 00000 n
+0000021155 00000 n
+0000021204 00000 n
+0000021253 00000 n
+0000021302 00000 n
+0000021351 00000 n
+0000021400 00000 n
+0000021449 00000 n
+0000021498 00000 n
+0000021547 00000 n
+0000021596 00000 n
+0000021645 00000 n
+0000021694 00000 n
+0000021743 00000 n
+0000021792 00000 n
+0000021841 00000 n
+0000021890 00000 n
+0000021939 00000 n
+0000021988 00000 n
+0000022037 00000 n
+0000022085 00000 n
+0000022134 00000 n
+0000022183 00000 n
+0000022232 00000 n
+0000022281 00000 n
+0000022330 00000 n
+0000022379 00000 n
+0000022428 00000 n
+0000022477 00000 n
+0000022526 00000 n
+0000022575 00000 n
+0000022624 00000 n
+0000022673 00000 n
+0000022722 00000 n
+0000022771 00000 n
+0000022820 00000 n
+0000022869 00000 n
+0000022918 00000 n
+0000022967 00000 n
+0000023016 00000 n
+0000023064 00000 n
+0000023113 00000 n
+0000023162 00000 n
+0000023211 00000 n
+0000023260 00000 n
+0000023309 00000 n
+0000023358 00000 n
+0000023407 00000 n
+0000023456 00000 n
+0000023505 00000 n
+0000023554 00000 n
+0000023603 00000 n
+0000023652 00000 n
+0000023701 00000 n
+0000023750 00000 n
+0000023799 00000 n
+0000023848 00000 n
+0000023897 00000 n
+0000023946 00000 n
+0000023995 00000 n
+0000024044 00000 n
+0000024093 00000 n
+0000024141 00000 n
+0000024190 00000 n
+0000024239 00000 n
+0000024288 00000 n
+0000024337 00000 n
+0000024386 00000 n
+0000024435 00000 n
+0000024484 00000 n
+0000024533 00000 n
+0000024582 00000 n
+0000024631 00000 n
+0000024680 00000 n
+0000024729 00000 n
+0000024778 00000 n
+0000024827 00000 n
+0000024876 00000 n
+0000024925 00000 n
+0000024974 00000 n
+0000025023 00000 n
+0000025072 00000 n
+0000025121 00000 n
+0000025170 00000 n
+0000025219 00000 n
+0000025268 00000 n
+0000025317 00000 n
+0000025366 00000 n
+0000025415 00000 n
+0000025464 00000 n
+0000025513 00000 n
+0000025562 00000 n
+0000025611 00000 n
+0000025660 00000 n
+0000025709 00000 n
+0000025758 00000 n
+0000025807 00000 n
+0000025856 00000 n
+0000025905 00000 n
+0000025953 00000 n
+0000026002 00000 n
+0000026359 00000 n
+0000026490 00000 n
+0000026719 00000 n
+0000026740 00000 n
+0000026835 00000 n
+0000026937 00000 n
+0000026957 00000 n
+0000027129 00000 n
+0000028048 00000 n
+0000028069 00000 n
+0000028182 00000 n
+0000028363 00000 n
+0000028384 00000 n
+0000028534 00000 n
+0000029674 00000 n
+0000029696 00000 n
+0000029809 00000 n
+0000029994 00000 n
+0000030015 00000 n
+0000030155 00000 n
+0000030789 00000 n
+0000030810 00000 n
+0000030923 00000 n
+0000031107 00000 n
+0000031128 00000 n
+0000031282 00000 n
+0000032127 00000 n
+0000032148 00000 n
+0000032261 00000 n
+0000032461 00000 n
+0000032482 00000 n
+0000032646 00000 n
+0000033574 00000 n
+0000033595 00000 n
+0000033768 00000 n
+0000034434 00000 n
+0000034455 00000 n
+0000034628 00000 n
+0000035534 00000 n
+0000035555 00000 n
+0000035749 00000 n
+0000043124 00000 n
+0000043146 00000 n
+0000043310 00000 n
+0000044337 00000 n
+0000044358 00000 n
+0000044498 00000 n
+0000045093 00000 n
+0000045114 00000 n
+0000045287 00000 n
+0000046244 00000 n
+0000046265 00000 n
+0000046405 00000 n
+0000047254 00000 n
+0000047275 00000 n
+0000047425 00000 n
+0000047998 00000 n
+0000048019 00000 n
+0000048192 00000 n
+0000048946 00000 n
+0000048967 00000 n
+0000049140 00000 n
+0000050108 00000 n
+0000050129 00000 n
+0000050260 00000 n
+0000050530 00000 n
+0000050551 00000 n
+0000050745 00000 n
+0000055500 00000 n
+0000055522 00000 n
+0000055687 00000 n
+0000056489 00000 n
+0000056510 00000 n
+0000056650 00000 n
+0000056963 00000 n
+0000056984 00000 n
+0000057179 00000 n
+0000065228 00000 n
+0000065250 00000 n
+0000065415 00000 n
+0000066044 00000 n
+0000066065 00000 n
+0000066239 00000 n
+0000067253 00000 n
+0000067274 00000 n
+0000067429 00000 n
+0000068330 00000 n
+0000068351 00000 n
+0000068464 00000 n
+0000068648 00000 n
+0000068669 00000 n
+0000068828 00000 n
+0000070060 00000 n
+0000070082 00000 n
+0000070232 00000 n
+0000071647 00000 n
+0000071669 00000 n
+0000071801 00000 n
+0000072120 00000 n
+0000072141 00000 n
+0000072254 00000 n
+0000072449 00000 n
+0000072470 00000 n
+0000072625 00000 n
+0000074443 00000 n
+0000074465 00000 n
+0000074578 00000 n
+0000074738 00000 n
+0000074758 00000 n
+0000074813 00000 n
+0000074918 00000 n
+0000075067 00000 n
+0000075190 00000 n
+0000075316 00000 n
+0000075469 00000 n
+0000075571 00000 n
+0000075687 00000 n
+0000075839 00000 n
+0000075941 00000 n
+0000076056 00000 n
+0000076224 00000 n
+0000076326 00000 n
+0000076438 00000 n
+0000076582 00000 n
+0000076687 00000 n
+0000076805 00000 n
+0000076923 00000 n
+0000077038 00000 n
+0000077154 00000 n
+0000077270 00000 n
+0000077384 00000 n
+0000077501 00000 n
+0000077603 00000 n
+0000077740 00000 n
+0000077843 00000 n
+0000077970 00000 n
+0000078100 00000 n
+0000078230 00000 n
+0000078358 00000 n
+0000078486 00000 n
+0000078614 00000 n
+0000078729 00000 n
+trailer
+<</Size 433/Root 432 0 R/Info 1 0 R>>
+startxref
+78957
+%%EOF
diff --git a/SrcUnix/espws-2.0/file.html b/SrcUnix/espws-2.0/file.html
new file mode 100644
index 0000000..4cc3c08
--- /dev/null
+++ b/SrcUnix/espws-2.0/file.html
@@ -0,0 +1,76 @@
+<HTML>
+<HEAD>
+ <TITLE>The File Chooser - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>The File Chooser</H1>
+
+<P>The <CODE>FileChooser</CODE> widget provides a standard file selection
+dialog for your applications. It supports three different selection modes -
+single file selection, multiple file selection, and new file selection (for
+use in "save as" situations).
+
+<H2>Implementation</H2>
+
+<P>The <CODE>FileChooser</CODE> widget is based upon four classes:
+
+<UL>
+
+ <LI><CODE>FileBrowser</CODE> - this is a subclass of
+ <CODE>Fl_Browser</CODE> that lists files in a specified directory or
+ all drives/mount points on a system.
+
+ <LI><CODE>FileChooser</CODE> - this is the high-level class that
+ provides the dialog window and controls.
+
+ <LI><CODE>FileIcon</CODE> - this class provides icon images for
+ the <CODE>FileBrowser</CODE> widget and associates
+ filetypes/extensions with those icon images. The current code
+ understands SGI ".fti" files used under IRIX and ".xpm" files
+ used by CDE.
+
+ <LI><CODE>FileInput</CODE> - this is a subclass of
+ <CODE>Fl_Input</CODE> that remaps the Tab key. The new mapping
+ allows a user to move the cursor to the end of the current
+ selection using the Tab key (i.e. to accept filename
+ completion), but if there is no selection the Tab key performs
+ navigation instead.
+
+</UL>
+
+<P>The <CODE>FileIcon</CODE> class allows you to add icons for
+individual file types. Normally you'll just use the
+<CODE>FileIcon::load_system_icons()</CODE> method to load icons
+specific to your system; if the system icons can't be loaded
+then generic file and folder icons are used instead. Icons are
+only shown if you have loaded them.
+
+<H2>Using the FileChooser Widget</H2>
+
+<P>To use the <CODE>FileChooser</CODE> widget in your program, do:
+
+<UL><PRE>
+#include "FileChooser.h"
+
+...
+
+{
+ FileIcon::load_system_icons(); // Optional...
+
+ FileChooser fc("pathname", "*.pattern", type, "title");
+
+ fc.show();
+ while (fc.visible())
+ Fl::wait();
+
+ fc.count() = number of selected files
+ fc.value() = value of first (or only) selected file
+ fc.value(n) = value of selection "n"
+}
+</PRE></UL>
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/flsurf.cxx b/SrcUnix/espws-2.0/flsurf.cxx
new file mode 100644
index 0000000..de7c9ac
--- /dev/null
+++ b/SrcUnix/espws-2.0/flsurf.cxx
@@ -0,0 +1,67 @@
+//
+// "$Id: flsurf.cxx,v 1.2 2000/01/24 01:27:21 mike Exp $"
+//
+// flsurf program.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outblockd in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// main() - Display the help GUI...
+//
+
+//
+// Include necessary headers...
+//
+
+#include "HelpApp.h"
+#include <FL/x.H>
+
+
+//
+// 'main()' - Display the help GUI...
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ HelpApp *app; // Help application
+
+
+ fl_open_display();
+
+ app = new HelpApp;
+
+ if (argc >= 2)
+ app->load(argv[1]);
+
+ app->show();
+
+ Fl::run();
+
+ delete app;
+
+ return (0);
+}
+
+
+//
+// End of "$Id: flsurf.cxx,v 1.2 2000/01/24 01:27:21 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/flsurf.gif b/SrcUnix/espws-2.0/flsurf.gif
new file mode 100644
index 0000000..ab586e9
--- /dev/null
+++ b/SrcUnix/espws-2.0/flsurf.gif
Binary files differ
diff --git a/SrcUnix/espws-2.0/flsurf.html b/SrcUnix/espws-2.0/flsurf.html
new file mode 100644
index 0000000..4796df5
--- /dev/null
+++ b/SrcUnix/espws-2.0/flsurf.html
@@ -0,0 +1,66 @@
+<HTML>
+<HEAD>
+ <TITLE>The Help Application (flsurf) - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORD="20,19,74,36" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORD="96,19,240,36" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORD="262,19,356,36" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORD="378,19,416,36" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORD="438,19,487,36" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>The Help Application (flsurf)</H1>
+
+<P>The <CODE>HelpApp</CODE> widget provides a simple web browser application,
+complete with bookmarks, proxy support, and so forth. The <CODE>flsurf</CODE>
+application included with the distribution demonstrates how to use it.
+
+<H2>Implementation</H2>
+
+<P>The <CODE>HelpApp</CODE> widget is composed of several windows and control
+widgets. The HTML viewing portion is handled by the <CODE>HelpView</CODE>
+widget, while file selection is handled by the <CODE>FileChooser</CODE>
+widget.
+
+<P>HTTP access to files is handled by the <A HREF="http://www.cups.org">CUPS</A>
+HTTP functions. Currently only a single file is cached, so any navigation
+results in a reload.
+
+<H2>Using the HelpApp Widget</H2>
+
+<P>The source for <CODE>flsurf</CODE> is shown below:
+
+<UL><PRE>
+#include "HelpApp.h"
+#include &lt;FL/x.H>
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ HelpApp *app; // Help application
+
+
+ fl_open_display();
+
+ app = new HelpApp;
+
+ if (argc >= 2)
+ app->load(argv[1]);
+
+ app->show();
+
+ Fl::run();
+
+ delete app;
+
+ return (0);
+}
+</PRE></UL>
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/fltk.css b/SrcUnix/espws-2.0/fltk.css
new file mode 100644
index 0000000..b8ee428
--- /dev/null
+++ b/SrcUnix/espws-2.0/fltk.css
@@ -0,0 +1,6 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
diff --git a/SrcUnix/espws-2.0/help.html b/SrcUnix/espws-2.0/help.html
new file mode 100644
index 0000000..1c844ed
--- /dev/null
+++ b/SrcUnix/espws-2.0/help.html
@@ -0,0 +1,44 @@
+<HTML>
+<HEAD>
+ <TITLE>The Help Dialog - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>The Help Dialog</H1>
+
+<P>The <CODE>HelpDialog</CODE> widget displays HTML files and allows the
+user to click on links to do navigation. Currently most HTML 2.0 elements
+are supported except for images. Table support is primitive at best.
+
+<P>Even so, it provides enough capabilities to be used for on-line help and
+other HTML applications.
+
+<H2>Implementation</H2>
+
+<P>The <CODE>HelpDialog</CODE> widget combines a dialog window, history buttons,
+text size buttons, and the <CODE>HelpView</CODE> widget to provide an embedded
+HTML file viewing dialog.
+
+<H2>Using the HelpDialog Widget</H2>
+
+<P>To use the <CODE>HelpDialog</CODE> widget in your program, do:
+
+<UL><PRE>
+#include "HelpDialog.h"
+
+...
+
+{
+ HelpDialog help();
+
+ help.load("filename.html");
+ help.show();
+ while (help.visible())
+ Fl::wait();
+}
+</PRE></UL>
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/home.xbm b/SrcUnix/espws-2.0/home.xbm
new file mode 100644
index 0000000..f8ade7c
--- /dev/null
+++ b/SrcUnix/espws-2.0/home.xbm
@@ -0,0 +1,6 @@
+#define home_width 16
+#define home_height 16
+static unsigned char home_bits[] = {
+ 0x80, 0x01, 0x40, 0x3a, 0x20, 0x2c, 0x10, 0x28, 0x08, 0x30, 0x04, 0x20,
+ 0x06, 0x60, 0x05, 0xa0, 0x74, 0x2f, 0x54, 0x29, 0x54, 0x29, 0x74, 0x29,
+ 0x04, 0x2b, 0x04, 0x29, 0x04, 0x29, 0xfc, 0x3f};
diff --git a/SrcUnix/espws-2.0/index.html b/SrcUnix/espws-2.0/index.html
new file mode 100644
index 0000000..d0946b3
--- /dev/null
+++ b/SrcUnix/espws-2.0/index.html
@@ -0,0 +1,57 @@
+<HTML>
+<HEAD>
+ <TITLE>Home Page - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,51,21" HREF="http://www.easysw.com" ALT="ESP Home Page">
+ <AREA SHAPE="RECT" COORDS="82,8,128,21" HREF="index.html" ALT="Widget Set Home Page">
+ <AREA SHAPE="RECT" COORDS="150,8,269,21" HREF="documentation.html" ALT="Widget Set Documentation">
+ <AREA SHAPE="RECT" COORDS="291,8,369,21" HREF="download.html" ALT="Download Widget Set">
+ <AREA SHAPE="RECT" COORDS="391,8,434,21" HREF="http://www.fltk.org" ALT="FLTK Home Page">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<P ALIGN="CENTER">
+<IMG SRC="navbar.gif" WIDTH="449" HEIGHT="30" BORDER="0" ISMAP USEMAP="#navbar">
+<BR>
+<A HREF="http://www.easysw.com">ESP</A> |
+<A HREF="index.html">Home</A> |
+<A HREF="documentation.html">Documentation</A> |
+<A HREF="download.html">Download</A> |
+<A HREF="http://www.fltk.org">FLTK</A>
+</P>
+
+<H1 ALIGN="CENTER">ESP Widget Set for FLTK</H1>
+
+The ESP Widget Set for FLTK provides check button, file
+chooser, help viewer, and wizard widgets for FLTK. These widgets are
+provided under the terms of the
+<A HREF="http://www.fsf.org/copyleft/gpl.html"> GNU General Public
+License</A>.
+<P>
+<TABLE WIDTH="100%" CELLSPACING="0" CELLPADDING="0">
+<TR>
+ <TD VALIGN="TOP"><A HREF="flsurf.html">
+ <IMG SRC="flsurf.gif" WIDTH="276" HEIGHT="196" BORDER="0" ALT="flsurf application"></A>
+ </TD>
+ <TD>&nbsp;</TD>
+ <TD VALIGN="TOP"><H2>News</H2>
+ <P><B>March 19, 2000</B>
+ <P>FileChooser and HelpDialog distributions merged into new
+ ESP Widget Set 2.0 distribution. The new distribution includes
+ "flsurf" (shown at left), a simple web browser for FLTK using the
+ HelpApp widget.
+ </TD>
+</TR>
+</TABLE>
+
+<HR>
+
+<P>Copyright 1997-2000 by Easy Software Products. This software is provided
+under the terms of the <A HREF="http://www.fsf.org/copyleft/gpl.html">
+GNU General Public License</A>.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/intro.html b/SrcUnix/espws-2.0/intro.html
new file mode 100644
index 0000000..f07f9c1
--- /dev/null
+++ b/SrcUnix/espws-2.0/intro.html
@@ -0,0 +1,57 @@
+<HTML>
+<HEAD>
+ <TITLE>ESP Widget Set for FLTK</TITLE>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2000">
+ <META NAME="AUTHOR" CONTENT="Easy Software Products">
+ <META NAME="DOCNUMBER" CONTENT="ESPWS-2.0">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>Introduction</H1>
+
+<P>The ESP Widget Set for FLTK provides check button, file
+chooser, help viewer, and wizard widgets for FLTK. These widgets are
+provided under the terms of the
+<A HREF="http://www.fsf.org/copyleft/gpl.html">GNU General Public
+License</A>.
+
+<P>The widget set comes with a configure script for UNIX systems and
+Visual C++ workspace and project files for Windows systems.
+
+<H2>Compiling the Widget Set under UNIX</H2>
+
+<P>First you must configure the makefile for use on your system; in most
+cases you just need to do:
+
+<UL><PRE>
+% <KBD>./configure <I>ENTER</I></KBD>
+</PRE></UL>
+
+<P>If the configure script is unable to determine what C and C++ compilers
+to use, set the <CODE>CC</CODE> and <CODE>CXX</CODE> environment variables
+to the corresponding program.
+
+<P>The <CODE>CFLAGS</CODE>, <CODE>CXXFLAGS</CODE>, and <CODE>LDFLAGS</CODE>
+environment variables can also be set to tell the compilers and linker
+where to find include files and libraries.
+
+<P>Once you have successfully configured the makefile, just type:
+
+<UL><PRE>
+% <KBD>make <I>ENTER</I></KBD>
+</PRE></UL>
+
+<P>to build the widget set and all the examples.
+
+<H2>Compiling the Widget Set under Windows</H2>
+
+<P>The Visual C++ project file was created using Visual C++ 6.0. We do not
+recommend using older versions of Visual C++.
+
+<P>To build the widget set and all the examples, open the "espws" workspace
+and do a batch build.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/navbar.gif b/SrcUnix/espws-2.0/navbar.gif
new file mode 100644
index 0000000..c655003
--- /dev/null
+++ b/SrcUnix/espws-2.0/navbar.gif
Binary files differ
diff --git a/SrcUnix/espws-2.0/new.xbm b/SrcUnix/espws-2.0/new.xbm
new file mode 100644
index 0000000..25a56c5
--- /dev/null
+++ b/SrcUnix/espws-2.0/new.xbm
@@ -0,0 +1,6 @@
+#define new_width 16
+#define new_height 16
+static unsigned char new_bits[] = {
+ 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x01, 0xfe, 0x01, 0x80,
+ 0x31, 0x80, 0x31, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00};
diff --git a/SrcUnix/espws-2.0/next.xbm b/SrcUnix/espws-2.0/next.xbm
new file mode 100644
index 0000000..753be4a
--- /dev/null
+++ b/SrcUnix/espws-2.0/next.xbm
@@ -0,0 +1,12 @@
+#define next_width 42
+#define next_height 16
+static unsigned char next_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x02, 0x00, 0x00, 0x04, 0x00, 0x14, 0x02, 0x00, 0x08, 0x0c, 0x00,
+ 0x14, 0x02, 0x00, 0x08, 0x1c, 0x00, 0x24, 0xe2, 0x19, 0x1f, 0x3c, 0x00,
+ 0x24, 0x32, 0x13, 0x09, 0x7c, 0x00, 0x44, 0x12, 0xa2, 0x08, 0xfc, 0x00,
+ 0x44, 0xf2, 0x43, 0x08, 0xfc, 0x00, 0x84, 0x12, 0x40, 0x08, 0x7c, 0x00,
+ 0x84, 0x12, 0xa0, 0x08, 0x3c, 0x00, 0x04, 0x33, 0x13, 0x09, 0x1c, 0x00,
+ 0x04, 0xe3, 0x19, 0x33, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
diff --git a/SrcUnix/espws-2.0/prev.xbm b/SrcUnix/espws-2.0/prev.xbm
new file mode 100644
index 0000000..f66fda6
--- /dev/null
+++ b/SrcUnix/espws-2.0/prev.xbm
@@ -0,0 +1,12 @@
+#define prev_width 42
+#define prev_height 16
+static unsigned char prev_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0xf8, 0x01, 0x00, 0x08, 0x00, 0x60, 0x08, 0x03, 0x00, 0x08, 0x00,
+ 0x70, 0x08, 0x02, 0x00, 0x08, 0x00, 0x78, 0x08, 0xe2, 0xe1, 0x89, 0x00,
+ 0x7c, 0x08, 0x31, 0x33, 0x4b, 0x00, 0x7e, 0xf8, 0x00, 0x12, 0x28, 0x00,
+ 0x7e, 0x08, 0xe1, 0x13, 0x18, 0x00, 0x7c, 0x08, 0x32, 0x12, 0x28, 0x00,
+ 0x78, 0x08, 0x12, 0x12, 0x4a, 0x00, 0x70, 0x08, 0x33, 0x33, 0x8b, 0x00,
+ 0x60, 0xf8, 0xe1, 0xe6, 0x09, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
diff --git a/SrcUnix/espws-2.0/relnotes.html b/SrcUnix/espws-2.0/relnotes.html
new file mode 100644
index 0000000..555e213
--- /dev/null
+++ b/SrcUnix/espws-2.0/relnotes.html
@@ -0,0 +1,209 @@
+<HTML>
+<HEAD>
+ <TITLE>Release Notes - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>Release Notes</H1>
+
+<H2>Changes in v2.0</A></H2>
+
+<UL>
+
+ <LI><B>Merged FileChooser and HelpDialog distributions</B>
+
+ <LI>Got rid of several compiler warnings (converting from float to int).
+
+ <LI>Open files in binary mode (workaround for MSVC++ C library
+ problems)
+
+ <LI>Fixed scrollbar problems.
+
+ <LI>Fixed <CODE>HR</CODE> problems (wasn't adding x() and y() offset.)
+
+ <LI>New <CODE>h()</CODE>, <CODE>position()</CODE>, <CODE>resize()</CODE>,
+ <CODE>w()</CODE>, <CODE>x()</CODE>, and <CODE>y()</CODE> methods to
+ control help dialog window.
+
+ <LI>New <CODE>link()</CODE> callback method - allows you to support
+ loading of data from other locations.
+
+ <LI>New <CODE>textcolor()</CODE> methods to control default text
+ color.
+
+ <LI>Now support <CODE>TABLE</CODE> border and width attributes.
+
+ <LI>Now support <CODE>BODY</CODE> color attributes.
+
+ <LI>Now support horizontal alignment.
+
+ <LI>Now support table background colors.
+
+ <LI>New <CODE>flsurf</CODE> application that supports limited web
+ browsing, etc. (web browsing requires CUPS library)
+
+ <LI>F_OK wasn't defined under Windows.
+
+ <LI>FileIcon::load() didn't check the filename extension
+ properly - it was missing the ".".
+
+ <LI>FileIcon::load_xpm() needed to use a case-insensitive
+ comparison for color names.
+
+ <LI>The KDE load_kde_mimelnk() function had the fopen()
+ check backwards.
+
+ <LI>Some of the old FTI code still used NULL for the
+ outline index, but GCC 2.95 didn't like that.
+
+ <LI>Added support for column_widths() and column_char()
+ methods from the Fl_Browser widget.
+
+ <LI>OS/2 fixes from Alexander Mai.
+
+</UL>
+
+<H2>Changes in HelpView v1.0.1</H2>
+
+<UL>
+
+ <LI>Now include a makefile and configure script.
+
+</UL>
+
+<H2>Changes in FileChooser v1.4.2</H2>
+
+<UL>
+
+ <LI>FileBrowser::load() didn't handle unreadable directories.
+
+ <LI>FileIcon::load_fti() could store the outline color in freed
+ memory.
+
+ <LI>FileIcon::load_system_icons() now uses default icons that
+ look like Microsoft Windows icons.
+
+ <LI>FileIcon::load_system_icons() now supports GNOME and KDE
+ icons.
+
+ <LI>FileIcon::draw() now accepts an "active" flag so that
+ inactive controls are drawn with inactive icons.
+
+</UL>
+
+<H2>Changes in FileChooser v1.4.1</H2>
+
+<UL>
+
+ <LI>Now include a makefile and configure script.
+
+ <LI>Added missing XBM icon files.
+
+</UL>
+
+<H2>Changes in FileChooser v1.4</H2>
+
+<UL>
+
+ <LI>Now provided under the LGPL.
+
+ <LI>Pressing the Cancel button, hitting escape, or closing the
+ dialog window clears the FileChooser value.
+
+ <LI>The FileIcon class now loads icons for CDE and the IRIX
+ Interactive Desktop (auto-detect at run-time.) Support for
+ GNOME, KDE, and Windows is in the works.
+
+ <LI>The FileIcon class now provides a <CODE>label()</CODE> method
+ for using icons as labels for widgets.
+
+</UL>
+
+<H2>Changes in FileChooser v1.3</H2>
+
+<UL>
+
+ <LI>Added new <CODE>FileInput</CODE> widget (world's shortest
+ widget! :) so that filename completion can be done with the
+ Tab, End, or right arrow key.
+
+ <LI>The <CODE>FileChooser</CODE> widget now uses the
+ <CODE>FileInput</CODE> widget instead of <CODE>Fl_Input</CODE>.
+
+ <LI>The text selection in the filename field now puts the cursor
+ at the end of the selection (unless you type the Backspace key.)
+
+</UL>
+
+<H2>Changes in FileChooser v1.2</H2>
+
+<UL>
+
+ <LI>Fixed VC++ compile problems.
+
+ <LI>Filename completion now scrolls the file list to the first matching
+ file and selects it when it matches exactly.
+
+ <LI>The <code>value()</code> method incorrectly reset the chooser
+ type to <code>FileChooser::SINGLE</code> when the type was
+ <code>FileChooser::CREATE</code>.
+
+ <LI>The <code>value()</code> method didn't handle directories without
+ filenames properly (always showed drives/file systems).
+
+ <LI>The "new directory" button is now only activated when the
+ chooser type is <code>FileChooser::CREATE</code>.
+
+ <LI>The "OK" button is now disabled until a filename is selected or
+ entered on the keyboard.
+
+ <LI>Previously the chooser would only beep at the user when a non-
+ existing filename was entered for <code>SINGLE</code> and
+ <code>MULTI</code> type choosers. It now also pops up an alert
+ dialog with the text, "Please choose an existing file!"
+
+ <LI>Added <code>iconsize()</code>, <code>textcolor()</code>,
+ <code>textfont()</code>, and <code>textsize()</code> methods to
+ the <code>FileChooser</code> class.
+
+ <LI>The chooser no longer loads any icons by default; call the
+ new <code>load_system_icons()</code> method in the
+ <code>FileIcon</code> class to get the icons.
+
+ <LI>The <code>FileBrowser</code> widget now has <code>iconsize()</code>
+ methods to control the size of the icons separately from the text font.
+
+ <LI>The <code>FileBrowser</code> widget now supports tabs and newlines
+ in the item string.
+
+ <LI>Added <code>iconsize</code>, <code>textcolor</code>,
+ <code>textfont</code>, and <code>textsize</code> methods to the
+ <code>FileChooser</code> class.
+
+</UL>
+
+<H2>Changes in FileChooser v1.1</H2>
+
+<UL>
+
+ <LI>The <code>FileChooser::value()</code> method now has a default
+ argument of 1.
+
+ <LI>Changed the <code>multi</code> methods and arguments to
+ <code>type</code> so that the chooser can limit selection to existing
+ files if necessary.
+
+ <LI>Added a <code>FileChooser::value(pathname)</code> method to
+ set the current selection and/or directory.
+
+ <LI>The file completion code now handles directory navigation when
+ you press "/".
+
+ <LI>The filename field now gets the full width of the window.
+
+</UL>
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws-2.0/reload.xbm b/SrcUnix/espws-2.0/reload.xbm
new file mode 100644
index 0000000..587b530
--- /dev/null
+++ b/SrcUnix/espws-2.0/reload.xbm
@@ -0,0 +1,6 @@
+#define reload_width 16
+#define reload_height 16
+static unsigned char reload_bits[] = {
+ 0x00, 0x00, 0xe0, 0x07, 0xf0, 0x0f, 0x38, 0x1c, 0x18, 0x38, 0x00, 0x70,
+ 0x00, 0xf8, 0x04, 0x70, 0x0e, 0x20, 0x1f, 0x00, 0x0e, 0x00, 0x1c, 0x18,
+ 0x38, 0x1c, 0xf0, 0x0f, 0xe0, 0x07, 0x00, 0x00};
diff --git a/SrcUnix/espws-2.0/reset.xbm b/SrcUnix/espws-2.0/reset.xbm
new file mode 100644
index 0000000..7335374
--- /dev/null
+++ b/SrcUnix/espws-2.0/reset.xbm
@@ -0,0 +1,4 @@
+#define reset_width 8
+#define reset_height 8
+static unsigned char reset_bits[] = {
+ 0xff, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0x81, 0xff};
diff --git a/SrcUnix/espws-2.0/stop.xbm b/SrcUnix/espws-2.0/stop.xbm
new file mode 100644
index 0000000..8ae52fe
--- /dev/null
+++ b/SrcUnix/espws-2.0/stop.xbm
@@ -0,0 +1,6 @@
+#define stop_width 16
+#define stop_height 16
+static unsigned char stop_bits[] = {
+ 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, 0xff,
+ 0x89, 0xcd, 0xdd, 0xaa, 0xd9, 0xca, 0xdb, 0xea, 0xd9, 0xed, 0xff, 0x7f,
+ 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x07};
diff --git a/SrcUnix/espws-2.0/testfile.cxx b/SrcUnix/espws-2.0/testfile.cxx
new file mode 100644
index 0000000..c8f56bb
--- /dev/null
+++ b/SrcUnix/espws-2.0/testfile.cxx
@@ -0,0 +1,141 @@
+//
+// "$Id: testfile.cxx,v 1.6 2000/01/04 13:45:55 mike Exp $"
+//
+// File chooser test program.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// main() - Create a file chooser and wait for a selection to be
+// made.
+// close_callback() - Close the main window...
+// show_callback() - Show the file chooser...
+//
+
+//
+// Include necessary headers...
+//
+
+#include <stdio.h>
+#include "FileChooser.h"
+
+
+//
+// Globals...
+//
+
+Fl_Input *filter;
+FileChooser *fc;
+
+
+//
+// Functions...
+//
+
+void close_callback(void);
+void show_callback(void);
+
+
+//
+// 'main()' - Create a file chooser and wait for a selection to be made.
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ Fl_Window *window;// Main window
+ Fl_Button *button;// Buttons
+ FileIcon *icon; // New file icon
+
+
+ // Make the file chooser...
+ FileIcon::load_system_icons();
+
+ fc = new FileChooser(".", "*", FileChooser::MULTI, "FileChooser Test");
+ fc->color((Fl_Color)196);
+
+ // Make the main window...
+ window = new Fl_Window(400, 80, "File Chooser Test");
+
+ filter = new Fl_Input(50, 10, 315, 25, "Filter:");
+ if (argc > 1)
+ filter->value(argv[1]);
+
+ button = new Fl_Button(365, 10, 25, 25);
+ button->labelcolor(FL_YELLOW);
+ button->callback((Fl_Callback *)show_callback);
+
+ icon = FileIcon::find(".", FileIcon::DIRECTORY);
+ icon->label(button);
+
+ button = new Fl_Button(340, 45, 50, 25, "Close");
+ button->callback((Fl_Callback *)close_callback);
+
+ window->end();
+ window->show();
+
+ Fl::run();
+
+ return (0);
+}
+
+
+//
+// 'close_callback()' - Close the main window...
+//
+
+void
+close_callback(void)
+{
+ exit(0);
+}
+
+
+//
+// 'show_callback()' - Show the file chooser...
+//
+
+void
+show_callback(void)
+{
+ int i; // Looping var
+ int count; // Number of files selected
+
+
+ fc->show();
+ if (filter->value()[0])
+ fc->filter(filter->value());
+
+ fc->show();
+
+ while (fc->visible())
+ Fl::wait();
+
+ count = fc->count();
+ printf("count = %d\n", count);
+ for (i = 1; i <= count; i ++)
+ printf("file %d = \"%s\"\n", i, fc->value(i));
+}
+
+
+//
+// End of "$Id: testfile.cxx,v 1.6 2000/01/04 13:45:55 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/testhelp.cxx b/SrcUnix/espws-2.0/testhelp.cxx
new file mode 100644
index 0000000..ed0ff35
--- /dev/null
+++ b/SrcUnix/espws-2.0/testhelp.cxx
@@ -0,0 +1,66 @@
+//
+// "$Id: testhelp.cxx,v 1.3 2000/01/04 13:45:56 mike Exp $"
+//
+// Help test program.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outblockd in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// main() - Display the help GUI...
+//
+
+//
+// Include necessary headers...
+//
+
+#include "HelpDialog.h"
+
+
+//
+// 'main()' - Display the help GUI...
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line arguments
+ char *argv[]) // I - Command-line arguments
+{
+ HelpDialog *help; // Help dialog
+
+
+ help = new HelpDialog;
+
+ if (argc < 2)
+ help->load("HelpDialog.html");
+ else
+ help->load(argv[1]);
+
+ help->show();
+
+ Fl::run();
+
+ delete help;
+
+ return (0);
+}
+
+
+//
+// End of "$Id: testhelp.cxx,v 1.3 2000/01/04 13:45:56 mike Exp $".
+//
diff --git a/SrcUnix/espws-2.0/up.xbm b/SrcUnix/espws-2.0/up.xbm
new file mode 100644
index 0000000..1a4f4b7
--- /dev/null
+++ b/SrcUnix/espws-2.0/up.xbm
@@ -0,0 +1,6 @@
+#define up_width 16
+#define up_height 16
+static unsigned char up_bits[] = {
+ 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x31, 0xfe, 0x79, 0x80,
+ 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00};
diff --git a/SrcUnix/espws-2.0/widgets.html b/SrcUnix/espws-2.0/widgets.html
new file mode 100644
index 0000000..bf6fc48
--- /dev/null
+++ b/SrcUnix/espws-2.0/widgets.html
@@ -0,0 +1,61 @@
+<HTML>
+<HEAD>
+ <TITLE>Widgets - ESP Widget Set for FLTK</TITLE>
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="fltk.css">
+</HEAD>
+
+<BODY BGCOLOR="#ccccff">
+
+<H1>Widgets</H1>
+
+<P>The widget set includes several base and composite widgets. The base widgets
+include:
+
+<UL>
+
+ <LI><A HREF="CheckButton.html"><CODE>CheckButton</CODE></A>, a
+ better looking check/radio button.
+
+ <LI><A HREF="FileBrowser.html"><CODE>FileBrowser</CODE></A>, a
+ browser widget that supports file icons.
+
+ <LI><A HREF="FileIcon.html"><CODE>FileIcon</CODE></A>, a class
+ for managing and drawing file icons.
+
+ <LI><A HREF="Fl_Wizard.html"><CODE>Fl_Wizard</CODE></A>, an
+ adaptation of the <CODE>Fl_Tabs</CODE> widget for "wizard"
+ interfaces.
+
+ <LI><A HREF="HelpView.html"><CODE>HelpView</CODE></A>, a simple
+ HTML viewing widget.
+
+</UL>
+
+<P>Technically, the <CODE>FileIcon</CODE> class is not a FLTK widget,
+however it does provide a <CODE>label()</CODE> method for widgets,
+much like <CODE>Fl_Pixmap</CODE>.
+
+<P>The composite widgets include:
+
+<UL>
+
+ <LI><A HREF="FileChooser.html"><CODE>FileChooser</CODE></A>, a
+ complete file chooser dialog using the <CODE>FileBrowser</CODE>,
+ <CODE>FileIcon</CODE>, and <CODE>FileInput</CODE> widgets.
+
+ <LI><A HREF="HelpDialog.html"><CODE>HelpDialog</CODE></A>, a
+ complete help dialog using the <CODE>HelpView</CODE> widget.
+
+ <LI><A HREF="HelpApp.html"><CODE>HelpApp</CODE></A>, a
+ simple web browser using the <CODE>FileChooser</CODE> and
+ <CODE>HelpView</CODE> widgets.
+
+</UL>
+
+<P>The <CODE>HelpDialog</CODE> widget is designed for embedded use within
+a FLTK application, while the <CODE>HelpApp</CODE> widget provides the
+framework for a complete application, such as the
+<A HREF="flsurf.html">flsurf</A> application included with the widget set.
+
+</BODY>
+</HTML>
diff --git a/SrcUnix/espws.diff b/SrcUnix/espws.diff
new file mode 100644
index 0000000..877cbab
--- /dev/null
+++ b/SrcUnix/espws.diff
@@ -0,0 +1,139 @@
+diff -Naur espws-2.0-orig/FileChooser.cxx espws-2.0/FileChooser.cxx
+--- espws-2.0-orig/FileChooser.cxx Tue Feb 29 10:45:55 2000
++++ espws-2.0/FileChooser.cxx Mon Jul 23 18:27:45 2001
+@@ -128,7 +128,7 @@
+ { Fl_Choice* o = dirMenu = new Fl_Choice(75, 10, 200, 25, "Directory:");
+ o->callback((Fl_Callback*)cb_dirMenu);
+ }
+- { Fl_Button* o = new Fl_Button(340, 10, 25, 25);
++ { Fl_Button* o = allFiles = new Fl_Button(340, 10, 25, 25);
+ bitmap_allfiles.label(o);
+ o->labelsize(28);
+ o->labelcolor(4);
+@@ -140,6 +140,7 @@
+ o->end();
+ }
+ window->size_range(345, 270, 345);
++directory_chooser_ = false;
+ fileList->filter(p);
+ type(t);
+ value(d);
+@@ -216,6 +217,14 @@
+ }
+
+ void FileChooser::type(int t) {
++ if (t == DIRECTORY)
++ {
++ t = SINGLE;
++ directory_chooser_ = true;
++ allFiles->deactivate();
++ fileList->filter("-_-_-_-_-_-"); /* Match that! */
++ }
++
+ type_ = t;
+ if (t == MULTI)
+ fileList->type(FL_MULTI_BROWSER);
+diff -Naur espws-2.0-orig/FileChooser.h espws-2.0/FileChooser.h
+--- espws-2.0-orig/FileChooser.h Tue Feb 29 10:45:55 2000
++++ espws-2.0/FileChooser.h Mon Jul 23 18:27:45 2001
+@@ -15,7 +15,7 @@
+
+ class FileChooser {
+ public:
+- enum { SINGLE, MULTI, CREATE };
++ enum { SINGLE, MULTI, CREATE, DIRECTORY };
+ FileChooser(const char *d, const char *p, int t, const char *title);
+ private:
+ Fl_Window *window;
+@@ -41,10 +41,12 @@
+ Fl_Choice *dirMenu;
+ inline void cb_dirMenu_i(Fl_Choice*, void*);
+ static void cb_dirMenu(Fl_Choice*, void*);
++ Fl_Button *allFiles;
+ inline void cb_allfiles_i(Fl_Button*, void*);
+ static void cb_allfiles(Fl_Button*, void*);
+ char directory_[1024];
+ int type_;
++ int directory_chooser_;
+ void fileListCB();
+ void fileNameCB();
+ void newdir();
+diff -Naur espws-2.0-orig/FileChooser2.cxx espws-2.0/FileChooser2.cxx
+--- espws-2.0-orig/FileChooser2.cxx Tue Jan 4 05:45:51 2000
++++ espws-2.0/FileChooser2.cxx Mon Jul 23 18:27:45 2001
+@@ -170,7 +170,7 @@
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+- if (filename_isdir(pathname))
++ if (filename_isdir(pathname) && !directory_chooser_)
+ return (0);
+ else
+ return (1);
+@@ -189,7 +189,7 @@
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+- if (!filename_isdir(pathname))
++ if (!filename_isdir(pathname) || directory_chooser_)
+ count ++;
+ }
+
+@@ -209,6 +209,16 @@
+ const char *name; // Current filename
+ static char pathname[1024]; // Filename + directory
+
++// There seems to be a little bit of a bug...sometimes
++// the returned path can start with '//'. I think the
++// Unix file system handles this OK ("ls //tmp" works),
++// but lets clean it up anyway.
++
++ if (strlen (directory_) >= 2 &&
++ directory_[0] == '/' && directory_[1] == '/')
++ {
++ memmove (directory_, directory_ + 1, strlen (directory_));
++ }
+
+ if (type_ != MULTI)
+ {
+@@ -227,7 +237,7 @@
+ name = fileList->text(i);
+ sprintf(pathname, "%s/%s", directory_, name);
+
+- if (!filename_isdir(pathname))
++ if (!filename_isdir(pathname) || directory_chooser_)
+ {
+ // Nope, see if this this is "the one"...
+ count ++;
+@@ -427,7 +437,7 @@
+ {
+ fileName->value(filename);
+
+- if (!filename_isdir(pathname))
++ if (!filename_isdir(pathname) || directory_chooser_)
+ okButton->activate();
+ }
+ }
+@@ -487,10 +497,10 @@
+ // Enter pressed - select or change directory...
+
+ #if defined(WIN32) || defined(__EMX__)
+- if ((strlen(pathname) == 2 && pathname[1] == ':') ||
+- filename_isdir(pathname))
++ if (((strlen(pathname) == 2 && pathname[1] == ':') ||
++ filename_isdir(pathname)) && !directory_chooser_)
+ #else
+- if (filename_isdir(pathname))
++ if (filename_isdir(pathname) && !directory_chooser_)
+ #endif /* WIN32 || __EMX__ */
+ directory(pathname);
+ else if (type_ == CREATE || access(pathname, 0) == 0)
+@@ -622,7 +632,7 @@
+ sprintf(pathname, "%s/%s", directory_, fileName->value());
+
+ if ((type_ == CREATE || access(pathname, 0) == 0) &&
+- !filename_isdir(pathname))
++ (!filename_isdir(pathname) || directory_chooser_))
+ okButton->activate();
+ else
+ okButton->deactivate();
diff --git a/SrcUnix/jconfig.h b/SrcUnix/jconfig.h
new file mode 100644
index 0000000..afe7249
--- /dev/null
+++ b/SrcUnix/jconfig.h
@@ -0,0 +1,46 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+/* #define void char */
+/* #define const */
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
+#undef NEED_SHORT_EXTERNAL_NAMES
+#undef INCOMPLETE_TYPES_BROKEN
+
+/* Define "boolean" as unsigned char, not int, per Windows custom */
+#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+typedef unsigned char boolean;
+#endif
+#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+#define TWO_FILE_COMMANDLINE /* optional */
+#define USE_SETMODE /* Microsoft has setmode() */
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+#undef PROGRESS_REPORT /* optional */
+
+#endif /* JPEG_CJPEG_DJPEG */
diff --git a/SrcUnix/poser.xpm b/SrcUnix/poser.xpm
new file mode 100644
index 0000000..6f01368
--- /dev/null
+++ b/SrcUnix/poser.xpm
@@ -0,0 +1,54 @@
+/* XPM */
+static char * poser_xpm[] = {
+"38 39 12 1",
+" c None",
+". c #C5C2C5",
+"+ c #525252",
+"@ c #212121",
+"# c #000000",
+"$ c #003163",
+"% c #CECE00",
+"& c #9C9C63",
+"* c #424242",
+"= c #639C63",
+"- c #737373",
+"; c #313131",
+"......................................",
+"......................................",
+"......................................",
+"....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+...",
+"....#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#...",
+"....#$$$$%%%%$%%$%%%%$$$$$$$$$$$$@#...",
+".....#$$$$$%%%##%%%$$$$$$$$$$$$$@#....",
+"......#$$$$$$$%%$$$$$$$$$$$$$$$@#.....",
+".......#$$$$$$$$$$$$$$$$$$$@@@@#......",
+".......#$$$$$$$$$$$$$$$$$$$$$$@#......",
+".......#%%%%%%%%%%%%%%%%$%$$$$@#......",
+".......#########################......",
+"......####################&@**@.......",
+".....####################&&@**@.......",
+"....@###################&=&@**@.......",
+"....@#################*&=&&@**@.......",
+"....+@#############@*=&=&=&@**@.......",
+"........@**@=&=&=&=&=&=&=&&@**@.......",
+"........@**@&=&=&=&=&=&=&=&@**@.......",
+"........@**@==============&@**@.......",
+"........@**@&&&&&&&&&&&&&&&@**@.......",
+"........@**@-+-&-&-&-&-&-+-@**@.......",
+"........@**@+&+&&&&&&&&&+&+@**@.......",
+"........@**@-+-&&&&&&&&&-+-@**@.......",
+"........@**@&&&&&&&&&&&&&&&@**@.......",
+"........@**@-+-&&&&&&&&&-+-@**@.......",
+"........@**@+&+&&&&&&&&&+&+@**@.......",
+"........@**@-+-&-&-&-&-&-+-@**@.......",
+"........@**;@@@@@@@@@@@@@@@;**@.......",
+"........@*********************@.......",
+"........@@@;;****************;@.......",
+".........@;;@@;;*********;;@@@........",
+".........@***;;@@@@@@@@@@@;;*@........",
+".........@*******************@........",
+".........+@@@@@@@@@@@@@@@@@@@+........",
+"......................................",
+"......................................",
+"......................................",
+"......................................"};
diff --git a/Tools/Strings2Resource.pl b/Tools/Strings2Resource.pl
new file mode 100644
index 0000000..3950680
--- /dev/null
+++ b/Tools/Strings2Resource.pl
@@ -0,0 +1,248 @@
+# -*- mode: Perl; tab-width: 4 -*-
+
+use File::Basename;
+
+$language = "ENGLISH";
+
+$input = $ARGV[0];
+$output = $ARGV[1];
+
+if (not @ARGV or not -f $input) {
+ die "Usage: $0 <full path of Strings.txt> <full path to output dir>\n";
+}
+
+
+$output_rez = $output . "Strings.cpp";
+$output_cpp = $output . "ResStrings.cpp";
+$output_vcpp = $output . "Strings.rc";
+
+
+@modes = (
+{
+ output => $output_rez,
+
+ maccreator => 'CWIE',
+
+ prefix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#/* This file is generated from SrcShared:Strings.txt */
+#
+#type 'STRA' {
+# integer = $$CountOf(SomeArray);
+# wide array SomeArray {
+# integer;
+# wstring;
+# };
+#};
+#
+#resource 'STRA' (1000) {{
+-EOT-
+
+ suffix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#}};
+#
+-EOT-
+
+ print => sub { "\t$_[0], \"" . backslash_quotes($_[1]) . "\";" },
+
+ prefix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#/* This file is generated from SrcShared/Strings.txt */
+#
+##include <map>
+#
+#static std::map<int, const char*> _ResStrMap;
+#
+#struct item
+#{
+# int key;
+# const char* value;
+#};
+#
+##pragma mpwc_newline on
+#
+#static const struct item _ResStrTable[] = {
+-EOT-
+
+ suffix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+# { 0, NULL }
+#};
+#
+#static void _ResStrTableInit (void)
+#{
+# for (const struct item* it = _ResStrTable; it->value != NULL; it++)
+# {
+# _ResStrMap[it->key] = it->value;
+# }
+#}
+#
+#
+#const char* _ResGetString(int idx);
+#const char* _ResGetString(int idx)
+#{
+# static int inited;
+# if (!inited)
+# {
+# inited = 1;
+# _ResStrTableInit();
+# }
+#
+# return _ResStrMap[idx];
+#}
+-EOT-
+
+ print => sub { "\t{ $_[0], \"" . backslash_quotes($_[1]) . "\" }," }
+},
+
+{
+ output => $output_cpp,
+
+ prefix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#/* This file is generated from SrcShared/Strings.txt */
+#
+##include <map>
+#
+#static std::map<int, const char*> _ResStrMap;
+#
+#struct item
+#{
+# int key;
+# const char* value;
+#};
+#
+#static const struct item _ResStrTable[] = {
+-EOT-
+
+ suffix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+# { 0, NULL }
+#};
+#
+#static void _ResStrTableInit (void)
+#{
+# for (const struct item* it = _ResStrTable; it->value != NULL; it++)
+# {
+# _ResStrMap[it->key] = it->value;
+# }
+#}
+#
+#
+#const char* _ResGetString(int idx)
+#{
+# static int inited;
+# if (!inited)
+# {
+# inited = 1;
+# _ResStrTableInit();
+# }
+#
+# return _ResStrMap[idx];
+#}
+-EOT-
+
+ print => sub { "\t{ $_[0], \"" . backslash_quotes(translate_high_ascii(1, $_[1])) . "\" }," }
+},
+
+{
+ output => $output_vcpp,
+
+ prefix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#/* This file is generated from SrcShared/Strings.txt */
+#
+#STRINGTABLE DISCARDABLE
+#BEGIN
+-EOT-
+
+ suffix => sub { local($_); $_=<<'-EOT-'; s/^#//gm; $_ },
+#END
+-EOT-
+
+ print => sub { "\t$_[0]\t\"" . double_quotes(translate_high_ascii(0, $_[1])) . "\"" }
+}
+);
+
+foreach $mode (@modes) {
+
+ open (I, "<$input") or die "Unable to open $input: $!\n";
+ open (O, ">$mode->{output}") or next;
+
+ $text = "";
+ $started = 0;
+ $id = "";
+ $text = "";
+
+ while (<I>) {
+ if (/^\t(.+)/ and $text) {
+ $text .= $1;
+ next;
+ }
+
+ print O &{$mode->{print}}($id,$text) if $text;
+ $text = "";
+
+ if (/^START$/) {
+ print O &{$mode->{prefix}}();
+ $started = 1;
+ } elsif (/^END$/) {
+ print O &{$mode->{suffix}}();
+ last;
+ } elsif ($started and /^([A-Z]+)=(.+)/) {
+ $id = $2 if $1 eq "ID";
+ $text = $2 if $1 eq $language;
+ } else {
+ print O;
+ }
+ }
+
+ if ($^O =~ /MacOS/i and $mode->{maccreator}) {
+ MacPerl::SetFileInfo($mode->{maccreator}, 'TEXT', $mode->{output});
+ }
+
+ close (O);
+ close (I);
+}
+
+
+sub backslash_quotes
+{
+ local($_)=@_;
+ s/\"/\\\"/g; # Turn a " into \"
+ return $_;
+}
+
+sub double_quotes
+{
+ local($_)=@_;
+ s/\"/\"\"/g; # Turn a " into ""
+ return $_;
+}
+
+sub translate_high_ascii
+{
+ local($unix, $_) = @_;
+ # Translate Macintosh High Ascii characters
+ # into the equivalents for Windows and Unix.
+
+ # (Note: I tried turning the curly quotes into
+ # the equivalent on Windows, but they just looked
+ # really bad in dialogs, so I now turn them into
+ # straight quotes.)
+
+ s/Ó/\"/g; # Turn Ó into "
+ s/Ò/\"/g; # Turn Ò into "
+ s/Õ/\'/g; # Turn Õ into '
+ s/Ô/\'/g; # Turn Ô into '
+ s/É/\.\.\./g; # Turn É into ...
+ s/ª/\(TM)/g; # Turn ª into (TM)
+
+ if (!$unix)
+ {
+ s/¨/\®/g; # Turn ¨ into ®
+ }
+ else
+ {
+ s/¨/(R)/g; # Turn ¨ into (R)
+ s/©/(c)/g; # Turn © into (c)
+ }
+
+ return $_;
+}
+
+
diff --git a/Tools/s2r.sh b/Tools/s2r.sh
new file mode 100755
index 0000000..36224f2
--- /dev/null
+++ b/Tools/s2r.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+perl ../Tools/Strings2Resource.pl ../SrcShared/Strings.txt
+
+
+